From 688fc500366d38d834d270143a41e6eceff72e4e Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Sat, 29 Feb 2020 20:20:08 +0100 Subject: [PATCH] Orb of Plague improved --- attack.cpp | 12 +++++++--- content.cpp | 2 +- graph.cpp | 13 +++++++++++ monstermove.cpp | 2 ++ pcmove.cpp | 61 ++++++++++++++++++++++++++++++------------------- 5 files changed, 62 insertions(+), 28 deletions(-) diff --git a/attack.cpp b/attack.cpp index 0d489e9c..6c6c1a49 100644 --- a/attack.cpp +++ b/attack.cpp @@ -1196,8 +1196,10 @@ EX void stabbingAttack(cell *mf, cell *mt, eMonster who, int bonuskill IS(0)) { } eMonster m = c->monst; int k = tkills(); - if(attackMonster(c, AF_STAB | AF_MSG, who)) + if(attackMonster(c, AF_STAB | AF_MSG, who)) { + spread_plague(mt, c, t, who); produceGhost(c, m, who); + } if(tkills() > k) numsh++; } @@ -1223,8 +1225,11 @@ EX void stabbingAttack(cell *mf, cell *mt, eMonster who, int bonuskill IS(0)) { if(c->monst == moFlailer && isPrincess(who) && isUnarmed(who)) achievement_gain("PRINCESS_PACIFIST"); - if(attackMonster(c, 0, who)) numflail++; - if(m == moVizier) produceGhost(c, m, who); + if(attackMonster(c, 0, who)) { + numflail++; + spread_plague(mf, c, t, who); + produceGhost(c, m, who); + } } } } @@ -1236,6 +1241,7 @@ EX void stabbingAttack(cell *mf, cell *mt, eMonster who, int bonuskill IS(0)) { if(anglestraight(mt, backdir, t)) flag |= AF_HORNS; if(canAttack(mt,who,c,c->monst, flag)) { if(attackMonster(c, flag | AF_MSG, who)) numlance++; + spread_plague(mt, c, t, who); produceGhost(c, mm, who); } } diff --git a/content.cpp b/content.cpp index e27950a6..83cb2421 100644 --- a/content.cpp +++ b/content.cpp @@ -1562,7 +1562,7 @@ MONSTER( 'P', 0xC08080, "Pike", moPike, CF_FACE_SIDE | CF_SHARK, RESERVED, moSha MONSTER( 'S', 0xC0C080, "Yellow Skipper", moYellowSkipper, CF_FACE_SIDE | CF_SHARK, RESERVED, moShark, "Just a nasty shark.") /* unused */ MONSTER( 'R', 0x4040C0, "Rusałka", moRusalka, CF_FACE_SIDE | CF_SHARK, RESERVED, moShark, "A water spirit. When killed, she will try to drown you, by changing dry land to shallow water and shallow water to deep water.") -ITEM( 'o', 0x808080, "Orb of Plague", itOrbPlague, IC_ORB, ZERO, RESERVED, osOffensive, NODESCYET) +ITEM( 'o', 0x808080, "Orb of Plague", itOrbPlague, IC_EMPATHY, ZERO, RESERVED, osOffensive, NODESCYET) NATIVE(among(m, moPike, moRusalka) ? 2 : 0) REQ( GOLD(R30) ) diff --git a/graph.cpp b/graph.cpp index 6657789b..4b9eea2d 100644 --- a/graph.cpp +++ b/graph.cpp @@ -3897,6 +3897,19 @@ EX void drawParticleSpeed(cell *c, color_t col, int speed) { EX void drawParticle(cell *c, color_t col, int maxspeed IS(100)) { drawParticleSpeed(c, col, 1 + rand() % maxspeed); } + +EX void drawDirectionalParticle(cell *c, int dir, color_t col, int maxspeed IS(100)) { + LATE( drawDirectionalParticle(c, dir, col, maxspeed); ) + if(vid.particles && !confusingGeometry()) { + int speed = 1 + rand() % maxspeed; + auto fd = flashdata(ticks, rand() % 16, c, col, speed); + fd.angle = -atan2(tC0(currentmap->adj(c, dir))); + fd.angle += 2 * M_PI * (rand() % 100 - rand() % 100) / 100 / c->type; + flashes.push_back(fd); + } + } + + EX void drawParticles(cell *c, color_t col, int qty, int maxspeed IS(100)) { if(vid.particles) while(qty--) drawParticle(c,col, maxspeed); diff --git a/monstermove.cpp b/monstermove.cpp index 2496cfd7..193925f5 100644 --- a/monstermove.cpp +++ b/monstermove.cpp @@ -1228,6 +1228,7 @@ EX void snakeAttack(cell *c, bool mounted) { mounted ? AF_ONLY_ENEMY : (AF_ONLY_FBUG | AF_GETPLAYER))) { eMonster m2 = c->move(j)->monst; attackMonster(c->move(j), AF_NORMAL | AF_GETPLAYER | AF_MSG, moHexSnake); + spread_plague(c, c->move(j), j, moHexSnake); produceGhost(c->move(j), moHexSnake, m2); } } @@ -1659,6 +1660,7 @@ EX void movegolems(flagtype flags) { markOrb(itOrbEmpathy), markOrb(itOrbSlaying); attackMonster(c2, flags | AF_MSG, m); animateAttack(movei(c, dir), LAYER_SMALL); + spread_plague(c, c2, dir, m); produceGhost(c2, m2, m); sideAttack(c, dir, m, 0); if(revenge) c->monst = m = moPrincessArmed; diff --git a/pcmove.cpp b/pcmove.cpp index 3044183e..fa23b790 100644 --- a/pcmove.cpp +++ b/pcmove.cpp @@ -717,6 +717,7 @@ bool pcmove::after_escape() { playSound(c2, "hit-axe" + pick123()); changes.ccell(c2); c2->wall = waNone; + spread_plague(cwt.at, c2, mi.d, moPlayer); return swing(); } else if(c2->wall == waBigTree) { @@ -887,7 +888,10 @@ bool pcmove::attack() { changes.ccell(c2); // salamanders are stunned for longer time when pushed into a wall if(c2->monst == moSalamander && (mip.t == c2 || !mip.t)) c2->stuntime = 10; - if(!c2->monst) produceGhost(c2, m, moPlayer); + if(!c2->monst) { + spread_plague(cwt.at, c2, mi.d, moPlayer); + produceGhost(c2, m, moPlayer); + } if(mip.proper()) pushMonster(mip); animateAttack(mi, LAYER_SMALL); } @@ -1264,33 +1268,53 @@ EX void swordAttackStatic() { swordAttackStatic(bb); } -EX void sideAttackAt(cell *mf, int dir, cell *mt, eMonster who, eItem orb) { +EX int plague_kills; + +EX void spread_plague(cell *mf, cell *mt, int dir, eMonster who) { + if(!items[itOrbPlague]) return; + int kk = tkills(); + forCellEx(mx, mt) if(celldistance(mx, mf) > celldistance(mx, mf->move(dir)) && celldistance(mx, mf) <= 4) { + sideAttackAt(mf, dir, mx, who, itOrbPlague, mt); + } + plague_kills += tkills() - kk; + } + +EX void sideAttackAt(cell *mf, int dir, cell *mt, eMonster who, eItem orb, cell *pf) { eMonster m = mt->monst; flagtype f = AF_SIDE; if(orb == itOrbPlague) f |= AF_PLAGUE; if(items[itOrbSlaying]) f|= AF_CRUSH; - if(m) println(hlog, "canAttack ", dnameof(m), " at ", mt, ":", canAttack(mf, who, mt, m, f)); + if(!items[orb]) return; + auto plague_particles = [&] { + if(orb == itOrbPlague) { + for(int i=0; i<16; i++) + drawDirectionalParticle(pf, neighborId(pf, mt), iinf[orb].color); + } + }; if(canAttack(mf, who, mt, m, f)) { if((f & AF_CRUSH) && !canAttack(mf, who, mt, m, AF_SIDE | AF_MUSTKILL)) markOrb(itOrbSlaying); markOrb(orb); + plague_particles(); if(who != moPlayer) markOrb(itOrbEmpathy); if(attackMonster(mt, AF_NORMAL | AF_SIDE | AF_MSG, who) || isAnyIvy(m)) { - println(hlog, "spread from ", mt); - forCellEx(mx, mt) if(celldistance(mx, mf) > celldistance(mx, mf->move(dir)) && celldistance(mx, mf) <= 4) - sideAttackAt(mf, dir, mx, who, orb); + if(mt->monst != m) spread_plague(mf, mt, dir, who); produceGhost(mt, m, who); } } else if(mt->wall == waSmallTree) { + plague_particles(); + markOrb(orb); mt->wall = waNone; - forCellEx(mx, mt) if(celldistance(mx, mf) > celldistance(mx, mf->move(dir)) && celldistance(mx, mf) <= 4) - sideAttackAt(mf, dir, mx, who, orb); + spread_plague(mf, mt, dir, who); } - else if(mt->wall == waBigTree) + else if(mt->wall == waBigTree) { + plague_particles(); + markOrb(orb); mt->wall = waSmallTree; + } else if(mt->wall == waExplosiveBarrel && orb != itOrbPlague) - explodeBarrel(mt); + explodeBarrel(mt); } EX void sideAttack(cell *mf, int dir, eMonster who, int bonus, eItem orb) { @@ -1298,29 +1322,18 @@ EX void sideAttack(cell *mf, int dir, eMonster who, int bonus, eItem orb) { if(who != moPlayer && !items[itOrbEmpathy]) return; for(int k: {-1, 1}) { cell *mt = mf->modmove(dir + k*bonus); - sideAttackAt(mf, dir, mt, who, orb); - } - } - -EX void sideAttackPlague(cell *mf, int dir, eMonster who) { - if(!items[itOrbPlague]) return; - cellwalker cw(mf, dir); - cw += wstep; - for(int i=2; itype-1; i++) { - println(hlog, "sa = ", (cw+i).cpeek(), " mo = ", dnameof((cw+i).cpeek()->monst)); - sideAttackAt(mf, dir, (cw+i).cpeek(), who, itOrbPlague); + sideAttackAt(mf, dir, mt, who, orb, mf); } } EX void sideAttack(cell *mf, int dir, eMonster who, int bonuskill) { int k = tkills(); + plague_kills = 0; sideAttack(mf, dir, who, 1, itOrbSide1); sideAttack(mf, dir, who, 2, itOrbSide2); sideAttack(mf, dir, who, 3, itOrbSide3); - k -= tkills(); - sideAttackPlague(mf, dir, who); - k += tkills(); + k -= tkills() - plague_kills; if(who == moPlayer) { int kills = tkills() - k + bonuskill;