diff -r ca3fd1fbe311 -r 5a9dc001e1ad src/vehicle.cpp --- 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();