# cargotype.cpp

Go to the documentation of this file.

    00001 /* $Id: cargotype.cpp 24848 2012-12-23 22:12:52Z 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
    00034 uint32 _standard_cargo_mask;
    00035
    00040 void SetupCargoForClimate(LandscapeID l)
    00041 {
    00042   assert(l < lengthof(_default_climate_cargo));
    00043
    00044   /* Reset and disable all cargo types */
    00045   memset(CargoSpec::array, 0, sizeof(CargoSpec::array));
    00046   for (CargoID i = 0; i < lengthof(CargoSpec::array); i++) {
    00047     CargoSpec::Get(i)->bitnum = INVALID_CARGO;
    00048
    00049     /* Set defaults for newer properties, which old GRFs do not know */
    00050     CargoSpec::Get(i)->multiplier = 0x100;
    00051   }
    00052
    00053   _cargo_mask = 0;
    00054
    00055   for (CargoID i = 0; i < lengthof(_default_climate_cargo[l]); i++) {
    00056     CargoLabel cl = _default_climate_cargo[l][i];
    00057
    00058     /* Bzzt: check if cl is just an index into the cargo table */
    00059     if (cl < lengthof(_default_cargo)) {
    00060       /* Copy the indexed cargo */
    00061       CargoSpec *cargo = CargoSpec::Get(i);
    00062       *cargo = _default_cargo[cl];
    00063       if (cargo->bitnum != INVALID_CARGO) SetBit(_cargo_mask, i);
    00064       continue;
    00065     }
    00066
    00067     /* Loop through each of the default cargo types to see if
    00068      * the label matches */
    00069     for (uint j = 0; j < lengthof(_default_cargo); j++) {
    00070       if (_default_cargo[j].label == cl) {
    00071         *CargoSpec::Get(i) = _default_cargo[j];
    00072
    00073         /* Populate the available cargo mask */
    00074         SetBit(_cargo_mask, i);
    00075         break;
    00076       }
    00077     }
    00078   }
    00079 }
    00080
    00086 CargoID GetCargoIDByLabel(CargoLabel cl)
    00087 {
    00088   const CargoSpec *cs;
    00089   FOR_ALL_CARGOSPECS(cs) {
    00090     if (cs->label == cl) return cs->Index();
    00091   }
    00092
    00093   /* No matching label was found, so it is invalid */
    00094   return CT_INVALID;
    00095 }
    00096
    00097
    00103 CargoID GetCargoIDByBitnum(uint8 bitnum)
    00104 {
    00105   if (bitnum == INVALID_CARGO) return CT_INVALID;
    00106
    00107   const CargoSpec *cs;
    00108   FOR_ALL_CARGOSPECS(cs) {
    00109     if (cs->bitnum == bitnum) return cs->Index();
    00110   }
    00111
    00112   /* No matching label was found, so it is invalid */
    00113   return CT_INVALID;
    00114 }
    00115
    00120 SpriteID CargoSpec::GetCargoIcon() const
    00121 {
    00122   SpriteID sprite = this->sprite;
    00123   if (sprite == 0xFFFF) {
    00124     /* A value of 0xFFFF indicates we should draw a custom icon */
    00125     sprite = GetCustomCargoSprite(this);
    00126   }
    00127
    00128   if (sprite == 0) sprite = SPR_CARGO_GOODS;
    00129
    00130   return sprite;
    00131 }
    00132
    00133 const CargoSpec *_sorted_cargo_specs[NUM_CARGO];
    00134 uint8 _sorted_cargo_specs_size;
    00135 uint8 _sorted_standard_cargo_specs_size;
    00136
    00137
    00139 static int CDECL CargoSpecNameSorter(const CargoSpec * const *a, const CargoSpec * const *b)
    00140 {
    00141   static char a_name[64];
    00142   static char b_name[64];
    00143
    00144   GetString(a_name, (*a)->name, lastof(a_name));
    00145   GetString(b_name, (*b)->name, lastof(b_name));
    00146
    00147   int res = strnatcmp(a_name, b_name); // Sort by name (natural sorting).
    00148
    00149   /* If the names are equal, sort by cargo bitnum. */
    00150   return (res != 0) ? res : ((*a)->bitnum - (*b)->bitnum);
    00151 }
    00152
    00154 static int CDECL CargoSpecClassSorter(const CargoSpec * const *a, const CargoSpec * const *b)
    00155 {
    00156   int res = ((*b)->classes & CC_PASSENGERS) - ((*a)->classes & CC_PASSENGERS);
    00157   if (res == 0) {
    00158     res = ((*b)->classes & CC_MAIL) - ((*a)->classes & CC_MAIL);
    00159     if (res == 0) {
    00160       res = ((*a)->classes & CC_SPECIAL) - ((*b)->classes & CC_SPECIAL);
    00161       if (res == 0) {
    00162         return CargoSpecNameSorter(a, b);
    00163       }
    00164     }
    00165   }
    00166
    00167   return res;
    00168 }
    00169
    00171 void InitializeSortedCargoSpecs()
    00172 {
    00173   _sorted_cargo_specs_size = 0;
    00174   const CargoSpec *cargo;
    00175   /* Add each cargo spec to the list. */
    00176   FOR_ALL_CARGOSPECS(cargo) {
    00177     _sorted_cargo_specs[_sorted_cargo_specs_size] = cargo;
    00178     _sorted_cargo_specs_size++;
    00179   }
    00180
    00181   /* Sort cargo specifications by cargo class and name. */
    00182   QSortT(_sorted_cargo_specs, _sorted_cargo_specs_size, &CargoSpecClassSorter);
    00183
    00184   _standard_cargo_mask = 0;
    00185
    00186   _sorted_standard_cargo_specs_size = 0;
    00187   FOR_ALL_SORTED_CARGOSPECS(cargo) {
    00188     if (cargo->classes & CC_SPECIAL) break;
    00189     _sorted_standard_cargo_specs_size++;
    00190     SetBit(_standard_cargo_mask, cargo->Index());
    00191   }
    00192 }
    00193