undo/redo for edit/clear item type

This commit is contained in:
2025-06-05 13:41:15 -05:00
parent 30945f7f4a
commit 8d7e5ba500
7 changed files with 125 additions and 10 deletions

View File

@@ -1407,3 +1407,41 @@ bool cItem::use_magic() const {
bool cItem::can_use() const {
return use_in_town() || use_in_combat() || use_outdoors();
}
bool cItem::operator==(const cItem& other) {
CHECK_EQ(other, variety);
CHECK_EQ(other, item_level);
CHECK_EQ(other, awkward);
CHECK_EQ(other, bonus);
CHECK_EQ(other, protection);
CHECK_EQ(other, charges);
CHECK_EQ(other, max_charges);
CHECK_EQ(other, weap_type);
CHECK_EQ(other, magic_use_type);
CHECK_EQ(other, graphic_num);
CHECK_EQ(other, ability);
CHECK_EQ(other, abil_strength);
CHECK_EQ(other, abil_data.value);
CHECK_EQ(other, type_flag);
CHECK_EQ(other, is_special);
CHECK_EQ(other, value);
CHECK_EQ(other, weight);
CHECK_EQ(other, special_class);
CHECK_EQ(other, missile);
CHECK_EQ(other, item_loc);
CHECK_EQ(other, full_name);
CHECK_EQ(other, name);
CHECK_EQ(other, treas_class);
CHECK_EQ(other, ident);
CHECK_EQ(other, property);
CHECK_EQ(other, magic);
CHECK_EQ(other, contained);
CHECK_EQ(other, held);
CHECK_EQ(other, cursed);
CHECK_EQ(other, concealed);
CHECK_EQ(other, enchanted);
CHECK_EQ(other, unsellable);
CHECK_EQ(other, rechargeable);
CHECK_EQ(other, desc);
return true;
}

View File

@@ -66,6 +66,11 @@ public:
unsigned int treas_class;
bool ident, property, magic, contained, held, cursed, concealed, enchanted, unsellable, rechargeable;
std::string desc;
// For detecting actual changes to types in the scenario editor
bool operator==(const cItem& other);
bool operator!=(const cItem& other) { return !(*this == other); }
unsigned char rec_treas_class() const;
short item_weight() const;
std::string interesting_string() const;

View File

@@ -1338,8 +1338,12 @@ static bool handle_terpal_action(location cur_point, bool option_hit) {
// option-click type that can't be deleted (because it would break other types' numbers, or is in use somewhere):
// reset type info
else{
scenario.scen_items[i] = cItem();
scenario.scen_items[i].full_name = "Unused Item";
cItem before = scenario.scen_items[i];
cItem after;
after.full_name = "Unused Item";
scenario.scen_items[i] = after;
undo_list.add(action_ptr(new aEditClearItem("Clear Item Type", i, before, after)));
update_edit_menu();
}
break;
}

View File

@@ -1625,31 +1625,31 @@ static void put_item_info_in_dlog(cDialog& me, cItem& item, short which) {
break;
}
// Even if hidden, the text needs to store the right value so == will work
me["missile"].setTextToNum(item.missile);
if(missile) {
me["missile"].show();
me["missile-pic"].show();
me["missile-title"].show();
me["missile-pic"].show();
me["choosemiss"].show();
me["missile"].setTextToNum(item.missile);
dynamic_cast<cPict&>(me["missile-pic"]).setPict(item.missile);
} else {
me["missile"].hide();
me["missile-title"].hide();
me["missile-pic"].hide();
me["choosemiss"].hide();
me["missile"].setText("0");
}
// Even if hidden, the text needs to store the right value so == will work
me["weap-type"].setTextToNum(int(item.weap_type));
if(weapon) {
me["skill-title"].show();
me["weap-type"].show();
me["choosetp"].show();
me["weap-type"].setTextToNum(int(item.weap_type));
} else {
me["skill-title"].hide();
me["weap-type"].hide();
me["choosetp"].hide();
me["weap-type"].setText("0");
}
me["level"].setTextToNum(item.item_level);
@@ -1730,6 +1730,7 @@ static void save_item_info(cDialog& me, cItem& item) {
static bool edit_item_type_event_filter(cDialog& me, std::string hit, cItem& item, short& which) {
short i;
short which_before = which;
cItem temp_item;
std::string variety = dynamic_cast<cLedGroup&>(me["variety"]).getSelected();
bool valid = true;
@@ -1739,22 +1740,46 @@ static bool edit_item_type_event_filter(cDialog& me, std::string hit, cItem& ite
return true;
}
bool commit_changes = false;
if(hit == "cancel") {
me.toast(false);
} else if(hit == "okay") {
save_item_info(me, item);
if(!me.toast(true)) return true;
scenario.scen_items[which] = item;
commit_changes = true;
} else if(hit == "prev") {
save_item_info(me, item);
scenario.scen_items[which] = item;
if(item != scenario.scen_items[which]){
// Confirm keeping changes
cChoiceDlog dlog("confirm-edit-item", {"keep","revert","cancel"}, &me);
dlog->getControl("keep-msg").replaceText("{{item}}", item.full_name);
std::string choice = dlog.show();
if(choice == "keep" && me.toast(true)){
commit_changes = true;
}else if(choice == "cancel"){
return true;
}
me.untoast();
}
which--;
if(which < 0) which = scenario.scen_items.size() - 1;
item = scenario.scen_items[which];
put_item_info_in_dlog(me, item, which);
} else if(hit == "next") {
save_item_info(me, item);
scenario.scen_items[which] = item;
if(item != scenario.scen_items[which]){
// Confirm keeping changes
cChoiceDlog dlog("confirm-edit-item", {"keep","revert","cancel"}, &me);
dlog->getControl("keep-msg").replaceText("{{item}}", item.full_name);
std::string choice = dlog.show();
if(choice == "keep" && me.toast(true)){
commit_changes = true;
}else if(choice == "cancel"){
return true;
}
me.untoast();
}
which++;
if(which >= scenario.scen_items.size()) which = 0;
item = scenario.scen_items[which];
@@ -1829,6 +1854,13 @@ static bool edit_item_type_event_filter(cDialog& me, std::string hit, cItem& ite
value = choose_text_editable(scenario.itf_names, value, &me, "Select item type flag:");
me["flag"].setTextToNum(value);
}
if(commit_changes){
undo_list.add(action_ptr(new aEditClearItem("Edit Item Type", which_before, scenario.scen_items[which_before], item)));
update_edit_menu();
scenario.scen_items[which_before] = item;
}
return true;
}

View File

@@ -134,6 +134,18 @@ bool aEditClearMonster::redo_me() {
return true;
}
bool aEditClearItem::undo_me() {
// TODO show the type
scenario.scen_items[which] = before;
return true;
}
bool aEditClearItem::redo_me() {
// TODO show the type
scenario.scen_items[which] = after;
return true;
}
bool aCreateDeleteMonster::undo_me() {
// TODO if not in MODE_EDIT_TYPES, show it
for(cMonster monst : monsters){

View File

@@ -169,4 +169,16 @@ public:
cAction(name), which(which), before(before), after(after) {}
};
/// Action which edits or clears an item type
class aEditClearItem : public cAction {
item_num_t which;
class cItem before;
class cItem after;
bool undo_me() override;
bool redo_me() override;
public:
aEditClearItem(std::string name, mon_num_t which, class cItem before, class cItem after) :
cAction(name), which(which), before(before), after(after) {}
};
#endif