cargotype.cpp

Go to the documentation of this file.
00001 /* $Id: cargotype.cpp 23860 2012-01-28 12:08:03Z frosch $ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00012 #include "stdafx.h"
00013 #include "cargotype.h"
00014 #include "newgrf_cargo.h"
00015 #include "string_func.h"
00016 #include "strings_func.h"
00017 #include "core/sort_func.hpp"
00018 
00019 #include "table/sprites.h"
00020 #include "table/strings.h"
00021 #include "table/cargo_const.h"
00022 
00023 CargoSpec CargoSpec::array[NUM_CARGO];
00024 
00029 uint32 _cargo_mask;
00030 
00035 void SetupCargoForClimate(LandscapeID l)
00036 {
00037   assert(l < lengthof(_default_climate_cargo));
00038 
00039   /* Reset and disable all cargo types */
00040   memset(CargoSpec::array, 0, sizeof(CargoSpec::array));
00041   for (CargoID i = 0; i < lengthof(CargoSpec::array); i++) {
00042     CargoSpec::Get(i)->bitnum = INVALID_CARGO;
00043 
00044     /* Set defaults for newer properties, which old GRFs do not know */
00045     CargoSpec::Get(i)->multiplier = 0x100;
00046   }
00047 
00048   _cargo_mask = 0;
00049 
00050   for (CargoID i = 0; i < lengthof(_default_climate_cargo[l]); i++) {
00051     CargoLabel cl = _default_climate_cargo[l][i];
00052 
00053     /* Bzzt: check if cl is just an index into the cargo table */
00054     if (cl < lengthof(_default_cargo)) {
00055       /* Copy the indexed cargo */
00056       CargoSpec *cargo = CargoSpec::Get(i);
00057       *cargo = _default_cargo[cl];
00058       if (cargo->bitnum != INVALID_CARGO) SetBit(_cargo_mask, i);
00059       continue;
00060     }
00061 
00062     /* Loop through each of the default cargo types to see if
00063      * the label matches */
00064     for (uint j = 0; j < lengthof(_default_cargo); j++) {
00065       if (_default_cargo[j].label == cl) {
00066         *CargoSpec::Get(i) = _default_cargo[j];
00067 
00068         /* Populate the available cargo mask */
00069         SetBit(_cargo_mask, i);
00070         break;
00071       }
00072     }
00073   }
00074 }
00075 
00081 CargoID GetCargoIDByLabel(CargoLabel cl)
00082 {
00083   const CargoSpec *cs;
00084   FOR_ALL_CARGOSPECS(cs) {
00085     if (cs->label == cl) return cs->Index();
00086   }
00087 
00088   /* No matching label was found, so it is invalid */
00089   return CT_INVALID;
00090 }
00091 
00092 
00098 CargoID GetCargoIDByBitnum(uint8 bitnum)
00099 {
00100   if (bitnum == INVALID_CARGO) return CT_INVALID;
00101 
00102   const CargoSpec *cs;
00103   FOR_ALL_CARGOSPECS(cs) {
00104     if (cs->bitnum == bitnum) return cs->Index();
00105   }
00106 
00107   /* No matching label was found, so it is invalid */
00108   return CT_INVALID;
00109 }
00110 
00115 SpriteID CargoSpec::GetCargoIcon() const
00116 {
00117   SpriteID sprite = this->sprite;
00118   if (sprite == 0xFFFF) {
00119     /* A value of 0xFFFF indicates we should draw a custom icon */
00120     sprite = GetCustomCargoSprite(this);
00121   }
00122 
00123   if (sprite == 0) sprite = SPR_CARGO_GOODS;
00124 
00125   return sprite;
00126 }
00127 
00128 const CargoSpec *_sorted_cargo_specs[NUM_CARGO]; 
00129 uint8 _sorted_cargo_specs_size;                  
00130 uint8 _sorted_standard_cargo_specs_size;         
00131 
00132 
00134 static int CDECL CargoSpecNameSorter(const CargoSpec * const *a, const CargoSpec * const *b)
00135 {
00136   static char a_name[64];
00137   static char b_name[64];
00138 
00139   GetString(a_name, (*a)->name, lastof(a_name));
00140   GetString(b_name, (*b)->name, lastof(b_name));
00141 
00142   int res = strnatcmp(a_name, b_name); // Sort by name (natural sorting).
00143 
00144   /* If the names are equal, sort by cargo bitnum. */
00145   return (res != 0) ? res : ((*a)->bitnum - (*b)->bitnum);
00146 }
00147 
00149 static int CDECL CargoSpecClassSorter(const CargoSpec * const *a, const CargoSpec * const *b)
00150 {
00151   int res = ((*b)->classes & CC_PASSENGERS) - ((*a)->classes & CC_PASSENGERS);
00152   if (res == 0) {
00153     res = ((*b)->classes & CC_MAIL) - ((*a)->classes & CC_MAIL);
00154     if (res == 0) {
00155       res = ((*a)->classes & CC_SPECIAL) - ((*b)->classes & CC_SPECIAL);
00156       if (res == 0) {
00157         return CargoSpecNameSorter(a, b);
00158       }
00159     }
00160   }
00161 
00162   return res;
00163 }
00164 
00166 void InitializeSortedCargoSpecs()
00167 {
00168   _sorted_cargo_specs_size = 0;
00169   const CargoSpec *cargo;
00170   /* Add each cargo spec to the list. */
00171   FOR_ALL_CARGOSPECS(cargo) {
00172     _sorted_cargo_specs[_sorted_cargo_specs_size] = cargo;
00173     _sorted_cargo_specs_size++;
00174   }
00175 
00176   /* Sort cargo specifications by cargo class and name. */
00177   QSortT(_sorted_cargo_specs, _sorted_cargo_specs_size, &CargoSpecClassSorter);
00178 
00179   _sorted_standard_cargo_specs_size = 0;
00180   FOR_ALL_SORTED_CARGOSPECS(cargo) {
00181     if (cargo->classes & CC_SPECIAL) break;
00182     _sorted_standard_cargo_specs_size++;
00183   }
00184 }
00185