universe: try to simplify the code...
This commit is contained in:
@@ -998,71 +998,6 @@ void cCurTown::swap(cCurTown& other) {
|
||||
memcpy(fields, temp, sizeof(fields));
|
||||
}
|
||||
|
||||
void cUniverse::check_monst(cMonster& monst) {
|
||||
if(monst.see_spec == -2) return; // Avoid infinite recursion
|
||||
monst.see_spec = -2;
|
||||
if(monst.picture_num >= 10000) {
|
||||
int pic = monst.picture_num - 10000;
|
||||
int sz = pic / 1000, base = pic % 1000;
|
||||
int numGraph = 4;
|
||||
if(sz > 1) numGraph *= 2;
|
||||
if(sz == 4) numGraph *= 2;
|
||||
for(int i = 0; i < numGraph; i++)
|
||||
used_graphics.insert(base + i);
|
||||
} else if(monst.picture_num >= 1000) {
|
||||
update_monsters[monst.picture_num - 1000].insert(&monst);
|
||||
}
|
||||
for(auto& abil : monst.abil) {
|
||||
switch(getMonstAbilCategory(abil.first)) {
|
||||
case eMonstAbilCat::MISSILE:
|
||||
if(abil.second.missile.pic >= 10000) {
|
||||
for(int i = 0; i < 4; i++)
|
||||
used_graphics.insert(abil.second.missile.pic - 10000 + i);
|
||||
} else if(abil.second.missile.pic >= 1000) {
|
||||
update_missiles[abil.second.missile.pic - 1000].insert(&abil.second.missile.pic);
|
||||
}
|
||||
break;
|
||||
case eMonstAbilCat::GENERAL:
|
||||
if(abil.second.gen.pic >= 10000) {
|
||||
for(int i = 0; i < 4; i++)
|
||||
used_graphics.insert(abil.second.gen.pic - 10000 + i);
|
||||
} else if(abil.second.gen.pic >= 1000) {
|
||||
update_missiles[abil.second.gen.pic - 1000].insert(&abil.second.gen.pic);
|
||||
}
|
||||
break;
|
||||
case eMonstAbilCat::SUMMON:
|
||||
if(abil.second.summon.type == eMonstSummon::TYPE)
|
||||
check_monst(scenario.scen_monsters[abil.second.summon.what]);
|
||||
break;
|
||||
case eMonstAbilCat::RADIATE:
|
||||
case eMonstAbilCat::SPECIAL:
|
||||
case eMonstAbilCat::INVALID:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cUniverse::check_item(cItem& item) {
|
||||
if(item.variety == eItemType::NO_ITEM) return;
|
||||
if(item.graphic_num >= 10000)
|
||||
used_graphics.insert(item.graphic_num - 10000);
|
||||
else if(item.graphic_num >= 1000)
|
||||
update_items[item.graphic_num - 1000].insert(&item);
|
||||
if(item.ability == eItemAbil::SUMMONING || item.ability == eItemAbil::MASS_SUMMONING) {
|
||||
mon_num_t monst = item.abil_data[1];
|
||||
if(monst >= 10000)
|
||||
check_monst(party.summons[monst - 10000]);
|
||||
else check_monst(scenario.scen_monsters[monst]);
|
||||
}
|
||||
if(item.variety == eItemType::ARROW || item.variety == eItemType::BOLTS || item.variety == eItemType::MISSILE_NO_AMMO || item.variety == eItemType::THROWN_MISSILE) {
|
||||
if(item.missile >= 10000)
|
||||
for(int i = 0; i < 4; i++)
|
||||
used_graphics.insert(item.missile - 10000 + i);
|
||||
else if(item.missile >= 1000)
|
||||
update_missiles[item.missile - 1000].insert(&item.missile);
|
||||
}
|
||||
}
|
||||
|
||||
// This attempts to find the index of a living entity in the party or town
|
||||
// Assuming success, the two get_target() calls are a round-trip
|
||||
// Returns maxint on failure (which could happen eg with a stored PC or a monster from a saved town)
|
||||
@@ -1116,9 +1051,23 @@ unsigned char& cUniverse::cpn_flag(unsigned int x, unsigned int y, std::string i
|
||||
return party.campaign_flags[id].idx[x][y];
|
||||
}
|
||||
|
||||
extern cCustomGraphics spec_scen_g;
|
||||
struct cCustomUpdateState {
|
||||
template<typename T> using update_info = std::set<T *>;
|
||||
std::map<pic_num_t, update_info<cItem>> items;
|
||||
std::map<pic_num_t, update_info<cMonster>> monsters;
|
||||
std::map<pic_num_t, update_info<cPlayer>> pcs;
|
||||
std::map<pic_num_t, update_info<miss_num_t>> missiles;
|
||||
std::set<pic_num_t> graphics;
|
||||
|
||||
std::set<cItem const *> seenItem;
|
||||
std::set<cMonster const *> seenMonster;
|
||||
pic_num_t add_graphic(pic_num_t pic, ePicType type);
|
||||
void check_monst(cUniverse &univers, cMonster & monst);
|
||||
void check_item(cUniverse &univers, cItem& item);
|
||||
};
|
||||
|
||||
pic_num_t cUniverse::addGraphic(pic_num_t pic, ePicType type) {
|
||||
extern cCustomGraphics spec_scen_g;
|
||||
pic_num_t cCustomUpdateState::add_graphic(pic_num_t pic, ePicType type) {
|
||||
// Now find the first unused slot with sufficient space for the graphic we're adding
|
||||
int needSlots = 0;
|
||||
switch(type - PIC_PARTY) {
|
||||
@@ -1135,22 +1084,89 @@ pic_num_t cUniverse::addGraphic(pic_num_t pic, ePicType type) {
|
||||
bool foundSpace = false;
|
||||
while(!foundSpace) {
|
||||
// First find an empty slot.
|
||||
while(used_graphics.count(++pos));
|
||||
while(graphics.count(++pos));
|
||||
// Then check if there's enough space.
|
||||
foundSpace = true;
|
||||
for(pic_num_t i = 1; i < needSlots; i++) {
|
||||
if(used_graphics.count(pos + i)) foundSpace = false;
|
||||
if(graphics.count(pos + i)) foundSpace = false;
|
||||
}
|
||||
}
|
||||
// And finally, actually transfer the graphic over
|
||||
spec_scen_g.copy_graphic(pos, pic, needSlots);
|
||||
// Also mark these slots used so we don't overwrite them with the next copy
|
||||
for(pic_num_t i = 0; i < needSlots; i++) {
|
||||
used_graphics.insert(pos + i);
|
||||
graphics.insert(pos + i);
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
void cCustomUpdateState::check_monst(cUniverse &univers, cMonster & monst) {
|
||||
if (seenMonster.count(&monst)) return; // Avoid infinite recursion
|
||||
seenMonster.insert(&monst);
|
||||
if(monst.picture_num >= 10000) {
|
||||
int pic = monst.picture_num - 10000;
|
||||
int sz = pic / 1000, base = pic % 1000;
|
||||
int numGraph = 4;
|
||||
if(sz > 1) numGraph *= 2;
|
||||
if(sz == 4) numGraph *= 2;
|
||||
for(int i = 0; i < numGraph; i++)
|
||||
graphics.insert(base + i);
|
||||
} else if(monst.picture_num >= 1000) {
|
||||
monsters[monst.picture_num - 1000].insert(&monst);
|
||||
}
|
||||
for(auto& abil : monst.abil) {
|
||||
switch(getMonstAbilCategory(abil.first)) {
|
||||
case eMonstAbilCat::MISSILE:
|
||||
if(abil.second.missile.pic >= 10000) {
|
||||
for(int i = 0; i < 4; i++)
|
||||
graphics.insert(abil.second.missile.pic - 10000 + i);
|
||||
} else if(abil.second.missile.pic >= 1000) {
|
||||
missiles[abil.second.missile.pic - 1000].insert(&abil.second.missile.pic);
|
||||
}
|
||||
break;
|
||||
case eMonstAbilCat::GENERAL:
|
||||
if(abil.second.gen.pic >= 10000) {
|
||||
for(int i = 0; i < 4; i++)
|
||||
graphics.insert(abil.second.gen.pic - 10000 + i);
|
||||
} else if(abil.second.gen.pic >= 1000) {
|
||||
missiles[abil.second.gen.pic - 1000].insert(&abil.second.gen.pic);
|
||||
}
|
||||
break;
|
||||
case eMonstAbilCat::SUMMON:
|
||||
if(abil.second.summon.type == eMonstSummon::TYPE)
|
||||
check_monst(univers, univers.scenario.scen_monsters[abil.second.summon.what]);
|
||||
break;
|
||||
case eMonstAbilCat::RADIATE:
|
||||
case eMonstAbilCat::SPECIAL:
|
||||
case eMonstAbilCat::INVALID:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cCustomUpdateState::check_item(cUniverse &universe, cItem& item) {
|
||||
if (seenItem.count(&item)) return;
|
||||
seenItem.insert(&item);
|
||||
if(item.variety == eItemType::NO_ITEM) return;
|
||||
if(item.graphic_num >= 10000)
|
||||
graphics.insert(item.graphic_num - 10000);
|
||||
else if(item.graphic_num >= 1000)
|
||||
items[item.graphic_num - 1000].insert(&item);
|
||||
if(item.ability == eItemAbil::SUMMONING || item.ability == eItemAbil::MASS_SUMMONING) {
|
||||
mon_num_t monst = item.abil_data[1];
|
||||
if(monst >= 10000)
|
||||
check_monst(universe, universe.party.summons[monst - 10000]);
|
||||
else check_monst(universe, universe.scenario.scen_monsters[monst]);
|
||||
}
|
||||
if(item.variety == eItemType::ARROW || item.variety == eItemType::BOLTS || item.variety == eItemType::MISSILE_NO_AMMO || item.variety == eItemType::THROWN_MISSILE) {
|
||||
if(item.missile >= 10000)
|
||||
for(int i = 0; i < 4; i++)
|
||||
graphics.insert(item.missile - 10000 + i);
|
||||
else if(item.missile >= 1000)
|
||||
missiles[item.missile - 1000].insert(&item.missile);
|
||||
}
|
||||
}
|
||||
|
||||
void cUniverse::exportGraphics() {
|
||||
// First determine which graphics are used, and which need to be copied.
|
||||
// The party sheet can contain the following types of graphics:
|
||||
@@ -1159,47 +1175,44 @@ void cUniverse::exportGraphics() {
|
||||
// - Custom PC graphics
|
||||
// TODO: Missile graphics for custom monsters
|
||||
// So basically, almost all the graphics are linked to items.
|
||||
used_graphics.clear();
|
||||
cCustomUpdateState state;
|
||||
for(int i = 0; i < 6; i++) {
|
||||
if(party[i].main_status == eMainStatus::ABSENT)
|
||||
continue;
|
||||
if(party[i].which_graphic >= 10000) {
|
||||
for(int j = 0; j < 4; j++)
|
||||
used_graphics.insert(party[i].which_graphic - 10000 + j);
|
||||
state.graphics.insert(party[i].which_graphic - 10000 + j);
|
||||
} else if(party[i].which_graphic >= 1000)
|
||||
update_pcs[party[i].which_graphic - 1000].insert(&party[i]);
|
||||
state.pcs[party[i].which_graphic - 1000].insert(&party[i]);
|
||||
for (auto &item : party[i].items)
|
||||
check_item(item);
|
||||
state.check_item(*this, item);
|
||||
}
|
||||
for (auto &items : party.stored_items)
|
||||
for (auto &item : items)
|
||||
check_item(item);
|
||||
state.check_item(*this, item);
|
||||
for(mon_num_t monst : party.imprisoned_monst) {
|
||||
if(monst > 0 && monst < scenario.scen_monsters.size())
|
||||
check_monst(scenario.scen_monsters[monst]);
|
||||
state.check_monst(*this, scenario.scen_monsters[monst]);
|
||||
else if(monst >= 10000 && monst - 10000 < party.summons.size())
|
||||
check_monst(party.summons[monst - 10000]);
|
||||
state.check_monst(*this, party.summons[monst - 10000]);
|
||||
}
|
||||
// And then, just add all the graphics, and update references to them
|
||||
for(auto pic : update_pcs) {
|
||||
pic_num_t pos = addGraphic(pic.first, PIC_PC);
|
||||
for(auto const &pic : state.pcs) {
|
||||
pic_num_t pos = state.add_graphic(pic.first, PIC_PC);
|
||||
for(auto& pc : pic.second)
|
||||
pc->which_graphic = 10000 + pos;
|
||||
}
|
||||
update_pcs.clear();
|
||||
for(auto pic : update_items) {
|
||||
pic_num_t pos = addGraphic(pic.first, PIC_ITEM);
|
||||
for(auto const &pic : state.items) {
|
||||
pic_num_t pos = state.add_graphic(pic.first, PIC_ITEM);
|
||||
for(auto& item : pic.second)
|
||||
item->graphic_num = 10000 + pos;
|
||||
}
|
||||
update_items.clear();
|
||||
for(auto pic : update_missiles) {
|
||||
pic_num_t pos = addGraphic(pic.first, PIC_MISSILE);
|
||||
for(auto const &pic : state.missiles) {
|
||||
pic_num_t pos = state.add_graphic(pic.first, PIC_MISSILE);
|
||||
for(auto& missile : pic.second)
|
||||
*missile = 10000 + pos;
|
||||
}
|
||||
update_missiles.clear();
|
||||
for(auto pic : update_monsters) {
|
||||
for(auto const &pic : state.monsters) {
|
||||
int sz = pic.first / 1000, base = pic.first % 1000;
|
||||
ePicType type;
|
||||
switch(sz) {
|
||||
@@ -1209,16 +1222,15 @@ void cUniverse::exportGraphics() {
|
||||
case 4: type = PIC_MONST_LG; break;
|
||||
default: continue;
|
||||
}
|
||||
pic_num_t pos = addGraphic(base, type);
|
||||
pic_num_t pos = state.add_graphic(base, type);
|
||||
for(auto& monst : pic.second)
|
||||
monst->picture_num = 10000 + sz * 1000 + pos;
|
||||
}
|
||||
update_monsters.clear();
|
||||
}
|
||||
|
||||
void cUniverse::exportSummons() {
|
||||
std::set<mon_num_t> used_monsters, need_monsters;
|
||||
std::map<mon_num_t, update_info<cItem>> update_items;
|
||||
std::map<mon_num_t, std::set<cItem *>> update_items;
|
||||
for(int i = 0; i < 6; i++) {
|
||||
if(party[i].main_status == eMainStatus::ABSENT)
|
||||
continue;
|
||||
|
@@ -165,16 +165,6 @@ public:
|
||||
enum eTargetType {TARG_ANY, TARG_PC, TARG_MONST};
|
||||
|
||||
class cUniverse{
|
||||
template<typename T> using update_info = std::set<T*>;
|
||||
// All these maps are transient data that doesn't need to be saved
|
||||
std::map<pic_num_t, update_info<cItem>> update_items;
|
||||
std::map<pic_num_t, update_info<cMonster>> update_monsters;
|
||||
std::map<pic_num_t, update_info<cPlayer>> update_pcs;
|
||||
std::map<pic_num_t, update_info<miss_num_t>> update_missiles;
|
||||
std::set<pic_num_t> used_graphics;
|
||||
pic_num_t addGraphic(pic_num_t pic, ePicType type);
|
||||
void check_monst(cMonster& monst);
|
||||
void check_item(cItem& item);
|
||||
// The string buffer currently isn't saved
|
||||
std::string strbuf;
|
||||
std::map<int,std::string> extrabufs;
|
||||
|
Reference in New Issue
Block a user