mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-12-24 17:10:36 +00:00
Terracotta now works in shmup
This commit is contained in:
parent
aba5ef5358
commit
1975069797
@ -202,10 +202,10 @@ void drawArrowTraps() {
|
||||
|
||||
try {
|
||||
transmatrix& t0 = gmatrix.at(r[0]);
|
||||
transmatrix& t1 = gmatrix.at(r[1]);
|
||||
transmatrix& t1 = gmatrix.at(r[4]);
|
||||
|
||||
queueline(tC0(t0), tC0(t1), 0xFF0000FF, 4, PPR_ITEM);
|
||||
if((c->wparam & 7) == 3) {
|
||||
if((c->wparam & 7) == 3 && !shmup::on) {
|
||||
// queueline(t0 * randomPointIn(r[0]->type), t1 * randomPointIn(r[1]->type), 0xFFFFFFFF, 4, PPR_ITEM);
|
||||
int tt = ticks % 401;
|
||||
|
||||
@ -222,3 +222,8 @@ void drawArrowTraps() {
|
||||
}
|
||||
}
|
||||
|
||||
auto ccm_blizzard = addHook(clearmemory, 0, [] () {
|
||||
arrowtraps.clear();
|
||||
blizzardcells.clear();
|
||||
bcells.clear();
|
||||
});
|
||||
|
@ -2008,7 +2008,7 @@ namespace heat {
|
||||
}
|
||||
}
|
||||
|
||||
if(c->wall == waArrowTrap && c->wparam) {
|
||||
if(c->wall == waArrowTrap && c->wparam && !shmup::on) {
|
||||
c->wparam++;
|
||||
if(c->wparam == 3) {
|
||||
if(canAttack(c, moArrowTrap, c, c->monst, AF_GETPLAYER))
|
||||
|
@ -183,8 +183,8 @@ bool isAnyIvy(eMonster m) {
|
||||
|
||||
bool isBulletType(eMonster m) {
|
||||
return
|
||||
m == moBullet || m == moFlailBullet ||
|
||||
m == moFireball || m == moTongue || m == moAirball;
|
||||
m == moBullet || m == moFlailBullet || m == moFireball ||
|
||||
m == moTongue || m == moAirball || m == moArrowTrap;
|
||||
}
|
||||
|
||||
bool isMutantIvy(cell *c) { return isMutantIvy(c->monst); }
|
||||
|
61
game.cpp
61
game.cpp
@ -2983,26 +2983,29 @@ bool isCentralTrap(cell *c) {
|
||||
return i == 2;
|
||||
}
|
||||
|
||||
array<cell*, 2> traplimits(cell *c) {
|
||||
array<cell*, 2> res;
|
||||
array<cell*, 5> traplimits(cell *c) {
|
||||
array<cell*, 5> res;
|
||||
int q = 0;
|
||||
res[2] = c;
|
||||
for(int d=0; d<c->type; d++) {
|
||||
cellwalker cw(c, d);
|
||||
cwstep(cw);
|
||||
if(cw.c->wall != waArrowTrap) continue;
|
||||
res[1+q*2] = cw.c;
|
||||
cwspin(cw, cw.c->type/2);
|
||||
if((cw.c->type&1) && cwpeek(cw, 0)->wall != waStone) cwspin(cw, 1);
|
||||
cwstep(cw);
|
||||
res[q++] = cw.c;
|
||||
res[(q++)*4] = cw.c;
|
||||
}
|
||||
while(q<2) res[q++] = NULL;
|
||||
while(q<2) { res[q*4] = res[1+q*2] = NULL; q++; }
|
||||
return res;
|
||||
}
|
||||
|
||||
void activateArrowTrap(cell *c) {
|
||||
if(c->wall == waArrowTrap && c->wparam == 0) {
|
||||
c->wparam = 1;
|
||||
c->wparam = shmup::on ? 2 : 1;
|
||||
forCellEx(c2, c) activateArrowTrap(c2);
|
||||
if(shmup::on) shmup::activateArrow(c);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3093,7 +3096,7 @@ void playerMoveEffects(cell *c1, cell *c2) {
|
||||
if((c2->wall == waClosePlate || c2->wall == waOpenPlate) && !markOrb(itOrbAether))
|
||||
toggleGates(c2, c2->wall);
|
||||
|
||||
if(c2->wall == waArrowTrap && !markOrb(itOrbAether))
|
||||
if(c2->wall == waArrowTrap && c2->wparam == 0 && !markOrb(itOrbAether))
|
||||
activateArrowTrap(c2);
|
||||
|
||||
princess::playernear(c2);
|
||||
@ -6620,27 +6623,37 @@ namespace orbbull {
|
||||
// predictable or not
|
||||
static constexpr bool randterra = false;
|
||||
|
||||
void terracotta(cell *c) {
|
||||
if(c->wall == waTerraWarrior) {
|
||||
bool live = false;
|
||||
if(randterra) {
|
||||
c->landparam++;
|
||||
if((c->landparam == 3 && hrand(3) == 0) ||
|
||||
(c->landparam == 4 && hrand(2) == 0) ||
|
||||
c->landparam == 5)
|
||||
live = true;
|
||||
}
|
||||
else {
|
||||
c->landparam--;
|
||||
live = !c->landparam;
|
||||
}
|
||||
if(live)
|
||||
c->monst = moTerraWarrior,
|
||||
c->hitpoints = 7,
|
||||
c->wall = waNone;
|
||||
}
|
||||
}
|
||||
|
||||
void terracotta() {
|
||||
for(int i=0; i<numplayers(); i++)
|
||||
forCellEx(c2, playerpos(i))
|
||||
if(c2->wall == waTerraWarrior) {
|
||||
bool live = false;
|
||||
if(randterra) {
|
||||
c2->landparam++;
|
||||
if((c2->landparam == 3 && hrand(3) == 0) ||
|
||||
(c2->landparam == 4 && hrand(2) == 0) ||
|
||||
c2->landparam == 5)
|
||||
live = true;
|
||||
}
|
||||
else {
|
||||
c2->landparam--;
|
||||
live = !c2->landparam;
|
||||
}
|
||||
if(live)
|
||||
c2->monst = moTerraWarrior,
|
||||
c2->hitpoints = 7,
|
||||
c2->wall = waNone;
|
||||
forCellEx(c, playerpos(i)) {
|
||||
if(shmup::on) {
|
||||
forCellEx(c2, c)
|
||||
terracotta(c2);
|
||||
}
|
||||
else
|
||||
terracotta(c);
|
||||
}
|
||||
}
|
||||
|
||||
void monstersTurn() {
|
||||
|
1
hyper.h
1
hyper.h
@ -233,6 +233,7 @@ namespace shmup {
|
||||
void virtualRebase(shmup::monster *m, bool tohex);
|
||||
void fixStorage();
|
||||
void addShmupHelp(string& out);
|
||||
void activateArrow(cell *c);
|
||||
}
|
||||
|
||||
// graph
|
||||
|
73
shmup.cpp
73
shmup.cpp
@ -1444,6 +1444,48 @@ bool hornKills(eMonster m) {
|
||||
m != moSalamander && m != moTerraWarrior;
|
||||
}
|
||||
|
||||
queue<pair<int, cell*>> traplist;
|
||||
|
||||
void activateArrow(cell *c) {
|
||||
if(isCentralTrap(c))
|
||||
traplist.emplace(ticks + 500, c);
|
||||
}
|
||||
|
||||
monster arrowtrap_fakeparent;
|
||||
|
||||
void doTraps() {
|
||||
while(true) {
|
||||
if(traplist.empty()) return;
|
||||
auto t = traplist.front();
|
||||
if(t.first > ticks) return;
|
||||
int d = t.second->wparam;
|
||||
if(d == 2) {
|
||||
auto tl = traplimits(t.second);
|
||||
for(int i=1; i<4; i++) if(tl[i]) tl[i]->wparam = 3;
|
||||
traplist.emplace(t.first + 500, t.second);
|
||||
|
||||
for(int i=0; i<5; i += 4) try {
|
||||
transmatrix& tu = gmatrix.at(tl[i]);
|
||||
transmatrix& tv = gmatrix.at(tl[4-i]);
|
||||
monster* bullet = new monster;
|
||||
bullet->base = tl[i];
|
||||
bullet->at = rspintox(inverse(tu) * tC0(tv));
|
||||
bullet->type = moArrowTrap;
|
||||
bullet->parent = &arrowtrap_fakeparent;
|
||||
bullet->pid = 0;
|
||||
bullet->parenttype = moArrowTrap;
|
||||
additional.push_back(bullet);
|
||||
}
|
||||
catch(out_of_range) {}
|
||||
}
|
||||
else if(d == 3) {
|
||||
auto tl = traplimits(t.second);
|
||||
for(int i=1; i<4; i++) if(tl[i]) tl[i]->wparam = 0;
|
||||
}
|
||||
traplist.pop();
|
||||
}
|
||||
}
|
||||
|
||||
bool hornStuns(eMonster m) {
|
||||
return !isBulletType(m) && m != moRoseBeauty;
|
||||
}
|
||||
@ -1757,6 +1799,9 @@ void movePlayer(monster *m, int delta) {
|
||||
if(c2->wall == waClosePlate || c2->wall == waOpenPlate)
|
||||
toggleGates(c2, c2->wall);
|
||||
|
||||
if(c2->wall == waArrowTrap && c2->wparam == 0 && !markOrb(itOrbAether))
|
||||
activateArrowTrap(c2);
|
||||
|
||||
if(c2->item == itOrbYendor && !peace::on) yendor::check(c2);
|
||||
collectItem(c2);
|
||||
}
|
||||
@ -2106,6 +2151,8 @@ void moveBullet(monster *m, int delta) {
|
||||
m->vel = 1/500.;
|
||||
else if(m->type == moAirball)
|
||||
m->vel = 1/200.;
|
||||
else if(m->type == moArrowTrap)
|
||||
m->vel = 1/200.;
|
||||
else if(m->type == moTongue) {
|
||||
m->vel = 1/1500.;
|
||||
if(m->isVirtual || !m->parent || intval(nat*C0, m->parent->pat*C0) > SCALE2 * 0.4)
|
||||
@ -2131,7 +2178,7 @@ void moveBullet(monster *m, int delta) {
|
||||
|
||||
bool godragon = m->type == moFireball && isDragon(c2->monst);
|
||||
|
||||
if(m->type != moTongue && !(godragon || passable(c2, m->base, P_BULLET | P_MIRRORWALL))) {
|
||||
if(m->type != moTongue && !(godragon || (c2==m->base && m->type == moArrowTrap) || passable(c2, m->base, P_BULLET | P_MIRRORWALL))) {
|
||||
m->dead = true;
|
||||
if(m->type != moAirball) killMonster(c2, m->parent ? m->parent->type : moNone);
|
||||
// cell *c = m->base;
|
||||
@ -2161,7 +2208,8 @@ void moveBullet(monster *m, int delta) {
|
||||
// items[itOrbWinter] = 100; items[itOrbLife] = 100;
|
||||
|
||||
if(!m->isVirtual) for(monster* m2: nonvirtual) {
|
||||
if(m2 == m || (m2 == m->parent && m->vel >= 0) || m2->parent == m->parent) continue;
|
||||
if(m2 == m || (m2 == m->parent && m->vel >= 0) || m2->parent == m->parent)
|
||||
continue;
|
||||
|
||||
// Flailers only killable by themselves
|
||||
if(m2->type == moFlailer && m2 != m->parent) continue;
|
||||
@ -2221,7 +2269,7 @@ void moveBullet(monster *m, int delta) {
|
||||
continue;
|
||||
}
|
||||
// conventional missiles cannot hurt some monsters
|
||||
bool conv = (m->type == moBullet || m->type == moFlailBullet || m->type == moTongue);
|
||||
bool conv = (m->type == moBullet || m->type == moFlailBullet || m->type == moTongue || m->type == moArrowTrap);
|
||||
|
||||
if(m2->type == moGreater && conv) {
|
||||
m->dead = true;
|
||||
@ -2243,7 +2291,7 @@ void moveBullet(monster *m, int delta) {
|
||||
}
|
||||
// Knights reflect bullets
|
||||
if(m2->type == moKnight) {
|
||||
if(m->parent) {
|
||||
if(m->parent && m->parent != &arrowtrap_fakeparent) {
|
||||
nat = nat * rspintox(inverse(m->pat) * m->parent->pat * C0);
|
||||
m->rebasePat(nat);
|
||||
}
|
||||
@ -2379,7 +2427,7 @@ void moveMonster(monster *m, int delta) {
|
||||
else {
|
||||
|
||||
if(m->type == moSleepBull && !m->isVirtual) {
|
||||
for(monster *m2: nonvirtual) if(m2!=m && m2->type != moBullet) {
|
||||
for(monster *m2: nonvirtual) if(m2!=m && m2->type != moBullet && m2->type != moArrowTrap) {
|
||||
double d = intval(m2->pat*C0, nat*C0);
|
||||
if(d < SCALE2*3 && m2->type == moPlayer) m->type = moRagingBull;
|
||||
}
|
||||
@ -2554,7 +2602,7 @@ void moveMonster(monster *m, int delta) {
|
||||
|
||||
monster* crashintomon = NULL;
|
||||
|
||||
if(!m->isVirtual) for(monster *m2: nonvirtual) if(m2!=m && m2->type != moBullet) {
|
||||
if(!m->isVirtual) for(monster *m2: nonvirtual) if(m2!=m && m2->type != moBullet && m2->type != moArrowTrap) {
|
||||
double d = intval(m2->pat*C0, nat*C0);
|
||||
if(d < SCALE2 * 0.1) crashintomon = m2;
|
||||
}
|
||||
@ -2620,6 +2668,9 @@ void moveMonster(monster *m, int delta) {
|
||||
if(c2 != m->base && (c2->wall == waClosePlate || c2->wall == waOpenPlate) && !ignoresPlates(m->type))
|
||||
toggleGates(c2, c2->wall, 3);
|
||||
|
||||
if(c2 != m->base && c2->wall == waArrowTrap && c2->wparam == 0 && !ignoresPlates(m->type))
|
||||
activateArrowTrap(c2);
|
||||
|
||||
if(c2 != m->base && mayExplodeMine(c2, m->type))
|
||||
killMonster(m, moNone);
|
||||
|
||||
@ -2891,6 +2942,7 @@ void turn(int delta) {
|
||||
break;
|
||||
|
||||
case moBullet: case moFlailBullet: case moFireball: case moTongue: case moAirball:
|
||||
case moArrowTrap:
|
||||
moveBullet(m, delta);
|
||||
break;
|
||||
|
||||
@ -2945,6 +2997,8 @@ void turn(int delta) {
|
||||
|
||||
if(shmup::on) {
|
||||
|
||||
doTraps();
|
||||
|
||||
bool tick = curtime >= nextmove;
|
||||
keepLightning = ticks <= lightat + 1000;
|
||||
cwt.c = pc[0]->base;
|
||||
@ -2977,6 +3031,7 @@ void turn(int delta) {
|
||||
if(havewhat&HF_HEX) movehex(false);
|
||||
wandering();
|
||||
livecaves();
|
||||
terracotta();
|
||||
heat::processfires();
|
||||
if(havewhat&HF_WHIRLPOOL) whirlpool::move();
|
||||
if(havewhat&HF_WHIRLWIND) whirlwind::move();
|
||||
@ -3201,6 +3256,11 @@ bool drawMonster(const transmatrix& V, cell *c, const transmatrix*& Vboat, trans
|
||||
}
|
||||
break;
|
||||
}
|
||||
case moArrowTrap: {
|
||||
queuepoly(mmscale(view, 1.15), shTrapArrow, 0xFFFFFFFF);
|
||||
ShadowV(view, shTrapArrow);
|
||||
break;
|
||||
}
|
||||
case moTongue: {
|
||||
queuepoly(mmscale(view, 1.15), shTongue, (minf[m->parenttype].color << 8) | 0xFF);
|
||||
ShadowV(view, shTongue);
|
||||
@ -3261,6 +3321,7 @@ void clearMonsters() {
|
||||
void clearMemory() {
|
||||
clearMonsters();
|
||||
gmatrix.clear();
|
||||
traplist = {};
|
||||
curtime = 0;
|
||||
nextmove = 0;
|
||||
nextdragon = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user