Changeset - r19949:26fad1c62a1b
[Not reviewed]
master
0 12 0
peter1138 - 12 years ago 2013-01-11 07:39:25
peter1138@openttd.org
(svn r24905) -Feature(ish): Implement station randomisation triggers.
12 files changed with 127 insertions and 11 deletions:
0 comments (0 inline, 0 general)
src/base_station_base.h
Show inline comments
 
@@ -71,6 +71,7 @@ struct BaseStation : StationPool::PoolIt
 
	uint16 random_bits;             ///< Random bits assigned to this station
 
	byte waiting_triggers;          ///< Waiting triggers (NewGRF) for this station
 
	uint8 cached_anim_triggers;     ///< NOSAVE: Combined animation trigger bitmask, used to determine if trigger processing should happen.
 
	uint32 cached_cargo_triggers;   ///< NOSAVE: Combined cargo trigger bitmask
 

	
 
	TileArea train_station;         ///< Tile area the train 'station' part covers
 
	StationRect rect;               ///< NOSAVE: Station spread out rectangle maintained by StationRect::xxx() functions
src/economy.cpp
Show inline comments
 
@@ -1535,6 +1535,7 @@ static void LoadUnloadVehicle(Vehicle *f
 
			st->last_vehicle_type = v->type;
 

	
 
			if (ge->cargo.Empty()) {
 
				TriggerStationRandomisation(st, st->xy, SRT_CARGO_TAKEN, v->cargo_type);
 
				TriggerStationAnimation(st, st->xy, SAT_CARGO_TAKEN, v->cargo_type);
 
				AirportAnimationTrigger(st, AAT_STATION_CARGO_TAKEN, v->cargo_type);
 
			}
 
@@ -1552,7 +1553,10 @@ static void LoadUnloadVehicle(Vehicle *f
 
	}
 

	
 
	if (anything_loaded || anything_unloaded) {
 
		if (front->type == VEH_TRAIN) TriggerStationAnimation(st, front->tile, SAT_TRAIN_LOADS);
 
		if (front->type == VEH_TRAIN) {
 
			TriggerStationRandomisation(st, front->tile, SRT_TRAIN_LOADS);
 
			TriggerStationAnimation(st, front->tile, SAT_TRAIN_LOADS);
 
		}
 
	}
 

	
 
	/* Only set completely_emptied, if we just unloaded all remaining cargo */
src/newgrf.cpp
Show inline comments
 
@@ -1908,6 +1908,9 @@ static ChangeInfoResult StationChangeInf
 

	
 
			case 0x12: // Cargo types for random triggers
 
				statspec->cargo_triggers = buf->ReadDWord();
 
				if (_cur.grffile->grf_version >= 7) {
 
					statspec->cargo_triggers = TranslateRefitMask(statspec->cargo_triggers);
 
				}
 
				break;
 

	
 
			case 0x13: // General flags
src/newgrf_station.cpp
Show inline comments
 
@@ -731,7 +731,7 @@ int AllocateSpecToStation(const StationS
 
		st->speclist[i].grfid    = statspec->grf_prop.grffile->grfid;
 
		st->speclist[i].localidx = statspec->grf_prop.local_id;
 

	
 
		StationUpdateAnimTriggers(st);
 
		StationUpdateCachedTriggers(st);
 
	}
 

	
 
	return i;
 
@@ -773,11 +773,12 @@ void DeallocateSpecFromStation(BaseStati
 
			st->num_specs = 0;
 
			st->speclist  = NULL;
 
			st->cached_anim_triggers = 0;
 
			st->cached_cargo_triggers = 0;
 
			return;
 
		}
 
	}
 

	
 
	StationUpdateAnimTriggers(st);
 
	StationUpdateCachedTriggers(st);
 
}
 

	
 
