mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2025-01-27 09:24:53 +00:00
crossbow: better mimic bowpaths, mimic bowpaths colored, mimic bowpaths slay mirror spirits
This commit is contained in:
parent
3645a9b85e
commit
8129cfd726
@ -2700,7 +2700,7 @@ void celldrawer::draw_bowpath() {
|
|||||||
for(auto& m: *v) {
|
for(auto& m: *v) {
|
||||||
|
|
||||||
hyperpoint h0 = C0, t0 = Hypc, h1 = C0, t1 = Hypc;
|
hyperpoint h0 = C0, t0 = Hypc, h1 = C0, t1 = Hypc;
|
||||||
bool birth = m.first;
|
bool birth = m.flags & bow::bpFIRST;
|
||||||
|
|
||||||
if(!birth) {
|
if(!birth) {
|
||||||
ld d = cellgfxdist(c, m.prev.spin) / 2;
|
ld d = cellgfxdist(c, m.prev.spin) / 2;
|
||||||
@ -2709,7 +2709,7 @@ void celldrawer::draw_bowpath() {
|
|||||||
}
|
}
|
||||||
else birth = true;
|
else birth = true;
|
||||||
|
|
||||||
if(!m.last) {
|
if(!(m.flags & bow::bpLAST)) {
|
||||||
ld d = cellgfxdist(c, m.next.spin) / 2;
|
ld d = cellgfxdist(c, m.next.spin) / 2;
|
||||||
h1 = ddspin(c, m.next.spin) * xpush0(d);
|
h1 = ddspin(c, m.next.spin) * xpush0(d);
|
||||||
t1 = ddspin(c, m.next.spin) * xpush(d) * xtangent(-d*2);
|
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));
|
ld t = frac(ptick(PURE?500:250));
|
||||||
|
|
||||||
color_t arrow_color = getcs().swordcolor;
|
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;
|
color_t arrow_color_trans = arrow_color & 0xFFFFFF00;
|
||||||
if(bow::fire_mode) arrow_color = gradient(arrow_color_trans, arrow_color, 0, 0.25, 1);
|
if(bow::fire_mode) arrow_color = gradient(arrow_color_trans, arrow_color, 0, 0.25, 1);
|
||||||
|
|
||||||
|
57
crossbow.cpp
57
crossbow.cpp
@ -39,9 +39,7 @@ EX bool crossbow_mode() { return weapon == wCrossbow; }
|
|||||||
#if HDR
|
#if HDR
|
||||||
struct bowpoint {
|
struct bowpoint {
|
||||||
cellwalker prev, next;
|
cellwalker prev, next;
|
||||||
bool first, last;
|
flagtype flags;
|
||||||
bool copied;
|
|
||||||
bool mirrored;
|
|
||||||
bowpoint() {}
|
bowpoint() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -52,6 +50,10 @@ struct bowscore {
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
EX flagtype bpFIRST = 1;
|
||||||
|
EX flagtype bpLAST = 2;
|
||||||
|
EX flagtype bpCOPIED = 4;
|
||||||
|
|
||||||
EX vector<bowpoint> bowpath;
|
EX vector<bowpoint> bowpath;
|
||||||
|
|
||||||
EX map<cell*, vector<bowpoint>> bowpath_map;
|
EX map<cell*, vector<bowpoint>> bowpath_map;
|
||||||
@ -148,37 +150,43 @@ EX int create_path() {
|
|||||||
}
|
}
|
||||||
reverse(dirseq.begin(), dirseq.end());
|
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();
|
bowpath.clear();
|
||||||
vector<cellwalker> bolts = { cwt };
|
vector<bolt> bolts = { bolt(cwt, 0) };
|
||||||
for(auto m: mirror::mirrors) bolts.push_back(m.second);
|
for(auto m: mirror::mirrors) bolts.emplace_back(m.second, bpCOPIED);
|
||||||
|
|
||||||
set<cell*> broken_mirrors;
|
set<cell*> broken_mirrors;
|
||||||
|
|
||||||
for(auto d: dirseq) {
|
for(auto d: dirseq) {
|
||||||
bool first = bowpath.empty();
|
bool first = bowpath.empty();
|
||||||
vector<cellwalker> nbolts;
|
vector<bolt> nbolts;
|
||||||
set<cell*> next_broken_mirrors = broken_mirrors;
|
set<cell*> next_broken_mirrors = broken_mirrors;
|
||||||
for(auto bolt: bolts) {
|
for(auto bolt: bolts) {
|
||||||
bowpath.emplace_back();
|
bowpath.emplace_back();
|
||||||
auto& p = bowpath.back();
|
auto& p = bowpath.back();
|
||||||
p.prev = bolt;
|
p.prev = bolt.at;
|
||||||
p.first = first;
|
p.flags = bolt.flags;
|
||||||
if(d == NODIR || blocks(bolt.at)) { p.next = bolt; p.last = true; }
|
if(first) p.flags |= bpFIRST;
|
||||||
|
if(d == NODIR || blocks(bolt.at.at)) { p.next = bolt.at; p.flags |= bpLAST; }
|
||||||
else {
|
else {
|
||||||
if(inmirror(bolt.at) || bolt.at->wall == waMirrorWall) bolt = mirror::reflect(bolt);
|
if(inmirror(bolt.at.at) || (bolt.at.at->wall == waMirrorWall && inmirror((bolt.at+d).cpeek())))
|
||||||
bolt += d;
|
bolt.at = mirror::reflect(bolt.at);
|
||||||
p.next = bolt; p.last = false;
|
bolt.at += d;
|
||||||
bolt += wstep;
|
p.next = bolt.at;
|
||||||
if(among(bolt.at->wall, waCloud, waMirror) && !broken_mirrors.count(bolt.at)) {
|
bolt.at += wstep;
|
||||||
|
if(among(bolt.at.at->wall, waCloud, waMirror) && !broken_mirrors.count(bolt.at.at)) {
|
||||||
auto &mir = mirror::mirrors;
|
auto &mir = mirror::mirrors;
|
||||||
vector<pair<int, cellwalker>> bmir;
|
vector<pair<int, cellwalker>> bmir;
|
||||||
swap(mir, bmir);
|
swap(mir, bmir);
|
||||||
mirror::createHere(bolt, 0);
|
mirror::createHere(bolt.at, 0);
|
||||||
swap(mir, bmir);
|
swap(mir, bmir);
|
||||||
for(auto b: bmir) nbolts.push_back(b.second);
|
for(auto b: bmir) nbolts.emplace_back(b.second, bolt.flags);
|
||||||
next_broken_mirrors.insert(bolt.at);
|
next_broken_mirrors.insert(bolt.at.at);
|
||||||
}
|
}
|
||||||
nbolts.push_back(bolt);
|
nbolts.push_back(bolt);
|
||||||
}
|
}
|
||||||
@ -265,18 +273,19 @@ EX void shoot() {
|
|||||||
cell *c = mov.prev.at;
|
cell *c = mov.prev.at;
|
||||||
cell *cf = mov.prev.cpeek();
|
cell *cf = mov.prev.cpeek();
|
||||||
if(!c) continue;
|
if(!c) continue;
|
||||||
|
eMonster who = (mov.flags & bpCOPIED) ? moMimic : moPlayer;
|
||||||
|
|
||||||
if(c != cf) for(int t=0; t<cf->type; t++) {
|
if(c != cf) for(int t=0; t<cf->type; t++) {
|
||||||
cell *c1 = cf->move(t);
|
cell *c1 = cf->move(t);
|
||||||
if(!c) continue;
|
if(!c) continue;
|
||||||
|
|
||||||
bool stabthere = false;
|
bool stabthere = false;
|
||||||
if(logical_adjacent(c, moPlayer, c1)) stabthere = true;
|
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);
|
changes.ccell(c1);
|
||||||
eMonster m = c->monst;
|
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);
|
spread_plague(c1, cf, t, moPlayer);
|
||||||
produceGhost(c, m, moPlayer);
|
produceGhost(c, m, moPlayer);
|
||||||
}
|
}
|
||||||
@ -286,13 +295,13 @@ EX void shoot() {
|
|||||||
mirror::breakMirror(mov.next, -1);
|
mirror::breakMirror(mov.next, -1);
|
||||||
eMonster m = c->monst;
|
eMonster m = c->monst;
|
||||||
if(!m || isMimic(m)) continue;
|
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();
|
pcmove pcm; pcm.mi = movei(mov.prev).rev();
|
||||||
pcm.tell_why_cannot_attack();
|
pcm.tell_why_cannot_attack();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
changes.ccell(c);
|
changes.ccell(c);
|
||||||
if(m) attackMonster(c, attackflags | AF_MSG, moPlayer);
|
if(m) attackMonster(c, attackflags | AF_MSG, who);
|
||||||
|
|
||||||
if(!c->monst || isAnyIvy(m)) {
|
if(!c->monst || isAnyIvy(m)) {
|
||||||
spread_plague(cf, c, movei(mov.prev).rev().d, moPlayer);
|
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(items[itCurseWeakness] || (isStunnable(c->monst) && c->hitpoints > 1)) {
|
||||||
if(!mov.last && monsterPushable(c)) {
|
if(!(mov.flags & bpLAST) && monsterPushable(c)) {
|
||||||
cell *ct = mov.next.cpeek();
|
cell *ct = mov.next.cpeek();
|
||||||
bool can_push = passable(ct, c, P_BLOW);
|
bool can_push = passable(ct, c, P_BLOW);
|
||||||
if(can_push) {
|
if(can_push) {
|
||||||
|
@ -256,7 +256,7 @@ bool pcmove::try_shooting(bool auto_target) {
|
|||||||
items[itCrossbow] = bow::loading_time();
|
items[itCrossbow] = bow::loading_time();
|
||||||
bow::shoot();
|
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(v >= 0) sideAttack(cwt.at, v, moPlayer, 0);
|
||||||
if(items[itOrbGravity]) {
|
if(items[itOrbGravity]) {
|
||||||
|
Loading…
Reference in New Issue
Block a user