src/order_cmd.cpp
branchnoai
changeset 9869 6404afe43575
parent 9837 c9ec4f82e0d0
child 10142 56ee7da4ad56
equal deleted inserted replaced
9868:3998f2e73dda 9869:6404afe43575
    21 #include "functions.h"
    21 #include "functions.h"
    22 #include "window_func.h"
    22 #include "window_func.h"
    23 #include "settings_type.h"
    23 #include "settings_type.h"
    24 #include "string_func.h"
    24 #include "string_func.h"
    25 #include "newgrf_cargo.h"
    25 #include "newgrf_cargo.h"
       
    26 #include "timetable.h"
       
    27 #include "vehicle_func.h"
    26 
    28 
    27 #include "table/strings.h"
    29 #include "table/strings.h"
    28 
    30 
    29 /* DestinationID must be at least as large as every these below, because it can
    31 /* DestinationID must be at least as large as every these below, because it can
    30  * be any of them
    32  * be any of them
    36 TileIndex _backup_orders_tile;
    38 TileIndex _backup_orders_tile;
    37 BackuppedOrders _backup_orders_data;
    39 BackuppedOrders _backup_orders_data;
    38 
    40 
    39 DEFINE_OLD_POOL_GENERIC(Order, Order)
    41 DEFINE_OLD_POOL_GENERIC(Order, Order)
    40 
    42 
       
    43 void Order::Free()
       
    44 {
       
    45 	this->type  = OT_NOTHING;
       
    46 	this->flags = 0;
       
    47 	this->dest  = 0;
       
    48 	this->next  = NULL;
       
    49 }
       
    50 
       
    51 void Order::MakeGoToStation(StationID destination)
       
    52 {
       
    53 	this->type = OT_GOTO_STATION;
       
    54 	this->flags = 0;
       
    55 	this->dest = destination;
       
    56 }
       
    57 
       
    58 void Order::MakeGoToDepot(DepotID destination, bool order, CargoID cargo, byte subtype)
       
    59 {
       
    60 	this->type = OT_GOTO_DEPOT;
       
    61 	this->flags = order ? OFB_PART_OF_ORDERS : OFB_NON_STOP;
       
    62 	this->dest = destination;
       
    63 	this->SetRefit(cargo, subtype);
       
    64 }
       
    65 
       
    66 void Order::MakeGoToWaypoint(WaypointID destination)
       
    67 {
       
    68 	this->type = OT_GOTO_WAYPOINT;
       
    69 	this->flags = 0;
       
    70 	this->dest = destination;
       
    71 }
       
    72 
       
    73 void Order::MakeLoading(bool ordered)
       
    74 {
       
    75 	this->type = OT_LOADING;
       
    76 	if (!ordered) this->flags = 0;
       
    77 }
       
    78 
       
    79 void Order::MakeLeaveStation()
       
    80 {
       
    81 	this->type = OT_LEAVESTATION;
       
    82 	this->flags = 0;
       
    83 }
       
    84 
       
    85 void Order::MakeDummy()
       
    86 {
       
    87 	this->type = OT_DUMMY;
       
    88 	this->flags = 0;
       
    89 }
       
    90 
       
    91 void Order::SetRefit(CargoID cargo, byte subtype)
       
    92 {
       
    93 	this->refit_cargo = cargo;
       
    94 	this->refit_subtype = subtype;
       
    95 }
       
    96 
       
    97 void Order::FreeChain()
       
    98 {
       
    99 	if (next != NULL) next->FreeChain();
       
   100 	delete this;
       
   101 }
       
   102 
       
   103 bool Order::Equals(const Order &other) const
       
   104 {
       
   105 	return
       
   106 			this->type  == other.type &&
       
   107 			this->flags == other.flags &&
       
   108 			this->dest  == other.dest;
       
   109 }
       
   110 
       
   111 static bool HasOrderPoolFree(uint amount)
       
   112 {
       
   113 	const Order *order;
       
   114 
       
   115 	/* There is always room if not all blocks in the pool are reserved */
       
   116 	if (_Order_pool.CanAllocateMoreBlocks()) return true;
       
   117 
       
   118 	FOR_ALL_ORDERS(order) if (!order->IsValid() && --amount == 0) return true;
       
   119 
       
   120 	return false;
       
   121 }
       
   122 
       
   123 uint32 Order::Pack() const
       
   124 {
       
   125 	return this->dest << 16 | this->flags << 8 | this->type;
       
   126 }
       
   127 
       
   128 Order::Order(uint32 packed)
       
   129 {
       
   130 	this->type    = (OrderType)GB(packed,  0,  8);
       
   131 	this->flags   = GB(packed,  8,  8);
       
   132 	this->dest    = GB(packed, 16, 16);
       
   133 	this->next    = NULL;
       
   134 	this->index   = 0; // avoid compiler warning
       
   135 	this->refit_cargo   = CT_NO_REFIT;
       
   136 	this->refit_subtype = 0;
       
   137 	this->wait_time     = 0;
       
   138 	this->travel_time   = 0;
       
   139 }
       
   140 
       
   141 /**
       
   142  *
       
   143  * Unpacks a order from savegames with version 4 and lower
       
   144  *
       
   145  */
       
   146 static Order UnpackVersion4Order(uint16 packed)
       
   147 {
       
   148 	return Order(GB(packed, 8, 8) << 16 | GB(packed, 4, 4) << 8 | GB(packed, 0, 4));
       
   149 }
       
   150 
    41 /**
   151 /**
    42  *
   152  *
    43  * Unpacks a order from savegames made with TTD(Patch)
   153  * Unpacks a order from savegames made with TTD(Patch)
    44  *
   154  *
    45  */
   155  */
    46 Order UnpackOldOrder(uint16 packed)
   156 Order UnpackOldOrder(uint16 packed)
    47 {
   157 {
    48 	Order order;
   158 	Order order = UnpackVersion4Order(packed);
    49 	order.type    = (OrderType)GB(packed, 0, 4);
   159 
    50 	order.flags   = GB(packed, 4, 4);
   160 	/*
    51 	order.dest    = GB(packed, 8, 8);
   161 	 * Sanity check
    52 	order.next    = NULL;
   162 	 * TTD stores invalid orders as OT_NOTHING with non-zero flags/station
    53 
   163 	 */
    54 	order.refit_cargo   = CT_NO_REFIT;
   164 	if (!order.IsValid() && (order.GetLoadType() != 0 || order.GetUnloadType() != 0 || order.GetDestination() != 0)) {
    55 	order.refit_subtype = 0;
   165 		order.MakeDummy();
    56 	order.wait_time     = 0;
   166 	}
    57 	order.travel_time   = 0;
   167 
    58 	order.index = 0; // avoid compiler warning
       
    59 
       
    60 	// Sanity check
       
    61 	// TTD stores invalid orders as OT_NOTHING with non-zero flags/station
       
    62 	if (!order.IsValid() && (order.flags != 0 || order.dest != 0)) {
       
    63 		order.type = OT_DUMMY;
       
    64 		order.flags = 0;
       
    65 	}
       
    66 
       
    67 	return order;
       
    68 }
       
    69 
       
    70 /**
       
    71  *
       
    72  * Unpacks a order from savegames with version 4 and lower
       
    73  *
       
    74  */
       
    75 static Order UnpackVersion4Order(uint16 packed)
       
    76 {
       
    77 	Order order;
       
    78 	order.type  = (OrderType)GB(packed, 0, 4);
       
    79 	order.flags = GB(packed, 4, 4);
       
    80 	order.dest  = GB(packed, 8, 8);
       
    81 	order.next  = NULL;
       
    82 	order.index = 0; // avoid compiler warning
       
    83 	order.refit_cargo   = CT_NO_REFIT;
       
    84 	order.refit_subtype = 0;
       
    85 	order.wait_time     = 0;
       
    86 	order.travel_time   = 0;
       
    87 	return order;
   168 	return order;
    88 }
   169 }
    89 
   170 
    90 /**
   171 /**
    91  *
   172  *
   107 static void SwapOrders(Order *order1, Order *order2)
   188 static void SwapOrders(Order *order1, Order *order2)
   108 {
   189 {
   109 	Order temp_order;
   190 	Order temp_order;
   110 
   191 
   111 	temp_order = *order1;
   192 	temp_order = *order1;
   112 	AssignOrder(order1, *order2);
   193 	order1->AssignOrder(*order2);
   113 	order1->next = order2->next;
   194 	order1->next = order2->next;
   114 	AssignOrder(order2, temp_order);
   195 	order2->AssignOrder(temp_order);
   115 	order2->next = temp_order.next;
   196 	order2->next = temp_order.next;
   116 }
   197 }
   117 
   198 
   118 /**
   199 /**
   119  *
   200  *
   120  * Assign data to an order (from an other order)
   201  * Assign data to an order (from an other order)
   121  *   This function makes sure that the index is maintained correctly
   202  *   This function makes sure that the index is maintained correctly
   122  *
   203  *
   123  */
   204  */
   124 void AssignOrder(Order *order, Order data)
   205 void Order::AssignOrder(const Order &other)
   125 {
   206 {
   126 	order->type  = data.type;
   207 	this->type  = other.type;
   127 	order->flags = data.flags;
   208 	this->flags = other.flags;
   128 	order->dest  = data.dest;
   209 	this->dest  = other.dest;
   129 
   210 
   130 	order->refit_cargo   = data.refit_cargo;
   211 	this->refit_cargo   = other.refit_cargo;
   131 	order->refit_subtype = data.refit_subtype;
   212 	this->refit_subtype = other.refit_subtype;
   132 
   213 
   133 	order->wait_time   = data.wait_time;
   214 	this->wait_time   = other.wait_time;
   134 	order->travel_time = data.travel_time;
   215 	this->travel_time = other.travel_time;
   135 }
   216 }
   136 
   217 
   137 
   218 
   138 /**
   219 /**
   139  * Delete all news items regarding defective orders about a vehicle
   220  * Delete all news items regarding defective orders about a vehicle
   150 }
   231 }
   151 
   232 
   152 
   233 
   153 static TileIndex GetOrderLocation(const Order& o)
   234 static TileIndex GetOrderLocation(const Order& o)
   154 {
   235 {
   155 	switch (o.type) {
   236 	switch (o.GetType()) {
   156 		default: NOT_REACHED();
   237 		default: NOT_REACHED();
   157 		case OT_GOTO_STATION: return GetStation(o.dest)->xy;
   238 		case OT_GOTO_STATION: return GetStation(o.GetDestination())->xy;
   158 		case OT_GOTO_DEPOT:   return GetDepot(o.dest)->xy;
   239 		case OT_GOTO_DEPOT:   return GetDepot(o.GetDestination())->xy;
   159 	}
   240 	}
   160 }
   241 }
   161 
   242 
   162 
   243 
   163 /** Add an order to the orderlist of a vehicle.
   244 /** Add an order to the orderlist of a vehicle.
   173 CommandCost CmdInsertOrder(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   254 CommandCost CmdInsertOrder(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   174 {
   255 {
   175 	Vehicle *v;
   256 	Vehicle *v;
   176 	VehicleID veh   = GB(p1,  0, 16);
   257 	VehicleID veh   = GB(p1,  0, 16);
   177 	VehicleOrderID sel_ord = GB(p1, 16, 16);
   258 	VehicleOrderID sel_ord = GB(p1, 16, 16);
   178 	Order new_order = UnpackOrder(p2);
   259 	Order new_order(p2);
   179 
   260 
   180 	if (!IsValidVehicleID(veh)) return CMD_ERROR;
   261 	if (!IsValidVehicleID(veh)) return CMD_ERROR;
   181 
   262 
   182 	v = GetVehicle(veh);
   263 	v = GetVehicle(veh);
   183 
   264 
   184 	if (!CheckOwnership(v->owner)) return CMD_ERROR;
   265 	if (!CheckOwnership(v->owner)) return CMD_ERROR;
   185 
   266 
   186 	/* Check if the inserted order is to the correct destination (owner, type),
   267 	/* Check if the inserted order is to the correct destination (owner, type),
   187 	 * and has the correct flags if any */
   268 	 * and has the correct flags if any */
   188 	switch (new_order.type) {
   269 	switch (new_order.GetType()) {
   189 		case OT_GOTO_STATION: {
   270 		case OT_GOTO_STATION: {
   190 			const Station *st;
   271 			if (!IsValidStationID(new_order.GetDestination())) return CMD_ERROR;
   191 
   272 
   192 			if (!IsValidStationID(new_order.dest)) return CMD_ERROR;
   273 			const Station *st = GetStation(new_order.GetDestination());
   193 			st = GetStation(new_order.dest);
       
   194 
   274 
   195 			if (st->owner != OWNER_NONE && !CheckOwnership(st->owner)) {
   275 			if (st->owner != OWNER_NONE && !CheckOwnership(st->owner)) {
   196 				return CMD_ERROR;
   276 				return CMD_ERROR;
   197 			}
   277 			}
   198 
   278 
   220 					break;
   300 					break;
   221 
   301 
   222 				default: return CMD_ERROR;
   302 				default: return CMD_ERROR;
   223 			}
   303 			}
   224 
   304 
       
   305 			if (new_order.GetNonStopType() != OFB_NO_NON_STOP && v->type != VEH_TRAIN) return CMD_ERROR;
       
   306 
   225 			/* Order flags can be any of the following for stations:
   307 			/* Order flags can be any of the following for stations:
   226 			 * [full-load | unload] [+ transfer] [+ non-stop]
   308 			 * [full-load | unload] [+ transfer] [+ non-stop]
   227 			 * non-stop orders (if any) are only valid for trains */
   309 			 * non-stop orders (if any) are only valid for trains */
   228 			switch (new_order.flags) {
   310 			switch (new_order.GetLoadType() | new_order.GetUnloadType()) {
   229 				case 0:
   311 				case 0:
   230 				case OFB_FULL_LOAD:
   312 				case OFB_FULL_LOAD:
   231 				case OFB_FULL_LOAD | OFB_TRANSFER:
   313 				case OFB_FULL_LOAD | OFB_TRANSFER:
   232 				case OFB_UNLOAD:
   314 				case OFB_UNLOAD:
   233 				case OFB_UNLOAD | OFB_TRANSFER:
   315 				case OFB_UNLOAD | OFB_TRANSFER:
   234 				case OFB_TRANSFER:
   316 				case OFB_TRANSFER:
   235 					break;
   317 					break;
   236 
   318 
   237 				case OFB_NON_STOP:
       
   238 				case OFB_NON_STOP | OFB_FULL_LOAD:
       
   239 				case OFB_NON_STOP | OFB_FULL_LOAD | OFB_TRANSFER:
       
   240 				case OFB_NON_STOP | OFB_UNLOAD:
       
   241 				case OFB_NON_STOP | OFB_UNLOAD | OFB_TRANSFER:
       
   242 				case OFB_NON_STOP | OFB_TRANSFER:
       
   243 					if (v->type != VEH_TRAIN) return CMD_ERROR;
       
   244 					break;
       
   245 
       
   246 				default: return CMD_ERROR;
   319 				default: return CMD_ERROR;
   247 			}
   320 			}
   248 			break;
   321 			break;
   249 		}
   322 		}
   250 
   323 
   251 		case OT_GOTO_DEPOT: {
   324 		case OT_GOTO_DEPOT: {
   252 			if (v->type == VEH_AIRCRAFT) {
   325 			if (v->type == VEH_AIRCRAFT) {
   253 				const Station* st;
   326 				if (!IsValidStationID(new_order.GetDestination())) return CMD_ERROR;
   254 
   327 
   255 				if (!IsValidStationID(new_order.dest)) return CMD_ERROR;
   328 				const Station *st = GetStation(new_order.GetDestination());
   256 				st = GetStation(new_order.dest);
       
   257 
   329 
   258 				if (!CheckOwnership(st->owner) ||
   330 				if (!CheckOwnership(st->owner) ||
   259 						!(st->facilities & FACIL_AIRPORT) ||
   331 						!(st->facilities & FACIL_AIRPORT) ||
   260 						st->Airport()->nof_depots == 0 ||
   332 						st->Airport()->nof_depots == 0 ||
   261 						!CanAircraftUseStation(v->engine_type, st)) {
   333 						!CanAircraftUseStation(v->engine_type, st)) {
   262 					return CMD_ERROR;
   334 					return CMD_ERROR;
   263 				}
   335 				}
   264 			} else {
   336 			} else {
   265 				const Depot* dp;
   337 				if (!IsValidDepotID(new_order.GetDestination())) return CMD_ERROR;
   266 
   338 
   267 				if (!IsValidDepotID(new_order.dest)) return CMD_ERROR;
   339 				const Depot *dp = GetDepot(new_order.GetDestination());
   268 				dp = GetDepot(new_order.dest);
       
   269 
   340 
   270 				if (!CheckOwnership(GetTileOwner(dp->xy))) return CMD_ERROR;
   341 				if (!CheckOwnership(GetTileOwner(dp->xy))) return CMD_ERROR;
   271 
   342 
   272 				switch (v->type) {
   343 				switch (v->type) {
   273 					case VEH_TRAIN:
   344 					case VEH_TRAIN:
   284 
   355 
   285 					default: return CMD_ERROR;
   356 					default: return CMD_ERROR;
   286 				}
   357 				}
   287 			}
   358 			}
   288 
   359 
       
   360 			if (new_order.GetNonStopType() != OFB_NO_NON_STOP && v->type != VEH_TRAIN) return CMD_ERROR;
       
   361 
   289 			/* Order flags can be any of the following for depots:
   362 			/* Order flags can be any of the following for depots:
   290 			 * order [+ halt] [+ non-stop]
   363 			 * order [+ halt] [+ non-stop]
   291 			 * non-stop orders (if any) are only valid for trains */
   364 			 * non-stop orders (if any) are only valid for trains */
   292 			switch (new_order.flags) {
   365 			switch (new_order.GetDepotOrderType() | new_order.GetDepotActionType()) {
   293 				case OFB_PART_OF_ORDERS:
   366 				case OFB_PART_OF_ORDERS:
   294 				case OFB_PART_OF_ORDERS | OFB_HALT_IN_DEPOT:
   367 				case OFB_PART_OF_ORDERS | OFB_HALT_IN_DEPOT:
   295 					break;
   368 					break;
   296 
   369 
   297 				case OFB_NON_STOP | OFB_PART_OF_ORDERS:
       
   298 				case OFB_NON_STOP | OFB_PART_OF_ORDERS | OFB_HALT_IN_DEPOT:
       
   299 					if (v->type != VEH_TRAIN) return CMD_ERROR;
       
   300 					break;
       
   301 
       
   302 				default: return CMD_ERROR;
   370 				default: return CMD_ERROR;
   303 			}
   371 			}
   304 			break;
   372 			break;
   305 		}
   373 		}
   306 
   374 
   307 		case OT_GOTO_WAYPOINT: {
   375 		case OT_GOTO_WAYPOINT: {
   308 			const Waypoint* wp;
       
   309 
   376 
   310 			if (v->type != VEH_TRAIN) return CMD_ERROR;
   377 			if (v->type != VEH_TRAIN) return CMD_ERROR;
   311 
   378 
   312 			if (!IsValidWaypointID(new_order.dest)) return CMD_ERROR;
   379 			if (!IsValidWaypointID(new_order.GetDestination())) return CMD_ERROR;
   313 			wp = GetWaypoint(new_order.dest);
   380 			const Waypoint *wp = GetWaypoint(new_order.GetDestination());
   314 
   381 
   315 			if (!CheckOwnership(GetTileOwner(wp->xy))) return CMD_ERROR;
   382 			if (!CheckOwnership(GetTileOwner(wp->xy))) return CMD_ERROR;
   316 
   383 
   317 			/* Order flags can be any of the following for waypoints:
   384 			/* Order flags can be any of the following for waypoints:
   318 			 * [non-stop]
   385 			 * [non-stop]
   319 			 * non-stop orders (if any) are only valid for trains */
   386 			 * non-stop orders (if any) are only valid for trains */
   320 			switch (new_order.flags) {
   387 			switch (new_order.GetNonStopType()) {
   321 				case 0: break;
   388 				case OFB_NO_NON_STOP: break;
   322 
   389 
   323 				case OFB_NON_STOP:
   390 				case OFB_NON_STOP:
   324 					if (v->type != VEH_TRAIN) return CMD_ERROR;
   391 					if (v->type != VEH_TRAIN) return CMD_ERROR;
   325 					break;
   392 					break;
   326 
   393 
   343 
   410 
   344 		/* Find the last goto station or depot order before the insert location.
   411 		/* Find the last goto station or depot order before the insert location.
   345 		 * If the order is to be inserted at the beginning of the order list this
   412 		 * If the order is to be inserted at the beginning of the order list this
   346 		 * finds the last order in the list. */
   413 		 * finds the last order in the list. */
   347 		for (const Order *o = v->orders; o != NULL; o = o->next) {
   414 		for (const Order *o = v->orders; o != NULL; o = o->next) {
   348 			if (o->type == OT_GOTO_STATION || o->type == OT_GOTO_DEPOT) prev = o;
   415 			if (o->IsType(OT_GOTO_STATION) || o->IsType(OT_GOTO_DEPOT)) prev = o;
   349 			if (++n == sel_ord && prev != NULL) break;
   416 			if (++n == sel_ord && prev != NULL) break;
   350 		}
   417 		}
   351 		if (prev != NULL) {
   418 		if (prev != NULL) {
   352 			uint dist = DistanceManhattan(
   419 			uint dist = DistanceManhattan(
   353 				GetOrderLocation(*prev),
   420 				GetOrderLocation(*prev),
   360 	}
   427 	}
   361 
   428 
   362 	if (flags & DC_EXEC) {
   429 	if (flags & DC_EXEC) {
   363 		Vehicle *u;
   430 		Vehicle *u;
   364 		Order *new_o = new Order();
   431 		Order *new_o = new Order();
   365 		AssignOrder(new_o, new_order);
   432 		new_o->AssignOrder(new_order);
   366 
   433 
   367 		/* Create new order and link in list */
   434 		/* Create new order and link in list */
   368 		if (v->orders == NULL) {
   435 		if (v->orders == NULL) {
   369 			v->orders = new_o;
   436 			v->orders = new_o;
   370 		} else {
   437 		} else {
   517 
   584 
   518 			assert(v->orders == u->orders);
   585 			assert(v->orders == u->orders);
   519 
   586 
   520 			/* NON-stop flag is misused to see if a train is in a station that is
   587 			/* NON-stop flag is misused to see if a train is in a station that is
   521 			 * on his order list or not */
   588 			 * on his order list or not */
   522 			if (sel_ord == u->cur_order_index && u->current_order.type == OT_LOADING &&
   589 			if (sel_ord == u->cur_order_index && u->current_order.IsType(OT_LOADING)) {
   523 					HasBit(u->current_order.flags, OF_NON_STOP)) {
   590 				u->current_order.SetNonStopType(OFB_NO_NON_STOP);
   524 				u->current_order.flags = 0;
       
   525 			}
   591 			}
   526 
   592 
   527 			/* Update any possible open window of the vehicle */
   593 			/* Update any possible open window of the vehicle */
   528 			InvalidateVehicleOrder(u);
   594 			InvalidateVehicleOrder(u);
   529 		}
   595 		}
   556 	if (flags & DC_EXEC) {
   622 	if (flags & DC_EXEC) {
   557 		v->cur_order_index = sel_ord;
   623 		v->cur_order_index = sel_ord;
   558 
   624 
   559 		if (v->type == VEH_ROAD) ClearSlot(v);
   625 		if (v->type == VEH_ROAD) ClearSlot(v);
   560 
   626 
   561 		if (v->current_order.type == OT_LOADING) {
   627 		if (v->current_order.IsType(OT_LOADING)) v->LeaveStation();
   562 			v->LeaveStation();
       
   563 			/* NON-stop flag is misused to see if a train is in a station that is
       
   564 			 * on his order list or not */
       
   565 			if (HasBit(v->current_order.flags, OF_NON_STOP)) v->current_order.flags = 0;
       
   566 		}
       
   567 
   628 
   568 		InvalidateVehicleOrder(v);
   629 		InvalidateVehicleOrder(v);
   569 	}
   630 	}
   570 
   631 
   571 	/* We have an aircraft/ship, they have a mini-schedule, so update them all */
   632 	/* We have an aircraft/ship, they have a mini-schedule, so update them all */
   687 
   748 
   688 	/* Is it a valid order? */
   749 	/* Is it a valid order? */
   689 	if (sel_ord >= v->num_orders) return CMD_ERROR;
   750 	if (sel_ord >= v->num_orders) return CMD_ERROR;
   690 
   751 
   691 	order = GetVehicleOrder(v, sel_ord);
   752 	order = GetVehicleOrder(v, sel_ord);
   692 	if ((order->type != OT_GOTO_STATION  || GetStation(order->dest)->IsBuoy()) &&
   753 	if ((!order->IsType(OT_GOTO_STATION)  || GetStation(order->GetDestination())->IsBuoy()) &&
   693 			(order->type != OT_GOTO_DEPOT    || p2 == OF_UNLOAD) &&
   754 			(!order->IsType(OT_GOTO_DEPOT)    || p2 == OF_UNLOAD) &&
   694 			(order->type != OT_GOTO_WAYPOINT || p2 != OF_NON_STOP)) {
   755 			(!order->IsType(OT_GOTO_WAYPOINT) || p2 != OF_NON_STOP)) {
   695 		return CMD_ERROR;
   756 		return CMD_ERROR;
   696 	}
   757 	}
   697 
   758 
   698 	if (flags & DC_EXEC) {
   759 	if (flags & DC_EXEC) {
   699 		switch (p2) {
   760 		switch (p2) {
   700 		case OF_FULL_LOAD:
   761 			case OF_FULL_LOAD:
   701 			ToggleBit(order->flags, OF_FULL_LOAD);
   762 				if (order->IsType(OT_GOTO_DEPOT)) {
   702 			if (order->type != OT_GOTO_DEPOT) ClrBit(order->flags, OF_UNLOAD);
   763 					order->SetDepotOrderType(order->GetDepotOrderType() ^ OFB_SERVICE_IF_NEEDED);
   703 			break;
   764 				} else {
   704 		case OF_UNLOAD:
   765 					order->SetLoadType(order->GetUnloadType() ^ OFB_FULL_LOAD);
   705 			ToggleBit(order->flags, OF_UNLOAD);
   766 					order->SetUnloadType(order->GetUnloadType() & ~OFB_UNLOAD);
   706 			ClrBit(order->flags, OF_FULL_LOAD);
   767 				}
   707 			break;
   768 				break;
   708 		case OF_NON_STOP:
   769 			case OF_UNLOAD:
   709 			ToggleBit(order->flags, OF_NON_STOP);
   770 				order->SetUnloadType(order->GetUnloadType() ^ OFB_UNLOAD);
   710 			break;
   771 				order->SetLoadType(0);
   711 		case OF_TRANSFER:
   772 				break;
   712 			ToggleBit(order->flags, OF_TRANSFER);
   773 			case OF_NON_STOP:
   713 			break;
   774 				order->SetNonStopType(order->GetNonStopType() ^ OFB_NON_STOP);
   714 		default: NOT_REACHED();
   775 				break;
       
   776 			case OF_TRANSFER:
       
   777 				order->SetUnloadType(order->GetUnloadType() ^ OFB_TRANSFER);
       
   778 				break;
       
   779 			default: NOT_REACHED();
   715 		}
   780 		}
   716 
   781 
   717 		/* Update the windows and full load flags, also for vehicles that share the same order list */
   782 		/* Update the windows and full load flags, also for vehicles that share the same order list */
   718 		{
   783 		{
   719 			Vehicle* u;
   784 			Vehicle* u;
   729 				 * other cases for the OrderTypeByte the flags are not used,
   794 				 * other cases for the OrderTypeByte the flags are not used,
   730 				 * so do not care and those orders should not be active
   795 				 * so do not care and those orders should not be active
   731 				 * when this function is called.
   796 				 * when this function is called.
   732 				 */
   797 				 */
   733 				if (sel_ord == u->cur_order_index &&
   798 				if (sel_ord == u->cur_order_index &&
   734 						u->current_order.type != OT_GOTO_DEPOT &&
   799 						!u->current_order.IsType(OT_GOTO_DEPOT) &&
   735 						HasBit(u->current_order.flags, OF_FULL_LOAD) != HasBit(order->flags, OF_FULL_LOAD)) {
   800 						u->current_order.GetLoadType() != order->GetLoadType()) {
   736 					ToggleBit(u->current_order.flags, OF_FULL_LOAD);
   801 					u->current_order.SetLoadType(order->GetLoadType());
   737 				}
   802 				}
   738 				InvalidateVehicleOrder(u);
   803 				InvalidateVehicleOrder(u);
   739 			}
   804 			}
   740 		}
   805 		}
   741 	}
   806 	}
   826 			if (src->type == VEH_ROAD) {
   891 			if (src->type == VEH_ROAD) {
   827 				const Order *order;
   892 				const Order *order;
   828 				TileIndex required_dst = INVALID_TILE;
   893 				TileIndex required_dst = INVALID_TILE;
   829 
   894 
   830 				FOR_VEHICLE_ORDERS(src, order) {
   895 				FOR_VEHICLE_ORDERS(src, order) {
   831 					if (order->type == OT_GOTO_STATION) {
   896 					if (order->IsType(OT_GOTO_STATION)) {
   832 						const Station *st = GetStation(order->dest);
   897 						const Station *st = GetStation(order->GetDestination());
   833 						if (IsCargoInClass(dst->cargo_type, CC_PASSENGERS)) {
   898 						if (IsCargoInClass(dst->cargo_type, CC_PASSENGERS)) {
   834 							if (st->bus_stops != NULL) required_dst = st->bus_stops->xy;
   899 							if (st->bus_stops != NULL) required_dst = st->bus_stops->xy;
   835 						} else {
   900 						} else {
   836 							if (st->truck_stops != NULL) required_dst = st->truck_stops->xy;
   901 							if (st->truck_stops != NULL) required_dst = st->truck_stops->xy;
   837 						}
   902 						}
   855 				DeleteVehicleOrders(dst);
   920 				DeleteVehicleOrders(dst);
   856 
   921 
   857 				order_dst = &dst->orders;
   922 				order_dst = &dst->orders;
   858 				FOR_VEHICLE_ORDERS(src, order) {
   923 				FOR_VEHICLE_ORDERS(src, order) {
   859 					*order_dst = new Order();
   924 					*order_dst = new Order();
   860 					AssignOrder(*order_dst, *order);
   925 					(*order_dst)->AssignOrder(*order);
   861 					order_dst = &(*order_dst)->next;
   926 					order_dst = &(*order_dst)->next;
   862 				}
   927 				}
   863 
   928 
   864 				dst->num_orders = src->num_orders;
   929 				dst->num_orders = src->num_orders;
   865 
   930 
   904 	if (order == NULL) return CMD_ERROR;
   969 	if (order == NULL) return CMD_ERROR;
   905 
   970 
   906 	if (flags & DC_EXEC) {
   971 	if (flags & DC_EXEC) {
   907 		Vehicle *u;
   972 		Vehicle *u;
   908 
   973 
   909 		order->refit_cargo = cargo;
   974 		order->SetRefit(cargo, subtype);
   910 		order->refit_subtype = subtype;
       
   911 
   975 
   912 		u = GetFirstVehicleFromSharedList(v);
   976 		u = GetFirstVehicleFromSharedList(v);
   913 		for (; u != NULL; u = u->next_shared) {
   977 		for (; u != NULL; u = u->next_shared) {
   914 			/* Update any possible open window of the vehicle */
   978 			/* Update any possible open window of the vehicle */
   915 			InvalidateVehicleOrder(u);
   979 			InvalidateVehicleOrder(u);
   916 
   980 
   917 			/* If the vehicle already got the current depot set as current order, then update current order as well */
   981 			/* If the vehicle already got the current depot set as current order, then update current order as well */
   918 			if (u->cur_order_index == order_number && HasBit(u->current_order.flags, OF_PART_OF_ORDERS)) {
   982 			if (u->cur_order_index == order_number && HasBit(u->current_order.GetDepotOrderType(), OF_PART_OF_ORDERS)) {
   919 				u->current_order.refit_cargo = cargo;
   983 				u->current_order.SetRefit(cargo, subtype);
   920 				u->current_order.refit_subtype = subtype;
       
   921 			}
   984 			}
   922 		}
   985 		}
   923 	}
   986 	}
   924 
   987 
   925 	return CommandCost();
   988 	return CommandCost();
   998 		/* CMD_NO_TEST_IF_IN_NETWORK is used here, because CMD_INSERT_ORDER checks if the
  1061 		/* CMD_NO_TEST_IF_IN_NETWORK is used here, because CMD_INSERT_ORDER checks if the
   999 		 *  order number is one more than the current amount of orders, and because
  1062 		 *  order number is one more than the current amount of orders, and because
  1000 		 *  in network the commands are queued before send, the second insert always
  1063 		 *  in network the commands are queued before send, the second insert always
  1001 		 *  fails in test mode. By bypassing the test-mode, that no longer is a problem. */
  1064 		 *  fails in test mode. By bypassing the test-mode, that no longer is a problem. */
  1002 		for (uint i = 0; bak->order[i].IsValid(); i++) {
  1065 		for (uint i = 0; bak->order[i].IsValid(); i++) {
  1003 			if (!DoCommandP(0, v->index + (i << 16), PackOrder(&bak->order[i]), NULL,
  1066 			if (!DoCommandP(0, v->index + (i << 16), bak->order[i].Pack(), NULL,
  1004 					CMD_INSERT_ORDER | CMD_NO_TEST_IF_IN_NETWORK)) {
  1067 					CMD_INSERT_ORDER | CMD_NO_TEST_IF_IN_NETWORK)) {
  1005 				break;
  1068 				break;
  1006 			}
  1069 			}
  1007 
  1070 
  1008 			/* Copy timetable if enabled */
  1071 			/* Copy timetable if enabled */
  1104 		/* Check the order list */
  1167 		/* Check the order list */
  1105 		n_st = 0;
  1168 		n_st = 0;
  1106 
  1169 
  1107 		FOR_VEHICLE_ORDERS(v, order) {
  1170 		FOR_VEHICLE_ORDERS(v, order) {
  1108 			/* Dummy order? */
  1171 			/* Dummy order? */
  1109 			if (order->type == OT_DUMMY) {
  1172 			if (order->IsType(OT_DUMMY)) {
  1110 				problem_type = 1;
  1173 				problem_type = 1;
  1111 				break;
  1174 				break;
  1112 			}
  1175 			}
  1113 			/* Does station have a load-bay for this vehicle? */
  1176 			/* Does station have a load-bay for this vehicle? */
  1114 			if (order->type == OT_GOTO_STATION) {
  1177 			if (order->IsType(OT_GOTO_STATION)) {
  1115 				const Station* st = GetStation(order->dest);
  1178 				const Station* st = GetStation(order->GetDestination());
  1116 				TileIndex required_tile = GetStationTileForVehicle(v, st);
  1179 				TileIndex required_tile = GetStationTileForVehicle(v, st);
  1117 
  1180 
  1118 				n_st++;
  1181 				n_st++;
  1119 				if (required_tile == 0) problem_type = 3;
  1182 				if (required_tile == 0) problem_type = 3;
  1120 			}
  1183 			}
  1122 
  1185 
  1123 		/* Check if the last and the first order are the same */
  1186 		/* Check if the last and the first order are the same */
  1124 		if (v->num_orders > 1) {
  1187 		if (v->num_orders > 1) {
  1125 			const Order* last = GetLastVehicleOrder(v);
  1188 			const Order* last = GetLastVehicleOrder(v);
  1126 
  1189 
  1127 			if (v->orders->type  == last->type &&
  1190 			if (v->orders->Equals(*last)) {
  1128 					v->orders->flags == last->flags &&
       
  1129 					v->orders->dest  == last->dest) {
       
  1130 				problem_type = 2;
  1191 				problem_type = 2;
  1131 			}
  1192 			}
  1132 		}
  1193 		}
  1133 
  1194 
  1134 		/* Do we only have 1 station in our order list? */
  1195 		/* Do we only have 1 station in our order list? */
  1172 		if (v->last_station_visited == destination && type == OT_GOTO_STATION) {
  1233 		if (v->last_station_visited == destination && type == OT_GOTO_STATION) {
  1173 			v->last_station_visited = INVALID_STATION;
  1234 			v->last_station_visited = INVALID_STATION;
  1174 		}
  1235 		}
  1175 
  1236 
  1176 		order = &v->current_order;
  1237 		order = &v->current_order;
  1177 		if ((v->type == VEH_AIRCRAFT && order->type == OT_GOTO_DEPOT ? OT_GOTO_STATION : order->type) == type &&
  1238 		if ((v->type == VEH_AIRCRAFT && order->IsType(OT_GOTO_DEPOT) ? OT_GOTO_STATION : order->GetType()) == type &&
  1178 				v->current_order.dest == destination) {
  1239 				v->current_order.GetDestination() == destination) {
  1179 			order->type = OT_DUMMY;
  1240 			order->MakeDummy();
  1180 			order->flags = 0;
       
  1181 			InvalidateWindow(WC_VEHICLE_VIEW, v->index);
  1241 			InvalidateWindow(WC_VEHICLE_VIEW, v->index);
  1182 		}
  1242 		}
  1183 
  1243 
  1184 		/* Clear the order from the order-list */
  1244 		/* Clear the order from the order-list */
  1185 		invalidate = false;
  1245 		invalidate = false;
  1186 		FOR_VEHICLE_ORDERS(v, order) {
  1246 		FOR_VEHICLE_ORDERS(v, order) {
  1187 			if ((v->type == VEH_AIRCRAFT && order->type == OT_GOTO_DEPOT ? OT_GOTO_STATION : order->type) == type &&
  1247 			if ((v->type == VEH_AIRCRAFT && order->IsType(OT_GOTO_DEPOT) ? OT_GOTO_STATION : order->GetType()) == type &&
  1188 					order->dest == destination) {
  1248 					order->GetDestination() == destination) {
  1189 				order->type = OT_DUMMY;
  1249 				order->MakeDummy();
  1190 				order->flags = 0;
       
  1191 				invalidate = true;
  1250 				invalidate = true;
  1192 			}
  1251 			}
  1193 		}
  1252 		}
  1194 
  1253 
  1195 		/* Only invalidate once, and if needed */
  1254 		/* Only invalidate once, and if needed */
  1207 bool VehicleHasDepotOrders(const Vehicle *v)
  1266 bool VehicleHasDepotOrders(const Vehicle *v)
  1208 {
  1267 {
  1209 	const Order *order;
  1268 	const Order *order;
  1210 
  1269 
  1211 	FOR_VEHICLE_ORDERS(v, order) {
  1270 	FOR_VEHICLE_ORDERS(v, order) {
  1212 		if (order->type == OT_GOTO_DEPOT)
  1271 		if (order->IsType(OT_GOTO_DEPOT))
  1213 			return true;
  1272 			return true;
  1214 	}
  1273 	}
  1215 
  1274 
  1216 	return false;
  1275 	return false;
  1217 }
  1276 }
  1273 Date GetServiceIntervalClamped(uint index)
  1332 Date GetServiceIntervalClamped(uint index)
  1274 {
  1333 {
  1275 	return (_patches.servint_ispercent) ? Clamp(index, MIN_SERVINT_PERCENT, MAX_SERVINT_PERCENT) : Clamp(index, MIN_SERVINT_DAYS, MAX_SERVINT_DAYS);
  1334 	return (_patches.servint_ispercent) ? Clamp(index, MIN_SERVINT_PERCENT, MAX_SERVINT_PERCENT) : Clamp(index, MIN_SERVINT_DAYS, MAX_SERVINT_DAYS);
  1276 }
  1335 }
  1277 
  1336 
  1278 
       
  1279 /**
  1337 /**
  1280  *
  1338  *
  1281  * Check if a vehicle has any valid orders
  1339  * Check if a vehicle has any valid orders
  1282  *
  1340  *
  1283  * @return false if there are no valid orders
  1341  * @return false if there are no valid orders
  1284  *
  1342  *
  1285  */
  1343  */
  1286 bool CheckForValidOrders(const Vehicle* v)
  1344 static bool CheckForValidOrders(const Vehicle *v)
  1287 {
  1345 {
  1288 	const Order *order;
  1346 	const Order *order;
  1289 
  1347 
  1290 	FOR_VEHICLE_ORDERS(v, order) if (order->type != OT_DUMMY) return true;
  1348 	FOR_VEHICLE_ORDERS(v, order) if (!order->IsType(OT_DUMMY)) return true;
  1291 
  1349 
  1292 	return false;
  1350 	return false;
       
  1351 }
       
  1352 
       
  1353 /**
       
  1354  * Handle the orders of a vehicle and determine the next place
       
  1355  * to go to if needed.
       
  1356  * @param v the vehicle to do this for.
       
  1357  * @return true *if* the vehicle is eligible for reversing
       
  1358  *              (basically only when leaving a station).
       
  1359  */
       
  1360 bool ProcessOrders(Vehicle *v)
       
  1361 {
       
  1362 	switch (v->current_order.GetType()) {
       
  1363 		case OT_GOTO_DEPOT:
       
  1364 			/* Let a depot order in the orderlist interrupt. */
       
  1365 			if (!(v->current_order.GetDepotOrderType() & OFB_PART_OF_ORDERS)) return false;
       
  1366 
       
  1367 			if ((v->current_order.GetDepotOrderType() & OFB_SERVICE_IF_NEEDED) && !VehicleNeedsService(v)) {
       
  1368 				UpdateVehicleTimetable(v, true);
       
  1369 				v->cur_order_index++;
       
  1370 			}
       
  1371 			break;
       
  1372 
       
  1373 		case OT_LOADING:
       
  1374 			return false;
       
  1375 
       
  1376 		case OT_LEAVESTATION:
       
  1377 			if (v->type != VEH_AIRCRAFT) return false;
       
  1378 			break;
       
  1379 
       
  1380 		default: break;
       
  1381 	}
       
  1382 
       
  1383 	/**
       
  1384 	 * Reversing because of order change is allowed only just after leaving a
       
  1385 	 * station (and the difficulty setting to allowed, of course)
       
  1386 	 * this can be detected because only after OT_LEAVESTATION, current_order
       
  1387 	 * will be reset to nothing. (That also happens if no order, but in that case
       
  1388 	 * it won't hit the point in code where may_reverse is checked)
       
  1389 	 */
       
  1390 	bool may_reverse = v->current_order.IsType(OT_NOTHING);
       
  1391 
       
  1392 	/* Check if we've reached the waypoint? */
       
  1393 	if (v->current_order.IsType(OT_GOTO_WAYPOINT) && v->tile == v->dest_tile) {
       
  1394 		UpdateVehicleTimetable(v, true);
       
  1395 		v->cur_order_index++;
       
  1396 	}
       
  1397 
       
  1398 	/* Check if we've reached a non-stop station while TTDPatch nonstop is enabled.. */
       
  1399 	if (_patches.new_nonstop &&
       
  1400 			v->current_order.GetNonStopType() & OFB_NON_STOP &&
       
  1401 			IsTileType(v->tile, MP_STATION) &&
       
  1402 			v->current_order.GetDestination() == GetStationIndex(v->tile)) {
       
  1403 		v->last_station_visited = v->current_order.GetDestination();
       
  1404 		UpdateVehicleTimetable(v, true);
       
  1405 		v->cur_order_index++;
       
  1406 	}
       
  1407 
       
  1408 	/* Get the current order */
       
  1409 	if (v->cur_order_index >= v->num_orders) v->cur_order_index = 0;
       
  1410 
       
  1411 	const Order *order = GetVehicleOrder(v, v->cur_order_index);
       
  1412 
       
  1413 	/* If no order, do nothing. */
       
  1414 	if (order == NULL || (v->type == VEH_AIRCRAFT && order->IsType(OT_DUMMY) && !CheckForValidOrders(v))) {
       
  1415 		if (v->type == VEH_AIRCRAFT) {
       
  1416 			/* Aircraft do something vastly different here, so handle separately */
       
  1417 			extern void HandleMissingAircraftOrders(Vehicle *v);
       
  1418 			HandleMissingAircraftOrders(v);
       
  1419 			return false;
       
  1420 		}
       
  1421 
       
  1422 		v->current_order.Free();
       
  1423 		v->dest_tile = 0;
       
  1424 		if (v->type == VEH_ROAD) ClearSlot(v);
       
  1425 		return false;
       
  1426 	}
       
  1427 
       
  1428 	/* If it is unchanged, keep it. */
       
  1429 	if (order->Equals(v->current_order) &&
       
  1430 			(v->type != VEH_SHIP || !order->IsType(OT_GOTO_STATION) || GetStation(order->GetDestination())->dock_tile != 0)) {
       
  1431 		return false;
       
  1432 	}
       
  1433 
       
  1434 	/* Otherwise set it, and determine the destination tile. */
       
  1435 	v->current_order = *order;
       
  1436 
       
  1437 	InvalidateVehicleOrder(v);
       
  1438 	switch (v->type) {
       
  1439 		default:
       
  1440 			NOT_REACHED();
       
  1441 
       
  1442 		case VEH_ROAD:
       
  1443 		case VEH_TRAIN:
       
  1444 			break;
       
  1445 
       
  1446 		case VEH_AIRCRAFT:
       
  1447 		case VEH_SHIP:
       
  1448 			InvalidateWindowClasses(v->GetVehicleListWindowClass());
       
  1449 			break;
       
  1450 	}
       
  1451 
       
  1452 	switch (order->GetType()) {
       
  1453 		case OT_GOTO_STATION:
       
  1454 			v->dest_tile = v->GetOrderStationLocation(order->GetDestination());
       
  1455 			break;
       
  1456 
       
  1457 		case OT_GOTO_DEPOT:
       
  1458 			if (v->type != VEH_AIRCRAFT) v->dest_tile = GetDepot(order->GetDestination())->xy;
       
  1459 			break;
       
  1460 
       
  1461 		case OT_GOTO_WAYPOINT:
       
  1462 			v->dest_tile = GetWaypoint(order->GetDestination())->xy;
       
  1463 			break;
       
  1464 
       
  1465 		default:
       
  1466 			v->dest_tile = 0;
       
  1467 			return false;
       
  1468 	}
       
  1469 
       
  1470 	return may_reverse;
       
  1471 }
       
  1472 
       
  1473 /**
       
  1474  * Check whether the given vehicle should stop at the given station
       
  1475  * based on this order and the non-stop settings.
       
  1476  * @param v       the vehicle that might be stopping.
       
  1477  * @param station the station to stop at.
       
  1478  * @return true if the vehicle should stop.
       
  1479  */
       
  1480 bool Order::ShouldStopAtStation(const Vehicle *v, StationID station) const
       
  1481 {
       
  1482 	return
       
  1483 			v->last_station_visited != station && // Do stop only when we've not just been there
       
  1484 			type == OT_GOTO_STATION &&            // Do stop only when going to a station
       
  1485 			/* Finally do stop when the non-stop flag is not set, or when we should stop at
       
  1486 			 * this station according to the new_nonstop setting. */
       
  1487 			(!(this->flags & OFB_NON_STOP) || ((this->dest != station) == _patches.new_nonstop));
  1293 }
  1488 }
  1294 
  1489 
  1295 void InitializeOrders()
  1490 void InitializeOrders()
  1296 {
  1491 {
  1297 	_Order_pool.CleanPool();
  1492 	_Order_pool.CleanPool();
  1298 	_Order_pool.AddBlockToPool();
  1493 	_Order_pool.AddBlockToPool();
  1299 
  1494 
  1300 	_backup_orders_tile = 0;
  1495 	_backup_orders_tile = 0;
  1301 }
  1496 }
  1302 
  1497 
       
  1498 const SaveLoad *GetOrderDescription() {
  1303 static const SaveLoad _order_desc[] = {
  1499 static const SaveLoad _order_desc[] = {
  1304 	SLE_VAR(Order, type,  SLE_UINT8),
  1500 	SLE_VAR(Order, type,  SLE_UINT8),
  1305 	SLE_VAR(Order, flags, SLE_UINT8),
  1501 	SLE_VAR(Order, flags, SLE_UINT8),
  1306 	SLE_VAR(Order, dest,  SLE_UINT16),
  1502 	SLE_VAR(Order, dest,  SLE_UINT16),
  1307 	SLE_REF(Order, next,  REF_ORDER),
  1503 	SLE_REF(Order, next,  REF_ORDER),
  1313 	/* Leftover from the minor savegame version stuff
  1509 	/* Leftover from the minor savegame version stuff
  1314 	 * We will never use those free bytes, but we have to keep this line to allow loading of old savegames */
  1510 	 * We will never use those free bytes, but we have to keep this line to allow loading of old savegames */
  1315 	SLE_CONDNULL(10, 5, 35),
  1511 	SLE_CONDNULL(10, 5, 35),
  1316 	SLE_END()
  1512 	SLE_END()
  1317 };
  1513 };
       
  1514 	return _order_desc;
       
  1515 }
  1318 
  1516 
  1319 static void Save_ORDR()
  1517 static void Save_ORDR()
  1320 {
  1518 {
  1321 	Order *order;
  1519 	Order *order;
  1322 
  1520 
  1323 	FOR_ALL_ORDERS(order) {
  1521 	FOR_ALL_ORDERS(order) {
  1324 		SlSetArrayIndex(order->index);
  1522 		SlSetArrayIndex(order->index);
  1325 		SlObject(order, _order_desc);
  1523 		SlObject(order, GetOrderDescription());
  1326 	}
  1524 	}
  1327 }
  1525 }
  1328 
  1526 
  1329 static void Load_ORDR()
  1527 static void Load_ORDR()
  1330 {
  1528 {
  1342 
  1540 
  1343 			SlArray(orders, len, SLE_UINT16);
  1541 			SlArray(orders, len, SLE_UINT16);
  1344 
  1542 
  1345 			for (i = 0; i < len; ++i) {
  1543 			for (i = 0; i < len; ++i) {
  1346 				Order *order = new (i) Order();
  1544 				Order *order = new (i) Order();
  1347 				AssignOrder(order, UnpackVersion4Order(orders[i]));
  1545 				order->AssignOrder(UnpackVersion4Order(orders[i]));
  1348 			}
  1546 			}
  1349 
  1547 
  1350 			free(orders);
  1548 			free(orders);
  1351 		} else if (CheckSavegameVersionOldStyle(5, 2)) {
  1549 		} else if (CheckSavegameVersionOldStyle(5, 2)) {
  1352 			len /= sizeof(uint16);
  1550 			len /= sizeof(uint16);
  1353 			uint16 *orders = MallocT<uint16>(len + 1);
  1551 			uint16 *orders = MallocT<uint16>(len + 1);
  1354 
  1552 
  1355 			SlArray(orders, len, SLE_UINT32);
  1553 			SlArray(orders, len, SLE_UINT32);
  1356 
  1554 
  1357 			for (i = 0; i < len; ++i) {
  1555 			for (i = 0; i < len; ++i) {
  1358 				Order *order = new (i) Order();
  1556 				new (i) Order(orders[i]);
  1359 				AssignOrder(order, UnpackOrder(orders[i]));
       
  1360 			}
  1557 			}
  1361 
  1558 
  1362 			free(orders);
  1559 			free(orders);
  1363 		}
  1560 		}
  1364 
  1561 
  1373 	} else {
  1570 	} else {
  1374 		int index;
  1571 		int index;
  1375 
  1572 
  1376 		while ((index = SlIterateArray()) != -1) {
  1573 		while ((index = SlIterateArray()) != -1) {
  1377 			Order *order = new (index) Order();
  1574 			Order *order = new (index) Order();
  1378 			SlObject(order, _order_desc);
  1575 			SlObject(order, GetOrderDescription());
  1379 		}
  1576 		}
  1380 	}
  1577 	}
  1381 }
  1578 }
  1382 
  1579 
  1383 extern const ChunkHandler _order_chunk_handlers[] = {
  1580 extern const ChunkHandler _order_chunk_handlers[] = {