Terracotta now works in shmup

This commit is contained in:
Zeno Rogue 2017-10-12 11:33:26 +02:00
parent aba5ef5358
commit 1975069797
6 changed files with 117 additions and 37 deletions

View File

@ -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;
@ -221,4 +221,9 @@ void drawArrowTraps() {
catch(out_of_range) {}
}
}
auto ccm_blizzard = addHook(clearmemory, 0, [] () {
arrowtraps.clear();
blizzardcells.clear();
bcells.clear();
});

View File

@ -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))

View File

@ -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); }

View File

@ -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() {

View File

@ -233,6 +233,7 @@ namespace shmup {
void virtualRebase(shmup::monster *m, bool tohex);
void fixStorage();
void addShmupHelp(string& out);
void activateArrow(cell *c);
}
// graph

View File

@ -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;
}
@ -1756,6 +1798,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;
}
@ -2619,7 +2667,10 @@ 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;