mirror of
				https://github.com/zenorogue/hyperrogue.git
				synced 2025-10-31 05:52:59 +00:00 
			
		
		
		
	Strong Wind and Orb of Vaulting now better with Orb of the Sword
This commit is contained in:
		| @@ -162,15 +162,19 @@ EX namespace whirlwind { | |||||||
|       } |       } | ||||||
|     } |     } | ||||||
|    |    | ||||||
|   EX cell *jumpFromWhereTo(cell *c, bool player) { |   EX cell *jumpFromWhereTo(cell *c, bool player, struct jumpdata& jdata) { | ||||||
|  |     jdata.uniq = true; | ||||||
|     for(int i=0; i<2; i++) { |     for(int i=0; i<2; i++) { | ||||||
|       calcdirs(c); |       calcdirs(c); | ||||||
|       if(qdirs != 1) return NULL; |       if(qdirs != 1) return NULL; | ||||||
|  |       auto mi = movei(c, dfrom[0]); | ||||||
|  |       jdata.moves.push_back(mi.rev()); | ||||||
|       cell *c2 = c->move(dfrom[0]); |       cell *c2 = c->move(dfrom[0]); | ||||||
|       if(!passable(c, c2, P_JUMP1)) return NULL; |       if(!passable(c, c2, P_JUMP1)) return NULL; | ||||||
|       if(player && i == 0 && !passable(c, c2, P_ISPLAYER)) return NULL; |       if(player && i == 0 && !passable(c, c2, P_ISPLAYER)) return NULL; | ||||||
|       c = c2; |       c = c2; | ||||||
|       } |       } | ||||||
|  |     reverse(jdata.moves.begin(), jdata.moves.end()); | ||||||
|     calcdirs(c); |     calcdirs(c); | ||||||
|     if(qdirs != 1) return NULL; |     if(qdirs != 1) return NULL; | ||||||
|     return c; |     return c; | ||||||
|   | |||||||
| @@ -502,6 +502,16 @@ struct movei { | |||||||
|   }; |   }; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | #if HDR | ||||||
|  | struct jumpdata { | ||||||
|  |   eMonster dashmon; | ||||||
|  |   cell *jumpthru; | ||||||
|  |   bool uniq; | ||||||
|  |   vector<movei> moves; | ||||||
|  |   jumpdata() { dashmon = moNone; jumpthru = nullptr; uniq = false; } | ||||||
|  |   }; | ||||||
|  | #endif | ||||||
|  |  | ||||||
| EX movei moveimon(cell *c) { return movei(c, c->mondir); } | EX movei moveimon(cell *c) { return movei(c, c->mondir); } | ||||||
|  |  | ||||||
| EX movei match(cell *f, cell *t) { | EX movei match(cell *f, cell *t) { | ||||||
|   | |||||||
| @@ -1224,7 +1224,8 @@ EX void groupmove(eMonster movtype, flagtype mf) { | |||||||
|       } |       } | ||||||
|        |        | ||||||
|     if(movtype == moEagle && c->monst == moNone && !isPlayerOn(c) && !bird_disruption(c)) { |     if(movtype == moEagle && c->monst == moNone && !isPlayerOn(c) && !bird_disruption(c)) { | ||||||
|       cell *c2 = whirlwind::jumpFromWhereTo(c, false); |       jumpdata jdata; | ||||||
|  |       cell *c2 = whirlwind::jumpFromWhereTo(c, false, jdata); | ||||||
|       groupmove2(movei(c2, c, STRONGWIND), movtype, mf); |       groupmove2(movei(c2, c, STRONGWIND), movtype, mf); | ||||||
|       } |       } | ||||||
|      |      | ||||||
|   | |||||||
							
								
								
									
										76
									
								
								orbs.cpp
									
									
									
									
									
								
							
							
						
						
									
										76
									
								
								orbs.cpp
									
									
									
									
									
								
							| @@ -665,12 +665,13 @@ EX void teleportTo(cell *dest) { | |||||||
|   } |   } | ||||||
|  |  | ||||||
| /* calls changes.rollback or changes.commit */ | /* calls changes.rollback or changes.commit */ | ||||||
| EX bool jumpTo(orbAction a, cell *dest, eItem byWhat, int bonuskill IS(0), eMonster dashmon IS(moNone), cell *phasecell IS(nullptr)) { | EX bool jumpTo(orbAction a, cell *dest, eItem byWhat, int bonuskill, jumpdata jdata) { | ||||||
|   if(byWhat != itStrongWind) playSound(dest, "orb-frog"); |   if(byWhat != itStrongWind) playSound(dest, "orb-frog"); | ||||||
|   cell *from = cwt.at; |   cell *from = cwt.at; | ||||||
|   changes.value_keep(cwt); |   changes.value_keep(cwt); | ||||||
|   changes.ccell(dest); |   changes.ccell(dest); | ||||||
|   changes.ccell(cwt.at); |   changes.ccell(cwt.at); | ||||||
|  |   changes.value_keep(sword::dir); | ||||||
|  |  | ||||||
|   if(byWhat == itOrbFrog) { |   if(byWhat == itOrbFrog) { | ||||||
|     useupOrb(itOrbFrog, 5); |     useupOrb(itOrbFrog, 5); | ||||||
| @@ -679,11 +680,12 @@ EX bool jumpTo(orbAction a, cell *dest, eItem byWhat, int bonuskill IS(0), eMons | |||||||
|    |    | ||||||
|   if(byWhat == itOrbDash) { |   if(byWhat == itOrbDash) { | ||||||
|     useupOrb(itOrbDash, 5); |     useupOrb(itOrbDash, 5); | ||||||
|     if(dashmon) addMessage(XLAT("You vault over %the1!", dashmon)); |     if(jdata.dashmon) addMessage(XLAT("You vault over %the1!", jdata.dashmon)); | ||||||
|     } |     } | ||||||
|    |    | ||||||
|   if(byWhat == itOrbPhasing) { |   if(byWhat == itOrbPhasing) { | ||||||
|     useupOrb(itOrbPhasing, 5); |     useupOrb(itOrbPhasing, 5); | ||||||
|  |     cell *phasecell = jdata.jumpthru; | ||||||
|     if(phasecell->monst) |     if(phasecell->monst) | ||||||
|       addMessage(XLAT("You phase through %the1!", phasecell->monst)); |       addMessage(XLAT("You phase through %the1!", phasecell->monst)); | ||||||
|     else |     else | ||||||
| @@ -703,7 +705,22 @@ EX bool jumpTo(orbAction a, cell *dest, eItem byWhat, int bonuskill IS(0), eMons | |||||||
|     flipplayer = true; |     flipplayer = true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   sword::reset(); |   if(jdata.uniq) { | ||||||
|  |     int numbb[2]; | ||||||
|  |     println(hlog, "moves = ", isize(jdata.moves)); | ||||||
|  |     for(int a=0; a<2; a++) numbb[a] = 0; | ||||||
|  |     for(int a=0; a<2; a++) { | ||||||
|  |       cell *mt = jdata.moves[a].t; | ||||||
|  |       do_swords(jdata.moves[a], moPlayer, | ||||||
|  |         [&] (cell *c, int bb) { if(swordAttack(mt, moPlayer, c, bb)) numbb[bb]++; }); | ||||||
|  |       sword::dir[multi::cpid] = sword::shift(jdata.moves[a], sword::dir[multi::cpid]); | ||||||
|  |       } | ||||||
|  |     for(int bb=0; bb<2; bb++) achievement_count("SLASH", numbb[bb], 0); | ||||||
|  |     } | ||||||
|  |   else { | ||||||
|  |     sword::reset(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|   auto mi = movei(c1, dest, JUMP); |   auto mi = movei(c1, dest, JUMP); | ||||||
|   stabbingAttack(mi, moPlayer, bonuskill); |   stabbingAttack(mi, moPlayer, bonuskill); | ||||||
|   playerMoveEffects(mi); |   playerMoveEffects(mi); | ||||||
| @@ -1243,11 +1260,11 @@ EX movei blowoff_destination(cell *c, int& di) { | |||||||
|   return blowoff_destination_dir(c, di, rev); |   return blowoff_destination_dir(c, di, rev); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| EX int check_jump(cell *cf, cell *ct, flagtype flags, cell*& jumpthru) { | EX int check_jump(cell *cf, cell *ct, flagtype flags, jumpdata& jdata) { | ||||||
|   int partial = 1; |   int partial = 1; | ||||||
|   forCellCM(c2, cf) { |   forCellCM(c2, cf) { | ||||||
|     if(isNeighbor(c2, ct)) { |     if(isNeighbor(c2, ct)) { | ||||||
|       jumpthru = c2; |       jdata.jumpthru = c2; | ||||||
|       if(passable(c2, cf, flags | P_JUMP1)) { |       if(passable(c2, cf, flags | P_JUMP1)) { | ||||||
|         partial = 2; |         partial = 2; | ||||||
|         if(passable(ct, c2, flags | P_JUMP2)) { |         if(passable(ct, c2, flags | P_JUMP2)) { | ||||||
| @@ -1259,11 +1276,11 @@ EX int check_jump(cell *cf, cell *ct, flagtype flags, cell*& jumpthru) { | |||||||
|   return partial; |   return partial; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| EX int check_phase(cell *cf, cell *ct, flagtype flags, cell*& jumpthru) { | EX int check_phase(cell *cf, cell *ct, flagtype flags, jumpdata& jdata) { | ||||||
|   int partial = 1; |   int partial = 1; | ||||||
|   forCellCM(c2, cf) { |   forCellCM(c2, cf) { | ||||||
|     if(isNeighbor(c2, ct) && !nonAdjacent(cf, c2) && !nonAdjacent(c2, ct)) { |     if(isNeighbor(c2, ct) && !nonAdjacent(cf, c2) && !nonAdjacent(c2, ct)) { | ||||||
|       jumpthru = c2; |       jdata.jumpthru = c2; | ||||||
|       if(passable(ct, cf, flags | P_PHASE)) { |       if(passable(ct, cf, flags | P_PHASE)) { | ||||||
|         partial = 2; |         partial = 2; | ||||||
|         if(c2->monst || (isWall(c2) && c2->wall != waShrub)) { |         if(c2->monst || (isWall(c2) && c2->wall != waShrub)) { | ||||||
| @@ -1295,14 +1312,17 @@ EX void apply_impact(cell *c) { | |||||||
|       } |       } | ||||||
|   } |   } | ||||||
|  |  | ||||||
| EX int check_vault(cell *cf, cell *ct, flagtype flags, cell*& jumpthru) { | EX int check_vault(cell *cf, cell *ct, flagtype flags, jumpdata& jdata) { | ||||||
|   cell *c2 = NULL, *c3 = NULL;     |   cell *c2 = NULL, *c3 = NULL;     | ||||||
|   forCellCM(cc, cf) { |   forCellCM(cc, cf) { | ||||||
|     if(isNeighbor(cc, ct) && c2 != cc) c3 = c2, c2 = cc; |     if(isNeighbor(cc, ct) && c2 != cc) c3 = c2, c2 = cc; | ||||||
|     } |     } | ||||||
|   jumpthru = c2; |  | ||||||
|   if(!c2) return 0; |   if(!c2) return 0; | ||||||
|   if(c3) return 1; |   if(c3) return 1; | ||||||
|  |   jdata.moves.push_back(movei(cf, c2, neighborId(cf, c2))); | ||||||
|  |   jdata.moves.push_back(movei(c2, ct, neighborId(c2, ct))); | ||||||
|  |   jdata.jumpthru = c2; | ||||||
|  |   jdata.uniq = true; | ||||||
|   bool cutwall = among(c2->wall, waShrub, waExplosiveBarrel, waSmallTree, waBigTree); |   bool cutwall = among(c2->wall, waShrub, waExplosiveBarrel, waSmallTree, waBigTree); | ||||||
|   if(!c2->monst && !cutwall) return 2; |   if(!c2->monst && !cutwall) return 2; | ||||||
|   bool for_monster = !(flags & P_ISPLAYER); |   bool for_monster = !(flags & P_ISPLAYER); | ||||||
| @@ -1363,11 +1383,13 @@ EX eItem targetRangedOrb(cell *c, orbAction a) { | |||||||
|   bool wouldkill_there = false; |   bool wouldkill_there = false; | ||||||
|   bool wouldkill_here = false; |   bool wouldkill_here = false; | ||||||
|  |  | ||||||
|  |   jumpdata jdata; | ||||||
|  |  | ||||||
|   // (0-) strong wind |   // (0-) strong wind | ||||||
|   if(items[itStrongWind] |   if(items[itStrongWind] | ||||||
|     && CHK(c->cpdist == 2 && cwt.at == whirlwind::jumpFromWhereTo(c, true), XLAT("Strong wind can only take you to a specific place!"))) { |     && CHK(c->cpdist == 2 && cwt.at == whirlwind::jumpFromWhereTo(c, true, jdata), XLAT("Strong wind can only take you to a specific place!"))) { | ||||||
|     changes.init(isCheck(a)); |     changes.init(isCheck(a)); | ||||||
|     if(jumpTo(a, c, itStrongWind)) return itStrongWind; |     if(jumpTo(a, c, itStrongWind, 0, jdata)) return itStrongWind; | ||||||
|     } |     } | ||||||
|    |    | ||||||
|   // (0x) control |   // (0x) control | ||||||
| @@ -1450,25 +1472,23 @@ EX eItem targetRangedOrb(cell *c, orbAction a) { | |||||||
|     else changes.rollback(); |     else changes.rollback(); | ||||||
|     } |     } | ||||||
|      |      | ||||||
|   // (0'') jump |  | ||||||
|   cell *jumpthru = NULL; |  | ||||||
|    |  | ||||||
|   // orb of vaulting |   // orb of vaulting | ||||||
|   if(!shmup::on && items[itOrbDash] && CHK(c->cpdist == 2, XLAT("Cannot vault that far!"))) { |   if(!shmup::on && items[itOrbDash] && CHK(c->cpdist == 2, XLAT("Cannot vault that far!"))) { | ||||||
|     changes.init(isCheck(a)); |     changes.init(isCheck(a)); | ||||||
|     int vaultstate = check_vault(cwt.at, c, P_ISPLAYER, jumpthru); |     int vaultstate = check_vault(cwt.at, c, P_ISPLAYER, jdata); | ||||||
|  |  | ||||||
|     if(vaultstate == 0) orb_error_messages.push_back(XLAT("ERROR: No common neighbor to vault through!")); |     if(vaultstate == 0) orb_error_messages.push_back(XLAT("ERROR: No common neighbor to vault through!")); | ||||||
|     if(vaultstate == 1) orb_error_messages.push_back(XLAT("Can only vault in a roughly straight line!")); |     if(vaultstate == 1) orb_error_messages.push_back(XLAT("Can only vault in a roughly straight line!")); | ||||||
|     if(vaultstate == 2) orb_error_messages.push_back(XLAT("Nothing to vault over!")); |     if(vaultstate == 2) orb_error_messages.push_back(XLAT("Nothing to vault over!")); | ||||||
|     if(vaultstate == 3) orb_error_messages.push_back(XLAT("Cannot pass through %the1 while vaulting!", jumpthru->wall)); |     if(vaultstate == 3) orb_error_messages.push_back(XLAT("Cannot pass through %the1 while vaulting!", jdata.jumpthru->wall)); | ||||||
|     if(vaultstate == 4 && c->monst) orb_error_messages.push_back(XLAT("Cannot vault onto %the1!", c->monst)); |     if(vaultstate == 4 && c->monst) orb_error_messages.push_back(XLAT("Cannot vault onto %the1!", c->monst)); | ||||||
|     if(vaultstate == 4 && !c->monst) orb_error_messages.push_back(XLAT("Cannot vault to %the1!", c->wall)); |     if(vaultstate == 4 && !c->monst) orb_error_messages.push_back(XLAT("Cannot vault to %the1!", c->wall)); | ||||||
|     if(vaultstate == 5) orb_error_messages.push_back(XLAT("Cannot attack %the1 while vaulting!", jumpthru->monst)); |     if(vaultstate == 5) orb_error_messages.push_back(XLAT("Cannot attack %the1 while vaulting!", jdata.jumpthru->monst)); | ||||||
|  |  | ||||||
|     if(vaultstate == 6) { |     if(vaultstate == 6) { | ||||||
|       int k = tkills(); |       int k = tkills(); | ||||||
|       eMonster m = jumpthru->monst; |       auto& jumpthru = jdata.jumpthru; | ||||||
|  |       jdata.dashmon = jumpthru->monst; | ||||||
|       if(jumpthru->wall == waShrub) { |       if(jumpthru->wall == waShrub) { | ||||||
|         addMessage(XLAT("You chop down the shrub.")); |         addMessage(XLAT("You chop down the shrub.")); | ||||||
|         jumpthru->wall = waNone; |         jumpthru->wall = waNone; | ||||||
| @@ -1484,10 +1504,10 @@ EX eItem targetRangedOrb(cell *c, orbAction a) { | |||||||
|       if(jumpthru->wall == waExplosiveBarrel) { |       if(jumpthru->wall == waExplosiveBarrel) { | ||||||
|         explodeBarrel(jumpthru); |         explodeBarrel(jumpthru); | ||||||
|         } |         } | ||||||
|       if(m) |       if(jdata.dashmon) | ||||||
|         attackMonster(jumpthru, AF_NORMAL | AF_MSG, moPlayer); |         attackMonster(jumpthru, AF_NORMAL | AF_MSG, moPlayer); | ||||||
|       k = tkills() - k; |       k = tkills() - k; | ||||||
|       if(jumpTo(a, c, itOrbDash, k, m)) vaultstate = 7; |       if(jumpTo(a, c, itOrbDash, k, jdata)) vaultstate = 7; | ||||||
|       else wouldkill_there = true; |       else wouldkill_there = true; | ||||||
|       if(vaultstate == 7) return itOrbDash; |       if(vaultstate == 7) return itOrbDash; | ||||||
|       } |       } | ||||||
| @@ -1496,12 +1516,12 @@ EX eItem targetRangedOrb(cell *c, orbAction a) { | |||||||
|    |    | ||||||
|   if(items[itOrbFrog] && CHK(c->cpdist == 2, XLAT("Cannot jump that far!"))) { |   if(items[itOrbFrog] && CHK(c->cpdist == 2, XLAT("Cannot jump that far!"))) { | ||||||
|     changes.init(isCheck(a)); |     changes.init(isCheck(a)); | ||||||
|     int frogstate = check_jump(cwt.at, c, P_ISPLAYER, jumpthru); |     int frogstate = check_jump(cwt.at, c, P_ISPLAYER, jdata); | ||||||
|     if(frogstate == 1 && jumpthru && jumpthru->monst) { |     if(frogstate == 1 && jdata.jumpthru && jdata.jumpthru->monst) { | ||||||
|       orb_error_messages.push_back(XLAT("Cannot jump through %the1!", jumpthru->monst)); |       orb_error_messages.push_back(XLAT("Cannot jump through %the1!", jdata.jumpthru->monst)); | ||||||
|       } |       } | ||||||
|     else if(frogstate == 1 && jumpthru) { |     else if(frogstate == 1 && jdata.jumpthru) { | ||||||
|       orb_error_messages.push_back(XLAT("Cannot jump through %the1!", jumpthru->wall)); |       orb_error_messages.push_back(XLAT("Cannot jump through %the1!", jdata.jumpthru->wall)); | ||||||
|       } |       } | ||||||
|     else if(frogstate == 2 && c->monst) { |     else if(frogstate == 2 && c->monst) { | ||||||
|       orb_error_messages.push_back(XLAT("Cannot jump onto %the1!", c->monst)); |       orb_error_messages.push_back(XLAT("Cannot jump onto %the1!", c->monst)); | ||||||
| @@ -1511,7 +1531,7 @@ EX eItem targetRangedOrb(cell *c, orbAction a) { | |||||||
|       } |       } | ||||||
|  |  | ||||||
|     if(frogstate == 3) { |     if(frogstate == 3) { | ||||||
|       if(jumpTo(a, c, itOrbFrog)) frogstate = 4; |       if(jumpTo(a, c, itOrbFrog, 0, jdata)) frogstate = 4; | ||||||
|       else wouldkill_there = true; |       else wouldkill_there = true; | ||||||
|       if(frogstate == 4) return itOrbFrog; |       if(frogstate == 4) return itOrbFrog; | ||||||
|       } |       } | ||||||
| @@ -1521,7 +1541,7 @@ EX eItem targetRangedOrb(cell *c, orbAction a) { | |||||||
|   if(items[itOrbPhasing] && CHK(c->cpdist == 2, XLAT("Cannot phase that far!"))) { |   if(items[itOrbPhasing] && CHK(c->cpdist == 2, XLAT("Cannot phase that far!"))) { | ||||||
|     changes.init(isCheck(a)); |     changes.init(isCheck(a)); | ||||||
|     if(shmup::on) shmup::pushmonsters(); |     if(shmup::on) shmup::pushmonsters(); | ||||||
|     int phasestate = check_phase(cwt.at, c, P_ISPLAYER, jumpthru); |     int phasestate = check_phase(cwt.at, c, P_ISPLAYER, jdata); | ||||||
|     if(phasestate == 1 && c->monst) { |     if(phasestate == 1 && c->monst) { | ||||||
|       orb_error_messages.push_back(XLAT("Cannot phase onto %the1!", c->monst)); |       orb_error_messages.push_back(XLAT("Cannot phase onto %the1!", c->monst)); | ||||||
|       } |       } | ||||||
| @@ -1533,7 +1553,7 @@ EX eItem targetRangedOrb(cell *c, orbAction a) { | |||||||
|       } |       } | ||||||
|  |  | ||||||
|     if(phasestate == 3) { |     if(phasestate == 3) { | ||||||
|       if(jumpTo(a, c, itOrbPhasing, 0, moNone, jumpthru)) phasestate = 4; |       if(jumpTo(a, c, itOrbPhasing, 0, jdata)) phasestate = 4; | ||||||
|       else wouldkill_there = true; |       else wouldkill_there = true; | ||||||
|       } |       } | ||||||
|     else changes.rollback(); |     else changes.rollback(); | ||||||
|   | |||||||
| @@ -475,7 +475,7 @@ EX bool isNeighbor1(cell *f, cell *w) { | |||||||
|   } |   } | ||||||
|  |  | ||||||
| EX bool passable_for(eMonster m, cell *w, cell *from, flagtype extra) { | EX bool passable_for(eMonster m, cell *w, cell *from, flagtype extra) { | ||||||
|   cell *dummy; |   jumpdata jdummy; | ||||||
|   if(w->monst && !(extra & P_MONSTER) && !isPlayerOn(w))  |   if(w->monst && !(extra & P_MONSTER) && !isPlayerOn(w))  | ||||||
|     return false; |     return false; | ||||||
|   if(m == moWolf) { |   if(m == moWolf) { | ||||||
| @@ -573,12 +573,12 @@ EX bool passable_for(eMonster m, cell *w, cell *from, flagtype extra) { | |||||||
|     } |     } | ||||||
|   #endif |   #endif | ||||||
|   if(m == moFrog) { |   if(m == moFrog) { | ||||||
|     return isNeighbor1(from, w) ? passable(w, from, extra) : check_jump(from, w, extra, dummy) == 3; |     return isNeighbor1(from, w) ? passable(w, from, extra) : check_jump(from, w, extra, jdummy) == 3; | ||||||
|     } |     } | ||||||
|   if(m == moPhaser) |   if(m == moPhaser) | ||||||
|     return isNeighbor1(from, w) ? passable(w, from, extra) : check_phase(from, w, extra, dummy) == 3; |     return isNeighbor1(from, w) ? passable(w, from, extra) : check_phase(from, w, extra, jdummy) == 3; | ||||||
|   if(m == moVaulter) |   if(m == moVaulter) | ||||||
|     return isNeighbor1(from, w) ? passable(w, from, extra) : check_vault(from, w, extra, dummy) == 6; |     return isNeighbor1(from, w) ? passable(w, from, extra) : check_vault(from, w, extra, jdummy) == 6; | ||||||
|   if(m == moAltDemon) { |   if(m == moAltDemon) { | ||||||
|     if(extra & P_ONPLAYER) { |     if(extra & P_ONPLAYER) { | ||||||
|       if(isPlayerOn(w)) return true; |       if(isPlayerOn(w)) return true; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Zeno Rogue
					Zeno Rogue