src/vehicle.cpp
branchNewGRF_ports
changeset 6871 5a9dc001e1ad
parent 6870 ca3fd1fbe311
child 6872 1c4a4a609f85
--- 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();