Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- setfenv(1, _G)
- water = {}
- local water = water
- function water.SetConfig(cfg)
- water.Resolution = cfg.resolution or 16
- water.Size = cfg.size or 32768 * 8
- water.Origin = cfg.origin or Vector(-32768, -32768, 0)*2
- water.Height = cfg.height or 256
- water.Depth = cfg.depth or 1024
- water.Color = cfg.color or Color(32, 128, 200, 200)
- water.surfaces = {}
- water.grid_size = water.Size / water.Resolution
- for y = 0, water.Resolution do
- local vertices = {}
- for x = 0, water.Resolution do
- table.insert(vertices, Vector(x * water.grid_size, y * water.grid_size, 0))
- table.insert(vertices, Vector(x * water.grid_size, y * water.grid_size + water.grid_size, 0))
- end
- table.insert(water.surfaces, vertices)
- end
- end
- water.SetConfig({})
- function water.IsPositionUnderWater(v)
- return v.x >= water.Origin.x and v.x <= water.Origin.x + water.Size and
- v.y >= water.Origin.y and v.y <= water.Origin.y + water.Size and
- v.z >= water.Origin.z and v.z <= water.Origin.z + water.Depth
- end
- function water.GetDepthFromPosition(v)
- return (water.Origin.z + water.Depth) - v.z
- end
- do -- meta override
- local META = FindMetaTable("Entity")
- water_oldWaterLevel = water_oldWaterLevel or META.WaterLevel
- local water_oldWaterLevel = _G.water_oldWaterLevel
- function META:WaterLevel(...)
- if water.IsPositionUnderWater(self:EyePos()) then
- return 3
- end
- return water_oldWaterLevel(self, ...)
- end
- end
- hook.Add("Move", "water", function(ply, move)
- if water.IsPositionUnderWater(ply:EyePos()) then
- ply:SetGroundEntity(NULL)
- local vel = move:GetVelocity()
- vel = vel + Vector(0, 0, 5)
- if ply:KeyDown(IN_FORWARD) then
- vel = vel + ply:GetAimVector() * 5
- end
- if ply:KeyDown(IN_JUMP) then
- vel = vel + ply:GetUp() * 5
- end
- vel = vel + move:GetVelocity() * -0.01
- move:SetVelocity(vel)
- end
- end)
- if SERVER then
- hook.Add("Think", "float", function()
- do return end
- for _, ent in ipairs(ents.GetAll()) do
- if water.IsPositionUnderWater(ent:EyePos()) then
- if ent:IsPlayer() then
- --ent:SetVelocity(Vector(0, 0, 25) + ent:GetVelocity() * -0.01)
- --ent:EmitSound("player/geiger3.wav")
- else
- local phys = ent:GetPhysicsObject()
- if phys:IsValid() then
- local force = (phys:GetVolume()/phys:GetMass()) * 0.1
- if phys:GetMaterial():sub(0,5) ~= "metal" then
- phys:AddVelocity(Vector(0, 0, force))
- else
- phys:AddVelocity(Vector(0, 0, force * 0.5))
- end
- phys:AddVelocity(phys:GetVelocity() * -0.1)
- phys:AddAngleVelocity(phys:GetAngleVelocity() * -0.1)
- end
- end
- end
- end
- end)
- end
- if CLIENT then
- local ply
- local snd
- hook.Add("PreDrawHUD", "water", function()
- ply = ply or LocalPlayer()
- snd = snd or CreateSound(ply, "ambient/water/underwater.wav")
- if water.IsPositionUnderWater(ply:EyePos()) then
- snd:PlayEx(100, 50)
- ply:SetDSP(14)
- surface.SetDrawColor(water.Color.r*0.3, water.Color.g*0.3, water.Color.b*0.3, math.Clamp(water.Color.a*1.3, 0, 250))
- surface.DrawRect(-2,-2, 4,4)
- ply.water_dsp_reset = false
- elseif not ply.water_dsp_reset then
- snd:Stop()
- ply:SetDSP(0)
- ply.water_dsp_reset = true
- end
- end)
- water.Translucent = true
- water.Material = CreateMaterial("water_overlay_" .. CurTime(),
- "Refract",
- {
- ["$model"] = 1,
- ["$nocull"] = 1,
- ["$vertexcolor"] = 1,
- ["$vertexalpha"] = 1,
- ["$refractamount"] = 0.1,
- ["$normalmap"] = "dev/water_normal",
- Proxies =
- {
- AnimatedTexture =
- {
- animatedtexturevar = "$normalmap",
- animatedtextureframenumvar = "$bumpframe",
- animatedtextureframerate = 30,
- },
- },
- }
- )
- local vector = Vector(0, 0, 0)
- -- hacky optimization
- -- allows only the last draw call
- local function setup_suppress()
- local last_framenumber = 0
- local current_frame = 0
- local current_frame_count = 0
- return function()
- local frame_number = FrameNumber()
- if frame_number == last_framenumber then
- current_frame = current_frame + 1
- else
- last_framenumber = frame_number
- if current_frame_count ~= current_frame then
- current_frame_count = current_frame
- end
- current_frame = 1
- end
- return current_frame < current_frame_count
- end
- end
- local should_suppres = setup_suppress()
- function water.Draw()
- if should_suppres() then return end
- render.SetMaterial(water.Material)
- render.FogMode(MATERIAL_FOG_LINEAR)
- render.FogStart(0)
- render.FogEnd(512)
- render.FogColor(water.Color.r, water.Color.g, water.Color.b)
- render.FogMaxDensity(water.Color.a / 255)
- local matrix = Matrix()
- matrix:Translate(water.Origin + Vector(0, 0, water.Depth))
- local t = CurTime()
- render.SetBlend(0.1)
- cam.PushModelMatrix(matrix)
- for y, vertices in ipairs(water.surfaces) do
- mesh.Begin(MATERIAL_TRIANGLE_STRIP, #vertices - 2)
- for x, vertex in ipairs(vertices) do
- vector.x = vertex.y
- vector.y = vertex.x
- vector.z = vertex.z + math.sin(vertex.x * 3 + vertex.y * 2.5 + t) * water.Height
- --mesh.Color(255, 0, 255, 100)
- --mesh.Normal(vector)
- mesh.Position(vector)
- mesh.TexCoord(0, vertex.x / 1024 + (t*0.2), vertex.y / 1024)
- mesh.AdvanceVertex()
- end
- mesh.End()
- end
- cam.PopModelMatrix()
- render.FogMode(MATERIAL_FOG_NONE)
- render.FogStart(0)
- render.FogEnd(0)
- end
- hook.Add("PostDrawTranslucentRenderables", "water", function() if water.Translucent then water.Draw() end end)
- hook.Add("PostDrawOpaqueRenderables", "water", function() if not water.Translucent then water.Draw() end end)
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement