Files
wnsrc/lua/autorun/hlr/autoreplace.lua
lifestorm 94063e4369 Upload
2024-08-04 22:55:00 +03:00

355 lines
13 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 CLIENT then return end
print("Executing Half-Life Resurgence auto replace script...")
-- https://developer.valvesoftware.com/wiki/Half-Life.fgd
-- https://developer.valvesoftware.com/wiki/Half_Life_2.fgd
local replaceTbl_Entities = {
-- Half-Life 1 --
["monster_alien_grunt"] = "npc_vj_hlr1_aliengrunt",
["monster_nihilanth"] = "npc_vj_hlr1_nihilanth",
["monster_tentacle"] = "npc_vj_hlr1_tentacle",
["monster_alien_slave"] = "npc_vj_hlr1_alienslave",
["monster_bigmomma"] = "npc_vj_hlr1_gonarch",
["monster_bullchicken"] = "npc_vj_hlr1_bullsquid",
["monster_gargantua"] = "npc_vj_hlr1_garg",
["monster_human_assassin"] = "npc_vj_hlr1_assassin_female",
["monster_babycrab"] = "npc_vj_hlr1_headcrab_baby",
-- ["monster_human_grunt"] = {"npc_vj_hlr1_hgrunt","npc_vj_hlrof_hgrunt","npc_vj_hlrof_hgrunt_med","npc_vj_hlrof_hgrunt_eng"},
["monster_human_grunt"] = "npc_vj_hlr1_hgrunt",
["monster_cockroach"] = "npc_vj_hlr1_cockroach",
["monster_houndeye"] = "npc_vj_hlr1_houndeye",
["monster_scientist"] = "npc_vj_hlr1_scientist",
["monster_sitting_scientist"] = "npc_vj_hlr1_scientist",
["monster_snark"] = "npc_vj_hlr1_snark",
["monster_zombie"] = {"npc_vj_hlr1_zombie","npc_vj_hlr1_zombie","npc_vj_hlr1_zombie","npc_vj_hlrof_zombie_sec","npc_vj_hlrof_zombie_sec","npc_vj_hlrof_zombie_soldier"},
["monster_headcrab"] = "npc_vj_hlr1_headcrab",
["monster_alien_controller"] = "npc_vj_hlr1_aliencontroller",
["monster_barney"] = "npc_vj_hlr1_securityguard",
["monster_turret"] = "npc_vj_hlr1_turret",
["monster_miniturret"] = "npc_vj_hlr1_turret_small",
["monster_sentry"] = "npc_vj_hlr1_sentry",
["monster_barnacle"] = "npc_vj_hlr1_barnacle",
["monster_ichthyosaur"] = "npc_vj_hlr1_ichthyosaur",
["monster_gman"] = "npc_vj_hlr1_gman",
["monster_apache"] = "npc_vj_hlr1_apache",
["monster_osprey"] = "npc_vj_hlr1_osprey",
["monster_turret"] = "npc_vj_hlr1_cturret",
["monster_miniturret"] = "npc_vj_hlr1_cturret_mini",
-- Half-Life 2 --
["npc_advisor"] = "npc_vj_hlr2_com_advisor",
["npc_alyx"] = "npc_vj_hlr2_alyx",
["npc_antlion"] = "npc_vj_hlr2_antlion",
["npc_antlion_worker"] = "npc_vj_hlr2_antlion_worker",
["npc_antlionguard"] = "npc_vj_hlr2_antlion_guard",
["npc_barney"] = "npc_vj_hlr2_barney",
["npc_citizen"] = "npc_vj_hlr2_citizen",
["npc_combine_s"] = "npc_vj_hlr2_com_soldier",
["npc_combinegunship"] = "npc_vj_hlr2_com_gunship",
["npc_crabsynth"] = "npc_vj_hlr2_com_crab",
["npc_fastzombie"] = "npc_vj_hlr2_zombie_fast",
["npc_gman"] = "npc_vj_hlr2_gman",
["npc_headcrab"] = "npc_vj_hlr2_headcrab",
["npc_headcrab_black"] = "npc_vj_hlr2_headcrab_poison",
["npc_headcrab_fast"] = "npc_vj_hlr2_headcrab_fast",
["npc_helicopter"] = "npc_vj_hlr2_com_chopper",
["npc_hunter"] = "npc_vj_hlr2_com_hunter",
["npc_metropolice"] = "npc_vj_hlr2_com_civilp",
["npc_monk"] = "npc_vj_hlr2_father_grigori",
["npc_mortarsynth"] = "npc_vj_hlr2_com_mortar",
["npc_poisonzombie"] = "npc_vj_hlr2_zombie_poison",
["npc_sniper"] = "npc_vj_hlr2_com_sniper",
["npc_stalker"] = "npc_vj_hlr2_com_stalker",
["npc_strider"] = "npc_vj_hlr2_com_strider",
["npc_turret_ceiling"] = "npc_vj_hlr2_com_ceilingturret",
["npc_turret_floor"] = "npc_vj_hlr2_com_sentry",
["npc_zombie"] = "npc_vj_hlr2_zombie",
["npc_zombine"] = "npc_vj_hlr2_zombine",
["prop_vehicle_apc"] = "npc_vj_hlr2_com_apc",
}
local replaceTbl_Weapons = {
-- Half-Life 2 --
["weapon_357"] = "weapon_vj_357",
["weapon_alyxgun"] = "weapon_vj_hlr2_alyxgun",
["weapon_annabelle"] = "weapon_vj_hlr2_annabelle",
["weapon_ar2"] = "weapon_vj_ar2",
["weapon_crossbow"] = "weapon_vj_crossbow",
["weapon_crowbar"] = "weapon_vj_crowbar",
["weapon_pistol"] = "weapon_vj_9mmpistol",
["weapon_rpg"] = "weapon_vj_hlr2_rpg",
["weapon_shotgun"] = "weapon_vj_spas12",
["weapon_smg1"] = "weapon_vj_smg1",
["weapon_stunstick"] = "weapon_vj_hlr2_stunstick"
}
local essentialTbl = { -- Will expand upon this later, I recommend we add support for custom HLR packs to add their own data to the auto-replace script (Example: Half-Life 2 HLR pack adding Kleiner or Breen to the auto-script)
-- Half-Life 2 --
npc_vj_hlr2_alyx=true,
npc_vj_hlr2_barney=true,
npc_vj_hlr2_father_grigori=true,
}
-- Before Create
local replaceOptions = {
-- If its an antlion guardian, then make sure to spawn that variant!
["npc_antlionguard"] = function(ent, replaceEnt)
return (ent:GetSkin() == 0 and "npc_vj_hlr2_antlion_guard") or "npc_vj_hlr2_antlion_guardian"
end,
-- Handle citizen / refugee / rebel variants
["npc_citizen"] = function(ent, replaceEnt)
for key, val in pairs(ent:GetKeyValues()) do
if key == "citizentype" then
if val == 0 or val == 1 then
return "npc_vj_hlr2_citizen"
elseif val == 2 then
return "npc_vj_hlr2_refugee"
elseif val == 3 or val == 4 then
return "npc_vj_hlr2_rebel"
end
end
end
end,
-- Handle combine soldier variants
["npc_combine_s"] = function(ent, replaceEnt)
local mdl = ent:GetModel()
if mdl == "models/combine_soldier.mdl" then
return (ent:GetSkin() == 0 and "npc_vj_hlr2_com_soldier") or "npc_vj_hlr2_com_shotgunner"
elseif mdl == "models/combine_soldier_prisonguard.mdl" then
return (ent:GetSkin() == 0 and "npc_vj_hlr2_com_prospekt") or "npc_vj_hlr2_com_prospekt_sg"
elseif mdl == "models/combine_super_soldier.mdl" then
return "npc_vj_hlr2_com_elite"
end
end,
-- Check for resistance turrets!
["npc_turret_floor"] = function(ent, replaceEnt)
return ent:HasSpawnFlags(SF_FLOOR_TURRET_CITIZEN) and "npc_vj_hlr2_res_sentry" or "npc_vj_hlr2_com_sentry"
end
}
-- Before Spawn
local replacePreSpawn = {
["npc_citizen"] = function(ent, newEnt)
if string.find(ent:GetModel(), "female") then
newEnt.Human_Gender = 1
else
newEnt.Human_Gender = 0
end
end,
["npc_metropolice"] = function(ent, newEnt)
for key, val in pairs(ent:GetKeyValues()) do
if key == manhacks && val == 0 then
newEnt.Metrocop_CanHaveManhack = false
end
end
end,
}
-- After Spawn
local afterSpawned = {
}
// lua_run PrintTable(Entity(1):GetEyeTrace().Entity:GetTable())
local defPos = Vector(0, 0, 0)
local gStatePrecriminal = false
local gStateAntlionFri = false
-- Prepare the HL1 and HL2 tables (This includes ALL NPCs!)
local allNPCs = list.Get("NPC")
local allHLR = {}
local allHLR1 = {}
local allHLR2 = {}
timer.Simple(0.01, function()
for k, _ in pairs(allNPCs) do
-- This should capture all the HL2 NPCs
if string.StartWith(k, "npc_vj_hlr2") then
table.insert(allHLR, k)
table.insert(allHLR2, k)
-- This should capture all the HL1 NPCs because many of them are "hlrof", "hlr1", "hlrsv", "hlrdc", etc.
elseif string.StartWith(k, "npc_vj_hlr") then
table.insert(allHLR, k)
table.insert(allHLR1, k)
end
end
end)
hook.Add("OnEntityCreated", "VJ_HLR_AutoReplace_EntCreate", function(ent)
local class = ent:GetClass()
local rEnt = VJ_PICK(replaceTbl_Entities[class])
if rEnt then
-- Make sure the game is loaded
if game && game.GetGlobalState then
gStatePrecriminal = game.GetGlobalState("gordon_precriminal") == 1
end
-- Check if it's HL1 & HL2 and stop if it's not supposed to continue
local isHL1 = string.StartWith(class, "monster_")
if isHL1 then
if GetConVar("vj_hlr_autoreplace_hl1"):GetInt() == 0 then
return
end
elseif GetConVar("vj_hlr_autoreplace_hl2"):GetInt() == 0 then
return
end
timer.Simple(0.01, function()
if IsValid(ent) then
local worldName = ent.GetName && ent:GetName() or nil
//if worldName == "rocketman" then return end -- Makes Odessa work a little bit
//local spawnAnim = ent:GetSequenceName(ent:GetSequence())
-- Spawn the correct entity (Ex: different combine or rebels/citizens)
if replaceOptions[class] then
rEnt = replaceOptions[class](ent, rEnt) or rEnt
end
-- FUN OPTION: Randomized NPC System
if GetConVar("vj_hlr_autoreplace_random"):GetInt() == 1 then
if GetConVar("vj_hlr_autoreplace_randommix"):GetInt() == 1 then
rEnt = VJ_PICK(allHLR) or rEnt
else
if isHL1 then
rEnt = VJ_PICK(allHLR1) or rEnt
else
rEnt = VJ_PICK(allHLR2) or rEnt
end
end
end
-- Start the actual final entity --
local newClass = VJ_PICK(rEnt)
local newEnt = ents.Create(newClass)
if !IsValid(newEnt) then MsgN("Entity [" .. newClass .. "] not valid (missing pack?), keeping original entity") return end
-- Certain entities need some checks before spawn (Ex: Citizen gender)
if replacePreSpawn[class] then
replacePreSpawn[class](ent, newEnt)
end
newEnt:SetPos(ent:GetPos() + Vector(0, 0, (class == "monster_barnacle" && -1) or 4))
newEnt:SetAngles(ent:GetAngles())
if IsValid(ent:GetParent()) then newEnt:SetParent(ent:GetParent()) end
if worldName && worldName != "" then newEnt:SetName(worldName) end
newEnt:Spawn()
newEnt:Activate()
-- Handle naming
if worldName && worldName != "" then -- Scripted NPC
newEnt.DisableWandering = true
end
-- Handle weapon
local wep = ent.GetActiveWeapon && ent:GetActiveWeapon() or false -- In case GetActiveWeapon is not in the ent's metatable
//print(worldName, wep)
if IsValid(wep) then
local foundWep = replaceTbl_Weapons[wep:GetClass()]
newEnt:Give(VJ_PICK(foundWep))
end
-- Handle enemy
local ene = ent.GetEnemy && ent:GetEnemy() or false -- In case GetEnemy is not in the ent's metatable
if IsValid(ene) then
newEnt:SetEnemy(ene)
end
-- Handle key values
for key, val in pairs(ent:GetSaveTable()) do
//print(ent, newEnt, key, val)
key = tostring(key)
if key == "health" then
newEnt:SetHealth(val)
elseif key == "max_health" then
newEnt:SetMaxHealth(val)
-- elseif key == "m_bSequenceLoops" && val == true && newEnt:GetInternalVariable("sequence") != -1 then
-- newEnt.Old_AnimTbl_IdleStand = newEnt.AnimTbl_IdleStand
-- newEnt.AnimTbl_IdleStand = {VJ_SequenceToActivity(newEnt,newEnt:GetInternalVariable("sequence"))}
-- newEnt:SetState(VJ_STATE_ONLY_ANIMATION_NOATTACK)
-- newEnt:VJ_ACT_PLAYACTIVITY(newEnt:GetInternalVariable("sequence"),true,false,false)
elseif key == "m_vecLastPosition" then
if val != defPos then
newEnt:SetLastPosition(val)
newEnt:VJ_TASK_GOTO_LASTPOS("TASK_WALK_PATH")
end
elseif key == "m_bShouldPatrol" && val == false then
newEnt.DisableWandering = true
-- Not what I thought it was, actual variable is m_LookDist using the function SetDistLook
-- Which both of them can't be accessed in Lua...
//elseif key == "m_flDistTooFar" then
//newEnt.SightDistance = val
end
end
//newEnt.SightDistance = 2048 -- Default Source engine sight distance...
-- Handle spawn flags
//if ent:HasSpawnFlags(SF_NPC_LONG_RANGE) then
//newEnt.SightDistance = 6000
//end
newEnt:SetKeyValue("spawnflags", ent:GetSpawnFlags())
if ent:HasSpawnFlags(SF_CITIZEN_NOT_COMMANDABLE) then
newEnt.FollowPlayer = false
end
//print(ent:GetInternalVariable("m_bShouldPatrol"))
-- Handle Gordon precriminal game state
if gStatePrecriminal == true then -- Toggles friendly-AI for the intro of Half-Life 2
//newEnt.DisableWandering = true
newEnt.DisableFindEnemy = true
newEnt.DisableMakingSelfEnemyToNPCs = true
newEnt.FriendsWithAllPlayerAllies = true
newEnt.FollowPlayer = false
newEnt.Behavior = VJ_BEHAVIOR_PASSIVE
newEnt.VJ_AutoScript_OldClass = newEnt.VJ_NPC_Class
newEnt.VJ_NPC_Class = {"CLASS_PLAYER_ALLY", "CLASS_COMBINE"}
newEnt.VJ_AutoScript_Reset = true
end
-- Things to run after it's fully spawned (EX: Turret sight distance)
if afterSpawned[rEnt] then
afterSpawned[rEnt](ent, newEnt)
end
-- Handle Essential NPCs
if GetConVar("vj_hlr_autoreplace_essential"):GetInt() == 1 && essentialTbl[newClass] then
newEnt.GodMode = true
end
-- FUN OPTION: Make them all allied together against players
if GetConVar("vj_hlr_autoreplace_alliedagainstply"):GetInt() == 1 then
newEnt.VJ_NPC_Class = {"CLASS_HALF_LIFE_AGAINST_PLAYERS"}
end
-- print(ent:GetClass(), ent:GetInternalVariable("GameEndAlly"))
-- Set the starting animation AND velocity
local vel = ent:GetVelocity()
timer.Simple(0.01, function()
if IsValid(newEnt) then
//newEnt:VJ_ACT_PLAYACTIVITY(spawnAnim, true, false, false)
if vel:Length() > 0 then
newEnt:SetGroundEntity(NULL)
newEnt:SetVelocity(vel)
end
end
end)
undo.ReplaceEntity(ent, newEnt)
ent:Remove()
end
end)
end
end)
hook.Add("Think", "VJ_HLR_AutoReplace_Think", function()
-- Make sure the game is loaded
if game && game.GetGlobalState then
gStatePrecriminal = game.GetGlobalState("gordon_precriminal") == 1
gStateAntlionFri = game.GetGlobalState("antlion_allied") == 1
end
for _,v in ipairs(ents.GetAll()) do
if v:IsNPC() then
if !gStatePrecriminal && v.VJ_AutoScript_Reset then
v.VJ_NPC_Class = v.VJ_AutoScript_OldClass
v.VJ_AutoScript_Reset = false
end
if gStateAntlionFri && v.VJ_HLR_Antlion then
table.insert(v.VJ_NPC_Class,"CLASS_PLAYER_ALLY")
v.PlayerFriendly = true
v.FriendsWithAllPlayerAllies = true
end
end
end
end)