0
|
1 |
#include "stdafx.h"
|
|
2 |
#include "ttd.h"
|
|
3 |
#include "command.h"
|
|
4 |
#include "viewport.h"
|
|
5 |
#include "player.h"
|
|
6 |
#include "gui.h"
|
|
7 |
#include "economy.h"
|
|
8 |
#include "town.h"
|
|
9 |
|
|
10 |
typedef struct DrawTileUnmovableStruct {
|
|
11 |
uint16 image;
|
|
12 |
byte subcoord_x;
|
|
13 |
byte subcoord_y;
|
|
14 |
byte width;
|
|
15 |
byte height;
|
|
16 |
byte z_size;
|
|
17 |
byte unused;
|
|
18 |
} DrawTileUnmovableStruct;
|
|
19 |
|
|
20 |
typedef struct DrawTileSeqStruct {
|
|
21 |
int8 delta_x;
|
|
22 |
int8 delta_y;
|
|
23 |
int8 delta_z;
|
|
24 |
byte width,height;
|
|
25 |
byte unk;
|
|
26 |
SpriteID image;
|
|
27 |
} DrawTileSeqStruct;
|
|
28 |
|
|
29 |
#include "table/unmovable_land.h"
|
|
30 |
|
|
31 |
static void DrawTile_Unmovable(TileInfo *ti)
|
|
32 |
{
|
|
33 |
uint32 image, ormod;
|
|
34 |
|
|
35 |
if (!(ti->map5 & 0x80)) {
|
|
36 |
if (ti->map5 == 2) {
|
|
37 |
|
|
38 |
// statue
|
|
39 |
DrawGroundSprite(0x58C);
|
|
40 |
|
|
41 |
image = PLAYER_SPRITE_COLOR(_map_owner[ti->tile]);
|
|
42 |
image += 0x8A48;
|
|
43 |
if (!(_display_opt & DO_TRANS_BUILDINGS))
|
|
44 |
image = (image & 0x3FFF) | 0x3224000;
|
|
45 |
AddSortableSpriteToDraw(image, ti->x, ti->y, 16, 16, 25, ti->z);
|
|
46 |
} else if (ti->map5 == 3) {
|
|
47 |
|
|
48 |
// "owned by" sign
|
|
49 |
DrawClearLandTile(ti, 0);
|
|
50 |
|
|
51 |
AddSortableSpriteToDraw(
|
|
52 |
PLAYER_SPRITE_COLOR(_map_owner[ti->tile]) + 0x92B6,
|
|
53 |
ti->x+8, ti->y+8,
|
|
54 |
1, 1,
|
|
55 |
10,
|
|
56 |
GetSlopeZ(ti->x+8, ti->y+8)
|
|
57 |
);
|
|
58 |
} else {
|
|
59 |
// lighthouse or transmitter
|
|
60 |
|
|
61 |
const DrawTileUnmovableStruct *dtus;
|
|
62 |
|
|
63 |
if (ti->tileh) DrawFoundation(ti, ti->tileh);
|
|
64 |
DrawClearLandTile(ti, 2);
|
|
65 |
|
|
66 |
dtus = &_draw_tile_unmovable_data[ti->map5];
|
|
67 |
|
|
68 |
image = dtus->image;
|
|
69 |
if (!(_display_opt & DO_TRANS_BUILDINGS))
|
|
70 |
image = (image & 0x3FFF) | 0x3224000;
|
|
71 |
|
|
72 |
AddSortableSpriteToDraw(image,
|
|
73 |
ti->x | dtus->subcoord_x,
|
|
74 |
ti->y | dtus->subcoord_y,
|
|
75 |
dtus->width, dtus->height,
|
|
76 |
dtus->z_size, ti->z);
|
|
77 |
}
|
|
78 |
} else {
|
|
79 |
const DrawTileSeqStruct *dtss;
|
|
80 |
const byte *t;
|
|
81 |
|
|
82 |
if (ti->tileh) DrawFoundation(ti, ti->tileh);
|
|
83 |
|
|
84 |
ormod = PLAYER_SPRITE_COLOR(_map_owner[ti->tile]);
|
|
85 |
|
|
86 |
t = _unmovable_display_datas[ti->map5 & 0x7F];
|
|
87 |
DrawGroundSprite(*(uint16*)t | ormod);
|
|
88 |
|
|
89 |
t += sizeof(uint16);
|
|
90 |
|
|
91 |
for(dtss = (DrawTileSeqStruct *)t; (byte)dtss->delta_x != 0x80; dtss++) {
|
|
92 |
image = dtss->image;
|
|
93 |
if (_display_opt & DO_TRANS_BUILDINGS) {
|
|
94 |
image |= ormod;
|
|
95 |
} else {
|
|
96 |
image = (image & 0x3FFF) | 0x03224000;
|
|
97 |
}
|
|
98 |
AddSortableSpriteToDraw(image, ti->x + dtss->delta_x, ti->y + dtss->delta_y,
|
|
99 |
dtss->width, dtss->height, dtss->unk, ti->z + dtss->delta_z);
|
|
100 |
}
|
|
101 |
}
|
|
102 |
}
|
|
103 |
|
|
104 |
static uint GetSlopeZ_Unmovable(TileInfo *ti)
|
|
105 |
{
|
|
106 |
return GetPartialZ(ti->x&0xF, ti->y&0xF, ti->tileh) + ti->z;
|
|
107 |
}
|
|
108 |
|
|
109 |
static int32 ClearTile_Unmovable(uint tile, byte flags)
|
|
110 |
{
|
|
111 |
byte m5 = _map5[tile];
|
|
112 |
//Town *t;
|
|
113 |
|
|
114 |
if (m5 & 0x80)
|
|
115 |
return_cmd_error(STR_5804_COMPANY_HEADQUARTERS_IN);
|
|
116 |
|
|
117 |
if (m5 == 3) // company owned land
|
|
118 |
return DoCommandByTile(tile, 0, 0, flags, CMD_SELL_LAND_AREA);
|
|
119 |
|
|
120 |
//t = ClosestTownFromTile(tile, _patches.dist_local_authority + 20); // needed for town penalty
|
|
121 |
|
|
122 |
// checks if you're allowed to remove unmovable things. no remove under rating "%difficulty setting"
|
|
123 |
if (_game_mode != GM_EDITOR) {
|
|
124 |
if (flags & DC_AUTO || !_cheats.magic_bulldozer.value)
|
|
125 |
return_cmd_error(STR_5800_OBJECT_IN_THE_WAY);
|
|
126 |
|
|
127 |
/*if (!CheckforTownRating(tile, flags, t, UNMOVEABLE_REMOVE))
|
|
128 |
return CMD_ERROR;
|
|
129 |
*/
|
|
130 |
|
|
131 |
}
|
|
132 |
|
|
133 |
if (flags & DC_EXEC) {
|
|
134 |
DoClearSquare(tile);
|
|
135 |
// decreases the town rating by 250;
|
|
136 |
/*if (_game_mode != GM_EDITOR)
|
|
137 |
ChangeTownRating(t, -250, -100);
|
|
138 |
*/
|
|
139 |
}
|
|
140 |
|
|
141 |
// return _price.build_industry*0.34;
|
|
142 |
return 0;
|
|
143 |
}
|
|
144 |
|
|
145 |
static void GetAcceptedCargo_Unmovable(uint tile, AcceptedCargo *ac)
|
|
146 |
{
|
|
147 |
byte m5 = _map5[tile];
|
|
148 |
uint level; // HQ level (depends on company performance) in the range 1..5.
|
|
149 |
|
|
150 |
if (!(m5 & 0x80)) {
|
|
151 |
/* not used */
|
|
152 |
return;
|
|
153 |
}
|
|
154 |
|
|
155 |
/* HQ accepts passenger and mail; but we have to divide the values
|
|
156 |
* between 4 tiles it occupies! */
|
|
157 |
|
|
158 |
level = (m5 & ~0x80) / 4 + 1;
|
|
159 |
|
|
160 |
// Top town building generates 10, so to make HQ interesting, the top
|
|
161 |
// type makes 20.
|
|
162 |
ac->type_1 = CT_PASSENGERS;
|
|
163 |
ac->amount_1 = level;
|
|
164 |
if (!ac->amount_1) ac->amount_1 = 1;
|
|
165 |
|
|
166 |
// Top town building generates 4, HQ can make up to 8. The
|
|
167 |
// proportion passengers:mail is different because such a huge
|
|
168 |
// commercial building generates unusually high amount of mail
|
|
169 |
// correspondence per physical visitor.
|
|
170 |
ac->type_2 = CT_MAIL;
|
|
171 |
ac->amount_2 = level / 2;
|
|
172 |
if (!ac->amount_2) ac->amount_2 = 1;
|
|
173 |
}
|
|
174 |
|
|
175 |
static const StringID _unmovable_tile_str[] = {
|
|
176 |
STR_5803_COMPANY_HEADQUARTERS,
|
|
177 |
STR_5801_TRANSMITTER,
|
|
178 |
STR_5802_LIGHTHOUSE,
|
|
179 |
STR_2016_STATUE,
|
|
180 |
STR_5805_COMPANY_OWNED_LAND,
|
|
181 |
};
|
|
182 |
|
|
183 |
static void GetTileDesc_Unmovable(uint tile, TileDesc *td)
|
|
184 |
{
|
|
185 |
int i = _map5[tile];
|
|
186 |
if (i & 0x80) i = -1;
|
|
187 |
td->str = _unmovable_tile_str[i + 1];
|
|
188 |
td->owner = _map_owner[tile];
|
|
189 |
}
|
|
190 |
|
|
191 |
static void AnimateTile_Unmovable(uint tile)
|
|
192 |
{
|
|
193 |
/* not used */
|
|
194 |
}
|
|
195 |
|
|
196 |
static void TileLoop_Unmovable(uint tile)
|
|
197 |
{
|
|
198 |
byte m5 = _map5[tile];
|
|
199 |
byte level; // HQ level (depends on company performance) in the range 1..5.
|
|
200 |
uint32 r;
|
|
201 |
|
|
202 |
if (!(m5 & 0x80)) {
|
|
203 |
/* not used */
|
|
204 |
return;
|
|
205 |
}
|
|
206 |
|
|
207 |
/* HQ accepts passenger and mail; but we have to divide the values
|
|
208 |
* between 4 tiles it occupies! */
|
|
209 |
|
|
210 |
level = (m5 & ~0x80) / 4 + 1;
|
|
211 |
assert(level < 6);
|
|
212 |
|
|
213 |
r = Random();
|
|
214 |
// Top town buildings generate 250, so the top HQ type makes 256.
|
|
215 |
if ((byte) r < (256 / 4 / (6 - level))) {
|
|
216 |
uint amt = ((byte) r >> 3) / 4 + 1;
|
|
217 |
if (_economy.fluct <= 0) amt = (amt + 1) >> 1;
|
|
218 |
MoveGoodsToStation(tile, 2, 2, CT_PASSENGERS, amt);
|
|
219 |
}
|
|
220 |
|
|
221 |
r >>= 8;
|
|
222 |
// Top town building generates 90, HQ can make up to 196. The
|
|
223 |
// proportion passengers:mail is about the same as in the acceptance
|
|
224 |
// equations.
|
|
225 |
if ((byte) r < (196 / 4 / (6 - level))) {
|
|
226 |
uint amt = ((byte) r >> 3) / 4 + 1;
|
|
227 |
if (_economy.fluct <= 0) amt = (amt + 1) >> 1;
|
|
228 |
MoveGoodsToStation(tile, 2, 2, CT_MAIL, amt);
|
|
229 |
}
|
|
230 |
}
|
|
231 |
|
|
232 |
|
|
233 |
static uint32 GetTileTrackStatus_Unmovable(uint tile, int mode)
|
|
234 |
{
|
|
235 |
return 0;
|
|
236 |
}
|
|
237 |
|
|
238 |
static void ClickTile_Unmovable(uint tile)
|
|
239 |
{
|
|
240 |
if (_map5[tile] & 0x80) {
|
|
241 |
ShowPlayerCompany(_map_owner[tile]);
|
|
242 |
}
|
|
243 |
}
|
|
244 |
|
|
245 |
static const TileIndexDiff _tile_add[4] = {
|
|
246 |
TILE_XY(1,0),
|
|
247 |
TILE_XY(0,1),
|
|
248 |
TILE_XY(-1,0),
|
|
249 |
TILE_XY(0,-1),
|
|
250 |
};
|
|
251 |
|
|
252 |
/* checks, if a radio tower is within a 9x9 tile square around tile */
|
|
253 |
bool checkRadioTowerNearby(uint tile)
|
|
254 |
{
|
|
255 |
uint tile_s;
|
|
256 |
|
|
257 |
tile_s = TILE_XY( (int) GET_TILE_X(tile)-4, (int) GET_TILE_Y(tile)-4 );
|
|
258 |
|
|
259 |
BEGIN_TILE_LOOP(tile, 9, 9, tile_s)
|
|
260 |
// already a radio tower here?
|
|
261 |
if (IS_TILETYPE(tile, MP_UNMOVABLE) && _map5[tile] == 0)
|
|
262 |
return false;
|
|
263 |
END_TILE_LOOP(tile, 9, 9, tile_s)
|
|
264 |
return true;
|
|
265 |
}
|
|
266 |
|
|
267 |
void GenerateUnmovables()
|
|
268 |
{
|
|
269 |
int i,j;
|
|
270 |
uint tile;
|
|
271 |
uint32 r;
|
|
272 |
int dir;
|
|
273 |
int h;
|
|
274 |
|
|
275 |
if (_opt.landscape == LT_CANDY)
|
|
276 |
return;
|
|
277 |
|
|
278 |
/* add radio tower */
|
|
279 |
i = 1000;
|
|
280 |
j = 40; // limit of 40 radio towers per world.
|
|
281 |
do {
|
|
282 |
r = Random();
|
|
283 |
tile = r % (TILES_X*TILES_Y);
|
|
284 |
// TILE_MASK seems to be not working correctly. Radio masts accumulate in one area.
|
|
285 |
// tile = TILE_MASK(r);
|
|
286 |
if (IS_TILETYPE(tile, MP_CLEAR) && GetTileSlope(tile, &h) == 0 && h >= 32) {
|
|
287 |
if(!checkRadioTowerNearby(tile))
|
|
288 |
continue;
|
|
289 |
_map_type_and_height[tile] |= MP_UNMOVABLE << 4;
|
|
290 |
_map5[tile] = 0;
|
|
291 |
_map_owner[tile] = OWNER_NONE;
|
|
292 |
if (--j == 0)
|
|
293 |
break;
|
|
294 |
}
|
|
295 |
} while (--i);
|
|
296 |
|
|
297 |
if (_opt.landscape == LT_DESERT)
|
|
298 |
return;
|
|
299 |
|
|
300 |
/* add lighthouses */
|
|
301 |
i = (Random()&3) + 7;
|
|
302 |
do {
|
|
303 |
restart:
|
|
304 |
r = Random();
|
|
305 |
dir = r >> 30;
|
|
306 |
r = r%((dir==0 || dir== 2)?TILE_Y_MAX:TILE_X_MAX);
|
|
307 |
tile =
|
|
308 |
(dir==0)?TILE_XY(0,r):0 + // left
|
|
309 |
(dir==1)?TILE_XY(r,0):0 + // top
|
|
310 |
(dir==2)?TILE_XY(TILE_X_MAX,r):0 + // right
|
|
311 |
(dir==3)?TILE_XY(r,TILE_Y_MAX):0; // bottom
|
|
312 |
j = 20;
|
|
313 |
do {
|
|
314 |
if (--j == 0)
|
|
315 |
goto restart;
|
|
316 |
tile = TILE_MASK(tile + _tile_add[dir]);
|
|
317 |
} while (!(IS_TILETYPE(tile, MP_CLEAR) && GetTileSlope(tile, &h) == 0 && h <= 16));
|
|
318 |
|
|
319 |
assert(tile == TILE_MASK(tile));
|
|
320 |
|
|
321 |
_map_type_and_height[tile] |= MP_UNMOVABLE << 4;
|
|
322 |
_map5[tile] = 1;
|
|
323 |
_map_owner[tile] = OWNER_NONE;
|
|
324 |
} while (--i);
|
|
325 |
}
|
|
326 |
|
|
327 |
extern int32 CheckFlatLandBelow(uint tile, uint w, uint h, uint flags, uint invalid_dirs, int *);
|
|
328 |
|
|
329 |
int32 CmdBuildCompanyHQ(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|
330 |
{
|
|
331 |
uint tile = TILE_FROM_XY(x,y);
|
|
332 |
|
|
333 |
if (CheckFlatLandBelow(tile, 2, 2, flags, 0, NULL) == CMD_ERROR)
|
|
334 |
return CMD_ERROR;
|
|
335 |
|
|
336 |
if (flags & DC_EXEC) {
|
|
337 |
DEREF_PLAYER(_current_player)->location_of_house = tile;
|
|
338 |
|
|
339 |
ModifyTile(tile + TILE_XY(0,0),
|
|
340 |
MP_SETTYPE(MP_UNMOVABLE) | MP_MAPOWNER_CURRENT | MP_MAP5,
|
|
341 |
0x80
|
|
342 |
);
|
|
343 |
|
|
344 |
ModifyTile(tile + TILE_XY(0,1),
|
|
345 |
MP_SETTYPE(MP_UNMOVABLE) | MP_MAPOWNER_CURRENT | MP_MAP5,
|
|
346 |
0x81
|
|
347 |
);
|
|
348 |
|
|
349 |
ModifyTile(tile + TILE_XY(1,0),
|
|
350 |
MP_SETTYPE(MP_UNMOVABLE) | MP_MAPOWNER_CURRENT | MP_MAP5,
|
|
351 |
0x82
|
|
352 |
);
|
|
353 |
|
|
354 |
ModifyTile(tile + TILE_XY(1,1),
|
|
355 |
MP_SETTYPE(MP_UNMOVABLE) | MP_MAPOWNER_CURRENT | MP_MAP5,
|
|
356 |
0x83
|
|
357 |
);
|
|
358 |
}
|
|
359 |
|
|
360 |
return 0;
|
|
361 |
}
|
|
362 |
|
|
363 |
static void ChangeTileOwner_Unmovable(uint tile, byte old_player, byte new_player)
|
|
364 |
{
|
|
365 |
if (_map_owner[tile] != old_player)
|
|
366 |
return;
|
|
367 |
|
|
368 |
if (_map5[tile]==3 && new_player != 255) {
|
|
369 |
_map_owner[tile] = new_player;
|
|
370 |
} else {
|
|
371 |
DoClearSquare(tile);
|
|
372 |
}
|
|
373 |
}
|
|
374 |
|
|
375 |
const TileTypeProcs _tile_type_unmovable_procs = {
|
|
376 |
DrawTile_Unmovable, /* draw_tile_proc */
|
|
377 |
GetSlopeZ_Unmovable, /* get_slope_z_proc */
|
|
378 |
ClearTile_Unmovable, /* clear_tile_proc */
|
|
379 |
GetAcceptedCargo_Unmovable, /* get_accepted_cargo_proc */
|
|
380 |
GetTileDesc_Unmovable, /* get_tile_desc_proc */
|
|
381 |
GetTileTrackStatus_Unmovable, /* get_tile_track_status_proc */
|
|
382 |
ClickTile_Unmovable, /* click_tile_proc */
|
|
383 |
AnimateTile_Unmovable, /* animate_tile_proc */
|
|
384 |
TileLoop_Unmovable, /* tile_loop_clear */
|
|
385 |
ChangeTileOwner_Unmovable, /* change_tile_owner_clear */
|
|
386 |
NULL, /* get_produced_cargo_proc */
|
|
387 |
NULL, /* vehicle_enter_tile_proc */
|
|
388 |
NULL, /* vehicle_leave_tile_proc */
|
|
389 |
};
|