* Draw visual effects (smoke and/or sparks) for a vehicle chain. * @pre this->IsPrimaryVehicle() */
| 2775 | * @pre this->IsPrimaryVehicle() |
| 2776 | */ |
| 2777 | void Vehicle::ShowVisualEffect() const |
| 2778 | { |
| 2779 | assert(this->IsPrimaryVehicle()); |
| 2780 | bool sound = false; |
| 2781 | |
| 2782 | /* Do not show any smoke when: |
| 2783 | * - vehicle smoke is disabled by the player |
| 2784 | * - the vehicle is slowing down or stopped (by the player) |
| 2785 | * - the vehicle is moving very slowly |
| 2786 | */ |
| 2787 | if (_settings_game.vehicle.smoke_amount == 0 || |
| 2788 | this->vehstatus.Any({VehState::TrainSlowing, VehState::Stopped}) || |
| 2789 | this->cur_speed < 2) { |
| 2790 | return; |
| 2791 | } |
| 2792 | |
| 2793 | /* Use the speed as limited by underground and orders. */ |
| 2794 | uint max_speed = this->GetCurrentMaxSpeed(); |
| 2795 | |
| 2796 | if (this->type == VEH_TRAIN) { |
| 2797 | const Train *t = Train::From(this); |
| 2798 | /* For trains, do not show any smoke when: |
| 2799 | * - the train is reversing |
| 2800 | * - is entering a station with an order to stop there and its speed is equal to maximum station entering speed |
| 2801 | */ |
| 2802 | if (t->flags.Test(VehicleRailFlag::Reversing) || |
| 2803 | (IsRailStationTile(t->tile) && t->IsFrontEngine() && t->current_order.ShouldStopAtStation(t, GetStationIndex(t->tile)) && |
| 2804 | t->cur_speed >= max_speed)) { |
| 2805 | return; |
| 2806 | } |
| 2807 | } |
| 2808 | |
| 2809 | const Vehicle *v = this; |
| 2810 | |
| 2811 | do { |
| 2812 | bool advanced = HasBit(v->vcache.cached_vis_effect, VE_ADVANCED_EFFECT); |
| 2813 | int effect_offset = GB(v->vcache.cached_vis_effect, VE_OFFSET_START, VE_OFFSET_COUNT) - VE_OFFSET_CENTRE; |
| 2814 | VisualEffectSpawnModel effect_model = VESM_NONE; |
| 2815 | if (advanced) { |
| 2816 | effect_offset = VE_OFFSET_CENTRE; |
| 2817 | effect_model = (VisualEffectSpawnModel)GB(v->vcache.cached_vis_effect, 0, VE_ADVANCED_EFFECT); |
| 2818 | if (effect_model >= VESM_END) effect_model = VESM_NONE; // unknown spawning model |
| 2819 | } else { |
| 2820 | effect_model = (VisualEffectSpawnModel)GB(v->vcache.cached_vis_effect, VE_TYPE_START, VE_TYPE_COUNT); |
| 2821 | assert(effect_model != (VisualEffectSpawnModel)VE_TYPE_DEFAULT); // should have been resolved by UpdateVisualEffect |
| 2822 | static_assert((uint)VESM_STEAM == (uint)VE_TYPE_STEAM); |
| 2823 | static_assert((uint)VESM_DIESEL == (uint)VE_TYPE_DIESEL); |
| 2824 | static_assert((uint)VESM_ELECTRIC == (uint)VE_TYPE_ELECTRIC); |
| 2825 | } |
| 2826 | |
| 2827 | /* Show no smoke when: |
| 2828 | * - Smoke has been disabled for this vehicle |
| 2829 | * - The vehicle is not visible |
| 2830 | * - The vehicle is under a bridge |
| 2831 | * - The vehicle is on a depot tile |
| 2832 | * - The vehicle is on a tunnel tile |
| 2833 | * - The vehicle is a train engine that is currently unpowered */ |
| 2834 | if (effect_model == VESM_NONE || |
no test coverage detected