diff --git a/game/engines/default/engine/interface/ActorTalents.lua b/game/engines/default/engine/interface/ActorTalents.lua index c462735488d41c1b809bbc7703a4c25b079ea4a3..73343b2f6ffe10e9e37851bd9ee63aa497e41145 100644 --- a/game/engines/default/engine/interface/ActorTalents.lua +++ b/game/engines/default/engine/interface/ActorTalents.lua @@ -1006,7 +1006,7 @@ function _M:talentParticles(p, ...) local Particles = require "engine.Particles" if not p.__tmpparticles then p.__tmpparticles = {} end for _, ps in ipairs{...} do - p.__tmpparticles[#p.__tmpparticles+1] = self:addParticles(Particles.new(ps.type, 1, ps.args)) + p.__tmpparticles[#p.__tmpparticles+1] = self:addParticles(Particles.new(ps.type, 1, ps.args, ps.shader)) end end diff --git a/game/engines/default/engine/interface/ActorTemporaryEffects.lua b/game/engines/default/engine/interface/ActorTemporaryEffects.lua index df72b87cebd5ebd6ebfaf9fe627efb1a321d0211..e498a656d59dfffae2f956ef084310743344e294 100644 --- a/game/engines/default/engine/interface/ActorTemporaryEffects.lua +++ b/game/engines/default/engine/interface/ActorTemporaryEffects.lua @@ -275,7 +275,7 @@ function _M:effectParticles(eff, ...) local Particles = require "engine.Particles" if not eff.__tmpparticles then eff.__tmpparticles = {} end for _, p in ipairs{...} do - eff.__tmpparticles[#eff.__tmpparticles+1] = self:addParticles(Particles.new(p.type, 1, p.args)) + eff.__tmpparticles[#eff.__tmpparticles+1] = self:addParticles(Particles.new(p.type, 1, p.args, ps.shader)) end end diff --git a/game/modules/tome/data/gfx/particles/shader_shield.lua b/game/modules/tome/data/gfx/particles/shader_shield.lua index 34caccd3c4e3c627d28a3530f9f6d8900fe36281..774885aa214a66bc0146e59abe08d2f68e9d3f16 100644 --- a/game/modules/tome/data/gfx/particles/shader_shield.lua +++ b/game/modules/tome/data/gfx/particles/shader_shield.lua @@ -19,9 +19,9 @@ base_size = 64 -local r = 1 -local g = 1 -local b = 1 +local r = r or 1 +local g = g or 1 +local b = b or 1 local a = a or 1 return { blend_mode = blend and core.particles.BLEND_SHINY or nil, generator = function() diff --git a/game/modules/tome/data/gfx/particles_images/rotating_shield.png b/game/modules/tome/data/gfx/particles_images/rotating_shield.png new file mode 100644 index 0000000000000000000000000000000000000000..5dc7f5f505161f8b88c318451062c5d3bff29785 Binary files /dev/null and b/game/modules/tome/data/gfx/particles_images/rotating_shield.png differ diff --git a/game/modules/tome/data/gfx/shaders/rotatingshield.frag b/game/modules/tome/data/gfx/shaders/rotatingshield.frag new file mode 100644 index 0000000000000000000000000000000000000000..fb87ae227a301acc61a2837b7bfa46bebbc85c33 --- /dev/null +++ b/game/modules/tome/data/gfx/shaders/rotatingshield.frag @@ -0,0 +1,86 @@ +uniform sampler2D tex; +uniform float tick; +uniform float tick_start; +uniform float time_factor; +uniform float noup; +uniform float cylinderRotationSpeed; //rotation speed of the aura, min: 0, max: 10, def: 1 +uniform float cylinderRadius; //radius of the cylinder aura. min: 0.2, max: 0.5, def: 0.45 +uniform float cylinderVerticalPos; //vertical position of the cylinder. 0 is in the middle. min: -0.2, max: 0.2 +uniform float cylinderHeight; //height of the cylinder. min: 0.1, max: 1.0, default: 0.4 +uniform float appearTime; //normalized appearence time. min: 0.01, max: 3.0, default: 1.0f +uniform float repeatTimes; +uniform float unbalancedSize; + +vec2 Rotate(vec2 point, float ang) +{ + return vec2( + point.x * cos(ang) - point.y * sin(ang), + point.x * sin(ang) + point.y * cos(ang)); +} + +vec4 Uberblend(vec4 col0, vec4 col1) +{ +// return vec4((1.0 - col0.a) * (col1.rgb) + col0.a * (col1.rgb * col1.a + col0.rgb * (1.0 - col1.a)), min(1.0, col0.a + col1.a)); +// return vec4((1.0 - col1.a) * (col0.rgb) + col1.a * (col1.rgb * col1.a + col0.rgb * (1.0 - col1.a)), min(1.0, col0.a + col1.a)); + return vec4( + (1.0 - col0.a) * (1.0 - col1.a) * (col0.rgb * col0.a + col1.rgb * col1.a) / (col0.a + col1.a + 1e-1) + + (1.0 - col0.a) * (0.0 + col1.a) * (col1.rgb) + + (0.0 + col0.a) * (1.0 - col1.a) * (col0.rgb * (1.0 - col1.a) + col1.rgb * col1.a) + + (0.0 + col0.a) * (0.0 + col1.a) * (col1.rgb), + min(1.0, col0.a + col1.a)); +} + +void main(void) +{ + vec2 pos = vec2(0.5, 0.5) - gl_TexCoord[0].xy; + + vec4 resultColor = vec4(0.0, 0.0, 0.0, 0.0); + + float dist = 2.0; + vec3 rayDir = normalize(vec3(0.0, -0.5, 1.0)); + vec3 xVector = normalize(cross(vec3(0.0, 1.0, 0.0), rayDir)); + vec3 yVector = cross(rayDir, xVector); + + vec3 rayPoint = vec3(0.0) - rayDir * dist + xVector * pos.x + yVector * pos.y; + + float normTime = (tick - tick_start) / time_factor; + float alpha = normTime * cylinderRotationSpeed; + + if(abs(pos.x) < cylinderRadius) + { + float localWidth = sqrt(cylinderRadius * cylinderRadius - pos.x * pos.x); + vec3 startPoint = rayPoint + rayDir * (-localWidth - rayPoint.z) / rayDir.z; + vec3 endPoint = rayPoint + rayDir * ( localWidth - rayPoint.z) / rayDir.z; + + vec3 cylinderPoint; + if(noup == 1.0) + { + cylinderPoint = startPoint; + }else + if(noup == 2.0) + { + cylinderPoint = endPoint; + } + float farRatio = (cylinderPoint.z - (-cylinderRadius)) / (2.0 * cylinderRadius); + float farDarkening = mix(1.0, 0.1, farRatio); + + vec2 planarPos; + planarPos.y = (cylinderPoint.y + cylinderHeight * 0.5 + cylinderVerticalPos) / cylinderHeight; + planarPos.y = 1.0 - planarPos.y; + planarPos.y = 0.5 + (planarPos.y - 0.5) * (1.0 + cylinderPoint.z * 0.5); + planarPos.x = mod((atan(cylinderPoint.z, cylinderPoint.x) + alpha) / (2.0 * 3.1415), 1.0); + + if(planarPos.y < 1.0 && planarPos.y > 0.0) + { + float glowMult = 1.0 + mix(3.0, 0.0, clamp(normTime / (appearTime * 1.5 + 1e-4), 0.0, 1.0)); + float alphaSub = 1.0f - clamp(normTime / (appearTime + 1e-4), 0.0, 1.0);; + planarPos.x *= repeatTimes; + planarPos.x = clamp(planarPos.x, 0.0, unbalancedSize); + resultColor = texture2D(tex, planarPos); + resultColor.rgb *= farDarkening; + resultColor.rgb *= glowMult; + resultColor.a = (resultColor.a - alphaSub) / (1.0 - alphaSub + 1e-4); + } + } + gl_FragColor = resultColor * gl_Color; +} diff --git a/game/modules/tome/data/gfx/shaders/rotatingshield.lua b/game/modules/tome/data/gfx/shaders/rotatingshield.lua new file mode 100644 index 0000000000000000000000000000000000000000..f5e4d0f3afabb5e8f112a0e88efb1124bcb0c32c --- /dev/null +++ b/game/modules/tome/data/gfx/shaders/rotatingshield.lua @@ -0,0 +1,39 @@ +-- ToME - Tales of Maj'Eyal +-- Copyright (C) 2009 - 2016 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 = "rotatingshield", + vert = nil, + args = { + tex = { texture = 0 }, + noup = noup or 0, + time_factor = time_factor or 1000, + cylinderRotationSpeed = cylinderRotationSpeed or 1, -- rotation speed of the aura, min: 0, max: 10, def: 1 + cylinderRadius = cylinderRadius or 0.45, -- radius of the cylinder aura. min: 0.2, max: 0.5, def: 0.45 + cylinderVerticalPos = cylinderVerticalPos or 0, -- vertical position of the cylinder. 0 is in the middle. min: -0.2, max: 0.2 + cylinderHeight = cylinderHeight or 0.4, -- height of the cylinder. min: 0.1, max: 1.0, default: 0.4 + appearTime = appearTime or 1, -- normalized appearence time. min: 0.01, max: 3.0, default: 1.0f + repeatTimes = repeatTimes or 1, + unbalancedSize = unbalancedSize or 1, + }, + resetargs = { + tick_start = function() return core.game.getFrameTime() end, + }, + clone = false, +} diff --git a/game/modules/tome/data/talents/techniques/weaponshield.lua b/game/modules/tome/data/talents/techniques/weaponshield.lua index 0714337dd3188714d7aa6a263ca38e4f38877502..78b468171bceac7b2455c7e3d702868b666056c5 100644 --- a/game/modules/tome/data/talents/techniques/weaponshield.lua +++ b/game/modules/tome/data/talents/techniques/weaponshield.lua @@ -204,13 +204,18 @@ newTalent{ game.logPlayer(self, "You cannot use Shield Wall without a shield!") return nil end - return { + local ret = { stun = self:addTemporaryValue("stun_immune", t.stunKBresist(self, t)), knock = self:addTemporaryValue("knockback_immune", t.stunKBresist(self, t)), dam = self:addTemporaryValue("inc_damage", {[DamageType.PHYSICAL]=-20}), def = self:addTemporaryValue("combat_def", t.getDefense(self, t)), armor = self:addTemporaryValue("combat_armor", t.getarmor(self,t)), } + if core.shader.active(4) then + self:talentParticles(ret, {type="shader_shield", args={toback=true, size_factor=1, img="rotating_shield"}, shader={type="rotatingshield", noup=2.0, appearTime=0.2}}) + self:talentParticles(ret, {type="shader_shield", args={toback=false, size_factor=1, img="rotating_shield"}, shader={type="rotatingshield", noup=1.0, appearTime=0.2}}) + end + return ret end, deactivate = function(self, t, p) self:removeTemporaryValue("combat_def", p.def)