Skip to content

Instantly share code, notes, and snippets.

@dhkatz
Last active September 24, 2017 05:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dhkatz/6534e3b8ab27110c7b97672c72d2bc18 to your computer and use it in GitHub Desktop.
Save dhkatz/6534e3b8ab27110c7b97672c72d2bc18 to your computer and use it in GitHub Desktop.
Spawn NPCs with a custom class and/or playermodel using a tool. Install to "garrysmod\lua\weapons\gmod_tool\stools"
TOOL.Category = "Event"
TOOL.Name = "Spawner"
TOOL.ClientConVar["type"] = "npc_citizen"
TOOL.ClientConVar["health"] = "500"
TOOL.ClientConVar["weapon"] = "none"
TOOL.ClientConVar["model"] = ""
TOOL.ClientConVar["proficiency"] = "AVERAGE"
TOOL.Information = {
{
name = "info",
stage = 1
},
{
name = "left"
},
{
name = "right"
}
}
if (CLIENT) then
language.Add("tool.swe_spawner.name", "Spawner")
language.Add("tool.swe_spawner.desc", "Spawn an NPC with custom attributes")
language.Add("tool.swe_spawner.left", "Spawn the custom NPC")
language.Add("tool.swe_spawner.right", "Get the class of the targeted NPC")
end
local proficiency = {
["POOR"] = WEAPON_PROFICIENCY_POOR,
["AVERAGE"] = WEAPON_PROFICIENCY_AVERAGE,
["GOOD"] = WEAPON_PROFICIENCY_GOOD,
["VERY GOOD"] = WEAPON_PROFICIENCY_VERY_GOOD,
["PERFECT"] = WEAPON_PROFICIENCY_PERFECT
}
function TOOL:SpawnNPC(Player, Position, Normal, Class, Equipment)
local NPCList = list.Get("NPC")
local NPCData = NPCList[Class]
if (not NPCData) then return end
if (NPCData.AdminOnly and not Player:IsAdmin()) then return end
local bDropToFloor = false
if (NPCData.OnCeiling and Vector(0, 0, -1):Dot(Normal) < 0.95) then return nil end
if (NPCData.OnFloor and Vector(0, 0, 1):Dot(Normal) < 0.95) then
return nil
else
bDropToFloor = true
end
if (NPCData.NoDrop) then
bDropToFloor = false
end
local Offset = NPCData.Offset or 32
Position = Position + Normal * Offset
local NPC = ents.Create(NPCData.Class)
if (not IsValid(NPC)) then return end
NPC:SetPos(Position)
local Angles = Angle(0, 0, 0)
if (IsValid(Player)) then
Angles = Player:GetAngles()
end
Angles.pitch = 0
Angles.roll = 0
Angles.yaw = Angles.yaw + 180
if (NPCData.Rotate) then
Angles = Angles + NPCData.Rotate
end
NPC:SetAngles(Angles)
if (NPCData.Model or self:GetClientInfo("model") ~= "") then
NPC:SetModel(self:GetClientInfo("model") or NPCData.Model)
end
if (NPCData.Material) then
NPC:SetMaterial(NPCData.Material)
end
local SpawnFlags = bit.bor(SF_NPC_FADE_CORPSE, SF_NPC_ALWAYSTHINK)
if (NPCData.SpawnFlags) then
SpawnFlags = bit.bor(SpawnFlags, NPCData.SpawnFlags)
end
if (NPCData.TotalSpawnFlags) then
SpawnFlags = NPCData.TotalSpawnFlags
end
NPC:SetKeyValue("spawnflags", SpawnFlags)
if (NPCData.KeyValues) then
for k, v in pairs(NPCData.KeyValues) do
NPC:SetKeyValue(k, v)
end
end
if (NPCData.Skin) then
NPC:SetSkin(NPCData.Skin)
end
local valid = false
for _, v in pairs(list.Get("NPCUsableWeapons")) do
if v.class == Equipment then
valid = true
break
end
end
if (Equipment and Equipment ~= "none" and valid) then
NPC:SetKeyValue("additionalequipment", Equipment)
NPC.Equipment = Equipment
end
DoPropSpawnedEffect(NPC)
NPC:Spawn()
NPC:Activate()
if (bDropToFloor and not NPCData.OnCeiling) then
NPC:DropToFloor()
end
return NPC
end
function TOOL:LeftClick(trace)
if (CLIENT) then return true end
local NPC_type = self:GetClientInfo("type")
local NPC_wep = self:GetClientInfo("weapon")
local NPC_health = self:GetClientInfo("health")
local NPC_prof = self:GetClientInfo("proficiency")
local ent = self:SpawnNPC(self:GetOwner(), trace.HitPos, trace.HitNormal, NPC_type, NPC_wep)
if (not ent:IsValid()) then return true end
ent:SetHealth(NPC_health)
ent:SetCurrentWeaponProficiency(proficiency[NPC_prof])
undo.Create("NPC")
undo.AddEntity(ent)
undo.SetPlayer(self:GetOwner())
undo.Finish()
self:GetOwner():AddCleanup("npcs", ent)
return true
end
function TOOL:RightClick(trace)
if game.SinglePlayer() then
self:GetOwner():PrintMessage(3, "Right click does not work in singleplayer!")
return false
end
if not (trace.Hit and IsValid(trace.Entity) and trace.Entity:IsNPC()) then
return false
end
if CLIENT then
self:GetOwner():PrintMessage(3, "Found NPC!")
SetClipboardText(trace.Entity:GetClass())
end
return true
end
function GetNPCModels(dir)
local realDir = dir .. "/*"
local files, folders = file.Find(realDir, "MOD")
local ModelFiles = {}
for _, v in pairs(folders) do
if not v then continue end
if string.GetExtensionFromFilename(v) == nil then
table.Add(ModelFiles, GetNPCModels(dir .. "/" .. v))
end
end
for _, v in pairs(files) do
if string.GetExtensionFromFilename(v) == "mdl" then
-- for a, pm in pairs(player_manager.AllValidModels()) do
-- if string.find(pm, v) then
-- fileFound = true
-- break
-- end
-- end
--if not fileFound and util.IsValidRagdoll(realDir .. v) then
-- if string.find(v, "keller") then
-- print(string.sub( realDir, 1, string.len( realDir ) - 1 ) .. v)
-- end
local mdl = string.sub(realDir, 1, string.len(realDir) - 1) .. v
--if util.IsValidRagdoll(mdl) then
--print(string.sub( realDir, 1, string.len( realDir ) - 1 ) .. v)
table.insert(ModelFiles, mdl)
--end
end
end
return ModelFiles
end
local ConVarsDefault = TOOL:BuildConVarList()
function TOOL.BuildCPanel(CPanel)
-- START PRESET DROPDOWN --
local Preset = vgui.Create("ControlPresets")
Preset:SetPreset("event_spawner")
Preset:AddOption("Default", ConVarsDefault)
for k, v in pairs(table.GetKeys(ConVarsDefault)) do
Preset:AddConVar(v)
end
CPanel:AddPanel(Preset)
-- END PRESET DROPDOWN --
local TypeList = vgui.Create("DListView")
TypeList:SizeToContents(true)
TypeList:SetHeight(300)
TypeList:SetMultiSelect(false)
TypeList:AddColumn("NPC")
local prevClass = {}
for k, v in pairs(list.Get("NPC")) do
if (prevClass[v.Class]) then continue end
TypeList:AddLine(v.Class)
prevClass[v.Class] = true
end
TypeList:SortByColumn(1)
TypeList.OnRowSelected = function(panel, row)
RunConsoleCommand("swe_spawner_type", panel:GetLine(row):GetColumnText(1))
end
CPanel:AddItem(TypeList)
local WeaponList = vgui.Create("DListView")
WeaponList:SizeToContents(true)
WeaponList:SetHeight(300)
WeaponList:SetMultiSelect(false)
WeaponList:AddColumn("Weapons")
for k, v in pairs(list.Get("NPCUsableWeapons")) do
WeaponList:AddLine(v.class)
end
WeaponList:SortByColumn(1)
WeaponList.OnRowSelected = function(panel, row)
RunConsoleCommand("swe_spawner_weapon", panel:GetLine(row):GetColumnText(1))
end
CPanel:AddItem(WeaponList)
-- START MODEL LIST --
-- local ModelList = vgui.Create("DListView")
-- ModelList:SizeToContents(true)
-- ModelList:SetHeight(300)
-- ModelList:SetMultiSelect(true)
-- ModelList:AddColumn("Models")
-- local NPCModels = GetNPCModels("models")
-- local prevModel = {}
-- for k, v in pairs(NPCModels) do
-- if prevModel[v] then continue end
-- ModelList:AddLine(v)
-- prevModel[v] = true
-- end
-- ModelList:SortByColumn(1)
-- ModelList.OnRowSelected = function(panel, row)
-- RunConsoleCommand("swe_spawner_model", panel:GetLine(row):GetColumnText(1))
-- end
-- CPanel:AddItem(ModelList)
-- END MODEL LIST --
CPanel:TextEntry("Model Override", "swe_spawner_model")
CPanel:NumSlider("Health:", "swe_spawner_health", 1, 10000, 2)
local Prof = vgui.Create("DComboBox")
Prof:SetValue("Proficiency")
for k, v in pairs(proficiency) do
Prof:AddChoice(k)
end
Prof.OnSelect = function(panel, index, value)
RunConsoleCommand("swe_spawner_proficiency", value)
end
CPanel:AddItem(Prof)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment