undo/redo for outdoor encounters

This commit is contained in:
2025-06-19 21:22:13 -05:00
parent 855310c516
commit 00a1d8f889
6 changed files with 98 additions and 4 deletions

View File

@@ -0,0 +1,12 @@
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<!-- NOTE: This file should be updated to use relative positioning the next time it changes. -->
<?xml-stylesheet href="dialog.xsl" type="text/xsl"?>
<dialog defbtn='keep' escbtn='cancel'>
<pict type='dlog' num='7' top='6' left='6'/>
<text name='keep-msg' top='6' left='49' width='256' height='32'>
Keep changes to {{enc-type}} {{num}} before editing another encounter?
</text>
<button name='cancel' type='regular' top='43' left='109'>Cancel</button>
<button name='revert' type='regular' top='43' left='175'>Discard</button>
<button name='keep' type='regular' top='43' left='240'>Keep</button>
</dialog>

View File

@@ -110,6 +110,21 @@ cOutdoors::cWandering::cWandering() {
std::fill(friendly.begin(), friendly.end(), 0);
}
bool cOutdoors::cWandering::operator==(const cOutdoors::cWandering& other) const {
for(int i = 0; i < monst.size(); ++i){
if(other.monst[i] != monst[i]) return false;
}
for(int i = 0; i < friendly.size(); ++i){
if(other.friendly[i] != friendly[i]) return false;
}
CHECK_EQ(other, spec_on_meet);
CHECK_EQ(other, spec_on_win);
CHECK_EQ(other, spec_on_flee);
CHECK_EQ(other, end_spec1);
CHECK_EQ(other, end_spec2);
return true;
}
cOutdoors::cOutdoors(cScenario& scenario) : cArea(AREA_MEDIUM), scenario(&scenario) {
location locs[4] = {loc(8,8),loc(32,8),loc(8,32),loc(32,32)};
bg_out = bg_fight = bg_town = bg_dungeon = -1;

View File

@@ -52,6 +52,9 @@ public:
short end_spec1,end_spec2;
bool cant_flee, forced;
bool operator==(const cWandering& other) const;
bool operator!=(const cWandering& other) const { return !(*this == other); }
bool isNull() const;
void import_legacy(legacy::out_wandering_type old);
void writeTo(cTagFile_Page& page) const;

View File

@@ -647,7 +647,9 @@ static void put_out_wand_in_dlog(cDialog& me, short which, const cOutdoors::cWan
me["location"].setText(boost::lexical_cast<std::string>(current_terrain->wandering_locs[which]));
}
// mode 0 - wandering, 1 - special, 100 - do not commit changes to the scenario yet
static void save_out_wand(cDialog& me, short which, cOutdoors::cWandering& wand, short mode) {
cOutdoors::cWandering old_wand = (mode == 0 ? current_terrain->wandering[which] : current_terrain->special_enc[which]);
wand.spec_on_meet = me["onmeet"].getTextAsNum();
wand.spec_on_win = me["onwin"].getTextAsNum();
wand.spec_on_flee = me["onflee"].getTextAsNum();
@@ -658,19 +660,45 @@ static void save_out_wand(cDialog& me, short which, cOutdoors::cWandering& wand,
wand.cant_flee = dynamic_cast<cLed&>(me["no-flee"]).getState() != led_off;
switch(mode) {
case 0:
case 0:{
current_terrain->wandering[which] = wand;
current_terrain->wandering_locs[which] = boost::lexical_cast<location>(me["location"].getText());
break;
location old_loc = current_terrain->wandering_locs[which];
location new_loc = boost::lexical_cast<location>(me["location"].getText());
current_terrain->wandering_locs[which] = new_loc;
undo_list.add(action_ptr(new aEditOutEncounter(cur_out, which, old_wand, old_loc, wand, new_loc)));
}break;
case 1:
current_terrain->special_enc[which] = wand;
undo_list.add(action_ptr(new aEditOutEncounter(cur_out, which, old_wand, wand)));
break;
}
update_edit_menu();
}
static bool edit_out_wand_event_filter(cDialog& me, std::string hit, short& which, cOutdoors::cWandering& wand, short mode) {
if(!me.toast(true)) return true;
save_out_wand(me, which, wand, mode);
bool loc_changed = (mode == 0 && current_terrain->wandering_locs[which] != boost::lexical_cast<location>(me["location"].getText()));
cOutdoors::cWandering old_wand = (mode == 0 ? current_terrain->wandering[which] : current_terrain->special_enc[which]);
if((loc_changed || wand != old_wand)){
// Confirm before moving left/right and committing changes
if(hit == "left" || hit == "right"){
cChoiceDlog dlog("confirm-edit-out-wand", {"keep","revert","cancel"}, &me);
dlog->getControl("keep-msg").replaceText("{{enc-type}}", (mode == 0 ? "Wandering Monster Group" : "Special Encounter"));
dlog->getControl("keep-msg").replaceText("{{num}}", std::to_string(which));
std::string choice = dlog.show();
if(choice == "keep"){
save_out_wand(me, which, wand, mode);
}else if(choice == "cancel"){
return true;
}
}
// Okay pressed
else{
save_out_wand(me, which, wand, mode);
}
}
size_t num_enc = (mode == 0) ? current_terrain->wandering.size() : current_terrain->special_enc.size();
if(hit == "left") {
me.untoast();

View File

@@ -981,3 +981,19 @@ bool aEditOutDetails::redo_me() {
out_set_details(*scenario.outdoors[out_sec.x][out_sec.y], new_details);
return true;
}
bool aEditOutEncounter::undo_me() {
cOutdoors& outdoors = *scenario.outdoors[out_sec.x][out_sec.y];
auto& encounters = (mode == 0 ? outdoors.wandering : outdoors.special_enc);
encounters[which] = old_enc;
if(mode == 0) outdoors.wandering_locs[which] = old_loc;
return true;
}
bool aEditOutEncounter::redo_me() {
cOutdoors& outdoors = *scenario.outdoors[out_sec.x][out_sec.y];
auto& encounters = (mode == 0 ? outdoors.wandering : outdoors.special_enc);
encounters[which] = new_enc;
if(mode == 0) outdoors.wandering_locs[which] = new_loc;
return true;
}

View File

@@ -642,4 +642,24 @@ public:
cAction("Edit Outdoor Details"), out_sec(out_sec), old_details(old_details), new_details(new_details) {}
};
class aEditOutEncounter : public cAction {
location out_sec;
short mode;
size_t which;
cOutdoors::cWandering old_enc;
cOutdoors::cWandering new_enc;
// Ignored for special encounters:
location old_loc;
location new_loc;
bool undo_me() override;
bool redo_me() override;
public:
aEditOutEncounter(location out_sec, size_t which, cOutdoors::cWandering old_enc, location old_loc, cOutdoors::cWandering new_enc, location new_loc) :
cAction("Edit Outdoor Wandering Encounter"),
out_sec(out_sec), mode(0), which(which), old_enc(old_enc), old_loc(old_loc), new_enc(new_enc), new_loc(new_loc) {}
aEditOutEncounter(location out_sec, size_t which, cOutdoors::cWandering old_enc, cOutdoors::cWandering new_enc) :
cAction("Edit Outdoor Special Encounter"),
out_sec(out_sec), mode(1), which(which), old_enc(old_enc), new_enc(new_enc) {}
};
#endif