45 #define DBG_REPLAY LOG_STREAM(debug, log_replay)
46 #define LOG_REPLAY LOG_STREAM(info, log_replay)
47 #define WRN_REPLAY LOG_STREAM(warn, log_replay)
48 #define ERR_REPLAY LOG_STREAM(err, log_replay)
64 static map* instance =
new map();
77 if ( !from.
valid() ) {
81 spectator.error(
"Missing leader location for recruitment.\n");
85 std::stringstream errbuf;
86 errbuf <<
"Recruiting leader not found at " << from <<
".\n";
87 spectator.error(errbuf.str());
91 std::string type_id = child[
"type"];
92 if ( type_id.empty() ) {
93 spectator.error(
"Recruitment is missing a unit type.");
99 std::stringstream errbuf;
100 errbuf <<
"Recruiting illegal unit: '" << type_id <<
"'.\n";
101 spectator.
error(errbuf.str());
108 std::stringstream errbuf;
109 errbuf <<
"cannot recruit unit: " << res <<
"\n";
110 spectator.error(errbuf.str());
114 const int beginning_gold = current_team.
gold();
118 if ( u_type->
cost() > beginning_gold ) {
119 std::stringstream errbuf;
120 errbuf <<
"unit '" << type_id <<
"' is too expensive to recruit: "
121 << u_type->
cost() <<
"/" << beginning_gold <<
"\n";
122 spectator.error(errbuf.str());
127 LOG_REPLAY <<
"recruit: team=" << current_team_num <<
" '" << type_id <<
"' at (" <<
loc
128 <<
") cost=" << u_type->
cost() <<
" from gold=" << beginning_gold <<
' '
129 <<
"-> " << current_team.
gold();
138 const std::string& unit_id = child[
"value"];
143 spectator.error(
"illegal recall: unit_id '" + unit_id +
"' could not be found within the recall list.\n");
152 const auto destination = child.optional_child(
"destination");
153 const auto source = child.optional_child(
"source");
157 spectator.error(
"no destination found in attack\n");
162 spectator.error(
"no source found in attack \n");
171 int weapon_num = child[
"weapon"].to_int();
177 int def_weapon_num = child[
"defender_weapon"].to_int(-2);
178 if (def_weapon_num == -2) {
180 LOG_REPLAY <<
"Old data, having to guess weapon";
186 spectator.error(
"unfound location for source of attack\n");
190 if (child.has_attribute(
"attacker_type")) {
191 const std::string &att_type_id = child[
"attacker_type"];
192 if (u->type_id() != att_type_id) {
193 WRN_REPLAY <<
"unexpected attacker type: " << att_type_id <<
"(game state gives: " << u->type_id() <<
")";
197 if (
static_cast<unsigned>(weapon_num) >= u->attacks().size()) {
198 spectator.error(
"illegal weapon type in attack\n");
205 std::stringstream errbuf;
206 errbuf <<
"unfound defender for attack: " <<
src <<
" -> " <<
dst <<
'\n';
207 spectator.error(errbuf.str());
211 if (child.has_attribute(
"defender_type")) {
212 const std::string &def_type_id = child[
"defender_type"];
213 if (tgt->type_id() != def_type_id) {
214 WRN_REPLAY <<
"unexpected defender type: " << def_type_id <<
"(game state gives: " << tgt->type_id() <<
")";
218 if (def_weapon_num >=
static_cast<int>(tgt->attacks().size())) {
220 spectator.error(
"illegal defender weapon type in attack\n");
224 DBG_REPLAY <<
"Attacker XP (before attack): " << u->experience();
237 const std::string& unit_id = child[
"value"];
242 if (!dismissed_unit) {
243 spectator.error(
"illegal disband\n");
259 std::vector<map_location> steps;
263 }
catch (
const std::invalid_argument&) {
264 WRN_REPLAY <<
"Warning: Path data contained something which could not be parsed to a sequence of locations:" <<
"\n config = " << child.debug();
266 }
catch (
const std::out_of_range&) {
267 WRN_REPLAY <<
"Warning: Path data contained something which could not be parsed to a sequence of locations:" <<
"\n config = " << child.debug();
273 WRN_REPLAY <<
"Warning: Missing path data found in [move]";
279 WRN_REPLAY <<
"Warning: Movement path contained an off-map location";
288 WRN_REPLAY <<
"Warning: Move with identical source and destination. Skipping...";
295 WRN_REPLAY <<
"Warning: Move destination " <<
dst <<
" appears occupied.";
303 std::stringstream errbuf;
304 errbuf <<
"unfound location for source of movement: "
305 <<
src <<
" -> " <<
dst <<
'\n';
306 spectator.error(errbuf.str());
310 bool skip_sighted = child[
"skip_sighted"] ==
"all";
311 bool skip_ally_sighted = child[
"skip_sighted"] ==
"only_ally";
320 if(
const auto last_select = child.optional_child(
"last_select"))
325 const std::string &event_name = child[
"raise"];
326 if (
const auto source = child.optional_child(
"source")) {
347 bool active = child[
"active"].to_bool();
348 bool block_undo = child[
"block_undo"].to_bool();
368 spectator.error(
"Team has DSU disabled but we found an explicit shroud update");
379 void debug_notification(
const std::string& text,
bool message_is_command =
false)
382 auto& current_team =
controller.current_team();
383 static bool ignore =
false;
384 bool show_long_message =
controller.is_replay() || !current_team.is_local();
389 if(i18n_vars[
"player"].empty()) {
390 i18n_vars[
"player"] =
_(
"(unknown player)");
393 if(message_is_command) {
394 i18n_vars[
"command"] = text;
395 message =
VGETTEXT(
"The :$command debug command was used during $player’s turn", i18n_vars);
400 if(show_long_message && !ignore) {
402 std::stringstream sbuilder;
403 sbuilder <<
_(
"A player used a debug command during the game. If this is unexpected, it is possible the player in question is cheating.")
405 <<
_(
"Details:") <<
"\n"
408 <<
_(
"Do you wish to save the game before continuing?");
410 save.set_title(
_(
"Debug Command Used"));
419 void debug_cmd_notification(
const std::string& command)
421 debug_notification(command,
true);
428 debug_cmd_notification(
"terrain");
431 const std::string&
terrain_type = child[
"terrain_type"];
432 const std::string& mode_str = child[
"mode_str"];
446 debug_cmd_notification(
"unit");
448 const std::string name = child[
"name"];
449 const std::string
value = child[
"value"];
455 if (name ==
"advances" ) {
459 }
catch (
const std::invalid_argument&) {
463 for (
int levels=0; levels<int_value; levels++) {
464 i->set_experience(
i->max_experience());
472 }
else if (name ==
"status" ) {
475 if (status.length() >= 1 && status[0] ==
'-') {
477 status = status.substr(1);
479 if (status.empty()) {
482 i->set_state(status, add);
492 new_u->set_location(
loc);
503 if (name ==
"fail") {
516 debug_notification(
N_(
"A unit was created using debug mode during $player’s turn"));
519 const std::string& variation = child[
"variation"].str();
523 spectator.
error(
"Invalid unit type");
552 if (unit_it.
valid() )
561 debug_cmd_notification(
"lua");
571 debug_cmd_notification(
"teleport");
573 const map_location teleport_from(child[
"teleport_from_x"].to_int(), child[
"teleport_from_y"].to_int(),
wml_loc());
574 const map_location teleport_to(child[
"teleport_to_x"].to_int(), child[
"teleport_to_y"].to_int(),
wml_loc());
578 if(unit_iter.
valid()) {
590 debug_cmd_notification(
"kill");
595 const int dying_side =
i->side();
618 debug_cmd_notification(
"next_level");
620 std::string next_level = child[
"next_level"];
621 if (!next_level.empty())
624 e.transient.carryover_report =
false;
625 e.prescenario_save =
true;
626 e.transient.linger_mode =
false;
627 e.proceed_to_next_level =
true;
640 debug_cmd_notification(
"turn_limit");
651 debug_cmd_notification(
"turn");
665 debug_cmd_notification(
"set_var");
681 debug_cmd_notification(
"gold");
693 debug_cmd_notification(
"throw");
706 debug_cmd_notification(
"fog");
723 debug_cmd_notification(
"shroud");
void attack_unit_and_advance(const map_location &attacker, const map_location &defender, int attack_with, int defend_with, bool update_display)
Performs an attack, and advanced the units afterwards.
Various functions that implement attacks and attack calculations.
Various functions related to moving units.
void advance_unit_at(const advance_unit_params ¶ms)
Various functions that implement advancements of units.
Class to encapsulate fog/shroud clearing and the resultant sighted events.
game_events::pump_result_t fire_events()
Fires the sighted events that were earlier recorded by fog/shroud clearing.
bool clear_unit(const map_location &view_loc, team &view_team, std::size_t viewer_id, int sight_range, bool slowed, const movetype::terrain_costs &costs, const map_location &real_loc, const std::set< map_location > *known_units=nullptr, std::size_t *enemy_count=nullptr, std::size_t *friend_count=nullptr, move_unit_spectator *spectator=nullptr, bool instant=true)
Clears shroud (and fog) around the provided location for view_team based on sight_range,...
void add_dismissal(const unit_const_ptr &u)
Adds a dismissal to the undo stack.
bool commit_vision()
Updates fog/shroud based on the undo stack, then updates stack as needed.
void add_auto_shroud(bool turned_on)
Adds an auto-shroud toggle to the undo stack.
A config object defines a single node in a WML file, with access to child nodes.
void recalculate_minimap()
Schedule the minimap for recalculation.
void redraw_minimap()
Schedule the minimap to be redrawn.
bool invalidate(const map_location &loc)
Function to invalidate a specific tile for redrawing.
void announce(const std::string &msg, const color_t &color=font::GOOD_COLOR, const announce_options &options=announce_options())
Announce a message prominently.
void queue_rerender()
Marks everything for rendering including all tiles and sidebar.
static display * get_singleton()
Returns the display object if a display object exists.
bool change_terrain(const map_location &loc, const std::string &t, const std::string &mode, bool replace_if_failed)
unit_map::iterator find_visible_unit(const map_location &loc, const team ¤t_team, bool see_all=false)
virtual const unit_map & units() const override
void set_next_scenario(const std::string &next_scenario)
void set_variable(const std::string &varname, const config::attribute_value &value)
does nothing if varname is no valid variable name.
void invalidate_unit()
Function to invalidate that unit status displayed on the sidebar.
static game_display * get_singleton()
void new_turn()
Update lighting settings.
void needs_rebuild(bool b)
Sets whether the screen (map visuals) needs to be rebuilt.
bool maybe_rebuild()
Rebuilds the screen if needs_rebuild(true) was previously called, and resets the flag.
game_events::wml_event_pump & pump()
void flush_messages()
Flushes WML messages and errors.
pump_result_t fire(const std::string &event, const entity_location &loc1=entity_location::null_entity, const entity_location &loc2=entity_location::null_entity, const config &data=config())
Function to fire an event.
void custom_command(const std::string &, const config &)
void run(char const *prog, const std::string &name, int nArgs=0)
Runs a plain script.
void set_end_level_data(const end_level_data &data)
int current_side() const
Returns the number of the side whose turn it is.
bool is_skipping_replay() const
virtual void force_end_turn()=0
game_events::wml_event_pump & pump()
std::size_t size() const
Get the number of units on the list.
unit_ptr find_if_matches_id(const std::string &unit_id)
Find a unit by id.
void erase_if_matches_id(const std::string &unit_id)
Erase any unit with this id.
synced_command(const std::string &tag, handler function)
static map & registry()
using static function variable instead of static member variable to prevent static initialization fia...
std::map< std::string, handler > map
static void block_undo(bool do_block=true, bool clear_undo=true)
set this to false to prevent clearing the undo stack, this is important when we cannot change the gam...
This class stores all the data for a single 'side' (in game nomenclature).
void set_shroud(bool shroud)
bool auto_shroud_updates() const
void set_auto_shroud_updates(bool value)
void spend_gold(const int amount)
recall_list_manager & recall_list()
void set_turn(const int num, game_data *vars=nullptr, const bool increase_limit_if_needed=true)
Dynamically change the current turn number.
void set_number_of_turns(int num)
unit_iterator find(std::size_t id)
umap_retval_pair_t replace(const map_location &l, const unit_ptr &p)
Works like unit_map::add; but l is emptied first, if needed.
std::size_t erase(const map_location &l)
Erases the unit at location l, if any.
umap_retval_pair_t insert(const unit_ptr &p)
Inserts the unit pointed to by p into the map.
const unit_type * find(const std::string &key, unit_type::BUILD_STATUS status=unit_type::FULL) const
Finds a unit_type by its id() and makes sure it is built to the specified level.
A single unit type that the player may recruit.
static unit_ptr create(const config &cfg, bool use_traits=false, const vconfig *vcfg=nullptr)
Initializes a unit from a config.
Various functions related to the creation of units (recruits, recalls, and placed units).
static std::string _(const char *str)
std::vector< map_location > read_locations(const config &cfg)
Parse x,y keys of a config into a vector of locations.
Standard logging facilities (interface).
std::string find_recruit_location(const int side, map_location &recruit_location, map_location &recruited_from, const std::string &unit_type)
Finds a location on which to place a unit.
void teleport_unit_from_replay(const std::vector< map_location > &steps, bool continued_move, bool skip_ally_sighted, bool show_move)
Teleports a unit across the board.
bool clear_shroud(int side, bool reset_fog, bool fire_events)
Function that will clear shroud (and fog) based on current unit positions.
bool recall_unit(const std::string &id, team ¤t_team, const map_location &loc, const map_location &from, map_location::direction facing)
Recalls the unit with the indicated ID for the provided team.
game_events::pump_result_t actor_sighted(const unit &target, const std::vector< int > *cache)
Fires sighted events for the sides that can see target.
void recruit_unit(const unit_type &u_type, int side_num, const map_location &loc, const map_location &from)
Recruits a unit of the given type for the given side.
game_events::pump_result_t get_village(const map_location &loc, int side, bool *action_timebonus, bool fire_event)
Makes it so the village at the given location is owned by the given side.
void recalculate_fog(int side)
Function that recalculates the fog of war.
void execute_move_unit(const std::vector< map_location > &steps, bool continued_move, bool skip_ally_sighted, move_unit_spectator *move_spectator)
Moves a unit across the board.
void pump()
Process all events currently in the queue.
const color_t NORMAL_COLOR
bool fire_event(const ui_event event, const std::vector< std::pair< widget *, ui_event >> &event_chain, widget *dispatcher, widget *w, F &&... params)
Helper function for fire_event.
std::string tag(std::string_view tag, Args &&... data)
Wraps the given data in the specified tag.
::tod_manager * tod_manager
game_events::manager * game_events
actions::undo_list * undo_stack
game_lua_kernel * lua_kernel
play_controller * controller
std::shared_ptr< wb::manager > whiteboard
void unit_die(const map_location &loc, unit &loser, const const_attack_ptr &attack, const const_attack_ptr &secondary_attack, const map_location &winner_loc, const unit_ptr &winner)
Show a unit fading out.
void unit_recruited(const map_location &loc, const map_location &leader_loc)
int stoi(std::string_view str)
Same interface as std::stoi and meant as a drop in replacement, except:
std::map< std::string, t_string > string_map
std::vector< std::string > split(const config_attribute_value &val)
auto * find(Container &container, const Value &value)
Convenience wrapper for using find on a container without needing to comare to end()
bool show(std::string title, std::string message)
Displays a tray notification.
std::shared_ptr< unit > unit_ptr
Define the game's event mechanism.
unit_race::GENDER string_gender(const std::string &str, unit_race::GENDER def)
std::unique_ptr< MIX_Audio, decltype(&MIX_DestroyAudio)> value
rect dst
Location on the final composed sheet.
rect src
Non-transparent portion of the surface to compose.
advances the unit at loc if it has enough experience, maximum 20 times.
Holds options for calls to function 'announce' (announce).
Additional information on the game outcome which can be provided by WML.
Encapsulates the map of the game.
static lg::log_domain log_replay("replay")
SYNCED_COMMAND_HANDLER_FUNCTION(recruit, child, spectator)
unit_type_data unit_types
Display units performing various actions: moving, attacking, and dying.
Various functions that implement the undoing (and redoing) of in-game commands.