1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-12-24 17:10:36 +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

View File

@ -138,10 +138,10 @@ EX bool canAttack(cell *c1, eMonster m1, cell *c2, eMonster m2, flagtype flags)
if(m2 == moGreater || m2 == moGreaterM) if(m2 == moGreater || m2 == moGreaterM)
if(!(flags & (AF_MAGIC | AF_SWORD_INTO | AF_HORNS | AF_CRUSH))) return false; 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(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)) if(c1 && c2 && againstRose(c1, c2) && !ignoresSmell(m1))
return false; return false;

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( '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, 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.") "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) NATIVE(among(m, moPike, moRusalka) ? 2 : 0)
REQ( GOLD(R30) ) REQ( GOLD(R30) )

View File

@ -483,6 +483,7 @@ typedef function<int(struct cell*)> cellfunction;
#define AF_BULL Flag(29) // bull attack #define AF_BULL Flag(29) // bull attack
#define AF_SIDE Flag(30) // side attack #define AF_SIDE Flag(30) // side attack
#define AF_CRUSH Flag(31) // Crusher's delayed 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 #if CAP_SDL

View File

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

View File

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

View File

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

View File

@ -1245,28 +1245,51 @@ EX void swordAttackStatic() {
swordAttackStatic(bb); 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) { EX void sideAttack(cell *mf, int dir, eMonster who, int bonus, eItem orb) {
if(!items[orb]) return; if(!items[orb]) return;
if(who != moPlayer && !items[itOrbEmpathy]) return; if(who != moPlayer && !items[itOrbEmpathy]) return;
for(int k: {-1, 1}) { for(int k: {-1, 1}) {
cell *mt = mf->modmove(dir + k*bonus); cell *mt = mf->modmove(dir + k*bonus);
eMonster m = mt->monst; sideAttackAt(mf, dir, mt, who, orb);
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)) EX void sideAttackPlague(cell *mf, int dir, eMonster who) {
markOrb(itOrbSlaying); if(!items[itOrbPlague]) return;
markOrb(orb); cellwalker cw(mf, dir);
if(who != moPlayer) markOrb(itOrbEmpathy); cw += wstep;
if(attackMonster(mt, AF_NORMAL | AF_SIDE | AF_MSG, who)) for(int i=2; i<cw.at->type-1; i++) {
produceGhost(mt, m, who); println(hlog, "sa = ", (cw+i).cpeek(), " mo = ", dnameof((cw+i).cpeek()->monst));
} sideAttackAt(mf, dir, (cw+i).cpeek(), who, itOrbPlague);
else if(mt->wall == waBigTree)
mt->wall = waSmallTree;
else if(mt->wall == waSmallTree)
mt->wall = waNone;
else if(mt->wall == waExplosiveBarrel)
explodeBarrel(mt);
} }
} }
@ -1275,7 +1298,10 @@ EX void sideAttack(cell *mf, int dir, eMonster who, int bonuskill) {
int k = tkills(); int k = tkills();
sideAttack(mf, dir, who, 1, itOrbSide1); sideAttack(mf, dir, who, 1, itOrbSide1);
sideAttack(mf, dir, who, 2, itOrbSide2); 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) { if(who == moPlayer) {
int kills = tkills() - k + bonuskill; int kills = tkills() - k + bonuskill;

View File

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