/**
 
@@ -969,18 +970,103 @@ void TriggerStationAnimation(BaseStation
 
}
 

	
 
/**
 
 * Trigger station randomisation
 
 * @param st station being triggered
 
 * @param tile specific tile of platform to trigger
 
 * @param trigger trigger type
 
 * @param cargo_type cargo type causing trigger
 
 */
 
void TriggerStationRandomisation(Station *st, TileIndex tile, StationRandomTrigger trigger, CargoID cargo_type)
 
{
 
	/* List of coverage areas for each animation trigger */
 
	static const TriggerArea tas[] = {
 
		TA_WHOLE, TA_WHOLE, TA_PLATFORM, TA_PLATFORM, TA_PLATFORM, TA_PLATFORM
 
	};
 

	
 
	/* Get Station if it wasn't supplied */
 
	if (st == NULL) st = Station::GetByTile(tile);
 

	
 
	/* Check the cached cargo trigger bitmask to see if we need
 
	 * to bother with any further processing. */
 
	if (st->cached_cargo_triggers == 0) return;
 
	if (cargo_type != CT_INVALID && !HasBit(st->cached_cargo_triggers, cargo_type)) return;
 

	
 
	uint32 whole_reseed = 0;
 
	ETileArea area = ETileArea(st, tile, tas[trigger]);
 

	
 
	uint32 empty_mask = 0;
 
	if (trigger == SRT_CARGO_TAKEN) {
 
		/* Create a bitmask of completely empty cargo types to be matched */
 
		for (CargoID i = 0; i < NUM_CARGO; i++) {
 
			if (st->goods[i].cargo.Empty()) {
 
				SetBit(empty_mask, i);
 
			}
 
		}
 
	}
 

	
 
	/* Convert trigger to bit */
 
	uint8 trigger_bit = 1 << trigger;
 

	
 
	/* Check all tiles over the station to check if the specindex is still in use */
 
	TILE_AREA_LOOP(tile, area) {
 
		if (st->TileBelongsToRailStation(tile)) {
 
			const StationSpec *ss = GetStationSpec(tile);
 
			if (ss == NULL) continue;
 

	
 
			/* Cargo taken "will only be triggered if all of those
 
			 * cargo types have no more cargo waiting." */
 
			if (trigger == SRT_CARGO_TAKEN) {
 
				if ((ss->cargo_triggers & ~empty_mask) != 0) continue;
 
			}
 

	
 
			if (cargo_type == CT_INVALID || HasBit(ss->cargo_triggers, cargo_type)) {
 
				StationResolverObject object(ss, st, tile, CBID_RANDOM_TRIGGER, 0);
 
				object.trigger = trigger_bit;
 

	
 
				const SpriteGroup *group = ResolveStation(&object);
 
				if (group == NULL) continue;
 

	
 
				uint32 reseed = object.GetReseedSum();
 
				if (reseed != 0) {
 
					whole_reseed |= reseed;
 
					reseed >>= 16;
 

	
 
					/* Set individual tile random bits */
 
					uint8 random_bits = GetStationTileRandomBits(tile);
 
					random_bits &= ~reseed;
 
					random_bits |= Random() & reseed;
 
					SetStationTileRandomBits(tile, random_bits);
 

	
 
					MarkTileDirtyByTile(tile);
 
				}
 
			}
 
		}
 
	}
 

	
 
	/* Update whole station random bits */
 
	if ((whole_reseed & 0xFFFF) != 0) {
 
		st->random_bits &= ~whole_reseed;
 
		st->random_bits |= Random() & whole_reseed;
 
	}
 
}
 

	
 
/**
 
 * Update the cached animation trigger bitmask for a station.
 
 * @param st Station to update.
 
 */
 
void StationUpdateAnimTriggers(BaseStation *st)
 
void StationUpdateCachedTriggers(BaseStation *st)
 
{
 
	st->cached_anim_triggers = 0;
 
	st->cached_cargo_triggers = 0;
 

	
 
	/* Combine animation trigger bitmask for all station specs
 
	 * of this station. */
 
	for (uint i = 0; i < st->num_specs; i++) {
 
		const StationSpec *ss = st->speclist[i].spec;
 
		if (ss != NULL) st->cached_anim_triggers |= ss->animation.triggers;
 
		if (ss != NULL) {
 
			st->cached_anim_triggers |= ss->animation.triggers;
 
			st->cached_cargo_triggers |= ss->cargo_triggers;
 
		}
 
	}
 
}
 

	
src/newgrf_station.h
Show inline comments
 
@@ -90,6 +90,16 @@ enum StationSpecFlags {
 
	SSF_EXTENDED_FOUNDATIONS, ///< Extended foundation block instead of simple.
 
};
 

	
 
/** Randomisation triggers for stations */
 
enum StationRandomTrigger {
 
	SRT_NEW_CARGO,        ///< Trigger station on new cargo arrival.
 
	SRT_CARGO_TAKEN,      ///< Trigger station when cargo is completely taken.
 
	SRT_TRAIN_ARRIVES,    ///< Trigger platform when train arrives.
 
	SRT_TRAIN_DEPARTS,    ///< Trigger platform when train leaves.
 
	SRT_TRAIN_LOADS,      ///< Trigger platform when train loads/unloads.
 
	SRT_PATH_RESERVATION, ///< Trigger platform when train reserves path.
 
};
 

	
 
/* Station layout for given dimensions - it is a two-dimensional array
 
 * where index is computed as (x * platforms) + platform. */
 
typedef byte *StationLayout;
 
@@ -176,6 +186,7 @@ bool DrawStationTile(int x, int y, RailT
 

	
 
void AnimateStationTile(TileIndex tile);
 
void TriggerStationAnimation(BaseStation *st, TileIndex tile, StationAnimationTrigger trigger, CargoID cargo_type = CT_INVALID);
 
void StationUpdateAnimTriggers(BaseStation *st);
 
void TriggerStationRandomisation(Station *st, TileIndex tile, StationRandomTrigger trigger, CargoID cargo_type = CT_INVALID);
 
void StationUpdateCachedTriggers(BaseStation *st);
 

	
 
#endif /* NEWGRF_STATION_H */
src/pathfinder/yapf/yapf_rail.cpp
Show inline comments
 
@@ -17,6 +17,7 @@
 
#include "yapf_costrail.hpp"
 
#include "yapf_destrail.hpp"
 
#include "../../viewport_func.h"
 
#include "../../newgrf_station.h"
 

	
 
#define DEBUG_YAPF_CACHE 0
 

	
 
@@ -83,6 +84,8 @@ private:
 
			tile = TILE_ADD(tile, diff);
 
		} while (IsCompatibleTrainStationTile(tile, start) && tile != m_origin_tile);
 

	
 
		TriggerStationRandomisation(NULL, start, SRT_PATH_RESERVATION);
 

	
 
		return true;
 
	}
 

	
src/pbs.cpp
Show inline comments
 
@@ -12,6 +12,7 @@
 
#include "stdafx.h"
 
#include "viewport_func.h"
 
#include "vehicle_func.h"
 
#include "newgrf_station.h"
 
#include "pathfinder/follow_track.hpp"
 

	
 
/**
 
@@ -72,10 +73,11 @@ void SetRailStationPlatformReservation(T
 
 * Try to reserve a specific track on a tile
 
 * @param tile the tile
 
 * @param t the track
 
 * @param trigger_stations whether to call station randomisation trigger
 
 * @return \c true if reservation was successful, i.e. the track was
 
 *     free and didn't cross any other reserved tracks.
 
 */
 
bool TryReserveRailTrack(TileIndex tile, Track t)
 
bool TryReserveRailTrack(TileIndex tile, Track t, bool trigger_stations)
 
