mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2025-01-22 23:17:04 +00:00
first version of the Land of Dice
This commit is contained in:
parent
b879682d82
commit
6a6ed4ea0d
@ -104,6 +104,8 @@ EX bool canAttack(cell *c1, eMonster m1, cell *c2, eMonster m2, flagtype flags)
|
||||
|
||||
if(m1 == moArrowTrap && arrow_stuns(m2)) return true;
|
||||
|
||||
if(m2 == moAnimatedDie && !(flags & (AF_MAGIC | AF_CRUSH))) return false;
|
||||
|
||||
if(among(m2, moAltDemon, moHexDemon, moPair, moCrusher, moNorthPole, moSouthPole, moMonk) && !(flags & (AF_EAT | AF_MAGIC | AF_BULL | AF_CRUSH)))
|
||||
return false;
|
||||
|
||||
|
@ -1601,8 +1601,19 @@ void celldrawer::draw_features() {
|
||||
poly_outline = OUTLINE_DEFAULT;
|
||||
}
|
||||
|
||||
else if(c->wall == waDie) {
|
||||
dice::draw_die(c, V);
|
||||
else if(among(c->wall, waRichDie, waBlandDie)) {
|
||||
color_t col = darkena(winf[c->wall].color, 0, 0xFF);
|
||||
|
||||
ld footphase;
|
||||
Vboat = V;
|
||||
bool animated = applyAnimation(c, Vboat, footphase, LAYER_BOAT);
|
||||
if(animated) {
|
||||
transmatrix U = inverse_shift(V, Vboat);
|
||||
U = rgpushxto0(tC0(U));
|
||||
Vboat = V * U;
|
||||
}
|
||||
die_target = V;
|
||||
dice::draw_die(c, Vboat, 1, col);
|
||||
}
|
||||
|
||||
else if(c->wall == waExplosiveBarrel) {
|
||||
|
314
complex2.cpp
314
complex2.cpp
@ -904,73 +904,148 @@ EX }
|
||||
|
||||
EX namespace dice {
|
||||
|
||||
/* vector<vector<int>> sides = {
|
||||
{1, 3, 5}, {0, 4, 2}, {3, 1, 7}, {2, 6, 0}, {5, 7, 1}, {4, 0, 6}, {7, 5, 3}, {6, 2, 4}
|
||||
}; */
|
||||
|
||||
vector<vector<int>> sides = {
|
||||
struct die_structure {
|
||||
vector<vector<int>> sides;
|
||||
vector<vector<int>> spins;
|
||||
vector<int> hardness;
|
||||
int faces;
|
||||
int order;
|
||||
die_structure(int ord, const vector<vector<int>>& v) {
|
||||
sides = v;
|
||||
spins = sides;
|
||||
faces = isize(sides);
|
||||
order = ord;
|
||||
for(int i=0; i<faces; i++)
|
||||
for(int j=0; j<isize(sides[i]); j++) {
|
||||
int i1 = sides[i][j];
|
||||
spins[i][j] = -1;
|
||||
for(int k=0; k<isize(sides[i1]); k++)
|
||||
if(sides[i1][k] == i)
|
||||
spins[i][j] = k;
|
||||
if(spins[i][j] == -1)
|
||||
println(hlog, "asymmetric");
|
||||
}
|
||||
hardness.resize(faces, 99);
|
||||
hardness.back() = 0;
|
||||
for(int it=0; it<faces; it++)
|
||||
for(int i=0; i<faces; i++)
|
||||
for(int j: sides[i])
|
||||
hardness[i] = min(hardness[i], hardness[j]+1);
|
||||
}
|
||||
};
|
||||
|
||||
die_structure d20(5, {
|
||||
{13-1, 7-1, 19-1}, {20-1, 12-1, 18-1}, {19-1, 17-1, 16-1}, {14-1, 18-1, 11-1}, {13-1, 18-1, 15-1},
|
||||
{14-1, 9-1, 16-1}, { 1-1, 15-1, 17-1}, {20-1, 16-1, 10-1}, {19-1, 6-1, 11-1}, { 8-1, 17-1, 12-1},
|
||||
{13-1, 9-1, 4-1}, { 2-1, 10-1, 15-1}, { 1-1, 11-1, 5-1}, {20-1, 4-1, 6-1}, { 7-1, 5-1, 12-1},
|
||||
{ 8-1, 6-1, 3-1}, { 7-1, 10-1, 3-1}, { 2-1, 5-1, 4-1}, { 1-1, 3-1, 9-1}, { 8-1, 2-1, 14-1}
|
||||
});
|
||||
|
||||
die_structure d8(4, {
|
||||
{1, 3, 5}, {0, 4, 2}, {3, 1, 7}, {2, 6, 0}, {5, 7, 1}, {4, 0, 6}, {7, 5, 3}, {6, 2, 4}
|
||||
});
|
||||
|
||||
die_structure d4(3, {{3,2,1}, {3,0,2}, {1,0,3}, {0,1,2}});
|
||||
|
||||
#if HDR
|
||||
struct die_data {
|
||||
struct die_structure *which;
|
||||
int val;
|
||||
int dir;
|
||||
int happy();
|
||||
};
|
||||
#endif
|
||||
|
||||
vector<vector<int>> spins;
|
||||
int order;
|
||||
|
||||
int faces() { return isize(sides); }
|
||||
|
||||
EX void generate_on(cell *c) {
|
||||
c->wparam = hrand(faces()) + faces() * (1 + hrand(3) * 2);
|
||||
int die_data::happy() {
|
||||
if(val == which->faces-1) return 1;
|
||||
if(val == 0) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool prepared;
|
||||
|
||||
void prepare() {
|
||||
if(prepared) return;
|
||||
prepared = true;
|
||||
spins = sides;
|
||||
order = faces() == 8 ? 4 : 5;
|
||||
for(int i=0; i<faces(); i++)
|
||||
for(int j=0; j<isize(sides[i]); j++) {
|
||||
int i1 = sides[i][j];
|
||||
spins[i][j] = -1;
|
||||
for(int k=0; k<isize(sides[i1]); k++)
|
||||
if(sides[i1][k] == i)
|
||||
spins[i][j] = k;
|
||||
if(spins[i][j] == -1)
|
||||
println(hlog, "asymmetric");
|
||||
}
|
||||
EX map<cell*, die_data> data;
|
||||
|
||||
EX void generate_random(cell *c) {
|
||||
auto& dd = data[c];
|
||||
dd.which = pick(&d4, &d8, &d20);
|
||||
dd.val = hrand(dd.which->faces);
|
||||
dd.dir = 1 + hrand(3) * 2;
|
||||
}
|
||||
|
||||
EX void generate_specific(cell *c, die_structure *ds, int min_hardness, int max_hardness) {
|
||||
auto& dd = data[c];
|
||||
dd.which = ds;
|
||||
dd.dir = 1 + hrand(3) * 2;
|
||||
vector<int> sides;
|
||||
for(int i=0; i<ds->faces; i++)
|
||||
if(ds->hardness[i] >= min_hardness && ds->hardness[i] <= max_hardness)
|
||||
sides.push_back(i);
|
||||
dd.val = sides[hrand(isize(sides))];
|
||||
}
|
||||
|
||||
EX void roll(movei mi) {
|
||||
prepare();
|
||||
EX void generate_full(cell *c, int hard) {
|
||||
int pct = hrand(100);
|
||||
int pct2 = hrand(4000);
|
||||
if(pct < 1) {
|
||||
c->wall = waBlandDie;
|
||||
generate_specific(c, &d4, 0, 99);
|
||||
}
|
||||
else if(pct < 3) {
|
||||
c->wall = waBlandDie;
|
||||
generate_specific(c, &d8, 0, 1);
|
||||
}
|
||||
else if(pct < 5) {
|
||||
c->wall = waBlandDie;
|
||||
generate_specific(c, &d20, 0, 1);
|
||||
}
|
||||
else if(pct < 9) {
|
||||
c->wall = waRichDie;
|
||||
generate_specific(c, &d20, 4, 5);
|
||||
}
|
||||
else if(pct < 10) {
|
||||
c->wall = waRichDie;
|
||||
generate_specific(c, &d8, 2, 3);
|
||||
}
|
||||
else if(pct2 < 1) {
|
||||
c->monst = moAnimatedDie;
|
||||
generate_specific(c, &d4, 0, 99);
|
||||
}
|
||||
else if(pct2 < 40) {
|
||||
c->monst = moAnimatedDie;
|
||||
generate_specific(c, &d8, 0, 99);
|
||||
}
|
||||
else if(pct2 < 40 + hard) {
|
||||
c->monst = moAnimatedDie;
|
||||
generate_specific(c, &d20, 0, 99);
|
||||
}
|
||||
}
|
||||
|
||||
EX die_data roll_effect(movei mi, die_data dd) {
|
||||
auto &cto = mi.t;
|
||||
auto &th = mi.s;
|
||||
|
||||
int rdir = mi.dir_force();
|
||||
int t = th->type;
|
||||
|
||||
int val = th->wparam % faces();
|
||||
int dir = th->wparam / faces();
|
||||
int val = dd.val;
|
||||
int dir = dd.dir;
|
||||
|
||||
int si = isize(sides[val]);
|
||||
auto& dw = dd.which;
|
||||
|
||||
if(t % si) { println(hlog, "error: bad roll\n"); return; }
|
||||
int si = isize(dw->sides[val]);
|
||||
|
||||
if(t % si) { println(hlog, "error: bad roll\n"); return dd; }
|
||||
|
||||
int sideid = (rdir - dir) * si / t;
|
||||
if(sideid < 0) sideid += si;
|
||||
|
||||
int val1 = sides[val][sideid];
|
||||
int val1 = dw->sides[val][sideid];
|
||||
|
||||
int si1 = isize(sides[val1]);
|
||||
int si1 = isize(dw->sides[val1]);
|
||||
|
||||
println(hlog, tie(val, si, rdir), " to ", tie(val1, si1));
|
||||
|
||||
int sideid1 = spins[val][sideid];
|
||||
int sideid1 = dw->spins[val][sideid];
|
||||
|
||||
int t1 = cto->type;
|
||||
if(t1 % si1) { println(hlog, "error: bad roll target\n"); return; }
|
||||
if(t1 % si1) { println(hlog, "error: bad roll target\n"); return dd; }
|
||||
|
||||
int rdir1 = mi.rev_dir_force();
|
||||
|
||||
@ -978,30 +1053,70 @@ EX namespace dice {
|
||||
|
||||
dir1 = gmod(dir1, t1);
|
||||
|
||||
th->wall = waNone;
|
||||
cto->wall = waDie;
|
||||
cto->wparam = val1 + faces() * dir1;
|
||||
dd.val = val1;
|
||||
dd.dir = dir1;
|
||||
return dd;
|
||||
}
|
||||
|
||||
EX void roll(movei mi) {
|
||||
auto &cto = mi.t;
|
||||
auto &th = mi.s;
|
||||
|
||||
changes.map_value(data, cto);
|
||||
changes.map_value(data, th);
|
||||
data[cto] = roll_effect(mi, data[th]);
|
||||
data.erase(th);
|
||||
}
|
||||
|
||||
EX void draw_die(cell *c, const shiftmatrix& V) {
|
||||
prepare();
|
||||
int val = c->wparam % faces();
|
||||
int dir = c->wparam / faces();
|
||||
queuestr(V, .5, its(val+1), 0xFFFFFFFF);
|
||||
auto& side = sides[val];
|
||||
int si = isize(side);
|
||||
EX void draw_die(cell *c, const shiftmatrix& V, ld scale, color_t color) {
|
||||
if(!data.count(c)) {
|
||||
queuepoly(V, cgi.shAsymmetric, 0xFF0000FF);
|
||||
return;
|
||||
}
|
||||
|
||||
eGeometry orig = geometry;
|
||||
bool fpp = GDIM == 3;
|
||||
|
||||
auto& dd = data[c];
|
||||
int val = dd.val;
|
||||
int dir = dd.dir;
|
||||
auto& dw = dd.which;
|
||||
|
||||
for(int i=0; i<si; i++) {
|
||||
int d = dir + c->type * i / isize(side);
|
||||
d = gmod(d, c->type);
|
||||
hyperpoint nxt = tC0(currentmap->adj(c, d));
|
||||
hyperpoint mid = normalize(C0 * 1.3 + nxt * -.3);
|
||||
queuestr(V * rgpushxto0(mid), .25, its(side[i]+1), 0xFFFFFFFF);
|
||||
auto& side = dw->sides[val];
|
||||
int si = isize(side);
|
||||
|
||||
if(c == lmouseover_distant) {
|
||||
set<cell*> visited;
|
||||
struct celldata_t {
|
||||
cell* c;
|
||||
die_data dd;
|
||||
shiftmatrix V;
|
||||
};
|
||||
vector<celldata_t> data;
|
||||
auto visit = [&] (cell *c, die_data dd, shiftmatrix V) {
|
||||
if(visited.count(c)) return;
|
||||
visited.insert(c);
|
||||
data.emplace_back(celldata_t{c, dd, V});
|
||||
};
|
||||
visit(c, dd, V);
|
||||
for(int i=0; i<isize(data); i++) {
|
||||
auto dat = data[i];
|
||||
queuestr(fpp ? dat.V * zpush(cgi.FLOOR) : dat.V, .5, its(dat.dd.val+1), 0xFF8000FF);
|
||||
if(i <= 22)
|
||||
forCellIdEx(c2, id, dat.c) if(!ctof(c2) && !visited.count(c2)) {
|
||||
auto re = roll_effect(movei(dat.c, id), dat.dd);
|
||||
shiftmatrix V2 = dat.V * currentmap->adj(dat.c, id);
|
||||
gridline(dat.V, C0, V2, C0, 0xFF800080, 0);
|
||||
visit(c2, re, V2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
shiftmatrix V1 = V * iddspin(c, dir) * spin(M_PI);
|
||||
shiftmatrix V1 = V * ddspin(c, dir) * spin(M_PI);
|
||||
|
||||
vector<bool> face_drawn(faces(), false);
|
||||
// loop:
|
||||
|
||||
vector<bool> face_drawn(dd.which->faces, false);
|
||||
|
||||
vector<pair<transmatrix, int> > facequeue;
|
||||
|
||||
@ -1011,46 +1126,64 @@ EX namespace dice {
|
||||
facequeue.emplace_back(T, d);
|
||||
};
|
||||
|
||||
add_to_queue(Id, val);
|
||||
|
||||
transmatrix S = Id;
|
||||
|
||||
ld outradius, inradius;
|
||||
|
||||
if(1) {
|
||||
dynamicval<eGeometry> g(geometry, gSphere);
|
||||
ld alpha = 360 * degree / order;
|
||||
ld alpha = 360 * degree / dw->order;
|
||||
inradius = edge_of_triangle_with_angles(alpha, 60*degree, 60*degree);
|
||||
outradius = edge_of_triangle_with_angles(60*degree, alpha, 60*degree);
|
||||
}
|
||||
|
||||
ld dieradius = 0.5;
|
||||
hyperpoint shift = inverse_shift(V1, tC0(die_target));
|
||||
hyperpoint log_shift = inverse_exp(shiftless(shift)) * (inradius / cgi.hexhexdist);
|
||||
|
||||
if(1) {
|
||||
dynamicval<eGeometry> g(geometry, gSphere);
|
||||
hyperpoint de = direct_exp(log_shift);
|
||||
S = rgpushxto0(de);
|
||||
if(GDIM == 3) {
|
||||
for(int i=0; i<4; i++) swap(S[i][2], S[i][3]);
|
||||
for(int i=0; i<4; i++) swap(S[2][i], S[3][i]);
|
||||
}
|
||||
for(int i=0; i<4; i++) S[i][1] *= -1;
|
||||
}
|
||||
|
||||
add_to_queue(S, val);
|
||||
|
||||
ld dieradius = scale / 2;
|
||||
|
||||
if(dw->faces == 20) dieradius /= 1.3;
|
||||
if(dw->faces == 8) dieradius /= 1.15;
|
||||
|
||||
ld base_to_base;
|
||||
|
||||
if(1) {
|
||||
dynamicval<eGeometry> g(geometry, gSpace534);
|
||||
hyperpoint h = cspin(2, 0, outradius) * zpush0(-dieradius);
|
||||
hyperpoint h = cspin(2, 0, M_PI-outradius) * zpush0(-dieradius);
|
||||
base_to_base = binsearch(-5, 5, [h] (ld d) {
|
||||
return (zpush(d) * h)[2] >= sin_auto(vid.depth);
|
||||
});
|
||||
// ld base_to_base = cspin(2, 0, outradius) * zpush0(-dieradius);
|
||||
}
|
||||
|
||||
vector<pair<ld, int> > ordering;
|
||||
|
||||
for(int i=0; i<faces(); i++) {
|
||||
for(int i=0; i<dw->faces; i++) {
|
||||
|
||||
transmatrix T = facequeue[i].first;
|
||||
int ws = facequeue[i].second;
|
||||
|
||||
for(int d=0; d<si; d++) {
|
||||
dynamicval<eGeometry> g(geometry, gSpace534);
|
||||
add_to_queue(T * cspin(0, 1, 2*M_PI*d/si) * cspin(2, 0, inradius) * cspin(0, 1, M_PI-2*M_PI*spins[ws][d]/si), sides[ws][d]);
|
||||
add_to_queue(T * cspin(0, 1, 2*M_PI*d/si) * cspin(2, 0, inradius) * cspin(0, 1, M_PI-2*M_PI*dw->spins[ws][d]/si), dw->sides[ws][d]);
|
||||
}
|
||||
|
||||
if(1) {
|
||||
dynamicval<eGeometry> g(geometry, gSpace534);
|
||||
hyperpoint h = zpush(base_to_base) * T * zpush0(dieradius);
|
||||
ld z = asin_auto(h[2]);
|
||||
ld z = fpp ? hdist0(h) : asin_auto(h[2]);
|
||||
ordering.emplace_back(-z, i);
|
||||
}
|
||||
}
|
||||
@ -1061,22 +1194,49 @@ EX namespace dice {
|
||||
int i = o.second;
|
||||
transmatrix T = facequeue[i].first;
|
||||
|
||||
transmatrix face;
|
||||
|
||||
hyperpoint sum = zpush(base_to_base) * C0 * -3;
|
||||
|
||||
auto sphere_to_space = [&] (hyperpoint h) {
|
||||
if(fpp) return h;
|
||||
ld z = asin_auto(h[2]);
|
||||
h /= cos_auto(z);
|
||||
h[2] = h[3]; h[3] = 0;
|
||||
dynamicval<eGeometry> g(geometry, orig);
|
||||
return zshift(h, geom3::scale_at_lev(z));
|
||||
};
|
||||
|
||||
for(int d=0; d<=si; d++) {
|
||||
hyperpoint h;
|
||||
ld z = 0;
|
||||
hyperpoint h, hs;
|
||||
if(1) {
|
||||
dynamicval<eGeometry> g(geometry, gSpace534);
|
||||
h = zpush(base_to_base) * T * cspin(0, 1, 2*M_PI*(d+.5)/si) * cspin(2, 0, outradius) * zpush0(dieradius);
|
||||
z = asin_auto(h[2]);
|
||||
h /= cos_auto(z);
|
||||
set_column(face, d, h);
|
||||
sum += h;
|
||||
hs = sphere_to_space(h);
|
||||
}
|
||||
h[2] = h[3]; h[3] = 0;
|
||||
h = zshift(h, geom3::scale_at_lev(z));
|
||||
curvepoint(h);
|
||||
curvepoint(hs);
|
||||
}
|
||||
queuecurve(V1, 0xFFFFFFFF, 0x40A040FF, PPR::WALL);
|
||||
}
|
||||
|
||||
set_column(face, 3, sum);
|
||||
|
||||
queuecurve(V1, 0xFFFFFFFF, color & 0xFFFFFF9F, PPR::WALL);
|
||||
|
||||
pointfunction pf = [&] (ld x, ld y) {
|
||||
hyperpoint hs;
|
||||
dynamicval<eGeometry> g(geometry, gSpace534);
|
||||
return sphere_to_space(normalize(face * hyperpoint(1/3. -y/2 -x, 1/3. + y, 1/3. -y/2 +x, 1e-2)));
|
||||
};
|
||||
|
||||
int fid = dw->faces - facequeue[i].second;
|
||||
if(dw->faces == 4) fid = facequeue[i].second + 1;
|
||||
string s;
|
||||
if(fid == 6) s = "6.";
|
||||
else if(fid == 9) s = "9.";
|
||||
else s = its(fid);
|
||||
write_in_space(V1, max_glfont_size, dw->faces < 10 ? -1.2 : -.75, s, 0xFFFFFFFF, 0, 8, PPR::WALL, pf);
|
||||
}
|
||||
}
|
||||
|
||||
EX }
|
||||
|
17
content.cpp
17
content.cpp
@ -1700,11 +1700,20 @@ LAND(0xC0C0FF, "Land of Dice", laDice, 0, itCursed, RESERVED,
|
||||
ITEM('/', 0xD0D0D8, "Crystal Die", itDice, IC_TREASURE, ZERO, RESERVED, osNone,
|
||||
"A nice souvenir from the Land of Dice. Make sure to collect the whole set!")
|
||||
|
||||
WALL('d', 0x181818, "Rollable Die", waDie, WF_WALL | WF_PUSHABLE, RESERVED, 0, sgNone, NODESC)
|
||||
|
||||
WALL('d', 0x181818, "Rollable Die", waDie1, ZERO, RESERVED, 0, sgNone, NODESC)
|
||||
WALL('d', 0x181818, "Rollable Die", waDie2, ZERO, RESERVED, 0, sgNone, NODESC)
|
||||
WALL('d', 0x7F6A10, "Unhappy Die", waRichDie, WF_WALL | WF_PUSHABLE, RESERVED, 0, sgNone,
|
||||
"Sentent dice like to be in a position such that their highest number is on top, or somewhere close. "
|
||||
"Unfortunately, someone has rolled this one into a wrong position, and did not fix this. "
|
||||
"It will reward you if you roll it so that the highest number is on top again!")
|
||||
WALL('d', 0x106010, "Happy Die", waBlandDie, WF_WALL | WF_PUSHABLE, RESERVED, 0, sgNone,
|
||||
"A happy sentent die. You can roll it.")
|
||||
|
||||
MONSTER('d', 0x603010, "Animated Die", moAnimatedDie, ZERO, RESERVED, moHexDemon,
|
||||
"When sentient dice are too long in an incorrect position, they start to move on their own, "
|
||||
"and attack everyone. You can still convince Animated Dice of your good intentions by "
|
||||
"rolling them into a position such that the highest number is on top. "
|
||||
"If you do, the die will stop moving and (if it happens in the Land of Dice) you will be rewarded. "
|
||||
"Other rolls and attacks are not allowed."
|
||||
)
|
||||
|
||||
//shmupspecials
|
||||
MONSTER( '@', 0xC0C0C0, "Rogue", moPlayer, CF_FACE_UP | CF_PLAYER, RESERVED, moNone, "In the Shoot'em Up mode, you are armed with thrown Knives.")
|
||||
|
@ -481,6 +481,7 @@ EX void bfs() {
|
||||
else if(isMagneticPole(c2->monst)) havewhat |= HF_MAGNET;
|
||||
else if(c2->monst == moAltDemon) havewhat |= HF_ALT;
|
||||
else if(c2->monst == moHexDemon) havewhat |= HF_HEXD;
|
||||
else if(c2->monst == moAnimatedDie) havewhat |= HF_HEXD;
|
||||
else if(c2->monst == moMonk) havewhat |= HF_MONK;
|
||||
else if(c2->monst == moShark || c2->monst == moCShark || among(c2->monst, moRusalka, moPike)) havewhat |= HF_SHARK;
|
||||
else if(c2->monst == moAirElemental)
|
||||
|
20
game.cpp
20
game.cpp
@ -379,8 +379,22 @@ EX void pushThumper(const movei& mi) {
|
||||
cto->wall = waCrateOnTarget;
|
||||
th->wall = waCrateTarget;
|
||||
}
|
||||
else if(w == waDie)
|
||||
dice::roll(mi);
|
||||
else if(among(w, waRichDie, waBlandDie)) {
|
||||
th->wall = waNone;
|
||||
cto->wall = w;
|
||||
animateMovement(mi, LAYER_BOAT);
|
||||
dice::roll(mi);
|
||||
if(w == waRichDie && dice::data[cto].happy() > 0) {
|
||||
cto->wall = waBlandDie;
|
||||
if(cto->land == laDice && th->land == laDice) {
|
||||
items[itDice]++;
|
||||
addMessage(XLAT("The die is now happy, and you are rewarded!"));
|
||||
}
|
||||
else {
|
||||
addMessage(XLAT("The die is now happy, but won't reward you outside of the Land of Dice!"));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
cto->wall = w;
|
||||
if(explode) cto->wall = waFireTrap, cto->wparam = explode;
|
||||
@ -389,7 +403,7 @@ EX void pushThumper(const movei& mi) {
|
||||
}
|
||||
|
||||
EX bool canPushThumperOn(cell *tgt, cell *thumper, cell *player) {
|
||||
if(thumper->wall == waDie && tgt->type == 7)
|
||||
if(among(thumper->wall, waRichDie, waBlandDie) && ctof(tgt))
|
||||
return false;
|
||||
if(tgt->wall == waBoat || tgt->wall == waStrandedBoat) return false;
|
||||
if(isReptile(tgt->wall)) return false;
|
||||
|
21
graph.cpp
21
graph.cpp
@ -814,7 +814,7 @@ EX bool drawItemType(eItem it, cell *c, const shiftmatrix& V, color_t icol, int
|
||||
(it == itBombEgg || it == itTrollEgg) ? &cgi.shEgg :
|
||||
it == itFrog ? &cgi.shDisk :
|
||||
it == itHunting ? &cgi.shTriangle :
|
||||
it == itDodeca ? &cgi.shDodeca :
|
||||
(it == itDodeca || it == itDice) ? &cgi.shDodeca :
|
||||
xch == '*' ? &cgi.shGem[ct6] :
|
||||
xch == '(' ? &cgi.shKnife :
|
||||
it == itShard ? &cgi.shMFloor.b[0] :
|
||||
@ -2251,7 +2251,15 @@ EX bool drawMonsterType(eMonster m, cell *where, const shiftmatrix& V1, color_t
|
||||
queuepoly(V, cgi.shAsteroid[1], darkena(col, 0, 0xFF));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
case moAnimatedDie: {
|
||||
if(where)
|
||||
dice::draw_die(where, V, 1, darkena(col, 0, 0xFF));
|
||||
else
|
||||
queuepoly(V, cgi.shDodeca, darkena(col, 0, 0xFF));
|
||||
return true;
|
||||
}
|
||||
|
||||
default: ;
|
||||
}
|
||||
|
||||
@ -2518,6 +2526,8 @@ void drawWormSegments() {
|
||||
|
||||
EX bool dont_face_pc = false;
|
||||
|
||||
EX shiftmatrix die_target;
|
||||
|
||||
EX bool drawMonster(const shiftmatrix& Vparam, int ct, cell *c, color_t col, color_t asciicol) {
|
||||
#if CAP_SHAPES
|
||||
|
||||
@ -2876,6 +2886,13 @@ EX bool drawMonster(const shiftmatrix& Vparam, int ct, cell *c, color_t col, col
|
||||
// golems, knights, and hyperbugs don't face the player (mondir-controlled)
|
||||
// also whatever in the lineview mode, and whatever in the quotient geometry
|
||||
|
||||
else if(c->monst == moAnimatedDie) {
|
||||
transmatrix U = inverse_shift(Vparam, Vs);
|
||||
U = rgpushxto0(tC0(U));
|
||||
die_target = Vparam;
|
||||
res = res && drawMonsterTypeDH(m, c, Vparam * U, col, darkhistory, footphase, asciicol);
|
||||
}
|
||||
|
||||
else if((hasFacing(c) && c->mondir != NODIR) || history::on || quotient || dont_face_pc) {
|
||||
if(c->monst == moKrakenH) Vs = Vb, nospins = nospinb;
|
||||
if(!nospins && c->mondir < c->type) Vs = Vs * ddspin(c, c->mondir, M_PI);
|
||||
|
12
landgen.cpp
12
landgen.cpp
@ -2586,16 +2586,8 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
||||
}
|
||||
|
||||
case laDice: {
|
||||
if(fargen) {
|
||||
int pct = hrand(100);
|
||||
if(pct < 10)
|
||||
c->wall = waDie;
|
||||
// c->wall = pick(waNone, waNone, waStone, waNone, waNone, waStone, waNone, waNone, waStone, waBigStatue, waCrateCrate, waDie);
|
||||
if(c->wall == waDie) {
|
||||
if(ctof(c)) c->wall = waNone;
|
||||
else dice::generate_on(c);
|
||||
}
|
||||
}
|
||||
if(fargen && !ctof(c))
|
||||
dice::generate_full(c, items[itDice] + yendor::hardness());
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -102,6 +102,9 @@ EX void moveEffect(const movei& mi, eMonster m) {
|
||||
animateMovement(mi.rev(), LAYER_BOAT);
|
||||
tortoise::move_baby(cf, ct);
|
||||
}
|
||||
|
||||
if(m == moAnimatedDie && mi.proper())
|
||||
dice::roll(mi);
|
||||
}
|
||||
|
||||
EX void moveMonster(const movei& mi) {
|
||||
@ -1086,6 +1089,11 @@ EX void groupmove2(const movei& mi, eMonster movtype, flagtype mf) {
|
||||
}
|
||||
}
|
||||
else return;
|
||||
|
||||
if(c->monst == moAnimatedDie) {
|
||||
forCellEx(c3, from) if(c3 != c && c3->monst == moAnimatedDie)
|
||||
return;
|
||||
}
|
||||
|
||||
if(from->monst) {
|
||||
if(mf & MF_MOUNT) {
|
||||
|
4
orbs.cpp
4
orbs.cpp
@ -808,6 +808,8 @@ EX eMonster summonedAt(cell *dest) {
|
||||
return moMiner;
|
||||
if(dest->wall == waMineOpen || dest->wall == waMineMine || dest->wall == waMineUnknown)
|
||||
return moBomberbird;
|
||||
if(dest->wall == waRichDie)
|
||||
return moAnimatedDie;
|
||||
if(dest->wall == waTrapdoor)
|
||||
return dest->land == laPalace ? moFatGuard : moOrangeDog;
|
||||
if(dest->land == laFrog && dest->wall == waNone) {
|
||||
@ -906,6 +908,8 @@ void summonAt(cell *dest) {
|
||||
dest->stuntime = 3;
|
||||
if(dest->monst == moPirate || dest->monst == moViking || (dest->monst == moRatling && dest->wall == waSea))
|
||||
dest->wall = waBoat, dest->item = itNone;
|
||||
if(dest->monst == moAnimatedDie)
|
||||
dest->wall = waNone;
|
||||
if(dest->monst == moViking && dest->land == laKraken)
|
||||
dest->item = itOrbFish;
|
||||
if(dest->wall == waStrandedBoat)
|
||||
|
14
pcmove.cpp
14
pcmove.cpp
@ -628,6 +628,18 @@ bool pcmove::actual_move() {
|
||||
activateActiv(c2, true);
|
||||
return after_instant(false);
|
||||
}
|
||||
|
||||
if(c2->monst == moAnimatedDie) {
|
||||
mip = determinePush(cwt, subdir, [c2] (cell *c) { return canPushThumperOn(c, c2, cwt.at); });
|
||||
if(mip.proper()) {
|
||||
auto tgt = roll_effect(mip, dice::data[c2]);
|
||||
if(tgt.happy() > 0) {
|
||||
changes.ccell(c2);
|
||||
c2->monst = moNone;
|
||||
c2->wall = waRichDie;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(isPushable(c2->wall) && !c2->monst && !nonAdjacentPlayer(c2, cwt.at) && fmsMove) {
|
||||
mip = determinePush(cwt, subdir, [c2] (cell *c) { return canPushThumperOn(c, c2, cwt.at); });
|
||||
@ -745,6 +757,8 @@ void pcmove::tell_why_cannot_attack() {
|
||||
addMessage(XLAT("You cannot attack Raiders directly!"));
|
||||
else if(isSwitch(c2->monst))
|
||||
addMessage(XLAT("You cannot attack Jellies in their wall form!"));
|
||||
else if(c2->monst == moAnimatedDie)
|
||||
addMessage(XLAT("You can only push this die if the highest number would be on the top!"));
|
||||
else
|
||||
addMessage(XLAT("For some reason... cannot attack!"));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user