1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-11-30 15:39:54 +00:00

Orb of the Sword in non-shmup 3D geometries

This commit is contained in:
Zeno Rogue 2019-06-24 22:28:20 +02:00
parent 84df837855
commit 3a4e84effe
5 changed files with 74 additions and 28 deletions

View File

@ -2620,14 +2620,17 @@ namespace dragon {
}
namespace sword {
array<int, MAXPLAYER> angle;
int sword_angles;
array<sworddir, MAXPLAYER> dir;
void possible_divisor(int s) { sword_angles *= s / gcd(sword_angles, s); }
void determine_sword_angles() {
sword_angles = 2;
if(IRREGULAR) sword_angles = 840;
if(DIM == 3) sword_angles = 1;
else if(IRREGULAR) sword_angles = 840;
else if(binarytiling) sword_angles = 42;
else if(archimedean) {
if(!PURE) possible_divisor((BITRUNCATED ? 2 : 1) * isize(arcm::current.faces));
@ -2639,7 +2642,7 @@ namespace sword {
}
}
cell *pos(cell *c, int s) {
cell *pos2(cell *c, int s) {
int t = c->type;
s *= 2;
s += sword_angles/t;
@ -2650,12 +2653,26 @@ namespace sword {
return c->move(s);
}
cell *pos(cell *c, const sworddir& sd, bool rev) {
if(WDIM == 2)
return pos2(c, sd.angle + (rev ? sword_angles/2 : 0));
else {
cell *best = NULL;
ld bdist = HUGE_VAL;
for(int i=0; i<S7; i++) {
ld dist = hdist(sd.T * xpush0(rev?-0.1:0.1), tC0(currentmap->relative_matrix(c->move(i)->master, c->master)));
if(dist < bdist) bdist = dist, best = c->move(i);
}
return best;
}
}
eItem orbof(bool rev) { return rev ? itOrbSword2 : itOrbSword; }
int orbcount(bool rev) { return items[orbof(rev)]; }
cell *pos(int id, bool rev) {
if(!orbcount(rev)) return NULL;
return pos(playerpos(id), angle[id] + (rev ? sword_angles/2 : 0));
return pos(playerpos(id), dir[id], rev);
}
bool at(cell *where, bool noplayer) {
@ -2673,19 +2690,29 @@ namespace sword {
}
// from c1 to c2
int shift(cell *c1, cell *c2, int angle) {
if(!c1 || !c2) return 0;
sworddir shift(cell *c1, cell *c2, sworddir d) {
if(!c1 || !c2) return d;
int s1 = neighborId(c1, c2);
int s2 = neighborId(c2, c1);
if(s1 < 0 || s2 < 0) return angle;
if(c1->c.mirror(s1))
return ((s2*sword_angles/c2->type - angle + s1*sword_angles/c1->type) + sword_angles/2) % sword_angles;
else
return ((s2*sword_angles/c2->type - s1*sword_angles/c1->type) + sword_angles/2 + angle) % sword_angles;
if(s1 < 0 || s2 < 0) return d;
if(WDIM == 2) {
if(c1->c.mirror(s1))
d.angle = ((s2*sword_angles/c2->type - d.angle + s1*sword_angles/c1->type) + sword_angles/2) % sword_angles;
else
d.angle = ((s2*sword_angles/c2->type - s1*sword_angles/c1->type) + sword_angles/2 + d.angle) % sword_angles;
}
else {
transmatrix T = currentmap->relative_matrix(c1->master, c2->master);
T = gpushxto0(tC0(T)) * T;
d.T = T * d.T;
fixmatrix(d.T);
}
return d;
}
void shuffle(int i) {
sword::angle[i] = euclid ? S7*hrand(6) : PURE ? 3*hrand(sword_angles/3)+1 : hrand(sword_angles);
dir[i].angle = hrand(sword_angles);
dir[i].T = Id;
}
void reset() {
@ -3217,7 +3244,7 @@ auto ccm = addHook(clearmemory, 0, [] () {
gd->store(prairie::enter);
gd->store(prairie::tchoices);
gd->store(prairie::beaststogen);
gd->store(sword::angle);
gd->store(sword::dir);
gd->store(elec::haveelec);
gd->store(elec::havecharge);
gd->store(elec::lightningfast);

View File

@ -1464,9 +1464,9 @@ bool monstersnear(cell *c, cell *nocount, eMonster who, cell *pushto, cell *come
dynamicval<cell*> x5(*wcw, c);
dynamicval<bool> x6(stalemate::nextturn, true);
dynamicval<int> x7(sword::angle[multi::cpid],
who == moPlayer ? sword::shift(comefrom, c, sword::angle[multi::cpid]) :
sword::angle[multi::cpid]);
dynamicval<sword::sworddir> x7(sword::dir[multi::cpid],
who == moPlayer ? sword::shift(comefrom, c, sword::dir[multi::cpid]) :
sword::dir[multi::cpid]);
for(int b=0; b<2; b++) {
if(who == moPlayer) {
@ -3545,7 +3545,7 @@ void playerMoveEffects(cell *c1, cell *c2) {
if(peace::on) items[itOrbSword] = c2->land == laBurial ? 100 : 0;
sword::angle[multi::cpid] = sword::shift(c1, c2, sword::angle[multi::cpid]);
sword::dir[multi::cpid] = sword::shift(c1, c2, sword::dir[multi::cpid]);
destroyWeakBranch(c1, c2, moPlayer);
@ -5267,8 +5267,8 @@ void sideAttack(cell *mf, int dir, eMonster who, int bonuskill) {
template<class T> 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)) {
cell *sf = sword::pos(mf, sword::angle[multi::cpid] + (bb?sword::sword_angles/2:0));
cell *st = sword::pos(mt, sword::shift(mf, mt, sword::angle[multi::cpid]) + (bb?sword::sword_angles/2:0));
cell *sf = sword::pos(mf, sword::dir[multi::cpid], bb);
cell *st = sword::pos(mt, sword::shift(mf, mt, sword::dir[multi::cpid]), bb);
f(st, bb);
if(sf != st && !isNeighbor(sf,st)) {
// also attack the in-transit cell

View File

@ -391,18 +391,22 @@ void drawPlayerEffects(const transmatrix& V, cell *c, bool onplayer) {
#endif
}
else if(shmup::on && WDIM == 3) {
else if(WDIM == 3) {
#if CAP_SHAPES
transmatrix Vsword =
shmup::on ? V * shmup::swordmatrix[multi::cpid] * cspin(2, 0, M_PI/2)
: gmatrix[c] * rgpushxto0(inverse(gmatrix[c]) * tC0(V)) * sword::dir[multi::cpid].T;
if(items[itOrbSword])
queuepoly(V*shmup::swordmatrix[multi::cpid] * cspin(2, 0, M_PI/2) * cspin(1,2, ticks / 150.), (peace::on ? cgi.shMagicShovel : cgi.shMagicSword), darkena(iinf[itOrbSword].color, 0, 0xC0 + 0x30 * sintick(200)));
queuepoly(Vsword * cspin(1,2, ticks / 150.), (peace::on ? cgi.shMagicShovel : cgi.shMagicSword), darkena(iinf[itOrbSword].color, 0, 0xC0 + 0x30 * sintick(200)));
if(items[itOrbSword2])
queuepoly(V*shmup::swordmatrix[multi::cpid] * cspin(2, 0, -M_PI/2) * cspin(1,2, ticks / 150.), (peace::on ? cgi.shMagicShovel : cgi.shMagicSword), darkena(iinf[itOrbSword2].color, 0, 0xC0 + 0x30 * sintick(200)));
queuepoly(Vsword * pispin * cspin(1,2, ticks / 150.), (peace::on ? cgi.shMagicShovel : cgi.shMagicSword), darkena(iinf[itOrbSword2].color, 0, 0xC0 + 0x30 * sintick(200)));
#endif
}
else {
int& ang = angle[multi::cpid];
int& ang = sword::dir[multi::cpid].angle;
ang %= sword::sword_angles;
#if CAP_QUEUE || CAP_SHAPES
@ -415,7 +419,7 @@ void drawPlayerEffects(const transmatrix& V, cell *c, bool onplayer) {
if(!euclid) for(int a=0; a<sword_angles; a++) {
if(a == ang && items[itOrbSword]) continue;
if((a+sword_angles/2)%sword_angles == ang && items[itOrbSword2]) continue;
bool longer = sword::pos(cwt.at, a-1) != sword::pos(cwt.at, a+1);
bool longer = sword::pos2(cwt.at, a-1) != sword::pos2(cwt.at, a+1);
if(sword_angles > 48 && !longer) continue;
color_t col = darkena(0xC0C0C0, 0, 0xFF);
ld l0 = PURE ? 0.6 * cgi.scalefactor : longer ? 0.36 : 0.4;
@ -6862,6 +6866,13 @@ void drawMarkers() {
}
#endif
if(WDIM == 3 && !shmup::on) {
if(items[itOrbSword])
queuechr(gmatrix[cwt.at] * sword::dir[multi::cpid].T * xpush0(cgi.sword_size), vid.fsize*2, '+', iinf[itOrbSword].color);
if(items[itOrbSword2])
queuechr(gmatrix[cwt.at] * sword::dir[multi::cpid].T * xpush0(-cgi.sword_size), vid.fsize*2, '+', iinf[itOrbSword2].color);
}
}
monsterToSummon = moNone;

11
hyper.h
View File

@ -1862,12 +1862,17 @@ namespace tortoise {
namespace sword {
extern array<int, MAXPLAYER> angle;
struct sworddir {
int angle;
transmatrix T;
};
cell *pos(cell *c, int s);
extern array<sworddir, MAXPLAYER> dir;
cell *pos(cell *c, const sworddir& sd, bool rev);
cell *pos(int id);
bool at(cell *where, bool noplayer = false);
int shift(cell *c1, cell *c2);
sworddir shift(cell *c1, cell *c2, sworddir);
}
void killThePlayer(eMonster m, int id, flagtype flags);

View File

@ -210,7 +210,10 @@ void initgame() {
}
sword::determine_sword_angles();
for(int i=0; i<numplayers(); i++) sword::angle[i] = (sword::sword_angles / cwt.at->type + 1) / 2;
for(int i=0; i<numplayers(); i++) {
sword::dir[i].angle = (sword::sword_angles / cwt.at->type + 1) / 2;
sword::dir[i].T = Id;
}
#if CAP_DAILY
daily::split();