From 2636b195a24a51c4f7b4e0ec4d023d925a6dc5a7 Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Sat, 29 Feb 2020 19:19:16 +0100 Subject: [PATCH] fixed Orbs in undo --- items.cpp | 10 +++++ orbs.cpp | 57 +++++++++++++++++------------ pcmove.cpp | 105 +++++++++++++++++++++++++---------------------------- 3 files changed, 93 insertions(+), 79 deletions(-) diff --git a/items.cpp b/items.cpp index 57ef6436..bbcecaa3 100644 --- a/items.cpp +++ b/items.cpp @@ -128,10 +128,20 @@ EX bool collectItem(cell *c2, bool telekinesis IS(false)) { #if CAP_TOUR else if(tour::on && (c2->item == itOrbSafety || c2->item == itOrbRecall)) { addMessage(XLAT("This Orb is not compatible with the Tutorial.")); + if(changes.on) changes.rollback(); return true; } #endif else if(c2->item == itOrbSafety) { + + if(changes.on) { + if(changes.checking) { + changes.rollback(); + return true; + } + changes.commit(); + } + playSound(c2, "pickup-orb"); // TODO safety if(!dual::state) items[c2->item] = 7; if(shmup::on) diff --git a/orbs.cpp b/orbs.cpp index de9a570d..0a2e997e 100644 --- a/orbs.cpp +++ b/orbs.cpp @@ -593,6 +593,9 @@ void teleportTo(cell *dest) { EX bool jumpTo(orbAction a, cell *dest, eItem byWhat, int bonuskill IS(0), eMonster dashmon IS(moNone)) { if(byWhat != itStrongWind) playSound(dest, "orb-frog"); cell *from = cwt.at; + changes.value_keep(cwt); + changes.ccell(dest); + changes.ccell(cwt.at); if(byWhat == itOrbFrog) { useupOrb(itOrbFrog, 5); @@ -615,14 +618,34 @@ EX bool jumpTo(orbAction a, cell *dest, eItem byWhat, int bonuskill IS(0), eMons cell *c1 = cwt.at; animateMovement(match(cwt.at, dest), LAYER_SMALL); - current_display->which_copy = ggmatrix(dest); cwt.at = dest; forCellIdEx(c2, i, dest) if(c2->cpdist < dest->cpdist) { cwt.spin = i; flipplayer = true; } - if(!monstersnearO(a, dest, moPlayer, NULL, cwt.at)) { + sword::reset(); + stabbingAttack(c1, dest, moPlayer, bonuskill); + playerMoveEffects(c1, dest); + + if(itemclass(byWhat) == IC_ORB) + apply_impact(dest); + + // do not apply movecost later, when from no longer exists + if(cwt.at->item == itOrbSafety) { + movecost(from, dest, 2); + from = NULL; + } + if(cwt.at->item != itOrbYendor && cwt.at->item != itHolyGrail) { + auto c = collectItem(cwt.at, true); + if(c) { + return true; + } + } + + mirror::destroyAll(); + + if(monstersnearO(a, dest, moPlayer, NULL, cwt.at)) { changes.rollback(); return false; } @@ -631,31 +654,17 @@ EX bool jumpTo(orbAction a, cell *dest, eItem byWhat, int bonuskill IS(0), eMons changes.rollback(); return true; } + + changes.commit(); + current_display->which_copy = ggmatrix(dest); countLocalTreasure(); - sword::reset(); - stabbingAttack(c1, dest, moPlayer, bonuskill); - playerMoveEffects(c1, dest); - - // do not apply movecost later, when from no longer exists - if(cwt.at->item == itOrbSafety) { - movecost(from, dest, 2); - from = NULL; - } - if(cwt.at->item != itOrbYendor && cwt.at->item != itHolyGrail) - collectItem(cwt.at, true); - - mirror::destroyAll(); - for(int i=9; i>=0; i--) setdist(cwt.at, i, NULL); if(from) movecost(from, dest, 2); - if(itemclass(byWhat) == IC_ORB) - apply_impact(dest); - createNoise(1); if(shmup::on) @@ -1159,7 +1168,7 @@ EX eItem targetRangedOrb(cell *c, orbAction a) { // (0-) strong wind if(items[itStrongWind] && c->cpdist == 2 && cwt.at == whirlwind::jumpFromWhereTo(c, true)) { - changes.init(); + changes.init(isCheck(a)); if(jumpTo(a, c, itStrongWind)) return itStrongWind; } @@ -1233,7 +1242,7 @@ EX eItem targetRangedOrb(cell *c, orbAction a) { items[itOrbAether] = i; if(jumpstate == 15) { - changes.init(); + changes.init(isCheck(a)); int k = tkills(); eMonster m = jumpthru->monst; if(jumpthru->wall == waShrub) { @@ -1254,7 +1263,7 @@ EX eItem targetRangedOrb(cell *c, orbAction a) { jumpstate = check_jump(cwt.at, c, P_ISPLAYER, jumpthru); items[itOrbAether] = i; if(jumpstate == 3) { - changes.init(); + changes.init(isCheck(a)); if(jumpTo(a, c, itOrbFrog)) jumpstate = 4; if(jumpstate == 4) return itOrbFrog; } @@ -1267,7 +1276,7 @@ EX eItem targetRangedOrb(cell *c, orbAction a) { jumpstate = 20 + check_phase(cwt.at, c, P_ISPLAYER, jumpthru); items[itOrbAether] = i; if(jumpstate == 23) { - changes.init(); + changes.init(isCheck(a)); if(jumpTo(a, c, itOrbPhasing)) jumpstate = 24; } if(shmup::on) shmup::popmonsters(); @@ -1309,7 +1318,7 @@ EX eItem targetRangedOrb(cell *c, orbAction a) { bool inrange = false; for(cell *c1: gun_targets(cwt.at)) if(c1 == c) inrange = true; if(inrange) { - changes.init(); + changes.init(isCheck(a)); gun_attack(c), apply_impact(c); if(monstersnearO(a, cwt.at, moPlayer, NULL, cwt.at)) { changes.rollback(); diff --git a/pcmove.cpp b/pcmove.cpp index 4d0d5b8a..20131028 100644 --- a/pcmove.cpp +++ b/pcmove.cpp @@ -265,7 +265,7 @@ bool pcmove::movepcto() { fmsAttack = forcedmovetype == fmSkip || forcedmovetype == fmAttack; fmsActivate = forcedmovetype == fmSkip || forcedmovetype == fmActivate; - changes.init(); + changes.init(checkonly); bool b = (d >= 0) ? actual_move() : stay(); if(checkonly || !b) { changes.rollback(); @@ -274,6 +274,44 @@ bool pcmove::movepcto() { println(hlog, "error: not commited!"); changes.commit(); } + + if(!b) { + // bool try_instant = (forcedmovetype == fmInstant) || (forcedmovetype == fmSkip && !passable(c2, cwt.at, P_ISPLAYER | P_MIRROR | P_USEBOAT | P_FRIENDSWAP)); + + if(items[itOrbFlash]) { + if(checkonly) { nextmovetype = lmInstant; return true; } + if(orbProtection(itOrbFlash)) return true; + activateFlash(); + checkmove(); + return true; + } + + if(items[itOrbLightning]) { + if(checkonly) { nextmovetype = lmInstant; return true; } + if(orbProtection(itOrbLightning)) return true; + activateLightning(); + checkmove(); + return true; + } + + if(false && who_kills_me == moOutlaw && items[itRevolver]) { + cell *c2 = cwt.cpeek(); + for(int i=0; itype; i++) { + cell *c3 = c2->move(i); + if(c3) for(int i=0; itype; i++) { + cell *c4 = c3->move(i); + if(c4 && c4->monst == moOutlaw) { + eItem i = targetRangedOrb(c4, roCheck); + if(i == itRevolver) { + targetRangedOrb(c4, roKeyboard); + return false; + } + } + } + } + } + } + return b; } @@ -340,6 +378,7 @@ bool pcmove::swing() { } bool pcmove::after_instant(bool kl) { + changes.commit(); keepLightning = kl; bfs(); keepLightning = false; @@ -370,12 +409,14 @@ struct changes_t { vector rollbacks; vector commits; bool on; + bool checking; - void init() { + void init(bool ch) { on = true; for(cell *dc: dcal) ccell(dc); value_keep(kills); value_keep(items); + checking = ch; } void commit() { @@ -498,8 +539,6 @@ bool pcmove::actual_move() { return false; } - bool try_instant = (forcedmovetype == fmInstant) || (forcedmovetype == fmSkip && !passable(c2, cwt.at, P_ISPLAYER | P_MIRROR | P_USEBOAT | P_FRIENDSWAP)); - if(items[itOrbDomination] > ORBBASE && isMountable(c2->monst) && !monstersnear2() && fmsMove) { if(checkonly) { nextmovetype = lmMove; return true; } if(!isMountable(cwt.at->monst)) dragon::target = NULL; @@ -511,20 +550,6 @@ bool pcmove::actual_move() { return perform_move_or_jump(); } - if(items[itOrbFlash] && try_instant) { - if(checkonly) { nextmovetype = lmInstant; return true; } - if(orbProtection(itOrbFlash)) return true; - activateFlash(); - return after_instant(false); - } - - if(items[itOrbLightning] && try_instant) { - if(checkonly) { nextmovetype = lmInstant; return true; } - if(orbProtection(itOrbLightning)) return true; - activateLightning(); - return after_instant(true); - } - if(isActivable(c2) && fmsActivate) { if(checkonly) { nextmovetype = lmInstant; return true; } activateActiv(c2, true); @@ -782,6 +807,9 @@ bool pcmove::attack() { auto& c2 = mi.t; if(!fmsAttack) return false; + if(items[itOrbFlash] || items[itOrbLightning]) + return false; + attackflags = AF_NORMAL; if(items[itOrbSpeed]&1) attackflags |= AF_FAST; if(items[itOrbSlaying]) attackflags |= AF_CRUSH; @@ -925,8 +953,10 @@ bool pcmove::perform_actual_move() { } if(items[itOrbWinter]) - forCellEx(c3, c2) if(c3->wall == waIcewall && c3->item) - markOrb(itOrbWinter), collectItem(c3); + forCellEx(c3, c2) if(c3->wall == waIcewall && c3->item) { + markOrb(itOrbWinter); + if(collectItem(c3)) return true; + } movecost(cwt.at, c2, 2); @@ -976,41 +1006,6 @@ bool pcmove::perform_move_or_jump() { if(monstersnear(cwt.at, moPlayer, nullptr, c1)) { changes.rollback(); - - /* todo - if(items[itOrbFlash]) { - if(checkonly) { nextmovetype = lmInstant; return true; } - if(orbProtection(itOrbFlash)) return true; - activateFlash(); - checkmove(); - return true; - } - - if(items[itOrbLightning]) { - if(checkonly) { nextmovetype = lmInstant; return true; } - if(orbProtection(itOrbLightning)) return true; - activateLightning(); - checkmove(); - return true; - } - - if(who_kills_me == moOutlaw && items[itRevolver]) { - for(int i=0; itype; i++) { - cell *c3 = c2->move(i); - if(c3) for(int i=0; itype; i++) { - cell *c4 = c3->move(i); - if(c4 && c4->monst == moOutlaw) { - eItem i = targetRangedOrb(c4, roCheck); - if(i == itRevolver) { - targetRangedOrb(c4, roKeyboard); - return false; - } - } - } - } - } - */ - if(errormsgs && !checkonly) wouldkill("%The1 would kill you there!"); return false; }