00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "../../stdafx.h"
00013 #include "script_town.hpp"
00014 #include "script_map.hpp"
00015 #include "script_cargo.hpp"
00016 #include "script_error.hpp"
00017 #include "../../town.h"
00018 #include "../../strings_func.h"
00019 #include "../../company_func.h"
00020 #include "../../station_base.h"
00021 #include "../../landscape.h"
00022 #include "table/strings.h"
00023
00024 int32 ScriptTown::GetTownCount()
00025 {
00026 return (int32)::Town::GetNumItems();
00027 }
00028
00029 bool ScriptTown::IsValidTown(TownID town_id)
00030 {
00031 return ::Town::IsValidID(town_id);
00032 }
00033
00034 char *ScriptTown::GetName(TownID town_id)
00035 {
00036 if (!IsValidTown(town_id)) return NULL;
00037 static const int len = 64;
00038 char *town_name = MallocT<char>(len);
00039
00040 ::SetDParam(0, town_id);
00041 ::GetString(town_name, STR_TOWN_NAME, &town_name[len - 1]);
00042
00043 return town_name;
00044 }
00045
00046 bool ScriptTown::SetText(TownID town_id, Text *text)
00047 {
00048 CCountedPtr<Text> counter(text);
00049
00050 EnforcePrecondition(false, text != NULL);
00051 EnforcePrecondition(false, IsValidTown(town_id));
00052
00053 return ScriptObject::DoCommand(::Town::Get(town_id)->xy, town_id, 0, CMD_TOWN_SET_TEXT, text->GetEncodedText());
00054 }
00055
00056 int32 ScriptTown::GetPopulation(TownID town_id)
00057 {
00058 if (!IsValidTown(town_id)) return -1;
00059 const Town *t = ::Town::Get(town_id);
00060 return t->population;
00061 }
00062
00063 int32 ScriptTown::GetHouseCount(TownID town_id)
00064 {
00065 if (!IsValidTown(town_id)) return -1;
00066 const Town *t = ::Town::Get(town_id);
00067 return t->num_houses;
00068 }
00069
00070 TileIndex ScriptTown::GetLocation(TownID town_id)
00071 {
00072 if (!IsValidTown(town_id)) return INVALID_TILE;
00073 const Town *t = ::Town::Get(town_id);
00074 return t->xy;
00075 }
00076
00077 int32 ScriptTown::GetLastMonthProduction(TownID town_id, CargoID cargo_id)
00078 {
00079 if (!IsValidTown(town_id)) return -1;
00080 if (!ScriptCargo::IsValidCargo(cargo_id)) return -1;
00081
00082 const Town *t = ::Town::Get(town_id);
00083
00084 return t->supplied[cargo_id].old_max;
00085 }
00086
00087 int32 ScriptTown::GetLastMonthSupplied(TownID town_id, CargoID cargo_id)
00088 {
00089 if (!IsValidTown(town_id)) return -1;
00090 if (!ScriptCargo::IsValidCargo(cargo_id)) return -1;
00091
00092 const Town *t = ::Town::Get(town_id);
00093
00094 return t->supplied[cargo_id].old_act;
00095 }
00096
00097 int32 ScriptTown::GetLastMonthTransportedPercentage(TownID town_id, CargoID cargo_id)
00098 {
00099 if (!IsValidTown(town_id)) return -1;
00100 if (!ScriptCargo::IsValidCargo(cargo_id)) return -1;
00101
00102 const Town *t = ::Town::Get(town_id);
00103 return ::ToPercent8(t->GetPercentTransported(cargo_id));
00104 }
00105
00106 int32 ScriptTown::GetLastMonthReceived(TownID town_id, ScriptCargo::TownEffect towneffect_id)
00107 {
00108 if (!IsValidTown(town_id)) return -1;
00109 if (!ScriptCargo::IsValidTownEffect(towneffect_id)) return -1;
00110
00111 const Town *t = ::Town::Get(town_id);
00112
00113 return t->received[towneffect_id].old_act;
00114 }
00115
00116 bool ScriptTown::SetCargoGoal(TownID town_id, ScriptCargo::TownEffect towneffect_id, uint32 goal)
00117 {
00118 EnforcePrecondition(false, IsValidTown(town_id));
00119 EnforcePrecondition(false, ScriptCargo::IsValidTownEffect(towneffect_id));
00120
00121 return ScriptObject::DoCommand(::Town::Get(town_id)->xy, town_id | (towneffect_id << 16), goal, CMD_TOWN_CARGO_GOAL);
00122 }
00123
00124 uint32 ScriptTown::GetCargoGoal(TownID town_id, ScriptCargo::TownEffect towneffect_id)
00125 {
00126 if (!IsValidTown(town_id)) return -1;
00127 if (!ScriptCargo::IsValidTownEffect(towneffect_id)) return -1;
00128
00129 const Town *t = ::Town::Get(town_id);
00130
00131 switch (t->goal[towneffect_id]) {
00132 case TOWN_GROWTH_WINTER:
00133 if (TileHeight(t->xy) >= GetSnowLine() && t->population > 90) return 1;
00134 return 0;
00135
00136 case TOWN_GROWTH_DESERT:
00137 if (GetTropicZone(t->xy) == TROPICZONE_DESERT && t->population > 60) return 1;
00138 return 0;
00139
00140 default: return t->goal[towneffect_id];
00141 }
00142 }
00143
00144 bool ScriptTown::SetGrowthRate(TownID town_id, uint16 days_between_town_growth)
00145 {
00146 days_between_town_growth = days_between_town_growth * DAY_TICKS / TOWN_GROWTH_TICKS;
00147
00148 EnforcePrecondition(false, IsValidTown(town_id));
00149 EnforcePrecondition(false, (days_between_town_growth & TOWN_GROW_RATE_CUSTOM) == 0);
00150
00151 return ScriptObject::DoCommand(::Town::Get(town_id)->xy, town_id, days_between_town_growth, CMD_TOWN_GROWTH_RATE);
00152 }
00153
00154 int32 ScriptTown::GetGrowthRate(TownID town_id)
00155 {
00156 if (!IsValidTown(town_id)) return false;
00157
00158 const Town *t = ::Town::Get(town_id);
00159
00160 return (t->growth_rate * TOWN_GROWTH_TICKS + DAY_TICKS) / DAY_TICKS;
00161 }
00162
00163 int32 ScriptTown::GetDistanceManhattanToTile(TownID town_id, TileIndex tile)
00164 {
00165 return ScriptMap::DistanceManhattan(tile, GetLocation(town_id));
00166 }
00167
00168 int32 ScriptTown::GetDistanceSquareToTile(TownID town_id, TileIndex tile)
00169 {
00170 return ScriptMap::DistanceSquare(tile, GetLocation(town_id));
00171 }
00172
00173 bool ScriptTown::IsWithinTownInfluence(TownID town_id, TileIndex tile)
00174 {
00175 if (!IsValidTown(town_id)) return false;
00176
00177 const Town *t = ::Town::Get(town_id);
00178 return ((uint32)GetDistanceSquareToTile(town_id, tile) <= t->squared_town_zone_radius[0]);
00179 }
00180
00181 bool ScriptTown::HasStatue(TownID town_id)
00182 {
00183 if (ScriptObject::GetCompany() == OWNER_DEITY) return false;
00184 if (!IsValidTown(town_id)) return false;
00185
00186 return ::HasBit(::Town::Get(town_id)->statues, ScriptObject::GetCompany());
00187 }
00188
00189 bool ScriptTown::IsCity(TownID town_id)
00190 {
00191 if (!IsValidTown(town_id)) return false;
00192
00193 return ::Town::Get(town_id)->larger_town;
00194 }
00195
00196 int ScriptTown::GetRoadReworkDuration(TownID town_id)
00197 {
00198 if (!IsValidTown(town_id)) return -1;
00199
00200 return ::Town::Get(town_id)->road_build_months;
00201 }
00202
00203 ScriptCompany::CompanyID ScriptTown::GetExclusiveRightsCompany(TownID town_id)
00204 {
00205 if (ScriptObject::GetCompany() == OWNER_DEITY) return ScriptCompany::COMPANY_INVALID;
00206 if (!IsValidTown(town_id)) return ScriptCompany::COMPANY_INVALID;
00207
00208 return (ScriptCompany::CompanyID)(int8)::Town::Get(town_id)->exclusivity;
00209 }
00210
00211 int32 ScriptTown::GetExclusiveRightsDuration(TownID town_id)
00212 {
00213 if (!IsValidTown(town_id)) return -1;
00214
00215 return ::Town::Get(town_id)->exclusive_counter;
00216 }
00217
00218 bool ScriptTown::IsActionAvailable(TownID town_id, TownAction town_action)
00219 {
00220 if (ScriptObject::GetCompany() == OWNER_DEITY) return false;
00221 if (!IsValidTown(town_id)) return false;
00222
00223 return HasBit(::GetMaskOfTownActions(NULL, ScriptObject::GetCompany(), ::Town::Get(town_id)), town_action);
00224 }
00225
00226 bool ScriptTown::PerformTownAction(TownID town_id, TownAction town_action)
00227 {
00228 EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
00229 EnforcePrecondition(false, IsValidTown(town_id));
00230 EnforcePrecondition(false, IsActionAvailable(town_id, town_action));
00231
00232 return ScriptObject::DoCommand(::Town::Get(town_id)->xy, town_id, town_action, CMD_DO_TOWN_ACTION);
00233 }
00234
00235 bool ScriptTown::ExpandTown(TownID town_id, int houses)
00236 {
00237 EnforcePrecondition(false, ScriptObject::GetCompany() == OWNER_DEITY);
00238 EnforcePrecondition(false, IsValidTown(town_id));
00239 EnforcePrecondition(false, houses > 0);
00240
00241 return ScriptObject::DoCommand(::Town::Get(town_id)->xy, town_id, houses, CMD_EXPAND_TOWN);
00242 }
00243
00244 ScriptTown::TownRating ScriptTown::GetRating(TownID town_id, ScriptCompany::CompanyID company_id)
00245 {
00246 if (!IsValidTown(town_id)) return TOWN_RATING_INVALID;
00247 ScriptCompany::CompanyID company = ScriptCompany::ResolveCompanyID(company_id);
00248 if (company == ScriptCompany::COMPANY_INVALID) return TOWN_RATING_INVALID;
00249
00250 const Town *t = ::Town::Get(town_id);
00251 if (!HasBit(t->have_ratings, company)) {
00252 return TOWN_RATING_NONE;
00253 } else if (t->ratings[company] <= RATING_APPALLING) {
00254 return TOWN_RATING_APPALLING;
00255 } else if (t->ratings[company] <= RATING_VERYPOOR) {
00256 return TOWN_RATING_VERY_POOR;
00257 } else if (t->ratings[company] <= RATING_POOR) {
00258 return TOWN_RATING_POOR;
00259 } else if (t->ratings[company] <= RATING_MEDIOCRE) {
00260 return TOWN_RATING_MEDIOCRE;
00261 } else if (t->ratings[company] <= RATING_GOOD) {
00262 return TOWN_RATING_GOOD;
00263 } else if (t->ratings[company] <= RATING_VERYGOOD) {
00264 return TOWN_RATING_VERY_GOOD;
00265 } else if (t->ratings[company] <= RATING_EXCELLENT) {
00266 return TOWN_RATING_EXCELLENT;
00267 } else {
00268 return TOWN_RATING_OUTSTANDING;
00269 }
00270 }
00271
00272 int ScriptTown::GetAllowedNoise(TownID town_id)
00273 {
00274 if (!IsValidTown(town_id)) return -1;
00275
00276 const Town *t = ::Town::Get(town_id);
00277 if (_settings_game.economy.station_noise_level) {
00278 return t->MaxTownNoise() - t->noise_reached;
00279 }
00280
00281 int num = 0;
00282 const Station *st;
00283 FOR_ALL_STATIONS(st) {
00284 if (st->town == t && (st->facilities & FACIL_AIRPORT) && st->airport.type != AT_OILRIG) num++;
00285 }
00286 return max(0, 2 - num);
00287 }
00288
00289 ScriptTown::RoadLayout ScriptTown::GetRoadLayout(TownID town_id)
00290 {
00291 if (!IsValidTown(town_id)) return ROAD_LAYOUT_INVALID;
00292
00293 return (ScriptTown::RoadLayout)((TownLayout)::Town::Get(town_id)->layout);
00294 }