Files
@ r28520:f9aebe299cae
Branch filter:
Location: cpp/openttd-patchpack/source/src/newgrf_industrytiles.cpp - annotation
r28520:f9aebe299cae
14.3 KiB
text/x-c
Codechange: MacOS already has MIN/MAX macros defined
This is caused because we use PreCompile Headers, and one of them
includes a system headers which defines MIN/MAX.
This is caused because we use PreCompile Headers, and one of them
includes a system headers which defines MIN/MAX.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 | r12768:980ae0491352 r12768:980ae0491352 r12768:980ae0491352 r12768:980ae0491352 r12768:980ae0491352 r12768:980ae0491352 r12768:980ae0491352 r9111:983de9c5a848 r6884:06c993c360e4 r6884:06c993c360e4 r6884:06c993c360e4 r6884:06c993c360e4 r7229:58b7db9e5145 r9018:0a11b607e602 r12816:33099b7286d4 r8213:466402e95092 r8275:5932486ddd21 r9718:c3fa0e5e369d r15929:5d5037945a0e r6884:06c993c360e4 r8264:d493cb51fe8a r8264:d493cb51fe8a r21383:942c32fb8b0e r21383:942c32fb8b0e r6884:06c993c360e4 r6884:06c993c360e4 r6884:06c993c360e4 r6884:06c993c360e4 r6884:06c993c360e4 r16279:c9054b28cdd6 r18308:05de10e00a85 r6884:06c993c360e4 r6884:06c993c360e4 r27737:728d55b97775 r6884:06c993c360e4 r16279:c9054b28cdd6 r8458:f7e90b7c0926 r6884:06c993c360e4 r18308:05de10e00a85 r6884:06c993c360e4 r6884:06c993c360e4 r15610:623a23fb6560 r15610:623a23fb6560 r6884:06c993c360e4 r6884:06c993c360e4 r6884:06c993c360e4 r6884:06c993c360e4 r6884:06c993c360e4 r6884:06c993c360e4 r6884:06c993c360e4 r6884:06c993c360e4 r6884:06c993c360e4 r27737:728d55b97775 r6884:06c993c360e4 r6919:aea636af9c8e r6919:aea636af9c8e r6884:06c993c360e4 r6884:06c993c360e4 r6884:06c993c360e4 r6884:06c993c360e4 r27942:f7389062d120 r6884:06c993c360e4 r6884:06c993c360e4 r11162:b56c3cec6367 r19735:1c0b94f19bce r6884:06c993c360e4 r11162:b56c3cec6367 r19735:1c0b94f19bce r6884:06c993c360e4 r6899:aa4751e3d864 r19735:1c0b94f19bce r6884:06c993c360e4 r6899:aa4751e3d864 r19735:1c0b94f19bce r6884:06c993c360e4 r6899:aa4751e3d864 r19735:1c0b94f19bce r6884:06c993c360e4 r6899:aa4751e3d864 r19735:1c0b94f19bce r23607:36c15679007d r6884:06c993c360e4 r7234:89807e0412b9 r19735:1c0b94f19bce r19735:1c0b94f19bce r19735:1c0b94f19bce r15924:f5bba173626e r6899:aa4751e3d864 r11162:b56c3cec6367 r19735:1c0b94f19bce r6884:06c993c360e4 r6884:06c993c360e4 r21008:be2e3d3c935b r6884:06c993c360e4 r6884:06c993c360e4 r25655:1030dcb7eb52 r7233:d578434a488b r7233:d578434a488b r11163:407814b6138f r6884:06c993c360e4 r6884:06c993c360e4 r27737:728d55b97775 r6884:06c993c360e4 r23607:36c15679007d r19735:1c0b94f19bce r15104:1752997daf93 r19735:1c0b94f19bce r6884:06c993c360e4 r6884:06c993c360e4 r27737:728d55b97775 r6884:06c993c360e4 r23607:36c15679007d r19735:1c0b94f19bce r19735:1c0b94f19bce r19735:1c0b94f19bce r6884:06c993c360e4 r6884:06c993c360e4 r17768:a8b4e13e2113 r19735:1c0b94f19bce r19735:1c0b94f19bce r19735:1c0b94f19bce r17768:a8b4e13e2113 r19735:1c0b94f19bce r17768:a8b4e13e2113 r19735:1c0b94f19bce r23607:36c15679007d r17768:a8b4e13e2113 r17768:a8b4e13e2113 r19738:837a139219f0 r19738:837a139219f0 r19738:837a139219f0 r19738:837a139219f0 r19738:837a139219f0 r19738:837a139219f0 r19738:837a139219f0 r19738:837a139219f0 r19738:837a139219f0 r19735:1c0b94f19bce r27737:728d55b97775 r19735:1c0b94f19bce r21008:be2e3d3c935b r24069:49625df81342 r24069:49625df81342 r6884:06c993c360e4 r21299:8973364c4b52 r19735:1c0b94f19bce r6884:06c993c360e4 r24069:49625df81342 r24069:49625df81342 r24069:49625df81342 r24069:49625df81342 r24069:49625df81342 r27737:728d55b97775 r24069:49625df81342 r24069:49625df81342 r24069:49625df81342 r24069:49625df81342 r27944:a5c70dad53db r6970:377763da9c24 r17728:6a6e98f25cac r6970:377763da9c24 r8571:ede148e241b1 r14309:f445232b17f6 r6970:377763da9c24 r14280:9e2593121da6 r17728:6a6e98f25cac r7656:8a3acdcc26d6 r9718:c3fa0e5e369d r9718:c3fa0e5e369d r9718:c3fa0e5e369d r15933:39e6324db57a r9718:c3fa0e5e369d r9718:c3fa0e5e369d r11085:c87a330fb4c2 r9718:c3fa0e5e369d r9718:c3fa0e5e369d r6970:377763da9c24 r14284:8fe3cab84763 r6970:377763da9c24 r6970:377763da9c24 r27737:728d55b97775 r6884:06c993c360e4 r23607:36c15679007d r15104:1752997daf93 r15104:1752997daf93 r19735:1c0b94f19bce r21299:8973364c4b52 r6884:06c993c360e4 r6970:377763da9c24 r6970:377763da9c24 r6970:377763da9c24 r6970:377763da9c24 r6970:377763da9c24 r13026:0c3f00ec0a74 r6970:377763da9c24 r27737:728d55b97775 r18301:0c1dfbaba57a r6970:377763da9c24 r6970:377763da9c24 r7335:93bf5f4b6ce4 r6970:377763da9c24 r6970:377763da9c24 r19735:1c0b94f19bce r6970:377763da9c24 r21299:8973364c4b52 r23607:36c15679007d r20669:d2e627ece87b r20669:d2e627ece87b r20669:d2e627ece87b r20669:d2e627ece87b r27944:a5c70dad53db r20669:d2e627ece87b r6970:377763da9c24 r7212:15205d2e5142 r7662:914446395fe3 r7662:914446395fe3 r15610:623a23fb6560 r15610:623a23fb6560 r14677:2cb23a1debe3 r14677:2cb23a1debe3 r14677:2cb23a1debe3 r14677:2cb23a1debe3 r14677:2cb23a1debe3 r23867:be2be375b64c r15105:18f362fd63e2 r15256:e22f3389fd3a r16231:76e02ca8f4e5 r19944:25a78576fb5e r14677:2cb23a1debe3 r27737:728d55b97775 r7212:15205d2e5142 r7216:15c27d8bad4a r7662:914446395fe3 r14159:6cb75763eb03 r14159:6cb75763eb03 r7216:15c27d8bad4a r15105:18f362fd63e2 r15256:e22f3389fd3a r7216:15c27d8bad4a r27737:728d55b97775 r7662:914446395fe3 r18247:d176683304d1 r14677:2cb23a1debe3 r7662:914446395fe3 r7212:15205d2e5142 r14677:2cb23a1debe3 r14677:2cb23a1debe3 r7212:15205d2e5142 r7212:15205d2e5142 r21154:68958e5391ae r7212:15205d2e5142 r7229:58b7db9e5145 r15929:5d5037945a0e r27942:f7389062d120 r15929:5d5037945a0e r17762:129a62225055 r15929:5d5037945a0e r15929:5d5037945a0e r15929:5d5037945a0e r26914:6e889cbdcba1 r15929:5d5037945a0e r15929:5d5037945a0e r15929:5d5037945a0e r15929:5d5037945a0e r15929:5d5037945a0e r15929:5d5037945a0e r15929:5d5037945a0e r7229:58b7db9e5145 r7229:58b7db9e5145 r15929:5d5037945a0e r23607:36c15679007d r9018:0a11b607e602 r15929:5d5037945a0e r7229:58b7db9e5145 r7229:58b7db9e5145 r27737:728d55b97775 r7229:58b7db9e5145 r15929:5d5037945a0e r7229:58b7db9e5145 r15925:9a7fe46227a0 r7229:58b7db9e5145 r15929:5d5037945a0e r7229:58b7db9e5145 r7229:58b7db9e5145 r7229:58b7db9e5145 r7229:58b7db9e5145 r7229:58b7db9e5145 r7229:58b7db9e5145 r27737:728d55b97775 r25451:917146b539af r18600:daee608b9023 r7627:149960d8e202 r7627:149960d8e202 r7627:149960d8e202 r7627:149960d8e202 r7627:149960d8e202 r7229:58b7db9e5145 r12519:e52fcaadf579 r7229:58b7db9e5145 r7229:58b7db9e5145 r7229:58b7db9e5145 r7860:c73688ce46ca r17834:447b5cb3ee1a r17834:447b5cb3ee1a r17834:447b5cb3ee1a r17834:447b5cb3ee1a r17834:447b5cb3ee1a r23023:7b8669afd1db r17834:447b5cb3ee1a r27737:728d55b97775 r7860:c73688ce46ca r15104:1752997daf93 r15104:1752997daf93 r7860:c73688ce46ca r7860:c73688ce46ca r7860:c73688ce46ca r23607:36c15679007d r9028:43b29ac0a74d r19735:1c0b94f19bce r22707:80b972b362a5 r22707:80b972b362a5 r7860:c73688ce46ca r21299:8973364c4b52 r23607:36c15679007d r7860:c73688ce46ca r22707:80b972b362a5 r22707:80b972b362a5 r22707:80b972b362a5 r22707:80b972b362a5 r7860:c73688ce46ca r7860:c73688ce46ca r17834:447b5cb3ee1a r17834:447b5cb3ee1a r7860:c73688ce46ca r12653:17768ec4dbe2 r17834:447b5cb3ee1a r17834:447b5cb3ee1a r7860:c73688ce46ca r7860:c73688ce46ca r17834:447b5cb3ee1a r17834:447b5cb3ee1a r17834:447b5cb3ee1a r17834:447b5cb3ee1a r17834:447b5cb3ee1a r27737:728d55b97775 r17834:447b5cb3ee1a r23607:36c15679007d r17834:447b5cb3ee1a r27737:728d55b97775 r17834:447b5cb3ee1a r17834:447b5cb3ee1a r17834:447b5cb3ee1a r17834:447b5cb3ee1a r17834:447b5cb3ee1a r17834:447b5cb3ee1a r17834:447b5cb3ee1a r17834:447b5cb3ee1a r17834:447b5cb3ee1a r7860:c73688ce46ca r7860:c73688ce46ca r27737:728d55b97775 r17834:447b5cb3ee1a r17834:447b5cb3ee1a r17834:447b5cb3ee1a r7860:c73688ce46ca r7860:c73688ce46ca r17834:447b5cb3ee1a r17834:447b5cb3ee1a r17834:447b5cb3ee1a r17834:447b5cb3ee1a r17834:447b5cb3ee1a r7860:c73688ce46ca r7860:c73688ce46ca r27737:728d55b97775 r25451:917146b539af r18600:daee608b9023 r17834:447b5cb3ee1a r7860:c73688ce46ca r12519:e52fcaadf579 r17834:447b5cb3ee1a r7860:c73688ce46ca r15071:e236d80508bb | /*
* This file is part of OpenTTD.
* 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.
* 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.
* 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/>.
*/
/** @file newgrf_industrytiles.cpp NewGRF handling of industry tiles. */
#include "stdafx.h"
#include "debug.h"
#include "landscape.h"
#include "newgrf_industrytiles.h"
#include "newgrf_sound.h"
#include "industry.h"
#include "town.h"
#include "command_func.h"
#include "water.h"
#include "newgrf_animation_base.h"
#include "table/strings.h"
#include "safeguards.h"
/**
* Based on newhouses equivalent, but adapted for newindustries
* @param parameter from callback. It's in fact a pair of coordinates
* @param tile TileIndex from which the callback was initiated
* @param index of the industry been queried for
* @param signed_offsets Are the x and y offset encoded in parameter signed?
* @param grf_version8 True, if we are dealing with a new NewGRF which uses GRF version >= 8.
* @return a construction of bits obeying the newgrf format
*/
uint32_t GetNearbyIndustryTileInformation(byte parameter, TileIndex tile, IndustryID index, bool signed_offsets, bool grf_version8)
{
if (parameter != 0) tile = GetNearbyTile(parameter, tile, signed_offsets); // only perform if it is required
bool is_same_industry = (IsTileType(tile, MP_INDUSTRY) && GetIndustryIndex(tile) == index);
return GetNearbyTileInformation(tile, grf_version8) | (is_same_industry ? 1 : 0) << 8;
}
/**
* This is the position of the tile relative to the northernmost tile of the industry.
* Format: 00yxYYXX
* Variable Content
* x the x offset from the northernmost tile
* XX same, but stored in a byte instead of a nibble
* y the y offset from the northernmost tile
* YY same, but stored in a byte instead of a nibble
* @param tile TileIndex of the tile to evaluate
* @param ind_tile northernmost tile of the industry
*/
uint32_t GetRelativePosition(TileIndex tile, TileIndex ind_tile)
{
byte x = TileX(tile) - TileX(ind_tile);
byte y = TileY(tile) - TileY(ind_tile);
return ((y & 0xF) << 20) | ((x & 0xF) << 16) | (y << 8) | x;
}
/* virtual */ uint32_t IndustryTileScopeResolver::GetVariable(byte variable, [[maybe_unused]] uint32_t parameter, bool *available) const
{
switch (variable) {
/* Construction state of the tile: a value between 0 and 3 */
case 0x40: return (IsTileType(this->tile, MP_INDUSTRY)) ? GetIndustryConstructionStage(this->tile) : 0;
/* Terrain type */
case 0x41: return GetTerrainType(this->tile);
/* Current town zone of the tile in the nearest town */
case 0x42: return GetTownRadiusGroup(ClosestTownFromTile(this->tile, UINT_MAX), this->tile);
/* Relative position */
case 0x43: return GetRelativePosition(this->tile, this->industry->location.tile);
/* Animation frame. Like house variable 46 but can contain anything 0..FF. */
case 0x44: return IsTileType(this->tile, MP_INDUSTRY) ? GetAnimationFrame(this->tile) : 0;
/* Land info of nearby tiles */
case 0x60: return GetNearbyIndustryTileInformation(parameter, this->tile,
this->industry == nullptr ? (IndustryID)INVALID_INDUSTRY : this->industry->index, true, this->ro.grffile->grf_version >= 8);
/* Animation stage of nearby tiles */
case 0x61: {
TileIndex tile = GetNearbyTile(parameter, this->tile);
if (IsTileType(tile, MP_INDUSTRY) && Industry::GetByTile(tile) == this->industry) {
return GetAnimationFrame(tile);
}
return UINT_MAX;
}
/* Get industry tile ID at offset */
case 0x62: return GetIndustryIDAtOffset(GetNearbyTile(parameter, this->tile), this->industry, this->ro.grffile->grfid);
}
Debug(grf, 1, "Unhandled industry tile variable 0x{:X}", variable);
*available = false;
return UINT_MAX;
}
/* virtual */ uint32_t IndustryTileScopeResolver::GetRandomBits() const
{
assert(this->industry != nullptr && IsValidTile(this->tile));
assert(this->industry->index == INVALID_INDUSTRY || IsTileType(this->tile, MP_INDUSTRY));
return (this->industry->index != INVALID_INDUSTRY) ? GetIndustryRandomBits(this->tile) : 0;
}
/* virtual */ uint32_t IndustryTileScopeResolver::GetTriggers() const
{
assert(this->industry != nullptr && IsValidTile(this->tile));
assert(this->industry->index == INVALID_INDUSTRY || IsTileType(this->tile, MP_INDUSTRY));
if (this->industry->index == INVALID_INDUSTRY) return 0;
return GetIndustryTriggers(this->tile);
}
/**
* Get the associated NewGRF file from the industry graphics.
* @param gfx Graphics to query.
* @return Grf file associated with the graphics, if any.
*/
static const GRFFile *GetIndTileGrffile(IndustryGfx gfx)
{
const IndustryTileSpec *its = GetIndustryTileSpec(gfx);
return (its != nullptr) ? its->grf_prop.grffile : nullptr;
}
/**
* Constructor of the industry tiles scope resolver.
* @param gfx Graphics of the industry.
* @param tile %Tile of the industry.
* @param indus %Industry owning the tile.
* @param callback Callback ID.
* @param callback_param1 First parameter (var 10) of the callback.
* @param callback_param2 Second parameter (var 18) of the callback.
*/
IndustryTileResolverObject::IndustryTileResolverObject(IndustryGfx gfx, TileIndex tile, Industry *indus,
CallbackID callback, uint32_t callback_param1, uint32_t callback_param2)
: ResolverObject(GetIndTileGrffile(gfx), callback, callback_param1, callback_param2),
indtile_scope(*this, indus, tile),
ind_scope(*this, tile, indus, indus->type),
gfx(gfx)
{
this->root_spritegroup = GetIndustryTileSpec(gfx)->grf_prop.spritegroup[0];
}
GrfSpecFeature IndustryTileResolverObject::GetFeature() const
{
return GSF_INDUSTRYTILES;
}
uint32_t IndustryTileResolverObject::GetDebugID() const
{
return GetIndustryTileSpec(gfx)->grf_prop.local_id;
}
static void IndustryDrawTileLayout(const TileInfo *ti, const TileLayoutSpriteGroup *group, byte rnd_colour, byte stage)
{
const DrawTileSprites *dts = group->ProcessRegisters(&stage);
SpriteID image = dts->ground.sprite;
PaletteID pal = dts->ground.pal;
if (HasBit(image, SPRITE_MODIFIER_CUSTOM_SPRITE)) image += stage;
if (HasBit(pal, SPRITE_MODIFIER_CUSTOM_SPRITE)) pal += stage;
if (GB(image, 0, SPRITE_WIDTH) != 0) {
/* If the ground sprite is the default flat water sprite, draw also canal/river borders
* Do not do this if the tile's WaterClass is 'land'. */
if (image == SPR_FLAT_WATER_TILE && IsTileOnWater(ti->tile)) {
DrawWaterClassGround(ti);
} else {
DrawGroundSprite(image, GroundSpritePaletteTransform(image, pal, GENERAL_SPRITE_COLOUR(rnd_colour)));
}
}
DrawNewGRFTileSeq(ti, dts, TO_INDUSTRIES, stage, GENERAL_SPRITE_COLOUR(rnd_colour));
}
uint16_t GetIndustryTileCallback(CallbackID callback, uint32_t param1, uint32_t param2, IndustryGfx gfx_id, Industry *industry, TileIndex tile)
{
assert(industry != nullptr && IsValidTile(tile));
assert(industry->index == INVALID_INDUSTRY || IsTileType(tile, MP_INDUSTRY));
IndustryTileResolverObject object(gfx_id, tile, industry, callback, param1, param2);
return object.ResolveCallback();
}
bool DrawNewIndustryTile(TileInfo *ti, Industry *i, IndustryGfx gfx, const IndustryTileSpec *inds)
{
if (ti->tileh != SLOPE_FLAT) {
bool draw_old_one = true;
if (HasBit(inds->callback_mask, CBM_INDT_DRAW_FOUNDATIONS)) {
/* Called to determine the type (if any) of foundation to draw for industry tile */
uint32_t callback_res = GetIndustryTileCallback(CBID_INDTILE_DRAW_FOUNDATIONS, 0, 0, gfx, i, ti->tile);
if (callback_res != CALLBACK_FAILED) draw_old_one = ConvertBooleanCallback(inds->grf_prop.grffile, CBID_INDTILE_DRAW_FOUNDATIONS, callback_res);
}
if (draw_old_one) DrawFoundation(ti, FOUNDATION_LEVELED);
}
IndustryTileResolverObject object(gfx, ti->tile, i);
const SpriteGroup *group = object.Resolve();
if (group == nullptr || group->type != SGT_TILELAYOUT) return false;
/* Limit the building stage to the number of stages supplied. */
const TileLayoutSpriteGroup *tlgroup = (const TileLayoutSpriteGroup *)group;
byte stage = GetIndustryConstructionStage(ti->tile);
IndustryDrawTileLayout(ti, tlgroup, i->random_colour, stage);
return true;
}
extern bool IsSlopeRefused(Slope current, Slope refused);
/**
* Check the slope of a tile of a new industry.
* @param ind_base_tile Base tile of the industry.
* @param ind_tile Tile to check.
* @param its Tile specification.
* @param type Industry type.
* @param gfx Gfx of the tile.
* @param layout_index Layout.
* @param initial_random_bits Random bits of industry after construction
* @param founder Industry founder
* @param creation_type The circumstances the industry is created under.
* @return Succeeded or failed command.
*/
CommandCost PerformIndustryTileSlopeCheck(TileIndex ind_base_tile, TileIndex ind_tile, const IndustryTileSpec *its, IndustryType type, IndustryGfx gfx, size_t layout_index, uint16_t initial_random_bits, Owner founder, IndustryAvailabilityCallType creation_type)
{
Industry ind;
ind.index = INVALID_INDUSTRY;
ind.location.tile = ind_base_tile;
ind.location.w = 0;
ind.type = type;
ind.random = initial_random_bits;
ind.founder = founder;
uint16_t callback_res = GetIndustryTileCallback(CBID_INDTILE_SHAPE_CHECK, 0, creation_type << 8 | (uint32_t)layout_index, gfx, &ind, ind_tile);
if (callback_res == CALLBACK_FAILED) {
if (!IsSlopeRefused(GetTileSlope(ind_tile), its->slopes_refused)) return CommandCost();
return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
}
if (its->grf_prop.grffile->grf_version < 7) {
if (callback_res != 0) return CommandCost();
return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
}
return GetErrorMessageFromLocationCallbackResult(callback_res, its->grf_prop.grffile, STR_ERROR_SITE_UNSUITABLE);
}
/* Simple wrapper for GetHouseCallback to keep the animation unified. */
uint16_t GetSimpleIndustryCallback(CallbackID callback, uint32_t param1, uint32_t param2, const IndustryTileSpec *spec, Industry *ind, TileIndex tile, int)
{
return GetIndustryTileCallback(callback, param1, param2, spec - GetIndustryTileSpec(0), ind, tile);
}
/** Helper class for animation control. */
struct IndustryAnimationBase : public AnimationBase<IndustryAnimationBase, IndustryTileSpec, Industry, int, GetSimpleIndustryCallback, TileAnimationFrameAnimationHelper<Industry> > {
static const CallbackID cb_animation_speed = CBID_INDTILE_ANIMATION_SPEED;
static const CallbackID cb_animation_next_frame = CBID_INDTILE_ANIM_NEXT_FRAME;
static const IndustryTileCallbackMask cbm_animation_speed = CBM_INDT_ANIM_SPEED;
static const IndustryTileCallbackMask cbm_animation_next_frame = CBM_INDT_ANIM_NEXT_FRAME;
};
void AnimateNewIndustryTile(TileIndex tile)
{
const IndustryTileSpec *itspec = GetIndustryTileSpec(GetIndustryGfx(tile));
if (itspec == nullptr) return;
IndustryAnimationBase::AnimateTile(itspec, Industry::GetByTile(tile), tile, (itspec->special_flags & INDTILE_SPECIAL_NEXTFRAME_RANDOMBITS) != 0);
}
bool StartStopIndustryTileAnimation(TileIndex tile, IndustryAnimationTrigger iat, uint32_t random)
{
const IndustryTileSpec *itspec = GetIndustryTileSpec(GetIndustryGfx(tile));
if (!HasBit(itspec->animation.triggers, iat)) return false;
IndustryAnimationBase::ChangeAnimationFrame(CBID_INDTILE_ANIM_START_STOP, itspec, Industry::GetByTile(tile), tile, random, iat);
return true;
}
bool StartStopIndustryTileAnimation(const Industry *ind, IndustryAnimationTrigger iat)
{
bool ret = true;
uint32_t random = Random();
for (TileIndex tile : ind->location) {
if (ind->TileBelongsToIndustry(tile)) {
if (StartStopIndustryTileAnimation(tile, iat, random)) {
SB(random, 0, 16, Random());
} else {
ret = false;
}
}
}
return ret;
}
/**
* Trigger random triggers for an industry tile and reseed its random bits.
* @param tile Industry tile to trigger.
* @param trigger Trigger to trigger.
* @param ind Industry of the tile.
* @param[in,out] reseed_industry Collects bits to reseed for the industry.
*/
static void DoTriggerIndustryTile(TileIndex tile, IndustryTileTrigger trigger, Industry *ind, uint32_t &reseed_industry)
{
assert(IsValidTile(tile) && IsTileType(tile, MP_INDUSTRY));
IndustryGfx gfx = GetIndustryGfx(tile);
const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
if (itspec->grf_prop.spritegroup[0] == nullptr) return;
IndustryTileResolverObject object(gfx, tile, ind, CBID_RANDOM_TRIGGER);
object.waiting_triggers = GetIndustryTriggers(tile) | trigger;
SetIndustryTriggers(tile, object.waiting_triggers); // store now for var 5F
const SpriteGroup *group = object.Resolve();
if (group == nullptr) return;
/* Store remaining triggers. */
SetIndustryTriggers(tile, object.GetRemainingTriggers());
/* Rerandomise tile bits */
byte new_random_bits = Random();
byte random_bits = GetIndustryRandomBits(tile);
random_bits &= ~object.reseed[VSG_SCOPE_SELF];
random_bits |= new_random_bits & object.reseed[VSG_SCOPE_SELF];
SetIndustryRandomBits(tile, random_bits);
MarkTileDirtyByTile(tile);
reseed_industry |= object.reseed[VSG_SCOPE_PARENT];
}
/**
* Reseeds the random bits of an industry.
* @param ind Industry.
* @param reseed Bits to reseed.
*/
static void DoReseedIndustry(Industry *ind, uint32_t reseed)
{
if (reseed == 0 || ind == nullptr) return;
uint16_t random_bits = Random();
ind->random &= reseed;
ind->random |= random_bits & reseed;
}
/**
* Trigger a random trigger for a single industry tile.
* @param tile Industry tile to trigger.
* @param trigger Trigger to trigger.
*/
void TriggerIndustryTile(TileIndex tile, IndustryTileTrigger trigger)
{
uint32_t reseed_industry = 0;
Industry *ind = Industry::GetByTile(tile);
DoTriggerIndustryTile(tile, trigger, ind, reseed_industry);
DoReseedIndustry(ind, reseed_industry);
}
/**
* Trigger a random trigger for all industry tiles.
* @param ind Industry to trigger.
* @param trigger Trigger to trigger.
*/
void TriggerIndustry(Industry *ind, IndustryTileTrigger trigger)
{
uint32_t reseed_industry = 0;
for (TileIndex tile : ind->location) {
if (ind->TileBelongsToIndustry(tile)) {
DoTriggerIndustryTile(tile, trigger, ind, reseed_industry);
}
}
DoReseedIndustry(ind, reseed_industry);
}
|