src/aircraft_cmd.cpp
changeset 10207 c291a21b304e
parent 10177 41ce7529a331
child 10208 72c00af5c95d
equal deleted inserted replaced
10206:0050610c0368 10207:c291a21b304e
   102 	HRS_ROTOR_MOVING_2,
   102 	HRS_ROTOR_MOVING_2,
   103 	HRS_ROTOR_MOVING_3,
   103 	HRS_ROTOR_MOVING_3,
   104 };
   104 };
   105 
   105 
   106 /** Find the nearest hangar to v
   106 /** Find the nearest hangar to v
   107  * INVALID_STATION is returned, if the player does not have any suitable
   107  * INVALID_STATION is returned, if the company does not have any suitable
   108  * airports (like helipads only)
   108  * airports (like helipads only)
   109  * @param v vehicle looking for a hangar
   109  * @param v vehicle looking for a hangar
   110  * @return the StationID if one is found, otherwise, INVALID_STATION
   110  * @return the StationID if one is found, otherwise, INVALID_STATION
   111  */
   111  */
   112 static StationID FindNearestHangar(const Vehicle *v)
   112 static StationID FindNearestHangar(const Vehicle *v)
   264  * @param p2 unused
   264  * @param p2 unused
   265  * return result of operation.  Could be cost, error
   265  * return result of operation.  Could be cost, error
   266  */
   266  */
   267 CommandCost CmdBuildAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   267 CommandCost CmdBuildAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   268 {
   268 {
   269 	if (!IsEngineBuildable(p1, VEH_AIRCRAFT, _current_player)) return_cmd_error(STR_AIRCRAFT_NOT_AVAILABLE);
   269 	if (!IsEngineBuildable(p1, VEH_AIRCRAFT, _current_company)) return_cmd_error(STR_AIRCRAFT_NOT_AVAILABLE);
   270 
   270 
   271 	const AircraftVehicleInfo *avi = AircraftVehInfo(p1);
   271 	const AircraftVehicleInfo *avi = AircraftVehInfo(p1);
   272 	CommandCost value = EstimateAircraftCost(p1, avi);
   272 	CommandCost value = EstimateAircraftCost(p1, avi);
   273 
   273 
   274 	/* to just query the cost, it is not neccessary to have a valid tile (automation/AI) */
   274 	/* to just query the cost, it is not neccessary to have a valid tile (automation/AI) */
   275 	if (flags & DC_QUERY_COST) return value;
   275 	if (flags & DC_QUERY_COST) return value;
   276 
   276 
   277 	if (!IsHangarTile(tile) || !IsTileOwner(tile, _current_player)) return CMD_ERROR;
   277 	if (!IsHangarTile(tile) || !IsTileOwner(tile, _current_company)) return CMD_ERROR;
   278 
   278 
   279 	/* Prevent building aircraft types at places which can't handle them */
   279 	/* Prevent building aircraft types at places which can't handle them */
   280 	if (!CanAircraftUseStation(p1, tile)) return CMD_ERROR;
   280 	if (!CanAircraftUseStation(p1, tile)) return CMD_ERROR;
   281 
   281 
   282 	/* Allocate 2 or 3 vehicle structs, depending on type
   282 	/* Allocate 2 or 3 vehicle structs, depending on type
   297 		v = new (v) Aircraft();
   297 		v = new (v) Aircraft();
   298 		u = new (u) Aircraft();
   298 		u = new (u) Aircraft();
   299 		v->unitnumber = unit_num;
   299 		v->unitnumber = unit_num;
   300 		v->direction = DIR_SE;
   300 		v->direction = DIR_SE;
   301 
   301 
   302 		v->owner = u->owner = _current_player;
   302 		v->owner = u->owner = _current_company;
   303 
   303 
   304 		v->tile = tile;
   304 		v->tile = tile;
   305 //		u->tile = 0;
   305 //		u->tile = 0;
   306 
   306 
   307 		uint x = TileX(tile) * TILE_SIZE + 5;
   307 		uint x = TileX(tile) * TILE_SIZE + 5;
   426 		if (v->subtype == AIR_HELICOPTER) {
   426 		if (v->subtype == AIR_HELICOPTER) {
   427 			Vehicle *w = vl[2];
   427 			Vehicle *w = vl[2];
   428 
   428 
   429 			w = new (w) Aircraft();
   429 			w = new (w) Aircraft();
   430 			w->direction = DIR_N;
   430 			w->direction = DIR_N;
   431 			w->owner = _current_player;
   431 			w->owner = _current_company;
   432 			w->x_pos = v->x_pos;
   432 			w->x_pos = v->x_pos;
   433 			w->y_pos = v->y_pos;
   433 			w->y_pos = v->y_pos;
   434 			w->z_pos = v->z_pos + 5;
   434 			w->z_pos = v->z_pos + 5;
   435 			w->vehstatus = VS_HIDDEN | VS_UNCLICKABLE;
   435 			w->vehstatus = VS_HIDDEN | VS_UNCLICKABLE;
   436 			w->spritenum = 0xFF;
   436 			w->spritenum = 0xFF;
   446 		}
   446 		}
   447 
   447 
   448 		InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
   448 		InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
   449 		InvalidateWindowClassesData(WC_AIRCRAFT_LIST, 0);
   449 		InvalidateWindowClassesData(WC_AIRCRAFT_LIST, 0);
   450 		InvalidateWindow(WC_COMPANY, v->owner);
   450 		InvalidateWindow(WC_COMPANY, v->owner);
   451 		if (IsLocalPlayer())
   451 		if (IsLocalCompany())
   452 			InvalidateAutoreplaceWindow(v->engine_type, v->group_id); //updates the replace Aircraft window
   452 			InvalidateAutoreplaceWindow(v->engine_type, v->group_id); //updates the replace Aircraft window
   453 
   453 
   454 		GetPlayer(_current_player)->num_engines[p1]++;
   454 		GetCompany(_current_company)->num_engines[p1]++;
   455 	}
   455 	}
   456 
   456 
   457 	return value;
   457 	return value;
   458 }
   458 }
   459 
   459 
   527 CommandCost CmdSendAircraftToHangar(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   527 CommandCost CmdSendAircraftToHangar(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   528 {
   528 {
   529 	if (p2 & DEPOT_MASS_SEND) {
   529 	if (p2 & DEPOT_MASS_SEND) {
   530 		/* Mass goto depot requested */
   530 		/* Mass goto depot requested */
   531 		if (!ValidVLWFlags(p2 & VLW_MASK)) return CMD_ERROR;
   531 		if (!ValidVLWFlags(p2 & VLW_MASK)) return CMD_ERROR;
   532 		return SendAllVehiclesToDepot(VEH_AIRCRAFT, flags, p2 & DEPOT_SERVICE, _current_player, (p2 & VLW_MASK), p1);
   532 		return SendAllVehiclesToDepot(VEH_AIRCRAFT, flags, p2 & DEPOT_SERVICE, _current_company, (p2 & VLW_MASK), p1);
   533 	}
   533 	}
   534 
   534 
   535 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
   535 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
   536 
   536 
   537 	Vehicle *v = GetVehicle(p1);
   537 	Vehicle *v = GetVehicle(p1);
   595 		pass = callback;
   595 		pass = callback;
   596 	}
   596 	}
   597 	_returned_refit_capacity = pass;
   597 	_returned_refit_capacity = pass;
   598 
   598 
   599 	CommandCost cost;
   599 	CommandCost cost;
   600 	if (IsHumanPlayer(v->owner) && new_cid != v->cargo_type) {
   600 	if (IsHumanCompany(v->owner) && new_cid != v->cargo_type) {
   601 		cost = GetRefitCost(v->engine_type);
   601 		cost = GetRefitCost(v->engine_type);
   602 	}
   602 	}
   603 
   603 
   604 	if (flags & DC_EXEC) {
   604 	if (flags & DC_EXEC) {
   605 		v->cargo_cap = pass;
   605 		v->cargo_cap = pass;
   658 	CommandCost cost(EXPENSES_AIRCRAFT_RUN, GetVehicleProperty(this, 0x0E, AircraftVehInfo(this->engine_type)->running_cost) * _price.aircraft_running * this->running_ticks / (364 * DAY_TICKS));
   658 	CommandCost cost(EXPENSES_AIRCRAFT_RUN, GetVehicleProperty(this, 0x0E, AircraftVehInfo(this->engine_type)->running_cost) * _price.aircraft_running * this->running_ticks / (364 * DAY_TICKS));
   659 
   659 
   660 	this->profit_this_year -= cost.GetCost();
   660 	this->profit_this_year -= cost.GetCost();
   661 	this->running_ticks = 0;
   661 	this->running_ticks = 0;
   662 
   662 
   663 	SubtractMoneyFromPlayerFract(this->owner, cost);
   663 	SubtractMoneyFromCompanyFract(this->owner, cost);
   664 
   664 
   665 	InvalidateWindow(WC_VEHICLE_DETAILS, this->index);
   665 	InvalidateWindow(WC_VEHICLE_DETAILS, this->index);
   666 	InvalidateWindowClasses(WC_AIRCRAFT_LIST);
   666 	InvalidateWindowClasses(WC_AIRCRAFT_LIST);
   667 }
   667 }
   668 
   668 
  1310 	 *    actually stops.
  1310 	 *    actually stops.
  1311 	 */
  1311 	 */
  1312 	const Station *st = GetTargetAirportIfValid(v);
  1312 	const Station *st = GetTargetAirportIfValid(v);
  1313 	if (st == NULL) {
  1313 	if (st == NULL) {
  1314 		CommandCost ret;
  1314 		CommandCost ret;
  1315 		PlayerID old_player = _current_player;
  1315 		CompanyID old_company = _current_company;
  1316 
  1316 
  1317 		_current_player = v->owner;
  1317 		_current_company = v->owner;
  1318 		ret = DoCommand(v->tile, v->index, 0, DC_EXEC, CMD_SEND_AIRCRAFT_TO_HANGAR);
  1318 		ret = DoCommand(v->tile, v->index, 0, DC_EXEC, CMD_SEND_AIRCRAFT_TO_HANGAR);
  1319 		_current_player = old_player;
  1319 		_current_company = old_company;
  1320 
  1320 
  1321 		if (CmdFailed(ret)) CrashAirplane(v);
  1321 		if (CmdFailed(ret)) CrashAirplane(v);
  1322 	} else if (!v->current_order.IsType(OT_GOTO_DEPOT)) {
  1322 	} else if (!v->current_order.IsType(OT_GOTO_DEPOT)) {
  1323 		v->current_order.Free();
  1323 		v->current_order.Free();
  1324 	}
  1324 	}
  1411 		st->had_vehicle_of_type |= HVOT_AIRCRAFT;
  1411 		st->had_vehicle_of_type |= HVOT_AIRCRAFT;
  1412 		SetDParam(0, st->index);
  1412 		SetDParam(0, st->index);
  1413 		/* show newsitem of celebrating citizens */
  1413 		/* show newsitem of celebrating citizens */
  1414 		AddNewsItem(
  1414 		AddNewsItem(
  1415 			STR_A033_CITIZENS_CELEBRATE_FIRST,
  1415 			STR_A033_CITIZENS_CELEBRATE_FIRST,
  1416 			(v->owner == _local_player) ? NS_ARRIVAL_PLAYER : NS_ARRIVAL_OTHER,
  1416 			(v->owner == _local_company) ? NS_ARRIVAL_COMPANY : NS_ARRIVAL_OTHER,
  1417 			v->index,
  1417 			v->index,
  1418 			st->index
  1418 			st->index
  1419 		);
  1419 		);
  1420 	}
  1420 	}
  1421 
  1421 
  1475  * @return true if the aircraft should head towards a hangar
  1475  * @return true if the aircraft should head towards a hangar
  1476  */
  1476  */
  1477 static inline bool CheckSendAircraftToHangarForReplacement(const Vehicle *v)
  1477 static inline bool CheckSendAircraftToHangarForReplacement(const Vehicle *v)
  1478 {
  1478 {
  1479 	EngineID new_engine;
  1479 	EngineID new_engine;
  1480 	Player *p = GetPlayer(v->owner);
  1480 	Company *c = GetCompany(v->owner);
  1481 
  1481 
  1482 	if (VehicleHasDepotOrders(v)) return false; // The aircraft will end up in the hangar eventually on it's own
  1482 	if (VehicleHasDepotOrders(v)) return false; // The aircraft will end up in the hangar eventually on it's own
  1483 
  1483 
  1484 	new_engine = EngineReplacementForPlayer(p, v->engine_type, v->group_id);
  1484 	new_engine = EngineReplacementForCompany(c, v->engine_type, v->group_id);
  1485 
  1485 
  1486 	if (new_engine == INVALID_ENGINE) {
  1486 	if (new_engine == INVALID_ENGINE) {
  1487 		/* There is no autoreplace assigned to this EngineID so we will set it to renew to the same type if needed */
  1487 		/* There is no autoreplace assigned to this EngineID so we will set it to renew to the same type if needed */
  1488 		new_engine = v->engine_type;
  1488 		new_engine = v->engine_type;
  1489 
  1489 
  1490 		if (!v->NeedsAutorenewing(p)) {
  1490 		if (!v->NeedsAutorenewing(c)) {
  1491 			/* No need to replace the aircraft */
  1491 			/* No need to replace the aircraft */
  1492 			return false;
  1492 			return false;
  1493 		}
  1493 		}
  1494 	}
  1494 	}
  1495 
  1495 
  1496 	if (!HasBit(GetEngine(new_engine)->player_avail, v->owner)) {
  1496 	if (!HasBit(GetEngine(new_engine)->company_avail, v->owner)) {
  1497 		/* Engine is not buildable anymore */
  1497 		/* Engine is not buildable anymore */
  1498 		return false;
  1498 		return false;
  1499 	}
  1499 	}
  1500 
  1500 
  1501 	if (p->player_money < (p->engine_renew_money + (2 * DoCommand(0, new_engine, 0, DC_QUERY_COST, CMD_BUILD_AIRCRAFT).GetCost()))) {
  1501 	if (c->money < (c->engine_renew_money + (2 * DoCommand(0, new_engine, 0, DC_QUERY_COST, CMD_BUILD_AIRCRAFT).GetCost()))) {
  1502 		/* We lack enough money to request the replacement right away.
  1502 		/* We lack enough money to request the replacement right away.
  1503 		 * We want 2*(the price of the new vehicle) and not looking at the value of the vehicle we are going to sell.
  1503 		 * We want 2*(the price of the new vehicle) and not looking at the value of the vehicle we are going to sell.
  1504 		 * The reason is that we don't want to send a whole lot of vehicles to the hangars when we only have enough money to replace a single one.
  1504 		 * The reason is that we don't want to send a whole lot of vehicles to the hangars when we only have enough money to replace a single one.
  1505 		 * Remember this happens in the background so the user can't stop this. */
  1505 		 * Remember this happens in the background so the user can't stop this. */
  1506 		return false;
  1506 		return false;
  1650 	/* get the next position to go to, differs per airport */
  1650 	/* get the next position to go to, differs per airport */
  1651 	AircraftNextAirportPos_and_Order(v);
  1651 	AircraftNextAirportPos_and_Order(v);
  1652 
  1652 
  1653 	/* Send the helicopter to a hangar if needed for replacement */
  1653 	/* Send the helicopter to a hangar if needed for replacement */
  1654 	if (CheckSendAircraftToHangarForReplacement(v)) {
  1654 	if (CheckSendAircraftToHangarForReplacement(v)) {
  1655 		_current_player = v->owner;
  1655 		_current_company = v->owner;
  1656 		DoCommand(v->tile, v->index, DEPOT_SERVICE | DEPOT_LOCATE_HANGAR, DC_EXEC, CMD_SEND_AIRCRAFT_TO_HANGAR);
  1656 		DoCommand(v->tile, v->index, DEPOT_SERVICE | DEPOT_LOCATE_HANGAR, DC_EXEC, CMD_SEND_AIRCRAFT_TO_HANGAR);
  1657 		_current_player = OWNER_NONE;
  1657 		_current_company = OWNER_NONE;
  1658 	}
  1658 	}
  1659 }
  1659 }
  1660 
  1660 
  1661 static void AircraftEventHandler_Flying(Vehicle *v, const AirportFTAClass *apc)
  1661 static void AircraftEventHandler_Flying(Vehicle *v, const AirportFTAClass *apc)
  1662 {
  1662 {
  1702 	v->u.air.state = ENDLANDING;
  1702 	v->u.air.state = ENDLANDING;
  1703 	AircraftLandAirplane(v);  // maybe crash airplane
  1703 	AircraftLandAirplane(v);  // maybe crash airplane
  1704 
  1704 
  1705 	/* check if the aircraft needs to be replaced or renewed and send it to a hangar if needed */
  1705 	/* check if the aircraft needs to be replaced or renewed and send it to a hangar if needed */
  1706 	if (CheckSendAircraftToHangarForReplacement(v)) {
  1706 	if (CheckSendAircraftToHangarForReplacement(v)) {
  1707 		_current_player = v->owner;
  1707 		_current_company = v->owner;
  1708 		DoCommand(v->tile, v->index, DEPOT_SERVICE, DC_EXEC, CMD_SEND_AIRCRAFT_TO_HANGAR);
  1708 		DoCommand(v->tile, v->index, DEPOT_SERVICE, DC_EXEC, CMD_SEND_AIRCRAFT_TO_HANGAR);
  1709 		_current_player = OWNER_NONE;
  1709 		_current_company = OWNER_NONE;
  1710 	}
  1710 	}
  1711 }
  1711 }
  1712 
  1712 
  1713 static void AircraftEventHandler_HeliLanding(Vehicle *v, const AirportFTAClass *apc)
  1713 static void AircraftEventHandler_HeliLanding(Vehicle *v, const AirportFTAClass *apc)
  1714 {
  1714 {