mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-09-28 06:08:14 +00:00
movei used in more places, also improved push in shmup
This commit is contained in:
parent
8ddd95d44e
commit
2172ca6fd7
129
game.cpp
129
game.cpp
@ -924,18 +924,18 @@ EX bool canPushStatueOn(cell *c) {
|
|||||||
!among(c->wall, waBoat, waFireTrap, waArrowTrap);
|
!among(c->wall, waBoat, waFireTrap, waArrowTrap);
|
||||||
}
|
}
|
||||||
|
|
||||||
EX void moveBoat(cell *to, cell *from, int direction_hint) {
|
EX void moveBoat(const movei& mi) {
|
||||||
eWall x = to->wall; to->wall = from->wall; from->wall = x;
|
eWall x = mi.t->wall; mi.t->wall = mi.s->wall; mi.s->wall = x;
|
||||||
to->mondir = neighborId(to, from);
|
mi.t->mondir = mi.rev_dir_or(NODIR);
|
||||||
moveItem(from, to, false);
|
moveItem(mi.s, mi.t, false);
|
||||||
animateMovement(from, to, LAYER_BOAT, direction_hint);
|
animateMovement(mi, LAYER_BOAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
EX void moveBoatIfUsingOne(cell *to, cell *from, int direction_hint) {
|
EX void moveBoatIfUsingOne(const movei& mi) {
|
||||||
if(from->wall == waBoat && isWatery(to)) moveBoat(to, from, direction_hint);
|
if(mi.s->wall == waBoat && isWatery(mi.t)) moveBoat(mi);
|
||||||
else if(from->wall == waBoat && boatGoesThrough(to) && isFriendly(to) && markEmpathy(itOrbWater)) {
|
else if(mi.s->wall == waBoat && boatGoesThrough(mi.t) && isFriendly(mi.t) && markEmpathy(itOrbWater)) {
|
||||||
placeWater(to, from);
|
placeWater(mi.t, mi.s);
|
||||||
moveBoat(to, from, direction_hint);
|
moveBoat(mi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2331,7 +2331,7 @@ EX void killMonster(cell *c, eMonster who, flagtype deathflags IS(0)) {
|
|||||||
}
|
}
|
||||||
if(m == moVineBeast)
|
if(m == moVineBeast)
|
||||||
petrify(c, waVinePlant, m), pcount = 0;
|
petrify(c, waVinePlant, m), pcount = 0;
|
||||||
if(isBird(m)) moveEffect(c, c, moDeadBird, -1);
|
if(isBird(m)) moveEffect(movei(c, FALL), moDeadBird);
|
||||||
if(m == moAcidBird) {
|
if(m == moAcidBird) {
|
||||||
playSound(c, "die-bomberbird");
|
playSound(c, "die-bomberbird");
|
||||||
pcount = 64;
|
pcount = 64;
|
||||||
@ -2701,8 +2701,10 @@ EX bool attackMonster(cell *c, flagtype flags, eMonster killer) {
|
|||||||
return ntk > tk;
|
return ntk > tk;
|
||||||
}
|
}
|
||||||
|
|
||||||
EX void pushMonster(cell *ct, cell *cf, int direction_hint) {
|
EX void pushMonster(const movei& mi) {
|
||||||
moveMonster(ct, cf, direction_hint);
|
moveMonster(mi);
|
||||||
|
auto& cf = mi.s;
|
||||||
|
auto& ct = mi.t;
|
||||||
if(ct->monst == moBrownBug) {
|
if(ct->monst == moBrownBug) {
|
||||||
int t = snakelevel(ct) - snakelevel(cf);
|
int t = snakelevel(ct) - snakelevel(cf);
|
||||||
if(t > 0)
|
if(t > 0)
|
||||||
@ -3587,7 +3589,13 @@ EX void activateArrowTrap(cell *c) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
EX void moveEffect(cell *ct, cell *cf, eMonster m, int direction_hint) {
|
EX void moveEffect(cell *ct, cell *cf, eMonster m, int direction_hint) {
|
||||||
|
moveEffect(movei(cf, ct, direction_hint), m);
|
||||||
|
}
|
||||||
|
|
||||||
|
EX void moveEffect(const movei& mi, eMonster m) {
|
||||||
|
|
||||||
|
auto& cf = mi.s;
|
||||||
|
auto& ct = mi.t;
|
||||||
if(cf) destroyWeakBranch(cf, ct, m);
|
if(cf) destroyWeakBranch(cf, ct, m);
|
||||||
|
|
||||||
mayExplodeMine(ct, m);
|
mayExplodeMine(ct, m);
|
||||||
@ -3622,7 +3630,7 @@ EX void moveEffect(cell *ct, cell *cf, eMonster m, int direction_hint) {
|
|||||||
if(cf && ct->item == itBabyTortoise && !cf->item) {
|
if(cf && ct->item == itBabyTortoise && !cf->item) {
|
||||||
cf->item = itBabyTortoise;
|
cf->item = itBabyTortoise;
|
||||||
ct->item = itNone;
|
ct->item = itNone;
|
||||||
animateMovement(ct, cf, LAYER_BOAT, direction_hint);
|
animateMovement(mi.rev(), LAYER_BOAT);
|
||||||
tortoise::babymap[cf] = tortoise::babymap[ct];
|
tortoise::babymap[cf] = tortoise::babymap[ct];
|
||||||
tortoise::babymap.erase(ct);
|
tortoise::babymap.erase(ct);
|
||||||
}
|
}
|
||||||
@ -3824,19 +3832,25 @@ EX void makeTrollFootprints(cell *c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
EX void moveMonster(cell *ct, cell *cf, int direction_hint) {
|
EX void moveMonster(cell *ct, cell *cf, int direction_hint) {
|
||||||
|
moveMonster(movei(cf, ct, direction_hint));
|
||||||
|
}
|
||||||
|
|
||||||
|
EX void moveMonster(const movei& mi) {
|
||||||
|
auto& cf = mi.s;
|
||||||
|
auto& ct = mi.t;
|
||||||
eMonster m = cf->monst;
|
eMonster m = cf->monst;
|
||||||
bool fri = isFriendly(cf);
|
bool fri = isFriendly(cf);
|
||||||
if(isDragon(m)) {
|
if(isDragon(m)) {
|
||||||
printf("called for Dragon\n");
|
printf("called for Dragon\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(m != moMimic) animateMovement(cf, ct, LAYER_SMALL, direction_hint);
|
if(m != moMimic) animateMovement(mi, LAYER_SMALL);
|
||||||
// the following line is necessary because otherwise plates disappear only inside the sight range
|
// the following line is necessary because otherwise plates disappear only inside the sight range
|
||||||
if(cellUnstable(cf) && !ignoresPlates(m)) {
|
if(cellUnstable(cf) && !ignoresPlates(m)) {
|
||||||
fallingFloorAnimation(cf);
|
fallingFloorAnimation(cf);
|
||||||
cf->wall = waChasm;
|
cf->wall = waChasm;
|
||||||
}
|
}
|
||||||
moveEffect(ct, cf, m, direction_hint);
|
moveEffect(mi, m);
|
||||||
if(ct->wall == waCamelotMoat &&
|
if(ct->wall == waCamelotMoat &&
|
||||||
(m == moShark || m == moCShark || m == moGreaterShark))
|
(m == moShark || m == moCShark || m == moGreaterShark))
|
||||||
achievement_gain("MOATSHARK");
|
achievement_gain("MOATSHARK");
|
||||||
@ -3879,10 +3893,10 @@ EX void moveMonster(cell *ct, cell *cf, int direction_hint) {
|
|||||||
if(ct->wall == waBigStatue) {
|
if(ct->wall == waBigStatue) {
|
||||||
ct->wall = cf->wall;
|
ct->wall = cf->wall;
|
||||||
cf->wall = waBigStatue;
|
cf->wall = waBigStatue;
|
||||||
animateMovement(ct, cf, LAYER_BOAT, revhint(cf, direction_hint));
|
animateMovement(mi.rev(), LAYER_BOAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
moveBoatIfUsingOne(ct, cf, revhint(cf, direction_hint));
|
moveBoatIfUsingOne(mi);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isTroll(m)) { makeTrollFootprints(ct); makeTrollFootprints(cf); }
|
if(isTroll(m)) { makeTrollFootprints(ct); makeTrollFootprints(cf); }
|
||||||
@ -4385,8 +4399,9 @@ EX vector<int> reverse_directions(heptagon *c, int dir) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if HDR
|
||||||
template<class T>
|
template<class T>
|
||||||
cell *determinePush(cellwalker who, cell *c2, int subdir, const T& valid, int& pushdir) {
|
movei determinePush(cellwalker who, int subdir, const T& valid) {
|
||||||
if(subdir != 1 && subdir != -1) {
|
if(subdir != 1 && subdir != -1) {
|
||||||
subdir = 1;
|
subdir = 1;
|
||||||
static bool first = true;
|
static bool first = true;
|
||||||
@ -4396,22 +4411,22 @@ cell *determinePush(cellwalker who, cell *c2, int subdir, const T& valid, int& p
|
|||||||
}
|
}
|
||||||
cellwalker push = who;
|
cellwalker push = who;
|
||||||
push += wstep;
|
push += wstep;
|
||||||
|
cell *c2 = push.at;
|
||||||
if(binarytiling) {
|
if(binarytiling) {
|
||||||
auto rd = reverse_directions(push.at, push.spin);
|
auto rd = reverse_directions(push.at, push.spin);
|
||||||
for(int i: rd) {
|
for(int i: rd) {
|
||||||
push.spin = i;
|
push.spin = i;
|
||||||
if(valid(push.cpeek())) return push.cpeek();
|
if(valid(push.cpeek())) return movei(push.at, push.spin);
|
||||||
}
|
}
|
||||||
return c2;
|
return movei(c2, NO_SPACE);
|
||||||
}
|
}
|
||||||
int pd = push.at->type/2;
|
int pd = push.at->type/2;
|
||||||
push += pd * -subdir;
|
push += pd * -subdir;
|
||||||
push += wstep;
|
push += wstep;
|
||||||
if(valid(push.at)) return push.at;
|
if(valid(push.at)) return movei(c2, (push+wstep).spin);
|
||||||
if(c2->type&1) {
|
if(c2->type&1) {
|
||||||
push = push + wstep - subdir + wstep;
|
push = push + wstep - subdir + wstep;
|
||||||
pushdir = (push+wstep).spin;
|
if(valid(push.at)) return movei(c2, (push+wstep).spin);
|
||||||
if(valid(push.at)) return push.at;
|
|
||||||
}
|
}
|
||||||
if(gravityLevelDiff(push.at, c2) < 0) {
|
if(gravityLevelDiff(push.at, c2) < 0) {
|
||||||
push = push + wstep + 1 + wstep;
|
push = push + wstep + 1 + wstep;
|
||||||
@ -4421,11 +4436,11 @@ cell *determinePush(cellwalker who, cell *c2, int subdir, const T& valid, int& p
|
|||||||
if(gravityLevelDiff(push.at, c2) < 0) {
|
if(gravityLevelDiff(push.at, c2) < 0) {
|
||||||
push = push + wstep + 1 + wstep;
|
push = push + wstep + 1 + wstep;
|
||||||
}
|
}
|
||||||
pushdir = (push+wstep).spin;
|
if(valid(push.at)) return movei(c2, (push+wstep).spin);
|
||||||
if(valid(push.at)) return push.at;
|
|
||||||
}
|
}
|
||||||
return c2;
|
return movei(c2, NO_SPACE);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Angry Beast attack
|
// Angry Beast attack
|
||||||
// note: this is done both before and after movement
|
// note: this is done both before and after movement
|
||||||
@ -4441,10 +4456,9 @@ EX void beastAttack(cell *c, bool player, bool targetdir) {
|
|||||||
if(c2->monst && c2->stuntime) {
|
if(c2->monst && c2->stuntime) {
|
||||||
cellwalker bull (c, d);
|
cellwalker bull (c, d);
|
||||||
int subdir = determinizeBullPush(bull);
|
int subdir = determinizeBullPush(bull);
|
||||||
int pushdir = NOHINT;
|
auto mi = determinePush(bull, subdir, [c2] (cell *c) { return passable(c, c2, P_BLOW); });
|
||||||
cell *c3 = determinePush(bull, c2, subdir, [c2] (cell *c) { return passable(c, c2, P_BLOW); }, pushdir);
|
if(mi.proper())
|
||||||
if(c3 && c3 != c2)
|
pushMonster(mi);
|
||||||
pushMonster(c3, c2, pushdir);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(c2->wall == waThumperOff) {
|
if(c2->wall == waThumperOff) {
|
||||||
@ -4459,10 +4473,9 @@ EX void beastAttack(cell *c, bool player, bool targetdir) {
|
|||||||
if(c2->wall == waThumperOn) {
|
if(c2->wall == waThumperOn) {
|
||||||
cellwalker bull (c, d);
|
cellwalker bull (c, d);
|
||||||
int subdir = determinizeBullPush(bull);
|
int subdir = determinizeBullPush(bull);
|
||||||
int pushdir = NOHINT;
|
auto mi = determinePush(bull, subdir, [c2] (cell *c) { return canPushThumperOn(c, c2, c); });
|
||||||
cell *c3 = determinePush(bull, c2, subdir, [c2] (cell *c) { return canPushThumperOn(c, c2, c); }, pushdir);
|
if(mi.proper())
|
||||||
if(c3 && c3 != c2)
|
pushThumper(mi);
|
||||||
pushThumper(c2, c3);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5750,10 +5763,6 @@ EX int movevalue(eMonster m, cell *c, cell *c2, flagtype flags) {
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HDR
|
|
||||||
constexpr int STRONGWIND = 99;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
EX void movegolems(flagtype flags) {
|
EX void movegolems(flagtype flags) {
|
||||||
if(items[itOrbEmpathy] && items[itOrbSlaying])
|
if(items[itOrbEmpathy] && items[itOrbSlaying])
|
||||||
flags |= AF_CRUSH;
|
flags |= AF_CRUSH;
|
||||||
@ -5799,7 +5808,8 @@ EX void movegolems(flagtype flags) {
|
|||||||
|
|
||||||
if(bq == 0) continue;
|
if(bq == 0) continue;
|
||||||
int dir = bdirs[hrand(bq)];
|
int dir = bdirs[hrand(bq)];
|
||||||
cell *c2 = dir != STRONGWIND ? c->move(dir) : whirlwind::jumpDestination(c);
|
auto mi = movei(c, dir);
|
||||||
|
auto& c2 = mi.t;
|
||||||
if(c2->monst) {
|
if(c2->monst) {
|
||||||
bool revenge = (m == moPrincess);
|
bool revenge = (m == moPrincess);
|
||||||
bool jealous = (isPrincess(c->monst) && isPrincess(c2->monst));
|
bool jealous = (isPrincess(c->monst) && isPrincess(c2->monst));
|
||||||
@ -5824,9 +5834,9 @@ EX void movegolems(flagtype flags) {
|
|||||||
else {
|
else {
|
||||||
passable_for(m, c2, c, P_DEADLY);
|
passable_for(m, c2, c, P_DEADLY);
|
||||||
DEBB(DF_TURN, ("move"));
|
DEBB(DF_TURN, ("move"));
|
||||||
moveMonster(c2, c, dir);
|
moveMonster(mi);
|
||||||
if(m != moTameBomberbird && m != moFriendlyGhost)
|
if(m != moTameBomberbird && m != moFriendlyGhost)
|
||||||
moveBoatIfUsingOne(c2, c, dir);
|
moveBoatIfUsingOne(mi);
|
||||||
|
|
||||||
if(c2->monst == m) {
|
if(c2->monst == m) {
|
||||||
if(m == moGolem) c2->monst = moGolemMoved;
|
if(m == moGolem) c2->monst = moGolemMoved;
|
||||||
@ -7879,7 +7889,9 @@ EX void monstersTurn() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
EX void pushThumper(cell *th, cell *cto) {
|
EX void pushThumper(const movei& mi) {
|
||||||
|
auto &cto = mi.t;
|
||||||
|
auto &th = mi.s;
|
||||||
eWall w = th->wall;
|
eWall w = th->wall;
|
||||||
if(th->land == laAlchemist)
|
if(th->land == laAlchemist)
|
||||||
th->wall = isAlch(cwt.at) ? cwt.at->wall : cto->wall;
|
th->wall = isAlch(cwt.at) ? cwt.at->wall : cto->wall;
|
||||||
@ -8146,9 +8158,8 @@ EX bool movepcto(int d, int subdir IS(1), bool checkonly IS(false)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(isPushable(c2->wall) && !c2->monst && !nonAdjacentPlayer(c2, cwt.at) && fmsMove) {
|
if(isPushable(c2->wall) && !c2->monst && !nonAdjacentPlayer(c2, cwt.at) && fmsMove) {
|
||||||
int pushdir;
|
auto mip = determinePush(cwt, subdir, [c2] (cell *c) { return canPushThumperOn(c, c2, cwt.at); });
|
||||||
cell *c3 = determinePush(cwt, c2, subdir, [c2] (cell *c) { return canPushThumperOn(c, c2, cwt.at); }, pushdir);
|
if(mip.d == NO_SPACE) {
|
||||||
if(c3 == c2) {
|
|
||||||
if(checkonly) return false;
|
if(checkonly) return false;
|
||||||
addMessage(XLAT("No room to push %the1.", c2->wall));
|
addMessage(XLAT("No room to push %the1.", c2->wall));
|
||||||
return false;
|
return false;
|
||||||
@ -8157,11 +8168,11 @@ EX bool movepcto(int d, int subdir IS(1), bool checkonly IS(false)) {
|
|||||||
if(!checkonly && errormsgs) wouldkill("%The1 would kill you there!");
|
if(!checkonly && errormsgs) wouldkill("%The1 would kill you there!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
global_pushto = c3;
|
global_pushto = mip.t;
|
||||||
if(checkonly) { nextmovetype = lmMove; return true; }
|
if(checkonly) { nextmovetype = lmMove; return true; }
|
||||||
addMessage(XLAT("You push %the1.", c2->wall));
|
addMessage(XLAT("You push %the1.", c2->wall));
|
||||||
lastmovetype = lmPush; lastmove = cwt.at;
|
lastmovetype = lmPush; lastmove = cwt.at;
|
||||||
pushThumper(c2, c3);
|
pushThumper(mip);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(c2->item == itHolyGrail && roundTableRadius(c2) < newRoundTableRadius()) {
|
if(c2->item == itHolyGrail && roundTableRadius(c2) < newRoundTableRadius()) {
|
||||||
@ -8203,7 +8214,7 @@ EX bool movepcto(int d, int subdir IS(1), bool checkonly IS(false)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(checkonly) { nextmovetype = lmMove; return true; }
|
if(checkonly) { nextmovetype = lmMove; return true; }
|
||||||
moveBoat(c2, cwt.at, d);
|
moveBoat(mi);
|
||||||
boatmove = true;
|
boatmove = true;
|
||||||
goto boatjump;
|
goto boatjump;
|
||||||
}
|
}
|
||||||
@ -8219,7 +8230,7 @@ EX bool movepcto(int d, int subdir IS(1), bool checkonly IS(false)) {
|
|||||||
if(checkonly) { nextmovetype = lmMove; return true; }
|
if(checkonly) { nextmovetype = lmMove; return true; }
|
||||||
if(c2->item && !cwt.at->item) moveItem(c2, cwt.at, false), boatmove = true;
|
if(c2->item && !cwt.at->item) moveItem(c2, cwt.at, false), boatmove = true;
|
||||||
placeWater(c2, cwt.at);
|
placeWater(c2, cwt.at);
|
||||||
moveBoat(c2, cwt.at, d);
|
moveBoat(mi);
|
||||||
c2->mondir = revhint(cwt.at, d);
|
c2->mondir = revhint(cwt.at, d);
|
||||||
if(c2->item) boatmove = !boatmove;
|
if(c2->item) boatmove = !boatmove;
|
||||||
goto boatjump;
|
goto boatjump;
|
||||||
@ -8375,23 +8386,25 @@ EX bool movepcto(int d, int subdir IS(1), bool checkonly IS(false)) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// pushto=c2 means that the monster is not killed and thus
|
// pushto=c2 means that the monster is not destroyed and thus
|
||||||
// still counts for lightning in monstersnear
|
// still counts for lightning in monstersnear
|
||||||
|
|
||||||
|
movei mip(c2, nullptr, NO_SPACE);
|
||||||
|
|
||||||
cell *pushto = NULL;
|
cell *pushto = NULL;
|
||||||
int pushdir = 0;
|
|
||||||
if(isStunnable(c2->monst) && c2->hitpoints > 1) {
|
if(isStunnable(c2->monst) && c2->hitpoints > 1) {
|
||||||
if(monsterPushable(c2))
|
if(monsterPushable(c2))
|
||||||
pushto = determinePush(cwt, c2, subdir, [c2] (cell *c) { return passable(c, c2, P_BLOW); }, pushdir);
|
mip = determinePush(cwt, subdir, [c2] (cell *c) { return passable(c, c2, P_BLOW); });
|
||||||
else
|
else
|
||||||
pushto = c2;
|
mip.t = c2;
|
||||||
}
|
}
|
||||||
if(c2->monst == moTroll || c2->monst == moFjordTroll ||
|
if(c2->monst == moTroll || c2->monst == moFjordTroll ||
|
||||||
c2->monst == moForestTroll || c2->monst == moStormTroll || c2->monst == moVineSpirit)
|
c2->monst == moForestTroll || c2->monst == moStormTroll || c2->monst == moVineSpirit)
|
||||||
pushto = c2;
|
mip.t = c2;
|
||||||
|
|
||||||
global_pushto = pushto;
|
global_pushto = mip.t;
|
||||||
|
|
||||||
if(havePushConflict(pushto, checkonly)) return false;
|
if(havePushConflict(mip.t, checkonly)) return false;
|
||||||
|
|
||||||
if(!(isWatery(cwt.at) && c2->monst == moWaterElemental) && checkNeedMove(checkonly, true))
|
if(!(isWatery(cwt.at) && c2->monst == moWaterElemental) && checkNeedMove(checkonly, true))
|
||||||
return false;
|
return false;
|
||||||
@ -8442,7 +8455,7 @@ EX bool movepcto(int d, int subdir IS(1), bool checkonly IS(false)) {
|
|||||||
// salamanders are stunned for longer time when pushed into a wall
|
// salamanders are stunned for longer time when pushed into a wall
|
||||||
if(c2->monst == moSalamander && (pushto == c2 || !pushto)) c2->stuntime = 10;
|
if(c2->monst == moSalamander && (pushto == c2 || !pushto)) c2->stuntime = 10;
|
||||||
if(!c2->monst) produceGhost(c2, m, moPlayer);
|
if(!c2->monst) produceGhost(c2, m, moPlayer);
|
||||||
if(pushto && pushto != c2) pushMonster(pushto, c2, pushdir);
|
if(mip.proper()) pushMonster(mip);
|
||||||
animateAttack(mi, LAYER_SMALL);
|
animateAttack(mi, LAYER_SMALL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -444,6 +444,7 @@ inline cellwalker operator+ (heptspin hs, cth_t) { return cellwalker(hs.at->c7,
|
|||||||
|
|
||||||
constexpr int STRONGWIND = 99;
|
constexpr int STRONGWIND = 99;
|
||||||
constexpr int FALL = 98;
|
constexpr int FALL = 98;
|
||||||
|
constexpr int NO_SPACE = 97;
|
||||||
|
|
||||||
namespace whirlwind { cell *jumpDestination(cell*); }
|
namespace whirlwind { cell *jumpDestination(cell*); }
|
||||||
|
|
||||||
@ -451,10 +452,11 @@ struct movei {
|
|||||||
cell *s;
|
cell *s;
|
||||||
cell *t;
|
cell *t;
|
||||||
int d;
|
int d;
|
||||||
|
bool op() { return s != t; }
|
||||||
bool proper() const { return d >= 0 && d < s->type && s->move(d) == t; }
|
bool proper() const { return d >= 0 && d < s->type && s->move(d) == t; }
|
||||||
movei(cell *_s, int _d) : s(_s), d(_d) {
|
movei(cell *_s, int _d) : s(_s), d(_d) {
|
||||||
if(d == STRONGWIND) t = whirlwind::jumpDestination(s);
|
if(d == STRONGWIND) t = whirlwind::jumpDestination(s);
|
||||||
else if(d == FALL) t = s;
|
else if(d == FALL || d == NO_SPACE) t = s;
|
||||||
else t = s->move(d);
|
else t = s->move(d);
|
||||||
}
|
}
|
||||||
movei(cell *_s, cell *_t, int _d) : s(_s), t(_t), d(_d) {}
|
movei(cell *_s, cell *_t, int _d) : s(_s), t(_t), d(_d) {}
|
||||||
|
29
orbs.cpp
29
orbs.cpp
@ -956,24 +956,26 @@ void placeIllusion(cell *c) {
|
|||||||
checkmoveO();
|
checkmoveO();
|
||||||
}
|
}
|
||||||
|
|
||||||
void blowoff(cell *cf, cell *ct, int direction_hint) {
|
void blowoff(const movei& mi) {
|
||||||
|
auto& cf = mi.s;
|
||||||
|
auto& ct = mi.t;
|
||||||
playSound(ct, "orb-ranged");
|
playSound(ct, "orb-ranged");
|
||||||
if(cf->monst)
|
if(cf->monst)
|
||||||
addMessage(XLAT("You blow %the1 away!", cf->monst));
|
addMessage(XLAT("You blow %the1 away!", cf->monst));
|
||||||
if(cf->wall == waThumperOff) activateActiv(cf, false);
|
if(cf->wall == waThumperOff) activateActiv(cf, false);
|
||||||
if(isPushable(cf->wall) || cf->wall == waBigStatue)
|
if(isPushable(cf->wall) || cf->wall == waBigStatue)
|
||||||
pushThumper(cf, ct);
|
pushThumper(mi);
|
||||||
else if(isBoat(cf) && !cf->monst) {
|
else if(isBoat(cf) && !cf->monst) {
|
||||||
bool was_stranded = cf->wall == waStrandedBoat;
|
bool was_stranded = cf->wall == waStrandedBoat;
|
||||||
bool willbe_stranded = ct->wall == waNone;
|
bool willbe_stranded = ct->wall == waNone;
|
||||||
if(was_stranded) cf->wall = waBoat;
|
if(was_stranded) cf->wall = waBoat;
|
||||||
if(willbe_stranded) ct->wall = waSea;
|
if(willbe_stranded) ct->wall = waSea;
|
||||||
moveBoat(ct, cf, direction_hint);
|
moveBoat(mi);
|
||||||
if(was_stranded) cf->wall = waNone;
|
if(was_stranded) cf->wall = waNone;
|
||||||
if(willbe_stranded) ct->wall = waStrandedBoat;
|
if(willbe_stranded) ct->wall = waStrandedBoat;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
pushMonster(ct, cf, direction_hint);
|
pushMonster(mi);
|
||||||
if(cf->item == itBabyTortoise) {
|
if(cf->item == itBabyTortoise) {
|
||||||
if(ct->item) ct->item = itNone;
|
if(ct->item) ct->item = itNone;
|
||||||
moveItem(cf, ct, true);
|
moveItem(cf, ct, true);
|
||||||
@ -1006,15 +1008,15 @@ bool monstersnearO(orbAction a, cell *c, cell *nocount, eMonster who, cell *push
|
|||||||
EX bool isCheck(orbAction a) { return a == roCheck || a == roMultiCheck; }
|
EX bool isCheck(orbAction a) { return a == roCheck || a == roMultiCheck; }
|
||||||
EX bool isWeakCheck(orbAction a) { return a == roCheck || a == roMultiCheck || a == roMouse; }
|
EX bool isWeakCheck(orbAction a) { return a == roCheck || a == roMultiCheck || a == roMouse; }
|
||||||
|
|
||||||
EX cell *blowoff_destination(cell *c, int& di) {
|
EX movei blowoff_destination(cell *c, int& di) {
|
||||||
int d = 0;
|
int d = 0;
|
||||||
for(; d<c->type; d++) if(c->move(d) && c->move(d)->cpdist < c->cpdist) break;
|
for(; d<c->type; d++) if(c->move(d) && c->move(d)->cpdist < c->cpdist) break;
|
||||||
if(d<c->type) for(int e=d; e<d+c->type; e++) {
|
if(d<c->type) for(int e=d; e<d+c->type; e++) {
|
||||||
int di = e % c->type;
|
int di = e % c->type;
|
||||||
cell *c2 = c->move(di);
|
cell *c2 = c->move(di);
|
||||||
if(c2 && c2->cpdist > c->cpdist && passable(c2, c, P_BLOW)) return c2;
|
if(c2 && c2->cpdist > c->cpdist && passable(c2, c, P_BLOW)) return movei(c, c2, di);
|
||||||
}
|
}
|
||||||
return NULL;
|
return movei(c, c, NO_SPACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
EX eItem targetRangedOrb(cell *c, orbAction a) {
|
EX eItem targetRangedOrb(cell *c, orbAction a) {
|
||||||
@ -1079,14 +1081,15 @@ EX eItem targetRangedOrb(cell *c, orbAction a) {
|
|||||||
bool nowhereToBlow = false;
|
bool nowhereToBlow = false;
|
||||||
if(items[itOrbAir] && (isBlowableMonster(c->monst) || isPushable(c->wall) || c->wall == waBigStatue || isBoat(c))) {
|
if(items[itOrbAir] && (isBlowableMonster(c->monst) || isPushable(c->wall) || c->wall == waBigStatue || isBoat(c))) {
|
||||||
int di = NODIR;
|
int di = NODIR;
|
||||||
cell *c2 = blowoff_destination(c, di);
|
movei mi = blowoff_destination(c, di);
|
||||||
if(c2 && isBoat(c) && !isWatery(c2) && c2->wall != waNone) c2 = NULL;
|
auto& c2 = mi.t;
|
||||||
if(c2 && c->wall == waBigStatue && !canPushStatueOn(c2)) c2 = NULL;
|
if(!mi.op()) nowhereToBlow = true;
|
||||||
if(c2) {
|
else if(isBoat(c) && !isWatery(c2) && c2->wall != waNone) nowhereToBlow = true;
|
||||||
if(!isCheck(a)) blowoff(c, c2, di);
|
else if(c->wall == waBigStatue && !canPushStatueOn(c2)) nowhereToBlow = true;
|
||||||
|
else {
|
||||||
|
if(!isCheck(a)) blowoff(mi);
|
||||||
return itOrbAir;
|
return itOrbAir;
|
||||||
}
|
}
|
||||||
else nowhereToBlow = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// nature
|
// nature
|
||||||
|
16
shmup.cpp
16
shmup.cpp
@ -1062,10 +1062,9 @@ void movePlayer(monster *m, int delta) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(isPushable(c2->wall) && !nonAdjacent(c2, m->base)) {
|
else if(isPushable(c2->wall) && !nonAdjacent(c2, m->base)) {
|
||||||
int sd = neighborId(c2, m->base);
|
int sd = neighborId(m->base, c2);
|
||||||
int subdir = 1;
|
int subdir = 1;
|
||||||
double bestd = 9999;
|
double bestd = 9999;
|
||||||
pushmonsters();
|
|
||||||
for(int di=-1; di<2; di+=2) {
|
for(int di=-1; di<2; di+=2) {
|
||||||
cell *c = c2->modmove(sd+di);
|
cell *c = c2->modmove(sd+di);
|
||||||
if(!c) continue;
|
if(!c) continue;
|
||||||
@ -1073,16 +1072,11 @@ void movePlayer(monster *m, int delta) {
|
|||||||
double d = sqdist(gmatrix[c] * C0, m->pat * C0);
|
double d = sqdist(gmatrix[c] * C0, m->pat * C0);
|
||||||
if(d<bestd) bestd=d, subdir = di;
|
if(d<bestd) bestd=d, subdir = di;
|
||||||
}
|
}
|
||||||
|
pushmonsters();
|
||||||
|
auto mip = determinePush(cellwalker(c2, sd), subdir, [m, c2] (cell *c) { return canPushThumperOn(c, c2, m->base); });
|
||||||
visibleFor(300);
|
visibleFor(300);
|
||||||
cellwalker push(c2, neighborId(c2, m->base));
|
if(!mip.proper()) go = false;
|
||||||
push = push + 3 * (-subdir) + wstep;
|
else pushThumper(mip);
|
||||||
if(!canPushThumperOn(push.at, c2, m->base) && c2->type == 7) {
|
|
||||||
push = push + wstep - subdir + wstep;
|
|
||||||
}
|
|
||||||
if(!canPushThumperOn(push.at, c2, m->base)) {
|
|
||||||
go = false;
|
|
||||||
}
|
|
||||||
else pushThumper(c2, push.at);
|
|
||||||
popmonsters();
|
popmonsters();
|
||||||
}
|
}
|
||||||
else if(c2->wall == waRose && !nonAdjacent(m->base, c2)) {
|
else if(c2->wall == waRose && !nonAdjacent(m->base, c2)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user