mirror of
				https://github.com/zenorogue/hyperrogue.git
				synced 2025-10-30 21:42:59 +00:00 
			
		
		
		
	Invinc monsters implemented
This commit is contained in:
		| @@ -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(); | ||||
|   }); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Zeno Rogue
					Zeno Rogue