|
@@ -424,25 +424,25 @@ CommandCost CmdBuildAircraft(TileIndex t
|
|
|
w->cur_image = SPR_ROTOR_STOPPED;
|
|
|
w->random_bits = VehicleRandomBits();
|
|
|
/* Use rotor's air.state to store the rotor animation frame */
|
|
|
w->state = HRS_ROTOR_STOPPED;
|
|
|
w->UpdateDeltaXY(INVALID_DIR);
|
|
|
|
|
|
u->SetNext(w);
|
|
|
VehicleMove(w, false);
|
|
|
}
|
|
|
|
|
|
InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
|
|
|
InvalidateWindowClassesData(WC_AIRCRAFT_LIST, 0);
|
|
|
InvalidateWindow(WC_COMPANY, v->owner);
|
|
|
SetWindowDirty(WC_COMPANY, v->owner);
|
|
|
if (IsLocalCompany())
|
|
|
InvalidateAutoreplaceWindow(v->engine_type, v->group_id); // updates the replace Aircraft window
|
|
|
|
|
|
Company::Get(_current_company)->num_engines[p1]++;
|
|
|
}
|
|
|
|
|
|
return value;
|
|
|
}
|
|
|
|
|
|
|
|
|
/** Sell an aircraft.
|
|
|
* @param tile unused
|
|
@@ -571,54 +571,54 @@ CommandCost CmdRefitAircraft(TileIndex t
|
|
|
if (flags & DC_EXEC) {
|
|
|
v->cargo_cap = pass;
|
|
|
|
|
|
Vehicle *u = v->Next();
|
|
|
uint mail = IsCargoInClass(new_cid, CC_PASSENGERS) ? avi->mail_capacity : 0;
|
|
|
u->cargo_cap = mail;
|
|
|
v->cargo.Truncate(v->cargo_type == new_cid ? pass : 0);
|
|
|
u->cargo.Truncate(v->cargo_type == new_cid ? mail : 0);
|
|
|
v->cargo_type = new_cid;
|
|
|
v->cargo_subtype = new_subtype;
|
|
|
v->colourmap = PAL_NONE; // invalidate vehicle colour map
|
|
|
v->InvalidateNewGRFCacheOfChain();
|
|
|
InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
|
|
|
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
|
|
|
SetWindowDirty(WC_VEHICLE_DETAILS, v->index);
|
|
|
SetWindowDirty(WC_VEHICLE_DEPOT, v->tile);
|
|
|
InvalidateWindowClassesData(WC_AIRCRAFT_LIST, 0);
|
|
|
}
|
|
|
|
|
|
return cost;
|
|
|
}
|
|
|
|
|
|
|
|
|
static void CheckIfAircraftNeedsService(Aircraft *v)
|
|
|
{
|
|
|
if (Company::Get(v->owner)->settings.vehicle.servint_aircraft == 0 || !v->NeedsAutomaticServicing()) return;
|
|
|
if (v->IsInDepot()) {
|
|
|
VehicleServiceInDepot(v);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
const Station *st = Station::Get(v->current_order.GetDestination());
|
|
|
|
|
|
assert(st != NULL);
|
|
|
|
|
|
/* only goto depot if the target airport has terminals (eg. it is airport) */
|
|
|
if (st->airport_tile != INVALID_TILE && st->Airport()->terminals != NULL) {
|
|
|
// printf("targetairport = %d, st->index = %d\n", v->targetairport, st->index);
|
|
|
// v->targetairport = st->index;
|
|
|
v->current_order.MakeGoToDepot(st->index, ODTFB_SERVICE);
|
|
|
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
|
|
|
SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
|
|
|
} else if (v->current_order.IsType(OT_GOTO_DEPOT)) {
|
|
|
v->current_order.MakeDummy();
|
|
|
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
|
|
|
SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
Money Aircraft::GetRunningCost() const
|
|
|
{
|
|
|
return GetVehicleProperty(this, 0x0E, AircraftVehInfo(this->engine_type)->running_cost) * _price.aircraft_running;
|
|
|
}
|
|
|
|
|
|
void Aircraft::OnNewDay()
|
|
|
{
|
|
|
if (!this->IsNormalAircraft()) return;
|
|
|
|
|
@@ -630,26 +630,26 @@ void Aircraft::OnNewDay()
|
|
|
AgeVehicle(this);
|
|
|
CheckIfAircraftNeedsService(this);
|
|
|
|
|
|
if (this->running_ticks == 0) return;
|
|
|
|
|
|
CommandCost cost(EXPENSES_AIRCRAFT_RUN, this->GetRunningCost() * this->running_ticks / (DAYS_IN_YEAR * DAY_TICKS));
|
|
|
|
|
|
this->profit_this_year -= cost.GetCost();
|
|
|
this->running_ticks = 0;
|
|
|
|
|
|
SubtractMoneyFromCompanyFract(this->owner, cost);
|
|
|
|
|
|
InvalidateWindow(WC_VEHICLE_DETAILS, this->index);
|
|
|
InvalidateWindowClasses(WC_AIRCRAFT_LIST);
|
|
|
SetWindowDirty(WC_VEHICLE_DETAILS, this->index);
|
|
|
SetWindowClassesDirty(WC_AIRCRAFT_LIST);
|
|
|
}
|
|
|
|
|
|
static void HelicopterTickHandler(Aircraft *v)
|
|
|
{
|
|
|
Aircraft *u = v->Next()->Next();
|
|
|
|
|
|
if (u->vehstatus & VS_HIDDEN) return;
|
|
|
|
|
|
/* if true, helicopter rotors do not rotate. This should only be the case if a helicopter is
|
|
|
* loading/unloading at a terminal or stopped */
|
|
|
if (v->current_order.IsType(OT_LOADING) || (v->vehstatus & VS_STOPPED)) {
|
|
|
if (u->cur_speed != 0) {
|
|
@@ -807,25 +807,25 @@ static int UpdateAircraftSpeed(Aircraft
|
|
|
speed_limit = v->cur_speed - max(1, ((v->cur_speed * v->cur_speed) / 16384) / _settings_game.vehicle.plane_speed);
|
|
|
}
|
|
|
|
|
|
spd = min(v->cur_speed + (spd >> 8) + (v->subspeed < t), speed_limit);
|
|
|
|
|
|
/* adjust speed for broken vehicles */
|
|
|
if (v->vehstatus & VS_AIRCRAFT_BROKEN) spd = min(spd, SPEED_LIMIT_BROKEN);
|
|
|
|
|
|
/* updates statusbar only if speed have changed to save CPU time */
|
|
|
if (spd != v->cur_speed) {
|
|
|
v->cur_speed = spd;
|
|
|
if (_settings_client.gui.vehicle_speed)
|
|
|
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
|
|
|
SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
|
|
|
}
|
|
|
|
|
|
/* Adjust distance moved by plane speed setting */
|
|
|
if (_settings_game.vehicle.plane_speed > 1) spd /= _settings_game.vehicle.plane_speed;
|
|
|
|
|
|
if (!(v->direction & 1)) spd = spd * 3 / 4;
|
|
|
|
|
|
spd += v->progress;
|
|
|
v->progress = (byte)spd;
|
|
|
return spd >> 8;
|
|
|
}
|
|
|
|
|
@@ -1210,26 +1210,26 @@ static bool HandleCrashedAircraft(Aircra
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
static void HandleBrokenAircraft(Aircraft *v)
|
|
|
{
|
|
|
if (v->breakdown_ctr != 1) {
|
|
|
v->breakdown_ctr = 1;
|
|
|
v->vehstatus |= VS_AIRCRAFT_BROKEN;
|
|
|
|
|
|
if (v->breakdowns_since_last_service != 255)
|
|
|
v->breakdowns_since_last_service++;
|
|
|
InvalidateWindow(WC_VEHICLE_VIEW, v->index);
|
|
|
InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
|
|
|
SetWindowDirty(WC_VEHICLE_VIEW, v->index);
|
|
|
SetWindowDirty(WC_VEHICLE_DETAILS, v->index);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
static void HandleAircraftSmoke(Aircraft *v)
|
|
|
{
|
|
|
static const struct {
|
|
|
int8 x;
|
|
|
int8 y;
|
|
|
} smoke_pos[] = {
|
|
|
{ 5, 5 },
|
|
|
{ 6, 0 },
|
|
@@ -1307,25 +1307,25 @@ void Aircraft::MarkDirty()
|
|
|
{
|
|
|
this->UpdateViewport(false, false);
|
|
|
if (this->subtype == AIR_HELICOPTER) this->Next()->Next()->cur_image = GetRotorImage(this);
|
|
|
}
|
|
|
|
|
|
static void CrashAirplane(Aircraft *v)
|
|
|
{
|
|
|
v->vehstatus |= VS_CRASHED;
|
|
|
v->crashed_counter = 0;
|
|
|
|
|
|
CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE);
|
|
|
|
|
|
InvalidateWindow(WC_VEHICLE_VIEW, v->index);
|
|
|
SetWindowDirty(WC_VEHICLE_VIEW, v->index);
|
|
|
|
|
|
uint amt = 2;
|
|
|
if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) amt += v->cargo.Count();
|
|
|
SetDParam(0, amt);
|
|
|
|
|
|
v->cargo.Truncate(0);
|
|
|
v->Next()->cargo.Truncate(0);
|
|
|
const Station *st = GetTargetAirportIfValid(v);
|
|
|
StringID newsitem;
|
|
|
AIEventVehicleCrashed::CrashReason crash_reason;
|
|
|
if (st == NULL) {
|
|
|
newsitem = STR_NEWS_PLANE_CRASH_OUT_OF_FUEL;
|
|
@@ -1430,25 +1430,25 @@ void AircraftLeaveHangar(Aircraft *v)
|
|
|
|
|
|
/* Rotor blades */
|
|
|
u = u->Next();
|
|
|
if (u != NULL) {
|
|
|
u->vehstatus &= ~VS_HIDDEN;
|
|
|
u->cur_speed = 80;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
VehicleServiceInDepot(v);
|
|
|
SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos);
|
|
|
InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
|
|
|
InvalidateWindowClasses(WC_AIRCRAFT_LIST);
|
|
|
SetWindowClassesDirty(WC_AIRCRAFT_LIST);
|
|
|
}
|
|
|
|
|
|
/** Checks if an aircraft should head towards a hangar because it needs replacement
|
|
|
* @param *v the vehicle to test
|
|
|
* @return true if the aircraft should head towards a hangar
|
|
|
*/
|
|
|
static inline bool CheckSendAircraftToHangarForReplacement(const Vehicle *v)
|
|
|
{
|
|
|
EngineID new_engine;
|
|
|
Company *c = Company::Get(v->owner);
|
|
|
|
|
|
if (VehicleHasDepotOrders(v)) return false; // The aircraft will end up in the hangar eventually on it's own
|
|
@@ -1541,25 +1541,25 @@ static void AircraftEventHandler_AtTermi
|
|
|
{
|
|
|
/* if we just arrived, execute EnterTerminal first */
|
|
|
if (v->previous_pos != v->pos) {
|
|
|
AircraftEventHandler_EnterTerminal(v, apc);
|
|
|
/* on an airport with helipads, a helicopter will always land there
|
|
|
* and get serviced at the same time - setting */
|
|
|
if (_settings_game.order.serviceathelipad) {
|
|
|
if (v->subtype == AIR_HELICOPTER && apc->helipads != NULL) {
|
|
|
/* an exerpt of ServiceAircraft, without the invisibility stuff */
|
|
|
v->date_of_last_service = _date;
|
|
|
v->breakdowns_since_last_service = 0;
|
|
|
v->reliability = Engine::Get(v->engine_type)->reliability;
|
|
|
InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
|
|
|
SetWindowDirty(WC_VEHICLE_DETAILS, v->index);
|
|
|
}
|
|
|
}
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (v->current_order.IsType(OT_NOTHING)) return;
|
|
|
|
|
|
/* if the block of the next position is busy, stay put */
|
|
|
if (AirportHasBlock(v, &apc->layout[v->pos], apc)) return;
|
|
|
|
|
|
/* airport-road is free. We either have to go to another airport, or to the hangar
|
|
|
* ---> start moving */
|