mirror of https://github.com/OpenTTD/OpenTTD
(svn r22635) -Fix: Correctly reseed random bits of industries and industry tiles.
parent
8b18292a2e
commit
8930337aae
|
@ -1070,8 +1070,9 @@ static void DoTriggerVehicle(Vehicle *v, VehicleTrigger trigger, byte base_rando
|
||||||
if (group == NULL) return;
|
if (group == NULL) return;
|
||||||
|
|
||||||
new_random_bits = Random();
|
new_random_bits = Random();
|
||||||
v->random_bits &= ~object.reseed;
|
uint32 reseed = object.GetReseedSum(); // The scope only affects triggers, not the reseeding
|
||||||
v->random_bits |= (first ? new_random_bits : base_random_bits) & object.reseed;
|
v->random_bits &= ~reseed;
|
||||||
|
v->random_bits |= (first ? new_random_bits : base_random_bits) & reseed;
|
||||||
|
|
||||||
switch (trigger) {
|
switch (trigger) {
|
||||||
case VEHICLE_TRIGGER_NEW_CARGO:
|
case VEHICLE_TRIGGER_NEW_CARGO:
|
||||||
|
|
|
@ -606,8 +606,9 @@ static void DoTriggerHouse(TileIndex tile, HouseTrigger trigger, byte base_rando
|
||||||
|
|
||||||
byte new_random_bits = Random();
|
byte new_random_bits = Random();
|
||||||
byte random_bits = GetHouseRandomBits(tile);
|
byte random_bits = GetHouseRandomBits(tile);
|
||||||
random_bits &= ~object.reseed;
|
uint32 reseed = object.GetReseedSum(); // The scope only affects triggers, not the reseeding
|
||||||
random_bits |= (first ? new_random_bits : base_random) & object.reseed;
|
random_bits &= ~reseed;
|
||||||
|
random_bits |= (first ? new_random_bits : base_random) & reseed;
|
||||||
SetHouseRandomBits(tile, random_bits);
|
SetHouseRandomBits(tile, random_bits);
|
||||||
|
|
||||||
switch (trigger) {
|
switch (trigger) {
|
||||||
|
|
|
@ -369,7 +369,14 @@ bool StartStopIndustryTileAnimation(const Industry *ind, IndustryAnimationTrigge
|
||||||
return ret;
|
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;
|
ResolverObject object;
|
||||||
|
|
||||||
|
@ -390,24 +397,55 @@ static void DoTriggerIndustryTile(TileIndex tile, IndustryTileTrigger trigger, I
|
||||||
|
|
||||||
byte new_random_bits = Random();
|
byte new_random_bits = Random();
|
||||||
byte random_bits = GetIndustryRandomBits(tile);
|
byte random_bits = GetIndustryRandomBits(tile);
|
||||||
random_bits &= ~object.reseed;
|
random_bits &= ~object.reseed[VSG_SCOPE_SELF];
|
||||||
random_bits |= new_random_bits & object.reseed;
|
random_bits |= new_random_bits & object.reseed[VSG_SCOPE_SELF];
|
||||||
SetIndustryRandomBits(tile, random_bits);
|
SetIndustryRandomBits(tile, random_bits);
|
||||||
MarkTileDirtyByTile(tile);
|
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)
|
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)
|
void TriggerIndustry(Industry *ind, IndustryTileTrigger trigger)
|
||||||
{
|
{
|
||||||
|
uint32 reseed_industry = 0;
|
||||||
TILE_AREA_LOOP(tile, ind->location) {
|
TILE_AREA_LOOP(tile, ind->location) {
|
||||||
if (IsTileType(tile, MP_INDUSTRY) && GetIndustryIndex(tile) == ind->index) {
|
if (IsTileType(tile, MP_INDUSTRY) && GetIndustryIndex(tile) == ind->index) {
|
||||||
DoTriggerIndustryTile(tile, trigger, ind);
|
DoTriggerIndustryTile(tile, trigger, ind, reseed_industry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
DoReseedIndustry(ind, reseed_industry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -207,7 +207,7 @@ const SpriteGroup *RandomizedSpriteGroup::Resolve(ResolverObject *object) const
|
||||||
|
|
||||||
if (res) {
|
if (res) {
|
||||||
waiting_triggers &= ~match;
|
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 {
|
} else {
|
||||||
waiting_triggers |= object->trigger;
|
waiting_triggers |= object->trigger;
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,12 +122,15 @@ protected:
|
||||||
|
|
||||||
/* Shared by deterministic and random groups. */
|
/* Shared by deterministic and random groups. */
|
||||||
enum VarSpriteGroupScope {
|
enum VarSpriteGroupScope {
|
||||||
VSG_SCOPE_SELF,
|
VSG_BEGIN,
|
||||||
/* Engine of consists for vehicles, city for stations. */
|
|
||||||
VSG_SCOPE_PARENT,
|
VSG_SCOPE_SELF = VSG_BEGIN, ///< Resolved object itself
|
||||||
/* Any vehicle in the consist (vehicles only) */
|
VSG_SCOPE_PARENT, ///< Related object of the resolved one
|
||||||
VSG_SCOPE_RELATIVE,
|
VSG_SCOPE_RELATIVE, ///< Relative position (vehicles only)
|
||||||
|
|
||||||
|
VSG_END
|
||||||
};
|
};
|
||||||
|
DECLARE_POSTFIX_INCREMENT(VarSpriteGroupScope)
|
||||||
|
|
||||||
enum DeterministicSpriteGroupSize {
|
enum DeterministicSpriteGroupSize {
|
||||||
DSG_SIZE_BYTE,
|
DSG_SIZE_BYTE,
|
||||||
|
@ -309,7 +312,7 @@ struct ResolverObject {
|
||||||
byte trigger;
|
byte trigger;
|
||||||
|
|
||||||
uint32 last_value; ///< Result of most recent DeterministicSpriteGroup (including procedure calls)
|
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
|
VarSpriteGroupScope scope; ///< Scope of currently resolved DeterministicSpriteGroup resp. RandomizedSpriteGroup
|
||||||
byte count; ///< Additional scope for RandomizedSpriteGroup
|
byte count; ///< Additional scope for RandomizedSpriteGroup
|
||||||
|
@ -382,6 +385,20 @@ struct ResolverObject {
|
||||||
const SpriteGroup *(*ResolveReal)(const struct ResolverObject*, const RealSpriteGroup*);
|
const SpriteGroup *(*ResolveReal)(const struct ResolverObject*, const RealSpriteGroup*);
|
||||||
void (*StorePSA)(struct ResolverObject*, uint, int32);
|
void (*StorePSA)(struct ResolverObject*, uint, int32);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
* Resets the dynamic state of the resolver object.
|
||||||
* To be called before resolving an Action-1-2-3 chain.
|
* To be called before resolving an Action-1-2-3 chain.
|
||||||
|
@ -390,7 +407,7 @@ struct ResolverObject {
|
||||||
{
|
{
|
||||||
this->last_value = 0;
|
this->last_value = 0;
|
||||||
this->trigger = 0;
|
this->trigger = 0;
|
||||||
this->reseed = 0;
|
memset(this->reseed, 0, sizeof(this->reseed));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue