--- a/src/vehicle.cpp Sat Oct 06 21:16:00 2007 +0000
+++ b/src/vehicle.cpp Mon Dec 03 23:39:38 2007 +0000
@@ -117,25 +117,11 @@
}
}
-static void *EnsureNoVehicleProc(Vehicle *v, void *data)
-{
- if (v->tile != *(const TileIndex*)data || v->type == VEH_DISASTER)
- return NULL;
-
- _error_message = VehicleInTheWayErrMsg(v);
- return v;
-}
-
-bool EnsureNoVehicle(TileIndex tile)
-{
- return VehicleFromPos(tile, &tile, EnsureNoVehicleProc) == NULL;
-}
-
static void *EnsureNoVehicleProcZ(Vehicle *v, void *data)
{
const TileInfo *ti = (const TileInfo*)data;
- if (v->tile != ti->tile || v->type == VEH_DISASTER) return NULL;
+ if (v->tile != ti->tile || v->type == VEH_DISASTER || (v->type == VEH_AIRCRAFT && v->subtype == AIR_SHADOW)) return NULL;
if (v->z_pos > ti->z) return NULL;
_error_message = VehicleInTheWayErrMsg(v);
@@ -248,7 +234,7 @@
FOR_ALL_VEHICLES(v) {
switch (v->type) {
case VEH_ROAD:
- v->u.road.roadtype = HASBIT(EngInfo(v->engine_type)->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD;
+ v->u.road.roadtype = HasBit(EngInfo(v->engine_type)->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD;
v->u.road.compatible_roadtypes = RoadTypeToRoadTypes(v->u.road.roadtype);
/* FALL THROUGH */
case VEH_TRAIN:
@@ -288,6 +274,7 @@
this->group_id = DEFAULT_GROUP;
this->fill_percent_te_id = INVALID_TE_ID;
this->first = this;
+ this->colormap = PAL_NONE;
}
/**
@@ -471,6 +458,12 @@
memset(_new_vehicle_position_hash, 0, sizeof(_new_vehicle_position_hash));
}
+void ResetVehicleColorMap()
+{
+ Vehicle *v;
+ FOR_ALL_VEHICLES(v) { v->colormap = PAL_NONE; }
+}
+
void InitializeVehicles()
{
_Vehicle_pool.CleanPool();
@@ -543,6 +536,12 @@
if ((this->type == VEH_TRAIN && EngineHasArticPart(this)) || (this->type == VEH_ROAD && RoadVehHasArticPart(this))) {
delete this->Next();
}
+
+ Window *w = FindWindowById(WC_VEHICLE_VIEW, this->index);
+ if (w != NULL && WP(w, vp_d).follow_vehicle == this->index) {
+ ScrollMainWindowTo(this->x_pos, this->y_pos); // lock the main view on the vehicle's last position
+ WP(w, vp_d).follow_vehicle = INVALID_VEHICLE;
+ }
}
Vehicle::~Vehicle()
@@ -564,13 +563,10 @@
/**
* Deletes all vehicles in a chain.
* @param v The first vehicle in the chain.
- *
- * @warning This function is not valid for any vehicle containing articulated
- * parts.
*/
void DeleteVehicleChain(Vehicle *v)
{
- assert(v->type != VEH_TRAIN && v->type != VEH_ROAD);
+ assert(v->First() == v);
do {
Vehicle *u = v;
@@ -588,7 +584,7 @@
void VehicleEnteredDepotThisTick(Vehicle *v)
{
/* we need to set v->leave_depot_instantly as we have no control of it's contents at this time */
- if (HASBIT(v->current_order.flags, OFB_HALT_IN_DEPOT) && !HASBIT(v->current_order.flags, OFB_PART_OF_ORDERS) && v->current_order.type == OT_GOTO_DEPOT) {
+ if (HasBit(v->current_order.flags, OFB_HALT_IN_DEPOT) && !HasBit(v->current_order.flags, OFB_PART_OF_ORDERS) && v->current_order.type == OT_GOTO_DEPOT) {
/* we keep the vehicle in the depot since the user ordered it to stay */
v->leave_depot_instantly = false;
} else {
@@ -656,7 +652,7 @@
*/
bool CanRefitTo(EngineID engine_type, CargoID cid_to)
{
- return HASBIT(EngInfo(engine_type)->refit_mask, cid_to);
+ return HasBit(EngInfo(engine_type)->refit_mask, cid_to);
}
/** Find the first cargo type that an engine can be refitted to.
@@ -669,7 +665,7 @@
if (refit_mask != 0) {
for (CargoID cid = 0; cid < NUM_CARGO; cid++) {
- if (HASBIT(refit_mask, cid)) return cid;
+ if (HasBit(refit_mask, cid)) return cid;
}
}
@@ -1268,7 +1264,7 @@
}
if (b->y == 4 && b->x == 1) {
- if (v->z_pos > 180 || CHANCE16I(1, 96, InteractiveRandom())) {
+ if (v->z_pos > 180 || Chance16I(1, 96, InteractiveRandom())) {
v->spritenum = 5;
SndPlayVehicleFx(SND_2F_POP, v);
}
@@ -1353,8 +1349,8 @@
Vehicle *CreateEffectVehicleAbove(int x, int y, int z, EffectVehicle type)
{
- int safe_x = clamp(x, 0, MapMaxX() * TILE_SIZE);
- int safe_y = clamp(y, 0, MapMaxY() * TILE_SIZE);
+ int safe_x = Clamp(x, 0, MapMaxX() * TILE_SIZE);
+ int safe_y = Clamp(y, 0, MapMaxY() * TILE_SIZE);
return CreateEffectVehicle(x, y, GetSlopeZ(safe_x, safe_y) + z, type);
}
@@ -1386,8 +1382,8 @@
y >= v->top_coord && y <= v->bottom_coord) {
dist = max(
- myabs( ((v->left_coord + v->right_coord)>>1) - x ),
- myabs( ((v->top_coord + v->bottom_coord)>>1) - y )
+ abs( ((v->left_coord + v->right_coord)>>1) - x ),
+ abs( ((v->top_coord + v->bottom_coord)>>1) - y )
);
if (dist < best_dist) {
@@ -1400,6 +1396,15 @@
return found;
}
+void CheckVehicle32Day(Vehicle *v)
+{
+ if ((v->day_counter & 0x1F) != 0) return;
+
+ uint16 callback = GetVehicleCallback(CBID_VEHICLE_32DAY_CALLBACK, 0, 0, v->engine_type, v);
+ if (callback == CALLBACK_FAILED) return;
+ if (HasBit(callback, 0)) TriggerVehicle(v, VEHICLE_TRIGGER_CALLBACK_32); // Trigger vehicle trigger 10
+ if (HasBit(callback, 1)) v->colormap = PAL_NONE; // Update colormap via callback 2D
+}
void DecreaseVehicleValue(Vehicle *v)
{
@@ -1438,7 +1443,7 @@
/* increase chance of failure */
chance = v->breakdown_chance + 1;
- if (CHANCE16I(1,25,r)) chance += 25;
+ if (Chance16I(1,25,r)) chance += 25;
v->breakdown_chance = min(255, chance);
/* calculate reliability value to use in comparison */
@@ -1515,8 +1520,8 @@
uint i;
uint stop_command;
VehicleType vehicle_type = (VehicleType)GB(p2, 0, 5);
- bool start_stop = HASBIT(p2, 5);
- bool vehicle_list_window = HASBIT(p2, 6);
+ bool start_stop = HasBit(p2, 5);
+ bool vehicle_list_window = HasBit(p2, 6);
switch (vehicle_type) {
case VEH_TRAIN: stop_command = CMD_START_STOP_TRAIN; break;
@@ -1746,8 +1751,8 @@
if (flags & DC_EXEC) {
w = GetVehicle(_new_vehicle_id);
- if (v->type == VEH_TRAIN && HASBIT(v->u.rail.flags, VRF_REVERSE_DIRECTION)) {
- SETBIT(w->u.rail.flags, VRF_REVERSE_DIRECTION);
+ if (v->type == VEH_TRAIN && HasBit(v->u.rail.flags, VRF_REVERSE_DIRECTION)) {
+ SetBit(w->u.rail.flags, VRF_REVERSE_DIRECTION);
}
if (v->type == VEH_TRAIN && !IsFrontEngine(v)) {
@@ -1762,10 +1767,9 @@
return result; // return error and the message returned from CMD_MOVE_RAIL_VEHICLE
}
} else {
- /* this is a front engine or not a train. It need orders */
+ /* this is a front engine or not a train. */
w_front = w;
w->service_interval = v->service_interval;
- DoCommand(0, (v->index << 16) | w->index, p2 & 1 ? CO_SHARE : CO_COPY, flags, CMD_CLONE_ORDER);
}
w_rear = w; // trains needs to know the last car in the train, so they can add more in next loop
}
@@ -1797,7 +1801,7 @@
if (flags & DC_EXEC) {
assert(w != NULL);
- if (w->cargo_type != v->cargo_type || w->cargo_subtype != v->cargo_type) {
+ if (w->cargo_type != v->cargo_type || w->cargo_subtype != v->cargo_subtype) {
cost = DoCommand(0, w->index, v->cargo_type | (v->cargo_subtype << 8) | 1U << 16 , flags, GetCmdRefitVeh(v));
if (CmdSucceeded(cost)) total_cost.AddCost(cost);
}
@@ -1829,6 +1833,15 @@
if ((flags & DC_EXEC) && v->type == VEH_TRAIN) w = GetNextVehicle(w);
} while (v->type == VEH_TRAIN && (v = GetNextVehicle(v)) != NULL);
+ if (flags & DC_EXEC) {
+ /*
+ * Set the orders of the vehicle. Cannot do it earlier as we need
+ * the vehicle refitted before doing this, otherwise the moved
+ * cargo types might not match (passenger vs non-passenger)
+ */
+ DoCommand(0, (v_front->index << 16) | w_front->index, p2 & 1 ? CO_SHARE : CO_COPY, flags, CMD_CLONE_ORDER);
+ }
+
/* Since we can't estimate the cost of cloning a vehicle accurately we must
* check whether the player has enough money manually. */
if (!CheckPlayerHasMoney(total_cost)) {
@@ -2101,7 +2114,7 @@
count += v->cargo.Count();
max += v->cargo_cap;
if (v->cargo_cap != 0) {
- unloading += HASBIT(v->vehicle_flags, VF_CARGO_UNLOADING) ? 1 : 0;
+ unloading += HasBit(v->vehicle_flags, VF_CARGO_UNLOADING) ? 1 : 0;
loading |= (u->current_order.flags & OF_UNLOAD) == 0 && st->goods[v->cargo_type].days_since_pickup != 255;
cars++;
}
@@ -2188,11 +2201,11 @@
}
}
- if (HASBIT(t.flags, OFB_PART_OF_ORDERS)) {
+ if (HasBit(t.flags, OFB_PART_OF_ORDERS)) {
/* Part of orders */
UpdateVehicleTimetable(v, true);
v->cur_order_index++;
- } else if (HASBIT(t.flags, OFB_HALT_IN_DEPOT)) {
+ } else if (HasBit(t.flags, OFB_HALT_IN_DEPOT)) {
/* Force depot visit */
v->vehstatus |= VS_STOPPED;
if (v->owner == _local_player) {
@@ -2504,7 +2517,7 @@
/* Can we actually build the vehicle type? */
EngineID e;
FOR_ALL_ENGINEIDS_OF_TYPE(e, type) {
- if (HASBIT(GetEngine(e)->player_avail, _local_player)) return true;
+ if (HasBit(GetEngine(e)->player_avail, _local_player)) return true;
}
return false;
}
@@ -2556,7 +2569,7 @@
scheme = LS_FREIGHT_WAGON;
}
} else {
- bool is_mu = HASBIT(EngInfo(engine_type)->misc_flags, EF_RAIL_IS_MU);
+ bool is_mu = HasBit(EngInfo(engine_type)->misc_flags, EF_RAIL_IS_MU);
switch (rvi->engclass) {
default: NOT_REACHED();
@@ -2577,7 +2590,7 @@
case VEH_ROAD: {
const RoadVehicleInfo *rvi = RoadVehInfo(engine_type);
if (cargo_type == CT_INVALID) cargo_type = rvi->cargo_type;
- if (HASBIT(EngInfo(engine_type)->misc_flags, EF_ROAD_TRAM)) {
+ if (HasBit(EngInfo(engine_type)->misc_flags, EF_ROAD_TRAM)) {
/* Tram */
scheme = IsCargoInClass(cargo_type, CC_PASSENGERS) ? LS_PASSENGER_TRAM : LS_FREIGHT_TRAM;
} else {
@@ -2616,10 +2629,13 @@
static SpriteID GetEngineColourMap(EngineID engine_type, PlayerID player, EngineID parent_engine_type, const Vehicle *v)
{
- SpriteID map = PAL_NONE;
+ SpriteID map = (v != NULL) ? v->colormap : PAL_NONE;
+
+ /* Return cached value if any */
+ if (map != PAL_NONE) return map;
/* Check if we should use the colour map callback */
- if (HASBIT(EngInfo(engine_type)->callbackmask, CBM_VEHICLE_COLOUR_REMAP)) {
+ if (HasBit(EngInfo(engine_type)->callbackmask, CBM_VEHICLE_COLOUR_REMAP)) {
uint16 callback = GetVehicleCallback(CBID_VEHICLE_COLOUR_MAPPING, 0, 0, engine_type, v);
/* A return value of 0xC000 is stated to "use the default two-color
* maps" which happens to be the failure action too... */
@@ -2627,11 +2643,15 @@
map = GB(callback, 0, 14);
/* If bit 14 is set, then the company colours are applied to the
* map else it's returned as-is. */
- if (!HASBIT(callback, 14)) return map;
+ if (!HasBit(callback, 14)) {
+ /* Update cache */
+ if (v != NULL) ((Vehicle*)v)->colormap = map;
+ return map;
+ }
}
}
- bool twocc = HASBIT(EngInfo(engine_type)->misc_flags, EF_USES_2CC);
+ bool twocc = HasBit(EngInfo(engine_type)->misc_flags, EF_USES_2CC);
if (map == PAL_NONE) map = twocc ? (SpriteID)SPR_2CCMAP_BASE : (SpriteID)PALETTE_RECOLOR_START;
@@ -2640,6 +2660,8 @@
map += livery->colour1;
if (twocc) map += livery->colour2 * 16;
+ /* Update cache */
+ if (v != NULL) ((Vehicle*)v)->colormap = map;
return map;
}
@@ -3092,7 +3114,7 @@
uint wait_time = max(this->current_order.wait_time - this->lateness_counter, 0);
/* Not the first call for this tick, or still loading */
- if (mode || !HASBIT(this->vehicle_flags, VF_LOADING_FINISHED) ||
+ if (mode || !HasBit(this->vehicle_flags, VF_LOADING_FINISHED) ||
(_patches.timetabling && this->current_order_time < wait_time)) return;
this->PlayLeaveStationSound();