1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2025-10-26 11:27:39 +00:00

Implemented the shmup versions of Ruined City and Jelly Kingdom.

This commit is contained in:
Zeno Rogue
2018-02-12 12:48:31 +01:00
parent 7218d95ce4
commit be06bd31ce
8 changed files with 81 additions and 23 deletions

View File

@@ -784,6 +784,7 @@ monstertype minf[motypes] = {
{ '*', 0xFFFF00, "Fireball", "This magical missile burns whatever it hits."}, { '*', 0xFFFF00, "Fireball", "This magical missile burns whatever it hits."},
{ '*', 0xFFFF00, "Tongue", "Some monsters have long tongues, which allow them to attack enemies in nearby cells."}, { '*', 0xFFFF00, "Tongue", "Some monsters have long tongues, which allow them to attack enemies in nearby cells."},
{ '*', 0xFFFFFF, "Airball", "This magical missile pushes back whatever it hits."}, { '*', 0xFFFFFF, "Airball", "This magical missile pushes back whatever it hits."},
{ '*', 0x0060E0, "Blueball", "A powerful missile from a Blue Raider."},
// technical // technical
{ '?', 0x00C000, "dead bug", NODESC}, { '?', 0x00C000, "dead bug", NODESC},
{ '?', 0xFFFF00, "electric discharge", elecdesc}, // appears as 'killed by electric discharge' { '?', 0xFFFF00, "electric discharge", elecdesc}, // appears as 'killed by electric discharge'

View File

@@ -1,4 +1,4 @@
static const int motypes = 161; static const int motypes = 162;
struct monstertype { struct monstertype {
char glyph; char glyph;
@@ -56,7 +56,7 @@ enum eMonster {
moPair, moHexDemon, moAltDemon, moMonk, moCrusher, moPair, moHexDemon, moAltDemon, moMonk, moCrusher,
moSwitch1, moSwitch2, moSwitch1, moSwitch2,
// shmup specials // shmup specials
moPlayer, moBullet, moFlailBullet, moFireball, moTongue, moAirball, moPlayer, moBullet, moFlailBullet, moFireball, moTongue, moAirball, moCrushball,
// temporary // temporary
moDeadBug, moLightningBolt, moDeadBird, moEnergySword, moWarning, moArrowTrap, moDeadBug, moLightningBolt, moDeadBird, moEnergySword, moWarning, moArrowTrap,
moRogueviz moRogueviz

View File

@@ -842,12 +842,24 @@ bool passable_for(eMonster m, cell *w, cell *from, flagtype extra) {
return passable(w, from, extra) && !cellUnstable(w) && ((m != moWorm && m != moTentacle) || !cellEdgeUnstable(w)); return passable(w, from, extra) && !cellUnstable(w) && ((m != moWorm && m != moTentacle) || !cellEdgeUnstable(w));
if(m == moVoidBeast) if(m == moVoidBeast)
return passable(w, from, extra | P_VOID); return passable(w, from, extra | P_VOID);
if(m == moHexDemon) if(m == moHexDemon) {
if(extra & P_ONPLAYER) {
if(isPlayerOn(w)) return true;
}
return !ctof(w) && passable(w, from, extra); return !ctof(w) && passable(w, from, extra);
if(m == moAltDemon) }
return (!w || !from || ctof(w) || ctof(from)) && passable(w, from, extra); if(m == moAltDemon) {
if(m == moMonk) if(extra & P_ONPLAYER) {
if(isPlayerOn(w)) return true;
}
return (!w || !from || w==from || ctof(w) || ctof(from)) && passable(w, from, extra);
}
if(m == moMonk) {
if(extra & P_ONPLAYER) {
if(isPlayerOn(w)) return true;
}
return notNearItem(w) && passable(w, from, extra); return notNearItem(w) && passable(w, from, extra);
}
return false; return false;
} }

View File

@@ -526,6 +526,9 @@ namespace shmup {
void addShmupHelp(string& out); void addShmupHelp(string& out);
void activateArrow(cell *c); void activateArrow(cell *c);
transmatrix& ggmatrix(cell *c); transmatrix& ggmatrix(cell *c);
void pushmonsters();
void popmonsters();
} }
// graph // graph

View File

@@ -1938,7 +1938,7 @@ void giantLandSwitch(cell *c, int d, cell *from) {
forCellEx(c2, c) if(out_ruin(c2)) forCellEx(c2, c) if(out_ruin(c2))
c->wall = waRuinWall; c->wall = waRuinWall;
} }
if(hrand(40000) < kf && !c->monst && !c->wall) { if(hrand(40000) < kf && !c->monst && !c->wall && !shmup::on) {
cell *c1 = c; cell *c1 = c;
cell *c2 = createMov(c1, hrand(c1->type)); cell *c2 = createMov(c1, hrand(c1->type));
if(c2->monst || c2->wall) return; if(c2->monst || c2->wall) return;

View File

@@ -1257,10 +1257,6 @@ int isLandValid(eLand l) {
if(l == laStorms && torus) if(l == laStorms && torus)
return 3; return 3;
// not yet implemented in Shmup
if(shmup::on && (l == laSwitch || l == laRuins))
return 0;
if(l == laMagnetic) if(l == laMagnetic)
return 0; return 0;

View File

@@ -1116,6 +1116,7 @@ eItem targetRangedOrb(cell *c, orbAction a) {
} }
if(items[itOrbPhasing] && c->cpdist == 2) { if(items[itOrbPhasing] && c->cpdist == 2) {
if(shmup::on) shmup::pushmonsters();
jumpstate = 21; jumpstate = 21;
int i = items[itOrbAether]; int i = items[itOrbAether];
if(i) items[itOrbAether] = i-1; if(i) items[itOrbAether] = i-1;
@@ -1136,8 +1137,9 @@ eItem targetRangedOrb(cell *c, orbAction a) {
if(jumpstate == 23 && !monstersnearO(a, c, NULL, moPlayer, NULL, cwt.c)) { if(jumpstate == 23 && !monstersnearO(a, c, NULL, moPlayer, NULL, cwt.c)) {
jumpstate = 24; jumpstate = 24;
if(!isCheck(a)) jumpTo(c, itOrbPhasing); if(!isCheck(a)) jumpTo(c, itOrbPhasing);
return itOrbPhasing;
} }
if(shmup::on) shmup::popmonsters();
if(jumpstate == 24) return itOrbPhasing;
} }
// (1) switch with an illusion // (1) switch with an illusion

View File

@@ -1596,7 +1596,15 @@ void movePlayer(monster *m, int delta) {
// don't have several players in one spot // don't have several players in one spot
// also don't let them run too far from each other! // also don't let them run too far from each other!
monster* crashintomon = m->isVirtual ? NULL : playerCrash(m, nat*C0); monster* crashintomon = NULL;
if(!m->isVirtual) {
crashintomon = playerCrash(m, nat*C0);
for(monster *m2: nonvirtual) if(m2!=m && m2->type == passive_switch) {
double d = intval(m2->pat*C0, nat*C0);
if(d < SCALE2 * 0.2) crashintomon = m2;
}
}
if(crashintomon) go = false; if(crashintomon) go = false;
if(go && c2 != m->base) { if(go && c2 != m->base) {
@@ -2082,6 +2090,8 @@ void moveBullet(monster *m, int delta) {
m->vel = 1/300.; m->vel = 1/300.;
else if(m->type == moFireball) else if(m->type == moFireball)
m->vel = 1/500.; m->vel = 1/500.;
else if(m->type == moCrushball)
m->vel = 1/1000.;
else if(m->type == moAirball) else if(m->type == moAirball)
m->vel = 1/200.; m->vel = 1/200.;
else if(m->type == moArrowTrap) else if(m->type == moArrowTrap)
@@ -2127,6 +2137,8 @@ void moveBullet(monster *m, int delta) {
else if(isActivable(c2)) else if(isActivable(c2))
activateActiv(c2, true); activateActiv(c2, true);
} }
if(m->type == moCrushball && c2->wall == waRuinWall)
c2->wall = waNone;
if(m->type == moFireball) { if(m->type == moFireball) {
makeflame(c2, 20, false) || makeflame(m->base, 20, false); makeflame(c2, 20, false) || makeflame(m->base, 20, false);
} }
@@ -2144,6 +2156,10 @@ void moveBullet(monster *m, int delta) {
if(m2 == m || (m2 == m->parent && m->vel >= 0) || m2->parent == m->parent) if(m2 == m || (m2 == m->parent && m->vel >= 0) || m2->parent == m->parent)
continue; continue;
eMonster ptype = parentOrSelf(m)->type;
bool slayer = m->type == moCrushball ||
(markOrb(itOrbSlaying) && (markOrb(itOrbEmpathy) ? isPlayerOrImage(ptype) : ptype == moPlayer));
// Flailers only killable by themselves // Flailers only killable by themselves
if(m2->type == moFlailer && m2 != m->parent) continue; if(m2->type == moFlailer && m2 != m->parent) continue;
// be nice to your images! would be too hard otherwise... // be nice to your images! would be too hard otherwise...
@@ -2156,6 +2172,9 @@ void moveBullet(monster *m, int delta) {
double d = intval(m2->pat*C0, m->pat*C0); double d = intval(m2->pat*C0, m->pat*C0);
if(d < SCALE2 * 0.1) { if(d < SCALE2 * 0.1) {
if(m2->type == passive_switch) { m->dead = true; continue; }
if(m->type == moAirball && isBlowableMonster(m2->type)) { if(m->type == moAirball && isBlowableMonster(m2->type)) {
if(m2->blowoff < curtime) { if(m2->blowoff < curtime) {
@@ -2167,7 +2186,7 @@ void moveBullet(monster *m, int delta) {
continue; continue;
} }
// Hedgehog Warriors only killable outside of the 45 degree angle // Hedgehog Warriors only killable outside of the 45 degree angle
if(m2->type == moHedge && !peace::on) { if(m2->type == moHedge && !peace::on && !slayer) {
hyperpoint h = inverse(m2->pat) * m->pat * C0; hyperpoint h = inverse(m2->pat) * m->pat * C0;
if(h[0] > fabsl(h[1])) { m->dead = true; continue; } if(h[0] > fabsl(h[1])) { m->dead = true; continue; }
} }
@@ -2176,10 +2195,10 @@ void moveBullet(monster *m, int delta) {
m2->stunoff = curtime + 600; m2->stunoff = curtime + 600;
continue; continue;
} }
// // multi-HP monsters
if((m2->type == moPalace || m2->type == moFatGuard || m2->type == moSkeleton || if((m2->type == moPalace || m2->type == moFatGuard || m2->type == moSkeleton ||
m2->type == moVizier || isMetalBeast(m2->type) || m2->type == moTortoise || m2->type == moVizier || isMetalBeast(m2->type) || m2->type == moTortoise ||
m2->type == moReptile || m2->type == moSalamander || m2->type == moTerraWarrior) && m2->hitpoints > 1) { m2->type == moReptile || m2->type == moSalamander || m2->type == moTerraWarrior) && m2->hitpoints > 1 && !slayer) {
m2->rebasePat(m2->pat * rspintox(inverse(m2->pat) * nat0 * C0)); m2->rebasePat(m2->pat * rspintox(inverse(m2->pat) * nat0 * C0));
if(m2->type != moSkeleton && !isMetalBeast(m2->type) && m2->type != moReptile && m2->type != moSalamander) if(m2->type != moSkeleton && !isMetalBeast(m2->type) && m2->type != moReptile && m2->type != moSalamander)
m2->hitpoints--; m2->hitpoints--;
@@ -2202,8 +2221,14 @@ void moveBullet(monster *m, int delta) {
continue; continue;
} }
// conventional missiles cannot hurt some monsters // conventional missiles cannot hurt some monsters
bool conv = (m->type == moBullet || m->type == moFlailBullet || m->type == moTongue || m->type == moArrowTrap); bool conv = (m->type == moBullet || m->type == moFlailBullet || m->type == moTongue || m->type == moArrowTrap) && !slayer;
// Raiders are unaffected
if((m2->type == moCrusher || m2->type == moPair || m2->type == moMonk ||
m2->type == moAltDemon || m2->type == moHexDemon) && conv) {
m->dead = true;
continue;
}
if(m2->type == moGreater && conv) { if(m2->type == moGreater && conv) {
m->dead = true; m->dead = true;
continue; continue;
@@ -2326,6 +2351,10 @@ void moveMonster(monster *m, int delta) {
step /= 3; step /= 3;
else if(isBull(m->type)) else if(isBull(m->type))
step *= 1.5; step *= 1.5;
else if(m->type == moAltDemon || m->type == moHexDemon || m->type == moCrusher || m->type == moMonk)
step *= 1.4;
if(m->type == passive_switch) step = 0;
if(items[itOrbBeauty] && !m->isVirtual) { if(items[itOrbBeauty] && !m->isVirtual) {
bool nearplayer = false; bool nearplayer = false;
@@ -2395,7 +2424,7 @@ void moveMonster(monster *m, int delta) {
closerTo = m->pat * C0; closerTo = m->pat * C0;
sort(bugtargets.begin(), bugtargets.end(), closer); sort(bugtargets.begin(), bugtargets.end(), closer);
for(monster *m2: bugtargets) if(step) for(monster *m2: bugtargets)
if(trackroute(m, m2->pat, step)) { if(trackroute(m, m2->pat, step)) {
goal = m2->pat; goal = m2->pat;
direct = true; direct = true;
@@ -2441,7 +2470,7 @@ void moveMonster(monster *m, int delta) {
} }
else if(!direct && !invismove && !peace::on) { else if(!direct && !invismove && !peace::on) {
for(int i=0; i<players; i++) for(int i=0; i<players; i++)
if(trackroute(m, pc[i]->pat, step) && (!direct || intval(pc[i]->pat*C0, m->pat*C0) < intval(goal*C0,m->pat*C0))) { if(step && trackroute(m, pc[i]->pat, step) && (!direct || intval(pc[i]->pat*C0, m->pat*C0) < intval(goal*C0,m->pat*C0))) {
goal = pc[i]->pat; goal = pc[i]->pat;
direct = true; direct = true;
directi = i; directi = i;
@@ -2450,7 +2479,7 @@ void moveMonster(monster *m, int delta) {
} }
if(!direct && !peace::on) while(true) { if(!direct && !peace::on) while(true) {
if(trackroute(m, gmatrix[c], step)) if(step && trackroute(m, gmatrix[c], step))
goal = gmatrix[c]; goal = gmatrix[c];
cell *cnext = c; cell *cnext = c;
for(int i=0; i<c->type; i++) { for(int i=0; i<c->type; i++) {
@@ -2581,6 +2610,8 @@ void moveMonster(monster *m, int delta) {
if(c2->wall == waChasm && !survivesChasm(m->type)) usetongue = true; if(c2->wall == waChasm && !survivesChasm(m->type)) usetongue = true;
if(isFireOrMagma(c2) && !survivesFire(m->type) && !m->inBoat) usetongue = true; if(isFireOrMagma(c2) && !survivesFire(m->type) && !m->inBoat) usetongue = true;
if(isBird(m->type) && !passable_for(moEagle, c2, c, 0)) usetongue = true; if(isBird(m->type) && !passable_for(moEagle, c2, c, 0)) usetongue = true;
if((m->type == moMonk || m->type == moAltDemon || m->type == moHexDemon) && !passable_for(m->type, c2, c, 0))
usetongue = true;
if(usetongue) { if(usetongue) {
if(curtime < m->nextshot) return; if(curtime < m->nextshot) return;
// m->nextshot = curtime + 25; // m->nextshot = curtime + 25;
@@ -2786,6 +2817,18 @@ void moveMonster(monster *m, int delta) {
additional.push_back(bullet); additional.push_back(bullet);
break; break;
} }
for(int i=0; i<players; i++) if(!pc[i]->isVirtual)
if(m->type == moCrusher && intval(m->pat*C0, pc[i]->pat*C0) < SCALE2 * .75) {
m->stunoff = curtime + 1500;
monster* bullet = new monster;
bullet->base = m->base;
bullet->at = m->at;
bullet->type = moCrushball;
bullet->parent = m;
bullet->pid = i;
additional.push_back(bullet);
break;
}
} }
} }
@@ -2830,6 +2873,7 @@ void fixStorage() {
void turn(int delta) { void turn(int delta) {
passive_switch = (gold() & 1) ? moSwitch1 : moSwitch2;
lmousetarget = NULL; lmousetarget = NULL;
if(mousetarget && !mousetarget->isVirtual && intval(mouseh, mousetarget->pat*C0) < 0.1) if(mousetarget && !mousetarget->isVirtual && intval(mouseh, mousetarget->pat*C0) < 0.1)
lmousetarget = mousetarget; lmousetarget = mousetarget;
@@ -2875,7 +2919,7 @@ void turn(int delta) {
break; break;
case moBullet: case moFlailBullet: case moFireball: case moTongue: case moAirball: case moBullet: case moFlailBullet: case moFireball: case moTongue: case moAirball:
case moArrowTrap: case moArrowTrap: case moCrushball:
moveBullet(m, delta); moveBullet(m, delta);
break; break;
@@ -3205,7 +3249,7 @@ bool drawMonster(const transmatrix& V, cell *c, const transmatrix*& Vboat, trans
ShadowV(view, shPHead); ShadowV(view, shPHead);
break; break;
} }
case moFlailBullet: { case moFlailBullet: case moCrushball: {
transmatrix t = view * spin(curtime / 50.0); transmatrix t = view * spin(curtime / 50.0);
queuepoly(mmscale(t, 1.15), shFlailMissile, (minf[m->type].color << 8) | 0xFF); queuepoly(mmscale(t, 1.15), shFlailMissile, (minf[m->type].color << 8) | 0xFF);
ShadowV(view, shFlailMissile); ShadowV(view, shFlailMissile);