4 |
4 |
5 #include "stdafx.h" |
5 #include "stdafx.h" |
6 #include "openttd.h" |
6 #include "openttd.h" |
7 #include "variables.h" |
7 #include "variables.h" |
8 #include "debug.h" |
8 #include "debug.h" |
9 #include "functions.h" |
|
10 #include "engine.h" |
9 #include "engine.h" |
11 #include "train.h" |
10 #include "train.h" |
12 #include "player.h" |
11 #include "player_func.h" |
|
12 #include "player_base.h" |
13 #include "station.h" |
13 #include "station.h" |
14 #include "airport.h" |
14 #include "airport.h" |
15 #include "newgrf.h" |
15 #include "newgrf.h" |
16 #include "newgrf_callbacks.h" |
16 #include "newgrf_callbacks.h" |
17 #include "newgrf_engine.h" |
17 #include "newgrf_engine.h" |
18 #include "newgrf_station.h" |
18 #include "newgrf_station.h" |
19 #include "newgrf_spritegroup.h" |
19 #include "newgrf_spritegroup.h" |
20 #include "newgrf_cargo.h" |
20 #include "newgrf_cargo.h" |
21 #include "date.h" |
|
22 #include "helpers.hpp" |
|
23 #include "cargotype.h" |
21 #include "cargotype.h" |
|
22 #include "date_func.h" |
|
23 #include "vehicle_func.h" |
|
24 #include "core/random_func.hpp" |
|
25 #include "direction_func.h" |
24 |
26 |
25 |
27 |
26 int _traininfo_vehicle_pitch = 0; |
28 int _traininfo_vehicle_pitch = 0; |
27 int _traininfo_vehicle_width = 29; |
29 int _traininfo_vehicle_width = 29; |
28 |
30 |
29 struct WagonOverride { |
31 struct WagonOverride { |
30 byte *train_id; |
32 EngineID *train_id; |
31 int trains; |
33 uint trains; |
32 CargoID cargo; |
34 CargoID cargo; |
33 const SpriteGroup *group; |
35 const SpriteGroup *group; |
34 }; |
36 }; |
35 |
37 |
36 struct WagonOverrides { |
38 struct WagonOverrides { |
37 int overrides_count; |
39 uint overrides_count; |
38 WagonOverride *overrides; |
40 WagonOverride *overrides; |
39 }; |
41 }; |
40 |
42 |
41 static WagonOverrides _engine_wagon_overrides[TOTAL_NUM_ENGINES]; |
43 static WagonOverrides _engine_wagon_overrides[TOTAL_NUM_ENGINES]; |
42 |
44 |
43 void SetWagonOverrideSprites(EngineID engine, CargoID cargo, const SpriteGroup *group, byte *train_id, int trains) |
45 void SetWagonOverrideSprites(EngineID engine, CargoID cargo, const SpriteGroup *group, EngineID *train_id, uint trains) |
44 { |
46 { |
45 WagonOverrides *wos; |
47 WagonOverrides *wos; |
46 WagonOverride *wo; |
48 WagonOverride *wo; |
47 |
49 |
48 assert(engine < TOTAL_NUM_ENGINES); |
50 assert(engine < TOTAL_NUM_ENGINES); |
57 * to prevent leaks. But first we need to refcount the SpriteGroup. |
59 * to prevent leaks. But first we need to refcount the SpriteGroup. |
58 * --pasky */ |
60 * --pasky */ |
59 wo->group = group; |
61 wo->group = group; |
60 wo->cargo = cargo; |
62 wo->cargo = cargo; |
61 wo->trains = trains; |
63 wo->trains = trains; |
62 wo->train_id = MallocT<byte>(trains); |
64 wo->train_id = MallocT<EngineID>(trains); |
63 memcpy(wo->train_id, train_id, trains); |
65 memcpy(wo->train_id, train_id, trains * sizeof *train_id); |
64 } |
66 } |
65 |
67 |
66 const SpriteGroup *GetWagonOverrideSpriteSet(EngineID engine, CargoID cargo, byte overriding_engine) |
68 const SpriteGroup *GetWagonOverrideSpriteSet(EngineID engine, CargoID cargo, EngineID overriding_engine) |
67 { |
69 { |
68 const WagonOverrides *wos = &_engine_wagon_overrides[engine]; |
70 const WagonOverrides *wos = &_engine_wagon_overrides[engine]; |
69 |
71 |
70 /* XXX: This could turn out to be a timesink on profiles. We could |
72 /* XXX: This could turn out to be a timesink on profiles. We could |
71 * always just dedicate 65535 bytes for an [engine][train] trampoline |
73 * always just dedicate 65535 bytes for an [engine][train] trampoline |
72 * for O(1). Or O(logMlogN) and searching binary tree or smt. like |
74 * for O(1). Or O(logMlogN) and searching binary tree or smt. like |
73 * that. --pasky */ |
75 * that. --pasky */ |
74 |
76 |
75 for (int i = 0; i < wos->overrides_count; i++) { |
77 for (uint i = 0; i < wos->overrides_count; i++) { |
76 const WagonOverride *wo = &wos->overrides[i]; |
78 const WagonOverride *wo = &wos->overrides[i]; |
77 |
79 |
78 if (wo->cargo != cargo && wo->cargo != CT_DEFAULT) continue; |
80 if (wo->cargo != cargo && wo->cargo != CT_DEFAULT) continue; |
79 |
81 |
80 for (int j = 0; j < wo->trains; j++) { |
82 for (uint j = 0; j < wo->trains; j++) { |
81 if (wo->train_id[j] == overriding_engine) return wo->group; |
83 if (wo->train_id[j] == overriding_engine) return wo->group; |
82 } |
84 } |
83 } |
85 } |
84 return NULL; |
86 return NULL; |
85 } |
87 } |
87 /** |
89 /** |
88 * Unload all wagon override sprite groups. |
90 * Unload all wagon override sprite groups. |
89 */ |
91 */ |
90 void UnloadWagonOverrides() |
92 void UnloadWagonOverrides() |
91 { |
93 { |
92 WagonOverrides *wos; |
94 for (EngineID engine = 0; engine < TOTAL_NUM_ENGINES; engine++) { |
93 WagonOverride *wo; |
95 WagonOverrides *wos = &_engine_wagon_overrides[engine]; |
94 EngineID engine; |
96 for (uint i = 0; i < wos->overrides_count; i++) { |
95 int i; |
97 WagonOverride *wo = &wos->overrides[i]; |
96 |
|
97 for (engine = 0; engine < TOTAL_NUM_ENGINES; engine++) { |
|
98 wos = &_engine_wagon_overrides[engine]; |
|
99 for (i = 0; i < wos->overrides_count; i++) { |
|
100 wo = &wos->overrides[i]; |
|
101 wo->group = NULL; |
|
102 free(wo->train_id); |
98 free(wo->train_id); |
103 } |
99 } |
104 free(wos->overrides); |
100 free(wos->overrides); |
105 wos->overrides_count = 0; |
101 wos->overrides_count = 0; |
106 wos->overrides = NULL; |
102 wos->overrides = NULL; |
128 void UnloadCustomEngineSprites() |
124 void UnloadCustomEngineSprites() |
129 { |
125 { |
130 memset(_engine_custom_sprites, 0, sizeof(_engine_custom_sprites)); |
126 memset(_engine_custom_sprites, 0, sizeof(_engine_custom_sprites)); |
131 memset(_engine_grf, 0, sizeof(_engine_grf)); |
127 memset(_engine_grf, 0, sizeof(_engine_grf)); |
132 } |
128 } |
133 |
|
134 static const SpriteGroup *heli_rotor_custom_sprites[NUM_AIRCRAFT_ENGINES]; |
|
135 |
|
136 /** Load a rotor override sprite group for an aircraft */ |
|
137 void SetRotorOverrideSprites(EngineID engine, const SpriteGroup *group) |
|
138 { |
|
139 assert(engine >= AIRCRAFT_ENGINES_INDEX); |
|
140 assert(engine < AIRCRAFT_ENGINES_INDEX + NUM_AIRCRAFT_ENGINES); |
|
141 |
|
142 if (heli_rotor_custom_sprites[engine - AIRCRAFT_ENGINES_INDEX] != NULL) { |
|
143 grfmsg(6, "SetRotorOverrideSprites: engine %d already has group -- replacing.", engine); |
|
144 } |
|
145 heli_rotor_custom_sprites[engine - AIRCRAFT_ENGINES_INDEX] = group; |
|
146 } |
|
147 |
|
148 /** Unload all rotor override sprite groups */ |
|
149 void UnloadRotorOverrideSprites() |
|
150 { |
|
151 EngineID engine; |
|
152 |
|
153 /* Starting at AIRCRAFT_ENGINES_INDEX may seem pointless, but it means |
|
154 * the context of EngineID is correct */ |
|
155 for (engine = AIRCRAFT_ENGINES_INDEX; engine < AIRCRAFT_ENGINES_INDEX + NUM_AIRCRAFT_ENGINES; engine++) { |
|
156 heli_rotor_custom_sprites[engine - AIRCRAFT_ENGINES_INDEX] = NULL; |
|
157 } |
|
158 } |
|
159 |
|
160 |
129 |
161 /** |
130 /** |
162 * Tie a GRFFile entry to an engine, to allow us to retrieve GRF parameters |
131 * Tie a GRFFile entry to an engine, to allow us to retrieve GRF parameters |
163 * etc during a game. |
132 * etc during a game. |
164 * @param engine Engine ID to tie the GRFFile to. |
133 * @param engine Engine ID to tie the GRFFile to. |
720 case 0x5A: return v->Next() == NULL ? INVALID_VEHICLE : v->Next()->index; |
689 case 0x5A: return v->Next() == NULL ? INVALID_VEHICLE : v->Next()->index; |
721 case 0x5C: return ClampToI32(v->value); |
690 case 0x5C: return ClampToI32(v->value); |
722 case 0x5D: return GB(ClampToI32(v->value), 8, 24); |
691 case 0x5D: return GB(ClampToI32(v->value), 8, 24); |
723 case 0x5E: return GB(ClampToI32(v->value), 16, 16); |
692 case 0x5E: return GB(ClampToI32(v->value), 16, 16); |
724 case 0x5F: return GB(ClampToI32(v->value), 24, 8); |
693 case 0x5F: return GB(ClampToI32(v->value), 24, 8); |
725 case 0x60: return v->string_id; |
|
726 case 0x61: return GB(v->string_id, 8, 8); |
|
727 case 0x72: return v->cargo_subtype; |
694 case 0x72: return v->cargo_subtype; |
728 case 0x7A: return v->random_bits; |
695 case 0x7A: return v->random_bits; |
729 case 0x7B: return v->waiting_triggers; |
696 case 0x7B: return v->waiting_triggers; |
730 } |
697 } |
731 |
698 |
786 |
753 |
787 bool in_motion = v->First()->current_order.type != OT_LOADING; |
754 bool in_motion = v->First()->current_order.type != OT_LOADING; |
788 |
755 |
789 totalsets = in_motion ? group->g.real.num_loaded : group->g.real.num_loading; |
756 totalsets = in_motion ? group->g.real.num_loaded : group->g.real.num_loading; |
790 |
757 |
791 if (v->cargo.Count() == v->cargo_cap || totalsets == 1) { |
758 if (v->cargo.Count() >= v->cargo_cap || totalsets == 1) { |
792 set = totalsets - 1; |
759 set = totalsets - 1; |
793 } else if (v->cargo.Empty() || totalsets == 2) { |
760 } else if (v->cargo.Empty() || totalsets == 2) { |
794 set = 0; |
761 set = 0; |
795 } else { |
762 } else { |
796 set = v->cargo.Count() * (totalsets - 2) / max((uint16)1, v->cargo_cap) + 1; |
763 set = v->cargo.Count() * (totalsets - 2) / max((uint16)1, v->cargo_cap) + 1; |
886 |
853 |
887 NewVehicleResolver(&object, engine, v); |
854 NewVehicleResolver(&object, engine, v); |
888 |
855 |
889 object.info_view = info_view; |
856 object.info_view = info_view; |
890 |
857 |
891 group = heli_rotor_custom_sprites[engine - AIRCRAFT_ENGINES_INDEX]; |
858 group = GetWagonOverrideSpriteSet(engine, CT_DEFAULT, engine); |
892 group = Resolve(group, &object); |
859 group = Resolve(group, &object); |
893 |
860 |
894 if (group == NULL || group->type != SGT_RESULT) return 0; |
861 if (group == NULL || group->type != SGT_RESULT) return 0; |
895 |
862 |
896 if (v == NULL) return group->g.result.sprite; |
863 if (v == NULL) return group->g.result.sprite; |
1054 } |
1021 } |
1055 |
1022 |
1056 DoTriggerVehicle(v, trigger, 0, true); |
1023 DoTriggerVehicle(v, trigger, 0, true); |
1057 } |
1024 } |
1058 |
1025 |
1059 StringID _engine_custom_names[TOTAL_NUM_ENGINES]; |
|
1060 |
|
1061 void SetCustomEngineName(EngineID engine, StringID name) |
|
1062 { |
|
1063 assert(engine < lengthof(_engine_custom_names)); |
|
1064 _engine_custom_names[engine] = name; |
|
1065 } |
|
1066 |
|
1067 void UnloadCustomEngineNames() |
|
1068 { |
|
1069 EngineID i; |
|
1070 for (i = 0; i < TOTAL_NUM_ENGINES; i++) { |
|
1071 _engine_custom_names[i] = 0; |
|
1072 } |
|
1073 } |
|
1074 |
|
1075 StringID GetCustomEngineName(EngineID engine) |
|
1076 { |
|
1077 return _engine_custom_names[engine] == 0 ? _engine_name_strings[engine] : _engine_custom_names[engine]; |
|
1078 } |
|
1079 |
|
1080 /* Functions for changing the order of vehicle purchase lists |
1026 /* Functions for changing the order of vehicle purchase lists |
1081 * This is currently only implemented for rail vehicles. */ |
1027 * This is currently only implemented for rail vehicles. */ |
1082 static EngineID _engine_list_order[NUM_TRAIN_ENGINES]; |
1028 static EngineID _engine_list_order[NUM_TRAIN_ENGINES]; |
1083 static byte _engine_list_position[NUM_TRAIN_ENGINES]; |
1029 static byte _engine_list_position[NUM_TRAIN_ENGINES]; |
1084 |
1030 |