diff --git a/celldrawer.cpp b/celldrawer.cpp index 2345af20..523659cc 100644 --- a/celldrawer.cpp +++ b/celldrawer.cpp @@ -2700,7 +2700,7 @@ void celldrawer::draw_bowpath() { for(auto& m: *v) { hyperpoint h0 = C0, t0 = Hypc, h1 = C0, t1 = Hypc; - bool birth = m.first; + bool birth = m.flags & bow::bpFIRST; if(!birth) { ld d = cellgfxdist(c, m.prev.spin) / 2; @@ -2709,7 +2709,7 @@ void celldrawer::draw_bowpath() { } else birth = true; - if(!m.last) { + if(!(m.flags & bow::bpLAST)) { ld d = cellgfxdist(c, m.next.spin) / 2; h1 = ddspin(c, m.next.spin) * xpush0(d); t1 = ddspin(c, m.next.spin) * xpush(d) * xtangent(-d*2); @@ -2718,6 +2718,12 @@ void celldrawer::draw_bowpath() { ld t = frac(ptick(PURE?500:250)); color_t arrow_color = getcs().swordcolor; + + if(m.flags & bow::bpCOPIED) { + arrow_color &= 0xFF; + arrow_color |= mirrorcolor(m.next.mirrored != cwt.mirrored ? 1 : 0) << 8; + } + color_t arrow_color_trans = arrow_color & 0xFFFFFF00; if(bow::fire_mode) arrow_color = gradient(arrow_color_trans, arrow_color, 0, 0.25, 1); diff --git a/crossbow.cpp b/crossbow.cpp index 88a83e07..00ce64f6 100644 --- a/crossbow.cpp +++ b/crossbow.cpp @@ -39,9 +39,7 @@ EX bool crossbow_mode() { return weapon == wCrossbow; } #if HDR struct bowpoint { cellwalker prev, next; - bool first, last; - bool copied; - bool mirrored; + flagtype flags; bowpoint() {} }; @@ -52,6 +50,10 @@ struct bowscore { }; #endif +EX flagtype bpFIRST = 1; +EX flagtype bpLAST = 2; +EX flagtype bpCOPIED = 4; + EX vector bowpath; EX map> bowpath_map; @@ -148,37 +150,43 @@ EX int create_path() { } reverse(dirseq.begin(), dirseq.end()); - println(hlog, "dirseq = ", dirseq); + struct bolt { + cellwalker at; + flagtype flags; + bolt(cellwalker cw, flagtype f) { at = cw; flags = f; } + }; bowpath.clear(); - vector bolts = { cwt }; - for(auto m: mirror::mirrors) bolts.push_back(m.second); + vector bolts = { bolt(cwt, 0) }; + for(auto m: mirror::mirrors) bolts.emplace_back(m.second, bpCOPIED); set broken_mirrors; for(auto d: dirseq) { bool first = bowpath.empty(); - vector nbolts; + vector nbolts; set next_broken_mirrors = broken_mirrors; for(auto bolt: bolts) { bowpath.emplace_back(); auto& p = bowpath.back(); - p.prev = bolt; - p.first = first; - if(d == NODIR || blocks(bolt.at)) { p.next = bolt; p.last = true; } + p.prev = bolt.at; + p.flags = bolt.flags; + if(first) p.flags |= bpFIRST; + if(d == NODIR || blocks(bolt.at.at)) { p.next = bolt.at; p.flags |= bpLAST; } else { - if(inmirror(bolt.at) || bolt.at->wall == waMirrorWall) bolt = mirror::reflect(bolt); - bolt += d; - p.next = bolt; p.last = false; - bolt += wstep; - if(among(bolt.at->wall, waCloud, waMirror) && !broken_mirrors.count(bolt.at)) { + if(inmirror(bolt.at.at) || (bolt.at.at->wall == waMirrorWall && inmirror((bolt.at+d).cpeek()))) + bolt.at = mirror::reflect(bolt.at); + bolt.at += d; + p.next = bolt.at; + bolt.at += wstep; + if(among(bolt.at.at->wall, waCloud, waMirror) && !broken_mirrors.count(bolt.at.at)) { auto &mir = mirror::mirrors; vector> bmir; swap(mir, bmir); - mirror::createHere(bolt, 0); + mirror::createHere(bolt.at, 0); swap(mir, bmir); - for(auto b: bmir) nbolts.push_back(b.second); - next_broken_mirrors.insert(bolt.at); + for(auto b: bmir) nbolts.emplace_back(b.second, bolt.flags); + next_broken_mirrors.insert(bolt.at.at); } nbolts.push_back(bolt); } @@ -265,18 +273,19 @@ EX void shoot() { cell *c = mov.prev.at; cell *cf = mov.prev.cpeek(); if(!c) continue; + eMonster who = (mov.flags & bpCOPIED) ? moMimic : moPlayer; if(c != cf) for(int t=0; ttype; t++) { cell *c1 = cf->move(t); if(!c) continue; - + bool stabthere = false; if(logical_adjacent(c, moPlayer, c1)) stabthere = true; - if(stabthere && canAttack(cf,moPlayer,c1,c1->monst,AF_STAB)) { + if(stabthere && canAttack(cf,who,c1,c1->monst,AF_STAB)) { changes.ccell(c1); eMonster m = c->monst; - if(attackMonster(c1, AF_STAB | AF_MSG, moPlayer)) { + if(attackMonster(c1, AF_STAB | AF_MSG, who)) { spread_plague(c1, cf, t, moPlayer); produceGhost(c, m, moPlayer); } @@ -286,13 +295,13 @@ EX void shoot() { mirror::breakMirror(mov.next, -1); eMonster m = c->monst; if(!m || isMimic(m)) continue; - if(!canAttack(cf, moPlayer, c, m, attackflags)) { + if(!canAttack(cf, who, c, m, attackflags)) { pcmove pcm; pcm.mi = movei(mov.prev).rev(); pcm.tell_why_cannot_attack(); continue; } changes.ccell(c); - if(m) attackMonster(c, attackflags | AF_MSG, moPlayer); + if(m) attackMonster(c, attackflags | AF_MSG, who); if(!c->monst || isAnyIvy(m)) { spread_plague(cf, c, movei(mov.prev).rev().d, moPlayer); @@ -300,7 +309,7 @@ EX void shoot() { } if(items[itCurseWeakness] || (isStunnable(c->monst) && c->hitpoints > 1)) { - if(!mov.last && monsterPushable(c)) { + if(!(mov.flags & bpLAST) && monsterPushable(c)) { cell *ct = mov.next.cpeek(); bool can_push = passable(ct, c, P_BLOW); if(can_push) { diff --git a/pcmove.cpp b/pcmove.cpp index c5034075..160fd128 100644 --- a/pcmove.cpp +++ b/pcmove.cpp @@ -256,7 +256,7 @@ bool pcmove::try_shooting(bool auto_target) { items[itCrossbow] = bow::loading_time(); bow::shoot(); - int v = -1; for(auto p: bow::bowpath) if(p.next.at == cwt.at && p.first) v = p.next.spin; + int v = -1; for(auto p: bow::bowpath) if(p.next.at == cwt.at && (p.flags & bow::bpFIRST)) v = p.next.spin; if(v >= 0) sideAttack(cwt.at, v, moPlayer, 0); if(items[itOrbGravity]) {