Orb of Plague improved

This commit is contained in:
Zeno Rogue 2020-02-29 20:20:08 +01:00
parent ca60e463b3
commit 688fc50036
5 changed files with 62 additions and 28 deletions

View File

@ -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);
}
}

View File

@ -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) )

View File

@ -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);

View File

@ -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;

View File

@ -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; i<cw.at->type-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;