1 #ifndef scenario_h 2 #define scenario_h 3 4 /** @file scenario.h declarations for scenario interface */ 5 6 #include "koord3d.h" 7 #include "../utils/plainstring.h" 8 #include "../script/dynamic_string.h" 9 #include "../dataobj/ribi.h" 10 #include "../convoihandle_t.h" 11 12 class loadsave_t; 13 class stadt_t; 14 class fabrik_t; 15 class karte_t; 16 class schedule_t; 17 class depot_t; 18 19 /** 20 * @class scenario_t 21 * Controls scenarios in connection to a simutrans world. 22 * 23 * Scenarios are scripted. In network games, only the server has access to the script, 24 * clients will be sent some results of the script. 25 * 26 * Each instance of karte_t carries a non-NULL pointer to a scenario_t 27 * thus also the need for inactive scenarios. 28 */ 29 class scenario_t 30 { 31 private: 32 /// possible states of scenario 33 enum scenario_state_t { 34 INACTIVE = 0, ///< scenario inactive 35 SCRIPTED = 7, ///< scenario active (non-network game or at server) 36 SCRIPTED_NETWORK = 8 ///< scenario active, network game at client 37 }; 38 39 /// state of the current scenario @see scenario_state_t 40 uint16 what_scenario; 41 42 /// the world we are scripting in 43 karte_t *welt; 44 45 /// name of scenario, files are searched in scenario_path/scenario_name/... 46 /// e.g. my_scenario 47 plainstring scenario_name; 48 49 /// path to scenario directory (relative to env_t::user_dir) 50 /// e.g. pak/scenario/my_scenario/ 51 plainstring scenario_path; 52 53 54 /** 55 * loads scenario file with the given name 56 * @param filename name scenario script file (including .nut extension) 57 */ 58 bool load_script(const char* filename); 59 60 /** 61 * loads necessary compatibility scripts 62 */ 63 void load_compatibility_script(); 64 65 /// is set, if an error occurred during loading of savegame 66 /// e.g. re-starting of scenario failed due to script error 67 bool rdwr_error; 68 69 70 /// pointer to virtual machine 71 script_vm_t *script; 72 73 /// @{ 74 /// @name Interface to forbid tools in-game 75 /** 76 * Struct to store information about forbidden tools 77 * 78 * Necessary in network games: there, the list of forbidden tools 79 * is transferred to clients. Needed to apply conditions to e.g. way-building 80 * tools or to have toolbars reflect allowed tools. 81 */ 82 struct forbidden_t { 83 enum forbid_type { forbid_tool = 1, forbid_tool_rect = 2}; 84 forbid_type type; 85 uint8 player_nr; 86 /// id of tool to be forbidden, as set by constructors of classes derived from 87 /// tool_t, @see simtool.h 88 uint16 toolnr; 89 /// waytype of tool, @see waytype_t 90 sint16 waytype; 91 koord pos_nw, pos_se; 92 sint8 hmin, hmax; 93 /// error message to be displayed if user tries to work with the tool 94 plainstring error; 95 96 /// constructor: forbid tool/etc for a certain player 97 forbidden_t(forbid_type type_=forbid_tool, uint8 player_nr_=255, uint16 toolnr_=0, sint16 waytype_=invalid_wt) : typeforbidden_t98 type(type_), player_nr(player_nr_), toolnr(toolnr_), waytype(waytype_), 99 pos_nw(koord::invalid), pos_se(koord::invalid), hmin(-128), hmax(127), error() {}; 100 101 /// constructor: forbid tool for a certain player at certain locations (and heights) 102 forbidden_t(uint8 player_nr_, uint16 toolnr_, sint16 waytype_, koord nw, koord se, sint8 hmin_=-128, sint8 hmax_=127) : typeforbidden_t103 type(forbid_tool_rect), player_nr(player_nr_), toolnr(toolnr_), waytype(waytype_), 104 pos_nw(nw), pos_se(se), hmin(hmin_), hmax(hmax_), error() {}; 105 106 // copy constructor 107 forbidden_t(const forbidden_t&); 108 109 /** 110 * @returns if this < other, compares: type, playernr, tool, wt 111 * DIRTY: (a <= b) && (b <= a) DOES NOT imply a == b 112 */ 113 bool operator <(const forbidden_t &) const; 114 115 bool operator <=(const forbidden_t &other) const { return !(other < *this); } 116 compareforbidden_t117 static bool compare(const forbidden_t *a, const forbidden_t *b) 118 { 119 return *a < *b; 120 } 121 122 /** 123 * compares everything (including coordinates) 124 * DIRTY: (a <= b) && (b <= a) DOES NOT imply a == b 125 */ 126 bool operator ==(const forbidden_t &other) const; 127 128 /** 129 * templated load/save support 130 */ rdwrforbidden_t131 template<class T> void rdwr(T *file) 132 { 133 uint8 t = (uint8)type; 134 file->rdwr_byte(t); 135 type= (forbid_type)t; 136 file->rdwr_byte(player_nr); 137 file->rdwr_short(toolnr); 138 file->rdwr_short(waytype); 139 file->rdwr_short(pos_nw.x); file->rdwr_short(pos_nw.y); 140 file->rdwr_short(pos_se.x); file->rdwr_short(pos_se.y); 141 file->rdwr_byte(hmin); 142 file->rdwr_byte(hmax); 143 file->rdwr_str(error); 144 } 145 146 void rotate90(const sint16 y_size); 147 148 private: 149 const forbidden_t& operator=(const forbidden_t&); 150 }; 151 152 /// list of forbidden tools 153 vector_tpl<forbidden_t*>forbidden_tools; 154 155 /// set to true if rules changed to update toolbars, 156 /// toolbars will be updated in next call to step() 157 bool need_toolbar_update; 158 159 /** 160 * helper function: 161 * @param other given record 162 * @returns first index i such that 163 * forbidden_tools[i-1] < other <= forbidden_tools[i] <= other 164 * or returns forbidden_tools.get_count() if no such index is found 165 */ 166 uint32 find_first(const forbidden_t &other) const; 167 168 /** 169 * Helper function: 170 * Puts/removes new record into/from forbidden_tools list, checks for identical entries. 171 * Only call this method from call_forbid_tool(forbidden_t *,bool) 172 * @param test must be pointer to allocated memory, will be invalid after call 173 * @param forbid if true puts, if false removes into/from list 174 */ 175 void intern_forbid(forbidden_t *test, bool forbid); 176 177 /** 178 * Helper function: works on forbidden_tools directly (if not in network-mode) 179 * or sends information over network (if at server) 180 * @param test must be pointer to allocated memory, will be invalid after call 181 * @param forbid if true forbids, if false allows the record 182 */ 183 void call_forbid_tool(forbidden_t *test, bool forbid); 184 /// @} 185 186 /// bit set if player has won / lost 187 uint16 won; 188 uint16 lost; 189 190 /// function to update the won / lost bitset 191 /// called if this information changes for some players 192 void update_won_lost(uint16 new_won, uint16 new_lost); 193 194 public: 195 196 scenario_t(karte_t *w); 197 ~scenario_t(); 198 199 /** 200 * Initializes scripted scenario 201 */ 202 const char* init( const char *scenario_base, const char *scenario_name, karte_t *welt ); 203 204 /** 205 * Load file with translations. Tries to load files in the following order 206 * (1) script_addon_path/iso/filename 207 * (2) script_addon_path/en/filename 208 * (3) script_path/iso/filename 209 * 210 * Here, iso refers to iso-abbreviation of currently active language 211 * @return content of loaded file 212 */ 213 plainstring load_language_file(const char* filename); 214 215 /// Load/save support 216 void rdwr(loadsave_t *file); 217 218 /// @returns true if loading succeed, false if script failed during loading rdwr_ok()219 bool rdwr_ok() const { return !rdwr_error; } 220 221 /** 222 * Stop scenario 223 */ stop()224 void stop() { what_scenario = INACTIVE; } 225 226 /// @return true if a scenario is present active()227 bool active() const { return what_scenario != INACTIVE; } 228 229 /// @return true if scenario is scripted is_scripted()230 bool is_scripted() const { return what_scenario == SCRIPTED || what_scenario == SCRIPTED_NETWORK; } 231 232 /** 233 * compiles and executes given string 234 * @returns error msg (or NULL if succeeded) 235 */ 236 const char* eval_string(const char* squirrel_string) const; 237 238 /** 239 * Get percentage of scenario completion. Does not call script to update this value. 240 * On clients: call server for update via dynamic_string logic. 241 * Returns percentage of scenario completion. 242 * @param player_nr player 243 * @returns percentage of scenario completion: 244 * if >= 100 then scenario is won 245 * if < 0 then scenario is lost 246 */ 247 sint32 get_completion(int player_nr); 248 249 /** 250 * Sets percentage of scenario completion. Used as callback if script call got suspended. 251 * @param player_nr player 252 * @returns dummy return value 253 */ 254 bool set_completion(sint32 player_nr, sint32 percentage); 255 256 void rotate90(const sint16 y_size); 257 258 /** 259 * rotate original coordinates to actual world coordinates 260 * uses the methods in script_api 261 */ 262 void koord_sq2w(koord &) const; 263 264 /** 265 * Text to be displayed in the finance info window 266 * i.e. short description of scenario 267 */ 268 dynamic_string description_text; 269 270 /// @{ 271 /// @name Text to be displayed in the scenario info window 272 dynamic_string info_text; 273 dynamic_string goal_text; 274 dynamic_string rule_text; 275 dynamic_string result_text; 276 dynamic_string about_text; 277 dynamic_string debug_text; 278 /// @} 279 280 /** 281 * Called to update the scenario texts 282 * @see dynamic_string::update 283 */ 284 void update_scenario_texts(); 285 286 /** 287 * opens scenario info window at tab @p tab. 288 */ 289 bool open_info_win(const char* tab = "result") const; 290 291 292 /** 293 * Last error of script 294 */ 295 const char* get_error_text(); 296 297 298 /** 299 * Calls scripted is_scenario_completed. Caches this value in statistics of player_t. 300 * Server sends update of won/lost if necessary. 301 */ 302 void step(); 303 304 /** 305 * Called upon month change: at 0:00 of the first day of the new month. 306 */ 307 void new_month(); 308 309 /** 310 * Called upon new year: at 0:00 January 1st. 311 */ 312 void new_year(); 313 314 /// @{ 315 /// @name Interface to forbid tools in-game 316 /** 317 * Forbid tool 318 * @ingroup squirrel-api 319 * 320 * @param player_nr number of player this rule applies to, 321 * if this is set to MAX_PLAYER_COUNT then this acts for all players except public player 322 * @param tool_id id of tool 323 */ 324 void forbid_tool(uint8 player_nr, uint16 tool_id); 325 326 /** 327 * @ingroup squirrel-api 328 * @see forbid_tool 329 */ 330 void allow_tool(uint8 player_nr, uint16 tool_id); 331 332 /** 333 * Forbid tool with certain waytype 334 * @ingroup squirrel-api 335 * 336 * @param player_nr number of player this rule applies to, 337 * if this is set to MAX_PLAYER_COUNT then this acts for all players except public player 338 * @param tool_id id of tool 339 * @param wt waytype 340 */ 341 void forbid_way_tool(uint8 player_nr, uint16 tool_id, waytype_t wt); 342 343 /** 344 * @ingroup squirrel-api 345 * @see forbid_way_tool 346 */ 347 void allow_way_tool(uint8 player_nr, uint16 tool_id, waytype_t wt); 348 349 /** 350 * Forbid tool with certain waytype within rectangular region on the map 351 * @ingroup squirrel-api 352 * 353 * @param player_nr number of player this rule applies to, 354 * if this is set to MAX_PLAYER_COUNT then this acts for all players except public player 355 * @param tool_id id of tool 356 * @param wt waytype 357 * @param pos_nw coordinate of north-western corner of rectangle 358 * @param pos_se coordinate of south-eastern corner of rectangle 359 * @param err error message presented to user when trying to apply this tool 360 */ 361 void forbid_way_tool_rect(uint8 player_nr, uint16 tool_id, waytype_t wt, koord pos_nw, koord pos_se, plainstring err); 362 363 /** 364 * @ingroup squirrel-api 365 * @see forbid_way_tool_rect 366 */ 367 void allow_way_tool_rect(uint8 player_nr, uint16 tool_id, waytype_t wt, koord pos_nw, koord pos_se); 368 369 /** 370 * Forbid tool with certain waytype within cubic region on the map. 371 * @ingroup squirrel-api 372 * 373 * @param player_nr number of player this rule applies to, 374 * if this is set to MAX_PLAYER_COUNT then this acts for all players except public player 375 * @param tool_id id of tool 376 * @param wt waytype 377 * @param pos_nw coordinate of north-western corner of cube 378 * @param pos_se coordinate of south-eastern corner of cube 379 * @param err error message presented to user when trying to apply this tool 380 */ 381 void forbid_way_tool_cube(uint8 player_nr, uint16 tool_id, waytype_t wt, koord3d pos_nw, koord3d pos_se, plainstring err); 382 383 /** 384 * @ingroup squirrel-api 385 * @see forbid_way_tool_cube 386 */ 387 void allow_way_tool_cube(uint8 player_nr, uint16 tool_id, waytype_t wt, koord3d pos_nw, koord3d pos_se); 388 389 /** 390 * Clears all rules. 391 * @ingroup squirrel-api 392 */ 393 void clear_rules(); 394 395 /** 396 * Checks if player can use this tool at all. 397 * Called for instance in karte_t::local_set_tool to change active tool or when filling toolbars. 398 * @return true if player can use this tool. 399 */ 400 bool is_tool_allowed(const player_t* player, uint16 tool_id, sint16 wt = invalid_wt); 401 402 /** 403 * Checks if player can use the tool at this position. 404 * @return NULL if allowed otherwise error message 405 */ 406 const char* is_work_allowed_here(const player_t* player, uint16 tool_id, sint16 wt, koord3d pos); 407 408 /** 409 * Checks if player can use this schedule. 410 * 411 * @param player player 412 * @param schedule the schedule 413 * 414 * @return null if allowed, an error message otherwise 415 */ 416 const char* is_schedule_allowed(const player_t* player, const schedule_t* schedule); 417 418 /** 419 * Checks if player can use this convoy. 420 * Called when player wants to start convoy at depot. 421 * 422 * @param player player 423 * @param cnv convoy 424 * @param depot depot 425 * 426 * @return null if allowed, an error message otherwise 427 */ 428 const char* is_convoy_allowed(const player_t* player, convoihandle_t cnv, depot_t* depot); 429 430 /// @return debug dump of forbidden tools 431 const char* get_forbidden_text(); 432 /// @} 433 434 friend class nwc_scenario_t; ///< to access vm, update_won_lost() 435 friend class nwc_scenario_rules_t; ///< to access forbidden_tool stuff 436 }; 437 438 #endif 439