diff --git a/game.cpp b/game.cpp index e9a51161..f296e57d 100644 --- a/game.cpp +++ b/game.cpp @@ -3927,6 +3927,7 @@ cell *moveNormal(cell *c, flagtype mf) { } else if(m2) { attackMonster(c2, AF_NORMAL | AF_MSG, m); + animateAttack(c, c2, LAYER_SMALL); if(m == moFlailer && m2 == moIllusion) attackMonster(c, 0, m2); return c2; @@ -3942,7 +3943,7 @@ cell *moveNormal(cell *c, flagtype mf) { cell *c2 = c->mov[posdir[i]]; if(isPlayerOn(c2)) { - killThePlayerAt(m, c2, 0); + killThePlayerAt(m, c2, 0); attacking = true; } @@ -4452,6 +4453,7 @@ void groupmove2(cell *c, cell *from, int d, eMonster movtype, flagtype mf) { if(!(mf & MF_NOATTACKS)) for(int j=0; jtype; j++) if(c->mov[j] && canAttack(c, c->monst, c->mov[j], c->mov[j]->monst, af)) { attackMonster(c->mov[j], AF_NORMAL | AF_GETPLAYER | AF_MSG, c->monst); + animateAttack(c, c->mov[j], LAYER_SMALL); c->aitmp = sval; // XLATC eagle return; @@ -5172,6 +5174,7 @@ void movegolems(flagtype flags) { else if((flags & AF_CRUSH) && !canAttack(c, m, c2, c2->monst, flags ^ AF_CRUSH ^ AF_MUSTKILL)) markOrb(itOrbEmpathy), markOrb(itOrbSlaying); attackMonster(c2, flags | AF_MSG, m); + animateAttack(c, c2, LAYER_SMALL); produceGhost(c2, m2, m); sideAttack(c, dir, m, 0); if(revenge) c->monst = m = moPrincessArmed; @@ -7554,6 +7557,7 @@ bool movepcto(int d, int subdir, bool checkonly) { if(c2->monst == moSalamander && (pushto == c2 || !pushto)) c2->stuntime = 10; if(!c2->monst) produceGhost(c2, m, moPlayer); if(pushto && pushto != c2) pushMonster(pushto, c2); + animateAttack(cwt.c, c2, LAYER_SMALL); } } diff --git a/graph.cpp b/graph.cpp index 7ba70be0..15b30929 100644 --- a/graph.cpp +++ b/graph.cpp @@ -1694,20 +1694,31 @@ bool applyAnimation(cell *c, transmatrix& V, double& footphase, int layer) { int td = ticks - a.ltick; ld aspd = td / 1000.0 * exp(vid.mspeed); - ld R = hdist0(tC0(a.wherenow)); + ld R; + again: + + if(a.attacking == 1) + R = hdist(tC0(a.attackat), tC0(a.wherenow)); + else + R = hdist0(tC0(a.wherenow)); aspd *= (1+R+(shmup::on?1:0)); if(R < aspd || std::isnan(R) || std::isnan(aspd) || R > 10) { + if(a.attacking == 1) { a.attacking = 2; goto again; } animations[layer].erase(c); return false; } else { - a.wherenow = a.wherenow * rspintox(tC0(inverse(a.wherenow))); + if(a.attacking == 1) + a.wherenow = a.wherenow * rspintox(tC0(inverse(a.wherenow) * a.attackat)); + else + a.wherenow = a.wherenow * rspintox(tC0(inverse(a.wherenow))); a.wherenow = a.wherenow * xpush(aspd); fixmatrix(a.wherenow); - a.footphase += aspd; + a.footphase += a.attacking == 2 ? -aspd : aspd; footphase = a.footphase; V = V * a.wherenow; + if(a.attacking == 2) V = V * pispin; a.ltick = ticks; return true; } @@ -5654,6 +5665,7 @@ void animateMovement(cell *src, cell *tgt, int layer) { a = animations[layer][src]; a.wherenow = inverse(gmatrix[tgt]) * gmatrix[src] * a.wherenow; animations[layer].erase(src); + a.attacking = 0; } else { a.ltick = ticks; @@ -5663,6 +5675,18 @@ void animateMovement(cell *src, cell *tgt, int layer) { } } +void animateAttack(cell *src, cell *tgt, int layer) { + if(vid.mspeed >= 5) return; // no animations! + if(gmatrix.count(src) && gmatrix.count(tgt)) { + bool newanim = !animations[layer].count(src); + animation& a = animations[layer][src]; + a.attacking = 1; + a.attackat = rspintox(tC0(inverse(gmatrix[src]) * gmatrix[tgt])) * xpush(hdist(gmatrix[src]*C0, gmatrix[tgt]*C0) / 3); + if(newanim) a.wherenow = Id, a.ltick = ticks, a.footphase = 0; + display(a.attackat); + } + } + vector > animstack; void indAnimateMovement(cell *src, cell *tgt, int layer) { diff --git a/hyper.h b/hyper.h index 43223022..e1881d7a 100644 --- a/hyper.h +++ b/hyper.h @@ -1254,6 +1254,8 @@ struct animation { int ltick; double footphase; transmatrix wherenow; + int attacking; + transmatrix attackat; }; // we need separate animation layers for Orb of Domination and Tentacle+Ghost, @@ -1266,6 +1268,8 @@ struct animation { extern map animations[ANIMLAYERS]; extern unordered_map gmatrix, gmatrix0; +void animateAttack(cell *src, cell *tgt, int layer); + void animateMovement(cell *src, cell *tgt, int layer); // for animations which might use the same locations,