diff --git a/graph.cpp b/graph.cpp index f3cd39d8..d2a4fb19 100644 --- a/graph.cpp +++ b/graph.cpp @@ -1725,9 +1725,10 @@ double chainAngle(cell *c, transmatrix& V, cell *c2, double dft, const transmatr } // equivalent to V = V * spin(-chainAngle(c,V,c2,dft)); -bool chainAnimation(cell *c, transmatrix& V, cell *c2, int i, int b, const transmatrix &Vwhere) { +bool chainAnimation(cell *c, transmatrix& V, cell *c2, int i, int b, const transmatrix &Vwhere, ld& length) { if(!gmatrix0.count(c2)) { V = V * ddspin(c,i,b); + length = cellgfxdist(c,i); return false; } hyperpoint h = C0; @@ -1736,6 +1737,7 @@ bool chainAnimation(cell *c, transmatrix& V, cell *c2, int i, int b, const trans h = inverse(V) * Vwhere * inverse(gmatrix0[c]) * gmatrix0[c2] * h; else h = inverse(V) * gmatrix0[c2] * h; + length = hdist0(h); V = V * rspintox(h); return true; } @@ -1764,6 +1766,31 @@ int cellcolor(cell *c) { return OUTLINE_NONE; } +int taildist(cell *c) { + int s = 0; + while(s < 1000 && c->mondir != NODIR && isWorm(c->monst)) { + s++; c = c->mov[c->mondir]; + } + return s; + } + +int last_wormsegment = -1; +vector > > wormsegments; + +void add_segment(int d, const std::function& s) { + if(size(wormsegments) <= d) wormsegments.resize(d+1); + last_wormsegment = max(last_wormsegment, d); + wormsegments[d].push_back(s); + } + +void drawWormSegments() { + for(int i=0; i<=last_wormsegment; i++) { + for(auto& f: wormsegments[i]) f(); + wormsegments[i].clear(); + } + last_wormsegment = -1; + } + bool drawMonster(const transmatrix& Vparam, int ct, cell *c, int col) { bool darkhistory = conformal::includeHistory && eq(c->aitmp, sval); @@ -1803,20 +1830,27 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, int col) { if(c->mondir != NODIR) { if(mmmon) { - if(nospinb) - chainAnimation(c, Vb, c->mov[c->mondir], c->mondir, 0, Vparam); - else + ld length; + // cell *c2 = c->mov[c->mondir]; + if(nospinb) + chainAnimation(c, Vb, c->mov[c->mondir], c->mondir, 0, Vparam, length); + else { Vb = Vb * ddspin(c, c->mondir); + length = cellgfxdist(c, c->mondir); + } if(mapeditor::drawUserShape(Vb, 1, c->monst, (col << 8) + 0xFF, c)) return false; if(isIvy(c) || isMutantIvy(c) || c->monst == moFriendlyIvy) queuepoly(Vb, shIBranch, (col << 8) + 0xFF); - else if(c->monst < moTentacle) { +/* else if(c->monst < moTentacle && wormstyle == 0) { ShadowV(Vb, shTentacleX, PPR_GIANTSHADOW); queuepoly(mmscale(Vb, geom3::ABODY), shTentacleX, 0xFF); queuepoly(mmscale(Vb, geom3::ABODY), shTentacle, (col << 8) + 0xFF); - } + } */ +// else if(c->monst < moTentacle) { +// } + else if(c->monst == moDragonHead || c->monst == moDragonTail) { char part = dragon::bodypart(c, dragon::findhead(c)); if(part != '2') { @@ -1832,9 +1866,32 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, int col) { drawMonsterType(moGhost, c, Vs, darkena(col, 0, 0xFF), footphase); col = minf[moTentacletail].color; } + /* queuepoly(mmscale(Vb, geom3::ABODY), shTentacleX, 0xFFFFFFFF); queuepoly(mmscale(Vb, geom3::ABODY), shTentacle, (col << 8) + 0xFF); ShadowV(Vb, shTentacleX, PPR_GIANTSHADOW); + */ + bool hexsnake = c->monst == moHexSnake || c->monst == moHexSnakeTail; + bool thead = c->monst == moTentacle || c->monst == moTentaclewait || c->monst == moTentacleEscaping; + hpcshape& sh = hexsnake ? shWormSegment : shSmallWormSegment; + ld wav = hexsnake ? 0 : + c->monst < moTentacle ? 1/1.5 : + 1; + int col0 = col; + if(c->monst == moWorm || c->monst == moWormwait) + col0 = minf[moWormtail].color; + else if(thead) + col0 = minf[moTentacletail].color; + add_segment(taildist(c), [=] () { + for(int i=11; i>=0; i--) { + if(i < 3 && (c->monst == moTentacle || c->monst == moTentaclewait)) continue; + transmatrix Vbx = Vb * spin(sin(M_PI * i / 6.) * wav / (i+.1)) * xpush(length * (i) / 12.0); + // transmatrix Vbx2 = Vnext * xpush(length2 * i / 6.0); + // Vbx = Vbx * rspintox(inverse(Vbx) * Vbx2 * C0) * pispin; + ShadowV(Vbx, sh, PPR_GIANTSHADOW); + queuepoly(mmscale(Vbx, geom3::ABODY), sh, (col0 << 8) + 0xFF); + } + }); } } @@ -1883,7 +1940,8 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, int col) { char part = dragon::bodypart(c, dragon::findhead(c)); if(part == 't') { if(nospinb) { - chainAnimation(c, Vb, c2, nd, 0, Vparam); + ld length; + chainAnimation(c, Vb, c2, nd, 0, Vparam, length); Vb = Vb * pispin; } else { @@ -1895,7 +1953,8 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, int col) { } else if(true) { if(nospinb) { - chainAnimation(c, Vb, c2, nd, 0, Vparam); + ld length; + chainAnimation(c, Vb, c2, nd, 0, Vparam, length); Vb = Vb * pispin; double ang = chainAngle(c, Vb, c->mov[c->mondir], (displaydir(c, c->mondir) - displaydir(c, nd)) * M_PI / S42, Vparam); ang /= 2; @@ -1916,8 +1975,29 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, int col) { } } else { - if(!(c->mondir == NODIR && (c->monst == moTentacletail || (c->monst == moWormtail && wormpos(c) < WORMLENGTH)))) - queuepoly(Vb, shJoint, darkena(col, 0, 0xFF)); + if(c->monst == moTentacletail && c->mondir == NODIR) { + queuepoly(Vb, shWormSegment, darkena(col, 0, 0xFF)); + } + else if(c->mondir == NODIR) { + bool hexsnake = c->monst == moHexSnake || c->monst == moHexSnakeTail; + cell *c2 = NULL; + for(int i=0; itype; i++) + if(c->mov[i] && isWorm(c->mov[i]->monst) && c->mov[i]->mondir == c->spn(i)) + c2 = c->mov[i]; + int nd = neighborId(c, c2); + if(nospinb) { + ld length; + chainAnimation(c, Vb, c2, nd, 0, Vparam, length); + Vb = Vb * pispin; + } + else { + Vb = Vb0 * ddspin(c, nd, S42); + } + transmatrix Vbb = mmscale(Vb, geom3::ABODY) * pispin; + hpcshape& sh = hexsnake ? shWormTail : shSmallWormTail; + queuepoly(Vbb, sh, darkena(col, 0, 0xFF)); + ShadowV(Vb, sh, PPR_GIANTSHADOW); + } } } @@ -1990,7 +2070,8 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, int col) { else if(c->monst == moKrakenT) { if(c->hitpoints == 0) col = 0x404040; if(nospinb) { - chainAnimation(c, Vb, c->mov[c->mondir], c->mondir, 0, Vparam); + ld length; + chainAnimation(c, Vb, c->mov[c->mondir], c->mondir, 0, Vparam, length); Vb = Vb * pispin; } else Vb = Vb * ddspin(c, c->mondir, S42); @@ -5070,6 +5151,7 @@ void drawthemap() { drawrec(viewctr, maxreclevel, hsOrigin, cview()); } + drawWormSegments(); drawBlizzards(); drawArrowTraps(); ivoryz = false; diff --git a/polygons.cpp b/polygons.cpp index 91d88809..371d5e19 100644 --- a/polygons.cpp +++ b/polygons.cpp @@ -1012,7 +1012,7 @@ hpcshape shSabre, shTurban1, shTurban2, shVikingHelmet, shRaiderHelmet, shRaiderArmor, shRaiderBody, shRaiderShirt, shWestHat1, shWestHat2, shGunInHand, shKnightArmor, shKnightCloak, shWightCloak, - shGhost, shEyes, shSlime, shJelly, shJoint, shWormHead, shTentHead, shShark, + shGhost, shEyes, shSlime, shJelly, shJoint, shWormHead, shTentHead, shShark, shWormSegment, shSmallWormSegment, shWormTail, shSmallWormTail, shHedgehogBlade, shHedgehogBladePlayer, shWolfBody, shWolfHead, shWolfLegs, shWolfEyes, shWolfFrontLeg, shWolfRearLeg, shWolfFrontPaw, shWolfRearPaw, @@ -2000,6 +2000,16 @@ void buildpolys() { copyshape(shJoint, shDisk, PPR_ONTENTACLE); bshape(shTentHead, PPR_ONTENTACLE, scalef, 79); bshape(shWormHead, PPR_ONTENTACLE, scalef, 80); + + bshape(shWormSegment, PPR_TENTACLE1); + for(int i=0; i<=S84; i+=S3) + hpcpush(ddi(i, .20 * scalef) * C0); + bshape(shSmallWormSegment, PPR_TENTACLE1); + for(int i=0; i<=S84; i+=S3) + hpcpush(ddi(i, .16 * scalef) * C0); + bshape(shWormTail, PPR_TENTACLE1, scalef, 383); + bshape(shSmallWormTail, PPR_TENTACLE1, scalef, 384); + if(nonbitrunc) bshape(shDragonSegment, PPR_TENTACLE1, 1, 233); else bshape(shDragonSegment, PPR_TENTACLE1, scalef, 234); bshape(shDragonWings, PPR_ONTENTACLE, scalef, 237); @@ -3451,6 +3461,11 @@ NEWSHAPE, 379, 7, 1, 0.649585,0.084560, 0.623391,0.075842, 0.599921,0.058309, 0. NEWSHAPE, 380, 1, 2, -0.157063,0.003936, -0.151414,0.044436, -0.065427,0.009052, -0.151414,0.044436, -0.151129,0.067964, -0.072440,0.024229, -0.150301,0.069258, -0.113069,0.110826, -0.037964,0.039249, -0.110463,0.109185, -0.011307,0.146227, -0.108855,0.111771, -0.113069,0.110826, -0.110452,0.155897, -0.007227,0.165082, -0.111749,0.156720, -0.114514,0.196200, 0.003252,0.188966, -0.009486,0.143350, 0.043508,0.083540, 0.057523,0.000604, NEWSHAPE, 381, 1, 2, -0.128015,0.002500, -0.121343,0.106487, -0.104134,0.121999, -0.063293,0.274181, 0.038783,0.286293, 0.071085,0.292868, 0.087907,0.266956, 0.077475,0.243894, 0.083000,0.234337, 0.068629,0.220991, 0.042226,0.206757, 0.023044,0.227068, -0.009573,0.218873, -0.027348,0.140245, -0.005432,-0.096462, 0.020544,-0.030837, NEWSHAPE, 382, 1, 2, 0.024784,0.028900, -0.009988,0.111744, -0.018320,0.147991, -0.006519,0.215354, 0.020083,0.223620, 0.029811,0.291799, -0.066579,0.278718, -0.136927,0.082023, -0.147101,-0.050084, + +NEWSHAPE, 383, 1, 2, 0.164154,0.032677, 0.112722,0.126268, 0.093106,0.144972, 0.036998,0.184005, -0.028137,0.220088, -0.088953,0.208314, -0.221199,0.117397, -0.270025,0.057450, -0.290973,0.020569, +NEWSHAPE, 384, 1, 2, 0.146470,0.021791, 0.134179,0.071381, 0.089857,0.116839, 0.039860,0.139410, -0.005910,0.150902, -0.047971,0.139775, -0.104973,0.100695, -0.147597,0.052809, -0.177722,0.017653, -0.186756,0.003107, + + NEWSHAPE };