{
 
	assert((GetTileTrackStatus(tile, TRANSPORT_RAIL, 0) & TrackToTrackBits(t)) != 0);
 

	
 
@@ -108,6 +110,7 @@ bool TryReserveRailTrack(TileIndex tile,
 
		case MP_STATION:
 
			if (HasStationRail(tile) && !HasStationReservation(tile)) {
 
				SetRailStationReservation(tile, true);
 
				if (trigger_stations) TriggerStationRandomisation(NULL, tile, SRT_PATH_RESERVATION);
 
				MarkTileDirtyByTile(tile); // some GRFs need redraw after reserving track
 
				return true;
 
			}
src/pbs.h
Show inline comments
 
@@ -21,7 +21,7 @@ TrackBits GetReservedTrackbits(TileIndex
 

	
 
void SetRailStationPlatformReservation(TileIndex start, DiagDirection dir, bool b);
 

	
 
bool TryReserveRailTrack(TileIndex tile, Track t);
 
bool TryReserveRailTrack(TileIndex tile, Track t, bool trigger_stations = true);
 
void UnreserveRailTrack(TileIndex tile, Track t);
 

	
 
/** This struct contains information about the end of a reserved path. */
src/saveload/station_sl.cpp
Show inline comments
 
@@ -123,7 +123,7 @@ void AfterLoadStations()
 
			for (const RoadStop *rs = sta->truck_stops; rs != NULL; rs = rs->next) sta->truck_station.Add(rs->xy);
 
		}
 

	
 
		StationUpdateAnimTriggers(st);
 
		StationUpdateCachedTriggers(st);
 
	}
 
}
 

	
src/station_cmd.cpp
Show inline comments
 
@@ -3380,6 +3380,7 @@ static uint UpdateStationWaiting(Station
 
		SetBit(ge.acceptance_pickup, GoodsEntry::GES_PICKUP);
 
	}
 

	
 
	TriggerStationRandomisation(st, st->xy, SRT_NEW_CARGO, type);
 
	TriggerStationAnimation(st, st->xy, SAT_NEW_CARGO, type);
 
	AirportAnimationTrigger(st, AAT_STATION_NEW_CARGO, type);
 

	
src/train_cmd.cpp
Show inline comments
 
@@ -2810,6 +2810,7 @@ static void TrainEnterStation(Train *v, 
 

	
 
	v->BeginLoading();
 

	
 
	TriggerStationRandomisation(st, v->tile, SRT_TRAIN_ARRIVES);
 
	TriggerStationAnimation(st, v->tile, SAT_TRAIN_ARRIVES);
 
}
 

	
 
@@ -3184,7 +3185,7 @@ bool TrainController(Train *v, Vehicle *
 
						}
 
						goto reverse_train_direction;
 
					} else {
 
						TryReserveRailTrack(gp.new_tile, TrackBitsToTrack(chosen_track));
 
						TryReserveRailTrack(gp.new_tile, TrackBitsToTrack(chosen_track), false);
 
					}
 
				} else {
 
					/* The wagon is active, simply follow the prev vehicle. */
src/vehicle.cpp
Show inline comments
 
@@ -2001,7 +2001,10 @@ void Vehicle::LeaveStation()
 

	
 
	if (this->type == VEH_TRAIN && !(this->vehstatus & VS_CRASHED)) {
 
		/* Trigger station animation (trains only) */
 
		if (IsTileType(this->tile, MP_STATION)) TriggerStationAnimation(st, this->tile, SAT_TRAIN_DEPARTS);
 
		if (IsTileType(this->tile, MP_STATION)) {
 
			TriggerStationRandomisation(st, this->tile, SRT_TRAIN_DEPARTS);
 
			TriggerStationAnimation(st, this->tile, SAT_TRAIN_DEPARTS);
 
		}
 

	
 
		SetBit(Train::From(this)->flags, VRF_LEAVING_STATION);
 
	}
0 comments (0 inline, 0 general)