Compare commits
No commits in common. "d9415d880f682d0a4b5030dc089bdb49542ffeca" and "85eb62a495f8a7564bfd4ed0c430ac804b83ae73" have entirely different histories.
d9415d880f
...
85eb62a495
6 changed files with 149 additions and 290 deletions
26
README.md
26
README.md
|
|
@ -2,31 +2,21 @@
|
||||||
|
|
||||||
Adds better NPC integration for the Garry's Mod addon Z-City. While Z-City has a convar that enables the custom health system on NPCs, it really isn't the best or most advanced thing in the world. This has irritated me since I first started using Z-City. Therefore, I've decided to take care of the problem myself with my own plugin.
|
Adds better NPC integration for the Garry's Mod addon Z-City. While Z-City has a convar that enables the custom health system on NPCs, it really isn't the best or most advanced thing in the world. This has irritated me since I first started using Z-City. Therefore, I've decided to take care of the problem myself with my own plugin.
|
||||||
|
|
||||||
- NPCs can be ragdolled like players can, and will wiggle around on the ground. They can get back up, too!
|
- NPCs can now be alive while ragdolled, and can move around in that state.
|
||||||
- It takes all elements of Z-City's health system into account, such as unconsciousness and pain.
|
- NPCs can collapse due to unconsciousness or pain.
|
||||||
- Various configurable settings are included, allowing you to tweak the mod to your liking.
|
- NPCs can get back up after being ragdolled.
|
||||||
|
- Various performance settings are included, with the biggest one being automatic corpse removal.
|
||||||
|
|
||||||
This mod is built to perform reasonably well, thus it includes optimizations, configurable performance settings, and an automatic corpse remover.
|
This plugin is based off of Kazarei's Euphoria, which in turn is a fork of Fedhoria by Rama. Credits to them for making the cool thing.
|
||||||
|
|
||||||
This addon is based off of Kazarei's Euphoria, which in turn is a fork of Fedhoria by Rama. Credits to them for making the cool thing.
|
|
||||||
|
|
||||||
## Known issues
|
## Known issues
|
||||||
|
|
||||||
- Bandages, tourniquets, etc. that are on the ragdoll or NPC body will not be there when they get back up. Don't know how to fix this unfortunately.
|
- Kicking NPCs does not knock them down. This is not something I can easily fix -- I would have to override code in Z-City, which I would rather not do.
|
||||||
- NPCs currently instantly get up, with no animation. I plan on remedying this in the future.
|
- NPCs currently instantly get up, with no animation. I plan on remedying this in the future.
|
||||||
- Enemy NPCs will not target living downed NPCs like how they do players. This will be fixed.
|
|
||||||
|
|
||||||
## Compatibility
|
## Incompatibilities
|
||||||
|
|
||||||
This should be compatible with:
|
- Any mod that modifies the behavior of death ragdolls (Reagdoll, Artagdoll, Fedhoria)
|
||||||
|
|
||||||
- The majority of NPC AI improvement mods
|
|
||||||
- Competently-programmed Z-City addons
|
|
||||||
|
|
||||||
It is, however, not compatbile with:
|
|
||||||
|
|
||||||
- Most mods that modify the behavior of death ragdolls (Reagdoll, Artagdoll, especially Fedhoria.)
|
|
||||||
- Mods that automatically remove death ragdolls (it will delete all ragdolled NPCs, even if they're still alive! Try the built-in automatic corpse removal instead.)
|
|
||||||
|
|
||||||
## Future plans
|
## Future plans
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,34 +1,11 @@
|
||||||
local function PopulateCustomNPCSBXToolMenu(pnl)
|
|
||||||
local modded_npc_whitelist = CreateConVar("zcnpci_modded_npc_whitelist", "NPC-classes-here!", bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
|
|
||||||
|
|
||||||
pnl:Help("ZCNPCi has support for both modded NPCs, as well as base-game humanoid NPCs that Z-City never added. There is no guarantee that modded NPCs will work, but ones with similar skeletal structure to other base-game humanoid NPCs will generally work better.")
|
|
||||||
|
|
||||||
pnl:CheckBox("Allow base-game extended NPCs", "zcnpci_allow_extended_base_npcs")
|
|
||||||
pnl:ControlHelp("Enable or disables applying custom health system to most other base-game humanoid NPCs, such as Kleiner.")
|
|
||||||
|
|
||||||
pnl:CheckBox("Allow modded NPCs", "zcnpci_allow_modded_npcs")
|
|
||||||
pnl:ControlHelp("Enable or disables applying custom health system to modded NPCs.")
|
|
||||||
|
|
||||||
pnl:CheckBox("Auto enable for all humanoid NPCs", "zcnpci_auto_enable_humanoid_npcs")
|
|
||||||
pnl:ControlHelp("If enabled, NPCs will automatically have the health system applied to them if they have a standard humanoid skeleton.")
|
|
||||||
|
|
||||||
pnl:Help("List of enabled modded NPC classes")
|
|
||||||
|
|
||||||
local text = vgui.Create("DTextEntry")
|
|
||||||
text:SetMultiline(true)
|
|
||||||
text:SetTall(200)
|
|
||||||
text:SetValue(modded_npc_whitelist:GetString())
|
|
||||||
|
|
||||||
text.OnChange = function (self)
|
|
||||||
RunConsoleCommand("zcnpci_set_modded_npc_whitelist", text:GetValue())
|
|
||||||
end
|
|
||||||
|
|
||||||
pnl:AddItem(text)
|
|
||||||
|
|
||||||
pnl:Help("One NPC class per line. No spaces or other characters. Can only be set by a superadmin or server operator.")
|
|
||||||
end
|
|
||||||
|
|
||||||
local function PopulateRagdollSBXToolMenu(pnl)
|
local function PopulateRagdollSBXToolMenu(pnl)
|
||||||
|
pnl:CheckBox("Enabled", "zcnpci_enabled")
|
||||||
|
pnl:ControlHelp("Enable or disable the addon.")
|
||||||
|
|
||||||
|
pnl:Help(" ")
|
||||||
|
|
||||||
|
pnl:Help(" ")
|
||||||
|
|
||||||
pnl:NumSlider("Stumble time", "zcnpci_stumble_time", 0, 10, 3)
|
pnl:NumSlider("Stumble time", "zcnpci_stumble_time", 0, 10, 3)
|
||||||
pnl:ControlHelp("How long the ragdoll should try to stumble for.")
|
pnl:ControlHelp("How long the ragdoll should try to stumble for.")
|
||||||
|
|
||||||
|
|
@ -43,15 +20,8 @@ local function PopulateRagdollSBXToolMenu(pnl)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function PopulatePerformanceSBXToolMenu(pnl)
|
local function PopulatePerformanceSBXToolMenu(pnl)
|
||||||
pnl:NumSlider("NPC ticks per second", "zcnpci_tps", 1, 66, 0)
|
pnl:NumSlider("Activation range", "zcnpci_active_range", 0, 5000, 0)
|
||||||
pnl:ControlHelp("How many times NPCs should be processed per second. Will make them more responsive at the cost of performance.")
|
pnl:ControlHelp("How close the ragdoll has to be to a player to be living when downed by damage. Enemies downed by other causes are unaffected.")
|
||||||
|
|
||||||
pnl:Help(" ")
|
|
||||||
|
|
||||||
pnl:Help(" ")
|
|
||||||
|
|
||||||
pnl:NumSlider("Activation range", "zcnpci_active_range", 0, 32768, 0)
|
|
||||||
pnl:ControlHelp("How close the ragdoll has to be to a player to live when downed by direct damage. Enemies downed by other causes are unaffected.")
|
|
||||||
|
|
||||||
pnl:CheckBox("Always activate on player kill", "zcnpci_always_active_on_player_kill")
|
pnl:CheckBox("Always activate on player kill", "zcnpci_always_active_on_player_kill")
|
||||||
pnl:ControlHelp("If on, all player-damaged ragdolls will be activated regardless of other factors.")
|
pnl:ControlHelp("If on, all player-damaged ragdolls will be activated regardless of other factors.")
|
||||||
|
|
@ -63,9 +33,6 @@ local function PopulatePerformanceSBXToolMenu(pnl)
|
||||||
pnl:CheckBox("Enable automatic corpse removal", "zcnpci_enable_corpse_removal")
|
pnl:CheckBox("Enable automatic corpse removal", "zcnpci_enable_corpse_removal")
|
||||||
pnl:ControlHelp("Enable or disable the removal of dead corpses.")
|
pnl:ControlHelp("Enable or disable the removal of dead corpses.")
|
||||||
|
|
||||||
pnl:NumSlider("Corpse time between loops", "zcnpci_corpse_loop_time", 1, 66, 0)
|
|
||||||
pnl:ControlHelp("How long should we wait in between checks?")
|
|
||||||
|
|
||||||
pnl:NumSlider("Max corpses", "zcnpci_max_corpses", -1, 64, 0)
|
pnl:NumSlider("Max corpses", "zcnpci_max_corpses", -1, 64, 0)
|
||||||
pnl:ControlHelp("The maximum amount of dead corpses that are allowed before one is removed. Set to -1 to disable")
|
pnl:ControlHelp("The maximum amount of dead corpses that are allowed before one is removed. Set to -1 to disable")
|
||||||
|
|
||||||
|
|
@ -75,53 +42,30 @@ local function PopulatePerformanceSBXToolMenu(pnl)
|
||||||
pnl:NumSlider("Max distance between player", "zcnpci_max_corpse_distance", -1, 32768, 2)
|
pnl:NumSlider("Max distance between player", "zcnpci_max_corpse_distance", -1, 32768, 2)
|
||||||
pnl:ControlHelp("If the corpse is further than this distance, it will be removed. Set to -1 to disable")
|
pnl:ControlHelp("If the corpse is further than this distance, it will be removed. Set to -1 to disable")
|
||||||
|
|
||||||
pnl:NumSlider("Min distance between player", "zcnpci_min_corpse_distance", 0, 32768, 2)
|
pnl:CheckBox("Never remove corpses near the player", "zcnpci_disable_corpse_removal_near_player")
|
||||||
pnl:ControlHelp("If the corpse is closer than this distance, it will never be cleared.")
|
pnl:ControlHelp("If on, corpses under the variable above in distance will never be cleared.")
|
||||||
|
|
||||||
pnl:CheckBox("Treat crippled NPCs as dead", "zcnpci_treat_crippled_as_dead")
|
pnl:CheckBox("Treat crippled NPCs as dead", "zcnpci_treat_crippled_as_dead")
|
||||||
pnl:ControlHelp("If on, bodies with amputations or both legs broken will be clearable.")
|
pnl:ControlHelp("If on, corpses with amputations or both legs broken will be clearable.")
|
||||||
|
|
||||||
pnl:CheckBox("Treat unconscious NPCs as dead", "zcnpci_treat_unconscious_as_dead")
|
|
||||||
pnl:ControlHelp("If on, bodies that are unconscious will be clearable.")
|
|
||||||
|
|
||||||
pnl:CheckBox("Treat near-death NPCs as dead", "zcnpci_treat_near_death_as_dead")
|
pnl:CheckBox("Treat near-death NPCs as dead", "zcnpci_treat_near_death_as_dead")
|
||||||
pnl:ControlHelp("If on, bodies near death (severe blood loss, comas, etc.) will be clearable.")
|
pnl:ControlHelp("If on, corpses near death (severe blood loss, comas, etc.) will be clearable.")
|
||||||
end
|
end
|
||||||
|
|
||||||
local function PopulateMainSBXToolMenu(pnl)
|
|
||||||
pnl:CheckBox("Enabled", "zcnpci_enabled")
|
|
||||||
pnl:ControlHelp("Enable or disable the addon.")
|
|
||||||
|
|
||||||
pnl:Help("This addon was developed by ToasterPanic.")
|
|
||||||
|
|
||||||
pnl:Help("It is based on Kazarei's Euphoria, which in turn is a fork of Fedhoria by Rama. Their work powers the ragdoll movement.")
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
if engine.ActiveGamemode() == "sandbox" then
|
if engine.ActiveGamemode() == "sandbox" then
|
||||||
hook.Add("AddToolMenuCategories", "ZCNPCICategory", function()
|
hook.Add("AddToolMenuCategories", "ZCNPCICategory", function()
|
||||||
spawnmenu.AddToolCategory("Utilities", "zcnpci", "Z-City NPCi")
|
spawnmenu.AddToolCategory("Utilities", "zcnpci", "Z-City NPCi")
|
||||||
end)
|
end)
|
||||||
|
|
||||||
hook.Add("PopulateToolMenu", "ZCNPCIMenuSettings", function()
|
hook.Add("PopulateToolMenu", "ZCNPCIMenuSettings", function()
|
||||||
spawnmenu.AddToolMenuOption("Utilities", "zcnpci", "ModdedNPCSettings", "Custom NPCs", "", "", function(pnl)
|
spawnmenu.AddToolMenuOption("Utilities", "zcnpci", "RagdollSettings", "Ragdoll", "", "", function(pnl)
|
||||||
pnl:ClearControls()
|
pnl:ClearControls()
|
||||||
PopulateCustomNPCSBXToolMenu(pnl)
|
PopulateRagdollSBXToolMenu(pnl)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
spawnmenu.AddToolMenuOption("Utilities", "zcnpci", "PerformanceSettings", "Performance", "", "", function(pnl)
|
spawnmenu.AddToolMenuOption("Utilities", "zcnpci", "PerformanceSettings", "Performance", "", "", function(pnl)
|
||||||
pnl:ClearControls()
|
pnl:ClearControls()
|
||||||
PopulatePerformanceSBXToolMenu(pnl)
|
PopulatePerformanceSBXToolMenu(pnl)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
spawnmenu.AddToolMenuOption("Utilities", "zcnpci", "RagdollSettings", "Ragdoll", "", "", function(pnl)
|
|
||||||
pnl:ClearControls()
|
|
||||||
PopulateRagdollSBXToolMenu(pnl)
|
|
||||||
end)
|
|
||||||
|
|
||||||
spawnmenu.AddToolMenuOption("Utilities", "zcnpci", "MainSettings", "Main", "", "", function(pnl)
|
|
||||||
pnl:ClearControls()
|
|
||||||
PopulateMainSBXToolMenu(pnl)
|
|
||||||
end)
|
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
254
lua/zcnpci.lua
254
lua/zcnpci.lua
|
|
@ -1,57 +1,23 @@
|
||||||
include("zcnpci/modules.lua")
|
include("zcnpci/modules.lua")
|
||||||
|
|
||||||
local enabled = CreateConVar("zcnpci_enabled", 1, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
|
local enabled = CreateConVar("zcnpci_enabled", 1, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
|
||||||
local active_range = CreateConVar("zcnpci_active_range", 32768, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
|
local active_range = CreateConVar("zcnpci_active_range", 3000, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
|
||||||
local always_active_on_player_kill = CreateConVar("zcnpci_always_active_on_player_kill", 1, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
|
local always_active_on_player_kill = CreateConVar("zcnpci_always_active_on_player_kill", 1, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
|
||||||
local ticks_per_second = CreateConVar("zcnpci_tps", 20, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
|
|
||||||
|
|
||||||
local remove_corpses = CreateConVar("zcnpci_enable_corpse_removal", 0, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
|
local remove_corpses = CreateConVar("zcnpci_enable_corpse_removal", 0, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
|
||||||
local corpse_loop_time = CreateConVar("zcnpci_corpse_loop_time", 2.0, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
|
|
||||||
local max_corpses = CreateConVar("zcnpci_max_corpses", 8, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
|
local max_corpses = CreateConVar("zcnpci_max_corpses", 8, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
|
||||||
local max_corpse_time = CreateConVar("zcnpci_max_corpse_time", 120, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
|
local max_corpse_time = CreateConVar("zcnpci_max_corpse_time", 120, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
|
||||||
local min_corpse_distance = CreateConVar("zcnpci_min_corpse_distance", 500, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
|
|
||||||
local max_corpse_distance = CreateConVar("zcnpci_max_corpse_distance", 2500, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
|
local max_corpse_distance = CreateConVar("zcnpci_max_corpse_distance", 2500, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
|
||||||
local no_corpse_removal_near_player = CreateConVar("zcnpci_disable_corpse_removal_near_player", 0, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
|
local no_corpse_removal_near_player = CreateConVar("zcnpci_disable_corpse_removal_near_player", 0, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
|
||||||
local treat_crippled_as_dead = CreateConVar("zcnpci_treat_crippled_as_dead", 1, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
|
local treat_crippled_as_dead = CreateConVar("zcnpci_treat_crippled_as_dead", 1, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
|
||||||
local treat_unconscious_as_dead = CreateConVar("zcnpci_treat_unconscious_as_dead", 1, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
|
|
||||||
local treat_near_death_as_dead = CreateConVar("zcnpci_treat_near_death_as_dead", 1, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
|
local treat_near_death_as_dead = CreateConVar("zcnpci_treat_near_death_as_dead", 1, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
|
||||||
|
|
||||||
local allow_extended_base_npcs = CreateConVar("zcnpci_allow_extended_base_npcs", 1, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
|
local debug_ragdoll_all = CreateConVar("zcnpci_debug_ragdoll_all", 0, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED, FCVAR_PROTECTED))
|
||||||
local allow_modded_npcs = CreateConVar("zcnpci_allow_modded_npcs", 0, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
|
|
||||||
local auto_enable_humanoid_npcs = CreateConVar("zcnpci_auto_enable_humanoid_npcs", 1, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
|
|
||||||
local modded_npc_whitelist = CreateConVar("zcnpci_modded_npc_whitelist", "nb_example", bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
|
|
||||||
|
|
||||||
-- The way I have to set up the npc whitelist client-side makes it so the host can't configure it without console commands, so we have to do this shit
|
|
||||||
local set_modded_npc_whitelist = concommand.Add("zcnpci_set_modded_npc_whitelist", function(ply, cmd, args)
|
|
||||||
if !IsValid(ply) or !args[1] then return end
|
|
||||||
|
|
||||||
if !ply:IsSuperAdmin() then return end
|
|
||||||
|
|
||||||
modded_npc_whitelist:SetString(args[1])
|
|
||||||
end)
|
|
||||||
|
|
||||||
local debug_ragdoll_all = CreateConVar("zcnpci_debug_ragdoll_all", 0, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
|
|
||||||
|
|
||||||
local last_dmgpos = {}
|
local last_dmgpos = {}
|
||||||
local last_hitgroup = {}
|
local last_hitgroup = {}
|
||||||
local last_attacker = {}
|
local last_attacker = {}
|
||||||
|
|
||||||
local npcs_to_fake = {}
|
|
||||||
|
|
||||||
-- These NPCs do not have organisms by default, despite being humanoid characters built into the game.
|
|
||||||
local base_npc_whitelist = {
|
|
||||||
"npc_kleiner",
|
|
||||||
"npc_breen",
|
|
||||||
"npc_barney",
|
|
||||||
"npc_alyx",
|
|
||||||
"npc_eli",
|
|
||||||
"npc_gman",
|
|
||||||
"npc_magnusson",
|
|
||||||
"npc_mossman",
|
|
||||||
"npc_odessa",
|
|
||||||
"npc_monk"
|
|
||||||
}
|
|
||||||
|
|
||||||
local corpses = {}
|
local corpses = {}
|
||||||
|
|
||||||
local last_corpse_tick = CurTime()
|
local last_corpse_tick = CurTime()
|
||||||
|
|
@ -100,33 +66,6 @@ hook.Add("CreateEntityRagdoll", "zcnpci", function(ent, ragdoll)
|
||||||
|
|
||||||
ragdoll.class_in_previous_life = ent:GetClass()
|
ragdoll.class_in_previous_life = ent:GetClass()
|
||||||
|
|
||||||
if !ragdoll.organism then
|
|
||||||
ragdoll.inventory = {}
|
|
||||||
ragdoll.inventory.Weapons = {}
|
|
||||||
|
|
||||||
hg.organism.Add(ragdoll)
|
|
||||||
table.Merge(ragdoll.organism, ent.organism)
|
|
||||||
|
|
||||||
hook.Run("RagdollDeath", ent, ragdoll)
|
|
||||||
|
|
||||||
ragdoll.organism.owner = ragdoll
|
|
||||||
ragdoll:CallOnRemove("organism", hg.organism.Remove, ragdoll)
|
|
||||||
ragdoll.organism.owner.fullsend = true
|
|
||||||
hg.send_bareinfo(ragdoll.organism)
|
|
||||||
|
|
||||||
ent.organism = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
if ent.npcfakeknockback then
|
|
||||||
ragdoll:GetPhysicsObject():SetVelocity(ent.npcfakeknockback)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- For some reason, citizen types such as rebels, medics, refugees, etc. use a keyvalue.
|
|
||||||
-- That keyvalue does not transfer over to the ragdoll, despite it looking like the NPC,
|
|
||||||
-- and you have to manually save it to the ragdoll to be able to make it work.
|
|
||||||
-- Why is it like this? Fuck if I know, I just know I don't wanna deal with it again.
|
|
||||||
ragdoll.citizentype = ent:GetInternalVariable("citizentype")
|
|
||||||
|
|
||||||
timer.Simple(0, function()
|
timer.Simple(0, function()
|
||||||
ragdoll.organism.alive = true
|
ragdoll.organism.alive = true
|
||||||
|
|
||||||
|
|
@ -137,60 +76,24 @@ hook.Add("CreateEntityRagdoll", "zcnpci", function(ent, ragdoll)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
hook.Add("HomigradDamage", "zcnpci", function(ent, dmginfo)
|
hook.Add("EntityTakeDamage", "zcnpci", function(ent, dmginfo)
|
||||||
if !enabled:GetBool() or !IsValid(dmginfo) then return end
|
if !enabled:GetBool() then return end
|
||||||
if !ent:IsNPC() then
|
if (!ent:IsNPC() or dmginfo:GetDamage() < ent:Health()) then return end
|
||||||
if !ent.organism or !ent.StartDie then return end
|
|
||||||
|
|
||||||
if dmginfo:IsDamageType(DMG_BULLET + DMG_BUCKSHOT + DMG_BLAST + DMG_CLUB + DMG_SLASH + DMG_GENERIC) then
|
last_dmgpos[ent] = dmginfo:GetDamagePosition()
|
||||||
-- Reset ragdoll get up timer -- don't want someone getting up mid-curbstomp
|
|
||||||
ent.StartDie = CurTime()
|
|
||||||
end
|
|
||||||
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
last_dmgpos[ent] = dmginfo:GetDamage()
|
|
||||||
last_attacker[ent] = dmginfo:GetAttacker()
|
last_attacker[ent] = dmginfo:GetAttacker()
|
||||||
|
|
||||||
if dmginfo:IsDamageType(DMG_BULLET + DMG_BUCKSHOT + DMG_BLAST) then
|
|
||||||
if dmginfo:GetDamage() > 3 then
|
|
||||||
table.insert(npcs_to_fake, ent)
|
|
||||||
end
|
|
||||||
elseif dmginfo:IsDamageType(DMG_CLUB + DMG_SLASH) then
|
|
||||||
local fists = dmginfo:GetAttacker():GetWeapon("weapon_hands_sh")
|
|
||||||
if !IsValid(fists) then fists = dmginfo:GetAttacker():GetWeapon("weapon_hg_coolhands") end
|
|
||||||
|
|
||||||
local attacker = dmginfo:GetAttacker()
|
|
||||||
|
|
||||||
print(fists.InLegKick)
|
|
||||||
|
|
||||||
-- Kicks should knock NPCs down
|
|
||||||
if IsValid(dmginfo:GetInflictor()) and IsValid(fists) and attacker.InLegKick and ((attacker.InLegKick + 0.1) > CurTime()) then
|
|
||||||
table.insert(npcs_to_fake, ent)
|
|
||||||
print("ADD TO LIST!!!")
|
|
||||||
|
|
||||||
local attacker_angle = dmginfo:GetAttacker():EyeAngles()
|
|
||||||
|
|
||||||
local normal = attacker_angle:Forward(normal)
|
|
||||||
|
|
||||||
ent.npcfakeknockback = normal * dmginfo:GetDamage() * 135
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
hook.Add("ScaleNPCDamage", "zcnpci", function(npc, hitgroup, dmginfo)
|
hook.Add("ScaleNPCDamage", "zcnpci", function(npc, hitgroup, dmginfo)
|
||||||
if !IsValid(npc) then return end
|
if not IsValid(npc) then return end
|
||||||
last_hitgroup[npc] = hitgroup
|
last_hitgroup[npc] = hitgroup
|
||||||
end)
|
end)
|
||||||
|
|
||||||
hook.Add("Tick", "zcnpci", function()
|
hook.Add("Think", "zcnpci", function()
|
||||||
local do_corpse_loop = (CurTime() - last_corpse_tick) > corpse_loop_time:GetFloat()
|
local do_corpse_loop = (CurTime() - last_corpse_tick) > 2.0
|
||||||
local do_general_loop = (CurTime() - last_tick) > (1 / ticks_per_second:GetInt())
|
local do_general_loop = (CurTime() - last_tick) > 0.1
|
||||||
|
|
||||||
if do_general_loop then
|
if do_general_loop then
|
||||||
last_tick = CurTime()
|
|
||||||
|
|
||||||
if do_corpse_loop then
|
if do_corpse_loop then
|
||||||
last_corpse_tick = CurTime()
|
last_corpse_tick = CurTime()
|
||||||
|
|
||||||
|
|
@ -208,6 +111,7 @@ hook.Add("Tick", "zcnpci", function()
|
||||||
table.remove(corpses, 1)
|
table.remove(corpses, 1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for i, ent in pairs(ents.GetAll()) do
|
for i, ent in pairs(ents.GetAll()) do
|
||||||
if !IsValid(ent) then continue end
|
if !IsValid(ent) then continue end
|
||||||
if !ent.organism then continue end
|
if !ent.organism then continue end
|
||||||
|
|
@ -221,10 +125,15 @@ hook.Add("Tick", "zcnpci", function()
|
||||||
(ent.organism.consciousness <= 0.3) or
|
(ent.organism.consciousness <= 0.3) or
|
||||||
(ent.organism.pain > 90) or
|
(ent.organism.pain > 90) or
|
||||||
ent:IsOnFire() or
|
ent:IsOnFire() or
|
||||||
ent.neednpcfake or
|
debug_ragdoll_all:GetBool()
|
||||||
debug_ragdoll_all:GetBool()
|
|
||||||
) then
|
) then
|
||||||
table.insert(npcs_to_fake, ent)
|
local damage_info = DamageInfo()
|
||||||
|
damage_info:SetDamage(ent:Health())
|
||||||
|
damage_info:SetAttacker(ent)
|
||||||
|
damage_info:SetDamageType( DMG_DIRECT )
|
||||||
|
damage_info:SetDamageForce(Vector(0, 0, 0))
|
||||||
|
|
||||||
|
ent:TakeDamageInfo(damage_info)
|
||||||
end
|
end
|
||||||
elseif do_corpse_loop and remove_corpses and ent.is_npc_corpse then
|
elseif do_corpse_loop and remove_corpses and ent.is_npc_corpse then
|
||||||
local clearable = false
|
local clearable = false
|
||||||
|
|
@ -241,10 +150,8 @@ hook.Add("Tick", "zcnpci", function()
|
||||||
(ent.organism.blood < 3000) or
|
(ent.organism.blood < 3000) or
|
||||||
(ent.organism.pulse < 10)
|
(ent.organism.pulse < 10)
|
||||||
) then clearable = true end
|
) then clearable = true end
|
||||||
if treat_unconscious_as_dead:GetBool() and (ent.organism.consciousness <= 0.3)
|
|
||||||
then clearable = true end
|
|
||||||
|
|
||||||
if !clearable then continue end
|
if !clearable then return end
|
||||||
|
|
||||||
-- Add to corpse list if not there already
|
-- Add to corpse list if not there already
|
||||||
if !table.HasValue(corpses, ent) then
|
if !table.HasValue(corpses, ent) then
|
||||||
|
|
@ -253,7 +160,6 @@ hook.Add("Tick", "zcnpci", function()
|
||||||
|
|
||||||
-- Get nearest player for future checks
|
-- Get nearest player for future checks
|
||||||
local nearby_player
|
local nearby_player
|
||||||
local player_too_close
|
|
||||||
local players = player.GetAll()
|
local players = player.GetAll()
|
||||||
|
|
||||||
for i, loop_player in pairs(players) do
|
for i, loop_player in pairs(players) do
|
||||||
|
|
@ -263,15 +169,11 @@ hook.Add("Tick", "zcnpci", function()
|
||||||
|
|
||||||
if (distance <= max_corpse_distance:GetFloat()) or (max_corpse_distance:GetFloat() == -1) then
|
if (distance <= max_corpse_distance:GetFloat()) or (max_corpse_distance:GetFloat() == -1) then
|
||||||
nearby_player = loop_player
|
nearby_player = loop_player
|
||||||
end
|
|
||||||
|
|
||||||
if (distance <= min_corpse_distance:GetFloat()) then
|
|
||||||
player_too_close = loop_player
|
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if player_too_close and IsValid(player_too_close) then continue
|
if nearby_player and IsValid(nearby_player) and no_corpse_removal_near_player:GetBool() then continue
|
||||||
elseif (max_corpse_distance:GetFloat() != -1) and !nearby_player then
|
elseif (max_corpse_distance:GetFloat() != -1) and !nearby_player then
|
||||||
ent:Remove()
|
ent:Remove()
|
||||||
continue
|
continue
|
||||||
|
|
@ -283,25 +185,12 @@ hook.Add("Tick", "zcnpci", function()
|
||||||
ent:Remove()
|
ent:Remove()
|
||||||
continue
|
continue
|
||||||
end
|
end
|
||||||
|
print((CurTime() - ent.corpse_timestamp) > max_corpse_time:GetFloat())
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
PrintTable(npcs_to_fake)
|
|
||||||
|
|
||||||
-- NPC faking is in a seperate area because we want NPCs to ragdoll as soon as they can
|
|
||||||
for i,ent in pairs(npcs_to_fake) do
|
|
||||||
local damage_info = DamageInfo()
|
|
||||||
damage_info:SetDamage(0)
|
|
||||||
damage_info:SetAttacker(ent)
|
|
||||||
damage_info:SetDamageType( DMG_DIRECT )
|
|
||||||
damage_info:SetDamageForce(Vector(0, 0, 0))
|
|
||||||
|
|
||||||
ent:BecomeRagdoll(damage_info)
|
|
||||||
|
|
||||||
table.remove(npcs_to_fake, 1)
|
|
||||||
end
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
--[[hook.Add("OnNPCKilled", "Fedhoria", function(ent, attacker, inflictor)
|
--[[hook.Add("OnNPCKilled", "Fedhoria", function(ent, attacker, inflictor)
|
||||||
|
|
@ -311,31 +200,47 @@ end)
|
||||||
last_dmgpos[ent] = dmginfo:GetDamagePosition()
|
last_dmgpos[ent] = dmginfo:GetDamagePosition()
|
||||||
end)]]
|
end)]]
|
||||||
|
|
||||||
hook.Add("OnEntityCreated", "zcnpci", function(ent)
|
|
||||||
if !IsValid(ent) then return end
|
|
||||||
|
|
||||||
local add_organism = false
|
|
||||||
|
|
||||||
if allow_modded_npcs:GetBool() then
|
|
||||||
local modded_npc_whitelist_string = modded_npc_whitelist:GetString()
|
|
||||||
modded_npc_whitelist_string = string.Replace(modded_npc_whitelist_string, "\n", " ")
|
|
||||||
|
|
||||||
local modded_npc_whitelist_table = string.Split(modded_npc_whitelist_string, " ")
|
|
||||||
|
|
||||||
if table.HasValue(modded_npc_whitelist_table, ent:GetClass()) then add_organism = true end
|
|
||||||
end
|
|
||||||
|
|
||||||
if allow_extended_base_npcs:GetBool() and table.HasValue(base_npc_whitelist, ent:GetClass()) then add_organism = true end
|
|
||||||
|
|
||||||
if add_organism then
|
|
||||||
hg.organism.Add(ent)
|
|
||||||
hg.organism.Clear(ent.organism)
|
|
||||||
ent.organism.fakePlayer = true
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
local once = true
|
local once = true
|
||||||
|
|
||||||
|
--RagMod/TTT support
|
||||||
|
--[[hook.Add("OnEntityCreated", "Fedhoria", function(ent)
|
||||||
|
--If RagMod isn't installed remove this hook
|
||||||
|
if once then
|
||||||
|
once = nil
|
||||||
|
if (!RMA_Ragdolize and !CORPSE) then
|
||||||
|
hook.Remove("OnEntityCreated", "Fedhoria")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
--these hooks fucks shit up
|
||||||
|
if RMA_Ragdolize then
|
||||||
|
hook.Remove( "PlayerDeath", "RM_PlayerDies")
|
||||||
|
hook.Add( "PostPlayerDeath", "RemoveRagdoll", function(ply)
|
||||||
|
if IsValid(ply.RM_Ragdoll) then
|
||||||
|
SafeRemoveEntity(ply:GetRagdollEntity())
|
||||||
|
ply:SpectateEntity(ply.RM_Ragdoll)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if (!enabled:GetBool() or !players:GetBool() or !ent:IsRagdoll()) then return end
|
||||||
|
timer.Simple(0, function()
|
||||||
|
if !IsValid(ent) then return end
|
||||||
|
if CORPSE then
|
||||||
|
local ply = ent:GetDTEntity(CORPSE.dti.ENT_PLAYER)
|
||||||
|
if (IsValid(ply) and ply:IsPlayer()) then
|
||||||
|
fedhoria.StartModule(ent, "stumble_legs")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for _, ply in ipairs(player.GetAll()) do
|
||||||
|
if (ply.RM_IsRagdoll and ply.RM_Ragdoll == ent) then
|
||||||
|
fedhoria.StartModule(ent, "stumble_legs")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end)]]
|
||||||
|
|
||||||
local PLAYER = FindMetaTable("Player")
|
local PLAYER = FindMetaTable("Player")
|
||||||
|
|
||||||
local oldCreateRagdoll = PLAYER.CreateRagdoll
|
local oldCreateRagdoll = PLAYER.CreateRagdoll
|
||||||
|
|
@ -377,4 +282,37 @@ local oldGetRagdollEntity = PLAYER.GetRagdollEntity
|
||||||
|
|
||||||
local function GetRagdollEntity(self)
|
local function GetRagdollEntity(self)
|
||||||
return dolls[self] or NULL
|
return dolls[self] or NULL
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--[[
|
||||||
|
if enabled:GetBool() then
|
||||||
|
PLAYER.CreateRagdoll = CreateRagdoll
|
||||||
|
PLAYER.GetRagdollEntity = GetRagdollEntity
|
||||||
|
end]]
|
||||||
|
|
||||||
|
--[[
|
||||||
|
cvars.AddChangeCallback("fedhoria_enabled", function(name, old, new)
|
||||||
|
if (new == "1") then
|
||||||
|
if players:GetBool() then
|
||||||
|
PLAYER.CreateRagdoll = CreateRagdoll
|
||||||
|
PLAYER.GetRagdollEntity = GetRagdollEntity
|
||||||
|
end
|
||||||
|
else
|
||||||
|
PLAYER.CreateRagdoll = oldCreateRagdoll
|
||||||
|
PLAYER.GetRagdollEntity = oldGetRagdollEntity
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
cvars.AddChangeCallback("fedhoria_players", function(name, old, new)
|
||||||
|
if (new == "1") then
|
||||||
|
if enabled:GetBool() then
|
||||||
|
if (debug.getinfo(PLAYER.CreateRagdoll).short_src == "[C]") then
|
||||||
|
PLAYER.CreateRagdoll = CreateRagdoll
|
||||||
|
PLAYER.GetRagdollEntity = GetRagdollEntity
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
PLAYER.CreateRagdoll = oldCreateRagdoll
|
||||||
|
PLAYER.GetRagdollEntity = oldGetRagdollEntity
|
||||||
|
end
|
||||||
|
end)]]
|
||||||
|
|
@ -75,7 +75,6 @@ function ENTITY:GetClosestPhysBone(pos)
|
||||||
end
|
end
|
||||||
|
|
||||||
if !collides then return end
|
if !collides then return end
|
||||||
if type(pos) != "Vector" then return end
|
|
||||||
|
|
||||||
local closest_bone
|
local closest_bone
|
||||||
local dist = math.huge
|
local dist = math.huge
|
||||||
|
|
|
||||||
|
|
@ -149,19 +149,16 @@ function MODULE:StartAnimationRoll()
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
--target.StartDie = nil
|
--self.StartDie = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
function MODULE:Init()
|
function MODULE:Init()
|
||||||
local seq = self:LookupSequence("Choked_Barnacle")
|
local seq = self:LookupSequence("Choked_Barnacle")
|
||||||
if seq then self:ResetSequence(seq) end
|
if seq then self:ResetSequence(seq) end
|
||||||
|
|
||||||
local target = self:GetTarget()
|
|
||||||
|
|
||||||
self:SetPlaybackRate(1)
|
self:SetPlaybackRate(1)
|
||||||
self.LastCollideTime = 0
|
self.LastCollideTime = 0
|
||||||
self.LastGroundCollideTime = 0
|
self.LastGroundCollideTime = 0
|
||||||
target.StartDie = nil
|
self.StartDie = nil
|
||||||
self.AnimationRollEndTime = 0
|
self.AnimationRollEndTime = 0
|
||||||
self.StopProcessing = false
|
self.StopProcessing = false
|
||||||
self.LastThink = CurTime()
|
self.LastThink = CurTime()
|
||||||
|
|
@ -254,20 +251,20 @@ function MODULE:PhysicsSimulate(phys, dt)
|
||||||
|
|
||||||
target.is_npc_corpse = true
|
target.is_npc_corpse = true
|
||||||
|
|
||||||
if !target.StartDie then target.StartDie = cur_time end
|
if !self.StartDie then self.StartDie = cur_time end
|
||||||
|
|
||||||
-- Check for active animation
|
-- Check for active animation
|
||||||
if cur_time < self.AnimationRollEndTime then
|
if cur_time < self.AnimationRollEndTime then
|
||||||
--target.StartDie = nil -- Resetting the "death" timer
|
--self.StartDie = nil -- Resetting the "death" timer
|
||||||
return true -- We use standard physics.
|
return true -- We use standard physics.
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Force multiplier
|
-- Logic for the disappearance timer
|
||||||
local f = target.organism.consciousness
|
local f = 1 -- Force multiplier (default: 1)
|
||||||
|
|
||||||
local minimum_down_timer = 0
|
local minimum_down_timer = 0
|
||||||
if target.StartDie then
|
if self.StartDie then
|
||||||
minimum_down_timer = math_Clamp((cur_time - target.StartDie) / minimum_down_time:GetFloat(), 0, 1)
|
minimum_down_timer = math_Clamp((cur_time - self.StartDie) / minimum_down_time:GetFloat(), 0, 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
if !target.organism then
|
if !target.organism then
|
||||||
|
|
@ -279,8 +276,8 @@ function MODULE:PhysicsSimulate(phys, dt)
|
||||||
-- If the NPC is dead, they probably aren't coming back; don't bother bringing them back to life
|
-- If the NPC is dead, they probably aren't coming back; don't bother bringing them back to life
|
||||||
self:Remove()
|
self:Remove()
|
||||||
return false -- Cut the bullshit
|
return false -- Cut the bullshit
|
||||||
elseif (target.organism.consciousness <= 0.5) or ((target.organism.lleg >= 0.85) and (target.organism.rleg >= 0.85)) then
|
elseif (target.organism.consciousness <= 0.3) or ((target.organism.lleg >= 0.85) and (target.organism.rleg >= 0.85)) then
|
||||||
target.StartDie = cur_time
|
self.StartDie = cur_time
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -291,22 +288,19 @@ function MODULE:PhysicsSimulate(phys, dt)
|
||||||
(target.class_in_previous_life != nil) and
|
(target.class_in_previous_life != nil) and
|
||||||
!(target.organism.llegamputated or target.organism.rlegamputated or target.organism.larmamputated or target.organism.rarmamputated) and
|
!(target.organism.llegamputated or target.organism.rlegamputated or target.organism.larmamputated or target.organism.rarmamputated) and
|
||||||
(target.organism.pain <= 80) and
|
(target.organism.pain <= 80) and
|
||||||
(target.organism.consciousness > 0.65) and
|
|
||||||
!target:IsOnFire()
|
!target:IsOnFire()
|
||||||
) then
|
) then
|
||||||
local ent = ents.Create(target.class_in_previous_life)
|
local ent = ents.Create(target.class_in_previous_life)
|
||||||
ent:SetPos(target:GetPos())
|
ent:SetPos(target:GetPos())
|
||||||
ent:SetModel(target:GetModel())
|
ent:SetModel(target:GetModel())
|
||||||
ent:SetMaterial(target:GetMaterial())
|
|
||||||
|
|
||||||
ent:SetSkin(target:GetSkin())
|
if target:GetNumBodyGroups() > 0 then
|
||||||
|
local i = 1
|
||||||
|
while (i <= target:GetNumBodyGroups()) do
|
||||||
|
ent:SetBodygroup(i, target:GetBodygroup(i))
|
||||||
|
|
||||||
if target.citizentype then
|
i = i + 1
|
||||||
ent:SetKeyValue("citizentype", target.citizentype)
|
end
|
||||||
end
|
|
||||||
|
|
||||||
for i = 0, target:GetNumBodyGroups() - 1 do
|
|
||||||
ent:SetBodygroup(i, target:GetBodygroup(i))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
ent:Spawn()
|
ent:Spawn()
|
||||||
|
|
@ -324,12 +318,6 @@ function MODULE:PhysicsSimulate(phys, dt)
|
||||||
ent:CallOnRemove("organism", hg.organism.Remove, ent)
|
ent:CallOnRemove("organism", hg.organism.Remove, ent)
|
||||||
hg.send_bareinfo(ent.organism)
|
hg.send_bareinfo(ent.organism)
|
||||||
|
|
||||||
ent:SetSkin(target:GetSkin())
|
|
||||||
|
|
||||||
for i = 0, target:GetNumBodyGroups() - 1 do
|
|
||||||
ent:SetBodygroup(i, target:GetBodygroup(i))
|
|
||||||
end
|
|
||||||
|
|
||||||
target:Remove()
|
target:Remove()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
@ -374,7 +362,7 @@ function MODULE:PhysicsSimulate(phys, dt)
|
||||||
self.last_pos = pos
|
self.last_pos = pos
|
||||||
|
|
||||||
if offset_sqr < (10*10 * dt*dt) then
|
if offset_sqr < (10*10 * dt*dt) then
|
||||||
target.StartDie = target.StartDie or cur_time
|
self.StartDie = self.StartDie or cur_time
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Physics correction after collision
|
-- Physics correction after collision
|
||||||
|
|
@ -387,7 +375,7 @@ function MODULE:PhysicsSimulate(phys, dt)
|
||||||
|
|
||||||
return true, f
|
return true, f
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Logic for other bones
|
-- Logic for other bones
|
||||||
local delta_collide = cur_time - self.LastCollideTime
|
local delta_collide = cur_time - self.LastCollideTime
|
||||||
if (delta_collide < 0.2) then
|
if (delta_collide < 0.2) then
|
||||||
|
|
|
||||||
|
|
@ -114,20 +114,17 @@ function MODULE:StartAnimationRoll()
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
target.StartDie = nil -- блять я заебался с этой хуйней
|
self.StartDie = nil -- блять я заебался с этой хуйней
|
||||||
-- print("[Fedhoria AnimRoll] StartAnimationRoll initiated. Speed:", cv_anim_roll_playback_rate:GetFloat(), "Duration:", cv_anim_roll_duration:GetFloat(), "End Time:", self.AnimationRollEndTime) -- Debug
|
-- print("[Fedhoria AnimRoll] StartAnimationRoll initiated. Speed:", cv_anim_roll_playback_rate:GetFloat(), "Duration:", cv_anim_roll_duration:GetFloat(), "End Time:", self.AnimationRollEndTime) -- Debug
|
||||||
end
|
end
|
||||||
|
|
||||||
function MODULE:Init()
|
function MODULE:Init()
|
||||||
local seq = self:LookupSequence("idleonfire")
|
local seq = self:LookupSequence("idleonfire")
|
||||||
if seq then self:ResetSequence(seq) end
|
if seq then self:ResetSequence(seq) end
|
||||||
|
|
||||||
local target = self:GetTarget()
|
|
||||||
|
|
||||||
self:SetPlaybackRate(1)
|
self:SetPlaybackRate(1)
|
||||||
self.LastCollideTime = 0
|
self.LastCollideTime = 0
|
||||||
self.LastGroundCollideTime = 0
|
self.LastGroundCollideTime = 0
|
||||||
target.StartDie = nil
|
self.StartDie = nil
|
||||||
self.AnimationRollEndTime = 0
|
self.AnimationRollEndTime = 0
|
||||||
|
|
||||||
-- идте нахуй с этой хуйней
|
-- идте нахуй с этой хуйней
|
||||||
|
|
@ -175,7 +172,7 @@ function MODULE:PhysicsSimulate(phys, dt)
|
||||||
-- проверка на физику
|
-- проверка на физику
|
||||||
if cur_time < self.AnimationRollEndTime then
|
if cur_time < self.AnimationRollEndTime then
|
||||||
-- print("[Fedhoria Sim] In Animation Roll. Time left:", self.AnimationRollEndTime - cur_time) -- Debug
|
-- print("[Fedhoria Sim] In Animation Roll. Time left:", self.AnimationRollEndTime - cur_time) -- Debug
|
||||||
-- target.StartDie = nil -- Сбрасываем таймер смерти
|
-- self.StartDie = nil -- Сбрасываем таймер смерти
|
||||||
|
|
||||||
return true -- стандартная физика пошла нахуй, у меня по ней 2
|
return true -- стандартная физика пошла нахуй, у меня по ней 2
|
||||||
-- return false -- если физика нахуй идет
|
-- return false -- если физика нахуй идет
|
||||||
|
|
@ -183,15 +180,18 @@ function MODULE:PhysicsSimulate(phys, dt)
|
||||||
|
|
||||||
-- --- логика идет нахуй
|
-- --- логика идет нахуй
|
||||||
|
|
||||||
-- Force multiplier
|
-- логика для таймера
|
||||||
local f = target.organism.consciousness
|
local f = 1 -- сила есть ума не надо (по умолчанию 1)
|
||||||
|
--[[if self.StartDie then
|
||||||
|
f = math_Clamp(1 - (cur_time - self.StartDie) / die_time:GetFloat(), 0, 1)
|
||||||
|
end]]
|
||||||
|
|
||||||
-- ебаная логика для regmod
|
-- ебаная логика для regmod
|
||||||
if ragmod and ragmod:IsRagmodRagdoll(target) then
|
if ragmod and ragmod:IsRagmodRagdoll(target) then
|
||||||
local owner = target:GetOwningPlayer()
|
local owner = target:GetOwningPlayer()
|
||||||
-- владелец идот нахуй
|
-- владелец идот нахуй
|
||||||
f = (IsValid(owner) and owner:Alive()) and 1 or 0
|
f = (IsValid(owner) and owner:Alive()) and 1 or 0
|
||||||
target.StartDie = nil
|
self.StartDie = nil
|
||||||
|
|
||||||
if f <= 0 then self.AnimationRollEndTime = 0 end
|
if f <= 0 then self.AnimationRollEndTime = 0 end
|
||||||
end
|
end
|
||||||
|
|
@ -244,10 +244,10 @@ function MODULE:PhysicsSimulate(phys, dt)
|
||||||
local offset_sqr = (pos - self.last_pos):LengthSqr()
|
local offset_sqr = (pos - self.last_pos):LengthSqr()
|
||||||
self.last_pos = pos
|
self.last_pos = pos
|
||||||
if (offset_sqr < (10*10 * dt*dt) and not (ragmod and ragmod:IsRagmodRagdoll(target))) then -- uменьшил порог неподвижности
|
if (offset_sqr < (10*10 * dt*dt) and not (ragmod and ragmod:IsRagmodRagdoll(target))) then -- uменьшил порог неподвижности
|
||||||
target.StartDie = target.StartDie or cur_time -- идите нахуй
|
self.StartDie = self.StartDie or cur_time -- идите нахуй
|
||||||
-- print("[Fedhoria Sim] Torso seems stationary. StartDie:", target.StartDie) -- Debug
|
-- print("[Fedhoria Sim] Torso seems stationary. StartDie:", self.StartDie) -- Debug
|
||||||
else
|
else
|
||||||
-- target.StartDie = nil -- нахуй таймер
|
-- self.StartDie = nil -- нахуй таймер
|
||||||
-- print("[Fedhoria Sim] Torso moved. Resetting StartDie.") -- Debug
|
-- print("[Fedhoria Sim] Torso moved. Resetting StartDie.") -- Debug
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue