mirror of https://github.com/OpenTTD/OpenTTD.git
(svn r1525) -Codechange: rewrote the _order_array, now it can be made dynamic.
-Codechange: renamed all 'schedule' stuff to 'order(list)' -Codechange: moved all order-stuff to order_cmd.c / order.h -Codechange: vehicles that share orders are now linked to eachother with next_shared/prev_shared in Vehicle Developers: please use AssignOrder to assign data to an order. If not, you _WILL_ make the save-routine to assert!
This commit is contained in:
parent
732c362dea
commit
d275109e79
2
ai.c
2
ai.c
|
@ -3618,7 +3618,7 @@ 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) {
|
||||
FOR_ALL_ORDERS(ord) {
|
||||
if (ord->type == OT_GOTO_STATION)
|
||||
in_use[ord->station] = 1;
|
||||
}
|
||||
|
|
14
ai_new.c
14
ai_new.c
|
@ -502,14 +502,12 @@ static bool AiNew_CheckVehicleStation(Player *p, Station *st) {
|
|||
// Also check if we don't have already a lot of busses to this city...
|
||||
FOR_ALL_VEHICLES(v) {
|
||||
if (v->owner == _current_player) {
|
||||
const Order *sched = v->schedule_ptr;
|
||||
if (sched != NULL) {
|
||||
for (; sched->type != OT_NOTHING; ++sched) {
|
||||
if (sched->type == OT_GOTO_STATION &&
|
||||
GetStation(sched->station) == st) {
|
||||
// This vehicle has this city in his list
|
||||
count++;
|
||||
}
|
||||
const Order *order;
|
||||
|
||||
FOR_VEHICLE_ORDERS(v, order) {
|
||||
if (order->type == OT_GOTO_STATION && GetStation(order->station) == st) {
|
||||
// This vehicle has this city in its list
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -126,7 +126,7 @@ int32 CmdBuildAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
|
||||
// allocate 2 or 3 vehicle structs, depending on type
|
||||
if (!AllocateVehicles(vl, (avi->subtype & 1) == 0 ? 3 : 2) ||
|
||||
_ptr_to_next_order >= endof(_order_array))
|
||||
IsOrderPoolFull())
|
||||
return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
|
||||
|
||||
unit_num = GetFreeUnitNumber(VEH_Aircraft);
|
||||
|
@ -200,9 +200,6 @@ int32 CmdBuildAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
|
||||
_new_aircraft_id = v->index;
|
||||
|
||||
_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
|
||||
|
@ -490,7 +487,7 @@ static void CheckIfAircraftNeedsService(Vehicle *v)
|
|||
v->current_order.flags & OF_FULL_LOAD)
|
||||
return;
|
||||
|
||||
if (_patches.gotodepot && ScheduleHasDepotOrders(v->schedule_ptr))
|
||||
if (_patches.gotodepot && VehicleHasDepotOrders(v))
|
||||
return;
|
||||
|
||||
st = GetStation(v->current_order.station);
|
||||
|
@ -510,13 +507,13 @@ static void CheckIfAircraftNeedsService(Vehicle *v)
|
|||
|
||||
void InvalidateAircraftWindows(const Vehicle *v)
|
||||
{
|
||||
const Order *o;
|
||||
const Order *order;
|
||||
|
||||
InvalidateWindow(WC_AIRCRAFT_LIST, v->owner);
|
||||
|
||||
for ( o = v->schedule_ptr; o->type != OT_NOTHING; o++) {
|
||||
if (o->type == OT_GOTO_STATION ) {
|
||||
InvalidateWindow(WC_AIRCRAFT_LIST, o->station << 16 | v->owner);
|
||||
FOR_VEHICLE_ORDERS(v, order) {
|
||||
if (order->type == OT_GOTO_STATION ) {
|
||||
InvalidateWindow(WC_AIRCRAFT_LIST, (order->station << 16) | v->owner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1024,21 +1021,9 @@ static void HandleAircraftSmoke(Vehicle *v)
|
|||
}
|
||||
}
|
||||
|
||||
// returns true if the vehicle does have valid orders
|
||||
// false if none are valid
|
||||
static bool CheckForValidOrders(Vehicle *v)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < v->num_orders; i++) {
|
||||
if( v->schedule_ptr[i].type != OT_DUMMY )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void ProcessAircraftOrder(Vehicle *v)
|
||||
{
|
||||
Order order;
|
||||
Order *order;
|
||||
|
||||
// OT_GOTO_DEPOT, OT_LOADING
|
||||
if (v->current_order.type == OT_GOTO_DEPOT ||
|
||||
|
@ -1057,32 +1042,32 @@ static void ProcessAircraftOrder(Vehicle *v)
|
|||
if (v->cur_order_index >= v->num_orders)
|
||||
v->cur_order_index = 0;
|
||||
|
||||
order = v->schedule_ptr[v->cur_order_index];
|
||||
order = GetVehicleOrder(v, v->cur_order_index);
|
||||
|
||||
if (order.type == OT_NOTHING) {
|
||||
if (order == NULL) {
|
||||
v->current_order.type = OT_NOTHING;
|
||||
v->current_order.flags = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( order.type == OT_DUMMY && !CheckForValidOrders(v))
|
||||
if (order->type == OT_DUMMY && !CheckForValidOrders(v))
|
||||
CrashAirplane(v);
|
||||
|
||||
if (order.type == v->current_order.type &&
|
||||
order.flags == v->current_order.flags &&
|
||||
order.station == v->current_order.station)
|
||||
if (order->type == v->current_order.type &&
|
||||
order->flags == v->current_order.flags &&
|
||||
order->station == v->current_order.station)
|
||||
return;
|
||||
|
||||
v->current_order = order;
|
||||
v->current_order = *order;
|
||||
|
||||
// orders are changed in flight, ensure going to the right station
|
||||
if (order.type == 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.station;
|
||||
v->u.air.targetairport = order->station;
|
||||
}
|
||||
|
||||
InvalidateVehicleOrderWidget(v);
|
||||
|
||||
InvalidateVehicleOrder(v);
|
||||
|
||||
InvalidateAircraftWindows(v);
|
||||
}
|
||||
|
||||
|
@ -1116,7 +1101,7 @@ static void HandleAircraftLoading(Vehicle *v, int mode)
|
|||
}
|
||||
}
|
||||
v->cur_order_index++;
|
||||
InvalidateVehicleOrderWidget(v);
|
||||
InvalidateVehicleOrder(v);
|
||||
}
|
||||
|
||||
static void CrashAirplane(Vehicle *v)
|
||||
|
|
|
@ -920,16 +920,13 @@ void ShowAircraftDepotWindow(uint tile)
|
|||
}
|
||||
}
|
||||
|
||||
static void DrawSmallSchedule(Vehicle *v, int x, int y) {
|
||||
const Order *sched;
|
||||
int sel;
|
||||
Order ord;
|
||||
int i = 0;
|
||||
static void DrawSmallOrderList(Vehicle *v, int x, int y) {
|
||||
const Order *order;
|
||||
int sel, i = 0;
|
||||
|
||||
sched = v->schedule_ptr;
|
||||
sel = v->cur_order_index;
|
||||
|
||||
while ((ord = *sched++).type != OT_NOTHING) {
|
||||
FOR_VEHICLE_ORDERS(v, order) {
|
||||
if (sel == 0) {
|
||||
_stringwidth_base = 0xE0;
|
||||
DoDrawString( "\xAF", x-6, y, 16);
|
||||
|
@ -937,8 +934,8 @@ static void DrawSmallSchedule(Vehicle *v, int x, int y) {
|
|||
}
|
||||
sel--;
|
||||
|
||||
if (ord.type == OT_GOTO_STATION) {
|
||||
SetDParam(0, ord.station);
|
||||
if (order->type == OT_GOTO_STATION) {
|
||||
SetDParam(0, order->station);
|
||||
DrawString(x, y, STR_A036, 0);
|
||||
|
||||
y += 6;
|
||||
|
@ -1052,7 +1049,7 @@ static void PlayerAircraftWndProc(Window *w, WindowEvent *e)
|
|||
DrawString(x + 19, y, STR_01AB, 0);
|
||||
}
|
||||
|
||||
DrawSmallSchedule(v, x + 136, y);
|
||||
DrawSmallOrderList(v, x + 136, y);
|
||||
|
||||
y += PLY_WND_PRC__SIZE_OF_ROW_BIG;
|
||||
}
|
||||
|
|
4
misc.c
4
misc.c
|
@ -150,6 +150,8 @@ void CSleep(int milliseconds)
|
|||
#endif
|
||||
}
|
||||
|
||||
void InitializeVehicles();
|
||||
void InitializeOrders();
|
||||
void InitializeClearLand();
|
||||
void InitializeRail();
|
||||
void InitializeRailGui();
|
||||
|
@ -206,7 +208,7 @@ void InitializeGame()
|
|||
}
|
||||
|
||||
InitializeVehicles();
|
||||
_backup_orders_tile = 0;
|
||||
InitializeOrders();
|
||||
|
||||
InitNewsItemStructs();
|
||||
InitializeLandscape();
|
||||
|
|
51
oldloader.c
51
oldloader.c
|
@ -752,6 +752,22 @@ static void FixDepot(Depot *n, OldDepot *o, int num)
|
|||
} while (n++,o++,--num);
|
||||
}
|
||||
|
||||
static void FixOrder(uint16 *o, int num)
|
||||
{
|
||||
Order *order;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num; ++i) {
|
||||
order = GetOrder(i);
|
||||
AssignOrder(order, UnpackOldOrder(*o));
|
||||
/* Recover the next list */
|
||||
if (i > 0 && order->type != OT_NOTHING)
|
||||
GetOrder(i - 1)->next = order;
|
||||
|
||||
o++;
|
||||
}
|
||||
}
|
||||
|
||||
static void FixVehicle(OldVehicle *o, int num)
|
||||
{
|
||||
Vehicle *n;
|
||||
|
@ -767,10 +783,9 @@ static void FixVehicle(OldVehicle *o, int num)
|
|||
n->subtype = o->subtype;
|
||||
|
||||
if (o->schedule_ptr == 0xFFFFFFFF || o->schedule_ptr == 0) {
|
||||
n->schedule_ptr = NULL;
|
||||
n->orders = NULL;
|
||||
} else {
|
||||
n->schedule_ptr = _order_array + REMAP_ORDER_IDX(o->schedule_ptr);
|
||||
assert(n->schedule_ptr >= _order_array && n->schedule_ptr < _ptr_to_next_order);
|
||||
n->orders = GetOrder(REMAP_ORDER_IDX(o->schedule_ptr));
|
||||
}
|
||||
|
||||
n->current_order.type = o->next_order & 0x0f;
|
||||
|
@ -870,6 +885,31 @@ static void FixVehicle(OldVehicle *o, int num)
|
|||
break;
|
||||
}
|
||||
} while (i++,o++,--num);
|
||||
|
||||
/* Check for shared orders, and link them correctly */
|
||||
{
|
||||
Vehicle *v;
|
||||
|
||||
FOR_ALL_VEHICLES(v) {
|
||||
Vehicle *u;
|
||||
|
||||
if (v->type == 0)
|
||||
continue;
|
||||
|
||||
FOR_ALL_VEHICLES_FROM(u, v->index + 1) {
|
||||
if (u->type == 0)
|
||||
continue;
|
||||
|
||||
/* If a vehicle has the same orders, add the link to eachother
|
||||
in both vehicles */
|
||||
if (v->orders == u->orders) {
|
||||
v->next_shared = u;
|
||||
u->prev_shared = v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void FixSubsidy(Subsidy *n, OldSubsidy *o, int num)
|
||||
|
@ -1447,15 +1487,12 @@ bool LoadOldSaveGame(const char *file)
|
|||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < lengthof(m->order_list); ++i)
|
||||
_order_array[i] = UnpackOldOrder(m->order_list[i]);
|
||||
_ptr_to_next_order = _order_array + REMAP_ORDER_IDX(m->ptr_to_next_order);
|
||||
|
||||
FixTown(m->town_list, lengthof(m->town_list), m->town_name_type);
|
||||
FixIndustry(m->industries, lengthof(m->industries));
|
||||
FixStation(m->stations, lengthof(m->stations));
|
||||
|
||||
FixDepot(_depots, m->depots, lengthof(m->depots));
|
||||
FixOrder(m->order_list, lengthof(m->order_list));
|
||||
FixVehicle(m->vehicles, lengthof(m->vehicles));
|
||||
FixSubsidy(_subsidies, m->subsidies, lengthof(m->subsidies));
|
||||
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
#ifndef ORDER_H
|
||||
#define ORDER_H
|
||||
|
||||
/* Order types */
|
||||
enum {
|
||||
OT_NOTHING = 0,
|
||||
OT_GOTO_STATION = 1,
|
||||
OT_GOTO_DEPOT = 2,
|
||||
OT_LOADING = 3,
|
||||
OT_LEAVESTATION = 4,
|
||||
OT_DUMMY = 5,
|
||||
OT_GOTO_WAYPOINT = 6
|
||||
};
|
||||
|
||||
/* Order flags -- please use OFB instead OF and use HASBIT/SETBIT/CLEARBIT */
|
||||
enum {
|
||||
OF_UNLOAD = 0x2,
|
||||
OF_FULL_LOAD = 0x4, // Also used when to force an aircraft into a depot
|
||||
OF_NON_STOP = 0x8
|
||||
};
|
||||
|
||||
/* Order flags bits */
|
||||
enum {
|
||||
OFB_UNLOAD = 1,
|
||||
OFB_FULL_LOAD = 2,
|
||||
OFB_NON_STOP = 3
|
||||
};
|
||||
|
||||
/* Possible clone options */
|
||||
enum {
|
||||
CO_SHARE = 0,
|
||||
CO_COPY = 1,
|
||||
CO_UNSHARE = 2
|
||||
};
|
||||
|
||||
/* If you change this, keep in mind that it is saved on 3 places:
|
||||
- Load_ORDR, all the global orders
|
||||
- Vehicle -> current_order
|
||||
- REF_SHEDULE (all REFs are currently limited to 16 bits!!) */
|
||||
typedef struct Order {
|
||||
uint8 type;
|
||||
uint8 flags;
|
||||
uint16 station;
|
||||
|
||||
struct Order *next; //! Pointer to next order. If NULL, end of list
|
||||
|
||||
uint16 index; //! Index of the order, is not saved or anything, just for reference
|
||||
} Order;
|
||||
|
||||
typedef struct {
|
||||
VehicleID clone;
|
||||
byte orderindex;
|
||||
Order order[41];
|
||||
uint16 service_interval;
|
||||
char name[32];
|
||||
} BackuppedOrders;
|
||||
|
||||
VARDEF TileIndex _backup_orders_tile;
|
||||
VARDEF BackuppedOrders _backup_orders_data[1];
|
||||
|
||||
VARDEF Order _orders[5000];
|
||||
VARDEF uint32 _orders_size;
|
||||
|
||||
static inline Order *GetOrder(uint index)
|
||||
{
|
||||
assert(index < _orders_size);
|
||||
return &_orders[index];
|
||||
}
|
||||
|
||||
#define FOR_ALL_ORDERS_FROM(o, from) for(o = GetOrder(from); o != &_orders[_orders_size]; o++)
|
||||
#define FOR_ALL_ORDERS(o) FOR_ALL_ORDERS_FROM(o, 0)
|
||||
|
||||
#define FOR_VEHICLE_ORDERS(v, order) for (order = v->orders; order != NULL; order = order->next)
|
||||
|
||||
static inline bool HasOrderPoolFree(uint amount)
|
||||
{
|
||||
Order *order;
|
||||
|
||||
FOR_ALL_ORDERS(order)
|
||||
if (order->type == OT_NOTHING)
|
||||
if (--amount == 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool IsOrderPoolFull()
|
||||
{
|
||||
return !HasOrderPoolFree(1);
|
||||
}
|
||||
|
||||
/* Pack and unpack routines */
|
||||
|
||||
static inline uint32 PackOrder(const Order *order)
|
||||
{
|
||||
return order->station << 16 | order->flags << 8 | order->type;
|
||||
}
|
||||
|
||||
static inline Order UnpackOrder(uint32 packed)
|
||||
{
|
||||
Order order;
|
||||
order.type = (packed & 0x000000FF);
|
||||
order.flags = (packed & 0x0000FF00) >> 8;
|
||||
order.station = (packed & 0xFFFF0000) >> 16;
|
||||
order.next = NULL;
|
||||
return order;
|
||||
}
|
||||
|
||||
/* Functions */
|
||||
void BackupVehicleOrders(Vehicle *v, BackuppedOrders *order);
|
||||
void RestoreVehicleOrders(Vehicle *v, BackuppedOrders *order);
|
||||
void DeleteDestinationFromVehicleOrder(Order dest);
|
||||
void InvalidateVehicleOrder(const Vehicle *v);
|
||||
bool VehicleHasDepotOrders(const Vehicle *v);
|
||||
bool CheckOrders(const Vehicle *v);
|
||||
void DeleteVehicleOrders(Vehicle *v);
|
||||
bool IsOrderListShared(const Vehicle *v);
|
||||
void AssignOrder(Order *order, Order data);
|
||||
bool CheckForValidOrders(Vehicle *v);
|
||||
|
||||
Order UnpackVersion4Order(uint16 packed);
|
||||
Order UnpackOldOrder(uint16 packed);
|
||||
|
||||
#endif /* ORDER_H */
|
1059
order_cmd.c
1059
order_cmd.c
File diff suppressed because it is too large
Load Diff
214
order_gui.c
214
order_gui.c
|
@ -14,32 +14,23 @@
|
|||
static int OrderGetSel(Window *w)
|
||||
{
|
||||
Vehicle *v = GetVehicle(w->window_number);
|
||||
const Order *sched = v->schedule_ptr;
|
||||
int num = WP(w,order_d).sel;
|
||||
int count = 0;
|
||||
|
||||
if (num == 0)
|
||||
return 0;
|
||||
if (num < 0 || num > v->num_orders)
|
||||
return v->num_orders;
|
||||
|
||||
while (sched->type != OT_NOTHING) {
|
||||
sched++;
|
||||
count++;
|
||||
if (--num == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return count;
|
||||
return num;
|
||||
}
|
||||
|
||||
static void DrawOrdersWindow(Window *w)
|
||||
{
|
||||
Vehicle *v;
|
||||
int num, sel;
|
||||
const Order *sched;
|
||||
Order ord;
|
||||
int y, i;
|
||||
const Vehicle *v;
|
||||
const Order *order;
|
||||
StringID str;
|
||||
bool shared_schedule;
|
||||
int sel;
|
||||
int y, i;
|
||||
bool shared_orders;
|
||||
byte color;
|
||||
|
||||
v = GetVehicle(w->window_number);
|
||||
|
||||
|
@ -57,40 +48,41 @@ static void DrawOrdersWindow(Window *w)
|
|||
w->disabled_state |= 1 << 6;
|
||||
}
|
||||
|
||||
shared_schedule = IsScheduleShared(v) != NULL;
|
||||
shared_orders = IsOrderListShared(v);
|
||||
|
||||
sched = v->schedule_ptr;
|
||||
num=0;
|
||||
while (sched->type != OT_NOTHING) {
|
||||
sched++;
|
||||
num++;
|
||||
}
|
||||
|
||||
if ((uint)num + shared_schedule <= (uint)WP(w,order_d).sel)
|
||||
if ((uint)v->num_orders + shared_orders <= (uint)WP(w,order_d).sel)
|
||||
SETBIT(w->disabled_state, 5); /* delete */
|
||||
|
||||
if (num == 0)
|
||||
if (v->num_orders == 0)
|
||||
SETBIT(w->disabled_state, 4); /* skip */
|
||||
|
||||
SetVScrollCount(w, num+1);
|
||||
SetVScrollCount(w, v->num_orders + 1);
|
||||
|
||||
sel = OrderGetSel(w);
|
||||
SetDParam(2, STR_8827_FULL_LOAD);
|
||||
|
||||
SetDParam(2,STR_8827_FULL_LOAD);
|
||||
switch (v->schedule_ptr[sel].type) {
|
||||
case OT_GOTO_STATION:
|
||||
break;
|
||||
case OT_GOTO_DEPOT:
|
||||
SETBIT(w->disabled_state, 9); /* unload */
|
||||
SetDParam(2,STR_SERVICE);
|
||||
break;
|
||||
order = GetVehicleOrder(v, sel);
|
||||
|
||||
case OT_GOTO_WAYPOINT:
|
||||
SETBIT(w->disabled_state, 8); /* full load */
|
||||
SETBIT(w->disabled_state, 9); /* unload */
|
||||
break;
|
||||
if (order != NULL) {
|
||||
switch (order->type) {
|
||||
case OT_GOTO_STATION:
|
||||
break;
|
||||
case OT_GOTO_DEPOT:
|
||||
SETBIT(w->disabled_state, 9); /* unload */
|
||||
SetDParam(2,STR_SERVICE);
|
||||
break;
|
||||
|
||||
default:
|
||||
case OT_GOTO_WAYPOINT:
|
||||
SETBIT(w->disabled_state, 8); /* full load */
|
||||
SETBIT(w->disabled_state, 9); /* unload */
|
||||
break;
|
||||
|
||||
default:
|
||||
SETBIT(w->disabled_state, 6); /* nonstop */
|
||||
SETBIT(w->disabled_state, 8); /* full load */
|
||||
SETBIT(w->disabled_state, 9); /* unload */
|
||||
}
|
||||
} else {
|
||||
SETBIT(w->disabled_state, 6); /* nonstop */
|
||||
SETBIT(w->disabled_state, 8); /* full load */
|
||||
SETBIT(w->disabled_state, 9); /* unload */
|
||||
|
@ -102,61 +94,62 @@ static void DrawOrdersWindow(Window *w)
|
|||
|
||||
y = 15;
|
||||
|
||||
i = 0;
|
||||
for(;;) {
|
||||
str = ((byte)v->cur_order_index == i) ? STR_8805 : STR_8804;
|
||||
i = w->vscroll.pos;
|
||||
order = GetVehicleOrder(v, i);
|
||||
while (order != NULL) {
|
||||
str = (v->cur_order_index == i) ? STR_8805 : STR_8804;
|
||||
|
||||
ord = v->schedule_ptr[i];
|
||||
if (i - w->vscroll.pos < 6) {
|
||||
SetDParam(1, 6);
|
||||
|
||||
if ( (uint)(i - w->vscroll.pos) < 6) {
|
||||
|
||||
if (ord.type == OT_NOTHING) {
|
||||
str = shared_schedule ? STR_END_OF_SHARED_ORDERS : STR_882A_END_OF_ORDERS;
|
||||
} else {
|
||||
SetDParam(1, 6);
|
||||
|
||||
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.station);
|
||||
} else {
|
||||
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 && 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, (ord.flags & OF_NON_STOP) ? STR_GO_NON_STOP_TO_WAYPOINT : STR_GO_TO_WAYPOINT);
|
||||
}
|
||||
}
|
||||
{
|
||||
byte color = (i == WP(w,order_d).sel) ? 0xC : 0x10;
|
||||
SetDParam(0, i+1);
|
||||
if (ord.type != OT_DUMMY) {
|
||||
DrawString(2, y, str, color);
|
||||
if (order->type == OT_GOTO_STATION) {
|
||||
SetDParam(1, STR_8806_GO_TO + (order->flags >> 1));
|
||||
SetDParam(2, order->station);
|
||||
} else if (order->type == OT_GOTO_DEPOT) {
|
||||
StringID s = STR_NULL;
|
||||
if (v->type == VEH_Aircraft) {
|
||||
s = STR_GO_TO_AIRPORT_HANGAR;
|
||||
SetDParam(2, order->station);
|
||||
} else {
|
||||
SetDParam(1, STR_INVALID_ORDER);
|
||||
SetDParam(2, ord.station);
|
||||
DrawString(2, y, str, color);
|
||||
SetDParam(2, _depots[order->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 && order->flags & OF_NON_STOP)
|
||||
s += 2;
|
||||
|
||||
if (order->flags & OF_FULL_LOAD)
|
||||
s++; /* XXX service */
|
||||
|
||||
SetDParam(1, s);
|
||||
} else if (order->type == OT_GOTO_WAYPOINT) {
|
||||
SetDParam(1, (order->flags & OF_NON_STOP) ? STR_GO_NON_STOP_TO_WAYPOINT : STR_GO_TO_WAYPOINT);
|
||||
SetDParam(2, order->station);
|
||||
}
|
||||
|
||||
color = (i == WP(w,order_d).sel) ? 0xC : 0x10;
|
||||
SetDParam(0, i + 1);
|
||||
if (order->type != OT_DUMMY) {
|
||||
DrawString(2, y, str, color);
|
||||
} else {
|
||||
SetDParam(1, STR_INVALID_ORDER);
|
||||
SetDParam(2, order->station);
|
||||
DrawString(2, y, str, color);
|
||||
}
|
||||
y += 10;
|
||||
}
|
||||
|
||||
i++;
|
||||
order = order->next;
|
||||
}
|
||||
|
||||
if (ord.type == OT_NOTHING)
|
||||
break;
|
||||
if (i - w->vscroll.pos < 6) {
|
||||
str = shared_orders ? STR_END_OF_SHARED_ORDERS : STR_882A_END_OF_ORDERS;
|
||||
color = (i == WP(w,order_d).sel) ? 0xC : 0x10;
|
||||
DrawString(2, y, str, color);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -317,12 +310,6 @@ static void OrdersPlaceObj(Vehicle *v, uint tile, Window *w)
|
|||
}
|
||||
}
|
||||
|
||||
enum OrderFlags {
|
||||
FULL_LOAD = 0,
|
||||
UNLOAD = 1,
|
||||
NON_STOP = 2
|
||||
};
|
||||
|
||||
static void OrderClick_Goto(Window *w, Vehicle *v)
|
||||
{
|
||||
InvalidateWidget(w, 7);
|
||||
|
@ -337,27 +324,27 @@ static void OrderClick_Goto(Window *w, Vehicle *v)
|
|||
|
||||
static void OrderClick_FullLoad(Window *w, Vehicle *v)
|
||||
{
|
||||
DoCommandP(v->tile, v->index, OrderGetSel(w) | (FULL_LOAD << 8), NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
|
||||
DoCommandP(v->tile, v->index + (OrderGetSel(w) << 16), OFB_FULL_LOAD, NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
|
||||
}
|
||||
|
||||
static void OrderClick_Unload(Window *w, Vehicle *v)
|
||||
{
|
||||
DoCommandP(v->tile, v->index, OrderGetSel(w) | (UNLOAD << 8), NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
|
||||
}
|
||||
|
||||
static void OrderClick_Skip(Window *w, Vehicle *v)
|
||||
{
|
||||
DoCommandP(v->tile,v->index, 0, NULL, CMD_SKIP_ORDER);
|
||||
}
|
||||
|
||||
static void OrderClick_Delete(Window *w, Vehicle *v)
|
||||
{
|
||||
DoCommandP(v->tile,v->index, OrderGetSel(w), NULL, CMD_DELETE_ORDER | CMD_MSG(STR_8834_CAN_T_DELETE_THIS_ORDER));
|
||||
DoCommandP(v->tile, v->index + (OrderGetSel(w) << 16), OFB_UNLOAD, NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
|
||||
}
|
||||
|
||||
static void OrderClick_Nonstop(Window *w, Vehicle *v)
|
||||
{
|
||||
DoCommandP(v->tile, v->index, OrderGetSel(w) | (NON_STOP << 8), NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
|
||||
DoCommandP(v->tile, v->index + (OrderGetSel(w) << 16), OFB_NON_STOP, NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
|
||||
}
|
||||
|
||||
static void OrderClick_Skip(Window *w, Vehicle *v)
|
||||
{
|
||||
DoCommandP(v->tile, v->index, 0, NULL, CMD_SKIP_ORDER);
|
||||
}
|
||||
|
||||
static void OrderClick_Delete(Window *w, Vehicle *v)
|
||||
{
|
||||
DoCommandP(v->tile, v->index, OrderGetSel(w), NULL, CMD_DELETE_ORDER | CMD_MSG(STR_8834_CAN_T_DELETE_THIS_ORDER));
|
||||
}
|
||||
|
||||
typedef void OnButtonClick(Window *w, Vehicle *v);
|
||||
|
@ -399,18 +386,18 @@ static void OrdersWndProc(Window *w, WindowEvent *e)
|
|||
|
||||
sel += w->vscroll.pos;
|
||||
|
||||
if (_ctrl_pressed && sel < v->num_orders) { // watch out for schedule_ptr overflow
|
||||
Order ord = v->schedule_ptr[sel];
|
||||
if (_ctrl_pressed && sel < v->num_orders) {
|
||||
Order *ord = GetVehicleOrder(v, sel);
|
||||
int xy = 0;
|
||||
switch (ord.type) {
|
||||
switch (ord->type) {
|
||||
case OT_GOTO_STATION: /* station order */
|
||||
xy = GetStation(ord.station)->xy ;
|
||||
xy = GetStation(ord->station)->xy ;
|
||||
break;
|
||||
case OT_GOTO_DEPOT: /* goto depot order */
|
||||
xy = _depots[ord.station].xy;
|
||||
xy = _depots[ord->station].xy;
|
||||
break;
|
||||
case OT_GOTO_WAYPOINT: /* goto waypoint order */
|
||||
xy = _waypoints[ord.station].xy;
|
||||
xy = _waypoints[ord->station].xy;
|
||||
}
|
||||
|
||||
if (xy)
|
||||
|
@ -447,7 +434,6 @@ static void OrdersWndProc(Window *w, WindowEvent *e)
|
|||
case 9: /* unload button */
|
||||
OrderClick_Unload(w, v);
|
||||
break;
|
||||
|
||||
}
|
||||
} break;
|
||||
|
||||
|
@ -473,7 +459,7 @@ static void OrdersWndProc(Window *w, WindowEvent *e)
|
|||
case WE_RCLICK: {
|
||||
Vehicle *v = GetVehicle(w->window_number);
|
||||
if (e->click.widget != 8) break;
|
||||
if (v->schedule_ptr[OrderGetSel(w)].type == OT_GOTO_DEPOT)
|
||||
if (GetVehicleOrder(v, OrderGetSel(w))->type == OT_GOTO_DEPOT)
|
||||
GuiShowTooltips(STR_SERVICE_HINT);
|
||||
else
|
||||
GuiShowTooltips(STR_8857_MAKE_THE_HIGHLIGHTED_ORDER);
|
||||
|
|
|
@ -768,10 +768,11 @@ static void DoDeleteWaypoint(Waypoint *cp)
|
|||
{
|
||||
Order order;
|
||||
cp->xy = 0;
|
||||
|
||||
order.type = OT_GOTO_WAYPOINT;
|
||||
order.flags = 0;
|
||||
order.station = cp - _waypoints;
|
||||
DeleteCommandFromVehicleSchedule(order);
|
||||
DeleteDestinationFromVehicleOrder(order);
|
||||
|
||||
if (~cp->town_or_string & 0xC000) DeleteName(cp->town_or_string);
|
||||
RedrawWaypointSign(cp);
|
||||
}
|
||||
|
|
|
@ -122,7 +122,7 @@ int32 CmdBuildRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
return cost;
|
||||
|
||||
v = AllocateVehicle();
|
||||
if (v == NULL || _ptr_to_next_order >= endof(_order_array))
|
||||
if (v == NULL || IsOrderPoolFull())
|
||||
return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
|
||||
|
||||
/* find the first free roadveh id */
|
||||
|
@ -172,9 +172,6 @@ int32 CmdBuildRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
_new_roadveh_id = v->index;
|
||||
|
||||
v->string_id = STR_SV_ROADVEH_NAME;
|
||||
_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;
|
||||
|
||||
|
@ -554,11 +551,11 @@ static void HandleBrokenRoadVeh(Vehicle *v)
|
|||
|
||||
static void ProcessRoadVehOrder(Vehicle *v)
|
||||
{
|
||||
Order order;
|
||||
Station *st;
|
||||
const Order *order;
|
||||
const Station *st;
|
||||
|
||||
if (v->current_order.type >= OT_GOTO_DEPOT && v->current_order.type <= OT_LEAVESTATION) {
|
||||
// Let a depot order in the schedule interrupt.
|
||||
// Let a depot order in the orderlist interrupt.
|
||||
if (v->current_order.type != OT_GOTO_DEPOT ||
|
||||
!(v->current_order.flags & OF_UNLOAD))
|
||||
return;
|
||||
|
@ -573,34 +570,35 @@ static void ProcessRoadVehOrder(Vehicle *v)
|
|||
if (v->cur_order_index >= v->num_orders)
|
||||
v->cur_order_index = 0;
|
||||
|
||||
order = v->schedule_ptr[v->cur_order_index];
|
||||
order = GetVehicleOrder(v, v->cur_order_index);
|
||||
|
||||
if (order.type == OT_NOTHING) {
|
||||
if (order == NULL) {
|
||||
v->current_order.type = OT_NOTHING;
|
||||
v->current_order.flags = 0;
|
||||
v->dest_tile = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (order.type == v->current_order.type &&
|
||||
order.flags == v->current_order.flags &&
|
||||
order.station == v->current_order.station)
|
||||
if (order->type == v->current_order.type &&
|
||||
order->flags == v->current_order.flags &&
|
||||
order->station == v->current_order.station)
|
||||
return;
|
||||
|
||||
v->current_order = order;
|
||||
v->current_order = *order;
|
||||
|
||||
v->dest_tile = 0;
|
||||
|
||||
if (order.type == OT_GOTO_STATION) {
|
||||
if (order.station == v->last_station_visited)
|
||||
if (order->type == OT_GOTO_STATION) {
|
||||
if (order->station == v->last_station_visited)
|
||||
v->last_station_visited = 0xFFFF;
|
||||
st = GetStation(order.station);
|
||||
v->dest_tile = v->cargo_type==CT_PASSENGERS ? st->bus_tile : st->lorry_tile;
|
||||
} else if (order.type == OT_GOTO_DEPOT) {
|
||||
v->dest_tile = _depots[order.station].xy;
|
||||
|
||||
st = GetStation(order->station);
|
||||
v->dest_tile = v->cargo_type == CT_PASSENGERS ? st->bus_tile : st->lorry_tile;
|
||||
} else if (order->type == OT_GOTO_DEPOT) {
|
||||
v->dest_tile = _depots[order->station].xy;
|
||||
}
|
||||
|
||||
InvalidateVehicleOrderWidget(v);
|
||||
InvalidateVehicleOrder(v);
|
||||
}
|
||||
|
||||
static void HandleRoadVehLoading(Vehicle *v)
|
||||
|
@ -634,7 +632,7 @@ static void HandleRoadVehLoading(Vehicle *v)
|
|||
}
|
||||
|
||||
v->cur_order_index++;
|
||||
InvalidateVehicleOrderWidget(v);
|
||||
InvalidateVehicleOrder(v);
|
||||
}
|
||||
|
||||
static void StartRoadVehSound(Vehicle *v)
|
||||
|
@ -1390,7 +1388,7 @@ void RoadVehEnterDepot(Vehicle *v)
|
|||
v->current_order.type = OT_DUMMY;
|
||||
v->current_order.flags = 0;
|
||||
|
||||
// Part of the schedule?
|
||||
// Part of the orderlist?
|
||||
if (t.flags & OF_UNLOAD) {
|
||||
v->cur_order_index++;
|
||||
} else if (t.flags & OF_FULL_LOAD) {
|
||||
|
@ -1436,7 +1434,7 @@ static void CheckIfRoadVehNeedsService(Vehicle *v)
|
|||
if (v->vehstatus & VS_STOPPED)
|
||||
return;
|
||||
|
||||
if (_patches.gotodepot && ScheduleHasDepotOrders(v->schedule_ptr))
|
||||
if (_patches.gotodepot && VehicleHasDepotOrders(v))
|
||||
return;
|
||||
|
||||
// Don't interfere with a depot visit scheduled by the user, or a
|
||||
|
|
12
saveload.c
12
saveload.c
|
@ -8,7 +8,7 @@
|
|||
|
||||
enum {
|
||||
SAVEGAME_MAJOR_VERSION = 5,
|
||||
SAVEGAME_MINOR_VERSION = 1,
|
||||
SAVEGAME_MINOR_VERSION = 2,
|
||||
|
||||
SAVEGAME_LOADABLE_VERSION = (SAVEGAME_MAJOR_VERSION << 8) + SAVEGAME_MINOR_VERSION
|
||||
};
|
||||
|
@ -869,6 +869,7 @@ static void UninitWriteZlib()
|
|||
extern const ChunkHandler _misc_chunk_handlers[];
|
||||
extern const ChunkHandler _player_chunk_handlers[];
|
||||
extern const ChunkHandler _veh_chunk_handlers[];
|
||||
extern const ChunkHandler _order_chunk_handlers[];
|
||||
extern const ChunkHandler _town_chunk_handlers[];
|
||||
extern const ChunkHandler _sign_chunk_handlers[];
|
||||
extern const ChunkHandler _station_chunk_handlers[];
|
||||
|
@ -880,6 +881,7 @@ extern const ChunkHandler _animated_tile_chunk_handlers[];
|
|||
static const ChunkHandler * const _chunk_handlers[] = {
|
||||
_misc_chunk_handlers,
|
||||
_veh_chunk_handlers,
|
||||
_order_chunk_handlers,
|
||||
_industry_chunk_handlers,
|
||||
_economy_chunk_handlers,
|
||||
_engine_chunk_handlers,
|
||||
|
@ -912,9 +914,7 @@ static uint ReferenceToInt(void *v, uint t)
|
|||
case REF_VEHICLE: return ((Vehicle *)v)->index + 1;
|
||||
case REF_STATION: return ((Station *)v)->index + 1;
|
||||
case REF_TOWN: return ((Town *)v)->index + 1;
|
||||
|
||||
case REF_SCHEDULE:
|
||||
return ((byte*)v - (byte*)_order_array) / sizeof(_order_array[0]) + 1;
|
||||
case REF_ORDER: return ((Order *)v)->index + 1;
|
||||
|
||||
default:
|
||||
NOT_REACHED();
|
||||
|
@ -935,13 +935,11 @@ void *IntToReference(uint r, uint t)
|
|||
return NULL;
|
||||
|
||||
switch (t) {
|
||||
case REF_ORDER: return GetOrder(r - 1);
|
||||
case REF_VEHICLE: return GetVehicle(r - 1);
|
||||
case REF_STATION: return GetStation(r - 1);
|
||||
case REF_TOWN: return GetTown(r - 1);
|
||||
|
||||
case REF_SCHEDULE:
|
||||
return (byte*)_order_array + (r - 1) * sizeof(_order_array[0]);
|
||||
|
||||
case REF_VEHICLE_OLD: {
|
||||
/* Old vehicles were saved differently: invalid vehicle was 0xFFFF,
|
||||
and the index was not - 1.. correct for this */
|
||||
|
|
10
saveload.h
10
saveload.h
|
@ -70,11 +70,11 @@ typedef struct {
|
|||
extern SaverLoader _sl;
|
||||
|
||||
enum {
|
||||
REF_SCHEDULE = 0,
|
||||
REF_VEHICLE = 1,
|
||||
REF_STATION = 2,
|
||||
REF_TOWN = 3,
|
||||
REF_VEHICLE_OLD = 4,
|
||||
REF_ORDER = 0,
|
||||
REF_VEHICLE = 1,
|
||||
REF_STATION = 2,
|
||||
REF_TOWN = 3,
|
||||
REF_VEHICLE_OLD = 4
|
||||
};
|
||||
|
||||
|
||||
|
|
53
ship_cmd.c
53
ship_cmd.c
|
@ -23,13 +23,13 @@ static byte GetTileShipTrackStatus(uint tile) {
|
|||
|
||||
void InvalidateShipWindows(const Vehicle *v)
|
||||
{
|
||||
const Order *o;
|
||||
const Order *order;
|
||||
|
||||
InvalidateWindow(WC_SHIPS_LIST, v->owner);
|
||||
|
||||
for ( o = v->schedule_ptr; o->type != OT_NOTHING; o++) {
|
||||
if (o->type == OT_GOTO_STATION ) {
|
||||
InvalidateWindow(WC_SHIPS_LIST, o->station << 16 | v->owner);
|
||||
FOR_VEHICLE_ORDERS(v, order) {
|
||||
if (order->type == OT_GOTO_STATION ) {
|
||||
InvalidateWindow(WC_SHIPS_LIST, (order->station << 16) | v->owner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ static void CheckIfShipNeedsService(Vehicle *v)
|
|||
v->current_order.flags & OF_FULL_LOAD)
|
||||
return;
|
||||
|
||||
if (_patches.gotodepot && ScheduleHasDepotOrders(v->schedule_ptr))
|
||||
if (_patches.gotodepot && VehicleHasDepotOrders(v))
|
||||
return;
|
||||
|
||||
i = FindClosestShipDepot(v);
|
||||
|
@ -215,8 +215,7 @@ static const TileIndexDiffC _dock_offs[] = {
|
|||
|
||||
static void ProcessShipOrder(Vehicle *v)
|
||||
{
|
||||
Order order;
|
||||
Station *st;
|
||||
const Order *order;
|
||||
|
||||
if (v->current_order.type >= OT_GOTO_DEPOT &&
|
||||
v->current_order.type <= OT_LEAVESTATION) {
|
||||
|
@ -235,36 +234,39 @@ static void ProcessShipOrder(Vehicle *v)
|
|||
if (v->cur_order_index >= v->num_orders)
|
||||
v->cur_order_index = 0;
|
||||
|
||||
order = v->schedule_ptr[v->cur_order_index];
|
||||
order = GetVehicleOrder(v, v->cur_order_index);
|
||||
|
||||
if (order.type == OT_NOTHING) {
|
||||
v->current_order.type = OT_NOTHING;
|
||||
if (order == NULL) {
|
||||
v->current_order.type = OT_NOTHING;
|
||||
v->current_order.flags = 0;
|
||||
v->dest_tile = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (order.type == v->current_order.type &&
|
||||
order.flags == v->current_order.flags &&
|
||||
order.station == v->current_order.station)
|
||||
if (order->type == v->current_order.type &&
|
||||
order->flags == v->current_order.flags &&
|
||||
order->station == v->current_order.station)
|
||||
return;
|
||||
|
||||
v->current_order = order;
|
||||
v->current_order = *order;
|
||||
|
||||
if (order.type == OT_GOTO_STATION) {
|
||||
if (order.station == v->last_station_visited)
|
||||
if (order->type == OT_GOTO_STATION) {
|
||||
const Station *st;
|
||||
|
||||
if (order->station == v->last_station_visited)
|
||||
v->last_station_visited = 0xFFFF;
|
||||
|
||||
st = GetStation(order.station);
|
||||
st = GetStation(order->station);
|
||||
if (st->dock_tile != 0) {
|
||||
v->dest_tile = TILE_ADD(st->dock_tile, ToTileIndexDiff(_dock_offs[_map5[st->dock_tile]-0x4B]));
|
||||
}
|
||||
} else if (order.type == OT_GOTO_DEPOT) {
|
||||
v->dest_tile = _depots[order.station].xy;
|
||||
} else if (order->type == OT_GOTO_DEPOT) {
|
||||
v->dest_tile = _depots[order->station].xy;
|
||||
} else {
|
||||
v->dest_tile = 0;
|
||||
}
|
||||
InvalidateVehicleOrderWidget(v);
|
||||
|
||||
InvalidateVehicleOrder(v);
|
||||
|
||||
InvalidateShipWindows(v);
|
||||
}
|
||||
|
@ -301,7 +303,7 @@ static void HandleShipLoading(Vehicle *v)
|
|||
}
|
||||
|
||||
v->cur_order_index++;
|
||||
InvalidateVehicleOrderWidget(v);
|
||||
InvalidateVehicleOrder(v);
|
||||
}
|
||||
|
||||
static void UpdateShipDeltaXY(Vehicle *v, int dir)
|
||||
|
@ -692,7 +694,7 @@ static void ShipController(Vehicle *v)
|
|||
|
||||
v->last_station_visited = v->current_order.station;
|
||||
|
||||
/* Process station in the schedule. Don't do that for buoys (HVOT_BUOY) */
|
||||
/* Process station in the orderlist. Don't do that for buoys (HVOT_BUOY) */
|
||||
st = GetStation(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 */
|
||||
|
@ -711,7 +713,7 @@ static void ShipController(Vehicle *v)
|
|||
v->current_order.type = OT_LEAVESTATION;
|
||||
v->current_order.flags = 0;
|
||||
v->cur_order_index++;
|
||||
InvalidateVehicleOrderWidget(v);
|
||||
InvalidateVehicleOrder(v);
|
||||
}
|
||||
goto else_end;
|
||||
}
|
||||
|
@ -830,7 +832,7 @@ int32 CmdBuildShip(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
return value;
|
||||
|
||||
v = AllocateVehicle();
|
||||
if (v == NULL || _ptr_to_next_order >= endof(_order_array) ||
|
||||
if (v == NULL || IsOrderPoolFull() ||
|
||||
(unit_num = GetFreeUnitNumber(VEH_Ship)) > _patches.max_ships)
|
||||
return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
|
||||
|
||||
|
@ -871,9 +873,6 @@ int32 CmdBuildShip(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
|
||||
v->string_id = STR_SV_SHIP_NAME;
|
||||
v->u.ship.state = 0x80;
|
||||
_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;
|
||||
|
|
23
ship_gui.c
23
ship_gui.c
|
@ -863,15 +863,14 @@ void ShowShipDepotWindow(uint tile)
|
|||
}
|
||||
|
||||
|
||||
static void DrawSmallShipSchedule(Vehicle *v, int x, int y) {
|
||||
Order *sched;
|
||||
int sel;
|
||||
Station *st;
|
||||
int i = 0;
|
||||
static void DrawSmallOrderList(Vehicle *v, int x, int y) {
|
||||
const Order *order;
|
||||
int sel, i = 0;
|
||||
|
||||
sel = v->cur_order_index;
|
||||
order = v->orders;
|
||||
|
||||
for (sched = v->schedule_ptr; sched->type != OT_NOTHING; ++sched) {
|
||||
while (order != NULL) {
|
||||
if (sel == 0) {
|
||||
_stringwidth_base = 0xE0;
|
||||
DoDrawString( "\xAF", x-6, y, 16);
|
||||
|
@ -879,11 +878,9 @@ static void DrawSmallShipSchedule(Vehicle *v, int x, int y) {
|
|||
}
|
||||
sel--;
|
||||
|
||||
if (sched->type == OT_GOTO_STATION) {
|
||||
st = GetStation(sched->station);
|
||||
|
||||
if (!(st->had_vehicle_of_type & HVOT_BUOY)) {
|
||||
SetDParam(0, sched->station);
|
||||
if (order->type == OT_GOTO_STATION) {
|
||||
if (!(GetStation(order->station)->had_vehicle_of_type & HVOT_BUOY)) {
|
||||
SetDParam(0, order->station);
|
||||
DrawString(x, y, STR_A036, 0);
|
||||
|
||||
y += 6;
|
||||
|
@ -891,6 +888,8 @@ static void DrawSmallShipSchedule(Vehicle *v, int x, int y) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
order = order->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -998,7 +997,7 @@ static void PlayerShipsWndProc(Window *w, WindowEvent *e)
|
|||
DrawString(x + 12, y, STR_01AB, 0);
|
||||
}
|
||||
|
||||
DrawSmallShipSchedule(v, x + 138, y);
|
||||
DrawSmallOrderList(v, x + 138, y);
|
||||
|
||||
y += PLY_WND_PRC__SIZE_OF_ROW_BIG;
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ enum {
|
|||
|
||||
void ModifyStationRatingAround(TileIndex tile, byte owner, int amount, uint radius);
|
||||
|
||||
TileIndex GetStationTileForVehicle(Vehicle *v, Station *st);
|
||||
TileIndex GetStationTileForVehicle(const Vehicle *v, const Station *st);
|
||||
|
||||
void ShowStationViewWindow(int station);
|
||||
void UpdateAllStationVirtCoord();
|
||||
|
|
|
@ -94,7 +94,7 @@ static Station *GetStationAround(uint tile, int w, int h, int closest_station)
|
|||
return (closest_station == -1) ? NULL : GetStation(closest_station);
|
||||
}
|
||||
|
||||
TileIndex GetStationTileForVehicle(Vehicle *v, Station *st)
|
||||
TileIndex GetStationTileForVehicle(const Vehicle *v, const Station *st)
|
||||
{
|
||||
switch (v->type) {
|
||||
case VEH_Train: return st->train_tile;
|
||||
|
@ -2257,10 +2257,11 @@ static void DeleteStation(Station *st)
|
|||
|
||||
index = st->index;
|
||||
DeleteWindowById(WC_STATION_VIEW, index);
|
||||
|
||||
order.type = OT_GOTO_STATION;
|
||||
order.flags = 0;
|
||||
order.station = index;
|
||||
DeleteCommandFromVehicleSchedule(order);
|
||||
DeleteDestinationFromVehicleOrder(order);
|
||||
|
||||
DeleteSubsidyWithStation(index);
|
||||
}
|
||||
|
||||
|
|
98
train_cmd.c
98
train_cmd.c
|
@ -395,7 +395,7 @@ int32 CmdBuildRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
|
||||
if (!(flags & DC_QUERY_COST)) {
|
||||
v = AllocateVehicle();
|
||||
if (v == NULL || _ptr_to_next_order >= endof(_order_array))
|
||||
if (v == NULL || IsOrderPoolFull())
|
||||
return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
|
||||
|
||||
unit_num = GetFreeUnitNumber(VEH_Train);
|
||||
|
@ -417,24 +417,13 @@ int32 CmdBuildRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
v->u.rail.track = 0x80;
|
||||
v->u.rail.first_engine = 0xffff;
|
||||
v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL;
|
||||
// v->subtype = 0;
|
||||
v->spritenum = rvi->image_index;
|
||||
v->cargo_type = rvi->cargo_type;
|
||||
v->cargo_cap = rvi->capacity;
|
||||
v->max_speed = rvi->max_speed;
|
||||
// v->cargo_count = 0;
|
||||
v->value = value;
|
||||
// v->day_counter = 0;
|
||||
// v->current_order = 0;
|
||||
// v->next_station = 0;
|
||||
// v->load_unload_time_rem = 0;
|
||||
// v->progress = 0;
|
||||
// v->targetairport = 0;
|
||||
// v->crash_anim_pos = 0;
|
||||
v->last_station_visited = 0xFFFF;
|
||||
v->dest_tile = 0;
|
||||
// v->profit_last_year = 0;
|
||||
// v->profit_this_year = 0;
|
||||
|
||||
v->engine_type = (byte)p1;
|
||||
e = &_engines[p1];
|
||||
|
@ -444,23 +433,10 @@ int32 CmdBuildRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
v->max_age = e->lifelength * 366;
|
||||
|
||||
v->string_id = STR_SV_TRAIN_NAME;
|
||||
// v->cur_speed = 0;
|
||||
// v->subspeed = 0;
|
||||
v->u.rail.railtype = e->railtype;
|
||||
_new_train_id = v->index;
|
||||
// v->cur_order_index = 0;
|
||||
// v->num_orders = 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;
|
||||
|
||||
v->service_interval = _patches.servint_trains;
|
||||
// v->breakdown_ctr = 0;
|
||||
// v->breakdowns_since_last_service = 0;
|
||||
// v->unk4D = 0;
|
||||
v->date_of_last_service = _date;
|
||||
v->build_year = _cur_year;
|
||||
v->type = VEH_Train;
|
||||
|
@ -680,12 +656,9 @@ int32 CmdMoveRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
// move the train to an empty line. for locomotives, we set the type to 0. for wagons, 4.
|
||||
if (is_loco) {
|
||||
if (src->subtype != 0) {
|
||||
// setting the type to 0 also involves setting up the schedule_ptr field.
|
||||
// setting the type to 0 also involves setting up the orders field.
|
||||
src->subtype = 0;
|
||||
assert(src->schedule_ptr == NULL);
|
||||
_ptr_to_next_order->type = OT_NOTHING;
|
||||
_ptr_to_next_order->flags = 0;
|
||||
src->schedule_ptr = _ptr_to_next_order++;
|
||||
assert(src->orders == NULL);
|
||||
src->num_orders = 0;
|
||||
}
|
||||
dst_head = src;
|
||||
|
@ -695,9 +668,9 @@ int32 CmdMoveRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
src->u.rail.first_engine = 0xffff;
|
||||
} else {
|
||||
if (src->subtype == 0) {
|
||||
// the vehicle was previously a loco. need to free the schedule list and delete vehicle windows etc.
|
||||
// the vehicle was previously a loco. need to free the order list and delete vehicle windows etc.
|
||||
DeleteWindowById(WC_VEHICLE_VIEW, src->index);
|
||||
DeleteVehicleSchedule(src);
|
||||
DeleteVehicleOrders(src);
|
||||
}
|
||||
|
||||
src->subtype = 2;
|
||||
|
@ -1644,13 +1617,13 @@ bad:;
|
|||
|
||||
static bool ProcessTrainOrder(Vehicle *v)
|
||||
{
|
||||
Order order;
|
||||
const Order *order;
|
||||
bool result;
|
||||
|
||||
// These are un-interruptible
|
||||
if (v->current_order.type >= OT_GOTO_DEPOT &&
|
||||
v->current_order.type <= OT_LEAVESTATION) {
|
||||
// Let a depot order in the schedule interrupt.
|
||||
// Let a depot order in the orderlist interrupt.
|
||||
if (v->current_order.type != OT_GOTO_DEPOT ||
|
||||
!(v->current_order.flags & OF_UNLOAD))
|
||||
return false;
|
||||
|
@ -1676,10 +1649,11 @@ static bool ProcessTrainOrder(Vehicle *v)
|
|||
// Get the current order
|
||||
if (v->cur_order_index >= v->num_orders)
|
||||
v->cur_order_index = 0;
|
||||
order = v->schedule_ptr[v->cur_order_index];
|
||||
|
||||
order = GetVehicleOrder(v, v->cur_order_index);
|
||||
|
||||
// If no order, do nothing.
|
||||
if (order.type == OT_NOTHING) {
|
||||
if (order == NULL) {
|
||||
v->current_order.type = OT_NOTHING;
|
||||
v->current_order.flags = 0;
|
||||
v->dest_tile = 0;
|
||||
|
@ -1687,31 +1661,37 @@ static bool ProcessTrainOrder(Vehicle *v)
|
|||
}
|
||||
|
||||
// If it is unchanged, keep it.
|
||||
if (order.type == v->current_order.type &&
|
||||
order.flags == v->current_order.flags &&
|
||||
order.station == v->current_order.station)
|
||||
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->current_order = order;
|
||||
v->current_order = *order;
|
||||
|
||||
v->dest_tile = 0;
|
||||
|
||||
result = false;
|
||||
if (order.type == OT_GOTO_STATION) {
|
||||
if (order.station == v->last_station_visited)
|
||||
v->last_station_visited = 0xFFFF;
|
||||
v->dest_tile = GetStation(order.station)->xy;
|
||||
result = CheckReverseTrain(v);
|
||||
} else if (order.type == OT_GOTO_DEPOT) {
|
||||
v->dest_tile = _depots[order.station].xy;
|
||||
result = CheckReverseTrain(v);
|
||||
} else if (order.type == OT_GOTO_WAYPOINT) {
|
||||
v->dest_tile = _waypoints[order.station].xy;
|
||||
result = CheckReverseTrain(v);
|
||||
switch (order->type) {
|
||||
case OT_GOTO_STATION:
|
||||
if (order->station == v->last_station_visited)
|
||||
v->last_station_visited = 0xFFFF;
|
||||
v->dest_tile = GetStation(order->station)->xy;
|
||||
result = CheckReverseTrain(v);
|
||||
break;
|
||||
|
||||
case OT_GOTO_DEPOT:
|
||||
v->dest_tile = _depots[order->station].xy;
|
||||
result = CheckReverseTrain(v);
|
||||
break;
|
||||
|
||||
case OT_GOTO_WAYPOINT:
|
||||
v->dest_tile = _waypoints[order->station].xy;
|
||||
result = CheckReverseTrain(v);
|
||||
break;
|
||||
}
|
||||
|
||||
InvalidateVehicleOrderWidget(v);
|
||||
InvalidateVehicleOrder(v);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -1771,7 +1751,7 @@ static void HandleTrainLoading(Vehicle *v, bool mode)
|
|||
|
||||
v->u.rail.days_since_order_progr = 0;
|
||||
v->cur_order_index++;
|
||||
InvalidateVehicleOrderWidget(v);
|
||||
InvalidateVehicleOrder(v);
|
||||
}
|
||||
|
||||
static int UpdateTrainSpeed(Vehicle *v)
|
||||
|
@ -2669,7 +2649,7 @@ void TrainEnterDepot(Vehicle *v, uint tile)
|
|||
v->current_order.type = OT_DUMMY;
|
||||
v->current_order.flags = 0;
|
||||
|
||||
if (t.flags & OF_UNLOAD) { // Part of the schedule?
|
||||
if (t.flags & OF_UNLOAD) { // Part of the orderlist?
|
||||
v->u.rail.days_since_order_progr = 0;
|
||||
v->cur_order_index++;
|
||||
} else if (t.flags & OF_FULL_LOAD) { // User initiated?
|
||||
|
@ -2701,7 +2681,7 @@ static void CheckIfTrainNeedsService(Vehicle *v)
|
|||
if (v->vehstatus & VS_STOPPED)
|
||||
return;
|
||||
|
||||
if (_patches.gotodepot && ScheduleHasDepotOrders(v->schedule_ptr))
|
||||
if (_patches.gotodepot && VehicleHasDepotOrders(v))
|
||||
return;
|
||||
|
||||
// Don't interfere with a depot visit scheduled by the user, or a
|
||||
|
@ -2834,11 +2814,3 @@ void InitializeTrains()
|
|||
{
|
||||
_age_cargo_skip_counter = 1;
|
||||
}
|
||||
|
||||
int ScheduleHasDepotOrders(const Order *schedule)
|
||||
{
|
||||
for (; schedule->type != OT_NOTHING; schedule++)
|
||||
if (schedule->type == OT_GOTO_DEPOT)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
|
1
ttd.c
1
ttd.c
|
@ -496,6 +496,7 @@ static void InitializeDynamicVariables(void)
|
|||
_industry_sort = NULL;
|
||||
|
||||
_sign_size = lengthof(_sign_list);
|
||||
_orders_size = lengthof(_orders);
|
||||
}
|
||||
|
||||
static void UnInitializeDynamicVariables(void)
|
||||
|
|
203
vehicle.c
203
vehicle.c
|
@ -33,24 +33,6 @@ bool VehicleNeedsService(const Vehicle *v)
|
|||
(v->date_of_last_service + v->service_interval < _date);
|
||||
}
|
||||
|
||||
Order UnpackOldOrder(uint16 packed)
|
||||
{
|
||||
Order order;
|
||||
order.type = (packed & 0x000f);
|
||||
order.flags = (packed & 0x00f0) >> 4;
|
||||
order.station = (packed & 0xff00) >> 8;
|
||||
|
||||
// Sanity check
|
||||
// TTD stores invalid orders as OT_NOTHING with non-zero flags/station
|
||||
if (order.type == OT_NOTHING && (order.flags != 0 || order.station != 0)) {
|
||||
order.type = OT_DUMMY;
|
||||
order.flags = 0;
|
||||
}
|
||||
|
||||
return order;
|
||||
}
|
||||
|
||||
|
||||
void VehicleInTheWayErrMsg(Vehicle *v)
|
||||
{
|
||||
StringID id;
|
||||
|
@ -177,11 +159,6 @@ void AfterLoadVehicles()
|
|||
if (v->subtype == 0)
|
||||
UpdateTrainAcceleration(v);
|
||||
}
|
||||
|
||||
#if defined(_DEBUG)
|
||||
if (!(v->schedule_ptr == NULL || (v->schedule_ptr >= _order_array && v->schedule_ptr < _ptr_to_next_order)))
|
||||
v->schedule_ptr = NULL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -196,7 +173,7 @@ static Vehicle *InitializeVehicle(Vehicle *v)
|
|||
memset(v, 0, sizeof(Vehicle));
|
||||
v->index = index;
|
||||
|
||||
assert(v->schedule_ptr == NULL);
|
||||
assert(v->orders == NULL);
|
||||
|
||||
v->left_coord = INVALID_COORD;
|
||||
v->next = NULL;
|
||||
|
@ -353,8 +330,6 @@ void InitializeVehicles()
|
|||
v->index = i++;
|
||||
|
||||
memset(_vehicle_position_hash, -1, sizeof(_vehicle_position_hash));
|
||||
|
||||
_ptr_to_next_order = _order_array;
|
||||
}
|
||||
|
||||
Vehicle *GetLastVehicleInChain(Vehicle *v)
|
||||
|
@ -439,91 +414,6 @@ uint GetWaypointByTile(uint tile)
|
|||
return i;
|
||||
}
|
||||
|
||||
|
||||
Vehicle *IsScheduleShared(Vehicle *u)
|
||||
{
|
||||
const Order *sched = u->schedule_ptr;
|
||||
Vehicle *v;
|
||||
|
||||
FOR_ALL_VEHICLES(v) {
|
||||
if (v->schedule_ptr == sched && u != v && v->type != 0)
|
||||
return v;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void DeleteVehicleSchedule(Vehicle *v)
|
||||
{
|
||||
Order *sched;
|
||||
Order *cur;
|
||||
int num;
|
||||
Vehicle *u;
|
||||
|
||||
// if the schedule is shared, don't delete it.
|
||||
if ((u = IsScheduleShared(v)) != NULL) {
|
||||
v->schedule_ptr = NULL;
|
||||
InvalidateWindow(WC_VEHICLE_ORDERS, u->index);
|
||||
return;
|
||||
}
|
||||
|
||||
sched = v->schedule_ptr;
|
||||
v->schedule_ptr = NULL;
|
||||
|
||||
num = v->num_orders + 1;
|
||||
|
||||
_ptr_to_next_order -= num;
|
||||
|
||||
cur = sched;
|
||||
while (cur != _ptr_to_next_order) {
|
||||
assert(cur < _ptr_to_next_order);
|
||||
cur[0] = cur[num];
|
||||
cur++;
|
||||
}
|
||||
|
||||
FOR_ALL_VEHICLES(v) {
|
||||
if (v->schedule_ptr != NULL && sched < v->schedule_ptr) {
|
||||
v->schedule_ptr -= num;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeleteCommandFromVehicleSchedule(Order cmd)
|
||||
{
|
||||
Vehicle *v;
|
||||
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.station && cmd.type == OT_GOTO_STATION)
|
||||
v->last_station_visited = 0xFFFF;
|
||||
|
||||
// check the next order
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (need_invalidate)
|
||||
InvalidateWindow(WC_VEHICLE_ORDERS, v->index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoDeleteDepot(uint tile)
|
||||
{
|
||||
Order order;
|
||||
|
@ -538,9 +428,8 @@ void DoDeleteDepot(uint tile)
|
|||
d->xy = 0;
|
||||
|
||||
order.type = OT_GOTO_DEPOT;
|
||||
order.flags = 0;
|
||||
order.station = dep_index;
|
||||
DeleteCommandFromVehicleSchedule(order);
|
||||
DeleteDestinationFromVehicleOrder(order);
|
||||
|
||||
// Delete the depot
|
||||
DeleteWindowById(WC_VEHICLE_DEPOT, tile);
|
||||
|
@ -553,8 +442,8 @@ void DeleteVehicle(Vehicle *v)
|
|||
UpdateVehiclePosHash(v, INVALID_COORD, 0);
|
||||
v->next_hash = 0xffff;
|
||||
|
||||
if (v->schedule_ptr != NULL)
|
||||
DeleteVehicleSchedule(v);
|
||||
if (v->orders != NULL)
|
||||
DeleteVehicleOrders(v);
|
||||
}
|
||||
|
||||
void DeleteVehicleChain(Vehicle *v)
|
||||
|
@ -1699,12 +1588,6 @@ void EndVehicleMove(Vehicle *v)
|
|||
);
|
||||
}
|
||||
|
||||
void InvalidateVehicleOrderWidget(Vehicle *v)
|
||||
{
|
||||
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
|
||||
InvalidateWindowWidget(WC_VEHICLE_ORDERS, v->index, 2);
|
||||
}
|
||||
|
||||
/* returns true if staying in the same tile */
|
||||
bool GetNewVehiclePos(Vehicle *v, GetNewVehiclePosResult *gp)
|
||||
{
|
||||
|
@ -1846,7 +1729,7 @@ const byte _common_veh_desc[] = {
|
|||
SLE_CONDVARX(offsetof(Vehicle, current_order) + offsetof(Order, flags), SLE_UINT8, 5, 255),
|
||||
SLE_CONDVARX(offsetof(Vehicle, current_order) + offsetof(Order, station), SLE_UINT16, 5, 255),
|
||||
|
||||
SLE_REF(Vehicle,schedule_ptr, REF_SCHEDULE),
|
||||
SLE_REF(Vehicle,orders, REF_ORDER),
|
||||
|
||||
SLE_VAR(Vehicle,age, SLE_UINT16),
|
||||
SLE_VAR(Vehicle,max_age, SLE_UINT16),
|
||||
|
@ -1869,9 +1752,11 @@ const byte _common_veh_desc[] = {
|
|||
SLE_VAR(Vehicle,random_bits, SLE_UINT8),
|
||||
SLE_VAR(Vehicle,waiting_triggers, SLE_UINT8),
|
||||
|
||||
// reserve extra space in savegame here. (currently 14 bytes)
|
||||
SLE_REF(Vehicle,next_shared, REF_VEHICLE),
|
||||
SLE_REF(Vehicle,prev_shared, REF_VEHICLE),
|
||||
|
||||
// reserve extra space in savegame here. (currently 10 bytes)
|
||||
SLE_CONDARR(NullStruct,null,SLE_FILE_U8 | SLE_VAR_NULL, 2, 2, 255), /* 2 */
|
||||
SLE_CONDARR(NullStruct,null,SLE_FILE_U16 | SLE_VAR_NULL, 2, 2, 255), /* 4 */
|
||||
SLE_CONDARR(NullStruct,null,SLE_FILE_U32 | SLE_VAR_NULL, 2, 2, 255), /* 8 */
|
||||
|
||||
SLE_END()
|
||||
|
@ -2068,6 +1953,29 @@ static void Load_VEHS()
|
|||
w->u.rail.first_engine = v->engine_type;
|
||||
}
|
||||
|
||||
/* Check for shared order-lists (we now use pointers for that) */
|
||||
if (_sl.full_version < 0x502) {
|
||||
FOR_ALL_VEHICLES(v) {
|
||||
Vehicle *u;
|
||||
|
||||
if (v->type == 0)
|
||||
continue;
|
||||
|
||||
FOR_ALL_VEHICLES_FROM(u, v->index + 1) {
|
||||
if (u->type == 0)
|
||||
continue;
|
||||
|
||||
/* If a vehicle has the same orders, add the link to eachother
|
||||
in both vehicles */
|
||||
if (v->orders == u->orders) {
|
||||
v->next_shared = u;
|
||||
u->prev_shared = v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This is to ensure all pointers are within the limits of
|
||||
_vehicles_size */
|
||||
if (_vehicle_id_ctr_day >= _vehicles_size)
|
||||
|
@ -2131,55 +2039,8 @@ static void Load_CHKP()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static void Save_ORDR()
|
||||
{
|
||||
uint32 orders[lengthof(_order_array)];
|
||||
uint len = _ptr_to_next_order - _order_array;
|
||||
uint i;
|
||||
|
||||
assert (len <= lengthof(orders));
|
||||
|
||||
for (i = 0; i < len; ++i)
|
||||
orders[i] = PackOrder(&_order_array[i]);
|
||||
|
||||
SlArray(orders, len, SLE_UINT32);
|
||||
}
|
||||
|
||||
static void Load_ORDR()
|
||||
{
|
||||
uint len = SlGetFieldLength();
|
||||
uint i;
|
||||
|
||||
if (_sl.version < 5) {
|
||||
/* Older version had an other layout for orders.. convert them correctly */
|
||||
uint16 orders[lengthof(_order_array)];
|
||||
|
||||
len /= sizeof(uint16);
|
||||
assert (len <= lengthof(orders));
|
||||
|
||||
SlArray(orders, len, SLE_UINT16);
|
||||
|
||||
for (i = 0; i < len; ++i)
|
||||
_order_array[i] = UnpackVersion4Order(orders[i]);
|
||||
} else {
|
||||
uint32 orders[lengthof(_order_array)];
|
||||
|
||||
len /= sizeof(uint32);
|
||||
assert (len <= lengthof(orders));
|
||||
|
||||
SlArray(orders, len, SLE_UINT32);
|
||||
|
||||
for (i = 0; i < len; ++i)
|
||||
_order_array[i] = UnpackOrder(orders[i]);
|
||||
}
|
||||
|
||||
_ptr_to_next_order = _order_array + len;
|
||||
}
|
||||
|
||||
const ChunkHandler _veh_chunk_handlers[] = {
|
||||
{ 'VEHS', Save_VEHS, Load_VEHS, CH_SPARSE_ARRAY},
|
||||
{ 'ORDR', Save_ORDR, Load_ORDR, CH_RIFF},
|
||||
{ 'DEPT', Save_DEPT, Load_DEPT, CH_ARRAY},
|
||||
{ 'CHKP', Save_CHKP, Load_CHKP, CH_ARRAY | CH_LAST},
|
||||
};
|
||||
|
|
132
vehicle.h
132
vehicle.h
|
@ -2,42 +2,7 @@
|
|||
#define VEHICLE_H
|
||||
|
||||
#include "vehicle_gui.h"
|
||||
|
||||
/* If you change this, keep in mind that it is saved on 3 places:
|
||||
- Load_ORDR, all the global orders
|
||||
- Vehicle -> current_order
|
||||
- REF_SHEDULE (all REFs are currently limited to 16 bits!!) */
|
||||
typedef struct Order {
|
||||
uint8 type;
|
||||
uint8 flags;
|
||||
uint16 station;
|
||||
} Order;
|
||||
|
||||
static inline uint32 PackOrder(const Order *order)
|
||||
{
|
||||
return order->station << 16 | order->flags << 8 | order->type;
|
||||
}
|
||||
|
||||
static inline Order UnpackOrder(uint32 packed)
|
||||
{
|
||||
Order order;
|
||||
order.type = (packed & 0x000000FF);
|
||||
order.flags = (packed & 0x0000FF00) >> 8;
|
||||
order.station = (packed & 0xFFFF0000) >> 16;
|
||||
return order;
|
||||
}
|
||||
|
||||
static inline Order UnpackVersion4Order(uint16 packed)
|
||||
{
|
||||
Order order;
|
||||
order.type = (packed & 0x000F);
|
||||
order.flags = (packed & 0x00F0) >> 4;
|
||||
order.station = (packed & 0xFF00) >> 8;
|
||||
return order;
|
||||
}
|
||||
|
||||
Order UnpackOldOrder(uint16 packed);
|
||||
|
||||
#include "order.h"
|
||||
|
||||
typedef struct VehicleRail {
|
||||
uint16 last_speed; // NOSAVE: only used in UI
|
||||
|
@ -177,11 +142,16 @@ struct Vehicle {
|
|||
byte day_counter; // increased by one for each day
|
||||
byte tick_counter;// increased by one for each tick
|
||||
|
||||
// related to the current order
|
||||
byte cur_order_index;
|
||||
byte num_orders;
|
||||
Order current_order;
|
||||
Order *schedule_ptr;
|
||||
/* Begin Order-stuff */
|
||||
Order current_order; //! The current order (+ status, like: loading)
|
||||
byte cur_order_index; //! The index to the current order
|
||||
|
||||
Order *orders; //! Pointer to the first order for this vehicle
|
||||
byte num_orders; //! How many orders there are in the list
|
||||
|
||||
Vehicle *next_shared; //! If not NULL, this points to the next vehicle that shared the order
|
||||
Vehicle *prev_shared; //! If not NULL, this points to the prev vehicle that shared the order
|
||||
/* End Order-stuff */
|
||||
|
||||
// Boundaries for the current position in the world and a next hash link.
|
||||
// NOSAVE: All of those can be updated with VehiclePositionChanged()
|
||||
|
@ -248,25 +218,6 @@ enum {
|
|||
VEH_Disaster = 0x15,
|
||||
};
|
||||
|
||||
/* Order types */
|
||||
enum {
|
||||
OT_NOTHING = 0,
|
||||
OT_GOTO_STATION = 1,
|
||||
OT_GOTO_DEPOT = 2,
|
||||
OT_LOADING = 3,
|
||||
OT_LEAVESTATION = 4,
|
||||
OT_DUMMY = 5,
|
||||
OT_GOTO_WAYPOINT = 6,
|
||||
};
|
||||
|
||||
/* Order flags */
|
||||
enum {
|
||||
OF_UNLOAD = 0x2,
|
||||
OF_FULL_LOAD = 0x4, // Also used when to force an aircraft into a depot
|
||||
OF_NON_STOP = 0x8
|
||||
};
|
||||
|
||||
|
||||
enum VehStatus {
|
||||
VS_HIDDEN = 1,
|
||||
VS_STOPPED = 2,
|
||||
|
@ -302,22 +253,11 @@ enum {
|
|||
typedef void VehicleTickProc(Vehicle *v);
|
||||
typedef void *VehicleFromPosProc(Vehicle *v, void *data);
|
||||
|
||||
typedef struct {
|
||||
VehicleID clone;
|
||||
byte orderindex;
|
||||
Order order[41];
|
||||
uint16 service_interval;
|
||||
char name[32];
|
||||
} BackuppedOrders;
|
||||
|
||||
void VehicleServiceInDepot(Vehicle *v);
|
||||
void BackupVehicleOrders(Vehicle *v, BackuppedOrders *order);
|
||||
void RestoreVehicleOrders(Vehicle *v, BackuppedOrders *order);
|
||||
Vehicle *AllocateVehicle();
|
||||
Vehicle *ForceAllocateVehicle();
|
||||
Vehicle *ForceAllocateSpecialVehicle();
|
||||
void UpdateVehiclePosHash(Vehicle *v, int x, int y);
|
||||
void InitializeVehicles();
|
||||
void VehiclePositionChanged(Vehicle *v);
|
||||
void AfterLoadVehicles();
|
||||
Vehicle *GetLastVehicleInChain(Vehicle *v);
|
||||
|
@ -328,8 +268,6 @@ void DeleteVehicle(Vehicle *v);
|
|||
void DeleteVehicleChain(Vehicle *v);
|
||||
void *VehicleFromPos(TileIndex tile, void *data, VehicleFromPosProc *proc);
|
||||
void CallVehicleTicks();
|
||||
void DeleteVehicleSchedule(Vehicle *v);
|
||||
Vehicle *IsScheduleShared(Vehicle *v);
|
||||
|
||||
Depot *AllocateDepot();
|
||||
Waypoint *AllocateWaypoint();
|
||||
|
@ -373,16 +311,12 @@ void CheckVehicleBreakdown(Vehicle *v);
|
|||
void AgeVehicle(Vehicle *v);
|
||||
void MaybeReplaceVehicle(Vehicle *v);
|
||||
|
||||
void DeleteCommandFromVehicleSchedule(Order cmd);
|
||||
|
||||
void BeginVehicleMove(Vehicle *v);
|
||||
void EndVehicleMove(Vehicle *v);
|
||||
|
||||
bool IsAircraftHangarTile(TileIndex tile);
|
||||
void ShowAircraftViewWindow(Vehicle *v);
|
||||
|
||||
void InvalidateVehicleOrderWidget(Vehicle *v);
|
||||
|
||||
bool IsShipDepotTile(TileIndex tile);
|
||||
uint GetFreeUnitNumber(byte type);
|
||||
|
||||
|
@ -397,9 +331,6 @@ int32 GetTrainRunningCost(Vehicle *v);
|
|||
|
||||
int CheckStoppedInDepot(Vehicle *v);
|
||||
|
||||
int ScheduleHasDepotOrders(const Order *schedule);
|
||||
int CheckOrders(Vehicle *v);
|
||||
|
||||
bool VehicleNeedsService(const Vehicle *v);
|
||||
|
||||
void InvalidateAircraftWindows(const Vehicle *v);
|
||||
|
@ -439,8 +370,43 @@ static inline Vehicle *GetVehicle(uint index)
|
|||
#define FOR_ALL_VEHICLES(v) for(v = _vehicles; v != &_vehicles[_vehicles_size]; v++)
|
||||
#define FOR_ALL_VEHICLES_FROM(v, from) for(v = GetVehicle(from); v != &_vehicles[_vehicles_size]; v++)
|
||||
|
||||
VARDEF Order _order_array[5000];
|
||||
VARDEF Order *_ptr_to_next_order;
|
||||
/* Returns order 'index' of a vehicle or NULL when it doesn't exists */
|
||||
static inline Order *GetVehicleOrder(const Vehicle *v, int index)
|
||||
{
|
||||
Order *order = v->orders;
|
||||
|
||||
if (index < 0)
|
||||
return NULL;
|
||||
|
||||
while (order != NULL && index-- > 0)
|
||||
order = order->next;
|
||||
|
||||
return order;
|
||||
}
|
||||
|
||||
/* Returns the last order of a vehicle, or NULL if it doesn't exists */
|
||||
static inline Order *GetLastVehicleOrder(const Vehicle *v)
|
||||
{
|
||||
Order *order = v->orders;
|
||||
|
||||
if (order == NULL)
|
||||
return NULL;
|
||||
|
||||
while (order->next != NULL)
|
||||
order = order->next;
|
||||
|
||||
return order;
|
||||
}
|
||||
|
||||
/* Get the first vehicle of a shared-list, so we only have to walk forwards */
|
||||
static inline Vehicle *GetFirstVehicleFromSharedList(Vehicle *v)
|
||||
{
|
||||
Vehicle *u = v;
|
||||
while (u->prev_shared != NULL)
|
||||
u = u->prev_shared;
|
||||
|
||||
return u;
|
||||
}
|
||||
|
||||
VARDEF Depot _depots[255];
|
||||
|
||||
|
@ -465,8 +431,6 @@ VARDEF TileIndex _last_built_train_depot_tile;
|
|||
VARDEF TileIndex _last_built_road_depot_tile;
|
||||
VARDEF TileIndex _last_built_aircraft_depot_tile;
|
||||
VARDEF TileIndex _last_built_ship_depot_tile;
|
||||
VARDEF TileIndex _backup_orders_tile;
|
||||
VARDEF BackuppedOrders _backup_orders_data[1];
|
||||
|
||||
// for each player, for each vehicle type, keep a list of the vehicles.
|
||||
//VARDEF Vehicle *_vehicle_arr[8][4];
|
||||
|
|
|
@ -90,14 +90,16 @@ void BuildVehicleList(vehiclelist_d *vl, int type, int owner, int station)
|
|||
const Vehicle *v;
|
||||
FOR_ALL_VEHICLES(v) {
|
||||
if (v->type == type && v->subtype <= subtype) {
|
||||
const Order *ord;
|
||||
for (ord = v->schedule_ptr; ord->type != OT_NOTHING; ++ord)
|
||||
if (ord->type == OT_GOTO_STATION && ord->station == station) {
|
||||
const Order *order;
|
||||
|
||||
FOR_VEHICLE_ORDERS(v, order) {
|
||||
if (order->type == OT_GOTO_STATION && order->station == station) {
|
||||
_vehicle_sort[n].index = v->index;
|
||||
_vehicle_sort[n].owner = v->owner;
|
||||
++n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue