diff --git a/ai.c b/ai.c index 5dacdb8c96..9930a5f73f 100644 --- a/ai.c +++ b/ai.c @@ -248,7 +248,7 @@ static int AiChooseShipToReplaceWith(Player *p, Vehicle *v) static void AiHandleGotoDepot(Player *p, int cmd) { - if ((p->ai.cur_veh->next_order & OT_MASK) != OT_GOTO_DEPOT) + if (p->ai.cur_veh->current_order.type != OT_GOTO_DEPOT) DoCommandByTile(0, p->ai.cur_veh->index, 0, DC_EXEC, cmd); if (++p->ai.state_counter <= 1387) { @@ -256,18 +256,20 @@ static void AiHandleGotoDepot(Player *p, int cmd) return; } - if ((p->ai.cur_veh->next_order&OT_MASK) == OT_GOTO_DEPOT) { - p->ai.cur_veh->next_order = OT_DUMMY; + if (p->ai.cur_veh->current_order.type == OT_GOTO_DEPOT) { + p->ai.cur_veh->current_order.type = OT_DUMMY; + p->ai.cur_veh->current_order.flags = 0; InvalidateWindow(WC_VEHICLE_VIEW, p->ai.cur_veh->index); } } static void AiRestoreVehicleOrders(Vehicle *v, BackuppedOrders *bak) { - uint16 *os = bak->order, ord; + const Order *os = bak->order; int ind = 0; - while ((ord = *os++) != 0) { - if (DoCommandByTile(0, v->index + (ind << 16), ord, DC_EXEC, CMD_INSERT_ORDER) == CMD_ERROR) + + while (os++->type != OT_NOTHING) { + if (DoCommandByTile(0, v->index + (ind << 16), PackOrder(os), DC_EXEC, CMD_INSERT_ORDER) == CMD_ERROR) break; ind++; } @@ -3519,7 +3521,7 @@ static void AiStateSellVeh(Player *p) if (v->type == VEH_Train) { if (!IsTrainDepotTile(v->tile) || v->u.rail.track != 0x80 || !(v->vehstatus&VS_STOPPED)) { - if ((v->next_order & OT_MASK) != OT_GOTO_DEPOT) + if (v->current_order.type != OT_GOTO_DEPOT) DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_TRAIN_GOTO_DEPOT); goto going_to_depot; } @@ -3529,7 +3531,7 @@ static void AiStateSellVeh(Player *p) } else if (v->type == VEH_Road) { if (!IsRoadDepotTile(v->tile) || v->u.road.state != 254 || !(v->vehstatus&VS_STOPPED)) { - if ((v->next_order & OT_MASK) != OT_GOTO_DEPOT) + if (v->current_order.type != OT_GOTO_DEPOT) DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SEND_ROADVEH_TO_DEPOT); goto going_to_depot; } @@ -3537,7 +3539,7 @@ static void AiStateSellVeh(Player *p) DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SELL_ROAD_VEH); } else if (v->type == VEH_Aircraft) { if (!IsAircraftHangarTile(v->tile) && !(v->vehstatus&VS_STOPPED)) { - if ((v->next_order & OT_MASK) != OT_GOTO_DEPOT) + if (v->current_order.type != OT_GOTO_DEPOT) DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SEND_AIRCRAFT_TO_HANGAR); goto going_to_depot; } @@ -3554,8 +3556,9 @@ going_to_depot:; if (++p->ai.state_counter <= 832) return; - if ((v->next_order&OT_MASK) == OT_GOTO_DEPOT) { - v->next_order = OT_DUMMY; + if (v->current_order.type == OT_GOTO_DEPOT) { + v->current_order.type = OT_DUMMY; + v->current_order.flags = 0; InvalidateWindow(WC_VEHICLE_VIEW, v->index); } return_to_loop:; @@ -3566,7 +3569,7 @@ static void AiStateRemoveStation(Player *p) { // Remove stations that aren't in use by any vehicle byte in_use[256], *used; - uint16 *ord; + Order *ord; Station *st; uint tile; @@ -3575,9 +3578,9 @@ static void AiStateRemoveStation(Player *p) // Get a list of all stations that are in use by a vehicle memset(in_use, 0, sizeof(in_use)); - for(ord=_order_array; ord != _ptr_to_next_order; ord++) { - if ((*ord & OT_MASK) == OT_GOTO_STATION) - in_use[*ord >> 8] = 1; + for (ord = _order_array; ord != _ptr_to_next_order; ++ord) { + if (ord->type == OT_GOTO_STATION) + in_use[ord->station] = 1; } // Go through all stations and delete those that aren't in use diff --git a/ai_new.c b/ai_new.c index a2d694d66d..5b31ef902e 100644 --- a/ai_new.c +++ b/ai_new.c @@ -497,17 +497,18 @@ static void AiNew_State_LocateRoute(Player *p) { static bool AiNew_CheckVehicleStation(Player *p, Station *st) { int count = 0; Vehicle *v; - uint16 *sched; - uint16 ord; // Also check if we don't have already a lot of busses to this city... FOR_ALL_VEHICLES(v) { if (v->owner == _current_player) { - sched = v->schedule_ptr; - while (sched != NULL && (ord=*sched++) != 0) { - if ((ord & OT_MASK) == OT_GOTO_STATION && DEREF_STATION(ord >> 8) == st) { - // This vehicle has this city in his list - count++; + const Order *sched = v->schedule_ptr; + if (sched != NULL) { + for (; sched->type != OT_NOTHING; ++sched) { + if (sched->type == OT_GOTO_STATION && + DEREF_STATION(sched->station) == st) { + // This vehicle has this city in his list + count++; + } } } } diff --git a/aircraft_cmd.c b/aircraft_cmd.c index 5da1823fbf..26ebc42117 100644 --- a/aircraft_cmd.c +++ b/aircraft_cmd.c @@ -198,7 +198,9 @@ int32 CmdBuildAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2) _new_aircraft_id = v->index; - *(v->schedule_ptr = _ptr_to_next_order++) = 0; + _ptr_to_next_order->type = OT_NOTHING; + _ptr_to_next_order->flags = 0; + v->schedule_ptr = _ptr_to_next_order++; // the AI doesn't click on a tile to build airplanes, so the below code will // never work. Therefore just assume the AI's planes always come from Hangar0 // On hold for NewAI @@ -361,11 +363,11 @@ int32 CmdSendAircraftToHangar(int x, int y, uint32 flags, uint32 p1, uint32 p2) if (!CheckOwnership(v->owner)) return CMD_ERROR; - if ((v->next_order&OT_MASK) == OT_GOTO_DEPOT) { + if (v->current_order.type == OT_GOTO_DEPOT) { if (flags & DC_EXEC) { - if (v->next_order&OF_UNLOAD) - { v->cur_order_index++; } - v->next_order = OT_DUMMY; + if (v->current_order.flags & OF_UNLOAD) v->cur_order_index++; + v->current_order.type = OT_DUMMY; + v->current_order.flags = 0; InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); } } else { @@ -376,8 +378,9 @@ int32 CmdSendAircraftToHangar(int x, int y, uint32 flags, uint32 p1, uint32 p2) return CMD_ERROR; if (flags & DC_EXEC) { - v->next_order = OF_NON_STOP | OF_FULL_LOAD | OT_GOTO_DEPOT; - v->next_order_param = v->u.air.targetairport; + v->current_order.type = OT_GOTO_DEPOT; + v->current_order.flags = OF_NON_STOP | OF_FULL_LOAD; + v->current_order.station = v->u.air.targetairport; InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); } } @@ -466,21 +469,24 @@ static void CheckIfAircraftNeedsService(Vehicle *v) if (v->vehstatus & VS_STOPPED) return; - if ((v->next_order & (OT_MASK | OF_FULL_LOAD)) == (OT_GOTO_DEPOT | OF_FULL_LOAD)) + if (v->current_order.type == OT_GOTO_DEPOT && + v->current_order.flags & OF_FULL_LOAD) return; if (_patches.gotodepot && ScheduleHasDepotOrders(v->schedule_ptr)) return; - st = DEREF_STATION(v->next_order_param); + st = DEREF_STATION(v->current_order.station); // only goto depot if the target airport has terminals (eg. it is airport) if (st->xy != 0 && st->airport_tile != 0 && GetAirport(st->airport_type)->nofterminals != 0) { // printf("targetairport = %d, st->index = %d\n", v->u.air.targetairport, st->index); // v->u.air.targetairport = st->index; - v->next_order = OF_NON_STOP | OT_GOTO_DEPOT; + v->current_order.type = OT_GOTO_DEPOT; + v->current_order.flags = OF_NON_STOP; InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); - } else if ((v->next_order & OT_MASK) == OT_GOTO_DEPOT) { - v->next_order = OT_DUMMY; + } else if (v->current_order.type == OT_GOTO_DEPOT) { + v->current_order.type = OT_DUMMY; + v->current_order.flags = 0; InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); } } @@ -552,7 +558,7 @@ static void HelicopterTickHandler(Vehicle *v) // if true, helicopter rotors do not rotate. This should only be the case if a helicopter is // loading/unloading at a terminal or stopped - if ((v->next_order&OT_MASK) == OT_LOADING || (v->vehstatus&VS_STOPPED)) { + if (v->current_order.type == OT_LOADING || (v->vehstatus & VS_STOPPED)) { if (u->cur_speed != 0) { u->cur_speed++; if (u->cur_speed >= 0x80 && u->cur_image == 0xF40) { @@ -983,15 +989,18 @@ static void HandleAircraftSmoke(Vehicle *v) static void ProcessAircraftOrder(Vehicle *v) { - uint order; + Order order; // OT_GOTO_DEPOT, OT_LOADING - if ((v->next_order & OT_MASK) >= OT_GOTO_DEPOT && (v->next_order & OT_MASK) <= OT_LOADING) { - if ((v->next_order & (OT_MASK|OF_UNLOAD)) != (OT_GOTO_DEPOT|OF_UNLOAD)) + if (v->current_order.type >= OT_GOTO_DEPOT && + v->current_order.type <= OT_LOADING) { + if (v->current_order.type != OT_GOTO_DEPOT || + !(v->current_order.flags & OF_UNLOAD)) return; } - if ((v->next_order & (OT_MASK|OF_UNLOAD|OF_FULL_LOAD)) == (OT_GOTO_DEPOT|OF_UNLOAD|OF_FULL_LOAD) && + if (v->current_order.type == OT_GOTO_DEPOT && + (v->current_order.flags & (OF_UNLOAD | OF_FULL_LOAD)) == (OF_UNLOAD | OF_FULL_LOAD) && SERVICE_INTERVAL) { v->cur_order_index++; } @@ -1001,21 +1010,23 @@ static void ProcessAircraftOrder(Vehicle *v) order = v->schedule_ptr[v->cur_order_index]; - if (order == 0) { - v->next_order = OT_NOTHING; + if (order.type == OT_NOTHING) { + v->current_order.type = OT_NOTHING; + v->current_order.flags = 0; return; } - if (order == (uint)((v->next_order | (v->next_order_param<<8)))) + if (order.type == v->current_order.type && + order.flags == v->current_order.flags && + order.station == v->current_order.station) return; - v->next_order = (byte)order; - v->next_order_param = (byte)(order >> 8); + v->current_order = order; // orders are changed in flight, ensure going to the right station - if ((order & OT_MASK) == OT_GOTO_STATION && v->u.air.state == FLYING) { + if (order.type == OT_GOTO_STATION && v->u.air.state == FLYING) { AircraftNextAirportPos_and_Order(v); - v->u.air.targetairport = order >> 8; + v->u.air.targetairport = order.station; } InvalidateVehicleOrderWidget(v); @@ -1023,11 +1034,11 @@ static void ProcessAircraftOrder(Vehicle *v) static void HandleAircraftLoading(Vehicle *v, int mode) { - if (v->next_order == OT_NOTHING) + if (v->current_order.type == OT_NOTHING) return; - if (v->next_order != OT_DUMMY) { - if ((v->next_order&OT_MASK) != OT_LOADING) + if (v->current_order.type != OT_DUMMY) { + if (v->current_order.type != OT_LOADING) return; if (mode != 0) @@ -1036,16 +1047,17 @@ static void HandleAircraftLoading(Vehicle *v, int mode) if (--v->load_unload_time_rem) return; - if (v->next_order&OF_FULL_LOAD && CanFillVehicle(v)) { + if (v->current_order.flags & OF_FULL_LOAD && CanFillVehicle(v)) { SET_EXPENSES_TYPE(EXPENSES_AIRCRAFT_INC); LoadUnloadVehicle(v); return; } { - byte b = v->next_order; - v->next_order = OT_NOTHING; - if (!(b & OF_NON_STOP)) + Order b = v->current_order; + v->current_order.type = OT_NOTHING; + v->current_order.flags = 0; + if (!(b.flags & OF_NON_STOP)) return; } } @@ -1105,9 +1117,9 @@ static void MaybeCrashAirplane(Vehicle *v) static void AircraftEntersTerminal(Vehicle *v) { Station *st; - byte old_order; + Order old_order; - if ((v->next_order & OT_MASK) == OT_GOTO_DEPOT) + if (v->current_order.type == OT_GOTO_DEPOT) return; st = DEREF_STATION(v->u.air.targetairport); @@ -1128,12 +1140,14 @@ static void AircraftEntersTerminal(Vehicle *v) 0); } - old_order = v->next_order; - v->next_order = OT_LOADING; + old_order = v->current_order; + v->current_order.type = OT_LOADING; + v->current_order.flags = 0; - if ((old_order & OT_MASK) == OT_GOTO_STATION && - v->next_order_param == v->last_station_visited) { - v->next_order = OT_LOADING | (old_order & (OF_UNLOAD|OF_FULL_LOAD)) | OF_NON_STOP; + if (old_order.type == OT_GOTO_STATION && + v->current_order.station == v->last_station_visited) { + v->current_order.flags = + (old_order.flags & (OF_FULL_LOAD | OF_UNLOAD)) | OF_NON_STOP; } SET_EXPENSES_TYPE(EXPENSES_AIRCRAFT_INC); @@ -1143,7 +1157,7 @@ static void AircraftEntersTerminal(Vehicle *v) static void AircraftEnterHangar(Vehicle *v) { - byte old_order; + Order old_order; ServiceAircraft(v); @@ -1151,15 +1165,16 @@ static void AircraftEnterHangar(Vehicle *v) TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT); - if ((v->next_order & OT_MASK) == OT_GOTO_DEPOT) { + if (v->current_order.type == OT_GOTO_DEPOT) { InvalidateWindow(WC_VEHICLE_VIEW, v->index); - old_order = v->next_order; - v->next_order = OT_NOTHING; + old_order = v->current_order; + v->current_order.type = OT_NOTHING; + v->current_order.flags = 0; - if (old_order & OF_UNLOAD) { v->cur_order_index++; } - - else if (old_order & OF_FULL_LOAD) { // force depot visit + if (old_order.flags & OF_UNLOAD) { + v->cur_order_index++; + } else if (old_order.flags & OF_FULL_LOAD) { // force depot visit v->vehstatus |= VS_STOPPED; if (v->owner == _local_player) { @@ -1192,9 +1207,9 @@ static void AircraftNextAirportPos_and_Order(Vehicle *v) Station *st; const AirportFTAClass *Airport; - if ((v->next_order&OT_MASK) == OT_GOTO_STATION || - (v->next_order&OT_MASK) == OT_GOTO_DEPOT) - v->u.air.targetairport = v->next_order_param; + if (v->current_order.type == OT_GOTO_STATION || + v->current_order.type == OT_GOTO_DEPOT) + v->u.air.targetairport = v->current_order.station; st = DEREF_STATION(v->u.air.targetairport); Airport = GetAirport(st->airport_type); @@ -1248,19 +1263,22 @@ static void AircraftEventHandler_InHangar(Vehicle *v, const AirportFTAClass *Air return; } - if ((v->next_order&OT_MASK) == OT_GOTO_DEPOT && (v->vehstatus&VS_STOPPED)) { // if we were sent to the depot, stay there - v->next_order = OT_NOTHING; + // if we were sent to the depot, stay there + if (v->current_order.type == OT_GOTO_DEPOT && (v->vehstatus & VS_STOPPED)) { + v->current_order.type = OT_NOTHING; + v->current_order.flags = 0; return; } - if ((v->next_order&OT_MASK) != OT_GOTO_STATION && (v->next_order&OT_MASK) != OT_GOTO_DEPOT) + if (v->current_order.type != OT_GOTO_STATION && + v->current_order.type != OT_GOTO_DEPOT) return; // if the block of the next position is busy, stay put if (AirportHasBlock(v, &Airport->layout[v->u.air.pos], Airport)) {return;} // We are already at the target airport, we need to find a terminal - if (v->next_order_param == v->u.air.targetairport) { + if (v->current_order.station == v->u.air.targetairport) { // FindFreeTerminal: // 1. Find a free terminal, 2. Occupy it, 3. Set the vehicle's state to that terminal if (v->subtype != 0) {if(!AirportFindFreeTerminal(v, Airport)) {return;}} // airplane @@ -1294,8 +1312,7 @@ static void AircraftEventHandler_AtTerminal(Vehicle *v, const AirportFTAClass *A return; } - // removed &0x1F - if (v->next_order == OT_NOTHING) {return;} + if (v->current_order.type == OT_NOTHING) return; // if the block of the next position is busy, stay put if (AirportHasBlock(v, &Airport->layout[v->u.air.pos], Airport)) { @@ -1305,19 +1322,20 @@ static void AircraftEventHandler_AtTerminal(Vehicle *v, const AirportFTAClass *A // airport-road is free. We either have to go to another airport, or to the hangar // ---> start moving - switch (v->next_order&OT_MASK) { + switch (v->current_order.type) { case OT_GOTO_STATION: // ready to fly to another airport // airplane goto state takeoff, helicopter to helitakeoff v->u.air.state = (v->subtype != 0) ? TAKEOFF : HELITAKEOFF; break; case OT_GOTO_DEPOT: // visit hangar for serivicing, sale, etc. - if (v->next_order_param == v->u.air.targetairport) + if (v->current_order.station == v->u.air.targetairport) v->u.air.state = HANGAR; else v->u.air.state = (v->subtype != 0) ? TAKEOFF : HELITAKEOFF; break; default: // orders have been deleted (no orders), goto depot and don't bother us - v->next_order = OT_NOTHING; + v->current_order.type = OT_NOTHING; + v->current_order.flags = 0; v->u.air.state = HANGAR; } AirportMove(v, Airport); @@ -1423,7 +1441,7 @@ static void AircraftEventHandler_EndLanding(Vehicle *v, const AirportFTAClass *A // 1. in case all terminals are busy AirportFindFreeTerminal() returns false or // 2. not going for terminal (but depot, no order), // --> get out of the way to the hangar. - if ((v->next_order&OT_MASK) == OT_GOTO_STATION) { + if (v->current_order.type == OT_GOTO_STATION) { if (AirportFindFreeTerminal(v, Airport)) {return;} } v->u.air.state = HANGAR; @@ -1442,7 +1460,7 @@ static void AircraftEventHandler_HeliEndLanding(Vehicle *v, const AirportFTAClas // --> else TAKEOFF // the reason behind this is that if an airport has a terminal, it also has a hangar. Airplanes // must go to a hangar. - if ((v->next_order&OT_MASK) == OT_GOTO_STATION) { + if (v->current_order.type == OT_GOTO_STATION) { if (AirportFindFreeHelipad(v, Airport)) {return;} } v->u.air.state = (Airport->nofterminals != 0) ? HANGAR : HELITAKEOFF; @@ -1720,7 +1738,7 @@ static void AircraftEventHandler(Vehicle *v, int loop) ProcessAircraftOrder(v); HandleAircraftLoading(v, loop); - if ((v->next_order&OT_MASK) >= OT_LOADING) + if (v->current_order.type >= OT_LOADING) return; // pass the right airport structure to the functions diff --git a/aircraft_gui.c b/aircraft_gui.c index a92e175b4c..cfe1b72383 100644 --- a/aircraft_gui.c +++ b/aircraft_gui.c @@ -547,15 +547,15 @@ static void AircraftViewWndProc(Window *w, WindowEvent *e) } else if (v->vehstatus & VS_STOPPED) { str = STR_8861_STOPPED; } else { - switch(v->next_order & OT_MASK) { + switch (v->current_order.type) { case OT_GOTO_STATION: { - SetDParam(0, v->next_order_param); + SetDParam(0, v->current_order.station); SetDParam(1, v->cur_speed * 8); str = STR_HEADING_FOR_STATION + _patches.vehicle_speed; } break; case OT_GOTO_DEPOT: { - SetDParam(0, v->next_order_param); + SetDParam(0, v->current_order.station); SetDParam(1, v->cur_speed * 8); str = STR_HEADING_FOR_HANGAR + _patches.vehicle_speed; } break; @@ -857,15 +857,15 @@ void ShowAircraftDepotWindow(uint tile) } static void DrawSmallSchedule(Vehicle *v, int x, int y) { - uint16 *sched; + const Order *sched; int sel; - uint ord; + Order ord; int i = 0; sched = v->schedule_ptr; sel = v->cur_order_index; - while ((ord=*sched++) != 0) { + while ((ord = *sched++).type != OT_NOTHING) { if (sel == 0) { _stringwidth_base = 0xE0; DoDrawString( "\xAF", x-6, y, 16); @@ -873,8 +873,8 @@ static void DrawSmallSchedule(Vehicle *v, int x, int y) { } sel--; - if ((ord & OT_MASK) == OT_GOTO_STATION) { - SetDParam(0, ord >> 8); + if (ord.type == OT_GOTO_STATION) { + SetDParam(0, ord.station); DrawString(x, y, STR_A036, 0); y += 6; diff --git a/disaster_cmd.c b/disaster_cmd.c index ed7d382db9..9e72f7c6b4 100644 --- a/disaster_cmd.c +++ b/disaster_cmd.c @@ -79,7 +79,9 @@ static void InitializeDisasterVehicle(Vehicle *v, int x, int y, byte z, byte dir v->owner = OWNER_NONE; v->vehstatus = VS_UNCLICKABLE; v->u.disaster.image_override = 0; - v->next_order = 0; + v->current_order.type = OT_NOTHING; + v->current_order.flags = 0; + v->current_order.station = 0; DisasterVehicleUpdateImage(v); VehiclePositionChanged(v); @@ -141,7 +143,7 @@ static void DisasterTick_Zeppeliner(Vehicle *v) ++v->tick_counter; - if (v->next_order < 2) { + if (v->current_order.station < 2) { if (v->tick_counter&1) return; @@ -149,23 +151,23 @@ static void DisasterTick_Zeppeliner(Vehicle *v) SetDisasterVehiclePos(v, gp.x, gp.y, v->z_pos); - if (v->next_order == 1) { + if (v->current_order.station == 1) { if (++v->age == 38) { - v->next_order = 2; + v->current_order.station = 2; v->age = 0; } if ((v->tick_counter&7)==0) { CreateEffectVehicleRel(v, 0, -17, 2, EV_SMOKE_3); } - } else if (v->next_order == 0) { + } else if (v->current_order.station == 0) { tile = v->tile; /**/ if (IS_TILETYPE(tile, MP_STATION) && IS_BYTE_INSIDE(_map5[tile], 8, 0x43) && IS_HUMAN_PLAYER(_map_owner[tile])) { - v->next_order = 1; + v->current_order.station = 1; v->age = 0; SetDParam(0, _map2[tile]); @@ -180,7 +182,7 @@ static void DisasterTick_Zeppeliner(Vehicle *v) return; } - if (v->next_order > 2) { + if (v->current_order.station > 2) { if (++v->age <= 13320) return; @@ -223,7 +225,7 @@ static void DisasterTick_Zeppeliner(Vehicle *v) EV_DEMOLISH); } } else if (v->age == 350) { - v->next_order = 3; + v->current_order.station = 3; v->age = 0; } @@ -248,7 +250,7 @@ static void DisasterTick_UFO(Vehicle *v) v->u.disaster.image_override = (++v->tick_counter & 8) ? 0xF45 : 0xF44; - if (v->next_order == 0) { + if (v->current_order.station == 0) { // fly around randomly int x = GET_TILE_X(v->dest_tile)*16; int y = GET_TILE_Y(v->dest_tile)*16; @@ -262,7 +264,7 @@ static void DisasterTick_UFO(Vehicle *v) v->dest_tile = TILE_MASK(Random()); return; } - v->next_order = 1; + v->current_order.station = 1; FOR_ALL_VEHICLES(u) { if (u->type == VEH_Road && IS_HUMAN_PLAYER(u->owner)) { @@ -336,7 +338,8 @@ static void DisasterTick_2(Vehicle *v) GetNewVehiclePosResult gp; v->tick_counter++; - v->u.disaster.image_override = (v->next_order == 1 && v->tick_counter&4) ? 0xF4F : 0; + v->u.disaster.image_override = + (v->current_order.station == 1 && v->tick_counter&4) ? 0xF4F : 0; GetNewVehiclePos(v, &gp); SetDisasterVehiclePos(v, gp.x, gp.y, v->z_pos); @@ -346,7 +349,7 @@ static void DisasterTick_2(Vehicle *v) return; } - if (v->next_order == 2) { + if (v->current_order.station == 2) { if (!(v->tick_counter&3)) { Industry *i = DEREF_INDUSTRY(v->dest_tile); int x = GET_TILE_X(i->xy)*16; @@ -360,13 +363,13 @@ static void DisasterTick_2(Vehicle *v) EV_DEMOLISH); if (++v->age >= 55) - v->next_order = 3; + v->current_order.station = 3; } - } else if (v->next_order == 1) { + } else if (v->current_order.station == 1) { if (++v->age == 112) { Industry *i; - v->next_order = 2; + v->current_order.station = 2; v->age = 0; i = DEREF_INDUSTRY(v->dest_tile); @@ -376,7 +379,7 @@ static void DisasterTick_2(Vehicle *v) AddNewsItem(STR_B002_OIL_REFINERY_EXPLOSION, NEWS_FLAGS(NM_THIN,NF_VIEWPORT|NF_TILE,NT_ACCIDENT,0), i->xy, 0); SndPlayTileFx(SND_12_EXPLOSION, i->xy); } - } else if (v->next_order == 0) { + } else if (v->current_order.station == 0) { int x,y; uint tile; int ind; @@ -394,7 +397,7 @@ static void DisasterTick_2(Vehicle *v) v->dest_tile = ind = _map2[tile]; if (DEREF_INDUSTRY(ind)->type == IT_OIL_REFINERY) { - v->next_order = 1; + v->current_order.station = 1; v->age = 0; } } @@ -406,7 +409,8 @@ static void DisasterTick_3(Vehicle *v) GetNewVehiclePosResult gp; v->tick_counter++; - v->u.disaster.image_override = (v->next_order == 1 && v->tick_counter&4) ? 0xF53 : 0; + v->u.disaster.image_override = + (v->current_order.station == 1 && v->tick_counter&4) ? 0xF53 : 0; GetNewVehiclePos(v, &gp); SetDisasterVehiclePos(v, gp.x, gp.y, v->z_pos); @@ -416,7 +420,7 @@ static void DisasterTick_3(Vehicle *v) return; } - if (v->next_order == 2) { + if (v->current_order.station == 2) { if (!(v->tick_counter&3)) { Industry *i = DEREF_INDUSTRY(v->dest_tile); int x = GET_TILE_X(i->xy)*16; @@ -430,13 +434,13 @@ static void DisasterTick_3(Vehicle *v) EV_DEMOLISH); if (++v->age >= 55) - v->next_order = 3; + v->current_order.station = 3; } - } else if (v->next_order == 1) { + } else if (v->current_order.station == 1) { if (++v->age == 112) { Industry *i; - v->next_order = 2; + v->current_order.station = 2; v->age = 0; i = DEREF_INDUSTRY(v->dest_tile); @@ -446,7 +450,7 @@ static void DisasterTick_3(Vehicle *v) AddNewsItem(STR_B003_FACTORY_DESTROYED_IN_SUSPICIOUS, NEWS_FLAGS(NM_THIN,NF_VIEWPORT|NF_TILE,NT_ACCIDENT,0), i->xy, 0); SndPlayTileFx(SND_12_EXPLOSION, i->xy); } - } else if (v->next_order == 0) { + } else if (v->current_order.station == 0) { int x,y; uint tile; int ind; @@ -464,7 +468,7 @@ static void DisasterTick_3(Vehicle *v) v->dest_tile = ind = _map2[tile]; if (DEREF_INDUSTRY(ind)->type == IT_FACTORY) { - v->next_order = 1; + v->current_order.station = 1; v->age = 0; } } @@ -496,7 +500,7 @@ static void DisasterTick_4(Vehicle *v) v->tick_counter++; - if (v->next_order == 1) { + if (v->current_order.station == 1) { int x = GET_TILE_X(v->dest_tile)*16 + 8; int y = GET_TILE_Y(v->dest_tile)*16 + 8; if (abs(v->x_pos - x) + abs(v->y_pos - y) >= 8) { @@ -513,7 +517,7 @@ static void DisasterTick_4(Vehicle *v) return; } - v->next_order = 2; + v->current_order.station = 2; FOR_ALL_VEHICLES(u) { if (u->type == VEH_Train || u->type == VEH_Road) { @@ -547,7 +551,7 @@ static void DisasterTick_4(Vehicle *v) u->next = w; InitializeDisasterVehicle(w, -6*16, v->y_pos, 0, 5, 12); w->vehstatus |= VS_DISASTER; - } else if (v->next_order < 1) { + } else if (v->current_order.station < 1) { int x = GET_TILE_X(v->dest_tile)*16; int y = GET_TILE_Y(v->dest_tile)*16; @@ -562,7 +566,7 @@ static void DisasterTick_4(Vehicle *v) v->dest_tile = TILE_MASK(Random()); return; } - v->next_order = 1; + v->current_order.station = 1; tile_org = tile = TILE_MASK(Random()); do { @@ -594,11 +598,11 @@ static void DisasterTick_4b(Vehicle *v) return; } - if (v->next_order == 0) { + if (v->current_order.station == 0) { u = &_vehicles[v->u.disaster.unk2]; if (abs(v->x_pos - u->x_pos) > 16) return; - v->next_order = 1; + v->current_order.station = 1; CreateEffectVehicleRel(u, 0, 7, 8, EV_CRASHED_SMOKE); SndPlayVehicleFx(SND_12_EXPLOSION, u); diff --git a/economy.c b/economy.c index 1e443cdc97..9fa35e5c4d 100644 --- a/economy.c +++ b/economy.c @@ -1231,7 +1231,7 @@ static bool LoadWait(const Vehicle *v, const Vehicle *u) { const Vehicle *x; bool has_any_cargo = false; - if (!(u->next_order & OF_FULL_LOAD)) return false; + if (!(u->current_order.flags & OF_FULL_LOAD)) return false; for (w = u; w != NULL; w = w->next) { if (w->cargo_count != 0) { @@ -1246,7 +1246,7 @@ static bool LoadWait(const Vehicle *v, const Vehicle *u) { if ((x->type != VEH_Train || x->subtype == 0) && // for all locs u->last_station_visited == x->last_station_visited && // at the same station !(x->vehstatus & VS_STOPPED) && // not stopped - (x->next_order & OT_MASK) == OT_LOADING && // loading + x->current_order.type == OT_LOADING && // loading u != x) { // not itself bool other_has_any_cargo = false; bool has_space_for_same_type = false; @@ -1288,7 +1288,7 @@ int LoadUnloadVehicle(Vehicle *v) byte old_player; bool completely_empty = true; - assert((v->next_order&0x1F) == OT_LOADING); + assert(v->current_order.type == OT_LOADING); v->cur_speed = 0; old_player = _current_player; @@ -1309,7 +1309,7 @@ int LoadUnloadVehicle(Vehicle *v) profit += DeliverGoods(v->cargo_count, v->cargo_type, v->cargo_source, last_visited, v->cargo_days); result |= 1; v->cargo_count = 0; - } else if (u->next_order & OF_UNLOAD) { + } else if (u->current_order.flags & OF_UNLOAD) { /* unload goods and let it wait at the station */ st->time_since_unload = 0; @@ -1335,7 +1335,7 @@ int LoadUnloadVehicle(Vehicle *v) } /* don't pick up goods that we unloaded */ - if (u->next_order & OF_UNLOAD) continue; + if (u->current_order.flags & OF_UNLOAD) continue; /* update stats */ ge->days_since_pickup = 0; diff --git a/engine.c b/engine.c index d04688724b..c184441094 100644 --- a/engine.c +++ b/engine.c @@ -314,14 +314,14 @@ ResolveVehicleSpriteGroup(struct SpriteGroup *spritegroup, struct Vehicle *veh, // TTDPatch runs on little-endian arch; // Variable is 0x80 + offset in TTD's vehicle structure switch (dsg->variable - 0x80) { -#define veh_prop(id_, value_) case id_: value = value_; break +#define veh_prop(id_, value_) case (id_): value = (value_); break veh_prop(0x00, veh->type); veh_prop(0x01, veh->subtype); veh_prop(0x04, veh->index); veh_prop(0x05, veh->index & 0xFF); /* XXX? Is THIS right? */ - veh_prop(0x0A, veh->next_order_param << 8 | veh->next_order); - veh_prop(0x0B, veh->next_order); + veh_prop(0x0A, PackOrder(&veh->current_order)); + veh_prop(0x0B, PackOrder(&veh->current_order) & 0xff); veh_prop(0x0C, veh->num_orders); veh_prop(0x0D, veh->cur_order_index); veh_prop(0x10, veh->load_unload_time_rem); diff --git a/oldloader.c b/oldloader.c index 81f3ed9b31..32e8e0abed 100644 --- a/oldloader.c +++ b/oldloader.c @@ -736,8 +736,9 @@ static void FixVehicle(Vehicle *n, OldVehicle *o, int num) assert(n->schedule_ptr >= _order_array && n->schedule_ptr < _ptr_to_next_order); } - n->next_order = o->next_order; - n->next_order_param = o->next_order_param; + n->current_order.type = o->next_order & 0x0f; + n->current_order.flags = o->next_order >> 4; + n->current_order.station = o->next_order_param; n->num_orders = o->num_orders; n->cur_order_index = o->cur_order_index; n->dest_tile = o->dest_tile; diff --git a/order_cmd.c b/order_cmd.c index ac91927cd6..e08448b186 100644 --- a/order_cmd.c +++ b/order_cmd.c @@ -15,7 +15,7 @@ int32 CmdInsertOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) { Vehicle *v = &_vehicles[p1 & 0xFFFF]; int sel = p1 >> 16; - int t; + Order new_order = UnpackOrder(p2); if (sel > v->num_orders) return_cmd_error(STR_EMPTY); if (_ptr_to_next_order == endof(_order_array)) return_cmd_error(STR_8831_NO_MORE_SPACE_FOR_ORDERS); @@ -23,21 +23,25 @@ int32 CmdInsertOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) // for ships, make sure that the station is not too far away from the previous destination. if (v->type == VEH_Ship && IS_HUMAN_PLAYER(v->owner) && - sel != 0 && ((t=v->schedule_ptr[sel-1])&OT_MASK) == OT_GOTO_STATION) { + sel != 0 && v->schedule_ptr[sel - 1].type == OT_GOTO_STATION) { - int dist = GetTileDist(DEREF_STATION(t >> 8)->xy, DEREF_STATION(p2 >> 8)->xy); + int dist = GetTileDist( + DEREF_STATION(v->schedule_ptr[sel - 1].station)->xy, + DEREF_STATION(new_order.station)->xy + ); if (dist >= 130) return_cmd_error(STR_0210_TOO_FAR_FROM_PREVIOUS_DESTINATIO); } if (flags & DC_EXEC) { - uint16 *s1, *s2; + Order *s1; + Order *s2; Vehicle *u; s1 = &v->schedule_ptr[sel]; s2 = _ptr_to_next_order++; do s2[1] = s2[0]; while (--s2 >= s1); - s1[0] = (uint16)p2; + *s1 = new_order; s1 = v->schedule_ptr; @@ -72,7 +76,9 @@ static int32 DecloneOrder(Vehicle *dst, uint32 flags) DeleteVehicleSchedule(dst); dst->num_orders = 0; - *(dst->schedule_ptr = _ptr_to_next_order++) = 0; + _ptr_to_next_order->type = OT_NOTHING; + _ptr_to_next_order->flags = 0; + dst->schedule_ptr = _ptr_to_next_order++; InvalidateWindow(WC_VEHICLE_ORDERS, dst->index); } @@ -92,9 +98,7 @@ int32 CmdDeleteOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) return DecloneOrder(v, flags); if (flags & DC_EXEC) { - uint16 *s1; - - s1 = &v->schedule_ptr[sel]; + Order *s1 = &v->schedule_ptr[sel]; // copy all orders to get rid of the hole do s1[0] = s1[1]; while (++s1 != _ptr_to_next_order); @@ -111,8 +115,11 @@ int32 CmdDeleteOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) if ((byte)sel < u->cur_order_index) u->cur_order_index--; - if ((byte)sel == u->cur_order_index && (u->next_order&(OT_MASK|OF_NON_STOP)) == (OT_LOADING|OF_NON_STOP)) - u->next_order = OT_LOADING; + if ((byte)sel == u->cur_order_index && + u->current_order.type == OT_LOADING && + u->current_order.flags & OF_NON_STOP) { + u->current_order.flags = 0; + } InvalidateWindow(WC_VEHICLE_VIEW, u->index); InvalidateWindow(WC_VEHICLE_ORDERS, u->index); @@ -139,8 +146,10 @@ int32 CmdSkipOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) v->u.rail.days_since_order_progr = 0; } - if ((v->next_order&(OT_MASK|OF_NON_STOP)) == (OT_LOADING|OF_NON_STOP)) - v->next_order = OT_LOADING; + if (v->current_order.type == OT_LOADING && + v->current_order.flags & OF_NON_STOP) { + v->current_order.flags = 0; + } InvalidateWindow(WC_VEHICLE_ORDERS, v->index); } @@ -155,29 +164,28 @@ int32 CmdModifyOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) { Vehicle *v = &_vehicles[p1]; byte sel = (byte)p2; - uint16 *sched; + Order *sched; if (sel >= v->num_orders) return CMD_ERROR; sched = &v->schedule_ptr[sel]; - if (!((*sched & OT_MASK) == OT_GOTO_STATION || - ((*sched & OT_MASK) == OT_GOTO_DEPOT && (p2>>8) != 1))) + if (sched->type != OT_GOTO_STATION && + (sched->type != OT_GOTO_DEPOT || (p2 >> 8) == 1)) return CMD_ERROR; if (flags & DC_EXEC) { - switch(p2 >> 8) { + switch (p2 >> 8) { case 0: // full load - *sched ^= OF_FULL_LOAD; - if ((*sched & OT_MASK) != OT_GOTO_DEPOT) - *sched &= ~OF_UNLOAD; + sched->flags ^= OF_FULL_LOAD; + if (sched->type != OT_GOTO_DEPOT) sched->flags &= ~OF_UNLOAD; break; case 1: // unload - *sched ^= OF_UNLOAD; - *sched &= ~OF_FULL_LOAD; + sched->flags ^= OF_UNLOAD; + sched->flags &= ~OF_FULL_LOAD; break; case 2: // non stop - *sched ^= OF_NON_STOP; + sched->flags ^= OF_NON_STOP; break; } sched = v->schedule_ptr; @@ -247,14 +255,12 @@ int32 CmdCloneOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) // let's see what happens with road vehicles if (src->type == VEH_Road) { - uint16 ord; - int i; - Station *st; + const Order *i; TileIndex required_dst; - for (i=0; (ord = src->schedule_ptr[i]) != 0; i++) { - if ( ( ord & OT_MASK ) == OT_GOTO_STATION ) { - st = DEREF_STATION(ord >> 8); + for (i = src->schedule_ptr; i->type != OT_NOTHING; ++i) { + if (i->type == OT_GOTO_STATION) { + const Station *st = DEREF_STATION(i->station); required_dst = (dst->cargo_type == CT_PASSENGERS) ? st->bus_tile : st->lorry_tile; if ( !required_dst ) return CMD_ERROR; @@ -289,7 +295,6 @@ int32 CmdCloneOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) void BackupVehicleOrders(Vehicle *v, BackuppedOrders *bak) { Vehicle *u = IsScheduleShared(v); - uint16 *sched, ord, *os; bak->orderindex = v->cur_order_index; bak->service_interval = v->service_interval; @@ -300,25 +305,24 @@ void BackupVehicleOrders(Vehicle *v, BackuppedOrders *bak) GetName(v->string_id & 0x7FF, bak->name); } - os = bak->order; // stored shared orders in this special way? - if (u) { - os[0] = 0xFFFF; - os[1] = u->index; - return; - } + if (u != NULL) { + bak->clone = u->index; + } else { + Order *sched = v->schedule_ptr; + Order *os = bak->order; - sched = v->schedule_ptr; - do { - ord = *sched++; - *os++ = ord; - } while (ord != 0); + bak->clone = INVALID_VEHICLE; + + do { + *os++ = *sched++; + } while (sched->type != OT_NOTHING); + } } void RestoreVehicleOrders(Vehicle *v, BackuppedOrders *bak) { - uint16 ord, *os; - int ind; + int i; if (bak->name[0]) { strcpy((char*)_decode_parameters, bak->name); @@ -327,9 +331,8 @@ void RestoreVehicleOrders(Vehicle *v, BackuppedOrders *bak) DoCommandP(0, v->index, bak->orderindex|(bak->service_interval<<16) , NULL, CMD_RESTORE_ORDER_INDEX); - os = bak->order; - if (os[0] == 0xFFFF) { - DoCommandP(0, v->index | os[1]<<16, 0, NULL, CMD_CLONE_ORDER); + if (bak->clone != INVALID_VEHICLE) { + DoCommandP(0, v->index | bak->clone << 16, 0, NULL, CMD_CLONE_ORDER); return; } @@ -337,12 +340,9 @@ void RestoreVehicleOrders(Vehicle *v, BackuppedOrders *bak) // order number is one more then the current amount of orders, and because // in network the commands are queued before send, the second insert always // fails in test mode. By bypassing the test-mode, that no longer is a problem. - ind = 0; - while ((ord = *os++) != 0) { - if (!DoCommandP(0, v->index + (ind << 16), ord, NULL, CMD_INSERT_ORDER | CMD_NO_TEST_IF_IN_NETWORK)) + for (i = 0; bak->order[i].type != OT_NOTHING; ++i) + if (!DoCommandP(0, v->index + (i << 16), PackOrder(&bak->order[i]), NULL, CMD_INSERT_ORDER | CMD_NO_TEST_IF_IN_NETWORK)) break; - ind++; - } } /* p1 = vehicle @@ -370,8 +370,8 @@ int CheckOrders(Vehicle *v) /* only check every 20 days, so that we don't flood the message log */ if ( ( ( v->day_counter % 20) == 0 ) && (v->owner == _local_player) ) { - - uint16 order, old_order; + Order order; + Order old_order; int i, n_st, problem_type = -1; Station *st; int message=0; @@ -381,21 +381,25 @@ int CheckOrders(Vehicle *v) order = v->schedule_ptr[0]; n_st = 0; - for (old_order = i = 0; order!=0; i++ ) { + old_order.type = OT_NOTHING; + old_order.flags = 0; + for (i = 0; order.type != OT_NOTHING; i++) { order = v->schedule_ptr[i]; - if (order == old_order) { + if (order.type == old_order.type && + order.flags == old_order.flags && + order.station == old_order.station) { problem_type = 2; break; } - if ( (order & OT_MASK) == OT_DUMMY ) { + if (order.type == OT_DUMMY) { problem_type = 1; break; } - if ( ( (order & OT_MASK) == OT_GOTO_STATION ) /*&& (order != old_order) */) { + if (order.type == OT_GOTO_STATION /*&& (order != old_order) */) { //I uncommented this in order not to get two error messages //when two identical entries are in the list n_st++; - st = DEREF_STATION(order >> 8); + st = DEREF_STATION(order.station); required_tile = GetStationTileForVehicle(v,st); if (!required_tile) problem_type = 3; } @@ -404,9 +408,11 @@ int CheckOrders(Vehicle *v) //Now, check the last and the first order //as the last order is the end of order marker, jump back 2 - if ( (v->schedule_ptr[0] == v->schedule_ptr[i-2]) && ( i-2 != 0 ) ) { + if (i > 2 && + v->schedule_ptr[0].type == v->schedule_ptr[i - 2].type && + v->schedule_ptr[0].flags == v->schedule_ptr[i - 2].flags && + v->schedule_ptr[0].station == v->schedule_ptr[i - 2].station) problem_type = 2; - } if ( (n_st < 2) && (problem_type == -1) ) problem_type = 0; diff --git a/order_gui.c b/order_gui.c index de58f33068..4f415e0870 100644 --- a/order_gui.c +++ b/order_gui.c @@ -13,14 +13,14 @@ static int OrderGetSel(Window *w) { Vehicle *v = &_vehicles[w->window_number]; - uint16 *sched = v->schedule_ptr; + const Order *sched = v->schedule_ptr; int num = WP(w,order_d).sel; int count = 0; if (num == 0) return 0; - while (*sched != 0) { + while (sched->type != OT_NOTHING) { sched++; count++; if (--num == 0) @@ -34,7 +34,8 @@ static void DrawOrdersWindow(Window *w) { Vehicle *v; int num, sel; - uint16 *sched, ord; + const Order *sched; + Order ord; int y, i; StringID str; bool shared_schedule; @@ -47,8 +48,10 @@ static void DrawOrdersWindow(Window *w) sched = v->schedule_ptr; num=0; - while (*sched != 0) - sched++,num++; + while (sched->type != OT_NOTHING) { + sched++; + num++; + } if ((uint)num + shared_schedule <= (uint)WP(w,order_d).sel) SETBIT(w->disabled_state, 5); /* delete */ @@ -61,7 +64,7 @@ static void DrawOrdersWindow(Window *w) sel = OrderGetSel(w); SetDParam(2,STR_8827_FULL_LOAD); - switch(v->schedule_ptr[sel] & 0x1F) { + switch (v->schedule_ptr[sel].type) { case OT_GOTO_STATION: break; case OT_GOTO_DEPOT: @@ -88,43 +91,43 @@ static void DrawOrdersWindow(Window *w) if ( (uint)(i - w->vscroll.pos) < 6) { - if (ord == 0) { + if (ord.type == OT_NOTHING) { str = shared_schedule ? STR_END_OF_SHARED_ORDERS : STR_882A_END_OF_ORDERS; } else { SetDParam(1, 6); - if ( (ord & OT_MASK) == OT_GOTO_STATION) { - SetDParam(1, STR_8806_GO_TO + ((ord >> 5) & 7)); - SetDParam(2, ord >> 8); - } else if ((ord & OT_MASK) == OT_GOTO_DEPOT) { + if (ord.type == OT_GOTO_STATION) { + SetDParam(1, STR_8806_GO_TO + (ord.flags >> 1)); + SetDParam(2, ord.station); + } else if (ord.type == OT_GOTO_DEPOT) { StringID s = STR_NULL; if (v->type == VEH_Aircraft) { s = STR_GO_TO_AIRPORT_HANGAR; - SetDParam(2, ord>>8); + SetDParam(2, ord.station); } else { - SetDParam(2, _depots[ord >> 8].town_index); + SetDParam(2, _depots[ord.station].town_index); switch (v->type) { case VEH_Train: s = STR_880E_GO_TO_TRAIN_DEPOT; break; case VEH_Road: s = STR_9038_GO_TO_ROADVEH_DEPOT; break; case VEH_Ship: s = STR_GO_TO_SHIP_DEPOT; break; } } - if (v->type == VEH_Train) - s += (ord>>6)&2; - SetDParam(1, s + ((ord>>6)&1) ); - } else if ((ord & OT_MASK) == OT_GOTO_WAYPOINT) { - SetDParam(2, ord >> 8); + if (v->type == VEH_Train && ord.flags & OF_NON_STOP) s += 2; + if (ord.flags & OF_FULL_LOAD) ++s; /* XXX service */ + SetDParam(1, s); + } else if (ord.type == OT_GOTO_WAYPOINT) { + SetDParam(2, ord.station); SetDParam(1, STR_GO_TO_WAYPOINT); } } { byte color = (i == WP(w,order_d).sel) ? 0xC : 0x10; SetDParam(0, i+1); - if ((ord & OT_MASK) != OT_DUMMY) { + if (ord.type != OT_DUMMY) { DrawString(2, y, str, color); } else { SetDParam(1, STR_INVALID_ORDER); - SetDParam(2, ord >> 8); + SetDParam(2, ord.station); DrawString(2, y, str, color); } } @@ -133,7 +136,7 @@ static void DrawOrdersWindow(Window *w) i++; - if (ord == 0) + if (ord.type == OT_NOTHING) break; } } @@ -288,17 +291,17 @@ static void OrdersWndProc(Window *w, WindowEvent *e) sel += w->vscroll.pos; if (_ctrl_pressed && sel < v->num_orders) { // watch out for schedule_ptr overflow - int ord = v->schedule_ptr[sel]; + Order ord = v->schedule_ptr[sel]; int xy = 0; - switch (ord & OT_MASK) { + switch (ord.type) { case OT_GOTO_STATION: /* station order */ - xy = _stations[ord >> 8].xy ; + xy = _stations[ord.station].xy ; break; case OT_GOTO_DEPOT: /* goto depot order */ - xy = _depots[ord >> 8].xy; + xy = _depots[ord.station].xy; break; case OT_GOTO_WAYPOINT: /* goto waypoint order */ - xy = _waypoints[ord >> 8].xy; + xy = _waypoints[ord.station].xy; } if (xy) @@ -352,7 +355,7 @@ static void OrdersWndProc(Window *w, WindowEvent *e) case WE_RCLICK: { Vehicle *v = &_vehicles[w->window_number]; if (e->click.widget != 8) break; - if ((v->schedule_ptr[OrderGetSel(w)] & OT_MASK) == OT_GOTO_DEPOT) + if (v->schedule_ptr[OrderGetSel(w)].type == OT_GOTO_DEPOT) GuiShowTooltips(STR_SERVICE_HINT); else GuiShowTooltips(STR_8857_MAKE_THE_HIGHLIGHTED_ORDER); diff --git a/rail_cmd.c b/rail_cmd.c index e373ac9876..4b5eb17d88 100644 --- a/rail_cmd.c +++ b/rail_cmd.c @@ -760,8 +760,12 @@ int32 CmdBuildTrainWaypoint(int x, int y, uint32 flags, uint32 p1, uint32 p2) static void DoDeleteWaypoint(Waypoint *cp) { + Order order; cp->xy = 0; - DeleteCommandFromVehicleSchedule(((cp-_waypoints) << 8) + OT_GOTO_WAYPOINT); + order.type = OT_GOTO_WAYPOINT; + order.flags = 0; + order.station = cp - _waypoints; + DeleteCommandFromVehicleSchedule(order); if (~cp->town_or_string & 0xC000) DeleteName(cp->town_or_string); RedrawWaypointSign(cp); } diff --git a/roadveh_cmd.c b/roadveh_cmd.c index 7c5d8688aa..6b39a5a114 100644 --- a/roadveh_cmd.c +++ b/roadveh_cmd.c @@ -169,7 +169,9 @@ int32 CmdBuildRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2) _new_roadveh_id = v->index; v->string_id = STR_SV_ROADVEH_NAME; - *(v->schedule_ptr = _ptr_to_next_order++) = 0; + _ptr_to_next_order->type = OT_NOTHING; + _ptr_to_next_order->flags = 0; + v->schedule_ptr = _ptr_to_next_order++; v->service_interval = _patches.servint_roadveh; @@ -300,11 +302,12 @@ int32 CmdSendRoadVehToDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2) if (v->type != VEH_Road || !CheckOwnership(v->owner)) return CMD_ERROR; - if ((v->next_order & OT_MASK) == OT_GOTO_DEPOT) { + if (v->current_order.type == OT_GOTO_DEPOT) { if (flags & DC_EXEC) { - if (v->next_order & OF_UNLOAD) + if (v->current_order.flags & OF_UNLOAD) v->cur_order_index++; - v->next_order = OT_DUMMY; + v->current_order.type = OT_DUMMY; + v->current_order.flags = 0; InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); } return 0; @@ -315,8 +318,9 @@ int32 CmdSendRoadVehToDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2) return_cmd_error(STR_9019_UNABLE_TO_FIND_LOCAL_DEPOT); if (flags & DC_EXEC) { - v->next_order = OF_NON_STOP | OF_FULL_LOAD | OT_GOTO_DEPOT; - v->next_order_param = (byte)depot; + v->current_order.type = OT_GOTO_DEPOT; + v->current_order.flags = OF_NON_STOP | OF_FULL_LOAD; + v->current_order.station = (byte)depot; v->dest_tile = _depots[depot].xy; InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); } @@ -556,16 +560,18 @@ static void HandleBrokenRoadVeh(Vehicle *v) static void ProcessRoadVehOrder(Vehicle *v) { - uint order; + Order order; Station *st; - if ((v->next_order & OT_MASK) >= OT_GOTO_DEPOT && (v->next_order & OT_MASK) <= OT_LEAVESTATION) { + if (v->current_order.type >= OT_GOTO_DEPOT && v->current_order.type <= OT_LEAVESTATION) { // Let a depot order in the schedule interrupt. - if ((v->next_order & (OT_MASK|OF_UNLOAD)) != (OT_GOTO_DEPOT|OF_UNLOAD)) + if (v->current_order.type != OT_GOTO_DEPOT || + !(v->current_order.flags & OF_UNLOAD)) return; } - if ((v->next_order & (OT_MASK|OF_UNLOAD|OF_FULL_LOAD)) == (OT_GOTO_DEPOT|OF_UNLOAD|OF_FULL_LOAD) && + if (v->current_order.type == OT_GOTO_DEPOT && + (v->current_order.flags & (OF_UNLOAD | OF_FULL_LOAD)) == (OF_UNLOAD | OF_FULL_LOAD) && SERVICE_INTERVAL ) { v->cur_order_index++; } @@ -575,27 +581,29 @@ static void ProcessRoadVehOrder(Vehicle *v) order = v->schedule_ptr[v->cur_order_index]; - if (order == 0) { - v->next_order = OT_NOTHING; + if (order.type == OT_NOTHING) { + v->current_order.type = OT_NOTHING; + v->current_order.flags = 0; v->dest_tile = 0; return; } - if (order == (uint)((v->next_order | (v->next_order_param<<8)))) + if (order.type == v->current_order.type && + order.flags == v->current_order.flags && + order.station == v->current_order.station) return; - v->next_order = (byte)order; - v->next_order_param = (byte)(order >> 8); + v->current_order = order; v->dest_tile = 0; - if ((order & OT_MASK) == OT_GOTO_STATION) { - if ( (byte)(order >> 8) == v->last_station_visited) + if (order.type == OT_GOTO_STATION) { + if (order.station == v->last_station_visited) v->last_station_visited = 0xFF; - st = DEREF_STATION(order >> 8); + st = DEREF_STATION(order.station); v->dest_tile = v->cargo_type==CT_PASSENGERS ? st->bus_tile : st->lorry_tile; - } else if ((order & OT_MASK) == OT_GOTO_DEPOT) { - v->dest_tile = _depots[order >> 8].xy; + } else if (order.type == OT_GOTO_DEPOT) { + v->dest_tile = _depots[order.station].xy; } InvalidateVehicleOrderWidget(v); @@ -603,17 +611,17 @@ static void ProcessRoadVehOrder(Vehicle *v) static void HandleRoadVehLoading(Vehicle *v) { - if (v->next_order == OT_NOTHING) + if (v->current_order.type == OT_NOTHING) return; - if (v->next_order != OT_DUMMY) { - if ((v->next_order&OT_MASK) != OT_LOADING) + if (v->current_order.type != OT_DUMMY) { + if (v->current_order.type != OT_LOADING) return; if (--v->load_unload_time_rem) return; - if (v->next_order&OF_FULL_LOAD && CanFillVehicle(v)) { + if (v->current_order.flags & OF_FULL_LOAD && CanFillVehicle(v)) { SET_EXPENSES_TYPE(EXPENSES_ROADVEH_INC); if (LoadUnloadVehicle(v)) { InvalidateWindow(WC_ROADVEH_LIST, v->owner); @@ -623,9 +631,10 @@ static void HandleRoadVehLoading(Vehicle *v) } { - byte b = v->next_order; - v->next_order = OT_LEAVESTATION; - if (!(b & OF_NON_STOP)) + Order b = v->current_order; + v->current_order.type = OT_LEAVESTATION; + v->current_order.flags = 0; + if (!(b.flags & OF_NON_STOP)) return; } } @@ -1052,7 +1061,7 @@ static const byte _roadveh_data_2[4] = { 0,1,8,9 }; static void RoadVehEventHandler(Vehicle *v) { GetNewVehiclePosResult gp; - byte new_dir,old_dir,old_order; + byte new_dir, old_dir; RoadDriveEntry rd; int x,y; Station *st; @@ -1088,7 +1097,7 @@ static void RoadVehEventHandler(Vehicle *v) ProcessRoadVehOrder(v); HandleRoadVehLoading(v); - if ((v->next_order & OT_MASK) == OT_LOADING) + if (v->current_order.type == OT_LOADING) return; if (v->u.road.state == 254) { @@ -1305,8 +1314,9 @@ again: st = DEREF_STATION(_map2[v->tile]); b = IS_BYTE_INSIDE(_map5[v->tile], 0x43, 0x47) ? &st->truck_stop_status : &st->bus_stop_status; - if ( (v->next_order&OT_MASK) != OT_LEAVESTATION && - (v->next_order&OT_MASK) != OT_GOTO_DEPOT) { + if (v->current_order.type != OT_LEAVESTATION && + v->current_order.type != OT_GOTO_DEPOT) { + Order old_order; *b &= ~0x80; @@ -1314,12 +1324,14 @@ again: RoadVehArrivesAt(v, st); - old_order = v->next_order; - v->next_order = OT_LOADING; + old_order = v->current_order; + v->current_order.type = OT_LOADING; + v->current_order.flags = 0; - if ((old_order & OT_MASK) == OT_GOTO_STATION && - v->next_order_param == v->last_station_visited) { - v->next_order = OT_LOADING | OF_NON_STOP | (old_order & (OF_FULL_LOAD|OF_UNLOAD)); + if (old_order.type == OT_GOTO_STATION && + v->current_order.station == v->last_station_visited) { + v->current_order.flags = + (old_order.flags & (OF_FULL_LOAD | OF_UNLOAD)) | OF_NON_STOP; } SET_EXPENSES_TYPE(EXPENSES_ROADVEH_INC); @@ -1331,12 +1343,13 @@ again: return; } - if ((v->next_order & OT_MASK) != OT_GOTO_DEPOT) { + if (v->current_order.type != OT_GOTO_DEPOT) { if (*b&0x80) { v->cur_speed = 0; return; } - v->next_order = 0; + v->current_order.type = OT_NOTHING; + v->current_order.flags = 0; } *b |= 0x80; @@ -1361,8 +1374,6 @@ again: void RoadVehEnterDepot(Vehicle *v) { - byte t; - v->u.road.state = 254; v->vehstatus |= VS_HIDDEN; @@ -1375,16 +1386,19 @@ void RoadVehEnterDepot(Vehicle *v) TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT); - if ((v->next_order&OT_MASK) == OT_GOTO_DEPOT) { + if (v->current_order.type == OT_GOTO_DEPOT) { + Order t; + InvalidateWindow(WC_VEHICLE_VIEW, v->index); - t = v->next_order; - v->next_order = OT_DUMMY; + t = v->current_order; + v->current_order.type = OT_DUMMY; + v->current_order.flags = 0; // Part of the schedule? - if (t & OF_UNLOAD) { v->cur_order_index++; } - - else if (t & OF_FULL_LOAD) { + if (t.flags & OF_UNLOAD) { + v->cur_order_index++; + } else if (t.flags & OF_FULL_LOAD) { v->vehstatus |= VS_STOPPED; if (v->owner == _local_player) { SetDParam(0, v->unitnumber); @@ -1432,25 +1446,29 @@ static void CheckIfRoadVehNeedsService(Vehicle *v) // Don't interfere with a depot visit scheduled by the user, or a // depot visit by the order list. - if ((v->next_order & OT_MASK) == OT_GOTO_DEPOT && - (v->next_order & (OF_FULL_LOAD|OF_UNLOAD)) != 0) + if (v->current_order.type == OT_GOTO_DEPOT && + (v->current_order.flags & (OF_FULL_LOAD | OF_UNLOAD)) != 0) return; i = FindClosestRoadDepot(v); if (i < 0 || GetTileDist(v->tile, (&_depots[i])->xy) > 12) { - if ((v->next_order & OT_MASK) == OT_GOTO_DEPOT) { - v->next_order = OT_DUMMY; + if (v->current_order.type == OT_GOTO_DEPOT) { + v->current_order.type = OT_DUMMY; + v->current_order.flags = 0; InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); } return; } - if (v->next_order == (OT_GOTO_DEPOT | OF_NON_STOP) && !CHANCE16(1,20)) + if (v->current_order.type == OT_GOTO_DEPOT && + v->current_order.flags & OF_NON_STOP && + !CHANCE16(1,20)) return; - v->next_order = OT_GOTO_DEPOT | OF_NON_STOP; - v->next_order_param = (byte)i; + v->current_order.type = OT_GOTO_DEPOT; + v->current_order.flags = OF_NON_STOP; + v->current_order.station = (byte)i; v->dest_tile = (&_depots[i])->xy; InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); } @@ -1473,8 +1491,8 @@ void OnNewDay_RoadVeh(Vehicle *v) CheckOrders(v); /* update destination */ - if ((v->next_order & OT_MASK) == OT_GOTO_STATION) { - st = DEREF_STATION(v->next_order_param); + if (v->current_order.type == OT_GOTO_STATION) { + st = DEREF_STATION(v->current_order.station); if ((tile=(v->cargo_type==CT_PASSENGERS ? st->bus_tile : st->lorry_tile)) != 0) v->dest_tile = tile; } diff --git a/roadveh_gui.c b/roadveh_gui.c index 610ebdb9f2..b86ded196d 100644 --- a/roadveh_gui.c +++ b/roadveh_gui.c @@ -204,15 +204,15 @@ static void RoadVehViewWndProc(Window *w, WindowEvent *e) } else if (v->vehstatus & VS_STOPPED) { str = STR_8861_STOPPED; } else { - switch(v->next_order & OT_MASK) { + switch (v->current_order.type) { case OT_GOTO_STATION: { - SetDParam(0, v->next_order_param); + SetDParam(0, v->current_order.station); SetDParam(1, v->cur_speed * 10 >> 5); str = STR_HEADING_FOR_STATION + _patches.vehicle_speed; } break; case OT_GOTO_DEPOT: { - Depot *dep = &_depots[v->next_order_param]; + Depot *dep = &_depots[v->current_order.station]; SetDParam(0, dep->town_index); SetDParam(1, v->cur_speed * 10 >> 5); str = STR_HEADING_FOR_ROAD_DEPOT + _patches.vehicle_speed; diff --git a/ship_cmd.c b/ship_cmd.c index 9865f746f7..7894eed6b3 100644 --- a/ship_cmd.c +++ b/ship_cmd.c @@ -95,7 +95,8 @@ static void CheckIfShipNeedsService(Vehicle *v) if (v->vehstatus & VS_STOPPED) return; - if ((v->next_order & (OT_MASK | OF_FULL_LOAD)) == (OT_GOTO_DEPOT | OF_FULL_LOAD)) + if (v->current_order.type == OT_GOTO_DEPOT && + v->current_order.flags & OF_FULL_LOAD) return; if (_patches.gotodepot && ScheduleHasDepotOrders(v->schedule_ptr)) @@ -104,15 +105,17 @@ static void CheckIfShipNeedsService(Vehicle *v) i = FindClosestShipDepot(v); if (i < 0 || GetTileDist(v->tile, (&_depots[i])->xy) > 12) { - if ((v->next_order & OT_MASK) == OT_GOTO_DEPOT) { - v->next_order = OT_DUMMY; + if (v->current_order.type == OT_GOTO_DEPOT) { + v->current_order.type = OT_DUMMY; + v->current_order.flags = 0; InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); } return; } - v->next_order = OT_GOTO_DEPOT | OF_NON_STOP; - v->next_order_param = (byte)i; + v->current_order.type = OT_GOTO_DEPOT; + v->current_order.flags = OF_NON_STOP; + v->current_order.station = (byte)i; v->dest_tile = (&_depots[i])->xy; InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); } @@ -199,15 +202,18 @@ static const TileIndexDiff _dock_offs[] = { static void ProcessShipOrder(Vehicle *v) { - uint order; + Order order; Station *st; - if ((v->next_order & OT_MASK) >= OT_GOTO_DEPOT && (v->next_order & OT_MASK) <= OT_LEAVESTATION) { - if ((v->next_order & (OT_MASK|OF_UNLOAD)) != (OT_GOTO_DEPOT|OF_UNLOAD)) + if (v->current_order.type >= OT_GOTO_DEPOT && + v->current_order.type <= OT_LEAVESTATION) { + if (v->current_order.type != OT_GOTO_DEPOT || + !(v->current_order.flags & OF_UNLOAD)) return; } - if ((v->next_order & (OT_MASK|OF_UNLOAD|OF_FULL_LOAD)) == (OT_GOTO_DEPOT|OF_UNLOAD|OF_FULL_LOAD) && + if (v->current_order.type == OT_GOTO_DEPOT && + (v->current_order.flags & (OF_UNLOAD | OF_FULL_LOAD)) == (OF_UNLOAD | OF_FULL_LOAD) && SERVICE_INTERVAL) { v->cur_order_index++; } @@ -218,28 +224,30 @@ static void ProcessShipOrder(Vehicle *v) order = v->schedule_ptr[v->cur_order_index]; - if (order == 0) { - v->next_order = OT_NOTHING; + if (order.type == OT_NOTHING) { + v->current_order.type = OT_NOTHING; + v->current_order.flags = 0; v->dest_tile = 0; return; } - if (order == (uint)((v->next_order | (v->next_order_param<<8)))) + if (order.type == v->current_order.type && + order.flags == v->current_order.flags && + order.station == v->current_order.station) return; - v->next_order = (byte)order; - v->next_order_param = (byte)(order >> 8); + v->current_order = order; - if ((order & OT_MASK) == OT_GOTO_STATION) { - if ( (byte)(order >> 8) == v->last_station_visited) + if (order.type == OT_GOTO_STATION) { + if (order.station == v->last_station_visited) v->last_station_visited = 0xFF; - st = DEREF_STATION(order >> 8); + st = DEREF_STATION(order.station); if (st->dock_tile != 0) { v->dest_tile = TILE_ADD(st->dock_tile, _dock_offs[_map5[st->dock_tile]-0x4B]); } - } else if ((order & OT_MASK) == OT_GOTO_DEPOT) { - v->dest_tile = _depots[order >> 8].xy; + } else if (order.type == OT_GOTO_DEPOT) { + v->dest_tile = _depots[order.station].xy; } else { v->dest_tile = 0; } @@ -248,17 +256,17 @@ static void ProcessShipOrder(Vehicle *v) static void HandleShipLoading(Vehicle *v) { - if (v->next_order == OT_NOTHING) + if (v->current_order.type == OT_NOTHING) return; - if (v->next_order != OT_DUMMY) { - if ((v->next_order&OT_MASK) != OT_LOADING) + if (v->current_order.type != OT_DUMMY) { + if (v->current_order.type != OT_LOADING) return; if (--v->load_unload_time_rem) return; - if (v->next_order&OF_FULL_LOAD && CanFillVehicle(v)) { + if (v->current_order.flags & OF_FULL_LOAD && CanFillVehicle(v)) { SET_EXPENSES_TYPE(EXPENSES_SHIP_INC); if (LoadUnloadVehicle(v)) { InvalidateWindow(WC_SHIPS_LIST, v->owner); @@ -269,9 +277,10 @@ static void HandleShipLoading(Vehicle *v) PlayShipSound(v); { - byte b = v->next_order; - v->next_order = OT_LEAVESTATION; - if (!(b & OF_NON_STOP)) + Order b = v->current_order; + v->current_order.type = OT_LEAVESTATION; + v->current_order.flags = 0; + if (!(b.flags & OF_NON_STOP)) return; } } @@ -380,8 +389,6 @@ static int32 EstimateShipCost(uint16 engine_type); static void ShipEnterDepot(Vehicle *v) { - byte t; - v->u.ship.state = 0x80; v->vehstatus |= VS_HIDDEN; v->cur_speed = 0; @@ -396,15 +403,18 @@ static void ShipEnterDepot(Vehicle *v) TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT); - if ((v->next_order&OT_MASK) == OT_GOTO_DEPOT) { + if (v->current_order.type == OT_GOTO_DEPOT) { + Order t; + InvalidateWindow(WC_VEHICLE_VIEW, v->index); - t = v->next_order; - v->next_order = OT_DUMMY; + t = v->current_order; + v->current_order.type = OT_DUMMY; + v->current_order.flags = 0; - if (t&OF_UNLOAD) { v->cur_order_index++; } - - else if (t & 0x40) { + if (t.flags & OF_UNLOAD) { + v->cur_order_index++; + } else if (t.flags & OF_FULL_LOAD) { v->vehstatus |= VS_STOPPED; if (v->owner == _local_player) { SetDParam(0, v->unitnumber); @@ -636,7 +646,7 @@ static void ShipController(Vehicle *v) ProcessShipOrder(v); HandleShipLoading(v); - if ((v->next_order & OT_MASK) == OT_LOADING) + if (v->current_order.type == OT_LOADING) return; CheckShipLeaveDepot(v); @@ -657,21 +667,23 @@ static void ShipController(Vehicle *v) if (r & 0x8) goto reverse_direction; if (v->dest_tile != 0 && v->dest_tile == gp.new_tile) { - if ((v->next_order & OT_MASK) == OT_GOTO_DEPOT) { + if (v->current_order.type == OT_GOTO_DEPOT) { if ((gp.x&0xF)==8 && (gp.y&0xF)==8) { ShipEnterDepot(v); return; } - } else if ((v->next_order & OT_MASK) == OT_GOTO_STATION) { + } else if (v->current_order.type == OT_GOTO_STATION) { Station *st; - v->last_station_visited = v->next_order_param; + v->last_station_visited = v->current_order.station; /* Process station in the schedule. Don't do that for buoys (HVOT_BUOY) */ - st = DEREF_STATION(v->next_order_param); + st = DEREF_STATION(v->current_order.station); if (!(st->had_vehicle_of_type & HVOT_BUOY) && (st->facilities & FACIL_DOCK)) { /* ugly, ugly workaround for problem with ships able to drop off cargo at wrong stations */ - v->next_order = (v->next_order & (OF_FULL_LOAD|OF_UNLOAD)) | OF_NON_STOP | OT_LOADING; + v->current_order.type = OT_LOADING; + v->current_order.flags &= OF_FULL_LOAD | OF_UNLOAD; + v->current_order.flags |= OF_NON_STOP; ShipArrivesAt(v, st); SET_EXPENSES_TYPE(EXPENSES_SHIP_INC); @@ -681,7 +693,8 @@ static void ShipController(Vehicle *v) } InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); } else { /* leave buoys right aways */ - v->next_order = OT_LEAVESTATION; + v->current_order.type = OT_LEAVESTATION; + v->current_order.flags = 0; v->cur_order_index++; InvalidateVehicleOrderWidget(v); } @@ -689,8 +702,9 @@ static void ShipController(Vehicle *v) } } - if (v->next_order == OT_LEAVESTATION) { - v->next_order = OT_NOTHING; + if (v->current_order.type == OT_LEAVESTATION) { + v->current_order.type = OT_NOTHING; + v->current_order.flags = 0; InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); } } @@ -843,7 +857,9 @@ int32 CmdBuildShip(int x, int y, uint32 flags, uint32 p1, uint32 p2) v->string_id = STR_SV_SHIP_NAME; v->u.ship.state = 0x80; - *(v->schedule_ptr = _ptr_to_next_order++) = 0; + _ptr_to_next_order->type = OT_NOTHING; + _ptr_to_next_order->flags = 0; + v->schedule_ptr = _ptr_to_next_order++; v->service_interval = _patches.servint_ships; v->date_of_last_service = _date; @@ -917,10 +933,11 @@ int32 CmdSendShipToDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2) if (!CheckOwnership(v->owner)) return CMD_ERROR; - if ((v->next_order&OT_MASK) == OT_GOTO_DEPOT) { + if (v->current_order.type == OT_GOTO_DEPOT) { if (flags & DC_EXEC) { - if (v->next_order&OF_UNLOAD) {v->cur_order_index++;} - v->next_order = OT_DUMMY; + if (v->current_order.flags & OF_UNLOAD) v->cur_order_index++; + v->current_order.type = OT_DUMMY; + v->current_order.flags = 0; InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); } } else { @@ -930,8 +947,9 @@ int32 CmdSendShipToDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2) if (flags & DC_EXEC) { v->dest_tile = _depots[depot].xy; - v->next_order = OF_NON_STOP | OF_FULL_LOAD | OT_GOTO_DEPOT; - v->next_order_param = depot; + v->current_order.type = OT_GOTO_DEPOT; + v->current_order.flags = OF_NON_STOP | OF_FULL_LOAD; + v->current_order.station = depot; InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); } } diff --git a/ship_gui.c b/ship_gui.c index 628aa5f3d2..f13c752ffa 100644 --- a/ship_gui.c +++ b/ship_gui.c @@ -498,15 +498,15 @@ static void ShipViewWndProc(Window *w, WindowEvent *e) { } else if (v->vehstatus & VS_STOPPED) { str = STR_8861_STOPPED; } else { - switch(v->next_order & OT_MASK) { + switch (v->current_order.type) { case OT_GOTO_STATION: { - SetDParam(0, v->next_order_param); + SetDParam(0, v->current_order.station); SetDParam(1, v->cur_speed * 10 >> 5); str = STR_HEADING_FOR_STATION + _patches.vehicle_speed; } break; case OT_GOTO_DEPOT: { - Depot *dep = &_depots[v->next_order_param]; + Depot *dep = &_depots[v->current_order.station]; SetDParam(0, dep->town_index); SetDParam(1, v->cur_speed * 10 >> 5); str = STR_HEADING_FOR_SHIP_DEPOT + _patches.vehicle_speed; @@ -836,16 +836,14 @@ void ShowShipDepotWindow(uint tile) static void DrawSmallShipSchedule(Vehicle *v, int x, int y) { - uint16 *sched; + Order *sched; int sel; - uint ord; Station *st; int i = 0; - sched = v->schedule_ptr; sel = v->cur_order_index; - while ((ord=*sched++) != 0) { + for (sched = v->schedule_ptr; sched->type != OT_NOTHING; ++sched) { if (sel == 0) { _stringwidth_base = 0xE0; DoDrawString( "\xAF", x-6, y, 16); @@ -853,11 +851,11 @@ static void DrawSmallShipSchedule(Vehicle *v, int x, int y) { } sel--; - if ((ord & OT_MASK) == OT_GOTO_STATION) { - st = DEREF_STATION(ord >> 8); + if (sched->type == OT_GOTO_STATION) { + st = DEREF_STATION(sched->station); if (!(st->had_vehicle_of_type & HVOT_BUOY)) { - SetDParam(0, ord >> 8); + SetDParam(0, sched->station); DrawString(x, y, STR_A036, 0); y += 6; diff --git a/station_cmd.c b/station_cmd.c index 420520a78e..57fa3c4ea7 100644 --- a/station_cmd.c +++ b/station_cmd.c @@ -2139,10 +2139,12 @@ static uint32 VehicleEnter_Station(Vehicle *v, uint tile, int x, int y) !IsTrainStationTile(tile + _tileoffs_by_dir[v->direction >> 1])) { station_id = _map2[tile]; - if ((!(v->next_order & OF_NON_STOP) && !_patches.new_nonstop) || - (((v->next_order & OT_MASK) == OT_GOTO_STATION && v->next_order_param == station_id))) { + if ((!(v->current_order.flags & OF_NON_STOP) && !_patches.new_nonstop) || + (v->current_order.type == OT_GOTO_STATION && v->current_order.station == station_id)) { - if (!(_patches.new_nonstop && (v->next_order & OF_NON_STOP)) && v->next_order != OT_LEAVESTATION && v->last_station_visited != station_id) { + if (!(_patches.new_nonstop && v->current_order.flags & OF_NON_STOP) && + v->current_order.type != OT_LEAVESTATION && + v->last_station_visited != station_id) { x &= 0xF; y &= 0xF; @@ -2199,6 +2201,7 @@ static uint32 VehicleEnter_Station(Vehicle *v, uint tile, int x, int y) static void DeleteStation(Station *st) { + Order order; int index; st->xy = 0; @@ -2209,7 +2212,10 @@ static void DeleteStation(Station *st) index = st->index; DeleteWindowById(WC_STATION_VIEW, index); - DeleteCommandFromVehicleSchedule((index << 8) + OT_GOTO_STATION); + order.type = OT_GOTO_STATION; + order.flags = 0; + order.station = index; + DeleteCommandFromVehicleSchedule(order); DeleteSubsidyWithStation(index); } diff --git a/train_cmd.c b/train_cmd.c index 8f9b187821..249cd1ab47 100644 --- a/train_cmd.c +++ b/train_cmd.c @@ -425,7 +425,7 @@ int32 CmdBuildRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2) // v->cargo_count = 0; v->value = value; // v->day_counter = 0; -// v->next_order = 0; +// v->current_order = 0; // v->next_station = 0; // v->load_unload_time_rem = 0; // v->progress = 0; @@ -451,7 +451,9 @@ int32 CmdBuildRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2) // v->cur_order_index = 0; // v->num_orders = 0; - *(v->schedule_ptr = _ptr_to_next_order++) = 0; + _ptr_to_next_order->type = OT_NOTHING; + _ptr_to_next_order->flags = 0; + v->schedule_ptr = _ptr_to_next_order++; // v->next_in_chain = 0xffff; // v->next = NULL; @@ -682,7 +684,9 @@ int32 CmdMoveRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2) // setting the type to 0 also involves setting up the schedule_ptr field. src->subtype = 0; assert(src->schedule_ptr == NULL); - *(src->schedule_ptr = _ptr_to_next_order++) = 0; + _ptr_to_next_order->type = OT_NOTHING; + _ptr_to_next_order->flags = 0; + src->schedule_ptr = _ptr_to_next_order++; src->num_orders = 0; } dst_head = src; @@ -1138,14 +1142,15 @@ int32 CmdTrainGotoDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2) Vehicle *v = &_vehicles[p1]; TrainFindDepotData tfdd; - if ((v->next_order & OT_MASK) == OT_GOTO_DEPOT) { + if (v->current_order.type == OT_GOTO_DEPOT) { if (flags & DC_EXEC) { - if (v->next_order & OF_UNLOAD) { + if (v->current_order.flags & OF_UNLOAD) { v->u.rail.days_since_order_progr = 0; v->cur_order_index++; } - v->next_order = OT_DUMMY; + v->current_order.type = OT_DUMMY; + v->current_order.flags = 0; InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); } return 0; @@ -1157,8 +1162,9 @@ int32 CmdTrainGotoDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2) if (flags & DC_EXEC) { v->dest_tile = tfdd.tile; - v->next_order = OF_NON_STOP | OF_FULL_LOAD | OT_GOTO_DEPOT; - v->next_order_param = GetDepotByTile(tfdd.tile); + v->current_order.type = OT_GOTO_DEPOT; + v->current_order.flags = OF_NON_STOP | OF_FULL_LOAD; + v->current_order.station = GetDepotByTile(tfdd.tile); InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); } @@ -1364,8 +1370,8 @@ static bool TrainTrackFollower(uint tile, TrainTrackFollowerData *ttfd, int trac static void FillWithStationData(TrainTrackFollowerData *fd, Vehicle *v) { fd->dest_coords = v->dest_tile; - if ((v->next_order & OT_MASK) == OT_GOTO_STATION) - fd->station_index = v->next_order_param; + if (v->current_order.type == OT_GOTO_STATION) + fd->station_index = v->current_order.station; else fd->station_index = -1; @@ -1570,29 +1576,32 @@ bad:; static bool ProcessTrainOrder(Vehicle *v) { - uint order; + Order order; bool result; // These are un-interruptible - if ((v->next_order & OT_MASK) >= OT_GOTO_DEPOT && (v->next_order & OT_MASK) <= OT_LEAVESTATION) { - + if (v->current_order.type >= OT_GOTO_DEPOT && + v->current_order.type <= OT_LEAVESTATION) { // Let a depot order in the schedule interrupt. - if ((v->next_order & (OT_MASK|OF_UNLOAD)) != (OT_GOTO_DEPOT|OF_UNLOAD)) + if (v->current_order.type != OT_GOTO_DEPOT || + !(v->current_order.flags & OF_UNLOAD)) return false; } - if ((v->next_order & (OT_MASK|OF_UNLOAD|OF_FULL_LOAD)) == (OT_GOTO_DEPOT|OF_UNLOAD|OF_FULL_LOAD) && + if (v->current_order.type == OT_GOTO_DEPOT && + (v->current_order.flags & (OF_UNLOAD | OF_FULL_LOAD)) == (OF_UNLOAD | OF_FULL_LOAD) && SERVICE_INTERVAL) { v->cur_order_index++; } // check if we've reached the waypoint? - if ((v->next_order & OT_MASK) == OT_GOTO_WAYPOINT && v->tile == v->dest_tile) { + if (v->current_order.type == OT_GOTO_WAYPOINT && v->tile == v->dest_tile) { v->cur_order_index++; } // check if we've reached a non-stop station while TTDPatch nonstop is enabled.. - if (_patches.new_nonstop && (v->next_order & OF_NON_STOP) && v->next_order_param == _map2[v->tile]) { + if (_patches.new_nonstop && v->current_order.flags & OF_NON_STOP && + v->current_order.station == _map2[v->tile]) { v->cur_order_index++; } @@ -1602,33 +1611,35 @@ static bool ProcessTrainOrder(Vehicle *v) order = v->schedule_ptr[v->cur_order_index]; // If no order, do nothing. - if (order == 0) { - v->next_order = OT_NOTHING; + if (order.type == OT_NOTHING) { + v->current_order.type = OT_NOTHING; + v->current_order.flags = 0; v->dest_tile = 0; return false; } // If it is unchanged, keep it. - if (order == (uint)((v->next_order | (v->next_order_param<<8)))) + if (order.type == v->current_order.type && + order.flags == v->current_order.flags && + order.station == v->current_order.station) return false; // Otherwise set it, and determine the destination tile. - v->next_order = (byte)order; - v->next_order_param = (byte)(order >> 8); + v->current_order = order; v->dest_tile = 0; result = false; - if ((order & OT_MASK) == OT_GOTO_STATION) { - if ( (byte)(order >> 8) == v->last_station_visited) + if (order.type == OT_GOTO_STATION) { + if (order.station == v->last_station_visited) v->last_station_visited = 0xFF; - v->dest_tile = DEREF_STATION(order >> 8)->xy; + v->dest_tile = DEREF_STATION(order.station)->xy; result = CheckReverseTrain(v); - } else if ((order & OT_MASK) == OT_GOTO_DEPOT) { - v->dest_tile = _depots[order >> 8].xy; + } else if (order.type == OT_GOTO_DEPOT) { + v->dest_tile = _depots[order.station].xy; result = CheckReverseTrain(v); - } else if ((order & OT_MASK) == OT_GOTO_WAYPOINT) { - v->dest_tile = _waypoints[order >> 8].xy; + } else if (order.type == OT_GOTO_WAYPOINT) { + v->dest_tile = _waypoints[order.station].xy; result = CheckReverseTrain(v); } @@ -1647,24 +1658,24 @@ static void MarkTrainDirty(Vehicle *v) static void HandleTrainLoading(Vehicle *v, bool mode) { - if (v->next_order == OT_NOTHING) + if (v->current_order.type == OT_NOTHING) return; - if (v->next_order != OT_DUMMY) { - if ((v->next_order&OT_MASK) != OT_LOADING) + if (v->current_order.type != OT_DUMMY) { + if (v->current_order.type != OT_LOADING) return; if (mode) return; // don't mark the train as lost if we're loading on the final station. - if (v->next_order & OF_NON_STOP) + if (v->current_order.flags & OF_NON_STOP) v->u.rail.days_since_order_progr = 0; if (--v->load_unload_time_rem) return; - if (v->next_order&OF_FULL_LOAD && CanFillVehicle(v)) { + if (v->current_order.flags & OF_FULL_LOAD && CanFillVehicle(v)) { SET_EXPENSES_TYPE(EXPENSES_TRAIN_INC); if (LoadUnloadVehicle(v)) { InvalidateWindow(WC_TRAINS_LIST, v->owner); @@ -1679,11 +1690,12 @@ static void HandleTrainLoading(Vehicle *v, bool mode) TrainPlayLeaveStationSound(v); { - byte b = v->next_order; - v->next_order = OT_LEAVESTATION; + Order b = v->current_order; + v->current_order.type = OT_LEAVESTATION; + v->current_order.flags = 0; // If this was not the final order, don't remove it from the list. - if (!(b & OF_NON_STOP)) + if (!(b.flags & OF_NON_STOP)) return; } } @@ -1739,15 +1751,19 @@ static void TrainEnterStation(Vehicle *v, int station) } // Did we reach the final destination? - if ((v->next_order&OT_MASK) == OT_GOTO_STATION && v->next_order_param == (byte)station) { + if (v->current_order.type == OT_GOTO_STATION && + v->current_order.station == (byte)station) { // Yeah, keep the load/unload flags // Non Stop now means if the order should be increased. - v->next_order = (v->next_order & (OF_FULL_LOAD|OF_UNLOAD)) | OF_NON_STOP | OT_LOADING; + v->current_order.type = OT_LOADING; + v->current_order.flags &= OF_FULL_LOAD | OF_UNLOAD; + v->current_order.flags |= OF_NON_STOP; } else { // No, just do a simple load - v->next_order = OT_LOADING; + v->current_order.type = OT_LOADING; + v->current_order.flags = 0; } - v->next_order_param = 0; + v->current_order.station = 0; SET_EXPENSES_TYPE(EXPENSES_TRAIN_INC); if (LoadUnloadVehicle(v) != 0) { @@ -2059,8 +2075,9 @@ static void TrainController(Vehicle *v) return; } - if (v->next_order == OT_LEAVESTATION) { - v->next_order = OT_NOTHING; + if (v->current_order.type == OT_LEAVESTATION) { + v->current_order.type = OT_NOTHING; + v->current_order.flags = 0; InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); } } @@ -2484,7 +2501,7 @@ static void TrainLocoHandler(Vehicle *v, bool mode) HandleTrainLoading(v, mode); - if ((v->next_order & OT_MASK) == OT_LOADING) + if (v->current_order.type == OT_LOADING) return; if (CheckTrainStayInDepot(v)) @@ -2532,8 +2549,6 @@ static const byte _depot_track_ind[4] = {0,1,0,1}; void TrainEnterDepot(Vehicle *v, uint tile) { - byte t; - SetSignalsOnBothDir(tile, _depot_track_ind[_map5[tile]&3]); if (v->subtype != 0) @@ -2551,17 +2566,19 @@ void TrainEnterDepot(Vehicle *v, uint tile) TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT); - if ((v->next_order&OT_MASK) == OT_GOTO_DEPOT) { + if (v->current_order.type == OT_GOTO_DEPOT) { + Order t; + InvalidateWindow(WC_VEHICLE_VIEW, v->index); - t = v->next_order; - v->next_order = OT_DUMMY; + t = v->current_order; + v->current_order.type = OT_DUMMY; + v->current_order.flags = 0; - // Part of the schedule? - if (t & OF_UNLOAD) { v->u.rail.days_since_order_progr = 0; v->cur_order_index++; } - - // User initiated? - else if (t & OF_FULL_LOAD) { + if (t.flags & OF_UNLOAD) { // Part of the schedule? + v->u.rail.days_since_order_progr = 0; + v->cur_order_index++; + } else if (t.flags & OF_FULL_LOAD) { // User initiated? v->vehstatus |= VS_STOPPED; if (v->owner == _local_player) { SetDParam(0, v->unitnumber); @@ -2594,18 +2611,19 @@ static void CheckIfTrainNeedsService(Vehicle *v) // Don't interfere with a depot visit scheduled by the user, or a // depot visit by the order list. - if ((v->next_order & OT_MASK) == OT_GOTO_DEPOT && - (v->next_order & (OF_FULL_LOAD|OF_UNLOAD)) != 0) + if (v->current_order.type == OT_GOTO_DEPOT && + (v->current_order.flags & (OF_FULL_LOAD | OF_UNLOAD)) != 0) return; tfdd = FindClosestTrainDepot(v); /* Only go to the depot if it is not too far out of our way. */ if (tfdd.best_length == (uint)-1 || tfdd.best_length > 16 ) { - if ((v->next_order & OT_MASK) == OT_GOTO_DEPOT) { + if (v->current_order.type == OT_GOTO_DEPOT) { /* If we were already heading for a depot but it has * suddenly moved farther away, we continue our normal * schedule? */ - v->next_order = OT_DUMMY; + v->current_order.type = OT_DUMMY; + v->current_order.flags = 0; InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); } return; @@ -2613,11 +2631,14 @@ static void CheckIfTrainNeedsService(Vehicle *v) depot = GetDepotByTile(tfdd.tile); - if ((v->next_order & OT_MASK) == OT_GOTO_DEPOT && v->next_order_param != depot && !CHANCE16(3,16)) + if (v->current_order.type == OT_GOTO_DEPOT && + v->current_order.station != depot && + !CHANCE16(3,16)) return; - v->next_order = OT_GOTO_DEPOT | OF_NON_STOP; - v->next_order_param = depot; + v->current_order.type = OT_GOTO_DEPOT; + v->current_order.flags = OF_NON_STOP; + v->current_order.station = depot; v->dest_tile = tfdd.tile; InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); } @@ -2662,8 +2683,8 @@ void OnNewDay_Train(Vehicle *v) CheckOrders(v); /* update destination */ - if ((v->next_order & OT_MASK) == OT_GOTO_STATION && - (tile=DEREF_STATION(v->next_order_param)->train_tile) != 0) + if (v->current_order.type == OT_GOTO_STATION && + (tile = DEREF_STATION(v->current_order.station)->train_tile) != 0) v->dest_tile = tile; if ((v->vehstatus & VS_STOPPED) == 0) { @@ -2719,10 +2740,10 @@ void InitializeTrains() _age_cargo_skip_counter = 1; } -int ScheduleHasDepotOrders(uint16 *schedule) +int ScheduleHasDepotOrders(const Order *schedule) { - for (;*schedule!=0;schedule++) - if ((*schedule&OT_MASK) == OT_GOTO_DEPOT) + for (; schedule->type != OT_NOTHING; schedule++) + if (schedule->type == OT_GOTO_DEPOT) return true; return false; } diff --git a/train_gui.c b/train_gui.c index 03593d3880..7e3c89113e 100644 --- a/train_gui.c +++ b/train_gui.c @@ -778,15 +778,15 @@ static void TrainViewWndProc(Window *w, WindowEvent *e) str = STR_TRAIN_STOPPING + _patches.vehicle_speed; } } else { - switch(v->next_order & OT_MASK) { + switch (v->current_order.type) { case OT_GOTO_STATION: { str = STR_HEADING_FOR_STATION + _patches.vehicle_speed; - SetDParam(0, v->next_order_param); + SetDParam(0, v->current_order.station); SetDParam(1, v->u.rail.last_speed * 10 >> 4); } break; case OT_GOTO_DEPOT: { - Depot *dep = &_depots[v->next_order_param]; + Depot *dep = &_depots[v->current_order.station]; SetDParam(0, dep->town_index); str = STR_HEADING_FOR_TRAIN_DEPOT + _patches.vehicle_speed; SetDParam(1, v->u.rail.last_speed * 10 >> 4); @@ -798,7 +798,7 @@ static void TrainViewWndProc(Window *w, WindowEvent *e) break; case OT_GOTO_WAYPOINT: { - SetDParam(0, v->next_order_param); + SetDParam(0, v->current_order.station); str = STR_HEADING_FOR_WAYPOINT + _patches.vehicle_speed; SetDParam(1, v->u.rail.last_speed * 10 >> 4); break; diff --git a/vehicle.c b/vehicle.c index e91511f6ed..191268dae4 100644 --- a/vehicle.c +++ b/vehicle.c @@ -402,7 +402,7 @@ uint GetWaypointByTile(uint tile) Vehicle *IsScheduleShared(Vehicle *u) { - uint16 *sched = u->schedule_ptr; + const Order *sched = u->schedule_ptr; Vehicle *v; FOR_ALL_VEHICLES(v) { @@ -414,7 +414,8 @@ Vehicle *IsScheduleShared(Vehicle *u) void DeleteVehicleSchedule(Vehicle *v) { - uint16 *sched, *cur; + Order *sched; + Order *cur; int num; Vehicle *u; @@ -446,32 +447,33 @@ void DeleteVehicleSchedule(Vehicle *v) } } -void DeleteCommandFromVehicleSchedule(uint cmd) +void DeleteCommandFromVehicleSchedule(Order cmd) { Vehicle *v; - uint16 *sched; - uint order; bool need_invalidate; FOR_ALL_VEHICLES(v) { if (v->type != 0 && v->schedule_ptr != NULL) { + Order *sched; // clear last station visited - if (v->last_station_visited == (cmd>>8) && (cmd & OT_MASK) == OT_GOTO_STATION) + if (v->last_station_visited == cmd.station && cmd.type == OT_GOTO_STATION) v->last_station_visited = 0xFF; // check the next order - if ( (uint)((v->next_order&OT_MASK) | (v->next_order_param<<8)) == cmd) { - v->next_order = OT_DUMMY; + if (v->current_order.type == cmd.type && + v->current_order.station == cmd.station) { + v->current_order.type = OT_DUMMY; + v->current_order.flags = 0; InvalidateWindow(WC_VEHICLE_VIEW, v->index); } // clear the order list need_invalidate = false; - sched = v->schedule_ptr; - while ((order=*sched++) != 0) { - if ( (order & (OT_MASK|0xFF00)) == cmd) { - sched[-1] = OT_DUMMY; + for (sched = v->schedule_ptr; sched->type != OT_NOTHING; ++sched) { + if (sched->type == cmd.type && sched->station == cmd.station) { + sched->type = OT_DUMMY; + sched->flags = 0; need_invalidate = true; } } @@ -484,6 +486,7 @@ void DeleteCommandFromVehicleSchedule(uint cmd) void DoDeleteDepot(uint tile) { + Order order; byte dep_index; Depot *d; @@ -494,7 +497,10 @@ void DoDeleteDepot(uint tile) for(d=_depots,dep_index=0; d->xy != (TileIndex)tile; d++) {dep_index++;} d->xy = 0; - DeleteCommandFromVehicleSchedule((dep_index << 8) + OT_GOTO_DEPOT); + order.type = OT_GOTO_DEPOT; + order.flags = 0; + order.station = dep_index; + DeleteCommandFromVehicleSchedule(order); // Delete the depot DeleteWindowById(WC_VEHICLE_DEPOT, tile); @@ -1586,8 +1592,8 @@ const byte _common_veh_desc[] = { SLE_VAR(Vehicle,cur_order_index, SLE_UINT8), SLE_VAR(Vehicle,num_orders, SLE_UINT8), - SLE_VAR(Vehicle,next_order, SLE_UINT8), - SLE_VAR(Vehicle,next_order_param, SLE_UINT8), + SLE_VAR(Vehicle,current_order, SLE_UINT8), /* XXX hack to avoid version bump */ + SLE_VAR(Vehicle,current_order.station, SLE_UINT8), SLE_REF(Vehicle,schedule_ptr, REF_SCHEDULE), SLE_VAR(Vehicle,age, SLE_UINT16), @@ -1731,7 +1737,7 @@ static const byte _disaster_desc[] = { SLE_VAR(Vehicle,z_height, SLE_UINT8), SLE_VAR(Vehicle,owner, SLE_UINT8), SLE_VAR(Vehicle,vehstatus, SLE_UINT8), - SLE_VAR(Vehicle,next_order, SLE_UINT8), + SLE_VAR(Vehicle,current_order.station, SLE_UINT8), SLE_VAR(Vehicle,cur_image, SLE_UINT16), SLE_VAR(Vehicle,age, SLE_UINT16), @@ -1858,15 +1864,31 @@ static void Load_CHKP() static void Save_ORDR() { + uint16 orders[lengthof(_order_array)]; uint len = _ptr_to_next_order - _order_array; - SlArray(_order_array, len, SLE_UINT16); + uint i; + + assert (len <= lengthof(orders)); + + for (i = 0; i < len; ++i) + orders[i] = PackOrder(&_order_array[i]); + + SlArray(orders, len, SLE_UINT16); } static void Load_ORDR() { + uint16 orders[lengthof(_order_array)]; uint len = SlGetFieldLength() >> 1; + uint i; + + assert (len <= lengthof(orders)); + _ptr_to_next_order = _order_array + len; - SlArray(_order_array, len, SLE_UINT16); + SlArray(orders, len, SLE_UINT16); + + for (i = 0; i < len; ++i) + _order_array[i] = UnpackOrder(orders[i]); } const ChunkHandler _veh_chunk_handlers[] = { diff --git a/vehicle.h b/vehicle.h index b6a9291086..596882eeb5 100644 --- a/vehicle.h +++ b/vehicle.h @@ -3,6 +3,27 @@ #include "vehicle_gui.h" +typedef struct Order { + uint8 type:4; + uint8 flags:4; + uint8 station; +} Order; + +static inline uint16 PackOrder(const Order *order) +{ + return order->station << 8 | order->flags << 4 | order->type; +} + +static inline Order UnpackOrder(uint16 packed) +{ + Order order = { + (packed & 0x000f), + (packed & 0x00f0) >> 4, + (packed & 0xff00) >> 8 + }; + return order; +} + typedef struct VehicleRail { uint16 last_speed; // NOSAVE: only used in UI uint16 crash_anim_pos; @@ -145,9 +166,8 @@ struct Vehicle { // related to the current order byte cur_order_index; byte num_orders; - byte next_order; - byte next_order_param; - uint16 *schedule_ptr; + Order current_order; + Order *schedule_ptr; // Boundaries for the current position in the world and a next hash link. // NOSAVE: All of those can be updated with VehiclePositionChanged() @@ -220,16 +240,13 @@ enum { OT_LEAVESTATION = 4, OT_DUMMY = 5, OT_GOTO_WAYPOINT = 6, - - OT_MASK = 0x1F, }; /* Order flags */ enum { - OF_UNLOAD = 0x20, - OF_FULL_LOAD = 0x40, // Also used when to force an aircraft into a depot. - OF_NON_STOP = 0x80, - OF_MASK = 0xE0, + OF_UNLOAD = 0x2, + OF_FULL_LOAD = 0x4, // Also used when to force an aircraft into a depot + OF_NON_STOP = 0x8 }; @@ -269,8 +286,9 @@ typedef void VehicleTickProc(Vehicle *v); typedef void *VehicleFromPosProc(Vehicle *v, void *data); typedef struct { + VehicleID clone; byte orderindex; - uint16 order[41]; + Order order[41]; uint16 service_interval; char name[32]; } BackuppedOrders; @@ -337,7 +355,7 @@ void CheckVehicleBreakdown(Vehicle *v); void AgeVehicle(Vehicle *v); void MaybeRenewVehicle(Vehicle *v, int32 build_cost); -void DeleteCommandFromVehicleSchedule(uint cmd); +void DeleteCommandFromVehicleSchedule(Order cmd); void BeginVehicleMove(Vehicle *v); void EndVehicleMove(Vehicle *v); @@ -361,7 +379,7 @@ int32 GetTrainRunningCost(Vehicle *v); int CheckStoppedInDepot(Vehicle *v); -int ScheduleHasDepotOrders(uint16 *schedule); +int ScheduleHasDepotOrders(const Order *schedule); int CheckOrders(Vehicle *v); typedef struct GetNewVehiclePosResult { @@ -389,8 +407,8 @@ enum { VARDEF Vehicle _vehicles[NUM_VEHICLES]; -VARDEF uint16 _order_array[5000]; -VARDEF uint16 *_ptr_to_next_order; +VARDEF Order _order_array[5000]; +VARDEF Order *_ptr_to_next_order; VARDEF Depot _depots[255];