src/aircraft_cmd.cpp
branchnoai
changeset 9722 ebf0ece7d8f6
parent 9718 f82a4facea8b
child 9723 eee46cb39750
equal deleted inserted replaced
9721:9a27928bcd5e 9722:ebf0ece7d8f6
   290 	Vehicle *vl[3];
   290 	Vehicle *vl[3];
   291 	if (!Vehicle::AllocateList(vl, avi->subtype & AIR_CTOL ? 2 : 3)) {
   291 	if (!Vehicle::AllocateList(vl, avi->subtype & AIR_CTOL ? 2 : 3)) {
   292 		return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
   292 		return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
   293 	}
   293 	}
   294 
   294 
   295 	UnitID unit_num = HASBIT(p2, 0) ? 0 : GetFreeUnitNumber(VEH_AIRCRAFT);
   295 	UnitID unit_num = HasBit(p2, 0) ? 0 : GetFreeUnitNumber(VEH_AIRCRAFT);
   296 	if (unit_num > _patches.max_aircraft)
   296 	if (unit_num > _patches.max_aircraft)
   297 		return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
   297 		return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
   298 
   298 
   299 	if (flags & DC_EXEC) {
   299 	if (flags & DC_EXEC) {
   300 		Vehicle *v = vl[0]; // aircraft
   300 		Vehicle *v = vl[0]; // aircraft
   301 		Vehicle *u = vl[1]; // shadow
   301 		Vehicle *u = vl[1]; // shadow
   302 
   302 
   303 		v->unitnumber = unit_num;
       
   304 		v = new (v) Aircraft();
   303 		v = new (v) Aircraft();
   305 		u = new (u) Aircraft();
   304 		u = new (u) Aircraft();
       
   305 		v->unitnumber = unit_num;
   306 		v->direction = DIR_SE;
   306 		v->direction = DIR_SE;
   307 
   307 
   308 		v->owner = u->owner = _current_player;
   308 		v->owner = u->owner = _current_player;
   309 
   309 
   310 		v->tile = tile;
   310 		v->tile = tile;
   363 		if (cargo != CT_INVALID && cargo != CT_PASSENGERS) {
   363 		if (cargo != CT_INVALID && cargo != CT_PASSENGERS) {
   364 			uint16 callback = CALLBACK_FAILED;
   364 			uint16 callback = CALLBACK_FAILED;
   365 
   365 
   366 			v->cargo_type = cargo;
   366 			v->cargo_type = cargo;
   367 
   367 
   368 			if (HASBIT(EngInfo(p1)->callbackmask, CBM_VEHICLE_REFIT_CAPACITY)) {
   368 			if (HasBit(EngInfo(p1)->callbackmask, CBM_VEHICLE_REFIT_CAPACITY)) {
   369 				callback = GetVehicleCallback(CBID_VEHICLE_REFIT_CAPACITY, 0, 0, v->engine_type, v);
   369 				callback = GetVehicleCallback(CBID_VEHICLE_REFIT_CAPACITY, 0, 0, v->engine_type, v);
   370 			}
   370 			}
   371 
   371 
   372 			if (callback == CALLBACK_FAILED) {
   372 			if (callback == CALLBACK_FAILED) {
   373 				/* Callback failed, or not executed; use the default cargo capacity */
   373 				/* Callback failed, or not executed; use the default cargo capacity */
   417 
   417 
   418 		v->random_bits = VehicleRandomBits();
   418 		v->random_bits = VehicleRandomBits();
   419 		u->random_bits = VehicleRandomBits();
   419 		u->random_bits = VehicleRandomBits();
   420 
   420 
   421 		v->vehicle_flags = 0;
   421 		v->vehicle_flags = 0;
   422 		if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SETBIT(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE);
   422 		if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SetBit(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE);
   423 
   423 
   424 		UpdateAircraftCache(v);
   424 		UpdateAircraftCache(v);
   425 
   425 
   426 		VehiclePositionChanged(v);
   426 		VehiclePositionChanged(v);
   427 		VehiclePositionChanged(u);
   427 		VehiclePositionChanged(u);
   490 
   490 
   491 	if (HASBITS(v->vehstatus, VS_CRASHED)) return_cmd_error(STR_CAN_T_SELL_DESTROYED_VEHICLE);
   491 	if (HASBITS(v->vehstatus, VS_CRASHED)) return_cmd_error(STR_CAN_T_SELL_DESTROYED_VEHICLE);
   492 
   492 
   493 	SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
   493 	SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
   494 
   494 
       
   495 	CommandCost ret(-v->value);
       
   496 
   495 	if (flags & DC_EXEC) {
   497 	if (flags & DC_EXEC) {
   496 		// Invalidate depot
   498 		// Invalidate depot
   497 		InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
   499 		InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
   498 		DoDeleteAircraft(v);
   500 		DoDeleteAircraft(v);
   499 	}
   501 	}
   500 
   502 
   501 	return CommandCost(-v->value);
   503 	return ret;
   502 }
   504 }
   503 
   505 
   504 /** Start/Stop an aircraft.
   506 /** Start/Stop an aircraft.
   505  * @param tile unused
   507  * @param tile unused
   506  * @param flags for command type
   508  * @param flags for command type
   532 		if (v->IsStoppedInDepot()) {
   534 		if (v->IsStoppedInDepot()) {
   533 			DeleteVehicleNews(p1, STR_A014_AIRCRAFT_IS_WAITING_IN);
   535 			DeleteVehicleNews(p1, STR_A014_AIRCRAFT_IS_WAITING_IN);
   534 		}
   536 		}
   535 
   537 
   536 		v->vehstatus ^= VS_STOPPED;
   538 		v->vehstatus ^= VS_STOPPED;
       
   539 		v->cur_speed = 0;
   537 		InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
   540 		InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
   538 		InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
   541 		InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
   539 		InvalidateWindowClasses(WC_AIRCRAFT_LIST);
   542 		InvalidateWindowClasses(WC_AIRCRAFT_LIST);
   540 	}
   543 	}
   541 
   544 
   564 	Vehicle *v = GetVehicle(p1);
   567 	Vehicle *v = GetVehicle(p1);
   565 
   568 
   566 	if (v->type != VEH_AIRCRAFT || !CheckOwnership(v->owner) || v->IsInDepot()) return CMD_ERROR;
   569 	if (v->type != VEH_AIRCRAFT || !CheckOwnership(v->owner) || v->IsInDepot()) return CMD_ERROR;
   567 
   570 
   568 	if (v->current_order.type == OT_GOTO_DEPOT && !(p2 & DEPOT_LOCATE_HANGAR)) {
   571 	if (v->current_order.type == OT_GOTO_DEPOT && !(p2 & DEPOT_LOCATE_HANGAR)) {
   569 		if (!!(p2 & DEPOT_SERVICE) == HASBIT(v->current_order.flags, OFB_HALT_IN_DEPOT)) {
   572 		if (!!(p2 & DEPOT_SERVICE) == HasBit(v->current_order.flags, OFB_HALT_IN_DEPOT)) {
   570 			/* We called with a different DEPOT_SERVICE setting.
   573 			/* We called with a different DEPOT_SERVICE setting.
   571 			 * Now we change the setting to apply the new one and let the vehicle head for the same hangar.
   574 			 * Now we change the setting to apply the new one and let the vehicle head for the same hangar.
   572 			 * Note: the if is (true for requesting service == true for ordered to stop in hangar) */
   575 			 * Note: the if is (true for requesting service == true for ordered to stop in hangar) */
   573 			if (flags & DC_EXEC) {
   576 			if (flags & DC_EXEC) {
   574 				CLRBIT(v->current_order.flags, OFB_PART_OF_ORDERS);
   577 				ClrBit(v->current_order.flags, OFB_PART_OF_ORDERS);
   575 				TOGGLEBIT(v->current_order.flags, OFB_HALT_IN_DEPOT);
   578 				ToggleBit(v->current_order.flags, OFB_HALT_IN_DEPOT);
   576 				InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
   579 				InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
   577 			}
   580 			}
   578 			return CommandCost();
   581 			return CommandCost();
   579 		}
   582 		}
   580 
   583 
   602 		if (flags & DC_EXEC) {
   605 		if (flags & DC_EXEC) {
   603 			if (v->current_order.type == OT_LOADING) v->LeaveStation();
   606 			if (v->current_order.type == OT_LOADING) v->LeaveStation();
   604 
   607 
   605 			v->current_order.type = OT_GOTO_DEPOT;
   608 			v->current_order.type = OT_GOTO_DEPOT;
   606 			v->current_order.flags = OF_NON_STOP;
   609 			v->current_order.flags = OF_NON_STOP;
   607 			if (!(p2 & DEPOT_SERVICE)) SETBIT(v->current_order.flags, OFB_HALT_IN_DEPOT);
   610 			if (!(p2 & DEPOT_SERVICE)) SetBit(v->current_order.flags, OFB_HALT_IN_DEPOT);
   608 			v->current_order.refit_cargo = CT_INVALID;
   611 			v->current_order.refit_cargo = CT_INVALID;
   609 			v->current_order.dest = next_airport_index;
   612 			v->current_order.dest = next_airport_index;
   610 			InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
   613 			InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
   611 			if (v->u.air.state == FLYING && !next_airport_has_hangar) {
   614 			if (v->u.air.state == FLYING && !next_airport_has_hangar) {
   612 				/* The aircraft is now heading for a different hangar than the next in the orders */
   615 				/* The aircraft is now heading for a different hangar than the next in the orders */
   646 
   649 
   647 	SET_EXPENSES_TYPE(EXPENSES_AIRCRAFT_RUN);
   650 	SET_EXPENSES_TYPE(EXPENSES_AIRCRAFT_RUN);
   648 
   651 
   649 	/* Check the refit capacity callback */
   652 	/* Check the refit capacity callback */
   650 	uint16 callback = CALLBACK_FAILED;
   653 	uint16 callback = CALLBACK_FAILED;
   651 	if (HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_REFIT_CAPACITY)) {
   654 	if (HasBit(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_REFIT_CAPACITY)) {
   652 		/* Back up the existing cargo type */
   655 		/* Back up the existing cargo type */
   653 		CargoID temp_cid = v->cargo_type;
   656 		CargoID temp_cid = v->cargo_type;
   654 		byte temp_subtype = v->cargo_subtype;
   657 		byte temp_subtype = v->cargo_subtype;
   655 		v->cargo_type = new_cid;
   658 		v->cargo_type = new_cid;
   656 		v->cargo_subtype = new_subtype;
   659 		v->cargo_subtype = new_subtype;
   829 	VehiclePositionChanged(v);
   832 	VehiclePositionChanged(v);
   830 	EndVehicleMove(v);
   833 	EndVehicleMove(v);
   831 
   834 
   832 	Vehicle *u = v->Next();
   835 	Vehicle *u = v->Next();
   833 
   836 
   834 	int safe_x = clamp(x, 0, MapMaxX() * TILE_SIZE);
   837 	int safe_x = Clamp(x, 0, MapMaxX() * TILE_SIZE);
   835 	int safe_y = clamp(y - 1, 0, MapMaxY() * TILE_SIZE);
   838 	int safe_y = Clamp(y - 1, 0, MapMaxY() * TILE_SIZE);
   836 	u->x_pos = x;
   839 	u->x_pos = x;
   837 	u->y_pos = y - ((v->z_pos-GetSlopeZ(safe_x, safe_y)) >> 3);;
   840 	u->y_pos = y - ((v->z_pos-GetSlopeZ(safe_x, safe_y)) >> 3);;
   838 
   841 
   839 	safe_y = clamp(u->y_pos, 0, MapMaxY() * TILE_SIZE);
   842 	safe_y = Clamp(u->y_pos, 0, MapMaxY() * TILE_SIZE);
   840 	u->z_pos = GetSlopeZ(safe_x, safe_y);
   843 	u->z_pos = GetSlopeZ(safe_x, safe_y);
   841 	u->cur_image = v->cur_image;
   844 	u->cur_image = v->cur_image;
   842 
   845 
   843 	BeginVehicleMove(u);
   846 	BeginVehicleMove(u);
   844 	VehiclePositionChanged(u);
   847 	VehiclePositionChanged(u);
  1108 		}
  1111 		}
  1109 		return false;
  1112 		return false;
  1110 	}
  1113 	}
  1111 
  1114 
  1112 	/* Get distance from destination pos to current pos. */
  1115 	/* Get distance from destination pos to current pos. */
  1113 	uint dist = myabs(x + amd->x - v->x_pos) +  myabs(y + amd->y - v->y_pos);
  1116 	uint dist = abs(x + amd->x - v->x_pos) +  abs(y + amd->y - v->y_pos);
  1114 
  1117 
  1115 	/* Need exact position? */
  1118 	/* Need exact position? */
  1116 	if (!(amd->flag & AMED_EXACTPOS) && dist <= (amd->flag & AMED_SLOWTURN ? 8U : 4U)) return true;
  1119 	if (!(amd->flag & AMED_EXACTPOS) && dist <= (amd->flag & AMED_SLOWTURN ? 8U : 4U)) return true;
  1117 
  1120 
  1118 	/* At final pos? */
  1121 	/* At final pos? */
  1150 
  1153 
  1151 	do {
  1154 	do {
  1152 
  1155 
  1153 		GetNewVehiclePosResult gp;
  1156 		GetNewVehiclePosResult gp;
  1154 
  1157 
  1155 		if (dist < 4) {
  1158 		if (dist < 4 || amd->flag & AMED_LAND) {
  1156 			/* move vehicle one pixel towards target */
  1159 			/* move vehicle one pixel towards target */
  1157 			gp.x = (v->x_pos != (x + amd->x)) ?
  1160 			gp.x = (v->x_pos != (x + amd->x)) ?
  1158 					v->x_pos + ((x + amd->x > v->x_pos) ? 1 : -1) :
  1161 					v->x_pos + ((x + amd->x > v->x_pos) ? 1 : -1) :
  1159 					v->x_pos;
  1162 					v->x_pos;
  1160 			gp.y = (v->y_pos != (y + amd->y)) ?
  1163 			gp.y = (v->y_pos != (y + amd->y)) ?
  1678 	/* check if the aircraft needs to be replaced or renewed and send it to a hangar if needed
  1681 	/* check if the aircraft needs to be replaced or renewed and send it to a hangar if needed
  1679 	 * unless it is due for renewal but the engine is no longer available */
  1682 	 * unless it is due for renewal but the engine is no longer available */
  1680 	if (v->owner == _local_player && (
  1683 	if (v->owner == _local_player && (
  1681 				EngineHasReplacementForPlayer(p, v->engine_type, v->group_id) ||
  1684 				EngineHasReplacementForPlayer(p, v->engine_type, v->group_id) ||
  1682 				((p->engine_renew && v->age - v->max_age > p->engine_renew_months * 30) &&
  1685 				((p->engine_renew && v->age - v->max_age > p->engine_renew_months * 30) &&
  1683 				HASBIT(GetEngine(v->engine_type)->player_avail, _local_player))
  1686 				HasBit(GetEngine(v->engine_type)->player_avail, _local_player))
  1684 			)) {
  1687 			)) {
  1685 		_current_player = _local_player;
  1688 		_current_player = _local_player;
  1686 		DoCommandP(v->tile, v->index, DEPOT_SERVICE | DEPOT_LOCATE_HANGAR, NULL, CMD_SEND_AIRCRAFT_TO_HANGAR | CMD_SHOW_NO_ERROR);
  1689 		DoCommandP(v->tile, v->index, DEPOT_SERVICE | DEPOT_LOCATE_HANGAR, NULL, CMD_SEND_AIRCRAFT_TO_HANGAR | CMD_SHOW_NO_ERROR);
  1687 		_current_player = OWNER_NONE;
  1690 		_current_player = OWNER_NONE;
  1688 	}
  1691 	}
  1955 
  1958 
  1956 static bool FreeTerminal(Vehicle *v, byte i, byte last_terminal)
  1959 static bool FreeTerminal(Vehicle *v, byte i, byte last_terminal)
  1957 {
  1960 {
  1958 	Station *st = GetStation(v->u.air.targetairport);
  1961 	Station *st = GetStation(v->u.air.targetairport);
  1959 	for (; i < last_terminal; i++) {
  1962 	for (; i < last_terminal; i++) {
  1960 		if (!HASBIT(st->airport_flags, _airport_terminal_flag[i])) {
  1963 		if (!HasBit(st->airport_flags, _airport_terminal_flag[i])) {
  1961 			/* TERMINAL# HELIPAD# */
  1964 			/* TERMINAL# HELIPAD# */
  1962 			v->u.air.state = _airport_terminal_state[i]; // start moving to that terminal/helipad
  1965 			v->u.air.state = _airport_terminal_state[i]; // start moving to that terminal/helipad
  1963 			SETBIT(st->airport_flags, _airport_terminal_flag[i]); // occupy terminal/helipad
  1966 			SetBit(st->airport_flags, _airport_terminal_flag[i]); // occupy terminal/helipad
  1964 			return true;
  1967 			return true;
  1965 		}
  1968 		}
  1966 	}
  1969 	}
  1967 	return false;
  1970 	return false;
  1968 }
  1971 }