From 64f68e636a44c9b98de285c5e672fe66244d29ec Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Sun, 22 Dec 2024 12:52:51 +0100 Subject: [PATCH] festive lights --- celldrawer.cpp | 27 +++++++++++---- geometry.cpp | 4 ++- graph.cpp | 94 +++++++++++++++++++++++++++++++++++++++++++++----- menus.cpp | 9 +++++ polygons.cpp | 7 ++++ system.cpp | 1 + 6 files changed, 127 insertions(+), 15 deletions(-) diff --git a/celldrawer.cpp b/celldrawer.cpp index 8f753ccf..c8e5c7dd 100644 --- a/celldrawer.cpp +++ b/celldrawer.cpp @@ -10,6 +10,7 @@ struct celldrawer { color_t fcol; color_t wcol; + color_t wcol_star; color_t asciicol; color_t aura_color; int fd; @@ -630,7 +631,21 @@ void celldrawer::setcolors() { if(!wmspatial && snakelevel(c) && !realred(c->wall)) fcol = wcol; - if(c->wall == waGlass && !wmspatial) fcol = wcol; + if(c->wall == waGlass && !wmspatial) fcol = wcol; + + wcol_star = wcol; + + if(festive) { + if(auto *at = at_or_null(old_shines, c)) { + fcol = darkenedby(fcol, fd); + wcol = darkenedby(wcol, fd); + fd = 0; + for(int p=0; p<3; p++) { + part(fcol, p) = min(255, part(fcol, p) + (*at)[p] / 4); + part(wcol, p) = min(255, part(wcol, p) + (*at)[p] / 8); + } + } + } if(neon_mode == eNeon::illustration) { fcol = highwall(c) ? w_monochromatize(fcol, 0) : w_monochromatize(fcol, 1); @@ -707,7 +722,7 @@ void celldrawer::draw_wall() { if(GDIM == 3 && WDIM == 2) { if(!qfi.fshape) qfi.fshape = &cgi.shFullFloor; if(conegraph(c)) { - draw_shapevec(c, V, qfi.fshape->cone[0], darkena(wcol, 0, 0xFF), PPR::WALL); + draw_shapevec(c, V, qfi.fshape->cone[0], darkena(wcol_star, 0, 0xFF), PPR::WALL); draw_wallshadow(); return; } @@ -718,11 +733,11 @@ void celldrawer::draw_wall() { queuepolyat(V * ddspin180(c, hdir), cgi.shPalaceGate, darkena(wcol, 0, 0xFF), wmspatial?PPR::WALL3A:PPR::WALL); return; } - color_t wcol0 = wcol; + color_t wcol0 = wcol_star; color_t wcol2 = gradient(0, wcol0, 0, .8, 1); color_t wcol1 = wcol2; if(geometry == gEuclidSquare) wcol1 = gradient(0, wcol0, 0, .9, 1); - draw_shapevec(c, V, qfi.fshape->levels[SIDE_WALL], darkena(wcol, 0, 0xFF), PPR::WALL); + draw_shapevec(c, V, qfi.fshape->levels[SIDE_WALL], darkena(wcol_star, 0, 0xFF), PPR::WALL); forCellIdEx(c2, i, c) if(!highwall(c2) || conegraph(c2) || c2->wall == waClosedGate || fake::split()) placeSidewall(c, i, SIDE_WALL, V, darkena((i&1)?wcol1:wcol2, fd, 255)); @@ -733,7 +748,7 @@ void celldrawer::draw_wall() { aura_color = wcol; color_t wcol0 = wcol; - int starcol = wcol; + int starcol = wcol_star; if(c->wall == waWarpGate) starcol = 0; if(c->wall == waVinePlant) starcol = 0x60C000; @@ -761,7 +776,7 @@ void celldrawer::draw_wall() { for(int z=1; zmonst, (col << 8) + 0xFF, c)) return false; - if(isIvy(c) || isMutantIvy(c) || c->monst == moFriendlyIvy) + if(isIvy(c) || isMutantIvy(c) || c->monst == moFriendlyIvy) { queuepoly(Vb, cgi.shIBranch, (col << 8) + 0xFF); -/* else if(c->monst < moTentacle && wormstyle == 0) { - ShadowV(Vb, cgi.shTentacleX, PPR::GIANTSHADOW); - queuepoly(at_smart_lof(Vb, cgi.ABODY), cgi.shTentacleX, 0xFF); - queuepoly(at_smart_lof(Vb, cgi.ABODY), cgi.shTentacle, (col << 8) + 0xFF); - } */ -// else if(c->monst < moTentacle) { -// } + christmas_lights(c, Vb); + } else if(c->monst == moDragonHead || c->monst == moDragonTail) { char part = dragon::bodypart(c, dragon::findhead(c)); @@ -3331,6 +3326,86 @@ EX bool drawMonster(const shiftmatrix& Vparam, int ct, cell *c, color_t col, col return res; } +EX color_t christmas_color(int d, bool simple) { + array cols = { 0x10101, 0x10100, 0x000001, 0x00100, 0x10000 }; + color_t v = cols[gmod(d, 5)]; + v *= 0x3F; + int mode; + if(false) { + mode = gmod(ticks / 20000, 2) ? 1 : 3; + } + else { + int t = gmod(ticks, 11000); + if(t > 10000) mode = 4; + else mode = 1 + gmod(ticks / 11000, 3); + } + switch(mode) { + case 0: + break; + case 1: + if((ticks/100 - d) % 16) v = 0; + break; + case 2: { + int z = gmod(d * 500 - ticks, 8000); + if(z > 1500) v = 0; + else if(z < 500) { v /= 0x3F; v *= 0x3F * z / 500; } + else if(z > 1000) { v /= 0x3F; v *= 0x3F * (1500 - z) / 500; } + break; + } + case 3: + if((-ticks / 100 - d) % 16) v = 0; + break; + case 4: + v /= 0x3F; + v *= int(0x20 + 0x1F * (1 - cos(ticks / 500. * TAU)) / 2); + break; + } + return v; + } + +EX std::unordered_map> shines, old_shines; + +EX bool festive, festive_date; +EX bool festive_option = true; + +EX void christmas_lights(cell *c, const shiftmatrix& Vb) { + if(!festive) return; + int lev = 0; + if(isMutantIvy(c)) lev = (c->stuntime - 1) & 15; + else { + auto c1 = c; + while(lev < 100 && c1->cpdist <= 7 && (isIvy(c1->monst) || c1->monst == moFriendlyIvy) && !among(c1->monst, moIvyRoot) && c1->mondir != NODIR) { + c1 = c1->cmove(c1->mondir); lev++; + } + } + auto cn = c->cmove(c->mondir); + ld dist = hdist0(currentmap->adj(c, c->mondir) * C0); + for(int a: {0, 1, 2}) { + color_t col = christmas_color(3*lev-a, c->monst == moMutant); + int bri = max(part(col, 0), max(part(col, 1), part(col, 2))); + color_t fcol = 0x7E + (col << 9) + 0x1010101 * int(129 * bri / 0x3F); + queuepoly(Vb * xpush(dist * (a*2+1) / 6), cgi.shChristmasLight, fcol); + for(int p: {0,1,2}) { + int val = part(col, p); + if(!val) continue; + if(a == 0) { + shines[c][p] += 2 * val; + forCellEx(c1, c) shines[c1][p] += val; + } + if(a == 2) { + shines[cn][p] += 2 * val; + forCellEx(c1, cn) shines[c1][p] += val; + } + if(a == 1) { + shines[c][p] += val; + shines[cn][p] += val; + forCellEx(c1, c) shines[c1][p] += val / 2; + forCellEx(c1, cn) shines[c1][p] += val / 2; + } + } + } + } + #define AURA 180 array,AURA+1> aurac; @@ -5794,6 +5869,9 @@ EX void gamescreen() { if(history::includeHistory) history::restore(); + festive = festive_date && festive_option; + old_shines = std::move(shines); shines.clear(); + anims::apply(); #if CAP_RUG if(rug::rugged) { diff --git a/menus.cpp b/menus.cpp index 567e3826..099693c5 100644 --- a/menus.cpp +++ b/menus.cpp @@ -846,6 +846,15 @@ EX bool showHalloween() { return false; } +EX bool showFestive() { + time_t t = time(NULL); + struct tm tm = *localtime(&t); + int month = tm.tm_mon + 1; + int day = tm.tm_mday; + if(month == 12 && day >= 24 && day <= 26) return true; + return false; + } + int daily_mode; void announce_random() { diff --git a/polygons.cpp b/polygons.cpp index e04e1956..2598bcd8 100644 --- a/polygons.cpp +++ b/polygons.cpp @@ -1358,6 +1358,13 @@ void geometry_information::prepare_shapes() { bshape(shWormHead, PPR::ONTENTACLE, scalefactor * wormscale, 80); bshape(shSmallWormHead, PPR::ONTENTACLE, scalefactor * wormscale / 2, 80); + bshape(shChristmasLight, PPR::ONTENTACLE_EYES); + hpcpush(hpxy(.05 * scalefactor, 0)); + hpcpush(hpxy(0, .03 * scalefactor)); + hpcpush(hpxy(-.05 * scalefactor, 0)); + hpcpush(hpxy(0, -.03 * scalefactor)); + hpcpush(hpxy(.05 * scalefactor, 0)); + bshape(shWormSegment, PPR::TENTACLE1); auto TC0 = tile_center(); RING(i) diff --git a/system.cpp b/system.cpp index f63c9f80..0d81e4ab 100644 --- a/system.cpp +++ b/system.cpp @@ -1808,6 +1808,7 @@ EX void initAll() { callhooks(hooks_initialize); init_floorcolors(); showstartmenu = true; + festive_date = showFestive(); ca::init(); #if CAP_COMMANDLINE arg::read(1);