mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-12-19 15:20:27 +00:00
Merge pull request #303 from lottieratworld/main
Extra canvas-specific options + extra animation options
This commit is contained in:
commit
bcc7c9c646
@ -1057,8 +1057,59 @@ void celldrawer::draw_mirrorwall() {
|
||||
}
|
||||
}
|
||||
|
||||
EX int canvasfloor;
|
||||
|
||||
void celldrawer::set_land_floor(const shiftmatrix& Vf) {
|
||||
switch(c->land) {
|
||||
case laCanvas:
|
||||
switch(canvasfloor) {
|
||||
case caflM: set_floor(cgi.shMFloor); break;
|
||||
case caflFull: set_floor(cgi.shFullFloor); break;
|
||||
// case caflWarp is warped floor
|
||||
case caflStar: set_floor(cgi.shStarFloor); break;
|
||||
case caflCloud: set_floor(cgi.shCloudFloor); break;
|
||||
case caflCross: set_floor(cgi.shCrossFloor); break;
|
||||
case caflCharged: set_floor(cgi.shChargedFloor); break;
|
||||
case caflSStar: set_floor(cgi.shSStarFloor); break;
|
||||
case caflOver: set_floor(cgi.shOverFloor); break;
|
||||
case caflTri: set_floor(cgi.shTriFloor); break;
|
||||
case caflFeather: set_floor(cgi.shFeatherFloor); break;
|
||||
case caflBarrow: set_floor(cgi.shBarrowFloor); break;
|
||||
case caflNew: set_floor(cgi.shNewFloor); break;
|
||||
case caflTroll: set_floor(cgi.shTrollFloor); break;
|
||||
case caflButterfly: set_floor(cgi.shButterflyFloor); break;
|
||||
case caflLava: set_floor(cgi.shLavaFloor); break;
|
||||
case caflPalace: set_floor(cgi.shPalaceFloor); break;
|
||||
case caflDemon: set_floor(cgi.shDemonFloor); break;
|
||||
case caflCave: set_floor(cgi.shCaveFloor); break;
|
||||
case caflDesert: set_floor(cgi.shDesertFloor); break;
|
||||
case caflPower: set_floor(cgi.shPowerFloor); break;
|
||||
case caflRose: set_floor(cgi.shRoseFloor); break;
|
||||
case caflTurtle: set_floor(cgi.shTurtleFloor); break;
|
||||
case caflDragon: set_floor(cgi.shDragonFloor); break;
|
||||
case caflReptile: set_reptile_floor(V, fcol); break;
|
||||
case caflHive:
|
||||
if(c->wall != waFloorB && c->wall != waFloorA && c->wall != waMirror && c->wall != waCloud && !chasmgraph(c)) {
|
||||
set_floor(cgi.shFloor);
|
||||
if(GDIM == 2) {
|
||||
draw_floorshape(c, V, cgi.shMFloor, darkena(fcol, fd + 1, 0xFF), PPR::FLOORa);
|
||||
draw_floorshape(c, V, cgi.shMFloor2, darkena(fcol, fcol==uint(c->landparam) ? fd : fd + 1, 0xFF), PPR::FLOORb);
|
||||
}
|
||||
}
|
||||
else
|
||||
set_floor(cgi.shFloor);
|
||||
break;
|
||||
case caflSwitch:
|
||||
set_floor(cgi.shSwitchFloor);
|
||||
if(!chasmgraph(c) && ctof(c) && STDVAR && !arcm::in() && !bt::in() && GDIM == 2) for(int i=0; i<c->type; i++)
|
||||
queuepoly(Vf * ddspin(c, i, M_PI/S7) * xpush(cgi.rhexf), cgi.shSwitchDisk, darkena(fcol, fd, 0xFF));
|
||||
break;
|
||||
case caflTower: set_towerfloor(celldist); break;
|
||||
case caflNone: default:
|
||||
set_floor(cgi.shFloor); break;
|
||||
}
|
||||
break;
|
||||
|
||||
case laPrairie:
|
||||
case laAlchemist:
|
||||
set_floor(cgi.shCloudFloor);
|
||||
@ -2466,7 +2517,7 @@ void celldrawer::add_map_effects() {
|
||||
for(int t=0; t<c->type; t++) if(c->move(t)) {
|
||||
if(c->move(t)->ligon) {
|
||||
int lcol = darkena(gradient(iinf[itOrbLightning].color, 0, 0, tim, 1100), 0, 0xFF);
|
||||
queueline(V*chei(xspinpush(ticks * M_PI / cgi.S42, cgi.hexf/2), rand() % 1000, 1000) * C0, V*chei(currentmap->adj(c, t), rand() % 1000, 1000) * C0, lcol, 2 + vid.linequality);
|
||||
queueline(V*chei(xspinpush((vid.flasheffects ? ticks : ptick(8)) * M_PI / cgi.S42, cgi.hexf/2), rand() % 1000, 1000) * C0, V*chei(currentmap->adj(c, t), rand() % 1000, 1000) * C0, lcol, 2 + vid.linequality);
|
||||
}
|
||||
for(int u: {-1, 1}) {
|
||||
cellwalker cw = cellwalker(c, t) + wstep + u;
|
||||
@ -2474,7 +2525,7 @@ void celldrawer::add_map_effects() {
|
||||
cell *c2 = cw.peek();
|
||||
if(c2 && c2->ligon) {
|
||||
int lcol = darkena(gradient(iinf[itOrbLightning].color, 0, 0, tim, 1100), 0, 0xFF);
|
||||
queueline(V*chei(xspinpush(ticks * M_PI / cgi.S42, cgi.hexf/2), rand() % 1000, 1000) * C0, V*chei(currentmap->adj(c, t)*currentmap->adj(cw.at, cw.spin), rand() % 1000, 1000) * C0, lcol, 2 + vid.linequality);
|
||||
queueline(V*chei(xspinpush((vid.flasheffects ? ticks : ptick(8)) * M_PI / cgi.S42, cgi.hexf/2), rand() % 1000, 1000) * C0, V*chei(currentmap->adj(c, t)*currentmap->adj(cw.at, cw.spin), rand() % 1000, 1000) * C0, lcol, 2 + vid.linequality);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
12
classes.cpp
12
classes.cpp
@ -626,6 +626,11 @@ EX walltype winf[walltypes] = {
|
||||
// -- land types ---
|
||||
|
||||
#if HDR
|
||||
enum eCanvasFloor { caflNone, caflM, caflFull, caflWarp, caflStar, caflCloud, caflCross, caflCharged,
|
||||
caflSStar, caflOver, caflTri, caflFeather, caflBarrow, caflNew, caflTroll, caflButterfly, caflLava,
|
||||
caflPalace, caflDemon, caflCave, caflDesert, caflPower, caflRose, caflTurtle, caflDragon, caflReptile,
|
||||
caflHive, caflSwitch, caflTower, caflEND };
|
||||
|
||||
static const flagtype LF_GENERATE_ALL = Flag(0);
|
||||
static const flagtype LF_ICY = Flag(1);
|
||||
static const flagtype LF_GRAVITY = Flag(2);
|
||||
@ -661,6 +666,13 @@ enum eLand {
|
||||
extern color_t floorcolors[landtypes];
|
||||
#endif
|
||||
|
||||
EX const char *canvasFloorNames[caflEND] = {
|
||||
"default", "smaller", "full", "warped", "star", "cloud", "cross", "charged",
|
||||
"saloon", "overgrown", "triangle", "feather", "barrow", "elemental", "troll", "butterfly", "lava",
|
||||
"palace", "demon", "cave", "desert", "power", "rose", "turtle", "dragon", "reptile",
|
||||
"hive", "jelly", "tower"
|
||||
};
|
||||
|
||||
EX const landtype linf[landtypes] = {
|
||||
#define LAND(a,b,c,d,e,f,g) {a,b,d,e,g},
|
||||
#include "content.cpp"
|
||||
|
15
config.cpp
15
config.cpp
@ -719,11 +719,14 @@ EX void initConfig() {
|
||||
addsaver(fat_edges, "fat-edges");
|
||||
param_f(vid.sspeed, "sspeed", "scrollingspeed", 0);
|
||||
param_f(vid.mspeed, "mspeed", "movement speed", 1);
|
||||
param_f(vid.ispeed, "ispeed", "idle speed", 1);
|
||||
addsaver(vid.aurastr, "aura strength", ISMOBILE ? 0 : 128);
|
||||
addsaver(vid.aurasmoothen, "aura smoothen", 5);
|
||||
param_enum(vid.graphglyph, "graphglyph", "graphical items/kills", 1)
|
||||
-> editable({{"letters", ""}, {"auto", ""}, {"images", ""}}, "inventory/kill mode", 'd');
|
||||
|
||||
addsaver(vid.flasheffects, "flasheffects", 1);
|
||||
|
||||
param_f(vid.binary_width, "bwidth", "binary-tiling-width", 1);
|
||||
param_custom(vid.binary_width, "binary tiling width", menuitem_binary_width, 'v');
|
||||
|
||||
@ -1650,6 +1653,18 @@ EX void showGraphConfig() {
|
||||
|
||||
dialog::addSelItem(XLAT("movement animation speed"), fts(vid.mspeed), 'm');
|
||||
|
||||
dialog::addSelItem(XLAT("idle animation speed"), fts(vid.ispeed), 'i');
|
||||
dialog::add_action([] {
|
||||
dialog::editNumber(vid.ispeed, 0, 4, 0.1, 1,
|
||||
XLAT("idle animation speed"),
|
||||
"0 = disable\n\nThis affects non-movement animations such as orb effects, item rotation, and more."
|
||||
);
|
||||
});
|
||||
|
||||
dialog::addBoolItem_action(XLAT("flashing effects"), (vid.flasheffects), 'h');
|
||||
if(getcstat == 'h')
|
||||
mouseovers = XLAT("Disable if you are photosensitive. Replaces flashing effects such as Orb of Storms lightning with slow, adjustable animations.");
|
||||
|
||||
dialog::addItem(XLAT("extra graphical effects"), 'u');
|
||||
|
||||
dialog::addBreak(50);
|
||||
|
50
graph.cpp
50
graph.cpp
@ -72,7 +72,7 @@ EX int animation_lcm = 0;
|
||||
|
||||
EX ld ptick(int period, ld phase IS(0)) {
|
||||
if(animation_lcm) animation_lcm = animation_lcm * (period / gcd(animation_lcm, period));
|
||||
return (ticks * animation_factor) / period + phase * 2 * M_PI;
|
||||
return (ticks * animation_factor * vid.ispeed) / period + phase * 2 * M_PI;
|
||||
}
|
||||
|
||||
EX ld fractick(int period, ld phase IS(0)) {
|
||||
@ -299,22 +299,39 @@ void drawWinter(const shiftmatrix& V, ld hdir, color_t col) {
|
||||
|
||||
void drawLightning(const shiftmatrix& V) {
|
||||
#if CAP_QUEUE
|
||||
float ds = ptick(600);
|
||||
color_t col = darkena(iinf[itOrbLightning].color, 0, 0xFF);
|
||||
for(int u=0; u<20; u++) {
|
||||
ld leng = 0.5 / (0.1 + (rand() % 100) / 100.0);
|
||||
ld rad = rand() % 1000;
|
||||
ld leng, rad;
|
||||
if(vid.flasheffects) {
|
||||
leng = 0.5 / (0.1 + (rand() % 100) / 100.0);
|
||||
rad = rand() % 1000;
|
||||
}
|
||||
else {
|
||||
if(u % 5) leng = 1.25 + sintick(200, ld(u) * 1.25) * 0.25;
|
||||
else leng = 2 + sintick(200, ld(u) * 1.25);
|
||||
rad = (u + ds) * (M_PI / 10);
|
||||
}
|
||||
shiftmatrix V1 = chei(V, u, 20);
|
||||
queueline(V1*xspinpush0(rad, cgi.hexf*0.3), V1*xspinpush0(rad, cgi.hexf*leng), col, 2 + vid.linequality);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void drawCurse(const shiftmatrix& V, color_t col) {
|
||||
void drawCurse(const shiftmatrix& V, eItem it) {
|
||||
#if CAP_QUEUE
|
||||
col = darkena(col, 0, 0xFF);
|
||||
float ds = ptick(450) + (it * 5.5); // Extra offset so both Gluttony and Repulsion are easily visible
|
||||
color_t col = darkena(iinf[it].color, 0, 0xFF);
|
||||
for(int u=0; u<20; u++) {
|
||||
ld leng = 0.6 + 0.3 * randd();
|
||||
ld rad = rand() % 1000;
|
||||
ld leng, rad;
|
||||
if(vid.flasheffects) {
|
||||
leng = 0.6 + 0.3 * randd();
|
||||
rad = rand() % 1000;
|
||||
}
|
||||
else {
|
||||
leng = 0.85 + sintick(150, ld(u) * 1.25) * 0.15;
|
||||
rad = (u + ds) * (M_PI / 10);
|
||||
}
|
||||
shiftmatrix V1 = chei(V, u, 20);
|
||||
queueline(V1*xspinpush0(rad, cgi.hexf*0.3), V1*xspinpush0(rad, cgi.hexf*leng), col, 2 + vid.linequality);
|
||||
}
|
||||
@ -330,8 +347,8 @@ EX void drawPlayerEffects(const shiftmatrix& V, cell *c, eMonster m) {
|
||||
if(items[itOrbShell] > (shmup::on ? 0 : ORBBASE)) drawShield(V, itOrbShell);
|
||||
|
||||
if(items[itOrbSpeed]) drawSpeed(V);
|
||||
if(items[itCurseGluttony]) drawCurse(V, iinf[itCurseGluttony].color);
|
||||
if(items[itCurseRepulsion]) drawCurse(V, iinf[itCurseRepulsion].color);
|
||||
if(items[itCurseGluttony]) drawCurse(V, itCurseGluttony);
|
||||
if(items[itCurseRepulsion]) drawCurse(V, itCurseRepulsion);
|
||||
|
||||
if(onplayer && (items[itOrbSword] || items[itOrbSword2])) {
|
||||
using namespace sword;
|
||||
@ -816,8 +833,8 @@ EX bool drawItemType(eItem it, cell *c, const shiftmatrix& V, color_t icol, int
|
||||
}
|
||||
|
||||
#if CAP_SHAPES
|
||||
auto sinptick = [c, pticks] (int period) { return c ? sintick(period) : sin(animation_factor * pticks / period);};
|
||||
auto spinptick = [c, pticks] (int period, ld phase) { return c ? spintick(period, phase) : spin((animation_factor * pticks + phase) / period); };
|
||||
auto sinptick = [c, pticks] (int period) { return c ? sintick(period) : sin(animation_factor * vid.ispeed * pticks / period);};
|
||||
auto spinptick = [c, pticks] (int period, ld phase) { return c ? spintick(period, phase) : spin((animation_factor * vid.ispeed * pticks + phase) / period); };
|
||||
int ct6 = c ? ctof(c) : 1;
|
||||
hpcshape *xsh =
|
||||
(it == itPirate || it == itKraken) ? &cgi.shPirateX :
|
||||
@ -934,7 +951,7 @@ EX bool drawItemType(eItem it, cell *c, const shiftmatrix& V, color_t icol, int
|
||||
if(GDIM == 3 && WDIM == 2) {
|
||||
ld h = cgi.human_height;
|
||||
dynamicval<qfloorinfo> qfi2(qfi, qfi);
|
||||
shiftmatrix V2 = V * spin(ticks / 1500.);
|
||||
shiftmatrix V2 = V * spin(pticks * vid.ispeed / 1500.);
|
||||
/* divisors should be higher than in plate renderer */
|
||||
qfi.fshape = &cgi.shMFloor2;
|
||||
draw_shapevec(c, V2 * zpush(-h/30), qfi.fshape->levels[0], 0xFFD500FF, PPR::WALL);
|
||||
@ -947,7 +964,7 @@ EX bool drawItemType(eItem it, cell *c, const shiftmatrix& V, color_t icol, int
|
||||
}
|
||||
else if(WDIM == 3 && c) {
|
||||
ld h = cgi.human_height;
|
||||
shiftmatrix V2 = Vit * spin(ticks / 1500.);
|
||||
shiftmatrix V2 = Vit * spin(pticks * vid.ispeed / 1500.);
|
||||
draw_floorshape(c, V2 * zpush(h/100), cgi.shMFloor3, 0xFFD500FF);
|
||||
draw_floorshape(c, V2 * zpush(h/50), cgi.shMFloor4, darkena(icol, 0, 0xFF));
|
||||
queuepoly(V2, cgi.shGem[ct6], 0xFFD500FF);
|
||||
@ -959,7 +976,7 @@ EX bool drawItemType(eItem it, cell *c, const shiftmatrix& V, color_t icol, int
|
||||
#endif
|
||||
{
|
||||
color_t hider = hidden ? 0xFFFFFF20 : 0xFFFFFFFF;
|
||||
shiftmatrix V2 = Vit * spin(ticks / 1500.);
|
||||
shiftmatrix V2 = Vit * spin(pticks * vid.ispeed / 1500.);
|
||||
draw_floorshape(c, V2, cgi.shMFloor3, 0xFFD500FF & hider);
|
||||
draw_floorshape(c, V2, cgi.shMFloor4, darkena(icol, 0, 0xFF) & hider);
|
||||
queuepoly(V2, cgi.shGem[ct6], 0xFFD500FF & hider);
|
||||
@ -3674,15 +3691,18 @@ bool allemptynear(cell *c) {
|
||||
}
|
||||
|
||||
EX bool bright;
|
||||
EX int canvasdark;
|
||||
|
||||
// how much to darken
|
||||
EX int getfd(cell *c) {
|
||||
if(bright) return 0;
|
||||
if(among(c->land, laAlchemist, laHell, laVariant, laEclectic) && WDIM == 2 && GDIM == 3) return 0;
|
||||
switch(c->land) {
|
||||
case laCanvas:
|
||||
return min(2,max(0,canvasdark));
|
||||
|
||||
case laRedRock:
|
||||
case laReptile:
|
||||
case laCanvas:
|
||||
return 0;
|
||||
|
||||
case laSnakeNest:
|
||||
|
3
hyper.h
3
hyper.h
@ -416,6 +416,9 @@ struct videopar {
|
||||
|
||||
eThreatLevel faraway_highlight; // draw attention to monsters on the horizon
|
||||
int faraway_highlight_color; // 0 = monster color, 100 = red-green oscillation
|
||||
|
||||
ld ispeed;
|
||||
bool flasheffects;
|
||||
};
|
||||
|
||||
extern videopar vid;
|
||||
|
@ -704,6 +704,8 @@ EX namespace mapstream {
|
||||
f.write(canvas_default_wall);
|
||||
f.write(mapeditor::drawplayer);
|
||||
if(patterns::whichCanvas == 'f') f.write(patterns::color_formula);
|
||||
f.write(canvasfloor);
|
||||
f.write(canvasdark);
|
||||
|
||||
{
|
||||
int i = ittypes; f.write(i);
|
||||
@ -887,6 +889,10 @@ EX namespace mapstream {
|
||||
f.read(canvas_default_wall);
|
||||
f.read(mapeditor::drawplayer);
|
||||
if(patterns::whichCanvas == 'f') f.read(patterns::color_formula);
|
||||
if(f.vernum >= 0xA90C) { // TODO Please replace this with the next version this pull request is included in
|
||||
f.read(canvasfloor);
|
||||
f.read(canvasdark);
|
||||
}
|
||||
|
||||
int i;
|
||||
f.read(i); if(i > ittypes || i < 0) throw hstream_exception();
|
||||
@ -3094,6 +3100,20 @@ EX namespace mapeditor {
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
string canvasFloorName(int id) {
|
||||
if(id>=0 && id<caflEND)
|
||||
return XLAT(canvasFloorNames[id]);
|
||||
return its(id);
|
||||
}
|
||||
string allCanvasFloorNames() {
|
||||
string ret;
|
||||
for(int i=0; i<caflEND; i++) {
|
||||
ret += its(i) + ":" + canvasFloorName(i) + " ";
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
EX void map_settings() {
|
||||
cmode = sm::SIDE | sm::MAYDARK;
|
||||
gamescreen(1);
|
||||
@ -3126,6 +3146,19 @@ EX namespace mapeditor {
|
||||
dialog::addItem(XLAT("edit cell values"), 'G');
|
||||
dialog::add_action(push_debug_screen);
|
||||
|
||||
dialog::addSelItem(XLAT("canvas floor shape"), canvasFloorName(canvasfloor), 'S');
|
||||
dialog::add_action([] {
|
||||
dialog::editNumber(canvasfloor, 0, caflEND - 1, 1, 0, XLAT("canvas floor shape"),allCanvasFloorNames());
|
||||
});
|
||||
|
||||
dialog::addSelItem(XLAT("canvas darkness"), its(canvasdark), 'd');
|
||||
dialog::add_action([] {
|
||||
dialog::editNumber(canvasdark, 0, 2, 1, 0, XLAT("canvas darkness"),
|
||||
"0: no darkening (bright mode, canvas, reptiles, etc)\n"
|
||||
"1: light darkening (r'lyeh, palace, dragon chasms, etc)\n"
|
||||
"2: normal darkening (default, most lands)");
|
||||
});
|
||||
|
||||
dialog::addBack();
|
||||
dialog::display();
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ EX eGravity get_move_gravity(cell *c, cell *c2) {
|
||||
}
|
||||
|
||||
EX bool isWarped(cell *c) {
|
||||
return isWarpedType(c->land) || (!inmirrororwall(c->land) && (items[itOrb37] && c->cpdist <= 4));
|
||||
return isWarpedType(c->land) || (c->land == laCanvas && canvasfloor == 3) || (!inmirrororwall(c->land) && (items[itOrb37] && c->cpdist <= 4));
|
||||
}
|
||||
|
||||
EX bool nonAdjacent(cell *c, cell *c2) {
|
||||
|
Loading…
Reference in New Issue
Block a user