From 8c2b717223df6303b7583c3713b0f75eec3bb5e5 Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Wed, 15 May 2019 14:19:19 +0200 Subject: [PATCH] monster orientation is now modelled in non-orientable geometries --- complex.cpp | 2 +- game.cpp | 10 ++++++++-- graph.cpp | 28 ++++++++++++++++++++++++++-- hyper.h | 4 +++- monstergen.cpp | 4 +++- 5 files changed, 41 insertions(+), 7 deletions(-) diff --git a/complex.cpp b/complex.cpp index 93cddb6e..83ff02b4 100644 --- a/complex.cpp +++ b/complex.cpp @@ -2786,7 +2786,7 @@ namespace kraken { vector > acells; acells.push_back(make_pair(c2, c)); forCellIdEx(c3, i, c) { - c3->monst = moKrakenT, c3->mondir = c->c.spin(i), onpath(c3, 0); + c3->monst = moKrakenT, c3->mondir = c->c.spin(i), c3->monmirror = c->monmirror ^ c->c.mirror(i), onpath(c3, 0); int i0 = (i+c->c.spin(c->mondir)-c->mondir+96+c->type/2) % c2->type; c3->hitpoints = hpcount[i0]; acells.push_back(make_pair(c2->move(i0), c3)); diff --git a/game.cpp b/game.cpp index dd4db339..f56da0aa 100644 --- a/game.cpp +++ b/game.cpp @@ -188,6 +188,7 @@ void initcell(cell *c) { c->land = laNone; c->ligon = 0; c->stuntime = 0; + c->monmirror = 0; } bool doesnotFall(cell *c) { @@ -3664,8 +3665,11 @@ void moveMonster(cell *ct, cell *cf, int direction_hint) { ct->monst = m; if(m == moWolf) ct->monst = moWolfMoved; if(m == moHunterChanging) ct->stuntime = 1; + int d =neighborId(ct, cf); if(ct->monst != moTentacleGhost) - ct->mondir = neighborId(ct, cf); + ct->mondir = d; + if(d >= 0) + ct->monmirror = cf->monmirror ^ ct->c.mirror(d); } ct->hitpoints = cf->hitpoints; ct->stuntime = cf->stuntime; @@ -4553,6 +4557,7 @@ void moveWorm(cell *c) { animateMovement(c, goal, LAYER_BIG, dir); c->monst = eMonster(moWormtail + id); goal->mondir = c->c.spin(j); + goal->monmirror = c->monmirror ^ c->c.mirror(j); mountmove(goal, goal->mondir, true, c); @@ -4589,7 +4594,7 @@ void moveWorm(cell *c) { } void ivynext(cell *c) { - cellwalker cw(c, c->mondir); + cellwalker cw(c, c->mondir, c->monmirror); // check the mirroring status cell *c2 = c; @@ -4683,6 +4688,7 @@ void moveivy() { if(mto && mto->cpdist) { animateMovement(mto->move(sp), mto, LAYER_BIG, mto->c.spin(sp)); mto->monst = moIvyWait, mto->mondir = sp; + mto->monmirror = c->monmirror ^ c->c.mirror(sp); moveEffect(mto, NULL, moIvyWait, NOHINT); // if this is the only branch, we want to move the head immediately to mto instead if(mto->move(mto->mondir)->monst == moIvyHead) { diff --git a/graph.cpp b/graph.cpp index 7443ca96..6a76891e 100644 --- a/graph.cpp +++ b/graph.cpp @@ -2196,6 +2196,7 @@ bool applyAnimation(cell *c, transmatrix& V, double& footphase, int layer) { a.footphase += a.attacking == 2 ? -aspd : aspd; footphase = a.footphase; V = V * a.wherenow; + if(a.mirrored) V = V * Mirror; if(a.attacking == 2) V = V * pispin; // if(DIM == 3) V = V * cspin(0, 2, M_PI/2); a.ltick = ticks; @@ -2297,9 +2298,11 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, bool m eMonster m = c->monst; + bool half_elliptic = elliptic && GDIM == 3 && WDIM == 2; + if(!m) ; - else if(elliptic && GDIM == 3 && WDIM == 2 && mirrored) ; + else if(half_elliptic && mirrored != c->monmirror && !isMimic(m)) ; else if(isAnyIvy(c) || isWorm(c)) { @@ -2336,6 +2339,8 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, bool m length = cellgfxdist(c, c->mondir); } + if(c->monmirror) Vb = Vb * Mirror; + if(mapeditor::drawUserShape(Vb, mapeditor::sgMonster, c->monst, (col << 8) + 0xFF, c)) return false; @@ -2411,18 +2416,21 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, bool m queuepoly(Vs, shILeaf[1], darkena(col, 0, 0xFF)); } else { + if(c->monmirror) Vb = Vb * Mirror; queuepoly(mmscale(Vb, geom3::ABODY), shILeaf[ctof(c)], darkena(col, 0, 0xFF)); ShadowV(Vb, shILeaf[ctof(c)], PPR::GIANTSHADOW); } } else if(m == moWorm || m == moWormwait || m == moHexSnake) { Vb = Vb * pispin; + if(c->monmirror) Vb = Vb * Mirror; transmatrix Vbh = mmscale(Vb, geom3::AHEAD); queuepoly(Vbh, shWormHead, darkena(col, 0, 0xFF)); queuepolyat(Vbh, shWormEyes, 0xFF, PPR::ONTENTACLE_EYES); ShadowV(Vb, shWormHead, PPR::GIANTSHADOW); } else if(m == moDragonHead) { + if(c->monmirror) Vb = Vb * Mirror; transmatrix Vbh = mmscale(Vb, geom3::AHEAD); ShadowV(Vb, shDragonHead, PPR::GIANTSHADOW); queuepoly(Vbh, shDragonHead, darkena(col, c->hitpoints?0:1, 0xFF)); @@ -2434,6 +2442,7 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, bool m } else if(m == moTentacle || m == moTentaclewait || m == moTentacleEscaping) { Vb = Vb * pispin; + if(c->monmirror) Vb = Vb * Mirror; transmatrix Vbh = mmscale(Vb, geom3::AHEAD); queuepoly(Vbh, shTentHead, darkena(col, 0, 0xFF)); ShadowV(Vb, shTentHead, PPR::GIANTSHADOW); @@ -2454,6 +2463,7 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, bool m else { Vb = Vb0 * ddspin(c, nd, M_PI); } + if(c->monmirror) Vb = Vb * Mirror; transmatrix Vbb = mmscale(Vb, geom3::ABODY); queuepoly(Vbb, shDragonTail, darkena(col, c->hitpoints?0:1, 0xFF)); ShadowV(Vb, shDragonTail, PPR::GIANTSHADOW); @@ -2474,6 +2484,7 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, bool m while(hdir1 < hdir0 - M_PI) hdir1 += 2*M_PI; Vb = Vb0 * spin((hdir0 + hdir1)/2 + M_PI); } + if(c->monmirror) Vb = Vb * Mirror; transmatrix Vbb = mmscale(Vb, geom3::ABODY); if(part == 'l' || part == '2') { queuepoly(Vbb, shDragonLegs, darkena(col, c->hitpoints?0:1, 0xFF)); @@ -2483,6 +2494,7 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, bool m } else { if(c->monst == moTentacletail && c->mondir == NODIR) { + if(c->monmirror) Vb = Vb * Mirror; queuepoly(Vb, shWormSegment, darkena(col, 0, 0xFF)); } else if(c->mondir == NODIR) { @@ -2500,6 +2512,7 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, bool m else { Vb = Vb0 * ddspin(c, nd, M_PI); } + if(c->monmirror) Vb = Vb * Mirror; transmatrix Vbb = mmscale(Vb, geom3::ABODY) * pispin; hpcshape& sh = hexsnake ? shWormTail : shSmallWormTail; queuepoly(Vbb, sh, darkena(col, 0, 0xFF)); @@ -2527,6 +2540,7 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, bool m if(d>=4) cw += 2; transmatrix Vs = Vparam; bool mirr = cw.mirrored; + if(mirrored != mirr && half_elliptic) continue; transmatrix T = Id; nospins = applyAnimation(cwt.at, T, footphase, LAYER_SMALL); if(nospins) @@ -2555,6 +2569,7 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, bool m else if(c->monst == moIllusion) { multi::cpid = 0; + if(c->monmirror) Vs = Vs * Mirror; drawMonsterType(c->monst, c, Vs, col, footphase); drawPlayerEffects(Vs, c, false); } @@ -2571,6 +2586,7 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, bool m } Vs = Vs * ddspin(c, d, 0); } + if(c->monmirror) Vs = Vs * Mirror; return drawMonsterTypeDH(m, c, Vs, col, darkhistory, footphase); } @@ -2590,6 +2606,7 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, bool m Vb = Vb * ddspin(c, c->mondir, M_PI); Vb = Vb * xpush(tentacle_length - cellgfxdist(c, c->mondir)); } + if(c->monmirror) Vb = Vb * Mirror; // if(ctof(c) && !masterless) Vb = Vb * xpush(hexhexdist - hcrossf); // return (!BITRUNCATED) ? tessf * gp::scale : (c->type == 6 && (i&1)) ? hexhexdist : crossf; @@ -2603,6 +2620,7 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, bool m if(c->monst == moKrakenH) Vs = Vb, nospins = nospinb; if(!nospins && c->mondir < c->type) Vs = Vs * ddspin(c, c->mondir, M_PI); if(c->monst == moPair) Vs = Vs * xpush(-.12); + if(c->monmirror) Vs = Vs * Mirror; if(isFriendly(c)) drawPlayerEffects(Vs, c, false); return drawMonsterTypeDH(m, c, Vs, col, darkhistory, footphase); } @@ -2625,6 +2643,7 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, bool m if(c->monst == moHunterChanging) Vs = Vs * cspin(WDIM-2, WDIM-1, M_PI); } + if(c->monmirror) Vs = Vs * Mirror; if(c->monst == moShadow) multi::cpid = c->hitpoints; @@ -2635,7 +2654,7 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, bool m for(int i=0; i 1 ? multi::player[i].mirrored : cwt.mirrored; - if(elliptic && GDIM == 3 && WDIM == 2 && mirr != mirrored) continue; + if(half_elliptic && mirr != mirrored) continue; if(!nospins) { Vs = playerV; if(multi::players > 1 ? multi::flipped[i] : flipplayer) Vs = Vs * pispin; @@ -7116,6 +7135,11 @@ void animateMovement(cell *src, cell *tgt, int layer, int direction_hint) { a.ltick = ticks; a.wherenow = T; a.footphase = 0; + a.mirrored = false; + } + if(direction_hint >= 0 && direction_hint < src->type) { + if(src->c.mirror(direction_hint)) + a.mirrored = !a.mirrored; } } diff --git a/hyper.h b/hyper.h index c5730159..d7f189c5 100644 --- a/hyper.h +++ b/hyper.h @@ -348,7 +348,8 @@ struct gcell { mondir : 8, // monster direction, for multi-tile monsters and graphics bardir : 8, // barrier direction stuntime : 8, // stun time left (for Palace Guards and Skeletons) - hitpoints : 8; // hitpoints left (for Palace Guards, also reused as cpid for mirrors) + hitpoints : 7, // hitpoints left (for Palace Guards, also reused as cpid for mirrors) + monmirror : 1; // monster mirroring state for nonorientable geometries unsigned landflags : 8; // extra flags for land #else @@ -2082,6 +2083,7 @@ struct animation { transmatrix wherenow; int attacking; transmatrix attackat; + bool mirrored; }; // we need separate animation layers for Orb of Domination and Tentacle+Ghost, diff --git a/monstergen.cpp b/monstergen.cpp index 0acc826f..d4a0e40c 100644 --- a/monstergen.cpp +++ b/monstergen.cpp @@ -13,6 +13,7 @@ int buildIvy(cell *c, int children, int minleaf) { if(c->monst) return 0; c->mondir = NODIR; c->monst = moIvyRoot; + c->monmirror = nonorientable && hrand(2); cell *child = NULL; @@ -25,7 +26,8 @@ int buildIvy(cell *c, int children, int minleaf) { child = c->move(i), leafchild = buildIvy(c->move(i), children-1, 5); else c->move(i)->monst = (leaf++ || peace::on) ? moIvyWait : moIvyHead, - c->move(i)->mondir = c->c.spin(i); + c->move(i)->mondir = c->c.spin(i), + c->move(i)->monmirror = c->monmirror; } }