mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-12-25 09:30:35 +00:00
Merge branch 'master' into makefile-fixes
This commit is contained in:
commit
b6f47dd907
@ -6,12 +6,12 @@ namespace hr {
|
||||
double randd() { return (rand() + .5) / (RAND_MAX + 1.); }
|
||||
|
||||
double cellgfxdist(cell *c, int i) {
|
||||
if(gp::on) return hdist0(tC0(shmup::calc_relative_matrix(c->mov[i], c)));
|
||||
if(gp::on) return hdist0(tC0(shmup::calc_relative_matrix(c->mov[i], c, i)));
|
||||
return nonbitrunc ? tessf * gp::scale : (c->type == 6 && (i&1)) ? hexhexdist : crossf;
|
||||
}
|
||||
|
||||
transmatrix cellrelmatrix(cell *c, int i) {
|
||||
if(gp::on) return shmup::calc_relative_matrix(c->mov[i], c);
|
||||
if(gp::on) return shmup::calc_relative_matrix(c->mov[i], c, i);
|
||||
double d = cellgfxdist(c, i);
|
||||
return ddspin(c, i) * xpush(d) * iddspin(c->mov[i], c->spin(i), euclid ? 0 : S42);
|
||||
}
|
||||
|
9
cell.cpp
9
cell.cpp
@ -1362,16 +1362,17 @@ map<pair<cell*, cell*>, int> saved_distances;
|
||||
int celldistance(cell *c1, cell *c2) {
|
||||
int d = 0;
|
||||
|
||||
if(euclid) {
|
||||
if(torus)
|
||||
if(euclid6) {
|
||||
if(!torus)
|
||||
return eudist(decodeId(c1->master) - decodeId(c2->master));
|
||||
else if(torus && torusconfig::torus_mode == 0)
|
||||
return torusmap()->dists[torusconfig::vec_to_id(decodeId(c1->master)-decodeId(c2->master))];
|
||||
return eudist(decodeId(c1->master) - decodeId(c2->master));
|
||||
}
|
||||
|
||||
if(quotient == 2 && !gp::on)
|
||||
return currfp.getdist(fieldpattern::fieldval(c1), fieldpattern::fieldval(c2));
|
||||
|
||||
if(sphere || quotient) {
|
||||
if(sphere || quotient || torus) {
|
||||
|
||||
if(saved_distances.count(make_pair(c1,c2)))
|
||||
return saved_distances[make_pair(c1,c2)];
|
||||
|
@ -2489,3 +2489,8 @@ non-game:
|
||||
- uniformized the 'back' and 'help' options in menu (consistent hotkeys, consistent placement, added them where they were missing)
|
||||
- pushing a thumper through a stranded boat is no longer allowed
|
||||
- fixed a bug with pushing Thumpers through tentacles
|
||||
|
||||
2018.06.14 16:39
|
||||
- fixed viewing the "past challenges"
|
||||
- fixed a bug which sometimes caused current scores to be copied to past challenge leaderboards.
|
||||
|
||||
|
16
complex.cpp
16
complex.cpp
@ -136,7 +136,7 @@ namespace whirlwind {
|
||||
for(int i=0; i<z-1; i++) {
|
||||
moveItem(whirlline[i], whirlline[i+1], true);
|
||||
if(whirlline[i]->item)
|
||||
animateMovement(whirlline[i+1], whirlline[i], LAYER_BOAT);
|
||||
animateMovement(whirlline[i+1], whirlline[i], LAYER_BOAT, NOHINT);
|
||||
}
|
||||
for(int i=0; i<z; i++)
|
||||
pickupMovedItems(whirlline[i]);
|
||||
@ -995,7 +995,7 @@ namespace whirlpool {
|
||||
if(wfrom && wto && wfrom->wall == waBoat && wto->wall == waSea && !wto->monst) {
|
||||
wfrom->wall = waSea; wto->wall = waBoat;
|
||||
wto->mondir = neighborId(wto, wfrom);
|
||||
animateMovement(wfrom, wto, LAYER_BOAT);
|
||||
animateMovement(wfrom, wto, LAYER_BOAT, NOHINT);
|
||||
}
|
||||
|
||||
if(wfrom && wto && wfrom->item && !wto->item && wfrom->wall != waBoat) {
|
||||
@ -1206,7 +1206,7 @@ namespace mirror {
|
||||
continue;
|
||||
}
|
||||
c->monst = moMimic;
|
||||
moveMonster(c2, c);
|
||||
moveMonster(c2, c, m.second.spin);
|
||||
c2->monst = moNone;
|
||||
empathyMove(c, c2, neighborId(c2, c));
|
||||
m.second = cw2;
|
||||
@ -1639,7 +1639,7 @@ namespace hive {
|
||||
// c->monst = moDeadBug, deadbug.push_back(c);
|
||||
}
|
||||
else {
|
||||
moveMonster(c2, c);
|
||||
moveMonster(c2, c, d);
|
||||
// pheromones!
|
||||
if(c->land == laHive && c->landparam < 90) c->landparam += 5;
|
||||
if(c2->land == laHive && c2->landparam < 90) c2->landparam += 5;
|
||||
@ -2297,7 +2297,7 @@ namespace dragon {
|
||||
mountmove(c, c->mondir, true, c2);
|
||||
c->monst = c2->monst;
|
||||
c->hitpoints = c2->hitpoints;
|
||||
animateMovement(c2, c, LAYER_BIG);
|
||||
animateMovement(c2, c, LAYER_BIG, c->spin(c->mondir));
|
||||
c->stuntime = 2;
|
||||
if(c2->mondir == NODIR) { c->mondir = NODIR; c2->monst = moNone; return; }
|
||||
c = c2;
|
||||
@ -2417,7 +2417,7 @@ namespace dragon {
|
||||
cmt->monst = cft->monst;
|
||||
cft->monst = moNone;
|
||||
mountmove(cmt, cmt->mondir, true, cft);
|
||||
animateMovement(cft, cmt, LAYER_BIG);
|
||||
animateMovement(cft, cmt, LAYER_BIG, allcells[i]->mondir);
|
||||
}
|
||||
while(c->mondir != NODIR) {
|
||||
c = c->mov[c->mondir];
|
||||
@ -2656,7 +2656,7 @@ namespace kraken {
|
||||
noconflict = false; */
|
||||
/* if(noconflict) */ {
|
||||
// found = true;
|
||||
indAnimateMovement(acells[i].first, acells[i].second, LAYER_BIG);
|
||||
indAnimateMovement(acells[i].first, acells[i].second, LAYER_BIG, NOHINT);
|
||||
acells[i] = acells[size(acells)-1];
|
||||
acells.resize(size(acells)-1);
|
||||
i--;
|
||||
@ -2872,7 +2872,7 @@ namespace prairie {
|
||||
}
|
||||
|
||||
if(!cn->monst && !isPlayerOn(cn) && passable_for(cp->monst, cn, cp, P_DEADLY))
|
||||
moveMonster(cn, cp);
|
||||
moveMonster(cn, cp, NODIR);
|
||||
else {
|
||||
playSound(NULL, "hit-axe"+pick123());
|
||||
beastcrash(cn, cp);
|
||||
|
@ -337,10 +337,10 @@ namespace conformal {
|
||||
|
||||
// virtualRebase(v[j], false);
|
||||
|
||||
hyperpoint prev = shmup::calc_relative_matrix(v[j-1]->base, v[j]->base) *
|
||||
hyperpoint prev = shmup::calc_relative_matrix(v[j-1]->base, v[j]->base, NOHINT) *
|
||||
v[j-1]->at * C0;
|
||||
|
||||
hyperpoint next = shmup::calc_relative_matrix(v[j+1]->base, v[j]->base) *
|
||||
hyperpoint next = shmup::calc_relative_matrix(v[j+1]->base, v[j]->base, NOHINT) *
|
||||
v[j+1]->at * C0;
|
||||
|
||||
hyperpoint hmid = mid(prev, next);
|
||||
@ -352,7 +352,7 @@ namespace conformal {
|
||||
}
|
||||
}
|
||||
|
||||
hyperpoint next0 = shmup::calc_relative_matrix(v[1]->base, v[0]->base) * v[1]->at * C0;
|
||||
hyperpoint next0 = shmup::calc_relative_matrix(v[1]->base, v[0]->base, NOHINT) * v[1]->at * C0;
|
||||
v[0]->at = v[0]->at * rspintox(inverse(v[0]->at) * next0);
|
||||
|
||||
llv = ticks;
|
||||
@ -380,7 +380,7 @@ namespace conformal {
|
||||
|
||||
hyperpoint now = v[ph]->at * C0;
|
||||
|
||||
hyperpoint next = shmup::calc_relative_matrix(v[ph+1]->base, v[ph]->base) *
|
||||
hyperpoint next = shmup::calc_relative_matrix(v[ph+1]->base, v[ph]->base, NOHINT) *
|
||||
v[ph+1]->at * C0;
|
||||
|
||||
View = spin(M_PI/180 * rotation) * xpush(-(phase-ph) * hdist(now, next)) * View;
|
||||
@ -411,7 +411,7 @@ namespace conformal {
|
||||
for(int j=0; j<siz-1; j++) {
|
||||
hyperpoint next =
|
||||
inverse(v[j]->at) *
|
||||
shmup::calc_relative_matrix(v[j+1]->base, v[j]->base) *
|
||||
shmup::calc_relative_matrix(v[j+1]->base, v[j]->base, NOHINT) *
|
||||
v[j+1]->at * C0;
|
||||
|
||||
hyperpoint nextscr;
|
||||
|
@ -110,7 +110,7 @@ void calcMousedest() {
|
||||
ld dists[MAX_EDGE];
|
||||
|
||||
for(int i=0; i<cwt.c->type; i++)
|
||||
dists[i] = intval(mouseh, tC0(shmup::ggmatrix(cwt.c->mov[i])));
|
||||
dists[i] = intval(mouseh, tC0(confusingGeometry() ? shmup::ggmatrix(cwt.c) * shmup::calc_relative_matrix(cwt.c->mov[i], cwt.c, i) : shmup::ggmatrix(cwt.c->mov[i])));
|
||||
|
||||
/* printf("curcell = %Lf\n", mousedist);
|
||||
for(int i=0; i<cwt.c->type; i++)
|
||||
|
@ -303,7 +303,7 @@ namespace gp {
|
||||
hyperpoint nearcorner(cell *c, local_info& li, int i) {
|
||||
cellwalker cw(c, i);
|
||||
cw += wstep;
|
||||
transmatrix cwm = shmup::calc_relative_matrix(cw.c, c);
|
||||
transmatrix cwm = shmup::calc_relative_matrix(cw.c, c, i);
|
||||
if(elliptic && cwm[2][2] < 0) cwm = centralsym * cwm;
|
||||
return cwm * C0;
|
||||
}
|
||||
@ -311,7 +311,7 @@ namespace gp {
|
||||
hyperpoint hypercorner(cell *c, local_info& li, int i) {
|
||||
cellwalker cw(c, i);
|
||||
cw += wstep;
|
||||
transmatrix cwm = shmup::calc_relative_matrix(cw.c, c);
|
||||
transmatrix cwm = shmup::calc_relative_matrix(cw.c, c, i);
|
||||
if(elliptic && cwm[2][2] < 0) cwm = centralsym * cwm;
|
||||
auto li1 = get_local_info(cw.c);
|
||||
return cwm * get_corner_position(li1, (cw+2).spin);
|
||||
@ -358,8 +358,9 @@ namespace gp {
|
||||
|
||||
cellwalker cw(c0, c);
|
||||
cw += d+sidir+siid+1;
|
||||
int hint = cw.spin;
|
||||
cw += wstep;
|
||||
transmatrix cwm = shmup::calc_relative_matrix(cw.c, c0);
|
||||
transmatrix cwm = shmup::calc_relative_matrix(cw.c, c0, hint);
|
||||
hyperpoint nfar = cwm*C0;
|
||||
auto li1 = get_local_info(cw.c);
|
||||
hyperpoint nlfar = cwm * get_corner_position(li1, (cw+2).spin);
|
||||
|
119
game.cpp
119
game.cpp
@ -734,18 +734,18 @@ bool canPushStatueOn(cell *c) {
|
||||
!isWorm(c->monst) && !isReptile(c->wall) && !peace::on;
|
||||
}
|
||||
|
||||
void moveBoat(cell *to, cell *from) {
|
||||
void moveBoat(cell *to, cell *from, int direction_hint) {
|
||||
eWall x = to->wall; to->wall = from->wall; from->wall = x;
|
||||
to->mondir = neighborId(to, from);
|
||||
moveItem(from, to, false);
|
||||
animateMovement(from, to, LAYER_BOAT);
|
||||
animateMovement(from, to, LAYER_BOAT, direction_hint);
|
||||
}
|
||||
|
||||
void moveBoatIfUsingOne(cell *to, cell *from) {
|
||||
if(from->wall == waBoat && isWatery(to)) moveBoat(to, from);
|
||||
void moveBoatIfUsingOne(cell *to, cell *from, int direction_hint) {
|
||||
if(from->wall == waBoat && isWatery(to)) moveBoat(to, from, direction_hint);
|
||||
else if(from->wall == waBoat && boatGoesThrough(to) && markEmpathy(itOrbWater)) {
|
||||
placeWater(to, from);
|
||||
moveBoat(to, from);
|
||||
moveBoat(to, from, direction_hint);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1881,7 +1881,7 @@ bool attackJustStuns(cell *c2, flagtype f) {
|
||||
return isStunnable(c2->monst) && c2->hitpoints > 1;
|
||||
}
|
||||
|
||||
void moveEffect(cell *ct, cell *cf, eMonster m);
|
||||
void moveEffect(cell *ct, cell *cf, eMonster m, int direction_hint);
|
||||
|
||||
void flameHalfvine(cell *c, int val) {
|
||||
if(itemBurns(c->item)) {
|
||||
@ -2087,7 +2087,7 @@ void killMonster(cell *c, eMonster who, flagtype deathflags) {
|
||||
}
|
||||
if(m == moVineBeast)
|
||||
petrify(c, waVinePlant, m), pcount = 0;
|
||||
if(isBird(m)) moveEffect(c, c, moDeadBird);
|
||||
if(isBird(m)) moveEffect(c, c, moDeadBird, -1);
|
||||
if(m == moBomberbird || m == moTameBomberbird) {
|
||||
pcount = 0;
|
||||
playSound(c, "die-bomberbird");
|
||||
@ -2446,8 +2446,8 @@ bool attackMonster(cell *c, flagtype flags, eMonster killer) {
|
||||
return ntk > tk;
|
||||
}
|
||||
|
||||
void pushMonster(cell *ct, cell *cf) {
|
||||
moveMonster(ct, cf);
|
||||
void pushMonster(cell *ct, cell *cf, int direction_hint) {
|
||||
moveMonster(ct, cf, direction_hint);
|
||||
}
|
||||
|
||||
bool destroyHalfvine(cell *c, eWall newwall, int tval) {
|
||||
@ -3242,7 +3242,7 @@ void activateArrowTrap(cell *c) {
|
||||
// this is called from moveMonster, or separately from moveIvy/moveWorm,
|
||||
// or when a dead bird falls (then m == moDeadBird)
|
||||
|
||||
void moveEffect(cell *ct, cell *cf, eMonster m) {
|
||||
void moveEffect(cell *ct, cell *cf, eMonster m, int direction_hint) {
|
||||
|
||||
if(cf) destroyWeakBranch(cf, ct, m);
|
||||
|
||||
@ -3273,7 +3273,7 @@ void moveEffect(cell *ct, cell *cf, eMonster m) {
|
||||
if(cf && ct->item == itBabyTortoise && !cf->item) {
|
||||
cf->item = itBabyTortoise;
|
||||
ct->item = itNone;
|
||||
animateMovement(ct, cf, LAYER_BOAT);
|
||||
animateMovement(ct, cf, LAYER_BOAT, direction_hint);
|
||||
tortoise::babymap[cf] = tortoise::babymap[ct];
|
||||
tortoise::babymap.erase(ct);
|
||||
}
|
||||
@ -3407,20 +3407,20 @@ void makeTrollFootprints(cell *c) {
|
||||
c->landparam = turncount + 100;
|
||||
}
|
||||
|
||||
void moveMonster(cell *ct, cell *cf) {
|
||||
void moveMonster(cell *ct, cell *cf, int direction_hint) {
|
||||
eMonster m = cf->monst;
|
||||
bool fri = isFriendly(cf);
|
||||
if(isDragon(m)) {
|
||||
printf("called for Dragon\n");
|
||||
return;
|
||||
}
|
||||
if(m != moMimic) animateMovement(cf, ct, LAYER_SMALL);
|
||||
if(m != moMimic) animateMovement(cf, ct, LAYER_SMALL, direction_hint);
|
||||
// the following line is necessary because otherwise plates disappear only inside the sight range
|
||||
if(cellUnstable(cf) && !ignoresPlates(m)) {
|
||||
fallingFloorAnimation(cf);
|
||||
cf->wall = waChasm;
|
||||
}
|
||||
moveEffect(ct, cf, m);
|
||||
moveEffect(ct, cf, m, direction_hint);
|
||||
if(ct->wall == waCamelotMoat &&
|
||||
(m == moShark || m == moCShark || m == moGreaterShark))
|
||||
achievement_gain("MOATSHARK");
|
||||
@ -3460,10 +3460,10 @@ void moveMonster(cell *ct, cell *cf) {
|
||||
if(ct->wall == waBigStatue) {
|
||||
ct->wall = cf->wall;
|
||||
cf->wall = waBigStatue;
|
||||
animateMovement(ct, cf, LAYER_BOAT);
|
||||
animateMovement(ct, cf, LAYER_BOAT, revhint(cf, direction_hint));
|
||||
}
|
||||
|
||||
moveBoatIfUsingOne(ct, cf);
|
||||
moveBoatIfUsingOne(ct, cf, revhint(cf, direction_hint));
|
||||
}
|
||||
|
||||
if(isTroll(m)) { makeTrollFootprints(ct); makeTrollFootprints(cf); }
|
||||
@ -3894,7 +3894,7 @@ int pickDownDirection(cell *c, flagtype mf) {
|
||||
}
|
||||
|
||||
template<class T>
|
||||
cell *determinePush(cellwalker who, cell *c2, int subdir, const T& valid) {
|
||||
cell *determinePush(cellwalker who, cell *c2, int subdir, const T& valid, int& pushdir) {
|
||||
if(subdir != 1 && subdir != -1) {
|
||||
subdir = 1;
|
||||
static bool first = true;
|
||||
@ -3910,6 +3910,7 @@ cell *determinePush(cellwalker who, cell *c2, int subdir, const T& valid) {
|
||||
if(valid(push.c)) return push.c;
|
||||
if(c2->type&1) {
|
||||
push = push + wstep - subdir + wstep;
|
||||
pushdir = (push+wstep).spin;
|
||||
if(valid(push.c)) return push.c;
|
||||
}
|
||||
if(gravityLevel(push.c) < gravityLevel(c2)) {
|
||||
@ -3920,6 +3921,7 @@ cell *determinePush(cellwalker who, cell *c2, int subdir, const T& valid) {
|
||||
if(gravityLevel(push.c) < gravityLevel(c2)) {
|
||||
push = push + wstep + 1 + wstep;
|
||||
}
|
||||
pushdir = (push+wstep).spin;
|
||||
if(valid(push.c)) return push.c;
|
||||
}
|
||||
return c2;
|
||||
@ -3939,9 +3941,10 @@ void beastAttack(cell *c, bool player) {
|
||||
if(c2->monst && c2->stuntime) {
|
||||
cellwalker bull (c, d);
|
||||
int subdir = determinizeBullPush(bull);
|
||||
cell *c3 = determinePush(bull, c2, subdir, [c2] (cell *c) { return passable(c, c2, P_BLOW); });
|
||||
int pushdir;
|
||||
cell *c3 = determinePush(bull, c2, subdir, [c2] (cell *c) { return passable(c, c2, P_BLOW); }, pushdir);
|
||||
if(c3 && c3 != c2)
|
||||
pushMonster(c3, c2);
|
||||
pushMonster(c3, c2, pushdir);
|
||||
}
|
||||
}
|
||||
if(c2->wall == waThumperOff) {
|
||||
@ -3951,7 +3954,8 @@ void beastAttack(cell *c, bool player) {
|
||||
if(c2->wall == waThumperOn) {
|
||||
cellwalker bull (c, d);
|
||||
int subdir = determinizeBullPush(bull);
|
||||
cell *c3 = determinePush(bull, c2, subdir, [c2] (cell *c) { return canPushThumperOn(c, c2, c); });
|
||||
int pushdir;
|
||||
cell *c3 = determinePush(bull, c2, subdir, [c2] (cell *c) { return canPushThumperOn(c, c2, c); }, pushdir);
|
||||
if(c3 && c3 != c2)
|
||||
pushThumper(c2, c3);
|
||||
}
|
||||
@ -4002,13 +4006,13 @@ cell *moveNormal(cell *c, flagtype mf) {
|
||||
}
|
||||
else if(m2) {
|
||||
attackMonster(c2, AF_NORMAL | AF_MSG, m);
|
||||
animateAttack(c, c2, LAYER_SMALL);
|
||||
animateAttack(c, c2, LAYER_SMALL, d);
|
||||
if(m == moFlailer && m2 == moIllusion)
|
||||
attackMonster(c, 0, m2);
|
||||
return c2;
|
||||
}
|
||||
|
||||
moveMonster(c2, c);
|
||||
moveMonster(c2, c, d);
|
||||
if(m == moRagingBull) beastAttack(c2, false);
|
||||
return c2;
|
||||
}
|
||||
@ -4036,7 +4040,7 @@ cell *moveNormal(cell *c, flagtype mf) {
|
||||
if(!attacking) for(int i=0; i<nc; i++) {
|
||||
cell *c2 = c->mov[posdir[i]];
|
||||
if(!c->monst) c->monst = m;
|
||||
moveMonster(c2, c);
|
||||
moveMonster(c2, c, posdir[i]);
|
||||
if(m == moRagingBull) beastAttack(c2, false);
|
||||
}
|
||||
return c->mov[d];
|
||||
@ -4177,7 +4181,7 @@ void mountmove(cell *c, int spin, bool fp, int id) {
|
||||
void mountmove(cell *c, int spin, bool fp, cell *ppos) {
|
||||
for(int i=0; i<numplayers(); i++) {
|
||||
if(playerpos(i) == ppos) {
|
||||
animateMovement(ppos, c, LAYER_SMALL);
|
||||
animateMovement(ppos, c, LAYER_SMALL, revhint(c, spin));
|
||||
mountmove(c, spin, fp, i);
|
||||
}
|
||||
if(lastmountpos[i] == ppos && ppos != NULL) {
|
||||
@ -4213,7 +4217,7 @@ void moveWorm(cell *c) {
|
||||
cell *cft = allcells[i];
|
||||
if(cft->monst != moTentacleGhost && cmt->monst != moTentacleGhost)
|
||||
mountmove(cmt, cft->spn(cft->mondir), false, cft);
|
||||
animateMovement(cft, cmt, LAYER_BIG);
|
||||
animateMovement(cft, cmt, LAYER_BIG, cft->mondir);
|
||||
}
|
||||
c->monst = moNone;
|
||||
if(c->mondir != NODIR) c->mov[c->mondir]->monst = moTentacleEscaping;
|
||||
@ -4283,9 +4287,9 @@ void moveWorm(cell *c) {
|
||||
|
||||
for(int j=0; j<c->type; j++) if(c->mov[j] == goal) {
|
||||
goal->monst = eMonster(moWormwait + id);
|
||||
moveEffect(goal, NULL, eMonster(moWormwait + id));
|
||||
moveEffect(goal, NULL, eMonster(moWormwait + id), NOHINT);
|
||||
|
||||
animateMovement(c, goal, LAYER_BIG);
|
||||
animateMovement(c, goal, LAYER_BIG, dir);
|
||||
c->monst = eMonster(moWormtail + id);
|
||||
goal->mondir = c->spn(j);
|
||||
|
||||
@ -4301,7 +4305,7 @@ void moveWorm(cell *c) {
|
||||
c3 = c2, c2 = c3->mov[c2->mondir];
|
||||
if(c3->monst != moTentacleGhost && c2->monst != moTentacleGhost)
|
||||
mountmove(c3, c3->mondir, true, c2);
|
||||
animateMovement(c2, c3, LAYER_BIG);
|
||||
animateMovement(c2, c3, LAYER_BIG, c2->spin(c2->mondir));
|
||||
}
|
||||
}
|
||||
|
||||
@ -4314,7 +4318,7 @@ void moveWorm(cell *c) {
|
||||
}
|
||||
c3 = c2, c2 = c3->mov[c2->mondir];
|
||||
mountmove(c3, c3->mondir, true, c2);
|
||||
animateMovement(c2, c3, LAYER_BIG);
|
||||
animateMovement(c2, c3, LAYER_BIG, revhint(c2, c2->mondir));
|
||||
}
|
||||
}
|
||||
|
||||
@ -4415,9 +4419,9 @@ void moveivy() {
|
||||
}
|
||||
|
||||
if(mto && mto->cpdist) {
|
||||
animateMovement(mto->mov[sp], mto, LAYER_BIG);
|
||||
animateMovement(mto->mov[sp], mto, LAYER_BIG, mto->spin(sp));
|
||||
mto->monst = moIvyWait, mto->mondir = sp;
|
||||
moveEffect(mto, NULL, moIvyWait);
|
||||
moveEffect(mto, NULL, moIvyWait, NOHINT);
|
||||
// if this is the only branch, we want to move the head immediately to mto instead
|
||||
if(mto->mov[mto->mondir]->monst == moIvyHead) {
|
||||
mto->monst = moIvyHead; co->monst = moIvyBranch;
|
||||
@ -4527,7 +4531,7 @@ void groupmove2(cell *c, cell *from, int d, eMonster movtype, flagtype mf) {
|
||||
if(!(mf & MF_NOATTACKS)) for(int j=0; j<c->type; j++)
|
||||
if(c->mov[j] && canAttack(c, c->monst, c->mov[j], c->mov[j]->monst, af)) {
|
||||
attackMonster(c->mov[j], AF_NORMAL | AF_GETPLAYER | AF_MSG, c->monst);
|
||||
animateAttack(c, c->mov[j], LAYER_SMALL);
|
||||
animateAttack(c, c->mov[j], LAYER_SMALL, j);
|
||||
c->aitmp = sval;
|
||||
// XLATC eagle
|
||||
return;
|
||||
@ -4540,7 +4544,7 @@ void groupmove2(cell *c, cell *from, int d, eMonster movtype, flagtype mf) {
|
||||
return;
|
||||
}
|
||||
|
||||
moveMonster(from, c);
|
||||
moveMonster(from, c, revhint(from, d));
|
||||
from->aitmp = sval;
|
||||
}
|
||||
c->aitmp = sval;
|
||||
@ -4612,12 +4616,12 @@ vector<cell*> hexdfs;
|
||||
// note: move from 'c' to 'from'!
|
||||
void moveHexSnake(cell *from, cell *c, int d, bool mounted) {
|
||||
if(from->wall == waBoat) from->wall = waSea;
|
||||
moveEffect(from, c, c->monst);
|
||||
from->monst = c->monst; from->mondir = d;
|
||||
moveEffect(from, c, c->monst, revhint(from, d));
|
||||
from->monst = c->monst; from->mondir = d; from->hitpoints = c->hitpoints;
|
||||
c->monst = moHexSnakeTail;
|
||||
preventbarriers(from);
|
||||
|
||||
animateMovement(c, from, LAYER_BIG);
|
||||
animateMovement(c, from, LAYER_BIG, revhint(from, d));
|
||||
mountmove(from, from->mondir, true, c);
|
||||
|
||||
cell *c2 = c, *c3=c2;
|
||||
@ -4625,7 +4629,7 @@ void moveHexSnake(cell *from, cell *c, int d, bool mounted) {
|
||||
if(a == ROCKSNAKELENGTH) { c2->monst = moNone, c3->mondir = NODIR; break; }
|
||||
if(c2->mondir == NODIR) break;
|
||||
mountmove(c2, c2->mondir, true, c2->mov[c2->mondir]);
|
||||
animateMovement(c2->mov[c2->mondir], c2, LAYER_BIG);
|
||||
animateMovement(c2->mov[c2->mondir], c2, LAYER_BIG, revhint(c2, c2->mondir));
|
||||
c3 = c2, c2 = c3->mov[c2->mondir];
|
||||
}
|
||||
else break;
|
||||
@ -4787,7 +4791,7 @@ void movemutant() {
|
||||
c2->monst = moMutant;
|
||||
c2->mondir = c->spn(j);
|
||||
c2->stuntime = mutantphase;
|
||||
animateMovement(c, c2, LAYER_BIG);
|
||||
animateMovement(c, c2, LAYER_BIG, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4823,7 +4827,7 @@ void moveshadow() {
|
||||
cell* where = shpos[p][cshpos];
|
||||
if(where && where->monst == moNone && where->cpdist && where->land == laGraveyard &&
|
||||
!sword::at(where)) {
|
||||
if(shfrom) animateMovement(shfrom, where, LAYER_SMALL);
|
||||
if(shfrom) animateMovement(shfrom, where, LAYER_SMALL, NOHINT);
|
||||
where->monst = moShadow;
|
||||
where->hitpoints = p;
|
||||
where->stuntime = 0;
|
||||
@ -4881,7 +4885,7 @@ void moveghosts() {
|
||||
addMessage(XLAT("%The1 scares %the2 a bit!", c->monst, c2->monst));
|
||||
c2->stuntime = 1;
|
||||
}
|
||||
else moveMonster(c2, c);
|
||||
else moveMonster(c2, c, d);
|
||||
|
||||
}
|
||||
nextghost: ;
|
||||
@ -5249,7 +5253,7 @@ void movegolems(flagtype flags) {
|
||||
else if((flags & AF_CRUSH) && !canAttack(c, m, c2, c2->monst, flags ^ AF_CRUSH ^ AF_MUSTKILL))
|
||||
markOrb(itOrbEmpathy), markOrb(itOrbSlaying);
|
||||
attackMonster(c2, flags | AF_MSG, m);
|
||||
animateAttack(c, c2, LAYER_SMALL);
|
||||
animateAttack(c, c2, LAYER_SMALL, dir);
|
||||
produceGhost(c2, m2, m);
|
||||
sideAttack(c, dir, m, 0);
|
||||
if(revenge) c->monst = m = moPrincessArmed;
|
||||
@ -5261,9 +5265,9 @@ void movegolems(flagtype flags) {
|
||||
else {
|
||||
passable_for(m, c2, c, P_DEADLY);
|
||||
DEBT("move");
|
||||
moveMonster(c2, c);
|
||||
moveMonster(c2, c, dir);
|
||||
if(m != moTameBomberbird && m != moFriendlyGhost)
|
||||
moveBoatIfUsingOne(c2, c);
|
||||
moveBoatIfUsingOne(c2, c, dir);
|
||||
|
||||
if(c2->monst == m) {
|
||||
if(m == moGolem) c2->monst = moGolemMoved;
|
||||
@ -7396,7 +7400,8 @@ bool movepcto(int d, int subdir, bool checkonly) {
|
||||
}
|
||||
|
||||
if(c2->wall == waThumperOn && !c2->monst && !nonAdjacentPlayer(c2, cwt.c)) {
|
||||
cell *c3 = determinePush(cwt, c2, subdir, [c2] (cell *c) { return canPushThumperOn(c, c2, cwt.c); });
|
||||
int pushdir;
|
||||
cell *c3 = determinePush(cwt, c2, subdir, [c2] (cell *c) { return canPushThumperOn(c, c2, cwt.c); }, pushdir);
|
||||
if(c3 == c2) {
|
||||
if(checkonly) return false;
|
||||
addMessage(XLAT("No room to push %the1.", c2->wall));
|
||||
@ -7446,7 +7451,7 @@ bool movepcto(int d, int subdir, bool checkonly) {
|
||||
}
|
||||
|
||||
if(checkonly) return true;
|
||||
moveBoat(c2, cwt.c);
|
||||
moveBoat(c2, cwt.c, d);
|
||||
boatmove = true;
|
||||
goto boatjump;
|
||||
}
|
||||
@ -7462,8 +7467,8 @@ bool movepcto(int d, int subdir, bool checkonly) {
|
||||
if(checkonly) return true;
|
||||
if(c2->item && !cwt.c->item) moveItem(c2, cwt.c, false), boatmove = true;
|
||||
placeWater(c2, cwt.c);
|
||||
moveBoat(c2, cwt.c);
|
||||
c2->mondir = neighborId(c2, cwt.c);
|
||||
moveBoat(c2, cwt.c, d);
|
||||
c2->mondir = revhint(cwt.c, d);
|
||||
if(c2->item) boatmove = !boatmove;
|
||||
goto boatjump;
|
||||
}
|
||||
@ -7495,7 +7500,7 @@ bool movepcto(int d, int subdir, bool checkonly) {
|
||||
|
||||
if(checkonly) { c2->wall = save_c2; cwt.c->wall = save_cw; return true; }
|
||||
addMessage(XLAT("You push %the1 behind you!", waBigStatue));
|
||||
animateMovement(c2, cwt.c, LAYER_BOAT);
|
||||
animateMovement(c2, cwt.c, LAYER_BOAT, cwt.c->spin(d));
|
||||
goto statuejump;
|
||||
}
|
||||
|
||||
@ -7522,7 +7527,7 @@ bool movepcto(int d, int subdir, bool checkonly) {
|
||||
playSound(c2, "hit-axe" + pick123());
|
||||
c2->wall = waNone;
|
||||
sideAttack(cwt.c, d, moPlayer, 0);
|
||||
animateAttack(cwt.c, c2, LAYER_SMALL);
|
||||
animateAttack(cwt.c, c2, LAYER_SMALL, d);
|
||||
}
|
||||
else if(c2->wall == waBigTree) {
|
||||
drawParticles(c2, winf[c2->wall].color, 8);
|
||||
@ -7530,13 +7535,13 @@ bool movepcto(int d, int subdir, bool checkonly) {
|
||||
playSound(c2, "hit-axe" + pick123());
|
||||
c2->wall = waSmallTree;
|
||||
sideAttack(cwt.c, d, moPlayer, 0);
|
||||
animateAttack(cwt.c, c2, LAYER_SMALL);
|
||||
animateAttack(cwt.c, c2, LAYER_SMALL, d);
|
||||
}
|
||||
else {
|
||||
if(!peace::on) {
|
||||
addMessage(XLAT("You swing your sword at the mirror."));
|
||||
sideAttack(cwt.c, d, moPlayer, 0);
|
||||
animateAttack(cwt.c, c2, LAYER_SMALL);
|
||||
animateAttack(cwt.c, c2, LAYER_SMALL, d);
|
||||
}
|
||||
}
|
||||
if(survivalist && isHaunted(c2->land))
|
||||
@ -7601,9 +7606,10 @@ bool movepcto(int d, int subdir, bool checkonly) {
|
||||
// pushto=c2 means that the monster is not killed and thus
|
||||
// still counts for lightning in monstersnear
|
||||
cell *pushto = NULL;
|
||||
int pushdir = 0;
|
||||
if(isStunnable(c2->monst) && c2->hitpoints > 1) {
|
||||
if(monsterPushable(c2))
|
||||
pushto = determinePush(cwt, c2, subdir, [c2] (cell *c) { return passable(c, c2, P_BLOW); });
|
||||
pushto = determinePush(cwt, c2, subdir, [c2] (cell *c) { return passable(c, c2, P_BLOW); }, pushdir);
|
||||
else
|
||||
pushto = c2;
|
||||
}
|
||||
@ -7661,8 +7667,8 @@ bool movepcto(int d, int subdir, bool checkonly) {
|
||||
// salamanders are stunned for longer time when pushed into a wall
|
||||
if(c2->monst == moSalamander && (pushto == c2 || !pushto)) c2->stuntime = 10;
|
||||
if(!c2->monst) produceGhost(c2, m, moPlayer);
|
||||
if(pushto && pushto != c2) pushMonster(pushto, c2);
|
||||
animateAttack(cwt.c, c2, LAYER_SMALL);
|
||||
if(pushto && pushto != c2) pushMonster(pushto, c2, pushdir);
|
||||
animateAttack(cwt.c, c2, LAYER_SMALL, d);
|
||||
}
|
||||
}
|
||||
|
||||
@ -7840,11 +7846,12 @@ bool movepcto(int d, int subdir, bool checkonly) {
|
||||
|
||||
stabbingAttack(cwt.c, c2, moPlayer);
|
||||
cell *c1 = cwt.c;
|
||||
int d = cwt.spin;
|
||||
cwt += wstep;
|
||||
if(switchplaces)
|
||||
animateReplacement(c1, cwt.c, LAYER_SMALL);
|
||||
animateReplacement(c1, cwt.c, LAYER_SMALL, d, cwt.spin);
|
||||
else
|
||||
animateMovement(c1, cwt.c, LAYER_SMALL);
|
||||
animateMovement(c1, cwt.c, LAYER_SMALL, d);
|
||||
|
||||
mirror::act(origd, mirror::SPINMULTI | mirror::ATTACK | mirror::GO);
|
||||
|
||||
|
17
goldberg.cpp
17
goldberg.cpp
@ -579,14 +579,17 @@ namespace hr { namespace gp {
|
||||
dialog::init(XLAT("Goldberg"));
|
||||
|
||||
bool show_nonthree = !(texture_remap && (S7&1));
|
||||
bool show_bitrunc = !(texture_remap && !(S7&1));
|
||||
|
||||
if(show_nonthree) {
|
||||
dialog::addBoolItem(XLAT("OFF"), param == loc(1,0), 'a');
|
||||
dialog::lastItem().value = "GP(1,0)";
|
||||
}
|
||||
|
||||
dialog::addBoolItem(XLAT("bitruncated"), param == loc(1,1), 'b');
|
||||
dialog::lastItem().value = "GP(1,1)";
|
||||
if(show_bitrunc) {
|
||||
dialog::addBoolItem(XLAT("bitruncated"), param == loc(1,1), 'b');
|
||||
dialog::lastItem().value = "GP(1,1)";
|
||||
}
|
||||
|
||||
if(show_nonthree) {
|
||||
dialog::addBoolItem(XLAT("chamfered"), param == loc(2,0), 'c');
|
||||
@ -601,7 +604,9 @@ namespace hr { namespace gp {
|
||||
dialog::addSelItem("y", its(config.second), 'y');
|
||||
|
||||
if((config.first-config.second)%3 && !show_nonthree)
|
||||
dialog::addInfo("This pattern needs x-y divisible by 3");
|
||||
dialog::addInfo(XLAT("This pattern needs x-y divisible by 3"));
|
||||
else if(config == loc(1,1) && !show_bitrunc)
|
||||
dialog::addInfo(XLAT("Select bitruncated from the previous menu"));
|
||||
else
|
||||
dialog::addBoolItem(XLAT("select"), param == internal_representation(config), 'f');
|
||||
|
||||
@ -610,17 +615,17 @@ namespace hr { namespace gp {
|
||||
dialog::addBack();
|
||||
dialog::display();
|
||||
|
||||
keyhandler = [show_nonthree, texture_remap] (int sym, int uni) {
|
||||
keyhandler = [show_nonthree, show_bitrunc, texture_remap] (int sym, int uni) {
|
||||
dialog::handleNavigation(sym, uni);
|
||||
if(uni == 'a' && show_nonthree)
|
||||
whirl_set(loc(1, 0), texture_remap);
|
||||
else if(uni == 'b')
|
||||
else if(uni == 'b' && show_bitrunc)
|
||||
whirl_set(loc(1, 1), texture_remap);
|
||||
else if(uni == 'c' && show_nonthree)
|
||||
whirl_set(loc(2, 0), texture_remap);
|
||||
else if(uni == 'd')
|
||||
whirl_set(loc(3, 0), texture_remap);
|
||||
else if(uni == 'f' && (show_nonthree || (config.first-config.second)%3 == 0))
|
||||
else if(uni == 'f' && (config == loc(1,1) ? show_bitrunc : (show_nonthree || (config.first-config.second)%3 == 0)))
|
||||
whirl_set(config, texture_remap);
|
||||
else if(uni == 'x')
|
||||
dialog::editNumber(config.first, 1, 10, 1, 1, "x", helptext());
|
||||
|
94
graph.cpp
94
graph.cpp
@ -1826,7 +1826,7 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, int col) {
|
||||
|
||||
if(isIvy(c) || isWorm(c) || isMutantIvy(c) || c->monst == moFriendlyIvy) {
|
||||
|
||||
if((m == moHexSnake || m == moHexSnakeTail) && c->land == laSnakeNest) {
|
||||
if((m == moHexSnake || m == moHexSnakeTail) && c->hitpoints == 2) {
|
||||
int d = c->mondir;
|
||||
if(d == NODIR)
|
||||
forCellIdEx(c2, i, c)
|
||||
@ -2090,7 +2090,7 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, int col) {
|
||||
Vb = Vb * xpush(tentacle_length - cellgfxdist(c, c->mondir));
|
||||
}
|
||||
else if(gp::on) {
|
||||
transmatrix T = shmup::calc_relative_matrix(c->mov[c->mondir], c);
|
||||
transmatrix T = shmup::calc_relative_matrix(c->mov[c->mondir], c, c->mondir);
|
||||
Vb = Vb * T * rspintox(tC0(inverse(T))) * xpush(tentacle_length);
|
||||
}
|
||||
else {
|
||||
@ -2139,6 +2139,10 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, int col) {
|
||||
Vs = playerV;
|
||||
if(multi::players > 1 ? multi::flipped[i] : flipplayer) Vs = Vs * pispin;
|
||||
}
|
||||
else {
|
||||
bool mirr = multi::players > 1 ? multi::player[i].mirrored : cwt.mirrored;
|
||||
if(mirr) Vs = Vs * Mirror;
|
||||
}
|
||||
shmup::cpid = i;
|
||||
|
||||
drawPlayerEffects(Vs, c, true);
|
||||
@ -2562,7 +2566,7 @@ void drawMovementArrows(cell *c, transmatrix V) {
|
||||
int sd = md.subdir;
|
||||
queuepoly(inverse(Centered) * rgpushxto0(Centered * tC0(V)) * rspintox(Centered*tC0(V)) * spin(-sd * M_PI/S7) * xpush(0.2), shArrow, col);
|
||||
}
|
||||
else break;
|
||||
else if(!confusingGeometry()) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3425,6 +3429,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
|
||||
#if CAP_TEXTURE
|
||||
if(texture::saving) {
|
||||
texture::config.apply(c, V, 0xFFFFFFFF);
|
||||
draw_qfi(c, V, 0xFFFFFFFF);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@ -4962,15 +4967,15 @@ void drawMarkers() {
|
||||
|
||||
if((vid.axes == 4 || (vid.axes == 1 && !mousing)) && !shmup::on) {
|
||||
if(multi::players == 1) {
|
||||
forCellAll(c2, cwt.c) IG(c2) drawMovementArrows(c2, Gm(c2));
|
||||
forCellIdAll(c2, d, cwt.c) IG(c2) drawMovementArrows(c2, confusingGeometry() ? Gm(cwt.c) * shmup::calc_relative_matrix(c2, cwt.c, d) : Gm(c2));
|
||||
}
|
||||
else if(multi::players > 1) for(int p=0; p<multi::players; p++) {
|
||||
if(multi::playerActive(p) && (vid.axes == 4 || !drawstaratvec(multi::mdx[p], multi::mdy[p])))
|
||||
forCellAll(c2, multi::player[p].c) IG(c2) {
|
||||
forCellIdAll(c2, d, multi::player[p].c) IG(c2) {
|
||||
multi::cpid = p;
|
||||
dynamicval<transmatrix> ttm(cwtV, multi::whereis[p]);
|
||||
dynamicval<cellwalker> tcw(cwt, multi::player[p]);
|
||||
drawMovementArrows(c2, Gm(c2));
|
||||
drawMovementArrows(c2, confusingGeometry() ? Gm(cwt.c) * shmup::calc_relative_matrix(c2, cwt.c, d) : Gm(c2));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5739,51 +5744,68 @@ void resetGeometry() {
|
||||
map<cell*, animation> animations[ANIMLAYERS];
|
||||
unordered_map<cell*, transmatrix> gmatrix, gmatrix0;
|
||||
|
||||
void animateMovement(cell *src, cell *tgt, int layer) {
|
||||
int revhint(cell *c, int hint) {
|
||||
if(hint >= 0 && hint < c->type) return c->spin(hint);
|
||||
else return hint;
|
||||
}
|
||||
|
||||
bool compute_relamatrix(cell *src, cell *tgt, int direction_hint, transmatrix& T) {
|
||||
if(confusingGeometry()) {
|
||||
T = shmup::calc_relative_matrix(src, tgt, revhint(src, direction_hint));
|
||||
}
|
||||
else {
|
||||
if(gmatrix.count(src) && gmatrix.count(tgt))
|
||||
T = inverse(gmatrix[tgt]) * gmatrix[src];
|
||||
else
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void animateMovement(cell *src, cell *tgt, int layer, int direction_hint) {
|
||||
if(vid.mspeed >= 5) return; // no animations!
|
||||
if(confusingGeometry()) return;
|
||||
if(gmatrix.count(src) && gmatrix.count(tgt)) {
|
||||
animation& a = animations[layer][tgt];
|
||||
if(animations[layer].count(src)) {
|
||||
a = animations[layer][src];
|
||||
a.wherenow = inverse(gmatrix[tgt]) * gmatrix[src] * a.wherenow;
|
||||
animations[layer].erase(src);
|
||||
a.attacking = 0;
|
||||
}
|
||||
else {
|
||||
a.ltick = ticks;
|
||||
a.wherenow = inverse(gmatrix[tgt]) * gmatrix[src];
|
||||
a.footphase = 0;
|
||||
}
|
||||
transmatrix T;
|
||||
if(!compute_relamatrix(src, tgt, direction_hint, T)) return;
|
||||
animation& a = animations[layer][tgt];
|
||||
if(animations[layer].count(src)) {
|
||||
a = animations[layer][src];
|
||||
a.wherenow = T * a.wherenow;
|
||||
animations[layer].erase(src);
|
||||
a.attacking = 0;
|
||||
}
|
||||
else {
|
||||
a.ltick = ticks;
|
||||
a.wherenow = T;
|
||||
a.footphase = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void animateAttack(cell *src, cell *tgt, int layer) {
|
||||
void animateAttack(cell *src, cell *tgt, int layer, int direction_hint) {
|
||||
if(vid.mspeed >= 5) return; // no animations!
|
||||
if(gmatrix.count(src) && gmatrix.count(tgt)) {
|
||||
bool newanim = !animations[layer].count(src);
|
||||
animation& a = animations[layer][src];
|
||||
a.attacking = 1;
|
||||
a.attackat = rspintox(tC0(inverse(gmatrix[src]) * gmatrix[tgt])) * xpush(hdist(gmatrix[src]*C0, gmatrix[tgt]*C0) / 3);
|
||||
if(newanim) a.wherenow = Id, a.ltick = ticks, a.footphase = 0;
|
||||
}
|
||||
transmatrix T;
|
||||
if(!compute_relamatrix(src, tgt, direction_hint, T)) return;
|
||||
bool newanim = !animations[layer].count(src);
|
||||
animation& a = animations[layer][src];
|
||||
a.attacking = 1;
|
||||
a.attackat = rspintox(tC0(inverse(T))) * xpush(hdist0(T*C0) / 3);
|
||||
if(newanim) a.wherenow = Id, a.ltick = ticks, a.footphase = 0;
|
||||
}
|
||||
|
||||
vector<pair<cell*, animation> > animstack;
|
||||
|
||||
void indAnimateMovement(cell *src, cell *tgt, int layer) {
|
||||
void indAnimateMovement(cell *src, cell *tgt, int layer, int direction_hint) {
|
||||
if(vid.mspeed >= 5) return; // no animations!
|
||||
if(confusingGeometry()) return;
|
||||
if(animations[layer].count(tgt)) {
|
||||
animation res = animations[layer][tgt];
|
||||
animations[layer].erase(tgt);
|
||||
animateMovement(src, tgt, layer);
|
||||
animateMovement(src, tgt, layer, direction_hint);
|
||||
if(animations[layer].count(tgt))
|
||||
animstack.push_back(make_pair(tgt, animations[layer][tgt]));
|
||||
animations[layer][tgt] = res;
|
||||
}
|
||||
else {
|
||||
animateMovement(src, tgt, layer);
|
||||
animateMovement(src, tgt, layer, direction_hint);
|
||||
if(animations[layer].count(tgt)) {
|
||||
animstack.push_back(make_pair(tgt, animations[layer][tgt]));
|
||||
animations[layer].erase(tgt);
|
||||
@ -5797,13 +5819,13 @@ void commitAnimations(int layer) {
|
||||
animstack.clear();
|
||||
}
|
||||
|
||||
void animateReplacement(cell *a, cell *b, int layer) {
|
||||
void animateReplacement(cell *a, cell *b, int layer, int direction_hinta, int direction_hintb) {
|
||||
if(vid.mspeed >= 5) return; // no animations!
|
||||
static cell c1;
|
||||
gmatrix[&c1] = gmatrix[b];
|
||||
if(animations[layer].count(b)) animations[layer][&c1] = animations[layer][b];
|
||||
animateMovement(a, b, layer);
|
||||
animateMovement(&c1, a, layer);
|
||||
animateMovement(a, b, layer, direction_hinta);
|
||||
animateMovement(&c1, a, layer, direction_hintb);
|
||||
}
|
||||
|
||||
void drawBug(const cellwalker& cw, int col) {
|
||||
|
25
hyper.h
25
hyper.h
@ -2,9 +2,9 @@
|
||||
// It is quite chaotic.
|
||||
|
||||
// version numbers
|
||||
#define VER "10.4b"
|
||||
#define VERNUM 10402
|
||||
#define VERNUM_HEX 0xA0B2
|
||||
#define VER "10.4c"
|
||||
#define VERNUM 10403
|
||||
#define VERNUM_HEX 0xA0B3
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
@ -480,7 +480,7 @@ bool movepcto(int d, int subdir = 1, bool checkonly = false);
|
||||
void stabbingAttack(cell *mf, cell *mt, eMonster who, int bonuskill = 0);
|
||||
bool earthMove(cell *from, int dir);
|
||||
void messageKill(eMonster killer, eMonster victim);
|
||||
void moveMonster(cell *ct, cell *cf);
|
||||
void moveMonster(cell *ct, cell *cf, int direction_hint);
|
||||
int palaceHP();
|
||||
void placeLocalOrbs(cell *c);
|
||||
int elementalKills();
|
||||
@ -654,7 +654,7 @@ namespace shmup {
|
||||
|
||||
void virtualRebase(cell*& base, transmatrix& at, bool tohex);
|
||||
void virtualRebase(shmup::monster *m, bool tohex);
|
||||
transmatrix calc_relative_matrix(cell *c, cell *c1);
|
||||
transmatrix calc_relative_matrix(cell *c, cell *c1, int direction_hint);
|
||||
void fixStorage();
|
||||
void addShmupHelp(string& out);
|
||||
void activateArrow(cell *c);
|
||||
@ -665,6 +665,8 @@ namespace shmup {
|
||||
void popmonsters();
|
||||
}
|
||||
|
||||
static const int NOHINT = -1;
|
||||
|
||||
// graph
|
||||
|
||||
void showMissionScreen();
|
||||
@ -1552,16 +1554,16 @@ struct animation {
|
||||
extern map<cell*, animation> animations[ANIMLAYERS];
|
||||
extern unordered_map<cell*, transmatrix> gmatrix, gmatrix0;
|
||||
|
||||
void animateAttack(cell *src, cell *tgt, int layer);
|
||||
void animateAttack(cell *src, cell *tgt, int layer, int direction_hint);
|
||||
|
||||
void animateMovement(cell *src, cell *tgt, int layer);
|
||||
void animateMovement(cell *src, cell *tgt, int layer, int direction_hint);
|
||||
|
||||
// for animations which might use the same locations,
|
||||
// such as replacements or multi-tile monsters
|
||||
void indAnimateMovement(cell *src, cell *tgt, int layer);
|
||||
void indAnimateMovement(cell *src, cell *tgt, int layer, int direction_hint);
|
||||
void commitAnimations(int layer);
|
||||
|
||||
void animateReplacement(cell *a, cell *b, int layer);
|
||||
void animateReplacement(cell *a, cell *b, int layer, int direction_hinta, int direction_hintb);
|
||||
void fallingFloorAnimation(cell *c, eWall w = waNone, eMonster m = moNone);
|
||||
void fallingMonsterAnimation(cell *c, eMonster m, int id = multi::cpid);
|
||||
|
||||
@ -2780,7 +2782,6 @@ namespace texture {
|
||||
void showMenu();
|
||||
|
||||
void drawPixel(cell *c, hyperpoint h, int col);
|
||||
|
||||
extern cell *where;
|
||||
// compute 'c' automatically, based on the hint in 'where'
|
||||
void drawPixel(hyperpoint h, int col);
|
||||
@ -3512,4 +3513,8 @@ void gdpush(int t);
|
||||
|
||||
extern int fontscale;
|
||||
|
||||
bool confusingGeometry();
|
||||
|
||||
int revhint(cell *c, int hint);
|
||||
|
||||
}
|
||||
|
@ -1626,7 +1626,7 @@ void giantLandSwitch(cell *c, int d, cell *from) {
|
||||
for(int t=0; t<c->type; t++) if(c->mov[t]->mpdist > c->mpdist && !pseudohept(c->mov[t]))
|
||||
i = t;
|
||||
if(i != -1 && !peace::on)
|
||||
generateSnake(c, i);
|
||||
generateSnake(c, i, 1);
|
||||
}
|
||||
else if(hrand(16000) < 50+items[itRedGem]+yendor::hardness() && (nonbitrunc?hrand(10)<3:!ishept(c)) && !c->monst)
|
||||
c->monst = moRedTroll,
|
||||
@ -1641,7 +1641,7 @@ void giantLandSwitch(cell *c, int d, cell *from) {
|
||||
for(int t=0; t<c->type; t++) if(c->mov[t]->mpdist > c->mpdist)
|
||||
gooddir.push_back(t);
|
||||
if(size(gooddir))
|
||||
generateSnake(c, gooddir[hrand(size(gooddir))]);
|
||||
generateSnake(c, gooddir[hrand(size(gooddir))], 2);
|
||||
}
|
||||
else if(hrand(10000) < items[itSnake] - 10 + yendor::hardness() && !c->monst && !c->wall && !peace::on) {
|
||||
c->monst = pick(moRedTroll, moMiner, moSkeleton, moBomberbird);
|
||||
@ -1970,7 +1970,7 @@ void giantLandSwitch(cell *c, int d, cell *from) {
|
||||
c->monst = moMonkey;
|
||||
else if(hrand(80000) < 5 + items[itRuby] + yendor::hardness())
|
||||
c->monst = moEagle;
|
||||
else if(ishept(c) && c != currentmap->gamestart() && hrand(4000) < 300 + items[itRuby] && !c->monst) {
|
||||
else if(pseudohept(c) && c != currentmap->gamestart() && hrand(4000) < 300 + items[itRuby] && !c->monst) {
|
||||
int hardchance = items[itRuby] + yendor::hardness();
|
||||
if(hardchance > 25) hardchance = 25;
|
||||
bool hardivy = hrand(100) < hardchance;
|
||||
|
@ -547,6 +547,12 @@ namespace mapeditor {
|
||||
if((isWorm(c) || isIvy(c) || isMutantIvy(c)) && c->mov[cdir] &&
|
||||
!isWorm(c->mov[cdir]) && !isIvy(c->mov[cdir]))
|
||||
c->mondir = NODIR;
|
||||
|
||||
if(c->monst == moMimic) {
|
||||
c->monst = moNone;
|
||||
mirror::createMirror(cellwalker(c, cdir, true), 0);
|
||||
c->monst = moMimic;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
c->item = eItem(paintwhat);
|
||||
@ -1054,6 +1060,8 @@ namespace mapeditor {
|
||||
displaymm('d', 8, 8+fs*7, 2, vid.fsize, XLAT("d = draw"), 0);
|
||||
displaymm('l', 8, 8+fs*8, 2, vid.fsize, XLAT("l = line"), 0);
|
||||
displaymm('c', 8, 8+fs*9, 2, vid.fsize, XLAT("c = circle"), 0);
|
||||
int s = size(texture::config.data.pixels_to_draw);
|
||||
if(s) displaymm(0, 8, 8+fs*11, 2, vid.fsize, its(s), 0);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
|
@ -673,8 +673,9 @@ void wandering() {
|
||||
}
|
||||
}
|
||||
|
||||
void generateSnake(cell *c, int i) {
|
||||
void generateSnake(cell *c, int i, int color) {
|
||||
c->monst = moHexSnake;
|
||||
c->hitpoints = color;
|
||||
int cpair = (1<<pattern_threecolor(c)) | (1<<pattern_threecolor(c->mov[i]));
|
||||
preventbarriers(c);
|
||||
int len = nonbitrunc ? 2 : ROCKSNAKELENGTH;
|
||||
@ -689,7 +690,7 @@ void generateSnake(cell *c, int i) {
|
||||
cell *c3 = c2->mov[i];
|
||||
if(c3->monst || c3->bardir != NODIR || c3->wall) break;
|
||||
c2 = c3;
|
||||
c2->monst = moHexSnakeTail;
|
||||
c2->monst = moHexSnakeTail; c2->hitpoints = color;
|
||||
i = (j + (c2->type%4 == 0 ? c2->type/2 : (len%2 ? 2 : c2->type - 2))) % c2->type;
|
||||
createMov(c2, i);
|
||||
if(!inpair(c2->mov[i], cpair)) {
|
||||
|
26
orbs.cpp
26
orbs.cpp
@ -577,7 +577,7 @@ void jumpTo(cell *dest, eItem byWhat, int bonuskill, eMonster dashmon) {
|
||||
killFriendlyIvy();
|
||||
|
||||
cell *c1 = cwt.c;
|
||||
animateMovement(cwt.c, dest, LAYER_SMALL);
|
||||
animateMovement(cwt.c, dest, LAYER_SMALL, NOHINT);
|
||||
cwt.c = dest;
|
||||
forCellIdEx(c2, i, dest) if(c2->cpdist < dest->cpdist) {
|
||||
cwt.spin = i;
|
||||
@ -619,13 +619,13 @@ void jumpTo(cell *dest, eItem byWhat, int bonuskill, eMonster dashmon) {
|
||||
monstersTurn();
|
||||
}
|
||||
|
||||
void growIvyTo(cell *dest, cell *src) {
|
||||
void growIvyTo(cell *dest, cell *src, int direction_hint) {
|
||||
if(dest->monst)
|
||||
attackMonster(dest, AF_NORMAL | AF_MSG, moFriendlyIvy);
|
||||
else {
|
||||
dest->monst = moFriendlyIvy;
|
||||
dest->mondir = neighborId(dest, src);
|
||||
moveEffect(dest, src, moFriendlyIvy);
|
||||
moveEffect(dest, src, moFriendlyIvy, direction_hint);
|
||||
empathyMove(src, dest, neighborId(src, dest));
|
||||
}
|
||||
createNoise(1);
|
||||
@ -797,7 +797,7 @@ void summonAt(cell *dest) {
|
||||
if(dest->monst == moTortoise)
|
||||
tortoise::emap[dest] = dest;
|
||||
addMessage(XLAT("You summon %the1!", dest->monst));
|
||||
moveEffect(dest, dest, dest->monst);
|
||||
moveEffect(dest, dest, dest->monst, -1);
|
||||
if(dest->wall == waClosePlate || dest->wall == waOpenPlate)
|
||||
toggleGates(dest, dest->wall);
|
||||
|
||||
@ -865,7 +865,7 @@ void gun_attack(cell *dest) {
|
||||
|
||||
void checkStunKill(cell *dest) {
|
||||
if(isBird(dest->monst)) {
|
||||
moveEffect(dest, dest, moDeadBird);
|
||||
moveEffect(dest, dest, moDeadBird, NOHINT);
|
||||
doesFall(dest);
|
||||
if(isWatery(dest) || dest->wall == waChasm || isFire(dest)) {
|
||||
addMessage(XLAT("%The1 falls!", dest->monst));
|
||||
@ -925,10 +925,10 @@ void placeIllusion(cell *c) {
|
||||
checkmoveO();
|
||||
}
|
||||
|
||||
void blowoff(cell *cf, cell *ct) {
|
||||
void blowoff(cell *cf, cell *ct, int direction_hint) {
|
||||
playSound(ct, "orb-ranged");
|
||||
addMessage(XLAT("You blow %the1 away!", cf->monst));
|
||||
pushMonster(ct, cf);
|
||||
pushMonster(ct, cf, direction_hint);
|
||||
if(cf->item == itBabyTortoise && !ct->item)
|
||||
moveItem(cf, ct, true);
|
||||
items[itOrbAir]--;
|
||||
@ -1024,9 +1024,10 @@ eItem targetRangedOrb(cell *c, orbAction a) {
|
||||
for(; d<c->type; d++) if(c->mov[d] && c->mov[d]->cpdist < c->cpdist) break;
|
||||
if(d<c->type) for(int e=d; e<d+c->type; e++) {
|
||||
nowhereToBlow = true;
|
||||
cell *c2 = c->mov[e % c->type];
|
||||
int di = e % c->type;
|
||||
cell *c2 = c->mov[di];
|
||||
if(c2 && c2->cpdist > c->cpdist && passable(c2, c, P_BLOW)) {
|
||||
if(!isCheck(a)) blowoff(c, c2);
|
||||
if(!isCheck(a)) blowoff(c, c2, di);
|
||||
return itOrbAir;
|
||||
}
|
||||
}
|
||||
@ -1035,8 +1036,9 @@ eItem targetRangedOrb(cell *c, orbAction a) {
|
||||
// nature
|
||||
if(items[itOrbNature] && numplayers() == 1 && c->monst != moFriendlyIvy) {
|
||||
cell *sides[8];
|
||||
int dirs[8];
|
||||
int qsides = 0;
|
||||
forCellCM(cf, c)
|
||||
forCellIdCM(cf, d, c)
|
||||
if(cf->monst == moFriendlyIvy) {
|
||||
|
||||
if(c->monst) {
|
||||
@ -1048,11 +1050,13 @@ eItem targetRangedOrb(cell *c, orbAction a) {
|
||||
if(strictlyAgainstGravity(c, cf, false, MF_IVY)) continue;
|
||||
if(monstersnear(cwt.c, NULL, moPlayer, c, cwt.c)) continue;
|
||||
}
|
||||
dirs[qsides] = d;
|
||||
sides[qsides++] = cf;
|
||||
}
|
||||
|
||||
if(qsides > 0) {
|
||||
if(!isCheck(a)) growIvyTo(c, sides[hrand(qsides)]);
|
||||
int di = hrand(qsides);
|
||||
if(!isCheck(a)) growIvyTo(c, sides[di], revhint(c, dirs[di]));
|
||||
return itOrbNature;
|
||||
}
|
||||
}
|
||||
|
@ -767,7 +767,7 @@ namespace patterns {
|
||||
if((gp::on? (S3==3) : !weirdhyperbolic) && isWarped(c))
|
||||
val_warped(c, si);
|
||||
else {
|
||||
si.id = ishept(c) ? 1 : 0;
|
||||
si.id = pseudohept(c) ? 1 : 0;
|
||||
if(euclid) {
|
||||
si.dir = ishex1(c) ? 0 : 3;
|
||||
if(ctof(c)) si.symmetries = 3;
|
||||
@ -957,6 +957,12 @@ namespace patterns {
|
||||
val_all(c, si, sub, pat);
|
||||
}
|
||||
|
||||
else if(gp::on) {
|
||||
bool football = (pat == PAT_COLORING && (sub & SPF_FOOTBALL)) || pat == 0;
|
||||
if(football) val_nopattern(c, si, sub);
|
||||
else val_threecolors(c, si, sub);
|
||||
}
|
||||
|
||||
else if(pat == PAT_COLORING && (S7 == 4 || euclid || (a38 && gp_threecolor() == 1))) {
|
||||
val_threecolors(c, si, sub);
|
||||
}
|
||||
@ -1626,6 +1632,7 @@ namespace patterns {
|
||||
dialog::addBoolItem(s, geometry == g.geo && nonbitrunc == g.nonbitru && whichPattern == g.whichPattern && subpattern_flags == g.subpattern_flags, 'a'+j);
|
||||
}
|
||||
bool have_goldberg = S3 == 3 && among(cgroup, cpFootball, cpThree) && !euclid;
|
||||
if(!(S7&1) && !nonbitrunc) have_goldberg = false; // always start from non-bitruncated
|
||||
if(have_goldberg) {
|
||||
dialog::addBoolItem(XLAT("Goldberg"), gp::on, 'G');
|
||||
dialog::lastItem().value = gp::operation_name();
|
||||
|
@ -334,7 +334,7 @@ void bantar_frame() {
|
||||
|
||||
View = Id;
|
||||
|
||||
transmatrix tView = actualV(cth(xcw), Id) * shmup::calc_relative_matrix(cwt.c, xcw.c) * inverse(actualV(cth(cwt), Id));
|
||||
transmatrix tView = actualV(cth(xcw), Id) * shmup::calc_relative_matrix(cwt.c, xcw.c, NOHINT) * inverse(actualV(cth(cwt), Id));
|
||||
|
||||
if(tphase < 2) part = 0;
|
||||
else if(tphase == 2)
|
||||
|
84
shmup.cpp
84
shmup.cpp
@ -1624,7 +1624,7 @@ void movePlayer(monster *m, int delta) {
|
||||
m->base->wall = waChasm;
|
||||
else {
|
||||
m->base->wall = waBigStatue;
|
||||
animateMovement(c2, m->base, LAYER_BOAT);
|
||||
animateMovement(c2, m->base, LAYER_BOAT, NOHINT);
|
||||
}
|
||||
}
|
||||
else if(m->inBoat && !isWateryOrBoat(c2) && passable(c2, m->base, P_ISPLAYER | P_MIRROR | reflectflag)) {
|
||||
@ -2728,7 +2728,7 @@ void moveMonster(monster *m, int delta) {
|
||||
m->base->wall = waChasm;
|
||||
else
|
||||
m->base->wall = waBigStatue;
|
||||
animateMovement(c2, m->base, LAYER_BOAT);
|
||||
animateMovement(c2, m->base, LAYER_BOAT, NOHINT);
|
||||
}
|
||||
if(passable_for(m->type, c2, m->base, P_CHAIN | P_ONPLAYER | reflectflag) && !isWatery(c2) && m->inBoat) {
|
||||
if(isWatery(m->base))
|
||||
@ -3336,7 +3336,7 @@ transmatrix master_relative(cell *c, bool get_inverse) {
|
||||
return T;
|
||||
}
|
||||
}
|
||||
else if(!nonbitrunc) {
|
||||
else if(!nonbitrunc && !euclid) {
|
||||
for(int d=0; d<S7; d++) if(c->master->c7->mov[d] == c)
|
||||
return (get_inverse?invhexmove:hexmove)[d];
|
||||
return Id;
|
||||
@ -3345,7 +3345,8 @@ transmatrix master_relative(cell *c, bool get_inverse) {
|
||||
return pispin * Id;
|
||||
}
|
||||
|
||||
transmatrix calc_relative_matrix(cell *c2, cell *c1) {
|
||||
// target, source, direction from source to target
|
||||
transmatrix calc_relative_matrix(cell *c2, cell *c1, int direction_hint) {
|
||||
|
||||
if(sphere) {
|
||||
if(!gmatrix0.count(c2) || !gmatrix0.count(c1)) {
|
||||
@ -3358,14 +3359,46 @@ transmatrix calc_relative_matrix(cell *c2, cell *c1) {
|
||||
swap(gmatrix, gmatrix0);
|
||||
gp::draw_li = bak;
|
||||
}
|
||||
if(gmatrix0.count(c2) && gmatrix0.count(c1))
|
||||
return inverse(gmatrix0[c1]) * gmatrix0[c2];
|
||||
if(gmatrix0.count(c2) && gmatrix0.count(c1)) {
|
||||
transmatrix T = inverse(gmatrix0[c1]) * gmatrix0[c2];
|
||||
if(elliptic && T[2][2] < 0)
|
||||
T = centralsym * T;
|
||||
return T;
|
||||
}
|
||||
else {
|
||||
printf("error: gmatrix0 not known\n");
|
||||
return Id;
|
||||
}
|
||||
}
|
||||
|
||||
if(torus) {
|
||||
transmatrix t = Id;
|
||||
if(whateveri) printf("[%p,%d] ", c2, celldistance(c2, c1));
|
||||
int mirrors = 0;
|
||||
approach:
|
||||
int d = celldistance(c2, c1);
|
||||
forCellIdEx(c3, i, c2) {
|
||||
if(celldistance(c3, c1) < d) {
|
||||
if(whateveri) printf(" %d [%p,%d]", i, c3, celldistance(c3, c1));
|
||||
if(c2->type < 8)
|
||||
t = eumovedir(i+(euclid6?3:2)) * t;
|
||||
else if(i&1)
|
||||
t = eumovedir(2+i/2) * eumovedir(2+(i+1)/2) * t;
|
||||
else
|
||||
t = eumovedir(2+i/2) * t;
|
||||
if(c2->mirror(i)) mirrors++;
|
||||
c2 = c3;
|
||||
goto approach;
|
||||
}
|
||||
}
|
||||
if(d != 0) printf("ERROR not reached\n");
|
||||
if(mirrors&1) t = Mirror * t * Mirror;
|
||||
if(whateveri) printf(" => %p\n", c1);
|
||||
return t;
|
||||
}
|
||||
|
||||
if(euclid) return inverse(gmatrix0[c1]) * gmatrix0[c2];
|
||||
|
||||
heptagon *h1 = c1->master;
|
||||
transmatrix gm = master_relative(c1, true);
|
||||
heptagon *h2 = c2->master;
|
||||
@ -3375,20 +3408,26 @@ transmatrix calc_relative_matrix(cell *c2, cell *c1) {
|
||||
//bool hsol = false;
|
||||
//transmatrix sol;
|
||||
while(h1 != h2) {
|
||||
int confusion = 0;
|
||||
if(quotient == 1 && gp::on) {
|
||||
for(int d=0; d<S7; d++) if(h2->move[d] == h1) confusion++;
|
||||
if(confusion > 1) {
|
||||
transmatrix T;
|
||||
confusion = 0;
|
||||
for(int d=0; d<S7; d++) if(h2->move[d] == h1) {
|
||||
int sp = h2->spin(d);
|
||||
transmatrix T1 = gm * heptmove[sp] * spin(2*M_PI*d/S7) * where;
|
||||
if(confusion == 0 || T1[2][2] < T[2][2]) T = T1;
|
||||
confusion++;
|
||||
if(quotient == 1) {
|
||||
transmatrix T;
|
||||
hyperpoint hint = ddspin(c1, direction_hint) * xpush(1e-2) * C0;
|
||||
ld bestdist = 1e9;
|
||||
for(int d=0; d<S7; d++) if(h2->move[d]) {
|
||||
int sp = h2->spin(d);
|
||||
transmatrix S = heptmove[sp] * spin(2*M_PI*d/S7);
|
||||
if(h2->move[d] == h1) {
|
||||
transmatrix T1 = gm * S * where;
|
||||
auto curdist = hdist(tC0(T1), hint);
|
||||
if(curdist < bestdist) T = T1, bestdist = curdist;
|
||||
}
|
||||
for(int e=0; e<S7; e++) if(h2->move[d]->move[e] == h1) {
|
||||
int sp2 = h2->move[d]->spin(e);
|
||||
transmatrix T1 = gm * heptmove[sp2] * spin(2*M_PI*e/S7) * S * where;
|
||||
auto curdist = hdist(tC0(T1), hint);
|
||||
if(curdist < bestdist) T = T1, bestdist = curdist;
|
||||
}
|
||||
return T;
|
||||
}
|
||||
return T;
|
||||
}
|
||||
for(int d=0; d<S7; d++) if(h2->move[d] == h1) {
|
||||
int sp = h2->spin(d);
|
||||
@ -3421,17 +3460,14 @@ transmatrix calc_relative_matrix(cell *c2, cell *c1) {
|
||||
transmatrix &ggmatrix(cell *c) {
|
||||
transmatrix& t = gmatrix[c];
|
||||
if(t[2][2] == 0) {
|
||||
if(torus) {
|
||||
forCellIdEx(c2, i, c)
|
||||
if(celldistance(c2, centerover.c) < celldistance(c, centerover.c))
|
||||
t = ggmatrix(c2) * eumovedir(3+i);
|
||||
}
|
||||
if(torus && centerover.c)
|
||||
t = calc_relative_matrix(c, centerover.c, NOHINT);
|
||||
else if(euclid) {
|
||||
if(!centerover.c) centerover = cwt;
|
||||
t = View * eumove(cell_to_vec(c) - cellwalker_to_vec(centerover));
|
||||
}
|
||||
else
|
||||
t = actualV(viewctr, cview()) * calc_relative_matrix(c, viewctr.h->c7);
|
||||
t = actualV(viewctr, cview()) * calc_relative_matrix(c, viewctr.h->c7, NOHINT);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
@ -1269,6 +1269,7 @@ void fillpixel(int x, int y, unsigned col) {
|
||||
}
|
||||
|
||||
void texture_data::undo() {
|
||||
texture::config.data.pixels_to_draw.clear();
|
||||
while(!undos.empty()) {
|
||||
auto p = undos.back();
|
||||
undos.pop_back();
|
||||
|
Loading…
Reference in New Issue
Block a user