From f22ec08f86c01961efbf6e8a9e569c44d876bc51 Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Fri, 14 Dec 2018 13:26:17 +0100 Subject: [PATCH] Warnings when hitting an ally. Better warnings --- dialogs.cpp | 7 +- game.cpp | 204 ++++++++++++++++++++++++++++++++++------------------ hyper.h | 5 +- 3 files changed, 141 insertions(+), 75 deletions(-) diff --git a/dialogs.cpp b/dialogs.cpp index 2b681ea4..096d0aa7 100644 --- a/dialogs.cpp +++ b/dialogs.cpp @@ -80,11 +80,14 @@ namespace dialog { map key_actions; - void add_action(reaction_t action) { - int& key = lastItem().key; + void add_key_action(int key, const reaction_t& action) { while(key_actions.count(key)) key++; key_actions[key] = action; } + + void add_action(const reaction_t& action) { + add_key_action(lastItem().key, action); + } void handler(int sym, int uni) { dialog::handleNavigation(sym, uni); diff --git a/game.cpp b/game.cpp index 8694ef65..6b6948a2 100644 --- a/game.cpp +++ b/game.cpp @@ -1276,7 +1276,7 @@ bool monstersnear(stalemate1& sm) { // Krakens just destroy boats if(c2->monst == moKrakenT && onboat(sm)) { if(krakensafe(c)) continue; - else if(warningprotection() && res == 0) m = moWarning; + else if(warningprotection(XLAT("This move appears dangerous -- are you sure?")) && res == 0) m = moWarning; else continue; } // they cannot attack through vines @@ -5016,32 +5016,54 @@ void sideAttack(cell *mf, int dir, eMonster who, int bonuskill) { } } -void stabbingAttack(cell *mf, cell *mt, eMonster who, int bonuskill) { - int numsh = 0, numflail = 0, numlance = 0, numslash = 0; - - int backdir = neighborId(mt, mf); - +template void do_swords(cell *mf, cell *mt, eMonster who, const T& f) { for(int bb=0; bb<2; bb++) if(who == moPlayer && sword::orbcount(bb)) { - int numbb = 0; cell *sf = sword::pos(mf, sword::angle[multi::cpid] + (bb?S21:0)); cell *st = sword::pos(mt, sword::shift(mf, mt, sword::angle[multi::cpid]) + (bb?S21:0)); - if(swordAttack(mt, who, st, bb)) numbb++; + f(st, bb); if(sf != st && !isNeighbor(sf,st)) { // also attack the in-transit cell if(S3 == 3) { - forCellEx(sb, sf) if(isNeighbor(sb, st) && sb != mf && sb != mt) - if(swordAttack(mt, who, sb, bb)) numbb++; + forCellEx(sb, sf) if(isNeighbor(sb, st) && sb != mf && sb != mt) f(sb, bb); } else { - forCellEx(sb, mf) if(isNeighbor(sb, st) && sb != mt) - if(swordAttack(mt, who, sb, bb)) numbb++; - forCellEx(sb, mt) if(isNeighbor(sb, sf) && sb != mf) - if(swordAttack(mt, who, sb, bb)) numbb++; + forCellEx(sb, mf) if(isNeighbor(sb, st) && sb != mt) f(sb, bb); + forCellEx(sb, mt) if(isNeighbor(sb, sf) && sb != mf) f(sb, bb); } } - achievement_count("SLASH", numbb, 0); - numslash += numbb; } + } + +eMonster do_we_stab_a_friend(cell *mf, cell *mt, eMonster who) { + eMonster m = moNone; + do_swords(mf, mt, who, [&] (cell *c, int bb) { + if(!peace::on && canAttack(mt, who, c, c->monst, AF_SWORD) && c->monst && isFriendly(c)) m = c->monst; + }); + + for(int t=0; ttype; t++) { + cell *c = mf->move(t); + if(!c) continue; + + bool stabthere = false; + if(logical_adjacent(mt, who, c)) stabthere = true; + + if(stabthere && canAttack(mt,who,c,c->monst,AF_STAB) && isFriendly(c)) + return c->monst; + } + + return m; + } + +void stabbingAttack(cell *mf, cell *mt, eMonster who, int bonuskill) { + int numsh = 0, numflail = 0, numlance = 0, numslash = 0, numbb[2]; + + numbb[0] = numbb[1] = 0; + + int backdir = neighborId(mt, mf); + + do_swords(mf, mt, who, [&] (cell *c, int bb) { if(swordAttack(mt, who, c, bb)) numbb[bb]++, numslash++; }); + + for(int bb=0; bb<2; bb++) achievement_count("SLASH", numbb[bb], 0); if(peace::on) return; @@ -7340,6 +7362,52 @@ bool monsterPushable(cell *c2) { bool got_survivalist; +bool should_switchplace(cell *c1, cell *c2) { + if(isPrincess(c2->monst) || among(c2->monst, moGolem, moIllusion, moMouse, moFriendlyGhost)) + return true; + + if(peace::on) return c2->monst && !isMultitile(c2->monst); + return false; + } + +bool warningprotection_hit(eMonster m) { + if(m && warningprotection(XLAT("Are you sure you want to hit %the1?", m))) + return true; + return false; + } + +bool switchplace_prevent(cell *c1, cell *c2, bool checkonly) { + if(!should_switchplace(c1, c2)) return false; + if(c1->monst && c1->monst != moFriendlyIvy) { + if(!checkonly) addMessage(XLAT("There is no room for %the1!", c2->monst)); + return true; + } + if(passable(c1, c2, P_ISFRIEND | (c2->monst == moTameBomberbird ? P_FLYING : 0))) return false; + if(warningprotection_hit(c2->monst)) return true; + return false; + } + +void handle_switchplaces(cell *c1, cell *c2, bool& switchplaces) { + if(should_switchplace(c1, c2)) { + bool pswitch = false; + if(c2->monst == moMouse) + princess::mouseSqueak(c2); + else if(isPrincess(c2->monst)) { + princess::line(c2); + princess::move(c1, c2); + } + else + pswitch = true; + c1->hitpoints = c2->hitpoints; + c1->stuntime = c2->stuntime; + placeGolem(c1, c2, c2->monst); + if(cwt.at->monst != moNone && pswitch) + addMessage(XLAT("You switch places with %the1.", c2->monst)); + c2->monst = moNone; + switchplaces = true; + } + } + bool movepcto(int d, int subdir, bool checkonly) { if(d >= 0 && !checkonly && subdir != 1 && subdir != -1) printf("subdir = %d\n", subdir); global_pushto = NULL; @@ -7661,9 +7729,10 @@ bool movepcto(int d, int subdir, bool checkonly) { return false; } + if(c2->monst == moTameBomberbird && warningprotection_hit(moTameBomberbird)) return false; + if(checkonly) return true; - - + /* if(c2->monst == moTortoise) { printf("seek=%d get=%d <%x/%x> item=%d\n", tortoise::seeking, @@ -7737,10 +7806,8 @@ bool movepcto(int d, int subdir, bool checkonly) { return false; } else { - if(mineMarked(c2) && !minesafe() && !checkonly && warningprotection()) { - addMessage("Are you sure you want to step there?"); + if(mineMarked(c2) && !minesafe() && !checkonly && warningprotection(XLAT("Are you sure you want to step there?"))) return false; - } if(monstersnear(c2, NULL, moPlayer, NULL, cwt.at)) { if(checkonly) return false; @@ -7780,6 +7847,11 @@ bool movepcto(int d, int subdir, bool checkonly) { wouldkill("%The1 would kill you there!"); return false; } + + if(switchplace_prevent(cwt.at, c2, checkonly)) return false; + if(!checkonly && warningprotection_hit(do_we_stab_a_friend(cwt.at, c2, moPlayer))) + return false; + if(checkonly) return true; boatjump: statuejump: @@ -7804,28 +7876,28 @@ bool movepcto(int d, int subdir, bool checkonly) { if(makeflame(cwt.at, 10, false)) markOrb(itOrbFire); } - { - bool haveIvy = false; - forCellEx(c3, cwt.at) if(c3->monst == moFriendlyIvy) haveIvy = true; - - bool killIvy = haveIvy; - - if(items[itOrbNature]) { - if(c2->monst != moFriendlyIvy && strictlyAgainstGravity(c2, cwt.at, false, MF_IVY)) { - invismove = false; - } - else if(cwt.at->monst) invismove = false; - else if(haveIvy || !cellEdgeUnstable(cwt.at, MF_IVY)) { - cwt.at->monst = moFriendlyIvy; - cwt.at->mondir = neighborId(cwt.at, c2); - invismove = false; - markOrb(itOrbNature); - killIvy = false; + if(1) { + bool haveIvy = false; + forCellEx(c3, cwt.at) if(c3->monst == moFriendlyIvy) haveIvy = true; + + bool killIvy = haveIvy; + + if(items[itOrbNature]) { + if(c2->monst != moFriendlyIvy && strictlyAgainstGravity(c2, cwt.at, false, MF_IVY)) { + invismove = false; + } + else if(cwt.at->monst) invismove = false; + else if(haveIvy || !cellEdgeUnstable(cwt.at, MF_IVY)) { + cwt.at->monst = moFriendlyIvy; + cwt.at->mondir = neighborId(cwt.at, c2); + invismove = false; + markOrb(itOrbNature); + killIvy = false; + } } + + if(killIvy) killFriendlyIvy(); } - - if(killIvy) killFriendlyIvy(); - } if(items[itOrbDigging]) { invismove = false; @@ -7848,34 +7920,8 @@ bool movepcto(int d, int subdir, bool checkonly) { movecost(cwt.at, c2, 2); - { - bool pushpast = false; - pushpast = - c2->monst == moGolem || c2->monst == moIllusion || isPrincess(c2->monst) || c2->monst == moMouse || - c2->monst == moFriendlyGhost; - - if(peace::on) pushpast |= c2->monst && !isMultitile(c2->monst); - - if(pushpast) { - bool pswitch = false; - if(c2->monst == moMouse) - princess::mouseSqueak(c2); - else if(isPrincess(c2->monst)) { - princess::line(c2); - princess::move(cwt.at, c2); - } - else - pswitch = true; - cwt.at->hitpoints = c2->hitpoints; - cwt.at->stuntime = c2->stuntime; - placeGolem(cwt.at, c2, c2->monst); - if(cwt.at->monst != moNone && pswitch) - addMessage(XLAT("You switch places with %the1.", c2->monst)); - c2->monst = moNone; - switchplaces = true; - } - } - + handle_switchplaces(cwt.at, c2, switchplaces); + mountjump: lastmovetype = lmMove; lastmove = cwt.at; @@ -8087,11 +8133,27 @@ bool minesafe() { return items[itOrbAether]; } -bool warningprotection() { +bool warningprotection(const string& s) { if(hardcore) return false; if(multi::activePlayers() > 1) return false; if(items[itWarning]) return false; - items[itWarning] = 1; + pushScreen([s] () { + gamescreen(1); + dialog::addBreak(250); + dialog::init(XLAT("WARNING"), 0xFF0000, 150, 100); + dialog::addBreak(500); + dialog::addInfo(s); + dialog::addBreak(500); + dialog::addItem(XLAT("YES"), 'y'); + dialog::lastItem().scale = 200; + auto yes = [] () { items[itWarning] = 1; popScreen(); }; + dialog::add_action(yes); + dialog::add_key_action(SDLK_RETURN, yes); + dialog::addItem(XLAT("NO"), 'n'); + dialog::lastItem().scale = 200; + dialog::add_action([] () { items[itWarning] = 0; popScreen(); }); + dialog::display(); + }); return true; } diff --git a/hyper.h b/hyper.h index 877f3b4d..f0107701 100644 --- a/hyper.h +++ b/hyper.h @@ -1721,7 +1721,7 @@ void killThePlayer(eMonster m, int id, flagtype flags); bool attackJustStuns(cell *c2, flagtype flags); bool isTargetOrAdjacent(cell *c); -bool warningprotection(); +bool warningprotection(const string& s); bool mineMarked(cell *c); bool minesafe(); bool hasSafeOrb(cell *c); @@ -1846,7 +1846,8 @@ namespace dialog { void addHelp(); void addBack(); - void add_action(reaction_t action); + void add_action(const reaction_t& action); + void add_key_action(int key, const reaction_t& action); string view_edited_string(); void start_editing(string& s);