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:
parent
84df837855
commit
3a4e84effe
53
complex.cpp
53
complex.cpp
@ -2620,14 +2620,17 @@ namespace dragon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace sword {
|
namespace sword {
|
||||||
array<int, MAXPLAYER> angle;
|
|
||||||
int sword_angles;
|
int sword_angles;
|
||||||
|
|
||||||
|
array<sworddir, MAXPLAYER> dir;
|
||||||
|
|
||||||
void possible_divisor(int s) { sword_angles *= s / gcd(sword_angles, s); }
|
void possible_divisor(int s) { sword_angles *= s / gcd(sword_angles, s); }
|
||||||
|
|
||||||
void determine_sword_angles() {
|
void determine_sword_angles() {
|
||||||
sword_angles = 2;
|
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(binarytiling) sword_angles = 42;
|
||||||
else if(archimedean) {
|
else if(archimedean) {
|
||||||
if(!PURE) possible_divisor((BITRUNCATED ? 2 : 1) * isize(arcm::current.faces));
|
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;
|
int t = c->type;
|
||||||
s *= 2;
|
s *= 2;
|
||||||
s += sword_angles/t;
|
s += sword_angles/t;
|
||||||
@ -2650,12 +2653,26 @@ namespace sword {
|
|||||||
return c->move(s);
|
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; }
|
eItem orbof(bool rev) { return rev ? itOrbSword2 : itOrbSword; }
|
||||||
int orbcount(bool rev) { return items[orbof(rev)]; }
|
int orbcount(bool rev) { return items[orbof(rev)]; }
|
||||||
|
|
||||||
cell *pos(int id, bool rev) {
|
cell *pos(int id, bool rev) {
|
||||||
if(!orbcount(rev)) return NULL;
|
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) {
|
bool at(cell *where, bool noplayer) {
|
||||||
@ -2673,19 +2690,29 @@ namespace sword {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// from c1 to c2
|
// from c1 to c2
|
||||||
int shift(cell *c1, cell *c2, int angle) {
|
sworddir shift(cell *c1, cell *c2, sworddir d) {
|
||||||
if(!c1 || !c2) return 0;
|
if(!c1 || !c2) return d;
|
||||||
int s1 = neighborId(c1, c2);
|
int s1 = neighborId(c1, c2);
|
||||||
int s2 = neighborId(c2, c1);
|
int s2 = neighborId(c2, c1);
|
||||||
if(s1 < 0 || s2 < 0) return angle;
|
if(s1 < 0 || s2 < 0) return d;
|
||||||
if(c1->c.mirror(s1))
|
if(WDIM == 2) {
|
||||||
return ((s2*sword_angles/c2->type - angle + s1*sword_angles/c1->type) + sword_angles/2) % sword_angles;
|
if(c1->c.mirror(s1))
|
||||||
else
|
d.angle = ((s2*sword_angles/c2->type - d.angle + s1*sword_angles/c1->type) + sword_angles/2) % sword_angles;
|
||||||
return ((s2*sword_angles/c2->type - s1*sword_angles/c1->type) + sword_angles/2 + angle) % 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) {
|
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() {
|
void reset() {
|
||||||
@ -3217,7 +3244,7 @@ auto ccm = addHook(clearmemory, 0, [] () {
|
|||||||
gd->store(prairie::enter);
|
gd->store(prairie::enter);
|
||||||
gd->store(prairie::tchoices);
|
gd->store(prairie::tchoices);
|
||||||
gd->store(prairie::beaststogen);
|
gd->store(prairie::beaststogen);
|
||||||
gd->store(sword::angle);
|
gd->store(sword::dir);
|
||||||
gd->store(elec::haveelec);
|
gd->store(elec::haveelec);
|
||||||
gd->store(elec::havecharge);
|
gd->store(elec::havecharge);
|
||||||
gd->store(elec::lightningfast);
|
gd->store(elec::lightningfast);
|
||||||
|
12
game.cpp
12
game.cpp
@ -1464,9 +1464,9 @@ bool monstersnear(cell *c, cell *nocount, eMonster who, cell *pushto, cell *come
|
|||||||
|
|
||||||
dynamicval<cell*> x5(*wcw, c);
|
dynamicval<cell*> x5(*wcw, c);
|
||||||
dynamicval<bool> x6(stalemate::nextturn, true);
|
dynamicval<bool> x6(stalemate::nextturn, true);
|
||||||
dynamicval<int> x7(sword::angle[multi::cpid],
|
dynamicval<sword::sworddir> x7(sword::dir[multi::cpid],
|
||||||
who == moPlayer ? sword::shift(comefrom, c, sword::angle[multi::cpid]) :
|
who == moPlayer ? sword::shift(comefrom, c, sword::dir[multi::cpid]) :
|
||||||
sword::angle[multi::cpid]);
|
sword::dir[multi::cpid]);
|
||||||
|
|
||||||
for(int b=0; b<2; b++) {
|
for(int b=0; b<2; b++) {
|
||||||
if(who == moPlayer) {
|
if(who == moPlayer) {
|
||||||
@ -3545,7 +3545,7 @@ void playerMoveEffects(cell *c1, cell *c2) {
|
|||||||
|
|
||||||
if(peace::on) items[itOrbSword] = c2->land == laBurial ? 100 : 0;
|
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);
|
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) {
|
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)) {
|
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 *sf = sword::pos(mf, sword::dir[multi::cpid], bb);
|
||||||
cell *st = sword::pos(mt, sword::shift(mf, mt, sword::angle[multi::cpid]) + (bb?sword::sword_angles/2:0));
|
cell *st = sword::pos(mt, sword::shift(mf, mt, sword::dir[multi::cpid]), bb);
|
||||||
f(st, bb);
|
f(st, bb);
|
||||||
if(sf != st && !isNeighbor(sf,st)) {
|
if(sf != st && !isNeighbor(sf,st)) {
|
||||||
// also attack the in-transit cell
|
// also attack the in-transit cell
|
||||||
|
21
graph.cpp
21
graph.cpp
@ -391,18 +391,22 @@ void drawPlayerEffects(const transmatrix& V, cell *c, bool onplayer) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(shmup::on && WDIM == 3) {
|
else if(WDIM == 3) {
|
||||||
#if CAP_SHAPES
|
#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])
|
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])
|
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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
int& ang = angle[multi::cpid];
|
int& ang = sword::dir[multi::cpid].angle;
|
||||||
ang %= sword::sword_angles;
|
ang %= sword::sword_angles;
|
||||||
|
|
||||||
#if CAP_QUEUE || CAP_SHAPES
|
#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(!euclid) for(int a=0; a<sword_angles; a++) {
|
||||||
if(a == ang && items[itOrbSword]) continue;
|
if(a == ang && items[itOrbSword]) continue;
|
||||||
if((a+sword_angles/2)%sword_angles == ang && items[itOrbSword2]) 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;
|
if(sword_angles > 48 && !longer) continue;
|
||||||
color_t col = darkena(0xC0C0C0, 0, 0xFF);
|
color_t col = darkena(0xC0C0C0, 0, 0xFF);
|
||||||
ld l0 = PURE ? 0.6 * cgi.scalefactor : longer ? 0.36 : 0.4;
|
ld l0 = PURE ? 0.6 * cgi.scalefactor : longer ? 0.36 : 0.4;
|
||||||
@ -6862,6 +6866,13 @@ void drawMarkers() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#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;
|
monsterToSummon = moNone;
|
||||||
|
11
hyper.h
11
hyper.h
@ -1862,12 +1862,17 @@ namespace tortoise {
|
|||||||
|
|
||||||
namespace sword {
|
namespace sword {
|
||||||
|
|
||||||
extern array<int, MAXPLAYER> angle;
|
struct sworddir {
|
||||||
|
int angle;
|
||||||
|
transmatrix T;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern array<sworddir, MAXPLAYER> dir;
|
||||||
|
|
||||||
cell *pos(cell *c, int s);
|
cell *pos(cell *c, const sworddir& sd, bool rev);
|
||||||
cell *pos(int id);
|
cell *pos(int id);
|
||||||
bool at(cell *where, bool noplayer = false);
|
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);
|
void killThePlayer(eMonster m, int id, flagtype flags);
|
||||||
|
@ -210,7 +210,10 @@ void initgame() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sword::determine_sword_angles();
|
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
|
#if CAP_DAILY
|
||||||
daily::split();
|
daily::split();
|
||||||
|
Loading…
Reference in New Issue
Block a user