Files
@ r28630:fe3c5717ad2b
Branch filter:
Location: cpp/openttd-patchpack/source/src/script/api/script_controller.hpp
r28630:fe3c5717ad2b
8.6 KiB
text/x-c++hdr
Fix: [Script] Apply random deviation only at script start (#11944)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 | /*
* This file is part of OpenTTD.
* 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.
* 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.
* 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 <http://www.gnu.org/licenses/>.
*/
/** @file script_controller.hpp The controller of the script. */
#ifndef SCRIPT_CONTROLLER_HPP
#define SCRIPT_CONTROLLER_HPP
#include "script_types.hpp"
/**
* The Controller, the class each Script should extend. It creates the Script,
* makes sure the logic kicks in correctly, and that #GetTick() has a valid
* value.
*
* When starting a new game, or when loading a game, OpenTTD tries to match a
* script that matches to the specified version as close as possible. It tries
* (from first to last, stopping as soon as the attempt succeeds)
*
* - load the latest version of the same script that supports loading data from
* the saved version (the version of saved data must be equal or greater
* than ScriptInfo::MinVersionToLoad),
* - load the latest version of the same script (ignoring version requirements),
* - (for AIs) load a random AI, and finally
* - (for AIs) load the dummy AI.
*
* After determining the script to use, starting it is done as follows
*
* - An instance is constructed of the class derived from ScriptController
* (class name is retrieved from ScriptInfo::CreateInstance).
* - If there is script data available in the loaded game and if the data is
* loadable according to ScriptInfo::MinVersionToLoad, #Load is called with the
* data from the loaded game.
* - Finally, #Start is called to start execution of the script.
*
* See also https://wiki.openttd.org/en/Development/Script/Save%20and%20Load for more details.
*
* @api ai game
*/
class ScriptController {
friend class AIScanner;
friend class ScriptInstance;
public:
#ifndef DOXYGEN_API
/**
* Initializer of the ScriptController.
* @param company The company this Script is normally serving.
*/
ScriptController(CompanyID company);
#else
/**
* This function is called to start your script. Your script starts here. If you
* return from this function, your script dies, so make sure that doesn't
* happen.
* @note Cannot be called from within your script.
*/
void Start();
/**
* Save the state of the script.
*
* By implementing this function, you can store some data inside the savegame.
* The function should return a table with the information you want to store.
* You can only store:
*
* - integers,
* - strings,
* - arrays (max. 25 levels deep),
* - tables (max. 25 levels deep),
* - booleans, and
* - nulls.
*
* In particular, instances of classes can't be saved including
* ScriptList. Such a list should be converted to an array or table on
* save and converted back on load.
*
* The function is called as soon as the user saves the game,
* independently of other activities of the script. The script is not
* notified of the call. To avoid race-conditions between #Save and the
* other script code, change variables directly after a #Sleep, it is
* very unlikely, to get interrupted at that point in the execution.
* See also https://wiki.openttd.org/en/Development/Script/Save%20and%20Load for more details.
*
* @note No other information is saved than the table returned by #Save.
* For example all pending events are lost as soon as the game is loaded.
*
* @return Data of the script that should be stored in the save game.
*/
SquirrelTable Save();
/**
* Load saved data just before calling #Start.
* The function is only called when there is data to load.
* @param version Version number of the script that created the \a data.
* @param data Data that was saved (return value of #Save).
*/
void Load(int version, SquirrelTable data);
#endif /* DOXYGEN_API */
/**
* Find at which tick your script currently is.
* @return returns the current tick.
*/
static uint GetTick();
/**
* Get the number of operations the script may still execute this tick.
* @return The amount of operations left to execute.
* @note This number can go negative when certain uninteruptable
* operations are executed. The amount of operations that you go
* over the limit will be deducted from the next tick you would
* be allowed to run.
*/
static int GetOpsTillSuspend();
/**
* Get the value of one of your settings you set via info.nut.
* @param name The name of the setting.
* @return the value for the setting, or -1 if the setting is not known.
*/
static int GetSetting(const std::string &name);
/**
* Get the OpenTTD version of this executable. The version is formatted
* with the bits having the following meaning:
* 24-31 major version + 16.
* 20-23 minor version.
* 19 1 if it is a release, 0 if it is not.
* 0-18 revision number; 0 when the revision is unknown.
* You have to subtract 16 from the major version to get the correct
* value.
*
* Prior to OpenTTD 12, the bits have the following meaning:
* 28-31 major version.
* 24-27 minor version.
* 20-23 build.
* 19 1 if it is a release, 0 if it is not.
* 0-18 revision number; 0 when the revision is unknown.
*
* @return The version in newgrf format.
*/
static uint GetVersion();
/**
* Change the minimum amount of time the script should be put in suspend mode
* when you execute a command. Normally in SP this is 1, and in MP it is
* what ever delay the server has been programmed to delay commands
* (normally between 1 and 5). To give a more 'real' effect to your script,
* you can control that number here.
* @param ticks The minimum amount of ticks to wait.
* @pre Ticks should be positive. Too big values will influence performance of the script.
* @note If the number is lower than the MP setting, the MP setting wins.
*/
static void SetCommandDelay(int ticks);
/**
* Sleep for X ticks. The code continues after this line when the X script ticks
* are passed. Mind that an script tick is different from in-game ticks and
* differ per script speed.
* @param ticks the ticks to wait
* @pre ticks > 0.
* @post the value of GetTick() will be changed exactly 'ticks' in value after
* calling this.
*/
static void Sleep(int ticks);
/**
* Break execution of the script when script developer tools are active. For
* other users, nothing will happen when you call this function. To resume
* the script, you have to click on the continue button in the AI debug
* window. It is not recommended to leave calls to this function in scripts
* that you publish or upload to bananas.
* @param message to print in the AI debug window when the break occurs.
* @note gui.ai_developer_tools setting must be enabled or the break is
* ignored.
*/
static void Break(const std::string &message);
/**
* When Squirrel triggers a print, this function is called.
* Squirrel calls this when 'print' is used, or when the script made an error.
* @param error_msg If true, it is a Squirrel error message.
* @param message The message Squirrel logged.
* @note Use ScriptLog.Info/Warning/Error instead of 'print'.
*/
static void Print(bool error_msg, const std::string &message);
/**
* Import a library.
* @param library The name of the library to import. The name should be composed as ScriptInfo::GetCategory() + "." +
* ScriptInfo::CreateInstance().
* @param class_name Under which name you want it to be available (or "" if you just want the returning object).
* @param version Which version you want specifically.
* @return The loaded library object. If class_name is set, it is also available (under the scope of the import) under that name.
* @note This command can be called from the global space, and does not need an instance.
*/
static HSQOBJECT Import(const std::string &library, const std::string &class_name, int version);
private:
typedef std::map<std::string, std::string, CaseInsensitiveComparator> LoadedLibraryList; ///< The type for loaded libraries.
uint ticks; ///< The amount of ticks we're sleeping.
LoadedLibraryList loaded_library; ///< The libraries we loaded.
int loaded_library_count; ///< The amount of libraries.
/**
* Register all classes that are known inside the script API.
*/
void RegisterClasses();
};
#endif /* SCRIPT_CONTROLLER_HPP */
|