1
0
Fork 0

(svn r22653) [1.1] -Backport from trunk:

- Fix: [NewGRF] Disable the 'set parameters' button in the NewGRF GUI, if the GRF specifies to have no parameters and one would not be able to set any parameters anyway (r22642)
- Fix: Keep the previous owner of the upper and lower lock parts if they are built on existing water (r22638)
- Fix: [NewGRF] Airports should not expose the tile specific random bits of the north tile. Only airport tiles should access those (r22636)
- Fix: [NewGRF] Correctly reseed random bits of industries and industry tiles (r22635, r22634)
release/1.1
rubidium 2011-07-10 20:29:19 +00:00
parent a873aa3337
commit 3a39cea23b
17 changed files with 109 additions and 72 deletions

View File

@ -171,8 +171,7 @@ static const SpriteGroup *AirportResolveReal(const ResolverObject *object, const
static uint32 AirportGetRandomBits(const ResolverObject *object)
{
const Station *st = object->u.airport.st;
const TileIndex tile = object->u.airport.tile;
return (st == NULL ? 0 : st->random_bits) | (tile == INVALID_TILE ? 0 : GetStationTileRandomBits(tile) << 16);
return st == NULL ? 0 : st->random_bits;
}
static uint32 AirportGetTriggers(const ResolverObject *object)
@ -201,10 +200,7 @@ static void NewAirportResolver(ResolverObject *res, TileIndex tile, Station *st,
res->callback = CBID_NO_CALLBACK;
res->callback_param1 = 0;
res->callback_param2 = 0;
res->last_value = 0;
res->trigger = 0;
res->reseed = 0;
res->count = 0;
res->ResetState();
const AirportSpec *as = AirportSpec::Get(airport_id);
res->grffile = as->grf_prop.grffile;

View File

@ -238,10 +238,7 @@ static void AirportTileResolver(ResolverObject *res, const AirportTileSpec *ats,
res->callback = CBID_NO_CALLBACK;
res->callback_param1 = 0;
res->callback_param2 = 0;
res->last_value = 0;
res->trigger = 0;
res->reseed = 0;
res->count = 0;
res->ResetState();
res->grffile = ats->grf_prop.grffile;
}

View File

@ -89,10 +89,8 @@ static void NewCanalResolver(ResolverObject *res, TileIndex tile, const GRFFile
res->callback = CBID_NO_CALLBACK;
res->callback_param1 = 0;
res->callback_param2 = 0;
res->last_value = 0;
res->trigger = 0;
res->reseed = 0;
res->count = 0;
res->ResetState();
res->grffile = grffile;
}

View File

@ -66,10 +66,8 @@ static void NewCargoResolver(ResolverObject *res, const CargoSpec *cs)
res->callback = CBID_NO_CALLBACK;
res->callback_param1 = 0;
res->callback_param2 = 0;
res->last_value = 0;
res->trigger = 0;
res->reseed = 0;
res->count = 0;
res->ResetState();
res->grffile = cs->grffile;
}

View File

@ -878,10 +878,7 @@ static inline void NewVehicleResolver(ResolverObject *res, EngineID engine_type,
res->callback = CBID_NO_CALLBACK;
res->callback_param1 = 0;
res->callback_param2 = 0;
res->last_value = 0;
res->trigger = 0;
res->reseed = 0;
res->count = 0;
res->ResetState();
const Engine *e = Engine::Get(engine_type);
res->grffile = (e != NULL ? e->grf_prop.grffile : NULL);
@ -1073,8 +1070,9 @@ static void DoTriggerVehicle(Vehicle *v, VehicleTrigger trigger, byte base_rando
if (group == NULL) return;
new_random_bits = Random();
v->random_bits &= ~object.reseed;
v->random_bits |= (first ? new_random_bits : base_random_bits) & object.reseed;
uint32 reseed = object.GetReseedSum(); // The scope only affects triggers, not the reseeding
v->random_bits &= ~reseed;
v->random_bits |= (first ? new_random_bits : base_random_bits) & reseed;
switch (trigger) {
case VEHICLE_TRIGGER_NEW_CARGO:

View File

@ -126,10 +126,8 @@ static inline void NewGenericResolver(ResolverObject *res, const GRFFile *grffil
res->callback = CBID_NO_CALLBACK;
res->callback_param1 = 0;
res->callback_param2 = 0;
res->last_value = 0;
res->trigger = 0;
res->reseed = 0;
res->count = 0;
res->ResetState();
res->grffile = grffile;
}

View File

@ -944,7 +944,7 @@ struct NewGRFWindow : public QueryStringBaseWindow {
break;
case SNGRFS_SET_PARAMETERS: { // Edit parameters
if (this->active_sel == NULL || !this->editable || !this->show_params) break;
if (this->active_sel == NULL || !this->editable || !this->show_params || this->active_sel->num_valid_params == 0) break;
OpenGRFParameterWindow(this->active_sel);
break;
@ -1099,7 +1099,7 @@ struct NewGRFWindow : public QueryStringBaseWindow {
SNGRFS_MOVE_DOWN,
WIDGET_LIST_END
);
this->SetWidgetDisabledState(SNGRFS_SET_PARAMETERS, !this->show_params || disable_all);
this->SetWidgetDisabledState(SNGRFS_SET_PARAMETERS, !this->show_params || disable_all || this->active_sel->num_valid_params == 0);
this->SetWidgetDisabledState(SNGRFS_TOGGLE_PALETTE, disable_all);
if (!disable_all) {

View File

@ -381,10 +381,7 @@ static void NewHouseResolver(ResolverObject *res, HouseID house_id, TileIndex ti
res->callback = CBID_NO_CALLBACK;
res->callback_param1 = 0;
res->callback_param2 = 0;
res->last_value = 0;
res->trigger = 0;
res->reseed = 0;
res->count = 0;
res->ResetState();
const HouseSpec *hs = HouseSpec::Get(house_id);
res->grffile = (hs != NULL ? hs->grf_prop.grffile : NULL);
@ -592,8 +589,9 @@ static void DoTriggerHouse(TileIndex tile, HouseTrigger trigger, byte base_rando
byte new_random_bits = Random();
byte random_bits = GetHouseRandomBits(tile);
random_bits &= ~object.reseed;
random_bits |= (first ? new_random_bits : base_random) & object.reseed;
uint32 reseed = object.GetReseedSum(); // The scope only affects triggers, not the reseeding
random_bits &= ~reseed;
random_bits |= (first ? new_random_bits : base_random) & reseed;
SetHouseRandomBits(tile, random_bits);
switch (trigger) {

View File

@ -387,10 +387,7 @@ static void NewIndustryResolver(ResolverObject *res, TileIndex tile, Industry *i
res->callback = CBID_NO_CALLBACK;
res->callback_param1 = 0;
res->callback_param2 = 0;
res->last_value = 0;
res->trigger = 0;
res->reseed = 0;
res->count = 0;
res->ResetState();
const IndustrySpec *indspec = GetIndustrySpec(type);
res->grffile = (indspec != NULL ? indspec->grf_prop.grffile : NULL);

View File

@ -165,10 +165,7 @@ static void NewIndustryTileResolver(ResolverObject *res, IndustryGfx gfx, TileIn
res->callback = CBID_NO_CALLBACK;
res->callback_param1 = 0;
res->callback_param2 = 0;
res->last_value = 0;
res->trigger = 0;
res->reseed = 0;
res->count = 0;
res->ResetState();
const IndustryTileSpec *its = GetIndustryTileSpec(gfx);
res->grffile = (its != NULL ? its->grf_prop.grffile : NULL);
@ -345,7 +342,14 @@ bool StartStopIndustryTileAnimation(const Industry *ind, IndustryAnimationTrigge
return ret;
}
static void DoTriggerIndustryTile(TileIndex tile, IndustryTileTrigger trigger, Industry *ind)
/**
* 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 &reseed_industry)
{
ResolverObject object;
@ -366,24 +370,55 @@ static void DoTriggerIndustryTile(TileIndex tile, IndustryTileTrigger trigger, I
byte new_random_bits = Random();
byte random_bits = GetIndustryRandomBits(tile);
random_bits &= ~object.reseed;
random_bits |= new_random_bits & object.reseed;
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 reseed)
{
if (reseed == 0 || ind == NULL) return;
uint16 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)
{
DoTriggerIndustryTile(tile, trigger, Industry::GetByTile(tile));
uint32 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 reseed_industry = 0;
TILE_AREA_LOOP(tile, ind->location) {
if (IsTileType(tile, MP_INDUSTRY) && GetIndustryIndex(tile) == ind->index) {
DoTriggerIndustryTile(tile, trigger, ind);
DoTriggerIndustryTile(tile, trigger, ind, reseed_industry);
}
}
DoReseedIndustry(ind, reseed_industry);
}
/**

View File

@ -376,10 +376,7 @@ static void NewObjectResolver(ResolverObject *res, const ObjectSpec *spec, const
res->callback = CBID_NO_CALLBACK;
res->callback_param1 = 0;
res->callback_param2 = 0;
res->last_value = 0;
res->trigger = 0;
res->reseed = 0;
res->count = 0;
res->ResetState();
res->grffile = spec->grf_prop.grffile;
}

View File

@ -81,10 +81,7 @@ static inline void NewRailTypeResolver(ResolverObject *res, TileIndex tile, Tile
res->callback = CBID_NO_CALLBACK;
res->callback_param1 = 0;
res->callback_param2 = 0;
res->last_value = 0;
res->trigger = 0;
res->reseed = 0;
res->count = 0;
res->ResetState();
res->grffile = grffile;
}

View File

@ -213,7 +213,7 @@ const SpriteGroup *RandomizedSpriteGroup::Resolve(ResolverObject *object) const
if (res) {
waiting_triggers &= ~match;
object->reseed |= (this->num_groups - 1) << this->lowest_randbit;
object->reseed[this->var_scope] |= (this->num_groups - 1) << this->lowest_randbit;
} else {
waiting_triggers |= object->trigger;
}

View File

@ -122,12 +122,15 @@ protected:
/* Shared by deterministic and random groups. */
enum VarSpriteGroupScope {
VSG_SCOPE_SELF,
/* Engine of consists for vehicles, city for stations. */
VSG_SCOPE_PARENT,
/* Any vehicle in the consist (vehicles only) */
VSG_SCOPE_RELATIVE,
VSG_BEGIN,
VSG_SCOPE_SELF = VSG_BEGIN, ///< Resolved object itself
VSG_SCOPE_PARENT, ///< Related object of the resolved one
VSG_SCOPE_RELATIVE, ///< Relative position (vehicles only)
VSG_END
};
DECLARE_POSTFIX_INCREMENT(VarSpriteGroupScope)
enum DeterministicSpriteGroupSize {
DSG_SIZE_BYTE,
@ -304,7 +307,7 @@ struct ResolverObject {
byte trigger;
uint32 last_value; ///< Result of most recent DeterministicSpriteGroup (including procedure calls)
uint32 reseed; ///< Collects bits to rerandomise while triggering triggers.
uint32 reseed[VSG_END]; ///< Collects bits to rerandomise while triggering triggers.
VarSpriteGroupScope scope; ///< Scope of currently resolved DeterministicSpriteGroup resp. RandomizedSpriteGroup
byte count; ///< Additional scope for RandomizedSpriteGroup
@ -377,6 +380,31 @@ struct ResolverObject {
void (*SetTriggers)(const struct ResolverObject*, int);
uint32 (*GetVariable)(const struct ResolverObject*, byte, byte, bool*);
const SpriteGroup *(*ResolveReal)(const struct ResolverObject*, const RealSpriteGroup*);
/**
* Returns the OR-sum of all bits that need reseeding
* independent of the scope they were accessed with.
* @return OR-sum of the bits.
*/
uint32 GetReseedSum() const
{
uint32 sum = 0;
for (VarSpriteGroupScope vsg = VSG_BEGIN; vsg < VSG_END; vsg++) {
sum |= this->reseed[vsg];
}
return sum;
}
/**
* Resets the dynamic state of the resolver object.
* To be called before resolving an Action-1-2-3 chain.
*/
void ResetState()
{
this->last_value = 0;
this->trigger = 0;
memset(this->reseed, 0, sizeof(this->reseed));
}
};
#endif /* NEWGRF_SPRITEGROUP_H */

View File

@ -531,10 +531,8 @@ static void NewStationResolver(ResolverObject *res, const StationSpec *statspec,
res->callback = CBID_NO_CALLBACK;
res->callback_param1 = 0;
res->callback_param2 = 0;
res->last_value = 0;
res->trigger = 0;
res->reseed = 0;
res->count = 0;
res->ResetState();
res->grffile = (statspec != NULL ? statspec->grf_prop.grffile : NULL);
}

View File

@ -279,8 +279,8 @@ static CommandCost RemoveLock(TileIndex tile, DoCommandFlag flags)
if (flags & DC_EXEC) {
DoClearSquare(tile);
MakeWaterKeepingClass(tile + delta, GetTileOwner(tile));
MakeWaterKeepingClass(tile - delta, GetTileOwner(tile));
MakeWaterKeepingClass(tile + delta, GetTileOwner(tile + delta));
MakeWaterKeepingClass(tile - delta, GetTileOwner(tile - delta));
MarkCanalsAndRiversAroundDirty(tile - delta);
MarkCanalsAndRiversAroundDirty(tile + delta);
}

View File

@ -420,8 +420,10 @@ static inline void MakeLock(TileIndex t, Owner o, DiagDirection d, WaterClass wc
TileIndexDiff delta = TileOffsByDiagDir(d);
MakeLockTile(t, o, LOCK_MIDDLE + d, WATER_CLASS_CANAL);
MakeLockTile(t - delta, o, LOCK_LOWER + d, wc_lower);
MakeLockTile(t + delta, o, LOCK_UPPER + d, wc_upper);
/* Keep the current owner for the upper and lower part if it is a
* water tile so we can restore the owner after deleting the lock. */
MakeLockTile(t - delta, IsWaterTile(t - delta) ? GetTileOwner(t - delta) : o, LOCK_LOWER + d, wc_lower);
MakeLockTile(t + delta, IsWaterTile(t + delta) ? GetTileOwner(t + delta) : o, LOCK_UPPER + d, wc_upper);
}
#endif /* WATER_MAP_H */