src/ship_cmd.cpp
branchnoai
changeset 9869 6404afe43575
parent 9837 c9ec4f82e0d0
child 10142 56ee7da4ad56
equal deleted inserted replaced
9868:3998f2e73dda 9869:6404afe43575
   151 	}
   151 	}
   152 
   152 
   153 	const Depot *depot = FindClosestShipDepot(v);
   153 	const Depot *depot = FindClosestShipDepot(v);
   154 
   154 
   155 	if (depot == NULL || DistanceManhattan(v->tile, depot->xy) > 12) {
   155 	if (depot == NULL || DistanceManhattan(v->tile, depot->xy) > 12) {
   156 		if (v->current_order.type == OT_GOTO_DEPOT) {
   156 		if (v->current_order.IsType(OT_GOTO_DEPOT)) {
   157 			v->current_order.type = OT_DUMMY;
   157 			v->current_order.MakeDummy();
   158 			v->current_order.flags = 0;
       
   159 			InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
   158 			InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
   160 		}
   159 		}
   161 		return;
   160 		return;
   162 	}
   161 	}
   163 
   162 
   164 	v->current_order.type = OT_GOTO_DEPOT;
   163 	v->current_order.MakeGoToDepot(depot->index, false);
   165 	v->current_order.flags = OFB_NON_STOP;
       
   166 	v->current_order.dest = depot->index;
       
   167 	v->dest_tile = depot->xy;
   164 	v->dest_tile = depot->xy;
   168 	InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
   165 	InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
   169 }
   166 }
   170 
   167 
   171 void Ship::OnNewDay()
   168 void Ship::OnNewDay()
   240 void Ship::PlayLeaveStationSound() const
   237 void Ship::PlayLeaveStationSound() const
   241 {
   238 {
   242 	PlayShipSound(this);
   239 	PlayShipSound(this);
   243 }
   240 }
   244 
   241 
   245 static void ProcessShipOrder(Vehicle *v)
   242 TileIndex Ship::GetOrderStationLocation(StationID station)
   246 {
   243 {
   247 	const Order *order;
   244 	if (station == this->last_station_visited) this->last_station_visited = INVALID_STATION;
   248 
   245 
   249 	switch (v->current_order.type) {
   246 	Station *st = GetStation(station);
   250 		case OT_GOTO_DEPOT:
   247 	if (st->dock_tile != 0) {
   251 			if (!(v->current_order.flags & OFB_PART_OF_ORDERS)) return;
   248 		return TILE_ADD(st->dock_tile, ToTileIndexDiff(GetDockOffset(st->dock_tile)));
   252 			if (v->current_order.flags & OFB_SERVICE_IF_NEEDED &&
       
   253 					!VehicleNeedsService(v)) {
       
   254 				UpdateVehicleTimetable(v, true);
       
   255 				v->cur_order_index++;
       
   256 			}
       
   257 			break;
       
   258 
       
   259 		case OT_LOADING:
       
   260 		case OT_LEAVESTATION:
       
   261 			return;
       
   262 
       
   263 		default: break;
       
   264 	}
       
   265 
       
   266 	if (v->cur_order_index >= v->num_orders) v->cur_order_index = 0;
       
   267 
       
   268 	order = GetVehicleOrder(v, v->cur_order_index);
       
   269 
       
   270 	if (order == NULL) {
       
   271 		v->current_order.Free();
       
   272 		v->dest_tile = 0;
       
   273 		return;
       
   274 	}
       
   275 
       
   276 	if (order->type  == v->current_order.type &&
       
   277 			order->flags == v->current_order.flags &&
       
   278 			order->dest  == v->current_order.dest &&
       
   279 			(order->type != OT_GOTO_STATION || GetStation(order->dest)->dock_tile != 0))
       
   280 		return;
       
   281 
       
   282 	v->current_order = *order;
       
   283 
       
   284 	if (order->type == OT_GOTO_STATION) {
       
   285 		const Station *st;
       
   286 
       
   287 		if (order->dest == v->last_station_visited)
       
   288 			v->last_station_visited = INVALID_STATION;
       
   289 
       
   290 		st = GetStation(order->dest);
       
   291 		if (st->dock_tile != 0) {
       
   292 			v->dest_tile = TILE_ADD(st->dock_tile, ToTileIndexDiff(GetDockOffset(st->dock_tile)));
       
   293 		} else {
       
   294 			v->cur_order_index++;
       
   295 		}
       
   296 	} else if (order->type == OT_GOTO_DEPOT) {
       
   297 		v->dest_tile = GetDepot(order->dest)->xy;
       
   298 	} else {
   249 	} else {
   299 		v->dest_tile = 0;
   250 		this->cur_order_index++;
   300 	}
   251 		return 0;
   301 
   252 	}
   302 	InvalidateVehicleOrder(v);
       
   303 
       
   304 	InvalidateWindowClasses(WC_SHIPS_LIST);
       
   305 }
   253 }
   306 
   254 
   307 void Ship::UpdateDeltaXY(Direction direction)
   255 void Ship::UpdateDeltaXY(Direction direction)
   308 {
   256 {
   309 #define MKIT(a, b, c, d) ((a & 0xFF) << 24) | ((b & 0xFF) << 16) | ((c & 0xFF) << 8) | ((d & 0xFF) << 0)
   257 #define MKIT(a, b, c, d) ((a & 0xFF) << 24) | ((b & 0xFF) << 16) | ((c & 0xFF) << 8) | ((d & 0xFF) << 0)
   320 #undef MKIT
   268 #undef MKIT
   321 
   269 
   322 	uint32 x = _delta_xy_table[direction];
   270 	uint32 x = _delta_xy_table[direction];
   323 	this->x_offs        = GB(x,  0, 8);
   271 	this->x_offs        = GB(x,  0, 8);
   324 	this->y_offs        = GB(x,  8, 8);
   272 	this->y_offs        = GB(x,  8, 8);
   325 	this->sprite_width  = GB(x, 16, 8);
   273 	this->x_extent      = GB(x, 16, 8);
   326 	this->sprite_height = GB(x, 24, 8);
   274 	this->y_extent      = GB(x, 24, 8);
   327 	this->z_height      = 6;
   275 	this->z_extent      = 6;
   328 }
   276 }
   329 
   277 
   330 void RecalcShipStuff(Vehicle *v)
   278 void RecalcShipStuff(Vehicle *v)
   331 {
   279 {
   332 	v->UpdateDeltaXY(v->direction);
   280 	v->UpdateDeltaXY(v->direction);
   472 		i = RemoveFirstTrack(&bits);
   420 		i = RemoveFirstTrack(&bits);
   473 
   421 
   474 		pfs.best_bird_dist = (uint)-1;
   422 		pfs.best_bird_dist = (uint)-1;
   475 		pfs.best_length = (uint)-1;
   423 		pfs.best_length = (uint)-1;
   476 
   424 
   477 		FollowTrack(tile, 0x1800 | TRANSPORT_WATER, 0, (DiagDirection)_ship_search_directions[i][dir], (TPFEnumProc*)ShipTrackFollower, NULL, &pfs);
   425 		FollowTrack(tile, PATHFIND_FLAGS_SHIP_MODE | PATHFIND_FLAGS_DISABLE_TILE_HASH, TRANSPORT_WATER, 0, (DiagDirection)_ship_search_directions[i][dir], (TPFEnumProc*)ShipTrackFollower, NULL, &pfs);
   478 
   426 
   479 		if (best_track != INVALID_TRACK) {
   427 		if (best_track != INVALID_TRACK) {
   480 			if (pfs.best_bird_dist != 0) {
   428 			if (pfs.best_bird_dist != 0) {
   481 				/* neither reached the destination, pick the one with the smallest bird dist */
   429 				/* neither reached the destination, pick the one with the smallest bird dist */
   482 				if (pfs.best_bird_dist > best_bird_dist) goto bad;
   430 				if (pfs.best_bird_dist > best_bird_dist) goto bad;
   648 		v->breakdown_ctr--;
   596 		v->breakdown_ctr--;
   649 	}
   597 	}
   650 
   598 
   651 	if (v->vehstatus & VS_STOPPED) return;
   599 	if (v->vehstatus & VS_STOPPED) return;
   652 
   600 
   653 	ProcessShipOrder(v);
   601 	ProcessOrders(v);
   654 	v->HandleLoading();
   602 	v->HandleLoading();
   655 
   603 
   656 	if (v->current_order.type == OT_LOADING) return;
   604 	if (v->current_order.IsType(OT_LOADING)) return;
   657 
   605 
   658 	CheckShipLeaveDepot(v);
   606 	CheckShipLeaveDepot(v);
   659 
   607 
   660 	if (!ShipAccelerate(v)) return;
   608 	if (!ShipAccelerate(v)) return;
   661 
   609 
   672 			r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y);
   620 			r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y);
   673 			if (HasBit(r, VETS_CANNOT_ENTER)) goto reverse_direction;
   621 			if (HasBit(r, VETS_CANNOT_ENTER)) goto reverse_direction;
   674 
   622 
   675 			/* A leave station order only needs one tick to get processed, so we can
   623 			/* A leave station order only needs one tick to get processed, so we can
   676 			 * always skip ahead. */
   624 			 * always skip ahead. */
   677 			if (v->current_order.type == OT_LEAVESTATION) {
   625 			if (v->current_order.IsType(OT_LEAVESTATION)) {
   678 				v->current_order.Free();
   626 				v->current_order.Free();
   679 				InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
   627 				InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
   680 			} else if (v->dest_tile != 0) {
   628 			} else if (v->dest_tile != 0) {
   681 				/* We have a target, let's see if we reached it... */
   629 				/* We have a target, let's see if we reached it... */
   682 				if (v->current_order.type == OT_GOTO_STATION &&
   630 				if (v->current_order.IsType(OT_GOTO_STATION) &&
   683 						IsBuoyTile(v->dest_tile) &&
   631 						IsBuoyTile(v->dest_tile) &&
   684 						DistanceManhattan(v->dest_tile, gp.new_tile) <= 3) {
   632 						DistanceManhattan(v->dest_tile, gp.new_tile) <= 3) {
   685 					/* We got within 3 tiles of our target buoy, so let's skip to our
   633 					/* We got within 3 tiles of our target buoy, so let's skip to our
   686 					 * next order */
   634 					 * next order */
   687 					UpdateVehicleTimetable(v, true);
   635 					UpdateVehicleTimetable(v, true);
   688 					v->cur_order_index++;
   636 					v->cur_order_index++;
   689 					v->current_order.type = OT_DUMMY;
   637 					v->current_order.MakeDummy();
   690 					InvalidateVehicleOrder(v);
   638 					InvalidateVehicleOrder(v);
   691 				} else {
   639 				} else {
   692 					/* Non-buoy orders really need to reach the tile */
   640 					/* Non-buoy orders really need to reach the tile */
   693 					if (v->dest_tile == gp.new_tile) {
   641 					if (v->dest_tile == gp.new_tile) {
   694 						if (v->current_order.type == OT_GOTO_DEPOT) {
   642 						if (v->current_order.IsType(OT_GOTO_DEPOT)) {
   695 							if ((gp.x & 0xF) == 8 && (gp.y & 0xF) == 8) {
   643 							if ((gp.x & 0xF) == 8 && (gp.y & 0xF) == 8) {
   696 								VehicleEnterDepot(v);
   644 								VehicleEnterDepot(v);
   697 								return;
   645 								return;
   698 							}
   646 							}
   699 						} else if (v->current_order.type == OT_GOTO_STATION) {
   647 						} else if (v->current_order.IsType(OT_GOTO_STATION)) {
   700 							Station *st;
   648 							v->last_station_visited = v->current_order.GetDestination();
   701 
       
   702 							v->last_station_visited = v->current_order.dest;
       
   703 
   649 
   704 							/* Process station in the orderlist. */
   650 							/* Process station in the orderlist. */
   705 							st = GetStation(v->current_order.dest);
   651 							Station *st = GetStation(v->current_order.GetDestination());
   706 							if (st->facilities & FACIL_DOCK) { // ugly, ugly workaround for problem with ships able to drop off cargo at wrong stations
   652 							if (st->facilities & FACIL_DOCK) { // ugly, ugly workaround for problem with ships able to drop off cargo at wrong stations
   707 								ShipArrivesAt(v, st);
   653 								ShipArrivesAt(v, st);
   708 								v->BeginLoading();
   654 								v->BeginLoading();
   709 							} else { // leave stations without docks right aways
   655 							} else { // leave stations without docks right aways
   710 								v->current_order.type = OT_LEAVESTATION;
   656 								v->current_order.MakeLeaveStation();
   711 								v->cur_order_index++;
   657 								v->cur_order_index++;
   712 								InvalidateVehicleOrder(v);
   658 								InvalidateVehicleOrder(v);
   713 							}
   659 							}
   714 						}
   660 						}
   715 					}
   661 					}
   994 	if (v->vehstatus & VS_CRASHED) return CMD_ERROR;
   940 	if (v->vehstatus & VS_CRASHED) return CMD_ERROR;
   995 
   941 
   996 	if (v->IsInDepot()) return CMD_ERROR;
   942 	if (v->IsInDepot()) return CMD_ERROR;
   997 
   943 
   998 	/* If the current orders are already goto-depot */
   944 	/* If the current orders are already goto-depot */
   999 	if (v->current_order.type == OT_GOTO_DEPOT) {
   945 	if (v->current_order.IsType(OT_GOTO_DEPOT)) {
  1000 		if (!!(p2 & DEPOT_SERVICE) == HasBit(v->current_order.flags, OF_HALT_IN_DEPOT)) {
   946 		bool halt_in_depot = HasBit(v->current_order.GetDepotActionType(), OF_HALT_IN_DEPOT);
       
   947 		if (!!(p2 & DEPOT_SERVICE) == halt_in_depot) {
  1001 			/* We called with a different DEPOT_SERVICE setting.
   948 			/* We called with a different DEPOT_SERVICE setting.
  1002 			 * Now we change the setting to apply the new one and let the vehicle head for the same depot.
   949 			 * Now we change the setting to apply the new one and let the vehicle head for the same depot.
  1003 			 * Note: the if is (true for requesting service == true for ordered to stop in depot)          */
   950 			 * Note: the if is (true for requesting service == true for ordered to stop in depot)          */
  1004 			if (flags & DC_EXEC) {
   951 			if (flags & DC_EXEC) {
  1005 				ClrBit(v->current_order.flags, OF_PART_OF_ORDERS);
   952 				v->current_order.SetDepotOrderType(OFB_MANUAL_ORDER);
  1006 				ToggleBit(v->current_order.flags, OF_HALT_IN_DEPOT);
   953 				v->current_order.SetDepotActionType(halt_in_depot ? OFB_NORMAL_ACTION : OFB_HALT_IN_DEPOT);
  1007 				InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
   954 				InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
  1008 			}
   955 			}
  1009 			return CommandCost();
   956 			return CommandCost();
  1010 		}
   957 		}
  1011 
   958 
  1012 		if (p2 & DEPOT_DONT_CANCEL) return CMD_ERROR; // Requested no cancelation of depot orders
   959 		if (p2 & DEPOT_DONT_CANCEL) return CMD_ERROR; // Requested no cancelation of depot orders
  1013 		if (flags & DC_EXEC) {
   960 		if (flags & DC_EXEC) {
  1014 			/* If the orders to 'goto depot' are in the orders list (forced servicing),
   961 			/* If the orders to 'goto depot' are in the orders list (forced servicing),
  1015 			 * then skip to the next order; effectively cancelling this forced service */
   962 			 * then skip to the next order; effectively cancelling this forced service */
  1016 			if (HasBit(v->current_order.flags, OF_PART_OF_ORDERS))
   963 			if (v->current_order.GetDepotOrderType() & OFB_PART_OF_ORDERS) v->cur_order_index++;
  1017 				v->cur_order_index++;
   964 
  1018 
   965 			v->current_order.MakeDummy();
  1019 			v->current_order.type = OT_DUMMY;
       
  1020 			v->current_order.flags = 0;
       
  1021 			InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
   966 			InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
  1022 		}
   967 		}
  1023 		return CommandCost();
   968 		return CommandCost();
  1024 	}
   969 	}
  1025 
   970 
  1026 	dep = FindClosestShipDepot(v);
   971 	dep = FindClosestShipDepot(v);
  1027 	if (dep == NULL) return_cmd_error(STR_981A_UNABLE_TO_FIND_LOCAL_DEPOT);
   972 	if (dep == NULL) return_cmd_error(STR_981A_UNABLE_TO_FIND_LOCAL_DEPOT);
  1028 
   973 
  1029 	if (flags & DC_EXEC) {
   974 	if (flags & DC_EXEC) {
  1030 		if (v->current_order.type == OT_LOADING) v->LeaveStation();
   975 		if (v->current_order.IsType(OT_LOADING)) v->LeaveStation();
  1031 
   976 
  1032 		v->dest_tile = dep->xy;
   977 		v->dest_tile = dep->xy;
  1033 		v->current_order.type = OT_GOTO_DEPOT;
   978 		v->current_order.MakeGoToDepot(dep->index, false);
  1034 		v->current_order.flags = OFB_NON_STOP;
   979 		if (!(p2 & DEPOT_SERVICE)) v->current_order.SetDepotActionType(OFB_HALT_IN_DEPOT);
  1035 		if (!(p2 & DEPOT_SERVICE)) SetBit(v->current_order.flags, OF_HALT_IN_DEPOT);
       
  1036 		v->current_order.refit_cargo = CT_INVALID;
       
  1037 		v->current_order.dest = dep->index;
       
  1038 		InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
   980 		InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
  1039 	}
   981 	}
  1040 
   982 
  1041 	return CommandCost();
   983 	return CommandCost();
  1042 }
   984 }