dobrograd-13-06-2022/garrysmod/addons/util-dlib/lua/entities/dlib_espawner.lua
Jonny_Bro (Nikita) e4d5311906 first commit
2023-11-16 15:01:19 +05:00

327 lines
7.9 KiB
Lua

-- Copyright (C) 2017-2020 DBotThePony
-- Permission is hereby granted, free of charge, to any person obtaining a copy
-- of this software and associated documentation files (the "Software"), to deal
-- in the Software without restriction, including without limitation the rights
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-- of the Software, and to permit persons to whom the Software is furnished to do so,
-- subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies
-- or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-- INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-- PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-- FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-- OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-- DEALINGS IN THE SOFTWARE.
AddCSLuaFile()
local PICKUP_RANGE = CreateConVar('dlib_spawner_range', '128', {FCVAR_ARCHIVE, FCVAR_NOTIFY}, 'Entity spawner spawn trigger range in Hu')
local RESET_TIMER = CreateConVar('dlib_spawner_timer', '10', {FCVAR_ARCHIVE, FCVAR_NOTIFY}, 'Entity spawner reset timer in seconds')
ENT.Type = 'anim'
ENT.Author = 'DBot'
ENT.Base = 'base_entity'
ENT.PrintName = 'Enitity Spawner Base'
ENT.RenderGroup = RENDERGROUP_BOTH
ENT.DefaultModel = 'models/items/item_item_crate.mdl'
ENT.SPAWN_HOOK_CALL = 'PlayerSpawnSENT'
ENT.SPAWNED_HOOK_CALL = 'PlayerSpawnedSENT'
ENT.IS_SPAWNER = true
ENT.PICKUP_RANGE = PICKUP_RANGE
ENT.RESET_TIMER = RESET_TIMER
function ENT:SetupDataTables()
self:NetworkVar('Float', 0, 'NextSpawn')
self:SetNextSpawn(0)
end
function ENT:SpawnFunction(ply, tr, class)
if not tr.Hit then return end
local can = hook.Run(self.SPAWN_HOOK_CALL, ply, self.CLASS)
if can == false then return end
if not self.TABLE.eSpawnerInfo then
local newEnt = ents.Create(self.CLASS)
newEnt:SetPos(tr.HitPos)
newEnt:Spawn()
newEnt:Activate()
local mdl = newEnt:GetModel()
local skin = newEnt:GetSkin()
local color = newEnt:GetColor()
local material = newEnt:GetMaterial()
local bg = newEnt:GetBodyGroups()
self.TABLE.eSpawnerInfo = {}
self.TABLE.eSpawnerInfo.mdl = util.IsValidModel(mdl) and mdl or self.DefaultModel
self.TABLE.eSpawnerInfo.skin = skin
self.TABLE.eSpawnerInfo.color = color
self.TABLE.eSpawnerInfo.material = material
self.TABLE.eSpawnerInfo.bg = bg
self.TABLE.eSpawnerInfo.bginfo = {}
if bg then
for k, v in pairs(bg) do
self.TABLE.eSpawnerInfo.bginfo[v.id] = newEnt:GetBodygroup(v.id)
end
end
newEnt:Remove()
end
local ent = ents.Create(class)
ent:SetPos(tr.HitPos + tr.HitNormal)
local mdl, skin, color, material = self.TABLE.eSpawnerInfo.mdl, self.TABLE.eSpawnerInfo.skin, self.TABLE.eSpawnerInfo.color, self.TABLE.eSpawnerInfo.material
if mdl then
ent.Model = mdl
ent:SetModel(mdl)
else
ent:SetModel(self.DefaultModel)
end
if skin then
ent:SetSkin(skin)
end
for k, v in pairs(self.TABLE.eSpawnerInfo.bginfo) do
ent:SetBodygroup(k, v)
end
ent:Spawn()
ent:Activate()
return ent
end
local MINS, MAXS = Vector(-10, -10, 0), Vector(10, 10, 10)
function ENT:GetIsSpawned()
return self:GetNextSpawn() < CurTimeL()
end
function ENT:Initialize()
timer.Simple(0.3, function()
if not self:IsValid() then return end
self:PhysicsInit(SOLID_NONE)
self:SetSolid(SOLID_NONE)
self:SetMoveType(MOVETYPE_NONE)
end)
self:DrawShadow(false)
self.CurrentClip = 0
if CLIENT then
self:ClientsideEntity()
self.CurrAngle = Angle(0, 0, 0)
end
end
function ENT:ClientsideEntity()
if IsValid(self.CModel) then self.CModel:Remove() end
local ent = octolib.createDummy(self:GetModel())
self.CModel = ent
ent:SetPos(self:GetPos())
ent:Spawn()
ent:Activate()
ent:SetNoDraw(true)
if IsValid(self.CModel2) then self.CModel2:Remove() end
local ent1 = ent
local ent = octolib.createDummy(self:GetModel())
local ent2 = ent
self.CModel2 = ent
ent:SetPos(self:GetPos())
ent:Spawn()
ent:Activate()
ent:SetNoDraw(true)
local bg = self:GetBodyGroups()
ent1:SetSkin(self:GetSkin() or 0)
ent1:SetColor(self:GetColor())
ent1:SetMaterial(self:GetMaterial() or '')
ent2:SetSkin(self:GetSkin() or 0)
ent2:SetColor(self:GetColor())
ent2:SetMaterial(self:GetMaterial() or '')
if bg then
for k, v in pairs(bg) do
ent1:SetBodygroup(v.id, self:GetBodygroup(v.id))
end
for k, v in pairs(bg) do
ent2:SetBodygroup(v.id, self:GetBodygroup(v.id))
end
end
end
function ENT:DoSpawn(ply)
if ply.EntSpawnerCooldown and ply.EntSpawnerCooldown > CurTimeL() then return false end
local try = hook.Run(self.SPAWN_HOOK_CALL, ply, self.CLASS)
if try == false then return false end
if not ply:CheckLimit('sents') then
ply.EntSpawnerCooldown = CurTimeL() + 10
return false
end
local sfunc = self.TABLE.SpawnFunction
local ent
local hpos = self:GetPos() + Vector(0, 0, 40)
if sfunc then
local fakeTrace = {
Hit = true,
HitPos = hpos,
StartPos = hpos,
EndPos = hpos,
HitWorld = true,
HitSky = false,
PhysicsBone = 0,
HitNoDraw = false,
HitNonWorld = false,
HitTexture = '',
HitGroup = HITGROUP_GENERIC,
MatType = MAT_GRASS, -- heh
HitNormal = Vector(0, 0, 1),
Entity = game.GetWorld()
}
ent = sfunc(self.TABLE, ply, fakeTrace, self.CLASS)
if not ent then return end
else
ent = ents.Create(self.CLASS)
end
ent:SetPos(hpos)
ent:Spawn()
ent:PhysWake()
hook.Run(self.SPAWNED_HOOK_CALL, ply, ent)
ent:Activate()
DoPropSpawnedEffect(ent)
self.LastEntity = ent
self.LastPly = ply
self:SetNextSpawn(CurTimeL() + (self.ResetTimer or RESET_TIMER:GetFloat()))
undo.Create('SENT')
undo.AddEntity(ent)
undo.SetPlayer(ply)
if ent.PrintName then
undo.SetCustomUndoText('Undone ' .. ent.PrintName)
end
undo.Finish()
return true
end
function ENT:Think()
if CLIENT then return end
if self:GetIsSpawned() then
local lpos = self:GetPos()
local dist = PICKUP_RANGE:GetInt()
for k, v in ipairs(player.GetAll()) do
if v:GetPos():Distance(lpos) < dist and self:DoSpawn(v) then
break
end
end
end
end
local debugwtite = Material('models/debug/debugwhite')
local glow = Color(0, 255, 255)
function ENT:Draw()
if not IsValid(self.CModel) then self:ClientsideEntity() end
if not IsValid(self.CModel2) then self:ClientsideEntity() end
local mdl = self:GetModel()
self.CModel:SetModel(mdl)
self.CModel2:SetModel(mdl)
local ang = self.CurrAngle or Angle(0, 0, 0)
local pos = self:GetPos()
ang.y = ang.y + FrameTime() * 33
pos.z = pos.z + math.sin(CurTimeL() * 2) * 10 + 20
ang:Normalize()
self.CModel:SetAngles(ang)
self.CModel2:SetAngles(ang)
self.CModel:SetPos(pos)
self.CModel2:SetPos(pos)
if self:GetIsSpawned() then
self.CModel:DrawModel()
-- God how i hate this part
-- GMod functions have documented the best
self.CurrentClip = (self.CurrentClip or 0) + FrameTime() * 22
if self.CurrentClip > 150 then
self.CurrentClip = -150
end
local Vec = ang:Forward()
local First = pos + Vec * self.CurrentClip
local Second = pos + Vec * self.CurrentClip + Vec * 5
local dot1 = Vec:Dot(First)
local dot2 = (-Vec):Dot(Second)
render.SuppressEngineLighting(true)
render.ModelMaterialOverride(debugwtite)
render.SetColorModulation(0, 1, 1)
render.ResetModelLighting(1, 1, 1)
local old = render.EnableClipping(true)
render.PushCustomClipPlane(Vec, dot1)
render.PushCustomClipPlane(-Vec, dot2)
self.CModel2:DrawModel()
render.PopCustomClipPlane()
render.PopCustomClipPlane()
render.EnableClipping(old)
render.SetColorModulation(1, 1, 1)
render.ModelMaterialOverride()
render.SuppressEngineLighting(false)
end
self.CurrAngle = ang
end
function ENT:OnRemove()
if CLIENT and IsValid(self.CModel) then
self.CModel:Remove()
end
if CLIENT and IsValid(self.CModel2) then
self.CModel2:Remove()
end
end