mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-02-01 20:03:26 +00:00
(svn r16396) -Codechange: split NewGRF spritegroup into multiple subclasses instead of using a big union
This commit is contained in:
parent
b270ca84ba
commit
f490394aa8
171
src/newgrf.cpp
171
src/newgrf.cpp
@ -2588,42 +2588,6 @@ static void ReserveChangeInfo(byte *buf, size_t len)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a spritegroup representing a callback result
|
||||
* @param value The value that was used to represent this callback result
|
||||
* @return A spritegroup representing that callback result
|
||||
*/
|
||||
static const SpriteGroup *NewCallBackResultSpriteGroup(uint16 value)
|
||||
{
|
||||
SpriteGroup *group = new SpriteGroup(SGT_CALLBACK);
|
||||
|
||||
/* Old style callback results have the highest byte 0xFF so signify it is a callback result
|
||||
* New style ones only have the highest bit set (allows 15-bit results, instead of just 8) */
|
||||
if ((value >> 8) == 0xFF) {
|
||||
value &= ~0xFF00;
|
||||
} else {
|
||||
value &= ~0x8000;
|
||||
}
|
||||
|
||||
group->g.callback.result = value;
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a spritegroup representing a sprite number result.
|
||||
* @param sprite The sprite number.
|
||||
* @param num_sprites The number of sprites per set.
|
||||
* @return A spritegroup representing the sprite number result.
|
||||
*/
|
||||
static const SpriteGroup *NewResultSpriteGroup(SpriteID sprite, byte num_sprites)
|
||||
{
|
||||
SpriteGroup *group = new SpriteGroup(SGT_RESULT);
|
||||
group->g.result.sprite = sprite;
|
||||
group->g.result.num_sprites = num_sprites;
|
||||
return group;
|
||||
}
|
||||
|
||||
/* Action 0x01 */
|
||||
static void NewSpriteSet(byte *buf, size_t len)
|
||||
{
|
||||
@ -2678,7 +2642,7 @@ static void SkipAct1(byte *buf, size_t len)
|
||||
* defined spritegroup. */
|
||||
static const SpriteGroup *GetGroupFromGroupID(byte setid, byte type, uint16 groupid)
|
||||
{
|
||||
if (HasBit(groupid, 15)) return NewCallBackResultSpriteGroup(groupid);
|
||||
if (HasBit(groupid, 15)) return new CallbackResultSpriteGroup(groupid);
|
||||
|
||||
if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) {
|
||||
grfmsg(1, "GetGroupFromGroupID(0x%02X:0x%02X): Groupid 0x%04X does not exist, leaving empty", setid, type, groupid);
|
||||
@ -2691,7 +2655,7 @@ static const SpriteGroup *GetGroupFromGroupID(byte setid, byte type, uint16 grou
|
||||
/* Helper function to either create a callback or a result sprite group. */
|
||||
static const SpriteGroup *CreateGroupFromGroupID(byte feature, byte setid, byte type, uint16 spriteid, uint16 num_sprites)
|
||||
{
|
||||
if (HasBit(spriteid, 15)) return NewCallBackResultSpriteGroup(spriteid);
|
||||
if (HasBit(spriteid, 15)) return new CallbackResultSpriteGroup(spriteid);
|
||||
|
||||
if (spriteid >= _cur_grffile->spriteset_numsets) {
|
||||
grfmsg(1, "CreateGroupFromGroupID(0x%02X:0x%02X): Sprite set %u invalid, max %u", setid, type, spriteid, _cur_grffile->spriteset_numsets);
|
||||
@ -2716,7 +2680,7 @@ static const SpriteGroup *CreateGroupFromGroupID(byte feature, byte setid, byte
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NewResultSpriteGroup(_cur_grffile->spriteset_start + spriteid * num_sprites, num_sprites);
|
||||
return new ResultSpriteGroup(_cur_grffile->spriteset_start + spriteid * num_sprites, num_sprites);
|
||||
}
|
||||
|
||||
/* Action 0x02 */
|
||||
@ -2732,7 +2696,7 @@ static void NewSpriteGroup(byte *buf, size_t len)
|
||||
* otherwise it specifies a number of entries, the exact
|
||||
* meaning depends on the feature
|
||||
* V feature-specific-data (huge mess, don't even look it up --pasky) */
|
||||
SpriteGroup *group = NULL;
|
||||
SpriteGroup *act_group = NULL;
|
||||
byte *bufend = buf + len;
|
||||
|
||||
if (!check_length(len, 5, "NewSpriteGroup")) return;
|
||||
@ -2765,14 +2729,15 @@ static void NewSpriteGroup(byte *buf, size_t len)
|
||||
/* Check we can load the var size parameter */
|
||||
if (!check_length(bufend - buf, 1, "NewSpriteGroup (Deterministic) (1)")) return;
|
||||
|
||||
group = new SpriteGroup(SGT_DETERMINISTIC);
|
||||
group->g.determ.var_scope = HasBit(type, 1) ? VSG_SCOPE_PARENT : VSG_SCOPE_SELF;
|
||||
DeterministicSpriteGroup *group = new DeterministicSpriteGroup();
|
||||
act_group = group;
|
||||
group->var_scope = HasBit(type, 1) ? VSG_SCOPE_PARENT : VSG_SCOPE_SELF;
|
||||
|
||||
switch (GB(type, 2, 2)) {
|
||||
default: NOT_REACHED();
|
||||
case 0: group->g.determ.size = DSG_SIZE_BYTE; varsize = 1; break;
|
||||
case 1: group->g.determ.size = DSG_SIZE_WORD; varsize = 2; break;
|
||||
case 2: group->g.determ.size = DSG_SIZE_DWORD; varsize = 4; break;
|
||||
case 0: group->size = DSG_SIZE_BYTE; varsize = 1; break;
|
||||
case 1: group->size = DSG_SIZE_WORD; varsize = 2; break;
|
||||
case 2: group->size = DSG_SIZE_DWORD; varsize = 4; break;
|
||||
}
|
||||
|
||||
if (!check_length(bufend - buf, 5 + varsize, "NewSpriteGroup (Deterministic) (2)")) return;
|
||||
@ -2782,17 +2747,17 @@ static void NewSpriteGroup(byte *buf, size_t len)
|
||||
do {
|
||||
DeterministicSpriteGroupAdjust *adjust;
|
||||
|
||||
if (group->g.determ.num_adjusts > 0) {
|
||||
if (group->num_adjusts > 0) {
|
||||
if (!check_length(bufend - buf, 2 + varsize + 3, "NewSpriteGroup (Deterministic) (3)")) return;
|
||||
}
|
||||
|
||||
group->g.determ.num_adjusts++;
|
||||
group->g.determ.adjusts = ReallocT(group->g.determ.adjusts, group->g.determ.num_adjusts);
|
||||
group->num_adjusts++;
|
||||
group->adjusts = ReallocT(group->adjusts, group->num_adjusts);
|
||||
|
||||
adjust = &group->g.determ.adjusts[group->g.determ.num_adjusts - 1];
|
||||
adjust = &group->adjusts[group->num_adjusts - 1];
|
||||
|
||||
/* The first var adjust doesn't have an operation specified, so we set it to add. */
|
||||
adjust->operation = group->g.determ.num_adjusts == 1 ? DSGA_OP_ADD : (DeterministicSpriteGroupAdjustOperation)grf_load_byte(&buf);
|
||||
adjust->operation = group->num_adjusts == 1 ? DSGA_OP_ADD : (DeterministicSpriteGroupAdjustOperation)grf_load_byte(&buf);
|
||||
adjust->variable = grf_load_byte(&buf);
|
||||
if (adjust->variable == 0x7E) {
|
||||
/* Link subroutine group */
|
||||
@ -2817,18 +2782,18 @@ static void NewSpriteGroup(byte *buf, size_t len)
|
||||
/* Continue reading var adjusts while bit 5 is set. */
|
||||
} while (HasBit(varadjust, 5));
|
||||
|
||||
group->g.determ.num_ranges = grf_load_byte(&buf);
|
||||
if (group->g.determ.num_ranges > 0) group->g.determ.ranges = CallocT<DeterministicSpriteGroupRange>(group->g.determ.num_ranges);
|
||||
group->num_ranges = grf_load_byte(&buf);
|
||||
if (group->num_ranges > 0) group->ranges = CallocT<DeterministicSpriteGroupRange>(group->num_ranges);
|
||||
|
||||
if (!check_length(bufend - buf, 2 + (2 + 2 * varsize) * group->g.determ.num_ranges, "NewSpriteGroup (Deterministic)")) return;
|
||||
if (!check_length(bufend - buf, 2 + (2 + 2 * varsize) * group->num_ranges, "NewSpriteGroup (Deterministic)")) return;
|
||||
|
||||
for (uint i = 0; i < group->g.determ.num_ranges; i++) {
|
||||
group->g.determ.ranges[i].group = GetGroupFromGroupID(setid, type, grf_load_word(&buf));
|
||||
group->g.determ.ranges[i].low = grf_load_var(varsize, &buf);
|
||||
group->g.determ.ranges[i].high = grf_load_var(varsize, &buf);
|
||||
for (uint i = 0; i < group->num_ranges; i++) {
|
||||
group->ranges[i].group = GetGroupFromGroupID(setid, type, grf_load_word(&buf));
|
||||
group->ranges[i].low = grf_load_var(varsize, &buf);
|
||||
group->ranges[i].high = grf_load_var(varsize, &buf);
|
||||
}
|
||||
|
||||
group->g.determ.default_group = GetGroupFromGroupID(setid, type, grf_load_word(&buf));
|
||||
group->default_group = GetGroupFromGroupID(setid, type, grf_load_word(&buf));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2839,25 +2804,26 @@ static void NewSpriteGroup(byte *buf, size_t len)
|
||||
{
|
||||
if (!check_length(bufend - buf, HasBit(type, 2) ? 8 : 7, "NewSpriteGroup (Randomized) (1)")) return;
|
||||
|
||||
group = new SpriteGroup(SGT_RANDOMIZED);
|
||||
group->g.random.var_scope = HasBit(type, 1) ? VSG_SCOPE_PARENT : VSG_SCOPE_SELF;
|
||||
RandomizedSpriteGroup *group = new RandomizedSpriteGroup();
|
||||
act_group = group;
|
||||
group->var_scope = HasBit(type, 1) ? VSG_SCOPE_PARENT : VSG_SCOPE_SELF;
|
||||
|
||||
if (HasBit(type, 2)) {
|
||||
if (feature <= GSF_AIRCRAFT) group->g.random.var_scope = VSG_SCOPE_RELATIVE;
|
||||
group->g.random.count = grf_load_byte(&buf);
|
||||
if (feature <= GSF_AIRCRAFT) group->var_scope = VSG_SCOPE_RELATIVE;
|
||||
group->count = grf_load_byte(&buf);
|
||||
}
|
||||
|
||||
uint8 triggers = grf_load_byte(&buf);
|
||||
group->g.random.triggers = GB(triggers, 0, 7);
|
||||
group->g.random.cmp_mode = HasBit(triggers, 7) ? RSG_CMP_ALL : RSG_CMP_ANY;
|
||||
group->g.random.lowest_randbit = grf_load_byte(&buf);
|
||||
group->g.random.num_groups = grf_load_byte(&buf);
|
||||
group->g.random.groups = CallocT<const SpriteGroup*>(group->g.random.num_groups);
|
||||
group->triggers = GB(triggers, 0, 7);
|
||||
group->cmp_mode = HasBit(triggers, 7) ? RSG_CMP_ALL : RSG_CMP_ANY;
|
||||
group->lowest_randbit = grf_load_byte(&buf);
|
||||
group->num_groups = grf_load_byte(&buf);
|
||||
group->groups = CallocT<const SpriteGroup*>(group->num_groups);
|
||||
|
||||
if (!check_length(bufend - buf, 2 * group->g.random.num_groups, "NewSpriteGroup (Randomized) (2)")) return;
|
||||
if (!check_length(bufend - buf, 2 * group->num_groups, "NewSpriteGroup (Randomized) (2)")) return;
|
||||
|
||||
for (uint i = 0; i < group->g.random.num_groups; i++) {
|
||||
group->g.random.groups[i] = GetGroupFromGroupID(setid, type, grf_load_word(&buf));
|
||||
for (uint i = 0; i < group->num_groups; i++) {
|
||||
group->groups[i] = GetGroupFromGroupID(setid, type, grf_load_word(&buf));
|
||||
}
|
||||
|
||||
break;
|
||||
@ -2866,8 +2832,6 @@ static void NewSpriteGroup(byte *buf, size_t len)
|
||||
/* Neither a variable or randomized sprite group... must be a real group */
|
||||
default:
|
||||
{
|
||||
|
||||
|
||||
switch (feature) {
|
||||
case GSF_TRAIN:
|
||||
case GSF_ROAD:
|
||||
@ -2888,25 +2852,26 @@ static void NewSpriteGroup(byte *buf, size_t len)
|
||||
|
||||
if (!check_length(bufend - buf, 2 * num_loaded + 2 * num_loading, "NewSpriteGroup (Real) (1)")) return;
|
||||
|
||||
group = new SpriteGroup(SGT_REAL);
|
||||
RealSpriteGroup *group = new RealSpriteGroup();
|
||||
act_group = group;
|
||||
|
||||
group->g.real.num_loaded = num_loaded;
|
||||
group->g.real.num_loading = num_loading;
|
||||
if (num_loaded > 0) group->g.real.loaded = CallocT<const SpriteGroup*>(num_loaded);
|
||||
if (num_loading > 0) group->g.real.loading = CallocT<const SpriteGroup*>(num_loading);
|
||||
group->num_loaded = num_loaded;
|
||||
group->num_loading = num_loading;
|
||||
if (num_loaded > 0) group->loaded = CallocT<const SpriteGroup*>(num_loaded);
|
||||
if (num_loading > 0) group->loading = CallocT<const SpriteGroup*>(num_loading);
|
||||
|
||||
grfmsg(6, "NewSpriteGroup: New SpriteGroup 0x%02X, %u views, %u loaded, %u loading",
|
||||
setid, sprites, num_loaded, num_loading);
|
||||
|
||||
for (uint i = 0; i < num_loaded; i++) {
|
||||
uint16 spriteid = grf_load_word(&buf);
|
||||
group->g.real.loaded[i] = CreateGroupFromGroupID(feature, setid, type, spriteid, sprites);
|
||||
group->loaded[i] = CreateGroupFromGroupID(feature, setid, type, spriteid, sprites);
|
||||
grfmsg(8, "NewSpriteGroup: + rg->loaded[%i] = subset %u", i, spriteid);
|
||||
}
|
||||
|
||||
for (uint i = 0; i < num_loading; i++) {
|
||||
uint16 spriteid = grf_load_word(&buf);
|
||||
group->g.real.loading[i] = CreateGroupFromGroupID(feature, setid, type, spriteid, sprites);
|
||||
group->loading[i] = CreateGroupFromGroupID(feature, setid, type, spriteid, sprites);
|
||||
grfmsg(8, "NewSpriteGroup: + rg->loading[%i] = subset %u", i, spriteid);
|
||||
}
|
||||
|
||||
@ -2919,32 +2884,33 @@ static void NewSpriteGroup(byte *buf, size_t len)
|
||||
byte num_sprites = max((uint8)1, type);
|
||||
uint i;
|
||||
|
||||
group = new SpriteGroup(SGT_TILELAYOUT);
|
||||
group->g.layout.num_sprites = sprites;
|
||||
group->g.layout.dts = CallocT<DrawTileSprites>(1);
|
||||
TileLayoutSpriteGroup *group = new TileLayoutSpriteGroup();
|
||||
act_group = group;
|
||||
group->num_sprites = sprites;
|
||||
group->dts = CallocT<DrawTileSprites>(1);
|
||||
|
||||
/* Groundsprite */
|
||||
group->g.layout.dts->ground.sprite = grf_load_word(&buf);
|
||||
group->g.layout.dts->ground.pal = grf_load_word(&buf);
|
||||
group->dts->ground.sprite = grf_load_word(&buf);
|
||||
group->dts->ground.pal = grf_load_word(&buf);
|
||||
|
||||
/* Remap transparent/colour modifier bits */
|
||||
MapSpriteMappingRecolour(&group->g.layout.dts->ground);
|
||||
MapSpriteMappingRecolour(&group->dts->ground);
|
||||
|
||||
if (HasBit(group->g.layout.dts->ground.pal, 15)) {
|
||||
if (HasBit(group->dts->ground.pal, 15)) {
|
||||
/* Bit 31 set means this is a custom sprite, so rewrite it to the
|
||||
* last spriteset defined. */
|
||||
SpriteID sprite = _cur_grffile->spriteset_start + GB(group->g.layout.dts->ground.sprite, 0, 14) * sprites;
|
||||
SB(group->g.layout.dts->ground.sprite, 0, SPRITE_WIDTH, sprite);
|
||||
ClrBit(group->g.layout.dts->ground.pal, 15);
|
||||
SpriteID sprite = _cur_grffile->spriteset_start + GB(group->dts->ground.sprite, 0, 14) * sprites;
|
||||
SB(group->dts->ground.sprite, 0, SPRITE_WIDTH, sprite);
|
||||
ClrBit(group->dts->ground.pal, 15);
|
||||
}
|
||||
|
||||
group->g.layout.dts->seq = CallocT<DrawTileSeqStruct>(num_sprites + 1);
|
||||
group->dts->seq = CallocT<DrawTileSeqStruct>(num_sprites + 1);
|
||||
|
||||
for (i = 0; i < num_sprites; i++) {
|
||||
DrawTileSeqStruct *seq = (DrawTileSeqStruct*)&group->g.layout.dts->seq[i];
|
||||
DrawTileSeqStruct *seq = (DrawTileSeqStruct*)&group->dts->seq[i];
|
||||
|
||||
seq->image.sprite = grf_load_word(&buf);
|
||||
seq->image.pal = grf_load_word(&buf);
|
||||
seq->image.pal = grf_load_word(&buf);
|
||||
seq->delta_x = grf_load_byte(&buf);
|
||||
seq->delta_y = grf_load_byte(&buf);
|
||||
|
||||
@ -2969,7 +2935,7 @@ static void NewSpriteGroup(byte *buf, size_t len)
|
||||
}
|
||||
|
||||
/* Set the terminator value. */
|
||||
((DrawTileSeqStruct*)group->g.layout.dts->seq)[i].delta_x = (int8)0x80;
|
||||
((DrawTileSeqStruct*)group->dts->seq)[i].delta_x = (int8)0x80;
|
||||
|
||||
break;
|
||||
}
|
||||
@ -2980,24 +2946,25 @@ static void NewSpriteGroup(byte *buf, size_t len)
|
||||
break;
|
||||
}
|
||||
|
||||
group = new SpriteGroup(SGT_INDUSTRY_PRODUCTION);
|
||||
group->g.indprod.version = type;
|
||||
IndustryProductionSpriteGroup *group = new IndustryProductionSpriteGroup();
|
||||
act_group = group;
|
||||
group->version = type;
|
||||
if (type == 0) {
|
||||
for (uint i = 0; i < 3; i++) {
|
||||
group->g.indprod.substract_input[i] = grf_load_word(&buf);
|
||||
group->substract_input[i] = grf_load_word(&buf);
|
||||
}
|
||||
for (uint i = 0; i < 2; i++) {
|
||||
group->g.indprod.add_output[i] = grf_load_word(&buf);
|
||||
group->add_output[i] = grf_load_word(&buf);
|
||||
}
|
||||
group->g.indprod.again = grf_load_byte(&buf);
|
||||
group->again = grf_load_byte(&buf);
|
||||
} else {
|
||||
for (uint i = 0; i < 3; i++) {
|
||||
group->g.indprod.substract_input[i] = grf_load_byte(&buf);
|
||||
group->substract_input[i] = grf_load_byte(&buf);
|
||||
}
|
||||
for (uint i = 0; i < 2; i++) {
|
||||
group->g.indprod.add_output[i] = grf_load_byte(&buf);
|
||||
group->add_output[i] = grf_load_byte(&buf);
|
||||
}
|
||||
group->g.indprod.again = grf_load_byte(&buf);
|
||||
group->again = grf_load_byte(&buf);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -3008,7 +2975,7 @@ static void NewSpriteGroup(byte *buf, size_t len)
|
||||
}
|
||||
}
|
||||
|
||||
_cur_grffile->spritegroups[setid] = group;
|
||||
_cur_grffile->spritegroups[setid] = act_group;
|
||||
}
|
||||
|
||||
static CargoID TranslateCargo(uint8 feature, uint8 ctype)
|
||||
|
@ -60,11 +60,11 @@ static uint32 CanalGetVariable(const ResolverObject *object, byte variable, byte
|
||||
}
|
||||
|
||||
|
||||
static const SpriteGroup *CanalResolveReal(const ResolverObject *object, const SpriteGroup *group)
|
||||
static const SpriteGroup *CanalResolveReal(const ResolverObject *object, const RealSpriteGroup *group)
|
||||
{
|
||||
if (group->g.real.num_loaded == 0) return NULL;
|
||||
if (group->num_loaded == 0) return NULL;
|
||||
|
||||
return group->g.real.loaded[0];
|
||||
return group->loaded[0];
|
||||
}
|
||||
|
||||
|
||||
@ -97,7 +97,7 @@ SpriteID GetCanalSprite(CanalFeature feature, TileIndex tile)
|
||||
NewCanalResolver(&object, tile, _water_feature[feature].grffile);
|
||||
|
||||
group = Resolve(_water_feature[feature].group, &object);
|
||||
if (group == NULL || group->type != SGT_RESULT) return 0;
|
||||
if (group == NULL) return 0;
|
||||
|
||||
return group->g.result.sprite;
|
||||
return group->GetResult();
|
||||
}
|
||||
|
@ -35,12 +35,12 @@ static uint32 CargoGetVariable(const ResolverObject *object, byte variable, byte
|
||||
}
|
||||
|
||||
|
||||
static const SpriteGroup *CargoResolveReal(const ResolverObject *object, const SpriteGroup *group)
|
||||
static const SpriteGroup *CargoResolveReal(const ResolverObject *object, const RealSpriteGroup *group)
|
||||
{
|
||||
/* Cargo action 2s should always have only 1 "loaded" state, but some
|
||||
* times things don't follow the spec... */
|
||||
if (group->g.real.num_loaded > 0) return group->g.real.loaded[0];
|
||||
if (group->g.real.num_loading > 0) return group->g.real.loading[0];
|
||||
if (group->num_loaded > 0) return group->loaded[0];
|
||||
if (group->num_loading > 0) return group->loading[0];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -75,9 +75,9 @@ SpriteID GetCustomCargoSprite(const CargoSpec *cs)
|
||||
NewCargoResolver(&object, cs);
|
||||
|
||||
group = Resolve(cs->group, &object);
|
||||
if (group == NULL || group->type != SGT_RESULT) return 0;
|
||||
if (group == NULL) return 0;
|
||||
|
||||
return group->g.result.sprite;
|
||||
return group->GetResult();
|
||||
}
|
||||
|
||||
|
||||
@ -92,9 +92,9 @@ uint16 GetCargoCallback(CallbackID callback, uint32 param1, uint32 param2, const
|
||||
object.callback_param2 = param2;
|
||||
|
||||
group = Resolve(cs->group, &object);
|
||||
if (group == NULL || group->type != SGT_CALLBACK) return CALLBACK_FAILED;
|
||||
if (group == NULL) return CALLBACK_FAILED;
|
||||
|
||||
return group->g.callback.result;
|
||||
return group->GetCallbackResult();
|
||||
}
|
||||
|
||||
|
||||
|
@ -815,24 +815,24 @@ static uint32 VehicleGetVariable(const ResolverObject *object, byte variable, by
|
||||
}
|
||||
|
||||
|
||||
static const SpriteGroup *VehicleResolveReal(const ResolverObject *object, const SpriteGroup *group)
|
||||
static const SpriteGroup *VehicleResolveReal(const ResolverObject *object, const RealSpriteGroup *group)
|
||||
{
|
||||
const Vehicle *v = object->u.vehicle.self;
|
||||
|
||||
if (v == NULL) {
|
||||
if (group->g.real.num_loading > 0) return group->g.real.loading[0];
|
||||
if (group->g.real.num_loaded > 0) return group->g.real.loaded[0];
|
||||
if (group->num_loading > 0) return group->loading[0];
|
||||
if (group->num_loaded > 0) return group->loaded[0];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool in_motion = !v->First()->current_order.IsType(OT_LOADING);
|
||||
|
||||
uint totalsets = in_motion ? group->g.real.num_loaded : group->g.real.num_loading;
|
||||
uint totalsets = in_motion ? group->num_loaded : group->num_loading;
|
||||
|
||||
uint set = (v->cargo.Count() * totalsets) / max((uint16)1, v->cargo_cap);
|
||||
set = min(set, totalsets - 1);
|
||||
|
||||
return in_motion ? group->g.real.loaded[set] : group->g.real.loading[set];
|
||||
return in_motion ? group->loaded[set] : group->loading[set];
|
||||
}
|
||||
|
||||
|
||||
@ -913,9 +913,9 @@ SpriteID GetCustomEngineSprite(EngineID engine, const Vehicle *v, Direction dire
|
||||
NewVehicleResolver(&object, engine, v);
|
||||
|
||||
group = Resolve(GetVehicleSpriteGroup(engine, v), &object);
|
||||
if (group == NULL || group->type != SGT_RESULT || group->g.result.num_sprites == 0) return 0;
|
||||
if (group == NULL || group->GetNumResults() == 0) return 0;
|
||||
|
||||
return group->g.result.sprite + (direction % group->g.result.num_sprites);
|
||||
return group->GetResult() + (direction % group->GetNumResults());
|
||||
}
|
||||
|
||||
|
||||
@ -936,11 +936,11 @@ SpriteID GetRotorOverrideSprite(EngineID engine, const Aircraft *v, bool info_vi
|
||||
const SpriteGroup *group = GetWagonOverrideSpriteSet(engine, CT_DEFAULT, engine);
|
||||
group = Resolve(group, &object);
|
||||
|
||||
if (group == NULL || group->type != SGT_RESULT || group->g.result.num_sprites == 0) return 0;
|
||||
if (group == NULL || group->GetNumResults() == 0) return 0;
|
||||
|
||||
if (v == NULL) return group->g.result.sprite;
|
||||
if (v == NULL) return group->GetResult();
|
||||
|
||||
return group->g.result.sprite + (info_view ? 0 : (v->Next()->Next()->state % group->g.result.num_sprites));
|
||||
return group->GetResult() + (info_view ? 0 : (v->Next()->Next()->state % group->GetNumResults()));
|
||||
}
|
||||
|
||||
|
||||
@ -976,9 +976,9 @@ uint16 GetVehicleCallback(CallbackID callback, uint32 param1, uint32 param2, Eng
|
||||
object.callback_param2 = param2;
|
||||
|
||||
group = Resolve(GetVehicleSpriteGroup(engine, v, false), &object);
|
||||
if (group == NULL || group->type != SGT_CALLBACK) return CALLBACK_FAILED;
|
||||
if (group == NULL) return CALLBACK_FAILED;
|
||||
|
||||
return group->g.callback.result;
|
||||
return group->GetCallbackResult();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1005,9 +1005,9 @@ uint16 GetVehicleCallbackParent(CallbackID callback, uint32 param1, uint32 param
|
||||
object.u.vehicle.parent = parent;
|
||||
|
||||
group = Resolve(GetVehicleSpriteGroup(engine, v, false), &object);
|
||||
if (group == NULL || group->type != SGT_CALLBACK) return CALLBACK_FAILED;
|
||||
if (group == NULL) return CALLBACK_FAILED;
|
||||
|
||||
return group->g.callback.result;
|
||||
return group->GetCallbackResult();
|
||||
}
|
||||
|
||||
|
||||
|
@ -98,11 +98,11 @@ static uint32 GenericCallbackGetVariable(const ResolverObject *object, byte vari
|
||||
}
|
||||
|
||||
|
||||
static const SpriteGroup *GenericCallbackResolveReal(const ResolverObject *object, const SpriteGroup *group)
|
||||
static const SpriteGroup *GenericCallbackResolveReal(const ResolverObject *object, const RealSpriteGroup *group)
|
||||
{
|
||||
if (group->g.real.num_loaded == 0) return NULL;
|
||||
if (group->num_loaded == 0) return NULL;
|
||||
|
||||
return group->g.real.loaded[0];
|
||||
return group->loaded[0];
|
||||
}
|
||||
|
||||
|
||||
@ -140,12 +140,12 @@ static uint16 GetGenericCallbackResult(uint8 feature, ResolverObject *object, co
|
||||
for (GenericCallbackList::const_iterator it = _gcl[feature].begin(); it != _gcl[feature].end(); ++it) {
|
||||
const SpriteGroup *group = it->group;
|
||||
group = Resolve(group, object);
|
||||
if (group == NULL || group->type != SGT_CALLBACK) continue;
|
||||
if (group == NULL) continue;
|
||||
|
||||
/* Return NewGRF file if necessary */
|
||||
if (file != NULL) *file = it->file;
|
||||
|
||||
return group->g.callback.result;
|
||||
return group->GetCallbackResult();
|
||||
}
|
||||
|
||||
/* No callback returned a valid result, so we've failed. */
|
||||
|
@ -309,7 +309,7 @@ static uint32 HouseGetVariable(const ResolverObject *object, byte variable, byte
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
static const SpriteGroup *HouseResolveReal(const ResolverObject *object, const SpriteGroup *group)
|
||||
static const SpriteGroup *HouseResolveReal(const ResolverObject *object, const RealSpriteGroup *group)
|
||||
{
|
||||
/* Houses do not have 'real' groups */
|
||||
return NULL;
|
||||
@ -355,14 +355,14 @@ uint16 GetHouseCallback(CallbackID callback, uint32 param1, uint32 param2, House
|
||||
object.callback_param2 = param2;
|
||||
|
||||
group = Resolve(GetHouseSpecs(house_id)->spritegroup, &object);
|
||||
if (group == NULL || group->type != SGT_CALLBACK) return CALLBACK_FAILED;
|
||||
if (group == NULL) return CALLBACK_FAILED;
|
||||
|
||||
return group->g.callback.result;
|
||||
return group->GetCallbackResult();
|
||||
}
|
||||
|
||||
static void DrawTileLayout(const TileInfo *ti, const SpriteGroup *group, byte stage, HouseID house_id)
|
||||
static void DrawTileLayout(const TileInfo *ti, const TileLayoutSpriteGroup *group, byte stage, HouseID house_id)
|
||||
{
|
||||
const DrawTileSprites *dts = group->g.layout.dts;
|
||||
const DrawTileSprites *dts = group->dts;
|
||||
const DrawTileSeqStruct *dtss;
|
||||
|
||||
const HouseSpec *hs = GetHouseSpecs(house_id);
|
||||
@ -427,10 +427,11 @@ void DrawNewHouseTile(TileInfo *ti, HouseID house_id)
|
||||
/* XXX: This is for debugging purposes really, and shouldn't stay. */
|
||||
DrawGroundSprite(SPR_SHADOW_CELL, PAL_NONE);
|
||||
} else {
|
||||
const TileLayoutSpriteGroup *tlgroup = (const TileLayoutSpriteGroup *)group;
|
||||
/* Limit the building stage to the number of stages supplied. */
|
||||
byte stage = GetHouseBuildingStage(ti->tile);
|
||||
stage = Clamp(stage - 4 + group->g.layout.num_sprites, 0, group->g.layout.num_sprites - 1);
|
||||
DrawTileLayout(ti, group, stage, house_id);
|
||||
stage = Clamp(stage - 4 + tlgroup->num_sprites, 0, tlgroup->num_sprites - 1);
|
||||
DrawTileLayout(ti, tlgroup, stage, house_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -329,7 +329,7 @@ uint32 IndustryGetVariable(const ResolverObject *object, byte variable, byte par
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
static const SpriteGroup *IndustryResolveReal(const ResolverObject *object, const SpriteGroup *group)
|
||||
static const SpriteGroup *IndustryResolveReal(const ResolverObject *object, const RealSpriteGroup *group)
|
||||
{
|
||||
/* IndustryTile do not have 'real' groups */
|
||||
return NULL;
|
||||
@ -388,9 +388,9 @@ uint16 GetIndustryCallback(CallbackID callback, uint32 param1, uint32 param2, In
|
||||
object.callback_param2 = param2;
|
||||
|
||||
group = Resolve(GetIndustrySpec(type)->grf_prop.spritegroup, &object);
|
||||
if (group == NULL || group->type != SGT_CALLBACK) return CALLBACK_FAILED;
|
||||
if (group == NULL) return CALLBACK_FAILED;
|
||||
|
||||
return group->g.callback.result;
|
||||
return group->GetCallbackResult();
|
||||
}
|
||||
|
||||
uint32 IndustryLocationGetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available)
|
||||
@ -465,18 +465,20 @@ bool CheckIfCallBackAllowsCreation(TileIndex tile, IndustryType type, uint itspe
|
||||
|
||||
/* Unlike the "normal" cases, not having a valid result means we allow
|
||||
* the building of the industry, as that's how it's done in TTDP. */
|
||||
if (group == NULL || group->type != SGT_CALLBACK || group->g.callback.result == 0x400) return true;
|
||||
if (group == NULL) return true;
|
||||
uint16 result = group->GetCallbackResult();
|
||||
if (result == 0x400 || result == CALLBACK_FAILED) return true;
|
||||
|
||||
/* Copy some parameters from the registers to the error message text ref. stack */
|
||||
SwitchToErrorRefStack();
|
||||
PrepareTextRefStackUsage(4);
|
||||
SwitchToNormalRefStack();
|
||||
|
||||
switch (group->g.callback.result) {
|
||||
switch (result) {
|
||||
case 0x401: _error_message = STR_ERROR_SITE_UNSUITABLE; break;
|
||||
case 0x402: _error_message = STR_ERROR_CAN_ONLY_BE_BUILT_IN_RAINFOREST; break;
|
||||
case 0x403: _error_message = STR_ERROR_CAN_ONLY_BE_BUILT_IN_DESERT; break;
|
||||
default: _error_message = GetGRFStringID(indspec->grf_prop.grffile->grfid, 0xD000 + group->g.callback.result); break;
|
||||
default: _error_message = GetGRFStringID(indspec->grf_prop.grffile->grfid, 0xD000 + result); break;
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -529,19 +531,20 @@ void IndustryProductionCallback(Industry *ind, int reason)
|
||||
}
|
||||
|
||||
SB(object.callback_param2, 8, 16, loop);
|
||||
const SpriteGroup *group = Resolve(spec->grf_prop.spritegroup, &object);
|
||||
if (group == NULL || group->type != SGT_INDUSTRY_PRODUCTION) break;
|
||||
const SpriteGroup *tgroup = Resolve(spec->grf_prop.spritegroup, &object);
|
||||
if (tgroup == NULL || tgroup->type != SGT_INDUSTRY_PRODUCTION) break;
|
||||
const IndustryProductionSpriteGroup *group = (const IndustryProductionSpriteGroup *)tgroup;
|
||||
|
||||
bool deref = (group->g.indprod.version == 1);
|
||||
bool deref = (group->version == 1);
|
||||
|
||||
for (uint i = 0; i < 3; i++) {
|
||||
ind->incoming_cargo_waiting[i] = Clamp(ind->incoming_cargo_waiting[i] - DerefIndProd(group->g.indprod.substract_input[i], deref) * multiplier, 0, 0xFFFF);
|
||||
ind->incoming_cargo_waiting[i] = Clamp(ind->incoming_cargo_waiting[i] - DerefIndProd(group->substract_input[i], deref) * multiplier, 0, 0xFFFF);
|
||||
}
|
||||
for (uint i = 0; i < 2; i++) {
|
||||
ind->produced_cargo_waiting[i] = Clamp(ind->produced_cargo_waiting[i] + max(DerefIndProd(group->g.indprod.add_output[i], deref), 0) * multiplier, 0, 0xFFFF);
|
||||
ind->produced_cargo_waiting[i] = Clamp(ind->produced_cargo_waiting[i] + max(DerefIndProd(group->add_output[i], deref), 0) * multiplier, 0, 0xFFFF);
|
||||
}
|
||||
|
||||
int32 again = DerefIndProd(group->g.indprod.again, deref);
|
||||
int32 again = DerefIndProd(group->again, deref);
|
||||
if (again == 0) break;
|
||||
|
||||
SB(object.callback_param2, 24, 8, again);
|
||||
|
@ -105,7 +105,7 @@ static uint32 IndustryTileGetVariable(const ResolverObject *object, byte variabl
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
static const SpriteGroup *IndustryTileResolveReal(const ResolverObject *object, const SpriteGroup *group)
|
||||
static const SpriteGroup *IndustryTileResolveReal(const ResolverObject *object, const RealSpriteGroup *group)
|
||||
{
|
||||
/* IndustryTile do not have 'real' groups. Or do they?? */
|
||||
return NULL;
|
||||
@ -163,9 +163,9 @@ static void NewIndustryTileResolver(ResolverObject *res, IndustryGfx gfx, TileIn
|
||||
res->grffile = (its != NULL ? its->grf_prop.grffile : NULL);
|
||||
}
|
||||
|
||||
static void IndustryDrawTileLayout(const TileInfo *ti, const SpriteGroup *group, byte rnd_colour, byte stage, IndustryGfx gfx)
|
||||
static void IndustryDrawTileLayout(const TileInfo *ti, const TileLayoutSpriteGroup *group, byte rnd_colour, byte stage, IndustryGfx gfx)
|
||||
{
|
||||
const DrawTileSprites *dts = group->g.layout.dts;
|
||||
const DrawTileSprites *dts = group->dts;
|
||||
const DrawTileSeqStruct *dtss;
|
||||
|
||||
SpriteID image = dts->ground.sprite;
|
||||
@ -224,7 +224,7 @@ uint16 GetIndustryTileCallback(CallbackID callback, uint32 param1, uint32 param2
|
||||
group = Resolve(GetIndustryTileSpec(gfx_id)->grf_prop.spritegroup, &object);
|
||||
if (group == NULL || group->type != SGT_CALLBACK) return CALLBACK_FAILED;
|
||||
|
||||
return group->g.callback.result;
|
||||
return group->GetCallbackResult();
|
||||
}
|
||||
|
||||
bool DrawNewIndustryTile(TileInfo *ti, Industry *i, IndustryGfx gfx, const IndustryTileSpec *inds)
|
||||
@ -249,10 +249,11 @@ bool DrawNewIndustryTile(TileInfo *ti, Industry *i, IndustryGfx gfx, const Indus
|
||||
if (group == NULL || group->type != SGT_TILELAYOUT) {
|
||||
return false;
|
||||
} else {
|
||||
const TileLayoutSpriteGroup *tlgroup = (const TileLayoutSpriteGroup *)group;
|
||||
/* Limit the building stage to the number of stages supplied. */
|
||||
byte stage = GetIndustryConstructionStage(ti->tile);
|
||||
stage = Clamp(stage - 4 + group->g.layout.num_sprites, 0, group->g.layout.num_sprites - 1);
|
||||
IndustryDrawTileLayout(ti, group, i->random_colour, stage, gfx);
|
||||
stage = Clamp(stage - 4 + tlgroup->num_sprites, 0, tlgroup->num_sprites - 1);
|
||||
IndustryDrawTileLayout(ti, tlgroup, i->random_colour, stage, gfx);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -11,32 +11,27 @@
|
||||
SpriteGroupPool _spritegroup_pool("SpriteGroup");
|
||||
INSTANTIATE_POOL_METHODS(SpriteGroup)
|
||||
|
||||
SpriteGroup::~SpriteGroup()
|
||||
RealSpriteGroup::~RealSpriteGroup()
|
||||
{
|
||||
/* Free dynamically allocated memory */
|
||||
switch (this->type) {
|
||||
case SGT_REAL:
|
||||
free((SpriteGroup**)this->g.real.loaded);
|
||||
free((SpriteGroup**)this->g.real.loading);
|
||||
break;
|
||||
free((SpriteGroup**)this->loaded);
|
||||
free((SpriteGroup**)this->loading);
|
||||
}
|
||||
|
||||
case SGT_DETERMINISTIC:
|
||||
free(this->g.determ.adjusts);
|
||||
free(this->g.determ.ranges);
|
||||
break;
|
||||
DeterministicSpriteGroup::~DeterministicSpriteGroup()
|
||||
{
|
||||
free(this->adjusts);
|
||||
free(this->ranges);
|
||||
}
|
||||
|
||||
case SGT_RANDOMIZED:
|
||||
free((SpriteGroup**)this->g.random.groups);
|
||||
break;
|
||||
RandomizedSpriteGroup::~RandomizedSpriteGroup()
|
||||
{
|
||||
free((SpriteGroup**)this->groups);
|
||||
}
|
||||
|
||||
case SGT_TILELAYOUT:
|
||||
free((void*)this->g.layout.dts->seq);
|
||||
free(this->g.layout.dts);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
TileLayoutSpriteGroup::~TileLayoutSpriteGroup()
|
||||
{
|
||||
free((void*)this->dts->seq);
|
||||
free(this->dts);
|
||||
}
|
||||
|
||||
TemporaryStorageArray<uint32, 0x110> _temp_store;
|
||||
@ -126,17 +121,16 @@ static U EvalAdjustT(const DeterministicSpriteGroupAdjust *adjust, ResolverObjec
|
||||
}
|
||||
|
||||
|
||||
static inline const SpriteGroup *ResolveVariable(const SpriteGroup *group, ResolverObject *object)
|
||||
static inline const SpriteGroup *ResolveVariable(const DeterministicSpriteGroup *group, ResolverObject *object)
|
||||
{
|
||||
static SpriteGroup nvarzero;
|
||||
uint32 last_value = 0;
|
||||
uint32 value = 0;
|
||||
uint i;
|
||||
|
||||
object->scope = group->g.determ.var_scope;
|
||||
object->scope = group->var_scope;
|
||||
|
||||
for (i = 0; i < group->g.determ.num_adjusts; i++) {
|
||||
DeterministicSpriteGroupAdjust *adjust = &group->g.determ.adjusts[i];
|
||||
for (i = 0; i < group->num_adjusts; i++) {
|
||||
DeterministicSpriteGroupAdjust *adjust = &group->adjusts[i];
|
||||
|
||||
/* Try to get the variable. We shall assume it is available, unless told otherwise. */
|
||||
bool available = true;
|
||||
@ -144,10 +138,10 @@ static inline const SpriteGroup *ResolveVariable(const SpriteGroup *group, Resol
|
||||
ResolverObject subobject = *object;
|
||||
subobject.procedure_call = true;
|
||||
const SpriteGroup *subgroup = Resolve(adjust->subroutine, &subobject);
|
||||
if (subgroup == NULL || subgroup->type != SGT_CALLBACK) {
|
||||
if (subgroup == NULL) {
|
||||
value = CALLBACK_FAILED;
|
||||
} else {
|
||||
value = subgroup->g.callback.result;
|
||||
value = subgroup->GetCallbackResult();
|
||||
}
|
||||
} else {
|
||||
value = GetVariable(object, adjust->variable, adjust->parameter, &available);
|
||||
@ -156,10 +150,10 @@ static inline const SpriteGroup *ResolveVariable(const SpriteGroup *group, Resol
|
||||
if (!available) {
|
||||
/* Unsupported property: skip further processing and return either
|
||||
* the group from the first range or the default group. */
|
||||
return Resolve(group->g.determ.num_ranges > 0 ? group->g.determ.ranges[0].group : group->g.determ.default_group, object);
|
||||
return Resolve(group->num_ranges > 0 ? group->ranges[0].group : group->default_group, object);
|
||||
}
|
||||
|
||||
switch (group->g.determ.size) {
|
||||
switch (group->size) {
|
||||
case DSG_SIZE_BYTE: value = EvalAdjustT<uint8, int8> (adjust, object, last_value, value); break;
|
||||
case DSG_SIZE_WORD: value = EvalAdjustT<uint16, int16>(adjust, object, last_value, value); break;
|
||||
case DSG_SIZE_DWORD: value = EvalAdjustT<uint32, int32>(adjust, object, last_value, value); break;
|
||||
@ -170,45 +164,42 @@ static inline const SpriteGroup *ResolveVariable(const SpriteGroup *group, Resol
|
||||
|
||||
object->last_value = last_value;
|
||||
|
||||
if (group->g.determ.num_ranges == 0) {
|
||||
if (group->num_ranges == 0) {
|
||||
/* nvar == 0 is a special case -- we turn our value into a callback result */
|
||||
if (value != CALLBACK_FAILED) value = GB(value, 0, 15);
|
||||
nvarzero.type = SGT_CALLBACK;
|
||||
nvarzero.g.callback.result = value;
|
||||
static CallbackResultSpriteGroup nvarzero(0);
|
||||
nvarzero.result = value;
|
||||
return &nvarzero;
|
||||
}
|
||||
|
||||
for (i = 0; i < group->g.determ.num_ranges; i++) {
|
||||
if (group->g.determ.ranges[i].low <= value && value <= group->g.determ.ranges[i].high) {
|
||||
return Resolve(group->g.determ.ranges[i].group, object);
|
||||
for (i = 0; i < group->num_ranges; i++) {
|
||||
if (group->ranges[i].low <= value && value <= group->ranges[i].high) {
|
||||
return Resolve(group->ranges[i].group, object);
|
||||
}
|
||||
}
|
||||
|
||||
return Resolve(group->g.determ.default_group, object);
|
||||
return Resolve(group->default_group, object);
|
||||
}
|
||||
|
||||
|
||||
static inline const SpriteGroup *ResolveRandom(const SpriteGroup *group, ResolverObject *object)
|
||||
static inline const SpriteGroup *ResolveRandom(const RandomizedSpriteGroup *group, ResolverObject *object)
|
||||
{
|
||||
uint32 mask;
|
||||
byte index;
|
||||
|
||||
object->scope = group->g.random.var_scope;
|
||||
object->count = group->g.random.count;
|
||||
object->scope = group->var_scope;
|
||||
object->count = group->count;
|
||||
|
||||
if (object->trigger != 0) {
|
||||
/* Handle triggers */
|
||||
/* Magic code that may or may not do the right things... */
|
||||
byte waiting_triggers = object->GetTriggers(object);
|
||||
byte match = group->g.random.triggers & (waiting_triggers | object->trigger);
|
||||
bool res;
|
||||
|
||||
res = (group->g.random.cmp_mode == RSG_CMP_ANY) ?
|
||||
(match != 0) : (match == group->g.random.triggers);
|
||||
byte match = group->triggers & (waiting_triggers | object->trigger);
|
||||
bool res = (group->cmp_mode == RSG_CMP_ANY) ? (match != 0) : (match == group->triggers);
|
||||
|
||||
if (res) {
|
||||
waiting_triggers &= ~match;
|
||||
object->reseed |= (group->g.random.num_groups - 1) << group->g.random.lowest_randbit;
|
||||
object->reseed |= (group->num_groups - 1) << group->lowest_randbit;
|
||||
} else {
|
||||
waiting_triggers |= object->trigger;
|
||||
}
|
||||
@ -216,10 +207,10 @@ static inline const SpriteGroup *ResolveRandom(const SpriteGroup *group, Resolve
|
||||
object->SetTriggers(object, waiting_triggers);
|
||||
}
|
||||
|
||||
mask = (group->g.random.num_groups - 1) << group->g.random.lowest_randbit;
|
||||
index = (object->GetRandomBits(object) & mask) >> group->g.random.lowest_randbit;
|
||||
mask = (group->num_groups - 1) << group->lowest_randbit;
|
||||
index = (object->GetRandomBits(object) & mask) >> group->lowest_randbit;
|
||||
|
||||
return Resolve(group->g.random.groups[index], object);
|
||||
return Resolve(group->groups[index], object);
|
||||
}
|
||||
|
||||
|
||||
@ -230,9 +221,9 @@ const SpriteGroup *Resolve(const SpriteGroup *group, ResolverObject *object)
|
||||
if (group == NULL) return NULL;
|
||||
|
||||
switch (group->type) {
|
||||
case SGT_REAL: return object->ResolveReal(object, group);
|
||||
case SGT_DETERMINISTIC: return ResolveVariable(group, object);
|
||||
case SGT_RANDOMIZED: return ResolveRandom(group, object);
|
||||
case SGT_REAL: return object->ResolveReal(object, (RealSpriteGroup *)group);
|
||||
case SGT_DETERMINISTIC: return ResolveVariable((DeterministicSpriteGroup *)group, object);
|
||||
case SGT_RANDOMIZED: return ResolveRandom((RandomizedSpriteGroup *)group, object);
|
||||
default: return group;
|
||||
}
|
||||
}
|
||||
|
@ -30,12 +30,44 @@ static inline uint32 GetRegister(uint i)
|
||||
return _temp_store.Get(i);
|
||||
}
|
||||
|
||||
/* List of different sprite group types */
|
||||
enum SpriteGroupType {
|
||||
SGT_REAL,
|
||||
SGT_DETERMINISTIC,
|
||||
SGT_RANDOMIZED,
|
||||
SGT_CALLBACK,
|
||||
SGT_RESULT,
|
||||
SGT_TILELAYOUT,
|
||||
SGT_INDUSTRY_PRODUCTION,
|
||||
};
|
||||
|
||||
struct SpriteGroup;
|
||||
typedef uint32 SpriteGroupID;
|
||||
typedef Pool<SpriteGroup, SpriteGroupID, 512, 64000> SpriteGroupPool;
|
||||
extern SpriteGroupPool _spritegroup_pool;
|
||||
|
||||
/* Common wrapper for all the different sprite group types */
|
||||
struct SpriteGroup : SpriteGroupPool::PoolItem<&_spritegroup_pool> {
|
||||
protected:
|
||||
SpriteGroup(SpriteGroupType type) : type(type) {}
|
||||
|
||||
public:
|
||||
virtual ~SpriteGroup() {}
|
||||
|
||||
SpriteGroupType type;
|
||||
|
||||
virtual SpriteID GetResult() const { return 0; }
|
||||
virtual byte GetNumResults() const { return 0; }
|
||||
virtual uint16 GetCallbackResult() const { return CALLBACK_FAILED; }
|
||||
};
|
||||
|
||||
|
||||
/* 'Real' sprite groups contain a list of other result or callback sprite
|
||||
* groups. */
|
||||
struct RealSpriteGroup {
|
||||
struct RealSpriteGroup : SpriteGroup {
|
||||
RealSpriteGroup() : SpriteGroup(SGT_REAL) {}
|
||||
~RealSpriteGroup();
|
||||
|
||||
/* Loaded = in motion, loading = not moving
|
||||
* Each group contains several spritesets, for various loading stages */
|
||||
|
||||
@ -114,7 +146,10 @@ struct DeterministicSpriteGroupRange {
|
||||
};
|
||||
|
||||
|
||||
struct DeterministicSpriteGroup {
|
||||
struct DeterministicSpriteGroup : SpriteGroup {
|
||||
DeterministicSpriteGroup() : SpriteGroup(SGT_DETERMINISTIC) {}
|
||||
~DeterministicSpriteGroup();
|
||||
|
||||
VarSpriteGroupScope var_scope;
|
||||
DeterministicSpriteGroupSize size;
|
||||
byte num_adjusts;
|
||||
@ -131,7 +166,10 @@ enum RandomizedSpriteGroupCompareMode {
|
||||
RSG_CMP_ALL,
|
||||
};
|
||||
|
||||
struct RandomizedSpriteGroup {
|
||||
struct RandomizedSpriteGroup : SpriteGroup {
|
||||
RandomizedSpriteGroup() : SpriteGroup(SGT_RANDOMIZED) {}
|
||||
~RandomizedSpriteGroup();
|
||||
|
||||
VarSpriteGroupScope var_scope; ///< Take this object:
|
||||
|
||||
RandomizedSpriteGroupCompareMode cmp_mode; ///< Check for these triggers:
|
||||
@ -147,68 +185,68 @@ struct RandomizedSpriteGroup {
|
||||
|
||||
/* This contains a callback result. A failed callback has a value of
|
||||
* CALLBACK_FAILED */
|
||||
struct CallbackResultSpriteGroup {
|
||||
struct CallbackResultSpriteGroup : SpriteGroup {
|
||||
/**
|
||||
* Creates a spritegroup representing a callback result
|
||||
* @param result The value that was used to represent this callback result
|
||||
*/
|
||||
CallbackResultSpriteGroup(uint16 value) :
|
||||
SpriteGroup(SGT_CALLBACK),
|
||||
result(result)
|
||||
{
|
||||
/* Old style callback results have the highest byte 0xFF so signify it is a callback result
|
||||
* New style ones only have the highest bit set (allows 15-bit results, instead of just 8) */
|
||||
if ((this->result >> 8) == 0xFF) {
|
||||
this->result &= ~0xFF00;
|
||||
} else {
|
||||
this->result &= ~0x8000;
|
||||
}
|
||||
}
|
||||
|
||||
uint16 result;
|
||||
uint16 GetCallbackResult() const { return this->result; }
|
||||
};
|
||||
|
||||
|
||||
/* A result sprite group returns the first SpriteID and the number of
|
||||
* sprites in the set */
|
||||
struct ResultSpriteGroup {
|
||||
struct ResultSpriteGroup : SpriteGroup {
|
||||
/**
|
||||
* Creates a spritegroup representing a sprite number result.
|
||||
* @param sprite The sprite number.
|
||||
* @param num_sprites The number of sprites per set.
|
||||
* @return A spritegroup representing the sprite number result.
|
||||
*/
|
||||
ResultSpriteGroup(SpriteID sprite, byte num_sprites) :
|
||||
SpriteGroup(SGT_RESULT),
|
||||
sprite(sprite),
|
||||
num_sprites(num_sprites)
|
||||
{
|
||||
}
|
||||
|
||||
SpriteID sprite;
|
||||
byte num_sprites;
|
||||
SpriteID GetResult() const { return this->sprite; }
|
||||
byte GetNumResults() const { return this->num_sprites; }
|
||||
};
|
||||
|
||||
struct TileLayoutSpriteGroup {
|
||||
struct TileLayoutSpriteGroup : SpriteGroup {
|
||||
TileLayoutSpriteGroup() : SpriteGroup(SGT_TILELAYOUT) {}
|
||||
~TileLayoutSpriteGroup();
|
||||
|
||||
byte num_sprites; ///< Number of sprites in the spriteset, used for loading stages
|
||||
struct DrawTileSprites *dts;
|
||||
};
|
||||
|
||||
struct IndustryProductionSpriteGroup {
|
||||
struct IndustryProductionSpriteGroup : SpriteGroup {
|
||||
IndustryProductionSpriteGroup() : SpriteGroup(SGT_INDUSTRY_PRODUCTION) {}
|
||||
|
||||
uint8 version;
|
||||
uint16 substract_input[3];
|
||||
uint16 add_output[2];
|
||||
uint8 again;
|
||||
};
|
||||
|
||||
/* List of different sprite group types */
|
||||
enum SpriteGroupType {
|
||||
SGT_INVALID,
|
||||
SGT_REAL,
|
||||
SGT_DETERMINISTIC,
|
||||
SGT_RANDOMIZED,
|
||||
SGT_CALLBACK,
|
||||
SGT_RESULT,
|
||||
SGT_TILELAYOUT,
|
||||
SGT_INDUSTRY_PRODUCTION,
|
||||
};
|
||||
|
||||
typedef uint32 SpriteGroupID;
|
||||
typedef Pool<SpriteGroup, SpriteGroupID, 512, 64000> SpriteGroupPool;
|
||||
extern SpriteGroupPool _spritegroup_pool;
|
||||
|
||||
/* Common wrapper for all the different sprite group types */
|
||||
struct SpriteGroup : SpriteGroupPool::PoolItem<&_spritegroup_pool> {
|
||||
SpriteGroup(SpriteGroupType type = SGT_INVALID) :
|
||||
type(type)
|
||||
{
|
||||
}
|
||||
|
||||
~SpriteGroup();
|
||||
|
||||
SpriteGroupType type;
|
||||
|
||||
union {
|
||||
RealSpriteGroup real;
|
||||
DeterministicSpriteGroup determ;
|
||||
RandomizedSpriteGroup random;
|
||||
CallbackResultSpriteGroup callback;
|
||||
ResultSpriteGroup result;
|
||||
TileLayoutSpriteGroup layout;
|
||||
IndustryProductionSpriteGroup indprod;
|
||||
} g;
|
||||
};
|
||||
|
||||
|
||||
struct ResolverObject {
|
||||
CallbackID callback;
|
||||
@ -273,7 +311,7 @@ struct ResolverObject {
|
||||
uint32 (*GetTriggers)(const struct ResolverObject*);
|
||||
void (*SetTriggers)(const struct ResolverObject*, int);
|
||||
uint32 (*GetVariable)(const struct ResolverObject*, byte, byte, bool*);
|
||||
const SpriteGroup *(*ResolveReal)(const struct ResolverObject*, const SpriteGroup*);
|
||||
const SpriteGroup *(*ResolveReal)(const struct ResolverObject*, const RealSpriteGroup*);
|
||||
|
||||
ResolverObject() : procedure_call(false) { }
|
||||
};
|
||||
|
@ -527,7 +527,7 @@ static uint32 StationGetVariable(const ResolverObject *object, byte variable, by
|
||||
}
|
||||
|
||||
|
||||
static const SpriteGroup *StationResolveReal(const ResolverObject *object, const SpriteGroup *group)
|
||||
static const SpriteGroup *StationResolveReal(const ResolverObject *object, const RealSpriteGroup *group)
|
||||
{
|
||||
const Station *st = object->u.station.st;
|
||||
const StationSpec *statspec = object->u.station.statspec;
|
||||
@ -537,7 +537,7 @@ static const SpriteGroup *StationResolveReal(const ResolverObject *object, const
|
||||
CargoID cargo_type = object->u.station.cargo_type;
|
||||
|
||||
if (st == NULL || statspec->sclass == STAT_CLASS_WAYP) {
|
||||
return group->g.real.loading[0];
|
||||
return group->loading[0];
|
||||
}
|
||||
|
||||
switch (cargo_type) {
|
||||
@ -562,18 +562,18 @@ static const SpriteGroup *StationResolveReal(const ResolverObject *object, const
|
||||
cargo = min(0xfff, cargo);
|
||||
|
||||
if (cargo > statspec->cargo_threshold) {
|
||||
if (group->g.real.num_loading > 0) {
|
||||
set = ((cargo - statspec->cargo_threshold) * group->g.real.num_loading) / (4096 - statspec->cargo_threshold);
|
||||
return group->g.real.loading[set];
|
||||
if (group->num_loading > 0) {
|
||||
set = ((cargo - statspec->cargo_threshold) * group->num_loading) / (4096 - statspec->cargo_threshold);
|
||||
return group->loading[set];
|
||||
}
|
||||
} else {
|
||||
if (group->g.real.num_loaded > 0) {
|
||||
set = (cargo * group->g.real.num_loaded) / (statspec->cargo_threshold + 1);
|
||||
return group->g.real.loaded[set];
|
||||
if (group->num_loaded > 0) {
|
||||
set = (cargo * group->num_loaded) / (statspec->cargo_threshold + 1);
|
||||
return group->loaded[set];
|
||||
}
|
||||
}
|
||||
|
||||
return group->g.real.loading[0];
|
||||
return group->loading[0];
|
||||
}
|
||||
|
||||
|
||||
@ -645,7 +645,7 @@ SpriteID GetCustomStationRelocation(const StationSpec *statspec, const Station *
|
||||
|
||||
group = ResolveStation(&object);
|
||||
if (group == NULL || group->type != SGT_RESULT) return 0;
|
||||
return group->g.result.sprite - 0x42D;
|
||||
return group->GetResult() - 0x42D;
|
||||
}
|
||||
|
||||
|
||||
@ -661,7 +661,7 @@ SpriteID GetCustomStationGroundRelocation(const StationSpec *statspec, const Sta
|
||||
|
||||
group = ResolveStation(&object);
|
||||
if (group == NULL || group->type != SGT_RESULT) return 0;
|
||||
return group->g.result.sprite - 0x42D;
|
||||
return group->GetResult() - 0x42D;
|
||||
}
|
||||
|
||||
|
||||
@ -677,8 +677,8 @@ uint16 GetStationCallback(CallbackID callback, uint32 param1, uint32 param2, con
|
||||
object.callback_param2 = param2;
|
||||
|
||||
group = ResolveStation(&object);
|
||||
if (group == NULL || group->type != SGT_CALLBACK) return CALLBACK_FAILED;
|
||||
return group->g.callback.result;
|
||||
if (group == NULL) return CALLBACK_FAILED;
|
||||
return group->GetCallbackResult();
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user