mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 21:53:46 +03:00
258 lines
17 KiB
Lua
258 lines
17 KiB
Lua
|
|
--[[
|
||
|
|
| This file was obtained through the combined efforts
|
||
|
|
| of Madbluntz & Plymouth Antiquarian Society.
|
||
|
|
|
|
||
|
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||
|
|
| Maloy, DrPepper10 @ RIP, Atle!
|
||
|
|
|
|
||
|
|
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||
|
|
--]]
|
||
|
|
|
||
|
|
if (!file.Exists("autorun/vj_base_autorun.lua","LUA")) then return end
|
||
|
|
AddCSLuaFile("shared.lua")
|
||
|
|
include("shared.lua")
|
||
|
|
/*--------------------------------------------------
|
||
|
|
*** Copyright (c) 2012-2023 by DrVrej, All rights reserved. ***
|
||
|
|
No parts of this code or any of its contents may be reproduced, copied, modified or adapted,
|
||
|
|
without the prior written consent of the author, unless otherwise indicated for stand-alone materials.
|
||
|
|
--------------------------------------------------*/
|
||
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
|
------ Core Variables ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
|
ENT.SingleSpawner = false -- If set to true, it will spawn the entities once then remove itself
|
||
|
|
ENT.VJBaseSpawnerDisabled = false -- If set to true, it will stop spawning the entities
|
||
|
|
ENT.OverrideDisableOnSpawn = false -- If set to true, the spawner will create entities on initialize even if it's disabled!
|
||
|
|
ENT.Model = {} -- The models it should spawn with | Picks a random one from the table
|
||
|
|
ENT.EntitiesToSpawn = {}
|
||
|
|
/* Example (3 NPCs):
|
||
|
|
ENT.EntitiesToSpawn = {
|
||
|
|
{SpawnPosition = {vForward=0, vRight=0, vUp=0}, Entities = {"npc_name_one"}},
|
||
|
|
{SpawnPosition = {vForward=0, vRight=0, vUp=0}, Entities = {"npc_name_one:1", "npc_name_two:5"}},
|
||
|
|
{SpawnPosition = {vForward=0, vRight=0, vUp=0}, Entities = {"npc_name_three", "npc_name_one:1", "npc_name_two:5"}},
|
||
|
|
}
|
||
|
|
Options:
|
||
|
|
Entities = {} -- The table of entities it spawns randomly, REQUIRED!
|
||
|
|
- ":" = Add at the end to apply a chance, it starts from 1
|
||
|
|
- ":1" = Spawn always or leave it empty
|
||
|
|
- WARNING: If no entity is left empty or set to ":1" then during randomization, the base will spawn the last NPC it checks if no other passes!
|
||
|
|
SpawnPosition = {vForward=0, vRight=0, vUp=0} -- The spawn position of the entity, it's based on the spawner's position, OPTIONAL | DEFAULT: Origin of the spawner
|
||
|
|
SpawnAngle = Angle(0, 0, 0) -- The spawn angle, it's based on the spawner's angle, OPTIONAL | DEFAULT: Spawners current angle
|
||
|
|
WeaponsList = {} -- The list of weapons it spawns with randomly, OPTIONAL | DEFAULT: Empty table
|
||
|
|
- "default" = Spawns the NPC with its default weapons list from the spawn menu
|
||
|
|
NPC_Class = "" or {} -- Overrides the NPC's relation class with the given string or table | DEFAULT: ""
|
||
|
|
FriToPlyAllies = false or true -- If set to true, the NPC will be allied with the player, must have NPC class "CLASS_PLAYER_ALLY" | DEFAULT: false
|
||
|
|
*/
|
||
|
|
ENT.TimedSpawn_Time = 3 -- How much time until it spawns another SNPC?
|
||
|
|
ENT.TimedSpawn_OnlyOne = true -- If it's true then it will only have one SNPC spawned at a time
|
||
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
|
------ Sound Variables ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
|
-- Idle
|
||
|
|
ENT.HasIdleSounds = true -- Does it have idle sounds?
|
||
|
|
ENT.SoundTbl_Idle = {}
|
||
|
|
ENT.IdleSoundChance = 1 -- How much chance to play the sound? 1 = always
|
||
|
|
ENT.IdleSoundLevel = 80
|
||
|
|
ENT.IdleSoundPitch = VJ_Set(80, 100)
|
||
|
|
ENT.NextSoundTime_Idle = VJ_Set(0.2, 0.5)
|
||
|
|
-- On Entity Spawn
|
||
|
|
ENT.HasSpawnEntitySound = true -- Does it play a sound on entity spawn?
|
||
|
|
ENT.SoundTbl_SpawnEntity = {}
|
||
|
|
ENT.SpawnEntitySoundChance = 1 -- How much chance to play the sound? 1 = always
|
||
|
|
ENT.SpawnEntitySoundLevel = 80
|
||
|
|
ENT.SpawnEntitySoundPitch = VJ_Set(80, 100)
|
||
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
|
------ Customization Functions ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
|
-- Use the functions below to customize certain parts of the base or to add new custom systems
|
||
|
|
---------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
|
--[[---------------------------------------------------------
|
||
|
|
Called when an entity spawns.
|
||
|
|
- ent = The entity it spawned
|
||
|
|
- spawnKey = The key or the position in the table of the current entity it spawned
|
||
|
|
- spawnTbl = Table of information for the entity it spawned including class names, spawn position, weapons, etc.
|
||
|
|
- initSpawn = Was this an initial spawn? Used by the base during initialization
|
||
|
|
-----------------------------------------------------------]]
|
||
|
|
function ENT:CustomOnEntitySpawn(ent, spawnKey, spawnTbl, initSpawn) end
|
||
|
|
---------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
|
function ENT:CustomOnInitialize() end
|
||
|
|
---------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
|
function ENT:CustomOnInitialize_AfterNPCSpawn() end
|
||
|
|
---------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
|
function ENT:CustomOnThink() end
|
||
|
|
---------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
|
function ENT:CustomOnThink_AfterAliveChecks() end
|
||
|
|
---------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
|
function ENT:CustomOnRemove() end
|
||
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
|
------ ///// WARNING: Don't touch anything below this line! \\\\\ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
|
ENT.Dead = false
|
||
|
|
ENT.NextIdleSoundT = 0
|
||
|
|
|
||
|
|
local string_explode = string.Explode
|
||
|
|
local defSpawnPos = {vForward=0, vRight=0, vUp=0}
|
||
|
|
local defAng = Angle(0, 0, 0)
|
||
|
|
---------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
|
--[[---------------------------------------------------------
|
||
|
|
Spawns an entity from the given information, recommended to not manually call this function!
|
||
|
|
- spawnKey = The key or the position in the table of the current entity to spawn
|
||
|
|
- spawnTbl = Table of information for the entity to spawn including class names, spawn position, weapons, etc.
|
||
|
|
- initSpawn = Is this a initial spawn? Used by the base during initialization | DEFAULT: false
|
||
|
|
-----------------------------------------------------------]]
|
||
|
|
function ENT:SpawnAnEntity(spawnKey, spawnTbl, initSpawn)
|
||
|
|
local initOverrideDisable = (initSpawn == true && self.OverrideDisableOnSpawn)
|
||
|
|
if self.VJBaseSpawnerDisabled == true && initOverrideDisable == false then return end
|
||
|
|
|
||
|
|
local spawnPos = spawnTbl.SpawnPosition or defSpawnPos
|
||
|
|
local spawnAng = spawnTbl.SpawnAngle
|
||
|
|
local spawnEnts = spawnTbl.Entities
|
||
|
|
local spawnNPCClass = spawnTbl.NPC_Class or ""
|
||
|
|
local spawnFriToPlyAllies = spawnTbl.FriToPlyAllies or false
|
||
|
|
local spawnWepPicked = VJ_PICK(spawnTbl.WeaponsList)
|
||
|
|
local entPicked; -- The entity that we will spawn
|
||
|
|
local entsNum = #spawnEnts -- The number of entities
|
||
|
|
local i = 0 -- If this number equals entsNum, then its the last entity
|
||
|
|
for _, v in RandomPairs(spawnEnts) do
|
||
|
|
i = i + 1
|
||
|
|
local strExp = string_explode(":", v) -- Separates the entity class and the number after ":"
|
||
|
|
//PrintTable(strExp)
|
||
|
|
if strExp[2] then
|
||
|
|
if i == entsNum then -- If we are the last entity, then just spawn it anyway
|
||
|
|
entPicked = strExp[1]
|
||
|
|
break
|
||
|
|
elseif math.random(1, strExp[2]) == 1 then
|
||
|
|
entPicked = strExp[1]
|
||
|
|
break
|
||
|
|
end
|
||
|
|
else -- String does NOT contain ":", so just pick this
|
||
|
|
entPicked = v
|
||
|
|
break
|
||
|
|
end
|
||
|
|
end
|
||
|
|
local ent = ents.Create(entPicked)
|
||
|
|
ent:SetPos(self:GetPos() + self:GetForward()*(spawnPos.vForward or 0) + self:GetRight()*(spawnPos.vRight or 0) + self:GetUp()*(spawnPos.vUp or 0))
|
||
|
|
ent:SetAngles((spawnAng or defAng) + self:GetAngles())
|
||
|
|
ent:Spawn()
|
||
|
|
ent:Activate()
|
||
|
|
if spawnNPCClass != "" then
|
||
|
|
ent.VJ_NPC_Class = istable(spawnNPCClass) && spawnNPCClass or {spawnNPCClass}
|
||
|
|
end
|
||
|
|
if spawnFriToPlyAllies then
|
||
|
|
ent.FriendsWithAllPlayerAllies = true
|
||
|
|
end
|
||
|
|
if ent:IsNPC() && spawnWepPicked != false && string.lower(spawnWepPicked) != "none" then
|
||
|
|
if string.lower(spawnWepPicked) == "default" then -- Default weapon from the spawn menu
|
||
|
|
local getDefWep = VJ_PICK(list.Get("NPC")[ent:GetClass()].Weapons)
|
||
|
|
if getDefWep then
|
||
|
|
ent:Give(getDefWep)
|
||
|
|
end
|
||
|
|
else
|
||
|
|
ent:Give(spawnWepPicked)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
self.CurrentEntities[spawnKey] = {Entities=spawnEnts, SpawnPosition=spawnPos, SpawnAngle=spawnAng, WeaponsList=spawnTbl.WeaponsList, NPC_Class=spawnNPCClass, FriToPlyAllies=spawnFriToPlyAllies, Ent=ent, Dead=false}
|
||
|
|
//table_remove(self.CurrentEntities, spawnKey)
|
||
|
|
//table.insert(self.CurrentEntities, spawnKey, {SpawnPosition=spawnPos, Entities=spawnEnts, WeaponsList=wepList, Ent=ent, Dead=false})
|
||
|
|
self:CustomOnEntitySpawn(ent, spawnKey, spawnTbl, initSpawn)
|
||
|
|
self:SpawnEntitySoundCode()
|
||
|
|
timer.Simple(0.1, function() if IsValid(self) && self.SingleSpawner == true then self:DoSingleSpawnerRemove() end end)
|
||
|
|
end
|
||
|
|
---------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
|
function ENT:Initialize()
|
||
|
|
self:CustomOnInitialize()
|
||
|
|
self:CustomOnInitialize_BeforeNPCSpawn() -- !!!!!!!!!!!!!! DO NOT USE THIS VARIABLE !!!!!!!!!!!!!! [Backwards Compatibility!]
|
||
|
|
if self:GetModel() == "models/error.mdl" then -- No model was detected
|
||
|
|
local mdls = VJ_PICK(self.Model)
|
||
|
|
if mdls && mdl !="models/props_junk/popcan01a.mdl" then
|
||
|
|
self:SetModel(mdls)
|
||
|
|
else -- No models found in self.Model
|
||
|
|
self:DrawShadow(false)
|
||
|
|
self:SetNoDraw(true)
|
||
|
|
self:SetNotSolid(true)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
self.CurrentEntities = {}
|
||
|
|
for spawnKey, spawnTbl in ipairs(self.EntitiesToSpawn) do
|
||
|
|
self:SpawnAnEntity(spawnKey, spawnTbl, true)
|
||
|
|
end
|
||
|
|
self:CustomOnInitialize_AfterNPCSpawn()
|
||
|
|
end
|
||
|
|
function ENT:CustomOnInitialize_BeforeNPCSpawn() end -- !!!!!!!!!!!!!! DO NOT USE THIS VARIABLE !!!!!!!!!!!!!! [Backwards Compatibility!]
|
||
|
|
// lua_run for spawnKey,spawnTbl in ipairs(ents.GetAll()) do if spawnTbl.IsVJBaseSpawner == true then spawnTbl.VJBaseSpawnerDisabled = false end end
|
||
|
|
---------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
|
function ENT:Think()
|
||
|
|
//print("-----------------------------------------------------------")
|
||
|
|
//PrintTable(self.CurrentEntities)
|
||
|
|
self:CustomOnThink()
|
||
|
|
self:IdleSoundCode()
|
||
|
|
|
||
|
|
-- If it's a continuous spawner then make sure to respawn any entity that has been removed
|
||
|
|
if self.VJBaseSpawnerDisabled == false && self.SingleSpawner == false then
|
||
|
|
for spawnKey, spawnTbl in ipairs(self.CurrentEntities) do
|
||
|
|
-- If entity is removed AND we are NOT already respawning it, then respawn!
|
||
|
|
if !IsValid(spawnTbl.Ent) && spawnTbl.Dead == false then
|
||
|
|
spawnTbl.Dead = true -- To make sure we do NOT respawn it more than once!
|
||
|
|
timer.Simple(self.TimedSpawn_Time, function()
|
||
|
|
if IsValid(self) then
|
||
|
|
self:SpawnAnEntity(spawnKey, spawnTbl, false)
|
||
|
|
end
|
||
|
|
end)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
self:CustomOnThink_AfterAliveChecks()
|
||
|
|
end
|
||
|
|
---------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
|
function ENT:IdleSoundCode()
|
||
|
|
if self.HasIdleSounds == false then return end
|
||
|
|
if CurTime() > self.NextIdleSoundT then
|
||
|
|
if math.random(1, self.IdleSoundChance) == 1 then
|
||
|
|
self.CurrentIdleSound = VJ_CreateSound(self, self.SoundTbl_Idle, self.IdleSoundLevel, math.random(self.IdleSoundPitch.a, self.IdleSoundPitch.b))
|
||
|
|
end
|
||
|
|
self.NextIdleSoundT = CurTime() + math.Rand(self.NextSoundTime_Idle.a, self.NextSoundTime_Idle.b)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
---------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
|
function ENT:SpawnEntitySoundCode()
|
||
|
|
if self.HasSpawnEntitySound == false then return end
|
||
|
|
if math.random(1, self.SpawnEntitySoundChance) then
|
||
|
|
self.CurrentSpawnEntitySound = VJ_CreateSound(self, self.SoundTbl_SpawnEntity, self.SpawnEntitySoundLevel, math.random(self.SpawnEntitySoundPitch.a, self.SpawnEntitySoundPitch.b))
|
||
|
|
end
|
||
|
|
end
|
||
|
|
---------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
|
function ENT:DoSingleSpawnerRemove()
|
||
|
|
if self.Dead then return end
|
||
|
|
if IsValid(self:GetCreator()) then
|
||
|
|
for _, spawnTbl in ipairs(self.CurrentEntities) do
|
||
|
|
if IsValid(spawnTbl.Ent) then
|
||
|
|
undo.Create(spawnTbl.Ent:GetName())
|
||
|
|
undo.AddEntity(spawnTbl.Ent)
|
||
|
|
undo.SetPlayer(self:GetCreator())
|
||
|
|
undo.Finish()
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
self.Dead = true
|
||
|
|
VJ_STOPSOUND(self.CurrentIdleSound)
|
||
|
|
self:Remove()
|
||
|
|
end
|
||
|
|
---------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
|
function ENT:OnRemove()
|
||
|
|
self:CustomOnRemove()
|
||
|
|
self.Dead = true
|
||
|
|
VJ_STOPSOUND(self.CurrentIdleSound)
|
||
|
|
|
||
|
|
-- If it's a continuous spawner then remove all the spawned entities!
|
||
|
|
if self.SingleSpawner == false && self.CurrentEntities != nil then
|
||
|
|
for _, spawnTbl in ipairs(self.CurrentEntities) do
|
||
|
|
if IsValid(spawnTbl.Ent) then
|
||
|
|
spawnTbl.Ent:Remove()
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|