From f61cb70c5147d8a57fd4931496ed408accb02544 Mon Sep 17 00:00:00 2001 From: DarkGod <darkgod@net-core.org> Date: Fri, 19 Dec 2014 01:50:03 +0100 Subject: [PATCH] when time stops .. time stops --- game/modules/tome/class/Game.lua | 9 +++ game/modules/tome/class/Player.lua | 6 ++ .../data/gfx/shaders/main_fbo/timestop.frag | 76 +++++++++++++++++++ .../data/gfx/shaders/main_fbo/timestop.lua | 31 ++++++++ .../modules/tome/data/timed_effects/other.lua | 7 ++ .../tome/data/zones/town-elvala/npcs.lua | 2 +- src/core_lua.c | 17 +++++ src/main.c | 7 +- src/main.h | 2 + 9 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 game/modules/tome/data/gfx/shaders/main_fbo/timestop.frag create mode 100644 game/modules/tome/data/gfx/shaders/main_fbo/timestop.lua diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua index c0805fd928..c1896654eb 100644 --- a/game/modules/tome/class/Game.lua +++ b/game/modules/tome/class/Game.lua @@ -532,6 +532,7 @@ function _M:createFBOs() underwater = Shader.new("main_fbo/underwater"), motionblur = Shader.new("main_fbo/motionblur"), blur = Shader.new("main_fbo/blur"), + timestop = Shader.new("main_fbo/timestop"), } self.posteffects_use = { self.fbo_shader.shad } if not self.fbo_shader.shad then self.fbo = nil self.fbo_shader = nil end @@ -1393,6 +1394,14 @@ function _M:displayMap(nb_keyframes) local changed = map.changed if changed then self:updateFOV() end + -- Ugh I dont like that but .. special case for timestop, for now it'll do! + if self.player and self.player:attr("timestopping") and self.player.x and self.posteffects and self.posteffects.timestop and self.posteffects.timestop.shad then + self.posteffects.timestop.shad:paramNumber2("texSize", map.viewport.width, map.viewport.height) + local sx, sy = map:getTileToScreen(self.player.x, self.player.y) + self.posteffects.timestop.shad:paramNumber2("playerPos", sx + map.tile_w / 2, sy + map.tile_h / 2) + self.posteffects.timestop.shad:paramNumber("tick_real", core.game.getTime()) + end + -- Display using Framebuffer, so that we can use shaders and all if self.fbo then self.fbo:use(true) diff --git a/game/modules/tome/class/Player.lua b/game/modules/tome/class/Player.lua index 5bebc15e05..ffd76f8381 100644 --- a/game/modules/tome/class/Player.lua +++ b/game/modules/tome/class/Player.lua @@ -458,6 +458,12 @@ function _M:updateMainShader() end end + -- Timestop shader + if self:attr("timestopping") and pf.timestop and pf.timestop.shad then + effects[pf.timestop.shad] = true + pf.timestop.shad:paramNumber("tick_start", core.game.getTime()) + end + game.posteffects_use = table.keys(effects) game.posteffects_use[#game.posteffects_use+1] = game.fbo_shader.shad end diff --git a/game/modules/tome/data/gfx/shaders/main_fbo/timestop.frag b/game/modules/tome/data/gfx/shaders/main_fbo/timestop.frag new file mode 100644 index 0000000000..3768c263ab --- /dev/null +++ b/game/modules/tome/data/gfx/shaders/main_fbo/timestop.frag @@ -0,0 +1,76 @@ +// uniform sampler2D tex; +// uniform vec2 texSize; +// uniform vec2 playerPos; +// uniform float innerRadius; +// uniform float outerRadius; +// uniform float tick_start; +// uniform float tick_real; +// uniform float growSpeed; + +// float wave(float x) +// { +// return (-x*x*x / 3.0 + x*x / 2.0) * 6.0; +// } + +// vec4 ConvertGrayscale(vec4 color) +// { +// float val = color.r * 0.299 + color.g * 0.587 + 0.114 * color.b; +// return vec4(val, val, val, color.a); +// } +// void main(void) +// { +// float growRatio = clamp((tick_real - tick_start) * growSpeed, 0.0, 1.0); +// growRatio = 1.0 - pow(1.0 - growRatio, 2.0); + +// // float circleRatio = clamp((length(gl_FragCoord.xy - playerPos) - innerRadius) / (outerRadius - innerRadius), 0.0, 1.0); +// float circleRatio = clamp((length(gl_FragCoord.xy - vec2(playerPos.x, texSize.y - playerPos.y)) - innerRadius) / (outerRadius - innerRadius), 0.0, 1.0); + +// float scale = growRatio * wave(circleRatio); + +// vec4 backgroundColor = texture2D(tex, gl_FragCoord.xy / texSize); +// vec4 grayscaleColor = ConvertGrayscale(backgroundColor); +// gl_FragColor = scale * grayscaleColor + (1.0 - scale) * backgroundColor; +// return; +// } + +uniform sampler2D tex; +uniform vec2 texSize; +uniform vec2 playerPos; +uniform float innerRadius; +uniform float outerRadius; +uniform float tick_start; +uniform float tick_real; +uniform float growSpeed; + +float wave(float x) +{ + return (-x*x*x / 3.0 + x*x / 2.0) * 6.0; +} + +vec4 ConvertGrayscale(vec4 color, vec4 lowColor, vec4 highColor) +{ + float val = color.r * 0.299 + color.g * 0.587 + 0.114 * color.b; + return highColor * val + lowColor * (1.0 - val); +} +void main(void) +{ + float growRatio = clamp((tick_real - tick_start) * growSpeed, 0.0, 1.0); + growRatio = 1.0 - pow(1.0 - growRatio, 2.0); + + innerRadius += innerRadius * 0.1 * sin(tick_real * growSpeed / 3); + outerRadius += outerRadius * 0.1 * cos(tick_real * growSpeed / 3); + float circleRatio = clamp((length(gl_FragCoord.xy - vec2(playerPos.x, texSize.y - playerPos.y)) - innerRadius) / (outerRadius - innerRadius), 0.0, 1.0); + // float circleRatio = clamp((length(gl_FragCoord.xy - playerPos) - innerRadius) / (outerRadius - innerRadius), 0.0, 1.0); + float scale = growRatio * wave(circleRatio); + + vec4 backgroundColor = texture2D(tex, gl_FragCoord.xy / texSize); + + vec4 highColor = vec4(243.0/255.0, 234.0/255.0, 255.0/255.0, 1.0); + vec4 lowColor = vec4(6.0/255.0 , 0.0 /255.0, 15.0 /255.0, 1.0); + /*vec4 highColor = vec4(1.0, 1.0, 1.0, 1.0); + vec4 lowColor = vec4(0.0, 0.0, 0.0, 1.0);*/ + + vec4 grayscaleColor = ConvertGrayscale(backgroundColor, lowColor, highColor); + gl_FragColor = scale * grayscaleColor + (1.0 - scale) * backgroundColor; + return; +} diff --git a/game/modules/tome/data/gfx/shaders/main_fbo/timestop.lua b/game/modules/tome/data/gfx/shaders/main_fbo/timestop.lua new file mode 100644 index 0000000000..661b2e61b6 --- /dev/null +++ b/game/modules/tome/data/gfx/shaders/main_fbo/timestop.lua @@ -0,0 +1,31 @@ +-- ToME - Tales of Maj'Eyal +-- Copyright (C) 2009 - 2014 Nicolas Casalini +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see <http://www.gnu.org/licenses/>. +-- +-- Nicolas Casalini "DarkGod" +-- darkgod@te4.org + +return { + frag = "main_fbo/timestop", + vert = nil, + args = { + tex = { texture = 0 }, + innerRadius = 70, + outerRadius = 90, + growSpeed = 0.001, + }, + clone = false, + permanent = true, +} diff --git a/game/modules/tome/data/timed_effects/other.lua b/game/modules/tome/data/timed_effects/other.lua index d93de637b7..eb55d698b1 100644 --- a/game/modules/tome/data/timed_effects/other.lua +++ b/game/modules/tome/data/timed_effects/other.lua @@ -2475,10 +2475,17 @@ newEffect{ if core.shader.active(4) then eff.particle1, eff.particle2 = self:addParticles3D("volumetric", {kind="vertical_and_awesome", radius=1.4, growSpeed=0.004, img="coggy_00"}) end + self:effectTemporaryValue(eff, "timestopping", 1) + self.no_leave_control = true + core.display.pauseAnims(true) + self:updateMainShader() end, deactivate = function(self, eff) + self.no_leave_control = false + core.display.pauseAnims(false) self:removeParticles(eff.particle1) self:removeParticles(eff.particle2) + self:updateMainShader() end, } diff --git a/game/modules/tome/data/zones/town-elvala/npcs.lua b/game/modules/tome/data/zones/town-elvala/npcs.lua index 0063473fe0..a188aa3408 100644 --- a/game/modules/tome/data/zones/town-elvala/npcs.lua +++ b/game/modules/tome/data/zones/town-elvala/npcs.lua @@ -109,7 +109,7 @@ newEntity{ base = "BASE_NPC_ELVALA_OGRE_TOWN", level_range = {1, nil}, exp_worth = 1, rarity = 3, - resolvers.inscriptions(4, "rune"), + resolvers.inscriptions(3, {"shielding rune", "phase door rune", "heat beam rune", "acid wave rune", "lightning rune"}), max_life = resolvers.rngavg(70,80), resolvers.equip{ {type="weapon", subtype="longsword", autoreq=true}, diff --git a/src/core_lua.c b/src/core_lua.c index e2d6196a80..d6ab43e57d 100644 --- a/src/core_lua.c +++ b/src/core_lua.c @@ -3077,6 +3077,22 @@ static int fbo_texture_bind(lua_State *L) return 0; } +static int pause_anims_started = 0; +static int display_pause_anims(lua_State *L) { + bool new_state = lua_toboolean(L, 1); + if (new_state == anims_paused) return 0; + + if (new_state) { + anims_paused = TRUE; + pause_anims_started = SDL_GetTicks(); + } else { + anims_paused = FALSE; + frame_tick_paused_time += SDL_GetTicks() - pause_anims_started; + } + printf("[DISPLAY] Animations paused: %d\n", anims_paused); + return 0; +} + static const struct luaL_Reg displaylib[] = { {"setTextBlended", set_text_aa}, @@ -3108,6 +3124,7 @@ static const struct luaL_Reg displaylib[] = {"setMouseCursor", sdl_set_mouse_cursor}, {"setMouseDrag", sdl_set_mouse_cursor_drag}, {"setGamma", sdl_set_gamma}, + {"pauseAnims", display_pause_anims}, {"glTranslate", gl_translate}, {"glScale", gl_scale}, {"glRotate", gl_rotate}, diff --git a/src/main.c b/src/main.c index a086c914ae..fd085aed1c 100644 --- a/src/main.c +++ b/src/main.c @@ -75,12 +75,14 @@ bool no_sound = FALSE; bool no_steam = FALSE; bool isActive = TRUE; bool tickPaused = FALSE; +bool anims_paused = FALSE; int mouse_cursor_ox, mouse_cursor_oy; int mouse_drag_w = 32, mouse_drag_h = 32; int mouse_drag_tex = 0, mouse_drag_tex_ref = LUA_NOREF; int mousex = 0, mousey = 0; float gamma_correction = 1; int cur_frame_tick = 0; +int frame_tick_paused_time = 0; /* The currently requested fps for the program */ int requested_fps = 30; /* The requested fps for when the program is idle (i.e., doesn't have focus) */ @@ -516,7 +518,7 @@ void call_draw(int nb_keyframes) if (nb_keyframes > 30) nb_keyframes = 30; // Notify the particles threads that there are new keyframes - thread_particle_new_keyframes(nb_keyframes); + if (!anims_paused) thread_particle_new_keyframes(nb_keyframes); if (current_game != LUA_NOREF) { @@ -578,7 +580,8 @@ void on_redraw() /* Gather our frames per second */ Frames++; if (!is_waiting()) { - int t = cur_frame_tick = SDL_GetTicks(); + int t = SDL_GetTicks(); + if (!anims_paused) cur_frame_tick = t - frame_tick_paused_time; if (t - T0 >= 1000) { float seconds = (t - T0) / 1000.0; float fps = Frames / seconds; diff --git a/src/main.h b/src/main.h index 9b0f17bc4a..73d51abcb9 100644 --- a/src/main.h +++ b/src/main.h @@ -62,6 +62,8 @@ extern bool safe_mode; extern bool fbo_active; extern bool multitexture_active; extern long total_keyframes; +extern bool anims_paused; +extern int frame_tick_paused_time; extern int cur_frame_tick; extern int g_argc; extern char **g_argv; -- GitLab