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); |
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 { |