src/vehicle.cpp
branchnoai
changeset 9869 6404afe43575
parent 9837 c9ec4f82e0d0
child 10142 56ee7da4ad56
equal deleted inserted replaced
9868:3998f2e73dda 9869:6404afe43575
   118 }
   118 }
   119 
   119 
   120 bool VehicleNeedsService(const Vehicle *v)
   120 bool VehicleNeedsService(const Vehicle *v)
   121 {
   121 {
   122 	if (v->vehstatus & (VS_STOPPED | VS_CRASHED))       return false;
   122 	if (v->vehstatus & (VS_STOPPED | VS_CRASHED))       return false;
   123 	if (v->current_order.type != OT_GOTO_DEPOT || !(v->current_order.flags & OFB_PART_OF_ORDERS)) { // Don't interfere with a depot visit by the order list
   123 	if (!v->current_order.IsType(OT_GOTO_DEPOT) || !(v->current_order.GetDepotOrderType() & OFB_PART_OF_ORDERS)) { // Don't interfere with a depot visit by the order list
   124 		if (_patches.gotodepot && VehicleHasDepotOrders(v)) return false;
   124 		if (_patches.gotodepot && VehicleHasDepotOrders(v)) return false;
   125 		if (v->current_order.type == OT_LOADING)            return false;
   125 		if (v->current_order.IsType(OT_LOADING))            return false;
   126 		if (v->current_order.type == OT_GOTO_DEPOT && v->current_order.flags & OFB_HALT_IN_DEPOT) return false;
   126 		if (v->current_order.IsType(OT_GOTO_DEPOT) && v->current_order.GetDepotActionType() & OFB_HALT_IN_DEPOT) return false;
   127 	}
   127 	}
   128 
   128 
   129 	if (_patches.no_servicing_if_no_breakdowns && _opt.diff.vehicle_breakdowns == 0) {
   129 	if (_patches.no_servicing_if_no_breakdowns && _opt.diff.vehicle_breakdowns == 0) {
   130 		return EngineHasReplacementForPlayer(GetPlayer(v->owner), v->engine_type, v->group_id);  /* Vehicles set for autoreplacing needs to go to a depot even if breakdowns are turned off */
   130 		return EngineHasReplacementForPlayer(GetPlayer(v->owner), v->engine_type, v->group_id);  /* Vehicles set for autoreplacing needs to go to a depot even if breakdowns are turned off */
   131 	}
   131 	}
   629  */
   629  */
   630 void VehicleEnteredDepotThisTick(Vehicle *v)
   630 void VehicleEnteredDepotThisTick(Vehicle *v)
   631 {
   631 {
   632 	/* We need to set v->leave_depot_instantly as we have no control of it's contents at this time.
   632 	/* We need to set v->leave_depot_instantly as we have no control of it's contents at this time.
   633 	 * Vehicle should stop in the depot if it was in 'stopping' state - train intered depot while slowing down. */
   633 	 * Vehicle should stop in the depot if it was in 'stopping' state - train intered depot while slowing down. */
   634 	if ((HasBit(v->current_order.flags, OF_HALT_IN_DEPOT) && !HasBit(v->current_order.flags, OF_PART_OF_ORDERS) && v->current_order.type == OT_GOTO_DEPOT) ||
   634 	if ((HasBit(v->current_order.GetDepotActionType(), OF_HALT_IN_DEPOT) && !HasBit(v->current_order.GetDepotOrderType(), OF_PART_OF_ORDERS) && v->current_order.IsType(OT_GOTO_DEPOT)) ||
   635 			(v->vehstatus & VS_STOPPED)) {
   635 			(v->vehstatus & VS_STOPPED)) {
   636 		/* we keep the vehicle in the depot since the user ordered it to stay */
   636 		/* we keep the vehicle in the depot since the user ordered it to stay */
   637 		v->leave_depot_instantly = false;
   637 		v->leave_depot_instantly = false;
   638 	} else {
   638 	} else {
   639 		/* the vehicle do not plan on stopping in the depot, so we stop it to ensure that it will not reserve the path
   639 		/* the vehicle do not plan on stopping in the depot, so we stop it to ensure that it will not reserve the path
   765 	} else {
   765 	} else {
   766 		pal = PAL_NONE;
   766 		pal = PAL_NONE;
   767 	}
   767 	}
   768 
   768 
   769 	AddSortableSpriteToDraw(image, pal, v->x_pos + v->x_offs, v->y_pos + v->y_offs,
   769 	AddSortableSpriteToDraw(image, pal, v->x_pos + v->x_offs, v->y_pos + v->y_offs,
   770 		v->sprite_width, v->sprite_height, v->z_height, v->z_pos, (v->vehstatus & VS_SHADOW) != 0);
   770 		v->x_extent, v->y_extent, v->z_extent, v->z_pos, (v->vehstatus & VS_SHADOW) != 0);
   771 }
   771 }
   772 
   772 
   773 void ViewportAddVehicles(DrawPixelInfo *dpi)
   773 void ViewportAddVehicles(DrawPixelInfo *dpi)
   774 {
   774 {
   775 	/* The bounding rectangle */
   775 	/* The bounding rectangle */
  2031 			FOR_ALL_VEHICLES(v) {
  2031 			FOR_ALL_VEHICLES(v) {
  2032 				if (v->type == type && v->IsPrimaryVehicle()) {
  2032 				if (v->type == type && v->IsPrimaryVehicle()) {
  2033 					const Order *order;
  2033 					const Order *order;
  2034 
  2034 
  2035 					FOR_VEHICLE_ORDERS(v, order) {
  2035 					FOR_VEHICLE_ORDERS(v, order) {
  2036 						if (order->type == OT_GOTO_STATION && order->dest == index) {
  2036 						if (order->IsType(OT_GOTO_STATION) && order->GetDestination() == index) {
  2037 							if (n == *length_of_array) ExtendVehicleListSize(sort_list, length_of_array, 50);
  2037 							if (n == *length_of_array) ExtendVehicleListSize(sort_list, length_of_array, 50);
  2038 							(*sort_list)[n++] = v;
  2038 							(*sort_list)[n++] = v;
  2039 							break;
  2039 							break;
  2040 						}
  2040 						}
  2041 					}
  2041 					}
  2075 			FOR_ALL_VEHICLES(v) {
  2075 			FOR_ALL_VEHICLES(v) {
  2076 				if (v->type == type && v->IsPrimaryVehicle()) {
  2076 				if (v->type == type && v->IsPrimaryVehicle()) {
  2077 					const Order *order;
  2077 					const Order *order;
  2078 
  2078 
  2079 					FOR_VEHICLE_ORDERS(v, order) {
  2079 					FOR_VEHICLE_ORDERS(v, order) {
  2080 						if (order->type == OT_GOTO_DEPOT && order->dest == index) {
  2080 						if (order->IsType(OT_GOTO_DEPOT) && order->GetDestination() == index) {
  2081 							if (n == *length_of_array) ExtendVehicleListSize(sort_list, length_of_array, 25);
  2081 							if (n == *length_of_array) ExtendVehicleListSize(sort_list, length_of_array, 25);
  2082 							(*sort_list)[n++] = v;
  2082 							(*sort_list)[n++] = v;
  2083 							break;
  2083 							break;
  2084 						}
  2084 						}
  2085 					}
  2085 					}
  2172 	for (; v != NULL; v = v->Next()) {
  2172 	for (; v != NULL; v = v->Next()) {
  2173 		count += v->cargo.Count();
  2173 		count += v->cargo.Count();
  2174 		max += v->cargo_cap;
  2174 		max += v->cargo_cap;
  2175 		if (v->cargo_cap != 0) {
  2175 		if (v->cargo_cap != 0) {
  2176 			unloading += HasBit(v->vehicle_flags, VF_CARGO_UNLOADING) ? 1 : 0;
  2176 			unloading += HasBit(v->vehicle_flags, VF_CARGO_UNLOADING) ? 1 : 0;
  2177 			loading |= (u->current_order.flags & OFB_UNLOAD) == 0 && st->goods[v->cargo_type].days_since_pickup != 255;
  2177 			loading |= !HasBit(u->current_order.GetUnloadType(), OF_UNLOAD) && st->goods[v->cargo_type].days_since_pickup != 255;
  2178 			cars++;
  2178 			cars++;
  2179 		}
  2179 		}
  2180 	}
  2180 	}
  2181 
  2181 
  2182 	if (unloading == 0 && loading)          *color = STR_PERCENT_UP;
  2182 	if (unloading == 0 && loading)          *color = STR_PERCENT_UP;
  2233 
  2233 
  2234 	VehicleServiceInDepot(v);
  2234 	VehicleServiceInDepot(v);
  2235 
  2235 
  2236 	TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT);
  2236 	TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT);
  2237 
  2237 
  2238 	if (v->current_order.type == OT_GOTO_DEPOT) {
  2238 	if (v->current_order.IsType(OT_GOTO_DEPOT)) {
  2239 		Order t;
  2239 		Order t;
  2240 
  2240 
  2241 		InvalidateWindow(WC_VEHICLE_VIEW, v->index);
  2241 		InvalidateWindow(WC_VEHICLE_VIEW, v->index);
  2242 
  2242 
  2243 		t = v->current_order;
  2243 		t = v->current_order;
  2244 		v->current_order.type = OT_DUMMY;
  2244 		v->current_order.MakeDummy();
  2245 		v->current_order.flags = 0;
  2245 
  2246 
  2246 		if (t.IsRefit()) {
  2247 		if (t.refit_cargo < NUM_CARGO) {
       
  2248 			CommandCost cost;
  2247 			CommandCost cost;
  2249 
  2248 
  2250 			_current_player = v->owner;
  2249 			_current_player = v->owner;
  2251 			cost = DoCommand(v->tile, v->index, t.refit_cargo | t.refit_subtype << 8, DC_EXEC, GetCmdRefitVeh(v));
  2250 			cost = DoCommand(v->tile, v->index, t.GetRefitCargo() | t.GetRefitSubtype() << 8, DC_EXEC, GetCmdRefitVeh(v));
  2252 
  2251 
  2253 			if (CmdFailed(cost)) {
  2252 			if (CmdFailed(cost)) {
  2254 				v->leave_depot_instantly = false; // We ensure that the vehicle stays in the depot
  2253 				v->leave_depot_instantly = false; // We ensure that the vehicle stays in the depot
  2255 				if (v->owner == _local_player) {
  2254 				if (v->owner == _local_player) {
  2256 					/* Notify the user that we stopped the vehicle */
  2255 					/* Notify the user that we stopped the vehicle */
  2261 			} else if (v->owner == _local_player && cost.GetCost() != 0) {
  2260 			} else if (v->owner == _local_player && cost.GetCost() != 0) {
  2262 				ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, cost.GetCost());
  2261 				ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, cost.GetCost());
  2263 			}
  2262 			}
  2264 		}
  2263 		}
  2265 
  2264 
  2266 		if (HasBit(t.flags, OF_PART_OF_ORDERS)) {
  2265 		if (HasBit(t.GetDepotOrderType(), OF_PART_OF_ORDERS)) {
  2267 			/* Part of orders */
  2266 			/* Part of orders */
  2268 			UpdateVehicleTimetable(v, true);
  2267 			UpdateVehicleTimetable(v, true);
  2269 			v->cur_order_index++;
  2268 			v->cur_order_index++;
  2270 		} else if (HasBit(t.flags, OF_HALT_IN_DEPOT)) {
  2269 		} else if (HasBit(t.GetDepotActionType(), OF_HALT_IN_DEPOT)) {
  2271 			/* Force depot visit */
  2270 			/* Force depot visit */
  2272 			v->vehstatus |= VS_STOPPED;
  2271 			v->vehstatus |= VS_STOPPED;
  2273 			if (v->owner == _local_player) {
  2272 			if (v->owner == _local_player) {
  2274 				StringID string;
  2273 				StringID string;
  2275 
  2274 
  3052 		SlObject(v, GetVehicleDescription(v->type));
  3051 		SlObject(v, GetVehicleDescription(v->type));
  3053 	}
  3052 	}
  3054 }
  3053 }
  3055 
  3054 
  3056 /** Will be called when vehicles need to be loaded. */
  3055 /** Will be called when vehicles need to be loaded. */
  3057 static void Load_VEHS()
  3056 void Load_VEHS()
  3058 {
  3057 {
  3059 	int index;
  3058 	int index;
  3060 	Vehicle *v;
  3059 	Vehicle *v;
  3061 
  3060 
  3062 	_cargo_count = 0;
  3061 	_cargo_count = 0;
  3095 			v->last_station_visited = INVALID_STATION;
  3094 			v->last_station_visited = INVALID_STATION;
  3096 
  3095 
  3097 		if (CheckSavegameVersion(5)) {
  3096 		if (CheckSavegameVersion(5)) {
  3098 			/* Convert the current_order.type (which is a mix of type and flags, because
  3097 			/* Convert the current_order.type (which is a mix of type and flags, because
  3099 			 *  in those versions, they both were 4 bits big) to type and flags */
  3098 			 *  in those versions, they both were 4 bits big) to type and flags */
  3100 			v->current_order.flags = (v->current_order.type & 0xF0) >> 4;
  3099 			v->current_order.flags = GB(v->current_order.type, 4, 4);
  3101 			v->current_order.type.m_val &= 0x0F;
  3100 			v->current_order.type.m_val &= 0x0F;
  3102 		}
  3101 		}
  3103 
  3102 
  3104 		/* Advanced vehicle lists got added */
  3103 		/* Advanced vehicle lists got added */
  3105 		if (CheckSavegameVersion(60)) v->group_id = DEFAULT_GROUP;
  3104 		if (CheckSavegameVersion(60)) v->group_id = DEFAULT_GROUP;
  3129 
  3128 
  3130 void Vehicle::BeginLoading()
  3129 void Vehicle::BeginLoading()
  3131 {
  3130 {
  3132 	assert(IsTileType(tile, MP_STATION) || type == VEH_SHIP);
  3131 	assert(IsTileType(tile, MP_STATION) || type == VEH_SHIP);
  3133 
  3132 
  3134 	if (this->current_order.type == OT_GOTO_STATION &&
  3133 	if (this->current_order.IsType(OT_GOTO_STATION) &&
  3135 			this->current_order.dest == this->last_station_visited) {
  3134 			this->current_order.GetDestination() == this->last_station_visited) {
  3136 		/* Arriving at the ordered station.
       
  3137 		 * Keep the load/unload flags, as we (obviously) still need them. */
       
  3138 		this->current_order.flags &= OFB_FULL_LOAD | OFB_UNLOAD | OFB_TRANSFER;
       
  3139 
       
  3140 		/* Furthermore add the Non Stop flag to mark that this station
  3135 		/* Furthermore add the Non Stop flag to mark that this station
  3141 		 * is the actual destination of the vehicle, which is (for example)
  3136 		 * is the actual destination of the vehicle, which is (for example)
  3142 		 * necessary to be known for HandleTrainLoading to determine
  3137 		 * necessary to be known for HandleTrainLoading to determine
  3143 		 * whether the train is lost or not; not marking a train lost
  3138 		 * whether the train is lost or not; not marking a train lost
  3144 		 * that arrives at random stations is bad. */
  3139 		 * that arrives at random stations is bad. */
  3145 		this->current_order.flags |= OFB_NON_STOP;
  3140 		this->current_order.SetNonStopType(OFB_NON_STOP);
       
  3141 
       
  3142 		current_order.MakeLoading(true);
  3146 		UpdateVehicleTimetable(this, true);
  3143 		UpdateVehicleTimetable(this, true);
  3147 	} else {
  3144 	} else {
  3148 		/* This is just an unordered intermediate stop */
  3145 		this->current_order.SetNonStopType(OFB_NO_NON_STOP);
  3149 		this->current_order.flags = 0;
  3146 		current_order.MakeLoading(false);
  3150 	}
  3147 	}
  3151 
  3148 
  3152 	current_order.type = OT_LOADING;
       
  3153 	GetStation(this->last_station_visited)->loading_vehicles.push_back(this);
  3149 	GetStation(this->last_station_visited)->loading_vehicles.push_back(this);
  3154 
  3150 
  3155 	VehiclePayment(this);
  3151 	VehiclePayment(this);
  3156 
  3152 
  3157 	InvalidateWindow(this->GetVehicleListWindowClass(), this->owner);
  3153 	InvalidateWindow(this->GetVehicleListWindowClass(), this->owner);
  3163 	this->MarkDirty();
  3159 	this->MarkDirty();
  3164 }
  3160 }
  3165 
  3161 
  3166 void Vehicle::LeaveStation()
  3162 void Vehicle::LeaveStation()
  3167 {
  3163 {
  3168 	assert(current_order.type == OT_LOADING);
  3164 	assert(current_order.IsType(OT_LOADING));
  3169 
  3165 
  3170 	/* Only update the timetable if the vehicle was supposed to stop here. */
  3166 	/* Only update the timetable if the vehicle was supposed to stop here. */
  3171 	if (current_order.flags & OFB_NON_STOP) UpdateVehicleTimetable(this, false);
  3167 	if (current_order.GetNonStopType() != OFB_NO_NON_STOP) UpdateVehicleTimetable(this, false);
  3172 
  3168 
  3173 	current_order.type = OT_LEAVESTATION;
  3169 	current_order.MakeLeaveStation();
  3174 	current_order.flags = 0;
       
  3175 	GetStation(this->last_station_visited)->loading_vehicles.remove(this);
  3170 	GetStation(this->last_station_visited)->loading_vehicles.remove(this);
  3176 
  3171 
  3177 	HideFillingPercent(this->fill_percent_te_id);
  3172 	HideFillingPercent(this->fill_percent_te_id);
  3178 	this->fill_percent_te_id = INVALID_TE_ID;
  3173 	this->fill_percent_te_id = INVALID_TE_ID;
  3179 }
  3174 }
  3180 
  3175 
  3181 
  3176 
  3182 void Vehicle::HandleLoading(bool mode)
  3177 void Vehicle::HandleLoading(bool mode)
  3183 {
  3178 {
  3184 	switch (this->current_order.type) {
  3179 	switch (this->current_order.GetType()) {
  3185 		case OT_LOADING: {
  3180 		case OT_LOADING: {
  3186 			uint wait_time = max(this->current_order.wait_time - this->lateness_counter, 0);
  3181 			uint wait_time = max(this->current_order.wait_time - this->lateness_counter, 0);
  3187 
  3182 
  3188 			/* Not the first call for this tick, or still loading */
  3183 			/* Not the first call for this tick, or still loading */
  3189 			if (mode || !HasBit(this->vehicle_flags, VF_LOADING_FINISHED) ||
  3184 			if (mode || !HasBit(this->vehicle_flags, VF_LOADING_FINISHED) ||
  3193 
  3188 
  3194 			Order b = this->current_order;
  3189 			Order b = this->current_order;
  3195 			this->LeaveStation();
  3190 			this->LeaveStation();
  3196 
  3191 
  3197 			/* If this was not the final order, don't remove it from the list. */
  3192 			/* If this was not the final order, don't remove it from the list. */
  3198 			if (!(b.flags & OFB_NON_STOP)) return;
  3193 			if (!(b.GetNonStopType() & OFB_NON_STOP)) return;
  3199 			break;
  3194 			break;
  3200 		}
  3195 		}
  3201 
  3196 
  3202 		case OT_DUMMY: break;
  3197 		case OT_DUMMY: break;
  3203 
  3198 
  3232 
  3227 
  3233 void SpecialVehicle::UpdateDeltaXY(Direction direction)
  3228 void SpecialVehicle::UpdateDeltaXY(Direction direction)
  3234 {
  3229 {
  3235 	this->x_offs        = 0;
  3230 	this->x_offs        = 0;
  3236 	this->y_offs        = 0;
  3231 	this->y_offs        = 0;
  3237 	this->sprite_width  = 1;
  3232 	this->x_extent      = 1;
  3238 	this->sprite_height = 1;
  3233 	this->y_extent      = 1;
  3239 	this->z_height      = 1;
  3234 	this->z_extent      = 1;
  3240 }
  3235 }
  3241 
  3236 
  3242 void StopAllVehicles()
  3237 void StopAllVehicles()
  3243 {
  3238 {
  3244 	Vehicle *v;
  3239 	Vehicle *v;