order_cmd.c
changeset 4389 e4555522d257
parent 4384 293c0d26294c
child 4391 7bfd170bfdf5
equal deleted inserted replaced
4388:e5a166837162 4389:e4555522d257
    45 Order UnpackOldOrder(uint16 packed)
    45 Order UnpackOldOrder(uint16 packed)
    46 {
    46 {
    47 	Order order;
    47 	Order order;
    48 	order.type    = GB(packed, 0, 4);
    48 	order.type    = GB(packed, 0, 4);
    49 	order.flags   = GB(packed, 4, 4);
    49 	order.flags   = GB(packed, 4, 4);
    50 	order.station = GB(packed, 8, 8);
    50 	order.dest.station = GB(packed, 8, 8);
    51 	order.next    = NULL;
    51 	order.next    = NULL;
    52 
    52 
    53 	// Sanity check
    53 	// Sanity check
    54 	// TTD stores invalid orders as OT_NOTHING with non-zero flags/station
    54 	// TTD stores invalid orders as OT_NOTHING with non-zero flags/station
    55 	if (order.type == OT_NOTHING && (order.flags != 0 || order.station != 0)) {
    55 	if (order.type == OT_NOTHING && (order.flags != 0 || order.dest.station != 0)) {
    56 		order.type = OT_DUMMY;
    56 		order.type = OT_DUMMY;
    57 		order.flags = 0;
    57 		order.flags = 0;
    58 	}
    58 	}
    59 
    59 
    60 	return order;
    60 	return order;
    68 static Order UnpackVersion4Order(uint16 packed)
    68 static Order UnpackVersion4Order(uint16 packed)
    69 {
    69 {
    70 	Order order;
    70 	Order order;
    71 	order.type    = GB(packed, 0, 4);
    71 	order.type    = GB(packed, 0, 4);
    72 	order.flags   = GB(packed, 4, 4);
    72 	order.flags   = GB(packed, 4, 4);
    73 	order.station = GB(packed, 8, 8);
    73 	order.dest.station = GB(packed, 8, 8);
    74 	order.next    = NULL;
    74 	order.next    = NULL;
    75 	order.index   = 0; // avoid compiler warning
    75 	order.index   = 0; // avoid compiler warning
    76 	return order;
    76 	return order;
    77 }
    77 }
    78 
    78 
   142  */
   142  */
   143 void AssignOrder(Order *order, Order data)
   143 void AssignOrder(Order *order, Order data)
   144 {
   144 {
   145 	order->type    = data.type;
   145 	order->type    = data.type;
   146 	order->flags   = data.flags;
   146 	order->flags   = data.flags;
   147 	order->station = data.station;
   147 	order->dest.station = data.dest.station;
   148 }
   148 }
   149 
   149 
   150 
   150 
   151 /**
   151 /**
   152  * Delete all news items regarding defective orders about a vehicle
   152  * Delete all news items regarding defective orders about a vehicle
   189 	 * and has the correct flags if any */
   189 	 * and has the correct flags if any */
   190 	switch (new_order.type) {
   190 	switch (new_order.type) {
   191 		case OT_GOTO_STATION: {
   191 		case OT_GOTO_STATION: {
   192 			const Station *st;
   192 			const Station *st;
   193 
   193 
   194 			if (!IsValidStationID(new_order.station)) return CMD_ERROR;
   194 			if (!IsValidStationID(new_order.dest.station)) return CMD_ERROR;
   195 			st = GetStation(new_order.station);
   195 			st = GetStation(new_order.dest.station);
   196 
   196 
   197 			if (st->airport_type != AT_OILRIG && !IsBuoy(st) && !CheckOwnership(st->owner)) {
   197 			if (st->airport_type != AT_OILRIG && !IsBuoy(st) && !CheckOwnership(st->owner)) {
   198 				return CMD_ERROR;
   198 				return CMD_ERROR;
   199 			}
   199 			}
   200 
   200 
   250 
   250 
   251 		case OT_GOTO_DEPOT: {
   251 		case OT_GOTO_DEPOT: {
   252 			if (v->type == VEH_Aircraft) {
   252 			if (v->type == VEH_Aircraft) {
   253 				const Station* st;
   253 				const Station* st;
   254 
   254 
   255 				if (!IsValidStationID(new_order.station)) return CMD_ERROR;
   255 				if (!IsValidStationID(new_order.dest.station)) return CMD_ERROR;
   256 				st = GetStation(new_order.station);
   256 				st = GetStation(new_order.dest.station);
   257 
   257 
   258 				if ((st->airport_type != AT_OILRIG && !CheckOwnership(st->owner)) ||
   258 				if ((st->airport_type != AT_OILRIG && !CheckOwnership(st->owner)) ||
   259 						!(st->facilities & FACIL_AIRPORT) ||
   259 						!(st->facilities & FACIL_AIRPORT) ||
   260 						GetAirport(st->airport_type)->nof_depots == 0) {
   260 						GetAirport(st->airport_type)->nof_depots == 0) {
   261 					return CMD_ERROR;
   261 					return CMD_ERROR;
   262 				}
   262 				}
   263 			} else {
   263 			} else {
   264 				const Depot* dp;
   264 				const Depot* dp;
   265 
   265 
   266 				if (!IsValidDepotID(new_order.station)) return CMD_ERROR;
   266 				if (!IsValidDepotID(new_order.dest.depot)) return CMD_ERROR;
   267 				dp = GetDepot(new_order.station);
   267 				dp = GetDepot(new_order.dest.depot);
   268 
   268 
   269 				if (!CheckOwnership(GetTileOwner(dp->xy))) return CMD_ERROR;
   269 				if (!CheckOwnership(GetTileOwner(dp->xy))) return CMD_ERROR;
   270 
   270 
   271 				switch (v->type) {
   271 				switch (v->type) {
   272 					case VEH_Train:
   272 					case VEH_Train:
   306 		case OT_GOTO_WAYPOINT: {
   306 		case OT_GOTO_WAYPOINT: {
   307 			const Waypoint* wp;
   307 			const Waypoint* wp;
   308 
   308 
   309 			if (v->type != VEH_Train) return CMD_ERROR;
   309 			if (v->type != VEH_Train) return CMD_ERROR;
   310 
   310 
   311 			if (!IsValidWaypointID(new_order.station)) return CMD_ERROR;
   311 			if (!IsValidWaypointID(new_order.dest.waypoint)) return CMD_ERROR;
   312 			wp = GetWaypoint(new_order.station);
   312 			wp = GetWaypoint(new_order.dest.waypoint);
   313 
   313 
   314 			if (!CheckOwnership(GetTileOwner(wp->xy))) return CMD_ERROR;
   314 			if (!CheckOwnership(GetTileOwner(wp->xy))) return CMD_ERROR;
   315 
   315 
   316 			/* Order flags can be any of the following for waypoints:
   316 			/* Order flags can be any of the following for waypoints:
   317 			 * [non-stop]
   317 			 * [non-stop]
   344 	if (v->type == VEH_Ship && IS_HUMAN_PLAYER(v->owner) &&
   344 	if (v->type == VEH_Ship && IS_HUMAN_PLAYER(v->owner) &&
   345 		sel_ord != 0 && GetVehicleOrder(v, sel_ord - 1)->type == OT_GOTO_STATION
   345 		sel_ord != 0 && GetVehicleOrder(v, sel_ord - 1)->type == OT_GOTO_STATION
   346 		&& !_patches.new_pathfinding_all) {
   346 		&& !_patches.new_pathfinding_all) {
   347 
   347 
   348 		int dist = DistanceManhattan(
   348 		int dist = DistanceManhattan(
   349 			GetStation(GetVehicleOrder(v, sel_ord - 1)->station)->xy,
   349 			GetStation(GetVehicleOrder(v, sel_ord - 1)->dest.station)->xy,
   350 			GetStation(new_order.station)->xy // XXX type != OT_GOTO_STATION?
   350 			GetStation(new_order.dest.station)->xy // XXX type != OT_GOTO_STATION?
   351 		);
   351 		);
   352 		if (dist >= 130)
   352 		if (dist >= 130)
   353 			return_cmd_error(STR_0210_TOO_FAR_FROM_PREVIOUS_DESTINATIO);
   353 			return_cmd_error(STR_0210_TOO_FAR_FROM_PREVIOUS_DESTINATIO);
   354 	}
   354 	}
   355 
   355 
   702 				const Order *order;
   702 				const Order *order;
   703 				TileIndex required_dst = INVALID_TILE;
   703 				TileIndex required_dst = INVALID_TILE;
   704 
   704 
   705 				FOR_VEHICLE_ORDERS(src, order) {
   705 				FOR_VEHICLE_ORDERS(src, order) {
   706 					if (order->type == OT_GOTO_STATION) {
   706 					if (order->type == OT_GOTO_STATION) {
   707 						const Station *st = GetStation(order->station);
   707 						const Station *st = GetStation(order->dest.station);
   708 						if (dst->cargo_type == CT_PASSENGERS) {
   708 						if (dst->cargo_type == CT_PASSENGERS) {
   709 							if (st->bus_stops != NULL) required_dst = st->bus_stops->xy;
   709 							if (st->bus_stops != NULL) required_dst = st->bus_stops->xy;
   710 						} else {
   710 						} else {
   711 							if (st->truck_stops != NULL) required_dst = st->truck_stops->xy;
   711 							if (st->truck_stops != NULL) required_dst = st->truck_stops->xy;
   712 						}
   712 						}
   917 				problem_type = 1;
   917 				problem_type = 1;
   918 				break;
   918 				break;
   919 			}
   919 			}
   920 			/* Does station have a load-bay for this vehicle? */
   920 			/* Does station have a load-bay for this vehicle? */
   921 			if (order->type == OT_GOTO_STATION) {
   921 			if (order->type == OT_GOTO_STATION) {
   922 				const Station* st = GetStation(order->station);
   922 				const Station* st = GetStation(order->dest.station);
   923 				TileIndex required_tile = GetStationTileForVehicle(v, st);
   923 				TileIndex required_tile = GetStationTileForVehicle(v, st);
   924 
   924 
   925 				n_st++;
   925 				n_st++;
   926 				if (required_tile == 0) problem_type = 3;
   926 				if (required_tile == 0) problem_type = 3;
   927 			}
   927 			}
   931 		if (v->num_orders > 1) {
   931 		if (v->num_orders > 1) {
   932 			const Order* last = GetLastVehicleOrder(v);
   932 			const Order* last = GetLastVehicleOrder(v);
   933 
   933 
   934 			if (v->orders->type    == last->type &&
   934 			if (v->orders->type    == last->type &&
   935 					v->orders->flags   == last->flags &&
   935 					v->orders->flags   == last->flags &&
   936 					v->orders->station == last->station) {
   936 					v->orders->dest.station == last->dest.station) {
   937 				problem_type = 2;
   937 				problem_type = 2;
   938 			}
   938 			}
   939 		}
   939 		}
   940 
   940 
   941 		/* Do we only have 1 station in our order list? */
   941 		/* Do we only have 1 station in our order list? */
   960 /**
   960 /**
   961  * Removes an order from all vehicles. Triggers when, say, a station is removed.
   961  * Removes an order from all vehicles. Triggers when, say, a station is removed.
   962  * @param type The type of the order (OT_GOTO_[STATION|DEPOT|WAYPOINT]).
   962  * @param type The type of the order (OT_GOTO_[STATION|DEPOT|WAYPOINT]).
   963  * @param destination The destination. Can be a StationID, DepotID or WaypointID.
   963  * @param destination The destination. Can be a StationID, DepotID or WaypointID.
   964  */
   964  */
   965 void RemoveOrderFromAllVehicles(OrderType type, StationID destination)
   965 void RemoveOrderFromAllVehicles(OrderType type, DestinationID destination)
   966 {
   966 {
   967 	Vehicle *v;
   967 	Vehicle *v;
   968 	Order *order;
   968 	Order *order;
   969 	bool need_invalidate;
   969 	bool need_invalidate;
   970 
   970 
   971 	/* Go through all vehicles */
   971 	/* Go through all vehicles */
   972 	FOR_ALL_VEHICLES(v) {
   972 	FOR_ALL_VEHICLES(v) {
   973 		if (v->orders == NULL) continue;
   973 		if (v->orders == NULL) continue;
   974 
   974 
   975 		/* Forget about this station if this station is removed */
   975 		/* Forget about this station if this station is removed */
   976 		if (v->last_station_visited == destination && type == OT_GOTO_STATION)
   976 		if (v->last_station_visited == destination.station && type == OT_GOTO_STATION)
   977 			v->last_station_visited = INVALID_STATION;
   977 			v->last_station_visited = INVALID_STATION;
   978 
   978 
   979 		/* Check the current order */
   979 		/* Check the current order */
   980 		if (v->current_order.type == type && v->current_order.station == destination) {
   980 		if (v->current_order.type == type && v->current_order.dest.station == destination.station) {
   981 			/* Mark the order as DUMMY */
   981 			/* Mark the order as DUMMY */
   982 			v->current_order.type = OT_DUMMY;
   982 			v->current_order.type = OT_DUMMY;
   983 			v->current_order.flags = 0;
   983 			v->current_order.flags = 0;
   984 			InvalidateWindow(WC_VEHICLE_VIEW, v->index);
   984 			InvalidateWindow(WC_VEHICLE_VIEW, v->index);
   985 		}
   985 		}
   986 
   986 
   987 		/* Clear the order from the order-list */
   987 		/* Clear the order from the order-list */
   988 		need_invalidate = false;
   988 		need_invalidate = false;
   989 		FOR_VEHICLE_ORDERS(v, order) {
   989 		FOR_VEHICLE_ORDERS(v, order) {
   990 			if (order->type == type && order->station == destination) {
   990 			if (order->type == type && order->dest.station == destination.station) {
   991 				/* Mark the order as DUMMY */
   991 				/* Mark the order as DUMMY */
   992 				order->type = OT_DUMMY;
   992 				order->type = OT_DUMMY;
   993 				order->flags = 0;
   993 				order->flags = 0;
   994 
   994 
   995 				need_invalidate = true;
   995 				need_invalidate = true;
  1110 }
  1110 }
  1111 
  1111 
  1112 static const SaveLoad _order_desc[] = {
  1112 static const SaveLoad _order_desc[] = {
  1113 	SLE_VAR(Order, type,    SLE_UINT8),
  1113 	SLE_VAR(Order, type,    SLE_UINT8),
  1114 	SLE_VAR(Order, flags,   SLE_UINT8),
  1114 	SLE_VAR(Order, flags,   SLE_UINT8),
  1115 	SLE_VAR(Order, station, SLE_UINT16),
  1115 	SLE_VAR(Order, dest.station, SLE_UINT16), // Saving one of the union is enough, they all share the same memory
  1116 	SLE_REF(Order, next,    REF_ORDER),
  1116 	SLE_REF(Order, next,    REF_ORDER),
  1117 
  1117 
  1118 	// reserve extra space in savegame here. (currently 10 bytes)
  1118 	// reserve extra space in savegame here. (currently 10 bytes)
  1119 	SLE_CONDNULL(10, 5, SL_MAX_VERSION),
  1119 	SLE_CONDNULL(10, 5, SL_MAX_VERSION),
  1120 	SLE_END()
  1120 	SLE_END()