diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/train_cmd.cpp | 133 | ||||
-rw-r--r-- | src/vehicle.cpp | 132 | ||||
-rw-r--r-- | src/vehicle_base.h | 6 |
3 files changed, 139 insertions, 132 deletions
diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index b1373d379..26b45b1f1 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -1886,137 +1886,6 @@ bool Train::FindClosestDepot(TileIndex *location, DestinationID *destination, bo return true; } -static const int8 _vehicle_smoke_pos[8] = { - 1, 1, 1, 0, -1, -1, -1, 0 -}; - -static void HandleLocomotiveSmokeCloud(const Vehicle *v) -{ - assert(v->IsPrimaryVehicle()); - bool sound = false; - - /* Do not show any smoke when: - * - vehicle smoke is disabled by the player - * - the vehicle is slowing down or stopped (by the player) - * - the vehicle is moving very slowly - */ - if (_settings_game.vehicle.smoke_amount == 0 || - v->vehstatus & (VS_TRAIN_SLOWING | VS_STOPPED) || - v->cur_speed < 2) { - return; - } - if (v->type == VEH_TRAIN) { - const Train *t = Train::From(v); - /* For trains, do not show any smoke when: - * - the train is reversing - * - is entering a station with an order to stop there and its speed is equal to maximum station entering speed - */ - if (HasBit(t->flags, VRF_REVERSING) || - (IsRailStationTile(t->tile) && t->IsFrontEngine() && t->current_order.ShouldStopAtStation(t, GetStationIndex(t->tile)) && - t->cur_speed >= t->Train::GetCurrentMaxSpeed())) { - return; - } - } - - const Vehicle *u = v; - - do { - int effect_offset = GB(v->vcache.cached_vis_effect, VE_OFFSET_START, VE_OFFSET_COUNT) - VE_OFFSET_CENTRE; - byte effect_type = GB(v->vcache.cached_vis_effect, VE_TYPE_START, VE_TYPE_COUNT); - bool disable_effect = HasBit(v->vcache.cached_vis_effect, VE_DISABLE_EFFECT); - - /* Show no smoke when: - * - Smoke has been disabled for this vehicle - * - The vehicle is not visible - * - The vehicle is on a depot tile - * - The vehicle is on a tunnel tile - * - The vehicle is a train engine that is currently unpowered */ - if (disable_effect || - v->vehstatus & VS_HIDDEN || - IsDepotTile(v->tile) || - IsTunnelTile(v->tile) || - (v->type == VEH_TRAIN && - !HasPowerOnRail(Train::From(v)->railtype, GetTileRailType(v->tile)))) { - continue; - } - - if (effect_type == VE_TYPE_DEFAULT) { - if (v->type == VEH_TRAIN && Train::From(v)->IsEngine()) { - /* Use default effect type for engine class. */ - effect_type = RailVehInfo(v->engine_type)->engclass + 1; - } else { - /* No default effect exists, so continue */ - continue; - } - } - - int x = _vehicle_smoke_pos[v->direction] * effect_offset; - int y = _vehicle_smoke_pos[(v->direction + 2) % 8] * effect_offset; - - if (v->type == VEH_TRAIN && HasBit(Train::From(v)->flags, VRF_REVERSE_DIRECTION)) { - x = -x; - y = -y; - } - - switch (effect_type) { - case VE_TYPE_STEAM: - /* Steam smoke - amount is gradually falling until vehicle reaches its maximum speed, after that it's normal. - * Details: while vehicle's current speed is gradually increasing, steam plumes' density decreases by one third each - * third of its maximum speed spectrum. Steam emission finally normalises at very close to vehicle's maximum speed. - * REGULATION: - * - instead of 1, 4 / 2^smoke_amount (max. 2) is used to provide sufficient regulation to steam puffs' amount. */ - if (GB(v->tick_counter, 0, ((4 >> _settings_game.vehicle.smoke_amount) + ((u->cur_speed * 3) / u->vcache.cached_max_speed))) == 0) { - CreateEffectVehicleRel(v, x, y, 10, EV_STEAM_SMOKE); - sound = true; - } - break; - - case VE_TYPE_DIESEL: { - /* Diesel smoke - thicker when vehicle is starting, gradually subsiding till it reaches its maximum speed - * when smoke emission stops. - * Details: Vehicle's (max.) speed spectrum is divided into 32 parts. When max. speed is reached, chance for smoke - * emission erodes by 32 (1/4). For trains, power and weight come in handy too to either increase smoke emission in - * 6 steps (1000HP each) if the power is low or decrease smoke emission in 6 steps (512 tonnes each) if the train - * isn't overweight. Power and weight contributions are expressed in a way that neither extreme power, nor - * extreme weight can ruin the balance (e.g. FreightWagonMultiplier) in the formula. When the vehicle reaches - * maximum speed no diesel_smoke is emitted. - * REGULATION: - * - up to which speed a diesel vehicle is emitting smoke (with reduced/small setting only until 1/2 of max_speed), - * - in Chance16 - the last value is 512 / 2^smoke_amount (max. smoke when 128 = smoke_amount of 2). */ - int power_weight_effect = 0; - if (v->type == VEH_TRAIN) { - power_weight_effect = (32 >> (Train::From(u)->acc_cache.cached_power >> 10)) - (32 >> (Train::From(u)->acc_cache.cached_weight >> 9)); - } - if (u->cur_speed < (u->vcache.cached_max_speed >> (2 >> _settings_game.vehicle.smoke_amount)) && - Chance16((64 - ((u->cur_speed << 5) / u->vcache.cached_max_speed) + power_weight_effect), (512 >> _settings_game.vehicle.smoke_amount))) { - CreateEffectVehicleRel(v, x, y, 10, EV_DIESEL_SMOKE); - sound = true; - } - break; - } - - case VE_TYPE_ELECTRIC: - /* Electric train's spark - more often occurs when train is departing (more load) - * Details: Electric locomotives are usually at least twice as powerful as their diesel counterparts, so spark - * emissions are kept simple. Only when starting, creating huge force are sparks more likely to happen, but when - * reaching its max. speed, quarter by quarter of it, chance decreases untill the usuall 2,22% at train's top speed. - * REGULATION: - * - in Chance16 the last value is 360 / 2^smoke_amount (max. sparks when 90 = smoke_amount of 2). */ - if (GB(v->tick_counter, 0, 2) == 0 && - Chance16((6 - ((u->cur_speed << 2) / u->vcache.cached_max_speed)), (360 >> _settings_game.vehicle.smoke_amount))) { - CreateEffectVehicleRel(v, x, y, 10, EV_ELECTRIC_SPARK); - sound = true; - } - break; - - default: - break; - } - } while ((v = v->Next()) != NULL); - - if (sound) PlayVehicleSound(u, VSE_VISUAL_EFFECT); -} - void Train::PlayLeaveStationSound() const { static const SoundFx sfx[] = { @@ -3722,7 +3591,7 @@ static bool TrainLocoHandler(Train *v, bool mode) if (CheckTrainStayInDepot(v)) return true; - if (!mode) HandleLocomotiveSmokeCloud(v); + if (!mode) v->ShowVisualEffect(); /* We had no order but have an order now, do look ahead. */ if (!valid_order && !v->current_order.IsType(OT_NOTHING)) { diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 75ef370f5..e7dc7c2d0 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -50,6 +50,8 @@ #include "effectvehicle_func.h" #include "effectvehicle_base.h" #include "vehiclelist.h" +#include "tunnel_map.h" +#include "depot_map.h" #include "table/strings.h" @@ -1895,6 +1897,136 @@ void Vehicle::UpdateVisualEffect(bool allow_power_change) } } +static const int8 _vehicle_smoke_pos[8] = { + 1, 1, 1, 0, -1, -1, -1, 0 +}; + +void Vehicle::ShowVisualEffect() const +{ + assert(this->IsPrimaryVehicle()); + bool sound = false; + + /* Do not show any smoke when: + * - vehicle smoke is disabled by the player + * - the vehicle is slowing down or stopped (by the player) + * - the vehicle is moving very slowly + */ + if (_settings_game.vehicle.smoke_amount == 0 || + this->vehstatus & (VS_TRAIN_SLOWING | VS_STOPPED) || + this->cur_speed < 2) { + return; + } + if (this->type == VEH_TRAIN) { + const Train *t = Train::From(this); + /* For trains, do not show any smoke when: + * - the train is reversing + * - is entering a station with an order to stop there and its speed is equal to maximum station entering speed + */ + if (HasBit(t->flags, VRF_REVERSING) || + (IsRailStationTile(t->tile) && t->IsFrontEngine() && t->current_order.ShouldStopAtStation(t, GetStationIndex(t->tile)) && + t->cur_speed >= t->Train::GetCurrentMaxSpeed())) { + return; + } + } + + const Vehicle *v = this; + + do { + int effect_offset = GB(v->vcache.cached_vis_effect, VE_OFFSET_START, VE_OFFSET_COUNT) - VE_OFFSET_CENTRE; + byte effect_type = GB(v->vcache.cached_vis_effect, VE_TYPE_START, VE_TYPE_COUNT); + bool disable_effect = HasBit(v->vcache.cached_vis_effect, VE_DISABLE_EFFECT); + + /* Show no smoke when: + * - Smoke has been disabled for this vehicle + * - The vehicle is not visible + * - The vehicle is on a depot tile + * - The vehicle is on a tunnel tile + * - The vehicle is a train engine that is currently unpowered */ + if (disable_effect || + v->vehstatus & VS_HIDDEN || + IsDepotTile(v->tile) || + IsTunnelTile(v->tile) || + (v->type == VEH_TRAIN && + !HasPowerOnRail(Train::From(v)->railtype, GetTileRailType(v->tile)))) { + continue; + } + + if (effect_type == VE_TYPE_DEFAULT) { + if (v->type == VEH_TRAIN && Train::From(v)->IsEngine()) { + /* Use default effect type for engine class. */ + effect_type = RailVehInfo(v->engine_type)->engclass + 1; + } else { + /* No default effect exists, so continue */ + continue; + } + } + + int x = _vehicle_smoke_pos[v->direction] * effect_offset; + int y = _vehicle_smoke_pos[(v->direction + 2) % 8] * effect_offset; + + if (v->type == VEH_TRAIN && HasBit(Train::From(v)->flags, VRF_REVERSE_DIRECTION)) { + x = -x; + y = -y; + } + + switch (effect_type) { + case VE_TYPE_STEAM: + /* Steam smoke - amount is gradually falling until vehicle reaches its maximum speed, after that it's normal. + * Details: while vehicle's current speed is gradually increasing, steam plumes' density decreases by one third each + * third of its maximum speed spectrum. Steam emission finally normalises at very close to vehicle's maximum speed. + * REGULATION: + * - instead of 1, 4 / 2^smoke_amount (max. 2) is used to provide sufficient regulation to steam puffs' amount. */ + if (GB(v->tick_counter, 0, ((4 >> _settings_game.vehicle.smoke_amount) + ((this->cur_speed * 3) / this->vcache.cached_max_speed))) == 0) { + CreateEffectVehicleRel(v, x, y, 10, EV_STEAM_SMOKE); + sound = true; + } + break; + + case VE_TYPE_DIESEL: { + /* Diesel smoke - thicker when vehicle is starting, gradually subsiding till it reaches its maximum speed + * when smoke emission stops. + * Details: Vehicle's (max.) speed spectrum is divided into 32 parts. When max. speed is reached, chance for smoke + * emission erodes by 32 (1/4). For trains, power and weight come in handy too to either increase smoke emission in + * 6 steps (1000HP each) if the power is low or decrease smoke emission in 6 steps (512 tonnes each) if the train + * isn't overweight. Power and weight contributions are expressed in a way that neither extreme power, nor + * extreme weight can ruin the balance (e.g. FreightWagonMultiplier) in the formula. When the vehicle reaches + * maximum speed no diesel_smoke is emitted. + * REGULATION: + * - up to which speed a diesel vehicle is emitting smoke (with reduced/small setting only until 1/2 of max_speed), + * - in Chance16 - the last value is 512 / 2^smoke_amount (max. smoke when 128 = smoke_amount of 2). */ + int power_weight_effect = 0; + if (v->type == VEH_TRAIN) { + power_weight_effect = (32 >> (Train::From(this)->acc_cache.cached_power >> 10)) - (32 >> (Train::From(this)->acc_cache.cached_weight >> 9)); + } + if (this->cur_speed < (this->vcache.cached_max_speed >> (2 >> _settings_game.vehicle.smoke_amount)) && + Chance16((64 - ((this->cur_speed << 5) / this->vcache.cached_max_speed) + power_weight_effect), (512 >> _settings_game.vehicle.smoke_amount))) { + CreateEffectVehicleRel(v, x, y, 10, EV_DIESEL_SMOKE); + sound = true; + } + break; + } + + case VE_TYPE_ELECTRIC: + /* Electric train's spark - more often occurs when train is departing (more load) + * Details: Electric locomotives are usually at least twice as powerful as their diesel counterparts, so spark + * emissions are kept simple. Only when starting, creating huge force are sparks more likely to happen, but when + * reaching its max. speed, quarter by quarter of it, chance decreases untill the usuall 2,22% at train's top speed. + * REGULATION: + * - in Chance16 the last value is 360 / 2^smoke_amount (max. sparks when 90 = smoke_amount of 2). */ + if (GB(v->tick_counter, 0, 2) == 0 && + Chance16((6 - ((this->cur_speed << 2) / this->vcache.cached_max_speed)), (360 >> _settings_game.vehicle.smoke_amount))) { + CreateEffectVehicleRel(v, x, y, 10, EV_ELECTRIC_SPARK); + sound = true; + } + break; + + default: + break; + } + } while ((v = v->Next()) != NULL); + + if (sound) PlayVehicleSound(this, VSE_VISUAL_EFFECT); +} void Vehicle::SetNext(Vehicle *next) { diff --git a/src/vehicle_base.h b/src/vehicle_base.h index 7db794c1e..070413ab9 100644 --- a/src/vehicle_base.h +++ b/src/vehicle_base.h @@ -618,6 +618,12 @@ public: */ void UpdateVisualEffect(bool allow_power_change = true); + /* + * Draw visual effects (smoke and/or sparks) for a vehicle chain. + * @pre this->IsPrimaryVehicle() + */ + void ShowVisualEffect() const; + /** * Increments cur_order_index, keeps care of the wrap-around and invalidates the GUI. * Note: current_order is not invalidated. |