undo/redo place/erase creatures
This commit is contained in:
@@ -713,6 +713,7 @@ stroke_ter_changes_t current_stroke_changes;
|
||||
std::string current_stroke_type;
|
||||
|
||||
item_changes_t current_items_placed;
|
||||
creature_changes_t current_creatures_placed;
|
||||
|
||||
void commit_stroke() {
|
||||
if(!current_stroke_changes.empty()){
|
||||
@@ -724,6 +725,10 @@ void commit_stroke() {
|
||||
undo_list.add(action_ptr(new aPlaceEraseItem(current_items_placed.size() > 1 ? "Place Items" : "Place Item", true, current_items_placed)));
|
||||
update_edit_menu();
|
||||
current_items_placed.clear();
|
||||
}else if(!current_creatures_placed.empty()){
|
||||
undo_list.add(action_ptr(new aPlaceEraseCreature(current_creatures_placed.size() > 1 ? "Place Creatures" : "Place Creature", true, current_creatures_placed)));
|
||||
update_edit_menu();
|
||||
current_items_placed.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -936,16 +941,10 @@ static bool handle_terrain_action(location the_point, bool ctrl_hit) {
|
||||
set_string("Paste monster","Not while outdoors.");
|
||||
break;
|
||||
}
|
||||
auto iter = std::find_if(town->creatures.begin(), town->creatures.end(), [](const cTownperson& who) {
|
||||
return who.number == 0;
|
||||
});
|
||||
if(iter != town->creatures.end()) {
|
||||
*iter = *monst;
|
||||
iter->start_loc = spot_hit;
|
||||
} else { // Placement failed
|
||||
town->creatures.push_back(*monst);
|
||||
town->creatures.back().start_loc = spot_hit;
|
||||
}
|
||||
place_creature(spot_hit, static_cast<mon_num_t>(mode_count), current_creatures_placed);
|
||||
undo_list.add(action_ptr(new aPlaceEraseCreature("Paste Creature", true, current_creatures_placed)));
|
||||
update_edit_menu();
|
||||
current_creatures_placed.clear();
|
||||
} else if(auto item = boost::get<cTown::cItem>(&clipboard)) {
|
||||
if(!editing_town) {
|
||||
set_string("Paste item","Not while outdoors.");
|
||||
@@ -968,14 +967,7 @@ static bool handle_terrain_action(location the_point, bool ctrl_hit) {
|
||||
// If we just placed this same creature here, forget it
|
||||
if(!mouse_button_held || last_placement != spot_hit) {
|
||||
mouse_button_held = true;
|
||||
auto iter = std::find_if(town->creatures.begin(), town->creatures.end(), [](const cTownperson& who) {
|
||||
return who.number == 0;
|
||||
});
|
||||
if(iter != town->creatures.end()) {
|
||||
*iter = {spot_hit, static_cast<mon_num_t>(mode_count), scenario.scen_monsters[mode_count]};
|
||||
} else { // Placement failed
|
||||
town->creatures.push_back({spot_hit, static_cast<mon_num_t>(mode_count), scenario.scen_monsters[mode_count]});
|
||||
}
|
||||
place_creature(spot_hit, static_cast<mon_num_t>(mode_count), current_creatures_placed);
|
||||
last_placement = spot_hit;
|
||||
}
|
||||
break;
|
||||
@@ -1132,11 +1124,11 @@ static bool handle_terrain_action(location the_point, bool ctrl_hit) {
|
||||
case MODE_ERASE_CREATURE: //delete monst
|
||||
for(short x = 0; x < town->creatures.size(); x++)
|
||||
if(monst_on_space(spot_hit,x)) {
|
||||
undo_list.add(action_ptr(new aPlaceEraseCreature("Erase Creature", false, x, town->creatures[x])));
|
||||
update_edit_menu();
|
||||
town->creatures[x].number = 0;
|
||||
break;
|
||||
}
|
||||
while(!town->creatures.empty() && town->creatures.back().number == 0)
|
||||
town->creatures.pop_back();
|
||||
overall_mode = MODE_DRAWING;
|
||||
break;
|
||||
case MODE_ERASE_ITEM: // delete item
|
||||
@@ -2487,6 +2479,22 @@ void place_items_in_town() {
|
||||
draw_terrain();
|
||||
}
|
||||
|
||||
bool place_creature(location spot_hit, mon_num_t which, creature_changes_t& creatures_placed) {
|
||||
for(short x = 0; x <= town->creatures.size(); x++){
|
||||
if(x == town->creatures.size()){
|
||||
town->creatures.resize(x+1);
|
||||
town->creatures[x].number = 0;
|
||||
}
|
||||
if(town->creatures[x].number == 0) {
|
||||
town->creatures[x] = {spot_hit, which, scenario.scen_monsters[which]};
|
||||
creatures_placed[x] = town->creatures[x];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Shouldn't be reached:
|
||||
return false;
|
||||
}
|
||||
|
||||
void place_edit_special(location loc) {
|
||||
if(!editing_town && (loc.x == 0 || loc.x == 47 || loc.y == 0 || loc.y == 47)) {
|
||||
cChoiceDlog("not-at-edge").show();
|
||||
|
@@ -28,8 +28,9 @@ void adjust_space(location l,stroke_ter_changes_t& stroke_changes);
|
||||
void commit_stroke();
|
||||
bool is_lava(short x,short y);
|
||||
ter_num_t coord_to_ter(short x,short y);
|
||||
bool place_item(location spot_hit,short which_item,bool property,bool always,short odds,std::map<size_t,cTown::cItem>& items_placed);
|
||||
bool place_item(location spot_hit,short which_item,bool property,bool always,short odds,item_changes_t& items_placed);
|
||||
void place_items_in_town();
|
||||
bool place_creature(location spot_hit,mon_num_t which,creature_changes_t& creatures_placed);
|
||||
void set_up_start_screen();
|
||||
void set_up_main_screen();
|
||||
void start_town_edit();
|
||||
|
@@ -91,6 +91,8 @@ static bool edit_placed_monst_event_filter(cDialog& me, std::string hit, cTownpe
|
||||
me.toast(false);
|
||||
} else if(hit == "del") {
|
||||
me.toast(false);
|
||||
undo_list.add(action_ptr(new aPlaceEraseCreature("Delete Creature", false, which, town->creatures[which])));
|
||||
update_edit_menu();
|
||||
town->creatures[which].number = 0;
|
||||
} else if(hit == "type-edit") {
|
||||
get_placed_monst_in_dlog(me, monst);
|
||||
|
@@ -134,3 +134,29 @@ bool aPlaceEraseItem::redo_me() {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
aPlaceEraseCreature::aPlaceEraseCreature(std::string name, bool place, size_t index, cTownperson creature)
|
||||
: cTerrainAction(name, creature.start_loc, !place)
|
||||
, creatures({{index, creature}})
|
||||
{}
|
||||
|
||||
aPlaceEraseCreature::aPlaceEraseCreature(std::string name, bool place, creature_changes_t creatures)
|
||||
: cTerrainAction(name, creatures.begin()->second.start_loc, !place)
|
||||
, creatures(creatures)
|
||||
{}
|
||||
|
||||
bool aPlaceEraseCreature::undo_me() {
|
||||
auto& town_creatures = scenario.towns[cur_town]->creatures;
|
||||
for(auto change : creatures){
|
||||
town_creatures[change.first].number = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool aPlaceEraseCreature::redo_me() {
|
||||
auto& town_creatures = scenario.towns[cur_town]->creatures;
|
||||
for(auto change : creatures){
|
||||
town_creatures[change.first] = change.second;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@@ -20,6 +20,7 @@ struct ter_change_t {
|
||||
|
||||
typedef std::map<location,ter_change_t,loc_compare> stroke_ter_changes_t;
|
||||
typedef std::map<size_t, cTown::cItem> item_changes_t;
|
||||
typedef std::map<size_t, cTownperson> creature_changes_t;
|
||||
|
||||
// Action that modified something in town or outdoor terrain, so we should show the modified area when undoing or redoing
|
||||
class cTerrainAction : public cAction {
|
||||
@@ -71,6 +72,17 @@ public:
|
||||
aPlaceEraseItem(std::string name, bool place, size_t index, cTown::cItem item);
|
||||
};
|
||||
|
||||
/// Action which places or erases creature(s) in a town
|
||||
class aPlaceEraseCreature : public cTerrainAction {
|
||||
bool placed;
|
||||
creature_changes_t creatures;
|
||||
bool undo_me() override;
|
||||
bool redo_me() override;
|
||||
public:
|
||||
aPlaceEraseCreature(std::string name, bool place, creature_changes_t creatures);
|
||||
aPlaceEraseCreature(std::string name, bool place, size_t index, cTownperson creature);
|
||||
};
|
||||
|
||||
/// Action which adds a new town to the end of the list, or deletes the last one
|
||||
class aCreateDeleteTown : public cAction {
|
||||
bool created;
|
||||
|
Reference in New Issue
Block a user