OpenTTD Source 20260815-master-gdf55704e7d
screensaver.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
10#include "screensaver.h"
11
12#include "stdafx.h"
13
14#include "core/random_func.hpp"
15#include "company_base.h"
16#include "timer/timer.h"
18#include "vehicle_base.h"
19#include "vehicle_func.h"
20#include "vehicle_type.h"
21#include "window_func.h"
22#include "window_gui.h"
23
24#include "safeguards.h"
25
34{
35 /* First pass, add up vehicles of all buildable types for all companies. */
36 uint n = 0;
37 for (const Company *c : Company::Iterate()) {
39 n += c->group_all[v].num_vehicle;
40 }
41 }
42
43 /* If we have no vehicles, we can't pick a vehicle so exit. */
44 if (n == 0) return nullptr;
45
46 /* Otherwise, pick a random vehicle index between 0 and n. */
47 n = InteractiveRandomRange(n);
48
49 /* Loop over all the vehicles until we get to that vehicle. */
50 for (const Vehicle *v : Vehicle::Iterate()) {
51 /* Skip count anything companies can't build. */
52 if (!IsCompanyBuildableVehicleType(v)) continue;
53
54 /* Skip vehicles if they're not "front vehicles" so we don't count train cars (or similar) as targets to follow. */
55 if (!v->IsPrimaryVehicle()) continue;
56
57 /* Otherwise, it is a vehicle we should count, so count down until zero. */
58 if (n-- == 0) return v;
59 }
60
61 /* In case we go over all the vehicles, return \c nullptr in that case. */
62 return nullptr;
63}
64
76static void SwitchVehicle(bool exit_on_invalid = true)
77{
78 /* Do not do anything in the main menu. */
79 if (_game_mode == GameMode::Menu) return;
80
81 const Window *main_win = GetMainWindow();
82
83 /* We start with a high chance of keeping with a moving vehicle. */
84 static int movement_bias = 48;
85
86 /* If we are targeting an invalid vehicle, stop running */
87 if (exit_on_invalid && main_win->viewport->follow_vehicle == VehicleID::Invalid()) {
89 return;
90 }
91
92 /* If we're targeting a vehicle, we have a chance to return early and not pick a new one. */
93 auto v = Vehicle::GetIfValid(main_win->viewport->follow_vehicle);
94 if (v != nullptr) {
95
96 /* Every time we stick on a moving vehicle, we make it less likely that
97 * we stick around next cycle to prevent staying on one vehicle for forever. */
98 if (v->cur_speed > 0 && !Chance16I(1, movement_bias, InteractiveRandom())) {
99 movement_bias -= 1;
100 return;
101 }
102
103 /* If we're not moving, we have a flat 25% chance to stay until the call
104 * to encourage switching to a moving vehicle. */
105 if (v->cur_speed == 0 && Chance16I(3, 4, InteractiveRandom())) {
106 return;
107 }
108 }
109
110 /* Reset our bias so that the next vehicle gets its full time. */
111 movement_bias = 48;
112
113 /* Try to get a vehicle (this fails if the vehicle picked isn't valid to follow). */
114 const Vehicle *new_vehicle = PickRandomVehicle();
115 /* If we didn't find vehicle to follow, try again next cycle. */
116 if (new_vehicle == nullptr) return;
117
118 /* Swap the main window over to following the new vehicle. */
119 main_win->viewport->CancelFollow(*main_win);
120 main_win->viewport->follow_vehicle = new_vehicle->index;
121}
122
123
124/* The screensaver is based off a timer on a fixed interval which rotates between vehicles. */
125
132
139static std::unique_ptr<IntervalTimer<TimerGameTick>> _switch_timer;
140
151{
152 const Window *main_win = GetMainWindow();
153
154 _switch_timer.reset();
155 main_win->viewport->CancelFollow(*main_win);
156}
157
173{
174 /* If we are in screensaver mode, exit it. */
175 if (_switch_timer != nullptr) {
177 return;
178 }
179
180 /* If we aren't, start it with a new timer. */
181 _switch_timer = std::make_unique<IntervalTimer<TimerGameTick>>(
183 [](uint) { SwitchVehicle(); }
184 );
185
186 /* Fire our callback once to start us following a first vehicle; otherwise we'd have to wait for the first time the timer fired.
187 * We pass false here to ignore if there is no followed vehicle */
188 SwitchVehicle(false);
189}
@ None
These timers can be executed in any order; the order is not relevant.
Definition of stuff that is very close to a company, like the company struct itself.
@ Menu
In the main menu.
Definition openttd.h:19
Pseudo random number generator.
bool Chance16I(const uint32_t a, const uint32_t b, const uint32_t r)
Checks if a given randomize-number is below a given probability.
A number of safeguards to prevent using unsafe methods.
static const auto _screensaver_check_interval
We use a fixed period for updating the screensaver's followed vehicle, stored in this variable.
static const Vehicle * PickRandomVehicle()
Selects a random vehicle of any type.
static void SwitchVehicle(bool exit_on_invalid=true)
Switches the current followed vehicle to a new random one.
void ToggleScreensaverMode()
Enters or exits "Screensaver Mode".
void ExitScreensaverMode()
Exits "Screensaver Mode".
static std::unique_ptr< IntervalTimer< TimerGameTick > > _switch_timer
The screensaver runs on an interval timer, stored in this pointer when it is running and freed when i...
Exports a function to turn on and off a screensaver mode.
Definition of base types and functions in a cross-platform compatible way.
static Pool::IterateWrapper< Company > Iterate(size_t from=0)
static Vehicle * GetIfValid(auto index)
Vehicle data structure.
Data structure for an opened window.
Definition window_gui.h:273
std::unique_ptr< ViewportData > viewport
Pointer to viewport data, if present.
Definition window_gui.h:318
Definition of Interval and OneShot timers.
Definition of the tick-based game-timer.
Base class for all vehicles.
Functions related to vehicles.
bool IsCompanyBuildableVehicleType(VehicleType type)
Is the given vehicle type buildable by a company?
Types related to vehicles.
VehicleType
Available vehicle types.
@ Begin
Begin marker.
@ CompanyEnd
Last company-ownable type.
Window * GetMainWindow()
Get the main window, i.e.
Definition window.cpp:1190
Window functions not directly related to making/drawing windows.
Functions, definitions and such used only by the GUI.