1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2025-04-21 10:13:14 +00:00

Orb of Plague

This commit is contained in:
Zeno Rogue 2020-02-26 02:49:35 +01:00
parent e13a604418
commit 6317101d66
8 changed files with 54 additions and 27 deletions

@ -138,10 +138,10 @@ EX bool canAttack(cell *c1, eMonster m1, cell *c2, eMonster m2, flagtype flags)
if(m2 == moGreater || m2 == moGreaterM)
if(!(flags & (AF_MAGIC | AF_SWORD_INTO | AF_HORNS | AF_CRUSH))) return false;
if(!(flags & (AF_GUN | AF_SWORD | AF_SWORD_INTO | AF_MAGIC)))
if(!(flags & (AF_GUN | AF_SWORD | AF_SWORD_INTO | AF_MAGIC | AF_PLAGUE)))
if(c1 != c2 && !logical_adjacent(c1, m1, c2)) return false;
if(!(flags & (AF_LANCE | AF_STAB | AF_BACK | AF_APPROACH | AF_GUN | AF_MAGIC)))
if(!(flags & (AF_LANCE | AF_STAB | AF_BACK | AF_APPROACH | AF_GUN | AF_MAGIC | AF_PLAGUE | AF_SIDE)))
if(c1 && c2 && againstRose(c1, c2) && !ignoresSmell(m1))
return false;

@ -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 the Swamp", itOrbSwamp, IC_ORB, ZERO, RESERVED, osUtility, NODESCYET)
ITEM( 'o', 0x808080, "Orb of Plague", itOrbPlague, IC_ORB, ZERO, RESERVED, osOffensive, NODESCYET)
NATIVE(among(m, moPike, moRusalka) ? 2 : 0)
REQ( GOLD(R30) )

@ -483,6 +483,7 @@ typedef function<int(struct cell*)> cellfunction;
#define AF_BULL Flag(29) // bull attack
#define AF_SIDE Flag(30) // side attack
#define AF_CRUSH Flag(31) // Crusher's delayed attack
#define AF_PLAGUE Flag(32) // Orb of Plague (do not check adjacency)
#if CAP_SDL

@ -353,7 +353,7 @@ EX namespace inv {
gainOrbs(itBrownian, itOrbChoice);
gainOrbs(itFrog, itOrbImpact);
gainOrbs(itWet, itOrbSwamp);
gainOrbs(itWet, itOrbPlague);
gainOrbs(itEclectic, itOrbChaos);
#if CAP_DAILY

@ -161,7 +161,7 @@ EX vector<orbinfo> orbinfos = {
{orbgenflags::S_NATIVE, laEclectic, 1000, 1000, itOrbChaos},
{orbgenflags::S_GUEST, laEclectic, 4000, 0, itOrbWinter},
{orbgenflags::S_GUEST, laEclectic, 2000, 0, itOrbLightning},
{orbgenflags::S_GUEST, laWet, 1000, 1000, itOrbSwamp},
{orbgenflags::S_GUEST, laWet, 1000, 1000, itOrbPlague},
{orbgenflags::S_GUEST, laWet, 4000, 0, itOrbFish},
{orbgenflags::S_NATIVE, laWhirlpool, 0, 2000, itOrbWater}, // needs to be last
};

@ -158,7 +158,7 @@ EX void reduceOrbPowers() {
reduceOrbPower(itOrbIntensity, 120);
reduceOrbPower(itOrbImpact, 120);
reduceOrbPower(itOrbChaos, 120);
reduceOrbPower(itOrbSwamp, 120);
reduceOrbPower(itOrbPlague, 120);
reduceOrbPower(itOrbSide1, 120);
reduceOrbPower(itOrbSide2, 120);
@ -1504,8 +1504,8 @@ EX int orbcharges(eItem it) {
case itOrbChaos:
return 60;
case itOrbSwamp:
return 60;
case itOrbPlague:
return 30;
default:
return 0;

@ -1245,28 +1245,51 @@ EX void swordAttackStatic() {
swordAttackStatic(bb);
}
EX void sideAttackAt(cell *mf, int dir, cell *mt, eMonster who, eItem orb) {
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(canAttack(mf, who, mt, m, f)) {
if((f & AF_CRUSH) && !canAttack(mf, who, mt, m, AF_SIDE | AF_MUSTKILL))
markOrb(itOrbSlaying);
markOrb(orb);
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);
produceGhost(mt, m, who);
}
}
else if(mt->wall == waSmallTree) {
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);
}
else if(mt->wall == waBigTree)
mt->wall = waSmallTree;
else if(mt->wall == waExplosiveBarrel && orb != itOrbPlague)
explodeBarrel(mt);
}
EX void sideAttack(cell *mf, int dir, eMonster who, int bonus, eItem orb) {
if(!items[orb]) return;
if(who != moPlayer && !items[itOrbEmpathy]) return;
for(int k: {-1, 1}) {
cell *mt = mf->modmove(dir + k*bonus);
eMonster m = mt->monst;
flagtype f = AF_SIDE;
if(items[itOrbSlaying]) f|= AF_CRUSH;
if(canAttack(mf, who, mt, m, f)) {
if((f & AF_CRUSH) && !canAttack(mf, who, mt, m, AF_SIDE | AF_MUSTKILL))
markOrb(itOrbSlaying);
markOrb(orb);
if(who != moPlayer) markOrb(itOrbEmpathy);
if(attackMonster(mt, AF_NORMAL | AF_SIDE | AF_MSG, who))
produceGhost(mt, m, who);
}
else if(mt->wall == waBigTree)
mt->wall = waSmallTree;
else if(mt->wall == waSmallTree)
mt->wall = waNone;
else if(mt->wall == waExplosiveBarrel)
explodeBarrel(mt);
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);
}
}
@ -1275,7 +1298,10 @@ EX void sideAttack(cell *mf, int dir, eMonster who, int bonuskill) {
int k = tkills();
sideAttack(mf, dir, who, 1, itOrbSide1);
sideAttack(mf, dir, who, 2, itOrbSide2);
sideAttack(mf, dir, who, 3, itOrbSide3);
sideAttack(mf, dir, who, 3, itOrbSide3);
k -= tkills();
sideAttackPlague(mf, dir, who);
k += tkills();
if(who == moPlayer) {
int kills = tkills() - k + bonuskill;

@ -835,7 +835,7 @@ EX void applyBoxes() {
applyBoxOrb(itOrbImpact);
applyBoxOrb(itOrbChaos);
applyBoxOrb(itOrbSwamp);
applyBoxOrb(itOrbPlague);
applyBoxI(itEclectic);
applyBoxI(itFrog);
applyBoxI(itWet);