mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-11-13 00:49:54 +00:00
Invinc monsters implemented
This commit is contained in:
parent
daba860085
commit
5f1b1a54eb
@ -759,6 +759,11 @@ monstertype minf[motypes] = {
|
||||
"When your plan has clearly failed, it is better to abandon it and go to a safe place, to have a chance of succeeding next time. This dog clearly knows this."},
|
||||
{ 'B', 0xC00000, "North Pole", NODESCYET},
|
||||
{ 'B', 0x0000C0, "South Pole", NODESCYET},
|
||||
{ 'P', 0xC0D000, "Pair Demon", NODESCYET},
|
||||
{ 'H', 0x00C0D0, "Hex Demon", NODESCYET},
|
||||
{ 'A', 0xD000C0, "Alt Demon", NODESCYET},
|
||||
{ 'M', 0x904000, "Monk", NODESCYET},
|
||||
{ 'C', 0x004070, "Crusher", NODESCYET},
|
||||
{ '@', 0xC00000, "Switcher A", NODESCYET},
|
||||
{ '@', 0x0000C0, "Switcher B", NODESCYET},
|
||||
|
||||
@ -1208,7 +1213,7 @@ itemtype iinf[ittypes] = {
|
||||
{ '!', 0x80FF00, "Glowing Crystal", crystaldesc},
|
||||
{ '!', 0x80FF80, "Snake Oil", NODESCYET},
|
||||
{ '*', 0x80FF80, "Sea Glass", NODESCYET},
|
||||
{ '*', 0x80FF80, "Invix Treasure", NODESCYET},
|
||||
{ '*', 0xFFFFFF, "Invix Treasure", NODESCYET},
|
||||
{ '*', 0x80FF80, "Monopole", NODESCYET},
|
||||
{ '*', 0xFFFF80, "Junk", NODESCYET},
|
||||
{ 'o', 0x80FF80, "Orb of Phasing", NODESCYET},
|
||||
|
@ -1,4 +1,4 @@
|
||||
static const int motypes = 156;
|
||||
static const int motypes = 161;
|
||||
|
||||
struct monstertype {
|
||||
char glyph;
|
||||
@ -53,6 +53,7 @@ enum eMonster {
|
||||
moHunterDog, moTerraWarrior, moJiangshi, moVoidBeast, moLavaWolf, moHunterGuard,
|
||||
moIceGolem, moSandBird, moSalamander, moHunterChanging,
|
||||
moNorthPole, moSouthPole,
|
||||
moPair, moHexDemon, moAltDemon, moMonk, moCrusher,
|
||||
moSwitch1, moSwitch2,
|
||||
// shmup specials
|
||||
moPlayer, moBullet, moFlailBullet, moFireball, moTongue, moAirball,
|
||||
|
14
flags.cpp
14
flags.cpp
@ -362,6 +362,10 @@ bool slowMover(eMonster m) {
|
||||
m == moTortoise || m == moDraugr;
|
||||
}
|
||||
|
||||
bool isMagneticPole(eMonster m) {
|
||||
return m == moNorthPole || m == moSouthPole;
|
||||
}
|
||||
|
||||
bool normalMover(eMonster m) {
|
||||
return
|
||||
m == moYeti || m == moRanger || m == moGoblin || m == moTroll || m == moDesertman ||
|
||||
@ -386,15 +390,11 @@ bool normalMover(eMonster m) {
|
||||
m == moLavaWolf || m == moSalamander ||
|
||||
m == moHunterGuard || m == moHunterChanging ||
|
||||
m == moIceGolem ||
|
||||
m == moNorthPole || m == moSouthPole ||
|
||||
m == moSwitch1 || m == moSwitch2 ||
|
||||
m == moSwitch1 || m == moSwitch2 || m == moCrusher || m == moPair ||
|
||||
isMagneticPole(m) ||
|
||||
slowMover(m);
|
||||
}
|
||||
|
||||
bool isMagneticPole(eMonster m) {
|
||||
return m == moNorthPole || m == moSouthPole;
|
||||
}
|
||||
|
||||
bool isSwitch(eMonster m) {
|
||||
return m == moSwitch1 || m == moSwitch2;
|
||||
}
|
||||
@ -519,7 +519,7 @@ bool isUnarmed(eMonster m) {
|
||||
}
|
||||
|
||||
bool isArmedEnemy(cell *w, eMonster forwho) {
|
||||
return w->monst != moCrystalSage && isActiveEnemy(w, forwho);
|
||||
return w->monst != moCrystalSage && w->monst != moCrusher && isActiveEnemy(w, forwho);
|
||||
}
|
||||
|
||||
bool isHive(eLand l) {
|
||||
|
158
game.cpp
158
game.cpp
@ -52,6 +52,11 @@ flagtype havewhat, hadwhat;
|
||||
#define HF_VOID Flag(24)
|
||||
#define HF_HUNTER Flag(25)
|
||||
#define HF_FAILED_AMBUSH Flag(26)
|
||||
#define HF_MAGNET Flag(27)
|
||||
#define HF_HEXD Flag(28)
|
||||
#define HF_ALT Flag(29)
|
||||
#define HF_MONK Flag(30)
|
||||
|
||||
|
||||
bool seenSevenMines = false;
|
||||
|
||||
@ -728,27 +733,51 @@ void moveBoatIfUsingOne(cell *to, cell *from) {
|
||||
}
|
||||
}
|
||||
|
||||
bool againstMagnet(cell *c1, cell *c2) { // (from, to)
|
||||
if(!isMagneticPole(c1->monst))
|
||||
return false;
|
||||
forCellEx(c3, c2)
|
||||
if(c3 != c1 && c3->monst == c1->monst)
|
||||
eMonster otherpole(eMonster m) {
|
||||
return eMonster(m ^ moNorthPole ^ moSouthPole);
|
||||
}
|
||||
|
||||
bool againstMagnet(cell *c1, cell *c2, eMonster m) { // (from, to)
|
||||
if(false) forCellEx(c3, c2) {
|
||||
if(c3 == c1) continue;
|
||||
if(c3->monst == m)
|
||||
return true;
|
||||
/* if(c3->monst == otherpole(m) && c3->mov[c3->mondir] != c1) {
|
||||
int i = 0;
|
||||
forCellEx(c4, c3) if(c4->monst == m) i++;
|
||||
if(i == 2) return true;
|
||||
} */
|
||||
}
|
||||
if(c1->monst == m && !isNeighbor(c2, c1->mov[c1->mondir]))
|
||||
return true;
|
||||
forCellEx(c3, c1)
|
||||
if(c3->monst != c1->monst && isMagneticPole(c3->monst))
|
||||
if(c3->monst != m && isMagneticPole(c3->monst))
|
||||
if(!isNeighbor(c3, c2))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool againstPair(cell *c1, cell *c2, eMonster m) { // (from, to)
|
||||
if(c1->monst == m && !isNeighbor(c2, c1->mov[c1->mondir]))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool notNearItem(cell *c) {
|
||||
forCellCM(c2, c) if(c2->item) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool passable_for(eMonster m, cell *w, cell *from, flagtype extra) {
|
||||
if(w->monst && !(extra & P_MONSTER) && !isPlayerOn(w))
|
||||
return false;
|
||||
if(m == moWolf) {
|
||||
return (isIcyLand(w) || w->land == laVolcano) && (isPlayerOn(w) || passable(w, from, extra));
|
||||
}
|
||||
if(isMagneticPole(m) && w && from && againstMagnet(from, w))
|
||||
return false;
|
||||
if(isMagneticPole(m))
|
||||
return !(w && from && againstMagnet(from, w, m)) && passable(w, from, extra);
|
||||
if(m == moPair)
|
||||
return !(w && from && againstPair(from, w, m)) && passable(w, from, extra);
|
||||
if(m == passive_switch) return false;
|
||||
if(normalMover(m) || isBug(m) || isDemon(m) || m == moHerdBull) {
|
||||
if((isWitch(m) || m == moEvilGolem) && w->land != laPower && w->land != laHalloween)
|
||||
@ -803,6 +832,12 @@ bool passable_for(eMonster m, cell *w, cell *from, flagtype extra) {
|
||||
return passable(w, from, extra) && !cellUnstable(w) && ((m != moWorm && m != moTentacle) || !cellEdgeUnstable(w));
|
||||
if(m == moVoidBeast)
|
||||
return passable(w, from, extra | P_VOID);
|
||||
if(m == moHexDemon)
|
||||
return !ctof(w) && passable(w, from, extra);
|
||||
if(m == moAltDemon)
|
||||
return (!w || !from || ctof(w) || ctof(from)) && passable(w, from, extra);
|
||||
if(m == moMonk)
|
||||
return notNearItem(w) && passable(w, from, extra);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -812,6 +847,7 @@ eMonster movegroup(eMonster m) {
|
||||
if(m == moWitchWinter) return moWitchWinter;
|
||||
return moWitch;
|
||||
}
|
||||
// if(isMagneticPole(m)) return m;
|
||||
if(normalMover(m)) return moYeti;
|
||||
if(m == moShark || m == moCShark) return moShark;
|
||||
if(isSlimeMover(m)) return moSlime;
|
||||
@ -832,6 +868,8 @@ eMonster movegroup(eMonster m) {
|
||||
if(m == moAirElemental) return moAirElemental;
|
||||
if(isBull(m)) return moRagingBull;
|
||||
if(m == moVoidBeast) return moVoidBeast;
|
||||
if(m == moAltDemon || m == moHexDemon || m == moMonk)
|
||||
return m;
|
||||
return moNone;
|
||||
}
|
||||
|
||||
@ -893,8 +931,11 @@ bool canAttack(cell *c1, eMonster m1, cell *c2, eMonster m2, flagtype flags) {
|
||||
if((flags & AF_ONLY_FRIEND) && m2 != moPlayer && !isFriendly(c2)) return false;
|
||||
if((flags & AF_ONLY_FBUG) && m2 != moPlayer && !isFriendlyOrBug(c2)) return false;
|
||||
if((flags & AF_ONLY_ENEMY) && (m2 == moPlayer || isFriendlyOrBug(c2))) return false;
|
||||
|
||||
if(m2 == moHedge && !(flags & (AF_STAB | AF_TOUGH | AF_EAT | AF_MAGIC | AF_LANCE | AF_SWORD_INTO | AF_HORNS | AF_BULL)))
|
||||
|
||||
if(among(m2, moAltDemon, moHexDemon, moPair, moCrusher, moNorthPole, moSouthPole, moMonk) && !(flags & (AF_EAT | AF_MAGIC | AF_BULL | AF_CRUSH)))
|
||||
return false;
|
||||
|
||||
if(m2 == moHedge && !(flags & (AF_STAB | AF_TOUGH | AF_EAT | AF_MAGIC | AF_LANCE | AF_SWORD_INTO | AF_HORNS | AF_BULL | AF_CRUSH)))
|
||||
if(!checkOrb(m1, itOrbThorns)) return false;
|
||||
|
||||
// krakens do not try to fight even with Discord
|
||||
@ -905,8 +946,8 @@ bool canAttack(cell *c1, eMonster m1, cell *c2, eMonster m2, flagtype flags) {
|
||||
if(m2 == moDraugr && !(flags & (AF_SWORD | AF_MAGIC | AF_SWORD_INTO | AF_HORNS))) return false;
|
||||
|
||||
// if(m2 == moHerdBull && !(flags & AF_MAGIC)) return false;
|
||||
if(isBull(m2) && !(flags & (AF_MAGIC | AF_HORNS | AF_SWORD_INTO))) return false;
|
||||
if(m2 == moButterfly && !(flags & (AF_MAGIC | AF_BULL | AF_HORNS | AF_SWORD_INTO))) return false;
|
||||
if(isBull(m2) && !(flags & (AF_MAGIC | AF_HORNS | AF_SWORD_INTO | AF_CRUSH))) return false;
|
||||
if(m2 == moButterfly && !(flags & (AF_MAGIC | AF_BULL | AF_HORNS | AF_SWORD_INTO | AF_CRUSH))) return false;
|
||||
|
||||
if(!(flags & AF_NOSHIELD) && ((flags & AF_NEXTTURN) ? checkOrb2 : checkOrb)(m2, itOrbShield)) return false;
|
||||
|
||||
@ -928,7 +969,7 @@ bool canAttack(cell *c1, eMonster m1, cell *c2, eMonster m2, flagtype flags) {
|
||||
if(!(flags & AF_IGNORE_UNARMED) && isUnarmed(m1)) return false;
|
||||
|
||||
if(m2 == moGreater || m2 == moGreaterM)
|
||||
if(!(flags & (AF_MAGIC | AF_SWORD_INTO | AF_HORNS))) return false;
|
||||
if(!(flags & (AF_MAGIC | AF_SWORD_INTO | AF_HORNS | AF_CRUSH))) return false;
|
||||
|
||||
if(!(flags & AF_GUN)) {
|
||||
|
||||
@ -964,10 +1005,10 @@ bool canAttack(cell *c1, eMonster m1, cell *c2, eMonster m2, flagtype flags) {
|
||||
return false;
|
||||
|
||||
if(m2 == moFlailer && !c2->stuntime)
|
||||
if(!(flags & (AF_MAGIC | AF_TOUGH | AF_EAT | AF_HORNS | AF_LANCE | AF_BACK | AF_SWORD_INTO | AF_BULL))) return false;
|
||||
if(!(flags & (AF_MAGIC | AF_TOUGH | AF_EAT | AF_HORNS | AF_LANCE | AF_BACK | AF_SWORD_INTO | AF_BULL | AF_CRUSH))) return false;
|
||||
|
||||
if(m2 == moVizier && c2->hitpoints > 1)
|
||||
if(!(flags & (AF_MAGIC | AF_TOUGH | AF_EAT | AF_HORNS | AF_LANCE | AF_BACK | AF_FAST | AF_BULL))) return false;
|
||||
if(!(flags & (AF_MAGIC | AF_TOUGH | AF_EAT | AF_HORNS | AF_LANCE | AF_BACK | AF_FAST | AF_BULL | AF_CRUSH))) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1117,6 +1158,8 @@ bool krakensafe(cell *c) {
|
||||
eMonster active_switch() {
|
||||
return eMonster(passive_switch ^ moSwitch1 ^ moSwitch2);
|
||||
}
|
||||
|
||||
vector<cell*> crush_now, crush_next;
|
||||
|
||||
int monstersnear(stalemate1& sm) {
|
||||
|
||||
@ -1134,6 +1177,10 @@ int monstersnear(stalemate1& sm) {
|
||||
if(c->wall == waArrowTrap && c->wparam == 2) {
|
||||
which = moArrowTrap; res++;
|
||||
}
|
||||
|
||||
for(auto c1: crush_now) if(c == c1) {
|
||||
which = moCrusher; res++;
|
||||
}
|
||||
|
||||
if(sm.who == moPlayer || items[itOrbEmpathy]) {
|
||||
fast = (items[itOrbSpeed] && (items[itOrbSpeed] & 1));
|
||||
@ -2114,6 +2161,12 @@ void killMonster(cell *c, eMonster who, flagtype deathflags) {
|
||||
c->monst = moTentacletail;
|
||||
else c->monst = moNone;
|
||||
|
||||
if(m == moPair && c->mov[c->mondir]->monst == moPair)
|
||||
killMonster(c->mov[c->mondir], who, deathflags);
|
||||
|
||||
if(isMagneticPole(m) && c->mov[c->mondir]->monst == otherpole(m))
|
||||
killMonster(c->mov[c->mondir], who, deathflags);
|
||||
|
||||
if(m == moEarthElemental) earthWall(c);
|
||||
if(m == moAlbatross && items[itOrbLuck])
|
||||
useupOrb(itOrbLuck, items[itOrbLuck] / 2);
|
||||
@ -2262,6 +2315,7 @@ bool attackMonster(cell *c, flagtype flags, eMonster killer) {
|
||||
}
|
||||
|
||||
if(c->monst == moSkeleton && (flags & AF_SWORD)) dostun = false;
|
||||
if(c->monst == moSkeleton && killer == moCrusher) dostun = false;
|
||||
|
||||
bool eu = elementalUnlocked();
|
||||
bool tu = trollUnlocked();
|
||||
@ -2893,6 +2947,10 @@ void bfs() {
|
||||
else if(c2->monst == moWaterElemental) havewhat |= HF_WATER;
|
||||
else if(c2->monst == moVoidBeast) havewhat |= HF_VOID;
|
||||
else if(c2->monst == moHunterDog) havewhat |= HF_HUNTER;
|
||||
else if(isMagneticPole(c2->monst)) havewhat |= HF_MAGNET;
|
||||
else if(c2->monst == moAltDemon) havewhat |= HF_ALT;
|
||||
else if(c2->monst == moHexDemon) havewhat |= HF_HEXD;
|
||||
else if(c2->monst == moMonk) havewhat |= HF_MONK;
|
||||
else if(c2->monst == moShark || c2->monst == moCShark) havewhat |= HF_SHARK;
|
||||
else if(c2->monst == moAirElemental)
|
||||
havewhat |= HF_AIR, airmap.push_back(make_pair(c2,0));
|
||||
@ -3267,7 +3325,11 @@ void moveMonster(cell *ct, cell *cf) {
|
||||
ct->hitpoints = cf->hitpoints;
|
||||
ct->stuntime = cf->stuntime;
|
||||
|
||||
if(isMagneticPole(m)) {
|
||||
if(isMagneticPole(m) || m == moPair) {
|
||||
if(cf->mondir == 15) {
|
||||
ct->monst = moPirate;
|
||||
return;
|
||||
}
|
||||
cell *other_pole = cf->mov[cf->mondir];
|
||||
if(other_pole) {
|
||||
ct->mondir = neighborId(ct, other_pole),
|
||||
@ -3397,6 +3459,8 @@ void moveMonster(cell *ct, cell *cf) {
|
||||
if(m == moAirElemental) airmap.push_back(make_pair(ct, 0));
|
||||
if(m == moWolf && ct->land == laVolcano) ct->monst = moLavaWolf;
|
||||
if(m == moLavaWolf && isIcyLand(ct)) ct->monst = moWolfMoved;
|
||||
|
||||
if(m == moPair) ct->stuntime++;
|
||||
|
||||
int inc = incline(cf, ct);
|
||||
if(inc == -3 && ct->monst == moReptile)
|
||||
@ -3806,12 +3870,25 @@ cell *moveNormal(cell *c, flagtype mf) {
|
||||
if(!quantum) {
|
||||
cell *c2 = c->mov[d];
|
||||
if(isPlayerOn(c2)) {
|
||||
if(m == moCrusher) {
|
||||
addMessage(XLAT("%The1 raises his weapon...", m));
|
||||
crush_next.push_back(c2);
|
||||
c->stuntime = 7;
|
||||
return c2;
|
||||
}
|
||||
killThePlayerAt(m, c2, 0);
|
||||
return c2;
|
||||
}
|
||||
|
||||
eMonster m2 = c2->monst;
|
||||
if(m2) {
|
||||
|
||||
if(m2 && m == moCrusher) {
|
||||
addMessage(XLAT("%The1 raises his weapon...", m));
|
||||
crush_next.push_back(c2);
|
||||
c->stuntime = 7;
|
||||
return c2;
|
||||
}
|
||||
else if(m2) {
|
||||
attackMonster(c2, AF_ORSTUN | AF_MSG, m);
|
||||
if(m == moFlailer && m2 == moIllusion)
|
||||
attackMonster(c, 0, m2);
|
||||
@ -4274,6 +4351,21 @@ void groupmove2(cell *c, cell *from, int d, eMonster movtype, flagtype mf) {
|
||||
else if(canAttack(c, movtype, from, from->monst, AF_GETPLAYER)) ; */
|
||||
else if(passable_for(movtype, from, c, P_CHAIN | P_MONSTER)) ;
|
||||
else if(canAttack(c, movtype, from, from->monst, AF_GETPLAYER)) ;
|
||||
else if(isMagneticPole(movtype)) {
|
||||
// a special case here -- we have to ignore the illegality of
|
||||
// the 'second' move due to an adjacent opposite pole
|
||||
forCellIdEx(c2, d, c)
|
||||
if(c2->monst == movtype) {
|
||||
cell *c3 = c2->mov[c2->mondir];
|
||||
eMonster m2 = c3->monst;
|
||||
c3->monst = moNone;
|
||||
bool ok =
|
||||
passable_for(movtype, from, c, P_CHAIN | P_MONSTER)
|
||||
&& passable_for(movtype, c, c2, P_CHAIN | P_MONSTER);
|
||||
c3->monst = m2;
|
||||
if(ok) groupmove2(c2, c, d, movtype, mf);
|
||||
}
|
||||
}
|
||||
else return;
|
||||
|
||||
if(from->monst) {
|
||||
@ -4297,9 +4389,9 @@ void groupmove2(cell *c, cell *from, int d, eMonster movtype, flagtype mf) {
|
||||
// Kraken movement
|
||||
if(movtype == moKrakenH && c->monst == moKrakenT && c->stuntime == 0)
|
||||
kraken::trymove(c);
|
||||
|
||||
if(movegroup(c->monst) == movtype) {
|
||||
|
||||
if(movegroup(c->monst) == movtype) {
|
||||
|
||||
int af = AF_ONLY_FBUG | AF_GETPLAYER;
|
||||
if(mf & MF_MOUNT) af = 0;
|
||||
|
||||
@ -5268,6 +5360,18 @@ void moverefresh(bool turn = true) {
|
||||
if(c->monst == moGreater && !cellEdgeUnstable(c)) c->monst = moGreaterM;
|
||||
else if(c->monst == moGreaterM) c->monst = moGreater;
|
||||
|
||||
if(c->monst == moPair && !c->stuntime) {
|
||||
cell *c2 = c->mov[c->mondir];
|
||||
if(c2->monst != moPair) continue;
|
||||
if(!c2->stuntime) {
|
||||
cell *c3 = c->mov[(c->mondir + 1) % c->type];
|
||||
if(c3->wall == waColumn) {
|
||||
drawParticles(c3, 0xC00000, 30);
|
||||
c3->wall = waNone;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(c->stuntime && !isMutantIvy(c)) {
|
||||
c->stuntime--;
|
||||
int breathrange = sphere ? 2 : 3;
|
||||
@ -5622,6 +5726,14 @@ void movemonsters() {
|
||||
if(havewhat & HF_WHIRLWIND) whirlwind::move();
|
||||
DEBT("river");
|
||||
if(havewhat & HF_RIVER) prairie::move();
|
||||
/* DEBT("magnet");
|
||||
if(havewhat & HF_MAGNET)
|
||||
groupmove(moSouthPole, 0),
|
||||
groupmove(moNorthPole, 0); */
|
||||
DEBT("bugs");
|
||||
if(havewhat & HF_HEXD) groupmove(moHexDemon, 0);
|
||||
if(havewhat & HF_ALT) groupmove(moAltDemon, 0);
|
||||
if(havewhat & HF_MONK) groupmove(moMonk, 0);
|
||||
|
||||
DEBT("worm");
|
||||
cell *savepos[MAXPLAYER];
|
||||
@ -6905,6 +7017,14 @@ void monstersTurn() {
|
||||
if(!phase1) livecaves();
|
||||
if(!phase1) ca::simulate();
|
||||
if(!phase1) heat::processfires();
|
||||
|
||||
for(cell *c: crush_now)
|
||||
if(canAttack(c, moCrusher, c, c->monst, AF_GETPLAYER | AF_CRUSH))
|
||||
attackMonster(c, AF_ORSTUN | AF_MSG | AF_GETPLAYER | AF_CRUSH, moCrusher);
|
||||
|
||||
crush_now = move(crush_next);
|
||||
crush_next.clear();
|
||||
|
||||
DEBT("heat");
|
||||
heat::processheat();
|
||||
// if(elec::havecharge) elec::drawcharges();
|
||||
|
12
graph.cpp
12
graph.cpp
@ -1219,6 +1219,13 @@ bool drawMonsterType(eMonster m, cell *where, const transmatrix& V, int col, dou
|
||||
if(!peace::on) queuepoly(VBODY, shPSword, 0xFFFF00FF);
|
||||
queuepoly(VHEAD, shHood, darkena(col, 0, 0xFF));
|
||||
}
|
||||
else if(m == moPair || m == moAltDemon || m == moHexDemon || m == moMonk || m == moCrusher) {
|
||||
otherbodyparts(V, darkena(col, 0, 0xC0), m, footphase);
|
||||
ShadowV(V, shPBody);
|
||||
queuepoly(VBODY, shPBody, darkena(col, 0, 0xC0));
|
||||
if(!peace::on) queuepoly(VBODY, shPSword, 0xFFFF00FF);
|
||||
queuepoly(VHEAD, shHood, darkena(col, 0, 0xFF));
|
||||
}
|
||||
else if(m == moPalace || m == moFatGuard || m == moVizier || m == moSkeleton) {
|
||||
queuepoly(VBODY, shSabre, 0xFFFFFFFF);
|
||||
if(m == moSkeleton) {
|
||||
@ -1929,7 +1936,7 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, int col) {
|
||||
// also whatever in the lineview mode
|
||||
|
||||
else if(isFriendly(c) || isBug(c) || (c->monst && conformal::on) || c->monst == moKrakenH || (isBull(c->monst) && c->mondir != NODIR) || c->monst == moButterfly || isMagneticPole(c->monst) ||
|
||||
isSwitch(c->monst)) {
|
||||
isSwitch(c->monst) || c->monst == moPair) {
|
||||
if(c->monst == moKrakenH) Vs = Vb, nospins = nospinb;
|
||||
if(!nospins) Vs = Vs * ddspin(c, c->mondir, S42);
|
||||
if(isFriendly(c)) drawPlayerEffects(Vs, c, false);
|
||||
@ -4724,6 +4731,9 @@ void queuecircleat(cell *c, double rad, int col) {
|
||||
void drawMarkers() {
|
||||
|
||||
if(!(cmode & sm::NORMAL)) return;
|
||||
|
||||
for(cell *c1: crush_now)
|
||||
queuecircleat(c1, .8, darkena(minf[moCrusher].color, 0, 0xFF));
|
||||
|
||||
if(!inHighQual) {
|
||||
|
||||
|
7
hyper.h
7
hyper.h
@ -824,6 +824,7 @@ void setGLProjection();
|
||||
#define P_REPTILE Flag(31) // is reptile
|
||||
#define P_VOID Flag(32) // void beast
|
||||
#define P_PHASE Flag(33) // phasing movement
|
||||
#define P_PULLMAGNET Flag(34) // pull the other part of the magnet
|
||||
|
||||
bool passable(cell *w, cell *from, flagtype flags);
|
||||
|
||||
@ -1007,6 +1008,7 @@ bool withRose(cell *cfrom, cell *cto);
|
||||
#define AF_HORNS Flag(28) // spear attack (always has APPROACH too)
|
||||
#define AF_BULL Flag(29) // bull attack
|
||||
#define AF_SIDE Flag(30) // side attack
|
||||
#define AF_CRUSH Flag(31) // Crusher's delayed attack
|
||||
|
||||
bool canAttack(cell *c1, eMonster m1, cell *c2, eMonster m2, flagtype flags);
|
||||
|
||||
@ -1645,9 +1647,8 @@ void displaymm(char c, int x, int y, int rad, int size, const string& title, int
|
||||
bool canPushThumperOn(cell *tgt, cell *thumper, cell *player);
|
||||
void pushThumper(cell *th, cell *cto);
|
||||
|
||||
template<class T> T pick(T x, T y) { return hrand(2) ? x : y; }
|
||||
template<class T> T pick(T x, T y, T z) { switch(hrand(3)) { case 0: return x; case 1: return y; case 2: return z; } return x; }
|
||||
template<class T> T pick(T x, T y, T z, T v) { switch(hrand(4)) { case 0: return x; case 1: return y; case 2: return z; case 3: return v; } return x; }
|
||||
template<class T, class... U> T pick(T x, U... u) { std::initializer_list<T> i = {x,u...}; return *(i.begin() + hrand(1+sizeof...(u))); }
|
||||
|
||||
template<class T, class V, class... U> bool among(T x, V y) { return x == y; }
|
||||
template<class T, class V, class... U> bool among(T x, V y, U... u) { return x==y || among(x,u...); }
|
||||
|
||||
|
34
landgen.cpp
34
landgen.cpp
@ -1902,6 +1902,40 @@ void giantLandSwitch(cell *c, int d, cell *from) {
|
||||
}
|
||||
break;
|
||||
|
||||
case laInvincible: {
|
||||
int kf = 10 + items[itInvix] + yendor::hardness();
|
||||
if(d == 8) {
|
||||
if(windmap::at(c) >= 128) {
|
||||
if(hrand(100) < 3)
|
||||
c->wall = waColumn;
|
||||
}
|
||||
else if(hrand(100) < 75) {
|
||||
forCellEx(c2, c) if(windmap::at(c2) >= 128)
|
||||
c->wall = waColumn;
|
||||
}
|
||||
if(hrand(1000) < 2)
|
||||
c->wall = waColumn;
|
||||
if(hrand(50000) < kf && !c->monst && !c->wall) {
|
||||
cell *c1 = c;
|
||||
cell *c2 = createMov(c1, hrand(c1->type));
|
||||
if(c2->monst || c2->wall) return;
|
||||
c1->monst = moPair;
|
||||
c2->monst = moPair;
|
||||
c1->mondir = neighborId(c1, c2);
|
||||
c2->mondir = neighborId(c2, c1);
|
||||
}
|
||||
}
|
||||
ONEMPTY {
|
||||
if(hrand(10000) < kf && !c->monst) {
|
||||
c->monst = pick(moHexDemon, moAltDemon, moMonk, moSkeleton, moCrusher);
|
||||
c->hitpoints = 3;
|
||||
}
|
||||
if(hrand(1500) < PT(30 + kills[moHexDemon] + kills[moSkeleton] + kills[moMonk] + kills[moPair], 100) && notDippingFor(itInvix))
|
||||
c->item = itInvix;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case laDocks: {
|
||||
if(d == 8) {
|
||||
patterns::patterninfo si;
|
||||
|
@ -1194,5 +1194,7 @@ auto cgm = addHook(clearmemory, 40, [] () {
|
||||
recallCell = NULL;
|
||||
butterflies.clear();
|
||||
buggycells.clear();
|
||||
crush_next.clear();
|
||||
crush_now.clear();
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user