26 #include "string_func.h" |
26 #include "string_func.h" |
27 #include "settings_type.h" |
27 #include "settings_type.h" |
28 #include "oldpool_func.h" |
28 #include "oldpool_func.h" |
29 #include "core/alloc_func.hpp" |
29 #include "core/alloc_func.hpp" |
30 #include "vehicle_func.h" |
30 #include "vehicle_func.h" |
31 #include "map" |
31 #include <map> |
32 |
32 |
33 #include "table/strings.h" |
33 #include "table/strings.h" |
34 #include "table/engines.h" |
34 #include "table/engines.h" |
35 |
35 |
36 DEFINE_OLD_POOL_GENERIC(Engine, Engine) |
36 DEFINE_OLD_POOL_GENERIC(Engine, Engine) |
113 { |
113 { |
114 UnloadWagonOverrides(this); |
114 UnloadWagonOverrides(this); |
115 free(this->name); |
115 free(this->name); |
116 } |
116 } |
117 |
117 |
118 /** Sort all items using qsort() and given 'CompareItems' function |
|
119 * @param el list to be sorted |
|
120 * @param compare function for evaluation of the quicksort |
|
121 */ |
|
122 void EngList_Sort(EngineList *el, EngList_SortTypeFunction compare) |
|
123 { |
|
124 size_t size = el->size(); |
|
125 /* out-of-bounds access at the next line for size == 0 (even with operator[] at some systems) |
|
126 * generally, do not sort if there are less than 2 items */ |
|
127 if (size < 2) return; |
|
128 qsort(&((*el)[0]), size, sizeof(EngineID), compare); // MorphOS doesn't know vector::at(int) ... |
|
129 } |
|
130 |
|
131 /** Sort selected range of items (on indices @ <begin, begin+num_items-1>) |
|
132 * @param el list to be sorted |
|
133 * @param compare function for evaluation of the quicksort |
|
134 * @param begin start of sorting |
|
135 * @param num_items count of items to be sorted |
|
136 */ |
|
137 void EngList_SortPartial(EngineList *el, EngList_SortTypeFunction compare, uint begin, uint num_items) |
|
138 { |
|
139 assert(begin <= (uint)el->size()); |
|
140 assert(begin + num_items <= (uint)el->size()); |
|
141 if (num_items < 2) return; |
|
142 qsort(&((*el)[begin]), num_items, sizeof(EngineID), compare); |
|
143 } |
|
144 |
|
145 |
|
146 /** Sets cached values in Player::num_vehicles and Group::num_vehicles |
118 /** Sets cached values in Player::num_vehicles and Group::num_vehicles |
147 */ |
119 */ |
148 void SetCachedEngineCounts() |
120 void SetCachedEngineCounts() |
149 { |
121 { |
150 uint engines = GetEnginePoolSize(); |
122 uint engines = GetEnginePoolSize(); |
210 { |
182 { |
211 /* XXX: not done */ |
183 /* XXX: not done */ |
212 DEBUG(misc, 1, "LoadCustomEngineNames: not done"); |
184 DEBUG(misc, 1, "LoadCustomEngineNames: not done"); |
213 } |
185 } |
214 |
186 |
|
187 /* Determine if an engine type is a wagon (and not a loco) */ |
|
188 static bool IsWagon(EngineID index) |
|
189 { |
|
190 const Engine *e = GetEngine(index); |
|
191 return e->type == VEH_TRAIN && e->u.rail.railveh_type == RAILVEH_WAGON; |
|
192 } |
|
193 |
215 static void CalcEngineReliability(Engine *e) |
194 static void CalcEngineReliability(Engine *e) |
216 { |
195 { |
217 uint age = e->age; |
196 uint age = e->age; |
218 |
197 |
219 /* Check for early retirement */ |
198 /* Check for early retirement */ |
220 if (e->player_avail != 0 && !_settings.vehicle.never_expire_vehicles) { |
199 if (e->player_avail != 0 && !_settings_game.vehicle.never_expire_vehicles) { |
221 int retire_early = e->info.retire_early; |
200 int retire_early = e->info.retire_early; |
222 uint retire_early_max_age = max(0, e->duration_phase_1 + e->duration_phase_2 - retire_early * 12); |
201 uint retire_early_max_age = max(0, e->duration_phase_1 + e->duration_phase_2 - retire_early * 12); |
223 if (retire_early != 0 && age >= retire_early_max_age) { |
202 if (retire_early != 0 && age >= retire_early_max_age) { |
224 /* Early retirement is enabled and we're past the date... */ |
203 /* Early retirement is enabled and we're past the date... */ |
225 e->player_avail = 0; |
204 e->player_avail = 0; |
228 } |
207 } |
229 |
208 |
230 if (age < e->duration_phase_1) { |
209 if (age < e->duration_phase_1) { |
231 uint start = e->reliability_start; |
210 uint start = e->reliability_start; |
232 e->reliability = age * (e->reliability_max - start) / e->duration_phase_1 + start; |
211 e->reliability = age * (e->reliability_max - start) / e->duration_phase_1 + start; |
233 } else if ((age -= e->duration_phase_1) < e->duration_phase_2 || _settings.vehicle.never_expire_vehicles) { |
212 } else if ((age -= e->duration_phase_1) < e->duration_phase_2 || _settings_game.vehicle.never_expire_vehicles) { |
234 /* We are at the peak of this engines life. It will have max reliability. |
213 /* We are at the peak of this engines life. It will have max reliability. |
235 * This is also true if the engines never expire. They will not go bad over time */ |
214 * This is also true if the engines never expire. They will not go bad over time */ |
236 e->reliability = e->reliability_max; |
215 e->reliability = e->reliability_max; |
237 } else if ((age -= e->duration_phase_2) < e->duration_phase_3) { |
216 } else if ((age -= e->duration_phase_2) < e->duration_phase_3) { |
238 uint max = e->reliability_max; |
217 uint max = e->reliability_max; |
282 r = Random(); |
261 r = Random(); |
283 e->duration_phase_1 = GB(r, 0, 5) + 7; |
262 e->duration_phase_1 = GB(r, 0, 5) + 7; |
284 e->duration_phase_2 = GB(r, 5, 4) + ei->base_life * 12 - 96; |
263 e->duration_phase_2 = GB(r, 5, 4) + ei->base_life * 12 - 96; |
285 e->duration_phase_3 = GB(r, 9, 7) + 120; |
264 e->duration_phase_3 = GB(r, 9, 7) + 120; |
286 |
265 |
287 e->reliability_spd_dec = (ei->unk2&0x7F) << 2; |
266 e->reliability_spd_dec = ei->decay_speed << 2; |
288 |
267 |
289 /* my invented flag for something that is a wagon */ |
268 if (IsWagon(e->index)) { |
290 if (ei->unk2 & 0x80) { |
|
291 e->age = 0xFFFF; |
269 e->age = 0xFFFF; |
292 } else { |
270 } else { |
293 CalcEngineReliability(e); |
271 CalcEngineReliability(e); |
294 } |
272 } |
295 |
273 |
296 e->lifelength = ei->lifelength + _settings.vehicle.extend_vehicle_life; |
274 e->lifelength = ei->lifelength + _settings_game.vehicle.extend_vehicle_life; |
297 |
275 |
298 /* prevent certain engines from ever appearing. */ |
276 /* prevent certain engines from ever appearing. */ |
299 if (!HasBit(ei->climates, _settings.game_creation.landscape)) { |
277 if (!HasBit(ei->climates, _settings_game.game_creation.landscape)) { |
300 e->flags |= ENGINE_AVAILABLE; |
278 e->flags |= ENGINE_AVAILABLE; |
301 e->player_avail = 0; |
279 e->player_avail = 0; |
302 } |
280 } |
303 } |
281 } |
304 } |
282 } |
401 if (GetBestPlayer(e->preview_player_rank) != _current_player) return CMD_ERROR; |
379 if (GetBestPlayer(e->preview_player_rank) != _current_player) return CMD_ERROR; |
402 |
380 |
403 if (flags & DC_EXEC) AcceptEnginePreview(p1, _current_player); |
381 if (flags & DC_EXEC) AcceptEnginePreview(p1, _current_player); |
404 |
382 |
405 return CommandCost(); |
383 return CommandCost(); |
406 } |
|
407 |
|
408 /* Determine if an engine type is a wagon (and not a loco) */ |
|
409 static bool IsWagon(EngineID index) |
|
410 { |
|
411 const Engine *e = GetEngine(index); |
|
412 return e->type == VEH_TRAIN && e->u.rail.railveh_type == RAILVEH_WAGON; |
|
413 } |
384 } |
414 |
385 |
415 StringID GetEngineCategoryName(EngineID engine); |
386 StringID GetEngineCategoryName(EngineID engine); |
416 |
387 |
417 static void NewVehicleAvailable(Engine *e) |
388 static void NewVehicleAvailable(Engine *e) |