Added the ability to move units on fog/shroud maps without ...
...updating the fog/shroud, so the moves can be undone. The player can commit the moves, forcing the fog/shroud to update, but then the moves can no longer be undone. Useful to make fog/shroud maps behave more like normal maps, with respect to move undoing.
This commit is contained in:
parent
5021410e72
commit
8a80955b83
10 changed files with 121 additions and 13 deletions
|
@ -39,7 +39,7 @@ height=600
|
|||
|
||||
[menu]
|
||||
is_context_menu=true
|
||||
items=undo,redo,cycle,describeunit,speak,recruit,recall,createunit,renameunit,labelterrain,showenemymoves,bestenemymoves,endturn
|
||||
items=undo,redo,cycle,describeunit,speak,recruit,recall,createunit,renameunit,labelterrain,showenemymoves,bestenemymoves,toggleshroud,updateshroud,endturn
|
||||
[/menu]
|
||||
|
||||
# top panel
|
||||
|
|
|
@ -125,6 +125,16 @@ language="English"
|
|||
ctrl=yes
|
||||
[/hotkey]
|
||||
[hotkey]
|
||||
command=toggleshroud
|
||||
key=k
|
||||
alt=yes
|
||||
[/hotkey]
|
||||
[hotkey]
|
||||
command=updateshroud
|
||||
key=k
|
||||
ctrl=yes
|
||||
[/hotkey]
|
||||
[hotkey]
|
||||
command=speak
|
||||
key=m
|
||||
[/hotkey]
|
||||
|
@ -450,6 +460,8 @@ action_mute="Mute"
|
|||
action_labelterrain="Set Label"
|
||||
action_showenemymoves="Show Enemy Moves"
|
||||
action_bestenemymoves="Best Possible Enemy Moves"
|
||||
action_toggleshroud="Toggle Shroud Updates"
|
||||
action_updateshroud="Update Shroud Now"
|
||||
action_editnewmap="New Map"
|
||||
action_editloadmap="Load Map"
|
||||
action_editsavemap="Save Map"
|
||||
|
|
|
@ -1430,9 +1430,12 @@ size_t move_unit(display* disp, const game_data& gamedata,
|
|||
|
||||
const bool skirmisher = u.type().is_skirmisher();
|
||||
|
||||
const bool check_shroud = teams[team_num].auto_shroud_updates() &&
|
||||
(teams[team_num].uses_shroud() || teams[team_num].uses_fog());
|
||||
|
||||
//if we use shroud/fog of war, count out the units we can currently see
|
||||
std::set<gamemap::location> known_units;
|
||||
if(teams[team_num].uses_shroud() || teams[team_num].uses_fog()) {
|
||||
if(check_shroud) {
|
||||
for(unit_map::const_iterator u = units.begin(); u != units.end(); ++u) {
|
||||
if(teams[team_num].fogged(u->first.x,u->first.y) == false) {
|
||||
known_units.insert(u->first);
|
||||
|
@ -1466,8 +1469,7 @@ size_t move_unit(display* disp, const game_data& gamedata,
|
|||
|
||||
//if we use fog or shroud, see if we have sighted an enemy unit, in
|
||||
//which case we should stop immediately.
|
||||
if(teams[team_num].uses_shroud() || teams[team_num].uses_fog()) {
|
||||
|
||||
if(check_shroud) {
|
||||
if(units.count(*step) == 0 && !map.is_village(*step)) {
|
||||
std::cerr << "checking for units from " << (step->x+1) << "," << (step->y+1) << "\n";
|
||||
|
||||
|
@ -1553,6 +1555,7 @@ size_t move_unit(display* disp, const game_data& gamedata,
|
|||
|
||||
if(undo_stack != NULL) {
|
||||
if(event_mutated || should_clear_stack) {
|
||||
apply_shroud_changes(*undo_stack,disp,status,map,gamedata,units,teams,team_num);
|
||||
undo_stack->clear();
|
||||
} else {
|
||||
undo_stack->push_back(undo_action(steps,starting_moves,orig_village_owner));
|
||||
|
@ -1671,3 +1674,42 @@ bool unit_can_move(const gamemap::location& loc, const unit_map& units,
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
void apply_shroud_changes(undo_list& undos, display* disp, const gamestatus& status, const gamemap& map,
|
||||
const game_data& gamedata, const unit_map& units, std::vector<team>& teams, int team)
|
||||
{
|
||||
// No need to do this if the team isn't using fog or shroud.
|
||||
if(!teams[team].uses_shroud() && !teams[team].uses_fog())
|
||||
return;
|
||||
/*
|
||||
This function works thusly:
|
||||
1. run through the list of undo_actions
|
||||
2. for each one, play back the unit's move
|
||||
3. for each location along the route, clear any "shrouded" squares that the unit can see
|
||||
4. clear the undo_list
|
||||
5. call clear_shroud to update the fog of war for each unit.
|
||||
6. fix up associated display stuff (done in a similar way to turn_info::undo())
|
||||
*/
|
||||
for(undo_list::const_iterator un = undos.begin(); un != undos.end(); ++un) {
|
||||
if(un->is_recall()) continue;
|
||||
unit_map::const_iterator ui = units.find(un->route.back());
|
||||
unit_map um;
|
||||
assert(ui != units.end());
|
||||
std::vector<gamemap::location>::const_iterator step;
|
||||
for(step = un->route.begin(); step != un->route.end(); ++step) {
|
||||
um.insert(std::pair<gamemap::location,unit>(*step,ui->second));
|
||||
clear_shroud_unit(map,status,gamedata,um,*step,teams,team,NULL,NULL);
|
||||
um.erase(*step);
|
||||
}
|
||||
}
|
||||
if(disp != NULL) {
|
||||
disp->invalidate_unit();
|
||||
disp->invalidate_game_status();
|
||||
clear_shroud(*disp,status,map,gamedata,units,teams,team);
|
||||
disp->recalculate_minimap();
|
||||
disp->set_paths(NULL);
|
||||
disp->set_route(NULL);
|
||||
} else {
|
||||
recalculate_fog(map,status,gamedata,units,teams,team);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -196,6 +196,11 @@ bool clear_shroud(display& disp, const gamestatus& status,
|
|||
const gamemap& map, const game_data& gamedata,
|
||||
const unit_map& units, std::vector<team>& teams, int team);
|
||||
|
||||
//function to apply pending shroud changes in the undo stack.
|
||||
//it needs tons of parameters because it calls clear_shroud(...) (see above)
|
||||
void apply_shroud_changes(undo_list& undos, display* disp, const gamestatus& status, const gamemap& map,
|
||||
const game_data& gamedata, const unit_map& units, std::vector<team>& teams, int team);
|
||||
|
||||
//will return true iff the unit at 'loc' has any possible moves it can do
|
||||
//(including attacking etc).
|
||||
bool unit_can_move(const gamemap::location& loc, const unit_map& units,
|
||||
|
|
|
@ -73,6 +73,8 @@ HOTKEY_COMMAND string_to_command(const std::string& str)
|
|||
m.insert(val("editsavemap",HOTKEY_EDIT_SAVE_MAP));
|
||||
m.insert(val("editsaveas",HOTKEY_EDIT_SAVE_AS));
|
||||
m.insert(val("editsetstartpos",HOTKEY_EDIT_SET_START_POS));
|
||||
m.insert(val("toggleshroud",HOTKEY_TOGGLE_SHROUD));
|
||||
m.insert(val("updateshroud",HOTKEY_UPDATE_SHROUD));
|
||||
}
|
||||
|
||||
const std::map<std::string,HOTKEY_COMMAND>::const_iterator i = m.find(str);
|
||||
|
@ -373,6 +375,12 @@ void execute_command(display& disp, HOTKEY_COMMAND command, command_executor* ex
|
|||
if(executor)
|
||||
executor->show_enemy_moves(true);
|
||||
break;
|
||||
case HOTKEY_TOGGLE_SHROUD:
|
||||
if(executor) executor->toggle_shroud_updates();
|
||||
break;
|
||||
case HOTKEY_UPDATE_SHROUD:
|
||||
if(executor) executor->update_shroud_now();
|
||||
break;
|
||||
case HOTKEY_QUIT_GAME: {
|
||||
const int res = gui::show_dialog(disp,NULL,"",string_table["quit_message"],gui::YES_NO);
|
||||
if(res == 0) {
|
||||
|
|
|
@ -34,6 +34,7 @@ enum HOTKEY_COMMAND { HOTKEY_CYCLE_UNITS, HOTKEY_END_UNIT_TURN, HOTKEY_LEADER,
|
|||
HOTKEY_SPEAK, HOTKEY_CREATE_UNIT, HOTKEY_PREFERENCES,
|
||||
HOTKEY_OBJECTIVES, HOTKEY_UNIT_LIST, HOTKEY_STATISTICS, HOTKEY_QUIT_GAME,
|
||||
HOTKEY_LABEL_TERRAIN, HOTKEY_SHOW_ENEMY_MOVES, HOTKEY_BEST_ENEMY_MOVES,
|
||||
HOTKEY_TOGGLE_SHROUD, HOTKEY_UPDATE_SHROUD,
|
||||
|
||||
//editing specific commands
|
||||
HOTKEY_EDIT_SET_TERRAIN,
|
||||
|
@ -106,6 +107,8 @@ public:
|
|||
virtual void show_statistics() = 0;
|
||||
virtual void label_terrain() = 0;
|
||||
virtual void show_enemy_moves(bool ignore_units) = 0;
|
||||
virtual void toggle_shroud_updates() = 0;
|
||||
virtual void update_shroud_now() = 0;
|
||||
|
||||
// Map editor stuff.
|
||||
virtual void edit_set_terrain() {}
|
||||
|
|
|
@ -675,7 +675,7 @@ void turn_info::left_click(const SDL_MouseButtonEvent& event)
|
|||
res = attacks_in_range[res];
|
||||
|
||||
u->second.set_goto(gamemap::location());
|
||||
undo_stack_.clear();
|
||||
clear_undo_stack();
|
||||
redo_stack_.clear();
|
||||
|
||||
current_paths_ = paths();
|
||||
|
@ -771,9 +771,7 @@ void turn_info::left_click(const SDL_MouseButtonEvent& event)
|
|||
gui_.set_paths(¤t_paths_);
|
||||
}
|
||||
|
||||
if(clear_shroud(gui_,status_,map_,gameinfo_,units_,teams_,team_num_-1)) {
|
||||
undo_stack_.clear();
|
||||
}
|
||||
if(clear_shroud()) clear_undo_stack();
|
||||
}
|
||||
} else {
|
||||
gui_.set_paths(NULL);
|
||||
|
@ -893,6 +891,11 @@ bool turn_info::can_execute_command(hotkey::HOTKEY_COMMAND command) const
|
|||
case hotkey::HOTKEY_UNDO:
|
||||
return !browse_ && !undo_stack_.empty();
|
||||
|
||||
case hotkey::HOTKEY_TOGGLE_SHROUD:
|
||||
return !browse_ && (teams_[team_num_-1].uses_fog() || teams_[team_num_-1].uses_shroud());
|
||||
case hotkey::HOTKEY_UPDATE_SHROUD:
|
||||
return !browse_ && !teams_[team_num_-1].auto_shroud_updates();
|
||||
|
||||
//commands we can only do if we are actually playing, not just viewing
|
||||
case hotkey::HOTKEY_END_UNIT_TURN:
|
||||
case hotkey::HOTKEY_RECRUIT:
|
||||
|
@ -1070,6 +1073,8 @@ void turn_info::end_turn()
|
|||
}
|
||||
}
|
||||
|
||||
//force any pending fog updates
|
||||
clear_undo_stack();
|
||||
end_turn_ = true;
|
||||
|
||||
//auto-save
|
||||
|
@ -1089,7 +1094,7 @@ void turn_info::goto_leader()
|
|||
{
|
||||
const unit_map::const_iterator i = team_leader(team_num_,units_);
|
||||
if(i != units_.end()) {
|
||||
clear_shroud(gui_,status_,map_,gameinfo_,units_,teams_,team_num_-1);
|
||||
clear_shroud();
|
||||
gui_.scroll_to_tile(i->first.x,i->first.y,display::WARP);
|
||||
}
|
||||
}
|
||||
|
@ -1174,7 +1179,7 @@ void turn_info::undo()
|
|||
|
||||
recorder.undo();
|
||||
|
||||
const bool shroud_cleared = clear_shroud(gui_,status_,map_,gameinfo_,units_,teams_,team_num_-1);
|
||||
const bool shroud_cleared = clear_shroud();
|
||||
|
||||
if(shroud_cleared) {
|
||||
gui_.recalculate_minimap();
|
||||
|
@ -1588,10 +1593,10 @@ void turn_info::do_recruit(const std::string& name)
|
|||
gui::show_dialog(gui_,NULL,"",msg,gui::OK_ONLY);
|
||||
}
|
||||
|
||||
undo_stack_.clear();
|
||||
clear_undo_stack();
|
||||
redo_stack_.clear();
|
||||
|
||||
clear_shroud(gui_,status_,map_,gameinfo_,units_,teams_,team_num_-1);
|
||||
clear_shroud();
|
||||
|
||||
gui_.recalculate_minimap();
|
||||
gui_.invalidate_game_status();
|
||||
|
@ -1996,6 +2001,29 @@ void turn_info::show_enemy_moves(bool ignore_units)
|
|||
gui_.set_paths(&all_paths_);
|
||||
}
|
||||
|
||||
void turn_info::toggle_shroud_updates() {
|
||||
bool auto_shroud = teams_[team_num_-1].auto_shroud_updates();
|
||||
// If we're turning automatic shroud updates on, then commit all moves
|
||||
if(auto_shroud == false) update_shroud_now();
|
||||
teams_[team_num_-1].set_auto_shroud_updates(!auto_shroud);
|
||||
}
|
||||
|
||||
void turn_info::update_shroud_now() {
|
||||
clear_undo_stack();
|
||||
}
|
||||
|
||||
bool turn_info::clear_shroud() {
|
||||
return teams_[team_num_-1].auto_shroud_updates() &&
|
||||
::clear_shroud(gui_,status_,map_,gameinfo_,units_,teams_,team_num_-1);
|
||||
}
|
||||
|
||||
void turn_info::clear_undo_stack() {
|
||||
if (teams_[team_num_-1].auto_shroud_updates() == false)
|
||||
apply_shroud_changes(undo_stack_,&gui_,status_,map_,gameinfo_,units_,teams_,team_num_-1);
|
||||
undo_stack_.clear();
|
||||
}
|
||||
|
||||
|
||||
unit_map::iterator turn_info::current_unit()
|
||||
{
|
||||
unit_map::iterator i = units_.end();
|
||||
|
|
|
@ -108,6 +108,8 @@ private:
|
|||
void show_statistics();
|
||||
void label_terrain();
|
||||
void show_enemy_moves(bool ignore_units);
|
||||
void toggle_shroud_updates();
|
||||
void update_shroud_now();
|
||||
|
||||
void do_recruit(const std::string& name);
|
||||
|
||||
|
@ -120,6 +122,9 @@ private:
|
|||
|
||||
void show_attack_options(unit_map::const_iterator u);
|
||||
|
||||
bool clear_shroud();
|
||||
void clear_undo_stack();
|
||||
|
||||
unit_map::iterator current_unit();
|
||||
unit_map::const_iterator current_unit() const;
|
||||
|
||||
|
|
|
@ -217,7 +217,7 @@ void team::team_info::write(config& cfg) const
|
|||
cfg["music"] = music;
|
||||
}
|
||||
|
||||
team::team(const config& cfg, int gold) : gold_(gold), info_(cfg)
|
||||
team::team(const config& cfg, int gold) : gold_(gold), info_(cfg), auto_shroud_updates_(true)
|
||||
{
|
||||
//gold is the maximum of 'gold' and what is given in the config file
|
||||
if(info_.gold.empty() == false)
|
||||
|
|
|
@ -120,6 +120,9 @@ public:
|
|||
bool clear_fog(size_t x, size_t y);
|
||||
void refog();
|
||||
|
||||
bool auto_shroud_updates() const { return auto_shroud_updates_; }
|
||||
void set_auto_shroud_updates(bool value) { auto_shroud_updates_ = value; }
|
||||
|
||||
const std::string& music() const;
|
||||
|
||||
static int nteams();
|
||||
|
@ -131,6 +134,8 @@ private:
|
|||
typedef std::vector<std::vector<bool> > shroud_map;
|
||||
shroud_map shroud_, fog_;
|
||||
|
||||
bool auto_shroud_updates_;
|
||||
|
||||
team_info info_;
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue