undo/redo for advanced town details

This commit is contained in:
2025-06-19 19:40:03 -05:00
parent 77d7212801
commit 56e3a6e627
5 changed files with 110 additions and 2 deletions

View File

@@ -288,3 +288,38 @@ bool cTown::cItem::operator==(const cTown::cItem& other) {
CHECK_EQ(other, contained);
return true;
}
town_advanced_t advanced_from_town(size_t which, cTown& town, cScenario& scenario) {
town_advanced_t details = {
town.exits,
town.spec_on_entry,
town.spec_on_entry_if_dead,
town.spec_on_hostile,
town.bg_town,
town.bg_fight,
town.is_hidden,
town.defy_mapping,
town.defy_scrying,
town.strong_barriers,
town.has_tavern
};
auto iter = scenario.store_item_rects.find(which);
if(iter != scenario.store_item_rects.end()) details.store_item_rect = iter->second;
return details;
}
void town_set_advanced(size_t which, cTown& town, cScenario& scenario, const town_advanced_t& details) {
town.exits = details.exits;
town.spec_on_entry = details.spec_on_entry;
town.spec_on_entry_if_dead = details.spec_on_entry_if_dead;
town.spec_on_hostile = details.spec_on_hostile;
town.bg_town = details.bg_town;
town.bg_fight = details.bg_fight;
town.is_hidden = details.is_hidden;
town.defy_mapping = details.defy_mapping;
town.defy_scrying = details.defy_scrying;
town.strong_barriers = details.strong_barriers;
town.has_tavern = details.has_tavern;
if(details.store_item_rect) scenario.store_item_rects[which] = *details.store_item_rect;
else scenario.store_item_rects.erase(which);
}

View File

@@ -181,4 +181,46 @@ inline void town_set_details(cTown& town, const town_details_t& details) {
town.comment = details.comment;
}
// Store a version of the advanced town details for undo history.
// This could be made a struct that cTown contains, and that would eliminate the next 2 functions, but it would
// require changing every reference to these detail values in the game and fileio code, making them more verbose. I don't know
// if that's worth it.
struct town_advanced_t {
std::array<spec_loc_t, 4> exits;
short spec_on_entry;
short spec_on_entry_if_dead;
short spec_on_hostile;
int bg_town;
int bg_fight;
bool is_hidden;
bool defy_mapping;
bool defy_scrying;
bool strong_barriers;
bool has_tavern;
boost::optional<rectangle> store_item_rect;
bool operator==(const town_advanced_t& other) const {
for(int i = 0; i < exits.size(); ++i){
if(other.exits[i].spec != exits[i].spec) return false;
if(other.exits[i] != exits[i]) return false;
}
CHECK_EQ(other,spec_on_entry);
CHECK_EQ(other,spec_on_entry_if_dead);
CHECK_EQ(other,spec_on_hostile);
CHECK_EQ(other,bg_town);
CHECK_EQ(other,bg_fight);
CHECK_EQ(other,is_hidden);
CHECK_EQ(other,defy_mapping);
CHECK_EQ(other,defy_scrying);
CHECK_EQ(other,strong_barriers);
CHECK_EQ(other,has_tavern);
CHECK_EQ(other,store_item_rect);
return true;
}
bool operator!=(const town_advanced_t& other) const { return !(*this == other); }
};
town_advanced_t advanced_from_town(size_t which, cTown& town, cScenario& scenario);
void town_set_advanced(size_t which, cTown& town, cScenario& scenario, const town_advanced_t& details);
#endif

View File

@@ -1027,9 +1027,19 @@ void edit_advanced_town() {
put_advanced_town_in_dlog(town_dlg);
town_advanced_t old_details = advanced_from_town(cur_town, *town, scenario);
town_dlg.run();
if(town_dlg.accepted() && delete_rect)
if(town_dlg.accepted()){
if(delete_rect){
scenario.store_item_rects.erase(cur_town);
}
town_advanced_t new_details = advanced_from_town(cur_town, *town, scenario);
if(new_details != old_details){
undo_list.add(action_ptr(new aEditTownAdvancedDetails(cur_town, old_details, new_details)));
update_edit_menu();
}
}
}
static bool save_town_wand(cDialog& me, std::string, eKeyMod) {

View File

@@ -951,3 +951,13 @@ bool aEditTownWandering::redo_me() {
scenario.towns[which]->wandering_locs = new_wandering_locs;
return true;
}
bool aEditTownAdvancedDetails::undo_me() {
town_set_advanced(which, *scenario.towns[which], scenario, old_details);
return true;
}
bool aEditTownAdvancedDetails::redo_me() {
town_set_advanced(which, *scenario.towns[which], scenario, new_details);
return true;
}

View File

@@ -609,4 +609,15 @@ public:
new_wandering(new_wandering), new_wandering_locs(new_wandering_locs) {}
};
class aEditTownAdvancedDetails : public cAction {
size_t which;
town_advanced_t old_details;
town_advanced_t new_details;
bool undo_me() override;
bool redo_me() override;
public:
aEditTownAdvancedDetails(size_t which, town_advanced_t old_details, town_advanced_t new_details) :
cAction("Edit Town Advanced Details"), which(which), old_details(old_details), new_details(new_details) {}
};
#endif