mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2026-08-08 08:48:50 +00:00
shmup:: replaced monsters_at with content lists
This commit is contained in:
@@ -249,6 +249,7 @@ EX int dirdiff(int dd, int t) {
|
||||
EX int cellcount = 0;
|
||||
|
||||
EX void destroy_cell(cell *c) {
|
||||
while(c->contents) c->contents->unlist_and_unref();
|
||||
tailored_delete(c);
|
||||
cellcount--;
|
||||
}
|
||||
|
||||
+1
-2
@@ -57,7 +57,6 @@ struct celldrawer {
|
||||
void draw();
|
||||
bool cell_clipped();
|
||||
void draw_fallanims();
|
||||
bool draw_shmup_monster();
|
||||
void draw_gravity_particles();
|
||||
|
||||
void set_land_floor(const shiftmatrix& Vf);
|
||||
@@ -2975,7 +2974,7 @@ void celldrawer::draw() {
|
||||
|
||||
Vboat = Vd;
|
||||
|
||||
draw_shmup_monster();
|
||||
FOR_LIST(li, c->contents) li->draw(self);
|
||||
|
||||
poly_outline = OUTLINE_DEFAULT;
|
||||
|
||||
|
||||
+43
-1
@@ -22,6 +22,45 @@ extern int cellcount, heptacount;
|
||||
#define NOBARRIERS 127
|
||||
#define NOBARRIERS2 125
|
||||
|
||||
using cell_content_list = struct cell_content*;
|
||||
|
||||
namespace shmup { struct monster; }
|
||||
|
||||
struct cell_content {
|
||||
cell_content *next;
|
||||
cell_content_list *last;
|
||||
virtual shmup::monster *as_monster() { return nullptr; }
|
||||
|
||||
void remove_from_list() {
|
||||
if(last) { last[0] = next; next->last = last; next = nullptr; last = nullptr; }
|
||||
}
|
||||
|
||||
void add_to_list(cell_content_list& l) {
|
||||
remove_from_list();
|
||||
last = &l;
|
||||
next = l;
|
||||
next->last = &next;
|
||||
l = this;
|
||||
}
|
||||
|
||||
int refs;
|
||||
cell_content() { refs = 1; }
|
||||
|
||||
virtual ~cell_content() {
|
||||
remove_from_list();
|
||||
}
|
||||
|
||||
void unref() {
|
||||
refs--;
|
||||
if(!refs) delete this;
|
||||
}
|
||||
|
||||
void unlist_and_unref() { remove_from_list(); unref(); }
|
||||
virtual void draw(struct celldrawer& cd) {}
|
||||
};
|
||||
|
||||
#define FOR_LIST(it, ml) for(cell_content *it = (ml); it; it = ml->next)
|
||||
|
||||
/** \brief Cell information for the game. struct cell builds on this */
|
||||
struct gcell {
|
||||
|
||||
@@ -98,11 +137,14 @@ struct gcell {
|
||||
#ifdef CELLID
|
||||
int cellid;
|
||||
#endif
|
||||
|
||||
cell_content_list contents;
|
||||
|
||||
gcell() {
|
||||
#ifdef CELLID
|
||||
cellid = cellcount;
|
||||
cellid = cellcount;
|
||||
#endif
|
||||
contents = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -67,12 +67,8 @@ EX void addradar(const shiftpoint h1, const shiftpoint h2, color_t col) {
|
||||
void celldrawer::drawcell_in_radar() {
|
||||
#if CAP_SHMUP
|
||||
if(shmup::on) {
|
||||
pair<shmup::mit, shmup::mit> p =
|
||||
shmup::monstersAt.equal_range(c);
|
||||
for(shmup::mit it = p.first; it != p.second; it++) {
|
||||
shmup::monster* m = it->second;
|
||||
FOR_LIST(it, c->contents) if(shmup::monster *m = it->as_monster())
|
||||
addradar(V*m->at, minf[m->type].glyph, minf[m->type].color, 0xFF0000FF);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(c->monst)
|
||||
|
||||
@@ -33,9 +33,13 @@ ld sqdist(shiftpoint a, shiftpoint b) {
|
||||
|
||||
EX namespace shmup {
|
||||
|
||||
EX hookset<void(struct monster*)> hooks_destroy_monster;
|
||||
|
||||
#if HDR
|
||||
|
||||
struct monster : dim_listener {
|
||||
extern struct monster *mousetarget, *lmousetarget;
|
||||
|
||||
struct monster : cell_content, dim_listener {
|
||||
eMonster type;
|
||||
cell *base; ///< on which base cell this monster currently is
|
||||
cell *torigin; ///< tortoises: origin, butterflies: last position
|
||||
@@ -60,18 +64,19 @@ struct monster : dim_listener {
|
||||
bool isVirtual; ///< off the screen: gmatrix is unknown, and pat equals at
|
||||
hyperpoint inertia;///< for frictionless lands
|
||||
|
||||
int refs; ///< +1 for every reference (parent, lists of active monsters)
|
||||
|
||||
int split_owner; ///< in splitscreen mode, which player handles this
|
||||
int split_tick; ///< in which tick was split_owner computed
|
||||
|
||||
void reset();
|
||||
|
||||
|
||||
monster *as_monster() override { return this; }
|
||||
void draw(celldrawer &cd) override;
|
||||
|
||||
monster() {
|
||||
reset();
|
||||
refs = 1; split_tick = -1; split_owner = -1;
|
||||
split_tick = -1; split_owner = -1;
|
||||
no_targetting = false;
|
||||
dead = false; inBoat = false; parent = NULL;
|
||||
dead = false; inBoat = false; parent = nullptr;
|
||||
}
|
||||
|
||||
eMonster get_parenttype() { return parent ? parent->type : moNone; }
|
||||
@@ -84,11 +89,15 @@ struct monster : dim_listener {
|
||||
|
||||
void rebasePat(const shiftmatrix& new_pat, cell *tgt);
|
||||
|
||||
void remove_reference();
|
||||
|
||||
~monster() {
|
||||
if(mousetarget == this) mousetarget = nullptr;
|
||||
if(lmousetarget == this) lmousetarget = nullptr;
|
||||
callhooks(hooks_destroy_monster, this);
|
||||
if(parent) parent->unref();
|
||||
}
|
||||
|
||||
void set_parent(monster *par) {
|
||||
if(parent == par) return;
|
||||
if(parent) parent->remove_reference();
|
||||
if(parent) parent->unref();
|
||||
parent = par;
|
||||
parent->refs++;
|
||||
}
|
||||
@@ -117,22 +126,9 @@ EX eLand delayed_safety_land;
|
||||
|
||||
bool lastdead = false;
|
||||
|
||||
EX multimap<cell*, monster*> monstersAt;
|
||||
EX cell_content_list active;
|
||||
|
||||
#if HDR
|
||||
typedef multimap<cell*, monster*>::iterator mit;
|
||||
#endif
|
||||
|
||||
EX vector<monster*> active, nonvirtual, additional;
|
||||
|
||||
void monster::remove_reference() {
|
||||
refs--;
|
||||
if(!refs) {
|
||||
if(parent) parent->remove_reference();
|
||||
nonvirtual.erase(std::remove(nonvirtual.begin(), nonvirtual.end(), this), nonvirtual.end());
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
EX vector<monster*> nonvirtual, additional;
|
||||
|
||||
cell *findbaseAround(shiftpoint p, cell *around, int maxsteps) {
|
||||
|
||||
@@ -170,9 +166,7 @@ cell *findbaseAround(const shiftmatrix& H, cell *around, int maxsteps) {
|
||||
return asinh(h[2]);
|
||||
} */
|
||||
|
||||
void monster::store() {
|
||||
monstersAt.insert(make_pair(base, this));
|
||||
}
|
||||
void monster::store() { add_to_list(base->contents); }
|
||||
|
||||
void monster::findpat() {
|
||||
isVirtual = !gmatrix.count(base) || invalid_matrix(gmatrix[base].T);
|
||||
@@ -1565,8 +1559,10 @@ EX bool verifyTeleport() {
|
||||
return true;
|
||||
}
|
||||
|
||||
#define FOR_MONSTERS_IN_LIST(it, m, ml) FOR_LIST(it, ml) if(monster *m = it->as_monster())
|
||||
|
||||
void destroyMimics() {
|
||||
for(monster *m: active)
|
||||
FOR_MONSTERS_IN_LIST(it, m, active)
|
||||
if(isMimic(m->type))
|
||||
m->dead = true;
|
||||
}
|
||||
@@ -2568,15 +2564,11 @@ void moveMonster(monster *m, int delta) {
|
||||
}
|
||||
}
|
||||
|
||||
void activateMonstersAt(cell *c) {
|
||||
pair<mit, mit> p =
|
||||
monstersAt.equal_range(c);
|
||||
for(mit it = p.first; it != p.second;) {
|
||||
mit itplus = it;
|
||||
itplus++;
|
||||
active.push_back(it->second);
|
||||
monstersAt.erase(it);
|
||||
it = itplus;
|
||||
void activate_monsters_at(cell *c) {
|
||||
auto p = &c->contents;
|
||||
while(*p) {
|
||||
if(monster *m = (*p)->as_monster()) m->add_to_list(active);
|
||||
else p = &((*p)->next);
|
||||
}
|
||||
if(c->monst && isMimic(c->monst)) c->monst = moNone;
|
||||
// mimics are awakened by awakenMimics
|
||||
@@ -2596,22 +2588,10 @@ void activateMonstersAt(cell *c) {
|
||||
enemy->inertia = random_spin() * point2(SCALE/3000., 0);
|
||||
}
|
||||
c->monst = moNone;
|
||||
active.push_back(enemy);
|
||||
enemy->add_to_list(active);
|
||||
}
|
||||
}
|
||||
|
||||
EX void fixStorage() {
|
||||
|
||||
vector<monster*> restore;
|
||||
|
||||
for(auto it = monstersAt.begin(); it != monstersAt.end(); it++)
|
||||
restore.push_back(it->second);
|
||||
|
||||
monstersAt.clear();
|
||||
|
||||
for(monster *m: restore) m->store();
|
||||
}
|
||||
|
||||
EX hookset<bool(int)> hooks_turn;
|
||||
|
||||
/** the amount of time chars are disabled in PvP */
|
||||
@@ -2687,28 +2667,24 @@ EX void turn(int delta) {
|
||||
|
||||
// detect active monsters
|
||||
if(doall)
|
||||
for(cell *c: currentmap->allcells()) activateMonstersAt(c);
|
||||
for(cell *c: currentmap->allcells()) activate_monsters_at(c);
|
||||
else
|
||||
for(auto& p: gmatrix)
|
||||
activateMonstersAt(p.first);
|
||||
|
||||
/* printf("size: gmatrix = %ld, active = %ld, monstersAt = %ld, delta = %d\n",
|
||||
gmatrix.size(), active.size(), monstersAt.size(),
|
||||
delta); */
|
||||
activate_monsters_at(p.first);
|
||||
|
||||
bool exists[motypes];
|
||||
|
||||
for(int i=0; i<motypes; i++) exists[i] = false;
|
||||
|
||||
nonvirtual.clear();
|
||||
for(monster *m: active) {
|
||||
nonvirtual.clear();
|
||||
FOR_MONSTERS_IN_LIST(it, m, active) {
|
||||
m->findpat();
|
||||
if(m->isVirtual) continue;
|
||||
else nonvirtual.push_back(m);
|
||||
exists[movegroup(m->type)] = true;
|
||||
}
|
||||
|
||||
for(monster *m: active) {
|
||||
FOR_MONSTERS_IN_LIST(it, m, active) {
|
||||
|
||||
switch(m->type) {
|
||||
case moPlayer:
|
||||
@@ -2724,7 +2700,7 @@ EX void turn(int delta) {
|
||||
}
|
||||
}
|
||||
|
||||
for(monster *m: active) {
|
||||
FOR_MONSTERS_IN_LIST(it, m, active) {
|
||||
if(isMimic(m->type))
|
||||
moveMimic(m);
|
||||
}
|
||||
@@ -2886,8 +2862,7 @@ EX void turn(int delta) {
|
||||
}
|
||||
}
|
||||
|
||||
for(monster *m: additional)
|
||||
active.push_back(m);
|
||||
for(monster *m: additional) m->add_to_list(active);
|
||||
additional.clear();
|
||||
|
||||
if(delayed_safety) {
|
||||
@@ -2895,18 +2870,13 @@ EX void turn(int delta) {
|
||||
delayed_safety = false;
|
||||
}
|
||||
|
||||
// deactivate all monsters
|
||||
for(monster *m: active)
|
||||
if(m->dead && m->type != moPlayer) {
|
||||
if(m == mousetarget) mousetarget = NULL;
|
||||
if(m == lmousetarget) lmousetarget = NULL;
|
||||
m->remove_reference();
|
||||
}
|
||||
else {
|
||||
while(active) {
|
||||
auto *m = (monster*) active;
|
||||
if(m->dead && m->type != moPlayer)
|
||||
m->unlist_and_unref();
|
||||
else
|
||||
m->store();
|
||||
}
|
||||
|
||||
active.clear();
|
||||
}
|
||||
}
|
||||
|
||||
EX void recall() {
|
||||
@@ -2954,29 +2924,13 @@ EX void init() {
|
||||
}
|
||||
|
||||
EX bool boatAt(cell *c) {
|
||||
pair<mit, mit> p =
|
||||
monstersAt.equal_range(c);
|
||||
for(mit it = p.first; it != p.second; it++) {
|
||||
monster* m = it->second;
|
||||
if(m->inBoat) return true;
|
||||
}
|
||||
FOR_MONSTERS_IN_LIST(it, m, c->contents) if(m->inBoat) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
EX hookset<bool(const shiftmatrix&, cell*, shmup::monster*)> hooks_draw;
|
||||
|
||||
EX void clearMonsters() {
|
||||
for(mit it = monstersAt.begin(); it != monstersAt.end(); it++)
|
||||
delete(it->second);
|
||||
for(monster *m: active) m->remove_reference();
|
||||
mousetarget = NULL;
|
||||
lmousetarget = NULL;
|
||||
monstersAt.clear();
|
||||
active.clear();
|
||||
}
|
||||
|
||||
EX void clearMemory() {
|
||||
clearMonsters();
|
||||
while(!traplist.empty()) traplist.pop();
|
||||
curtime = 0;
|
||||
speed_saving = 0;
|
||||
@@ -2995,7 +2949,6 @@ void gamedata(hr::gamedata* gd) {
|
||||
gd->store(nextdragon);
|
||||
gd->store(visibleAt);
|
||||
gd->store(traplist);
|
||||
gd->store(monstersAt);
|
||||
gd->store(active);
|
||||
gd->store(mousetarget);
|
||||
gd->store(lmousetarget);
|
||||
@@ -3018,7 +2971,7 @@ EX bool playerInBoat(int i) {
|
||||
}
|
||||
|
||||
EX void destroyBoats(cell *c) {
|
||||
for(monster *m: active)
|
||||
FOR_MONSTERS_IN_LIST(it, m, active)
|
||||
if(m->base == c && m->inBoat)
|
||||
m->inBoat = false;
|
||||
}
|
||||
@@ -3039,17 +2992,7 @@ EX void addShmupHelp(string& out) {
|
||||
}
|
||||
|
||||
auto hooks = addHook(hooks_clearmemory, 0, shmup::clearMemory) +
|
||||
addHook(hooks_gamedata, 0, shmup::gamedata) +
|
||||
addHook(hooks_removecells, 0, [] () {
|
||||
for(mit it = monstersAt.begin(); it != monstersAt.end();) {
|
||||
if(is_cell_removed(it->first)) {
|
||||
monstersAt.insert(make_pair(nullptr, it->second));
|
||||
auto it0 = it; it++;
|
||||
monstersAt.erase(it0);
|
||||
}
|
||||
else it++;
|
||||
}
|
||||
});
|
||||
addHook(hooks_gamedata, 0, shmup::gamedata);
|
||||
|
||||
EX void switch_shmup() {
|
||||
stop_game();
|
||||
@@ -3071,21 +3014,19 @@ EX void draw_collision_debug() {
|
||||
|
||||
EX }
|
||||
|
||||
bool celldrawer::draw_shmup_monster() {
|
||||
using namespace shmup;
|
||||
void shmup::monster::draw(struct hr::celldrawer& cd) {
|
||||
#if CAP_SHAPES
|
||||
using namespace shmup;
|
||||
|
||||
auto m = this;
|
||||
cell *c = cd.c;
|
||||
auto& Vd = cd.Vd;
|
||||
auto& V = cd.V;
|
||||
auto& Vboat = cd.Vboat;
|
||||
|
||||
pair<mit, mit> p =
|
||||
monstersAt.equal_range(c);
|
||||
|
||||
if(p.first == p.second) return false;
|
||||
ld zlev = -geom3::factor_to_lev(zlevel(tC0(Vd.T)));
|
||||
|
||||
vector<monster*> monsters;
|
||||
|
||||
for(mit it = p.first; it != p.second; it++) {
|
||||
monster* m = it->second;
|
||||
if(c != m->base) continue; // may happen in RogueViz Collatz
|
||||
if(1) {
|
||||
m->pat = ggmatrix(m->base) * m->at;
|
||||
shiftmatrix view = V * m->at;
|
||||
|
||||
@@ -3097,7 +3038,7 @@ bool celldrawer::draw_shmup_monster() {
|
||||
|
||||
bool half_elliptic = elliptic && GDIM == 3 && WDIM == 2;
|
||||
bool mirrored = det(view.T) > 0;
|
||||
if(half_elliptic && mirrored) continue;
|
||||
if(half_elliptic && mirrored) return;
|
||||
|
||||
if(!mouseout()) {
|
||||
if(m->no_targetting) ; else
|
||||
@@ -3133,7 +3074,7 @@ bool celldrawer::draw_shmup_monster() {
|
||||
int q = isize(ptds);
|
||||
if(q != isize(ptds) && !m->inBoat) pushdown(c, q, view, zlev, true, false);
|
||||
|
||||
if(callhandlers(false, hooks_draw, V, c, m)) continue;
|
||||
if(callhandlers(false, hooks_draw, V, c, m)) return;
|
||||
|
||||
switch(m->type) {
|
||||
case moPlayer: {
|
||||
@@ -3284,7 +3225,6 @@ bool celldrawer::draw_shmup_monster() {
|
||||
}
|
||||
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user