mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 05:43:46 +03:00
Upload
This commit is contained in:
1052
gamemodes/helix/gamemode/core/hooks/cl_hooks.lua
Normal file
1052
gamemodes/helix/gamemode/core/hooks/cl_hooks.lua
Normal file
File diff suppressed because it is too large
Load Diff
672
gamemodes/helix/gamemode/core/hooks/sh_hooks.lua
Normal file
672
gamemodes/helix/gamemode/core/hooks/sh_hooks.lua
Normal file
@@ -0,0 +1,672 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
|
||||
function GM:PlayerNoClip(client)
|
||||
return client:IsAdmin()
|
||||
end
|
||||
|
||||
-- luacheck: globals HOLDTYPE_TRANSLATOR
|
||||
HOLDTYPE_TRANSLATOR = {}
|
||||
HOLDTYPE_TRANSLATOR[""] = "normal"
|
||||
HOLDTYPE_TRANSLATOR["physgun"] = "smg"
|
||||
HOLDTYPE_TRANSLATOR["ar2"] = "smg"
|
||||
HOLDTYPE_TRANSLATOR["crossbow"] = "shotgun"
|
||||
HOLDTYPE_TRANSLATOR["rpg"] = "shotgun"
|
||||
HOLDTYPE_TRANSLATOR["slam"] = "normal"
|
||||
HOLDTYPE_TRANSLATOR["grenade"] = "grenade"
|
||||
HOLDTYPE_TRANSLATOR["fist"] = "normal"
|
||||
HOLDTYPE_TRANSLATOR["melee2"] = "melee"
|
||||
HOLDTYPE_TRANSLATOR["passive"] = "normal"
|
||||
HOLDTYPE_TRANSLATOR["knife"] = "melee"
|
||||
HOLDTYPE_TRANSLATOR["duel"] = "pistol"
|
||||
HOLDTYPE_TRANSLATOR["camera"] = "smg"
|
||||
HOLDTYPE_TRANSLATOR["magic"] = "normal"
|
||||
HOLDTYPE_TRANSLATOR["revolver"] = "pistol"
|
||||
|
||||
-- luacheck: globals PLAYER_HOLDTYPE_TRANSLATOR
|
||||
PLAYER_HOLDTYPE_TRANSLATOR = {}
|
||||
PLAYER_HOLDTYPE_TRANSLATOR[""] = "normal"
|
||||
PLAYER_HOLDTYPE_TRANSLATOR["fist"] = "normal"
|
||||
PLAYER_HOLDTYPE_TRANSLATOR["pistol"] = "normal"
|
||||
PLAYER_HOLDTYPE_TRANSLATOR["grenade"] = "normal"
|
||||
PLAYER_HOLDTYPE_TRANSLATOR["melee"] = "normal"
|
||||
PLAYER_HOLDTYPE_TRANSLATOR["slam"] = "normal"
|
||||
PLAYER_HOLDTYPE_TRANSLATOR["melee2"] = "normal"
|
||||
PLAYER_HOLDTYPE_TRANSLATOR["passive"] = "normal"
|
||||
PLAYER_HOLDTYPE_TRANSLATOR["knife"] = "normal"
|
||||
PLAYER_HOLDTYPE_TRANSLATOR["duel"] = "normal"
|
||||
PLAYER_HOLDTYPE_TRANSLATOR["bugbait"] = "normal"
|
||||
|
||||
local PLAYER_HOLDTYPE_TRANSLATOR = PLAYER_HOLDTYPE_TRANSLATOR
|
||||
local HOLDTYPE_TRANSLATOR = HOLDTYPE_TRANSLATOR
|
||||
local animationFixOffset = Vector(16.5438, -0.1642, -20.5493)
|
||||
|
||||
function GM:TranslateActivity(client, act)
|
||||
local clientInfo = client:GetTable()
|
||||
local modelClass = clientInfo.ixAnimModelClass or "player"
|
||||
local bRaised = client:IsWepRaised()
|
||||
|
||||
if (modelClass == "player") then
|
||||
local weapon = client:GetActiveWeapon()
|
||||
local bAlwaysRaised = ix.config.Get("weaponAlwaysRaised")
|
||||
weapon = IsValid(weapon) and weapon or nil
|
||||
|
||||
if (!bAlwaysRaised and weapon and !bRaised and client:OnGround()) then
|
||||
local model = string.lower(client:GetModel())
|
||||
|
||||
if (string.find(model, "zombie")) then
|
||||
local tree = ix.anim.zombie
|
||||
|
||||
if (string.find(model, "fast")) then
|
||||
tree = ix.anim.fastZombie
|
||||
end
|
||||
|
||||
if (tree[act]) then
|
||||
return tree[act]
|
||||
end
|
||||
end
|
||||
|
||||
local holdType = weapon and (weapon.HoldType or weapon:GetHoldType()) or "normal"
|
||||
|
||||
if (!bAlwaysRaised and weapon and !bRaised and client:OnGround()) then
|
||||
holdType = PLAYER_HOLDTYPE_TRANSLATOR[holdType] or "passive"
|
||||
end
|
||||
|
||||
local tree = ix.anim.player[holdType]
|
||||
|
||||
if (tree and tree[act]) then
|
||||
if (isstring(tree[act])) then
|
||||
clientInfo.CalcSeqOverride = client:LookupSequence(tree[act])
|
||||
|
||||
return
|
||||
else
|
||||
return tree[act]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return self.BaseClass:TranslateActivity(client, act)
|
||||
end
|
||||
|
||||
if (clientInfo.ixAnimTable) then
|
||||
local glide = clientInfo.ixAnimGlide
|
||||
|
||||
if (client:InVehicle()) then
|
||||
act = clientInfo.ixAnimTable[1]
|
||||
|
||||
local fixVector = clientInfo.ixAnimTable[2]
|
||||
|
||||
if (isvector(fixVector)) then
|
||||
client:SetLocalPos(animationFixOffset)
|
||||
end
|
||||
|
||||
if (isstring(act)) then
|
||||
clientInfo.CalcSeqOverride = client:LookupSequence(act)
|
||||
else
|
||||
return act
|
||||
end
|
||||
elseif (client:OnGround()) then
|
||||
if (clientInfo.ixAnimTable[act]) then
|
||||
local act2 = clientInfo.ixAnimTable[act][bRaised and 2 or 1]
|
||||
|
||||
if (isstring(act2)) then
|
||||
clientInfo.CalcSeqOverride = client:LookupSequence(act2)
|
||||
else
|
||||
return act2
|
||||
end
|
||||
end
|
||||
elseif (glide) then
|
||||
if (isstring(glide)) then
|
||||
clientInfo.CalcSeqOverride = client:LookupSequence(glide)
|
||||
else
|
||||
return clientInfo.ixAnimGlide
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function GM:CanPlayerUseBusiness(client, uniqueID)
|
||||
local itemTable = ix.item.list[uniqueID]
|
||||
|
||||
if (!client:GetCharacter()) then
|
||||
return false
|
||||
end
|
||||
|
||||
if (itemTable.noBusiness) then
|
||||
return false
|
||||
end
|
||||
|
||||
if (itemTable.factions) then
|
||||
local allowed = false
|
||||
|
||||
if (istable(itemTable.factions)) then
|
||||
for _, v in pairs(itemTable.factions) do
|
||||
if (client:Team() == v) then
|
||||
allowed = true
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
elseif (client:Team() != itemTable.factions) then
|
||||
allowed = false
|
||||
end
|
||||
|
||||
if (!allowed) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
if (itemTable.classes) then
|
||||
local allowed = false
|
||||
|
||||
if (istable(itemTable.classes)) then
|
||||
for _, v in pairs(itemTable.classes) do
|
||||
if (client:GetCharacter():GetClass() == v) then
|
||||
allowed = true
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
elseif (client:GetCharacter():GetClass() == itemTable.classes) then
|
||||
allowed = true
|
||||
end
|
||||
|
||||
if (!allowed) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
if (itemTable.flag) then
|
||||
if (!client:GetCharacter():HasFlags(itemTable.flag)) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function GM:DoAnimationEvent(client, event, data)
|
||||
local class = client.ixAnimModelClass
|
||||
|
||||
if (class == "player") then
|
||||
return self.BaseClass:DoAnimationEvent(client, event, data)
|
||||
else
|
||||
local weapon = client:GetActiveWeapon()
|
||||
|
||||
if (IsValid(weapon)) then
|
||||
local animation = client.ixAnimTable
|
||||
|
||||
if (event == PLAYERANIMEVENT_ATTACK_PRIMARY) then
|
||||
client:AnimRestartGesture(GESTURE_SLOT_ATTACK_AND_RELOAD, animation.attack or ACT_GESTURE_RANGE_ATTACK_SMG1, true)
|
||||
|
||||
return ACT_VM_PRIMARYATTACK
|
||||
elseif (event == PLAYERANIMEVENT_ATTACK_SECONDARY) then
|
||||
client:AnimRestartGesture(GESTURE_SLOT_ATTACK_AND_RELOAD, animation.attack or ACT_GESTURE_RANGE_ATTACK_SMG1, true)
|
||||
|
||||
return ACT_VM_SECONDARYATTACK
|
||||
elseif (event == PLAYERANIMEVENT_RELOAD) then
|
||||
client:AnimRestartGesture(GESTURE_SLOT_ATTACK_AND_RELOAD, animation.reload or ACT_GESTURE_RELOAD_SMG1, true)
|
||||
|
||||
return ACT_INVALID
|
||||
elseif (event == PLAYERANIMEVENT_JUMP) then
|
||||
client:AnimRestartMainSequence()
|
||||
|
||||
return ACT_INVALID
|
||||
elseif (event == PLAYERANIMEVENT_CANCEL_RELOAD) then
|
||||
client:AnimResetGestureSlot(GESTURE_SLOT_ATTACK_AND_RELOAD)
|
||||
|
||||
return ACT_INVALID
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return ACT_INVALID
|
||||
end
|
||||
|
||||
function GM:EntityEmitSound(data)
|
||||
if (data.Entity.ixIsMuted) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function GM:EntityRemoved(entity)
|
||||
if (SERVER) then
|
||||
entity:ClearNetVars()
|
||||
elseif (entity:IsWeapon()) then
|
||||
local owner = entity:GetOwner()
|
||||
|
||||
-- GetActiveWeapon is the player's new weapon at this point so we'll assume
|
||||
-- that the player switched away from this weapon
|
||||
if (IsValid(owner) and owner:IsPlayer()) then
|
||||
hook.Run("PlayerWeaponChanged", owner, owner:GetActiveWeapon())
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function UpdatePlayerHoldType(client, weapon)
|
||||
weapon = weapon or client:GetActiveWeapon()
|
||||
local holdType = "normal"
|
||||
|
||||
if (IsValid(weapon)) then
|
||||
holdType = weapon.HoldType or weapon:GetHoldType()
|
||||
holdType = HOLDTYPE_TRANSLATOR[holdType] or holdType
|
||||
end
|
||||
|
||||
client.ixAnimHoldType = holdType
|
||||
end
|
||||
|
||||
local function UpdateAnimationTable(client, vehicle)
|
||||
local baseTable = ix.anim[client.ixAnimModelClass] or {}
|
||||
|
||||
if (IsValid(client) and IsValid(vehicle)) then
|
||||
local vehicleClass = vehicle:IsChair() and "chair" or vehicle:GetClass()
|
||||
|
||||
if (baseTable.vehicle and baseTable.vehicle[vehicleClass]) then
|
||||
client.ixAnimTable = baseTable.vehicle[vehicleClass]
|
||||
else
|
||||
client.ixAnimTable = baseTable.normal[ACT_MP_CROUCH_IDLE]
|
||||
end
|
||||
else
|
||||
client.ixAnimTable = baseTable[client.ixAnimHoldType]
|
||||
end
|
||||
|
||||
client.ixAnimGlide = baseTable["glide"]
|
||||
end
|
||||
|
||||
function GM:PlayerWeaponChanged(client, weapon)
|
||||
UpdatePlayerHoldType(client, weapon)
|
||||
UpdateAnimationTable(client)
|
||||
|
||||
if (CLIENT) then
|
||||
return
|
||||
end
|
||||
|
||||
-- update weapon raise state
|
||||
if (weapon.IsAlwaysRaised or ALWAYS_RAISED[weapon:GetClass()]) then
|
||||
client:SetWepRaised(true, weapon)
|
||||
return
|
||||
elseif (weapon.IsAlwaysLowered or weapon.NeverRaised) then
|
||||
client:SetWepRaised(false, weapon)
|
||||
return
|
||||
end
|
||||
|
||||
-- If the player has been forced to have their weapon lowered.
|
||||
if (client:IsRestricted()) then
|
||||
client:SetWepRaised(false, weapon)
|
||||
return
|
||||
end
|
||||
|
||||
-- Let the config decide before actual results.
|
||||
if (ix.config.Get("weaponAlwaysRaised")) then
|
||||
client:SetWepRaised(true, weapon)
|
||||
return
|
||||
end
|
||||
|
||||
client:SetWepRaised(false, weapon)
|
||||
end
|
||||
|
||||
function GM:PlayerSwitchWeapon(client, oldWeapon, weapon)
|
||||
if (!IsFirstTimePredicted()) then
|
||||
return
|
||||
end
|
||||
|
||||
-- the player switched weapon themself (i.e not through SelectWeapon), so we have to network it here
|
||||
if (SERVER) then
|
||||
net.Start("PlayerSelectWeapon")
|
||||
net.WriteEntity(client)
|
||||
net.WriteString(weapon:GetClass())
|
||||
net.Broadcast()
|
||||
end
|
||||
|
||||
hook.Run("PlayerWeaponChanged", client, weapon)
|
||||
end
|
||||
|
||||
function GM:PlayerModelChanged(client, model)
|
||||
client.ixAnimModelClass = ix.anim.GetModelClass(model)
|
||||
|
||||
UpdateAnimationTable(client)
|
||||
end
|
||||
|
||||
do
|
||||
local vectorAngle = FindMetaTable("Vector").Angle
|
||||
local normalizeAngle = math.NormalizeAngle
|
||||
|
||||
function GM:CalcMainActivity(client, velocity)
|
||||
local clientInfo = client:GetTable()
|
||||
local forcedSequence = client:GetNetVar("forcedSequence")
|
||||
|
||||
if (forcedSequence) then
|
||||
if (client:GetSequence() != forcedSequence) then
|
||||
client:SetCycle(0)
|
||||
end
|
||||
|
||||
return -1, forcedSequence
|
||||
end
|
||||
|
||||
client:SetPoseParameter("move_yaw", normalizeAngle(vectorAngle(velocity)[2] - client:EyeAngles()[2]))
|
||||
|
||||
local sequenceOverride = clientInfo.CalcSeqOverride
|
||||
clientInfo.CalcSeqOverride = -1
|
||||
clientInfo.CalcIdeal = ACT_MP_STAND_IDLE
|
||||
|
||||
-- we could call the baseclass function, but it's faster to do it this way
|
||||
local BaseClass = self.BaseClass
|
||||
|
||||
if (BaseClass:HandlePlayerNoClipping(client, velocity) or
|
||||
BaseClass:HandlePlayerDriving(client) or
|
||||
BaseClass:HandlePlayerVaulting(client, velocity) or
|
||||
BaseClass:HandlePlayerJumping(client, velocity) or
|
||||
BaseClass:HandlePlayerSwimming(client, velocity) or
|
||||
BaseClass:HandlePlayerDucking(client, velocity)) then -- luacheck: ignore 542
|
||||
else
|
||||
local length = velocity:Length2DSqr()
|
||||
|
||||
if (length > 22500) then
|
||||
clientInfo.CalcIdeal = ACT_MP_RUN
|
||||
elseif (length > 0.25) then
|
||||
clientInfo.CalcIdeal = ACT_MP_WALK
|
||||
end
|
||||
end
|
||||
|
||||
clientInfo.m_bWasOnGround = client:OnGround()
|
||||
clientInfo.m_bWasNoclipping = (client:GetMoveType() == MOVETYPE_NOCLIP and !client:InVehicle())
|
||||
|
||||
return clientInfo.CalcIdeal, sequenceOverride or clientInfo.CalcSeqOverride or -1
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
local KEY_BLACKLIST = IN_ATTACK + IN_ATTACK2
|
||||
|
||||
function GM:StartCommand(client, command)
|
||||
if (!client:CanShootWeapon()) then
|
||||
command:RemoveKey(KEY_BLACKLIST)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function GM:CharacterVarChanged(char, varName, oldVar, newVar)
|
||||
if (ix.char.varHooks[varName]) then
|
||||
for _, v in pairs(ix.char.varHooks[varName]) do
|
||||
v(char, oldVar, newVar)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function GM:CanPlayerThrowPunch(client)
|
||||
if (!client:IsWepRaised()) then
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function GM:OnCharacterCreated(client, character)
|
||||
local faction = ix.faction.Get(character:GetFaction())
|
||||
|
||||
if (faction and faction.OnCharacterCreated) then
|
||||
faction:OnCharacterCreated(client, character)
|
||||
end
|
||||
end
|
||||
|
||||
function GM:GetDefaultCharacterName(client, faction)
|
||||
local info = ix.faction.indices[faction]
|
||||
|
||||
if (info and info.GetDefaultName) then
|
||||
return info:GetDefaultName(client)
|
||||
end
|
||||
end
|
||||
|
||||
function GM:CanPlayerUseCharacter(client, character)
|
||||
local banned = character:GetData("banned")
|
||||
|
||||
if (banned) then
|
||||
if (isnumber(banned)) then
|
||||
if (banned < os.time()) then
|
||||
return
|
||||
end
|
||||
|
||||
return false, "@charBannedTemp"
|
||||
end
|
||||
|
||||
return false, "@charBanned"
|
||||
end
|
||||
|
||||
local bHasWhitelist = client:HasWhitelist(character:GetFaction())
|
||||
|
||||
if (!bHasWhitelist) then
|
||||
return false, "@noWhitelist"
|
||||
end
|
||||
end
|
||||
|
||||
function GM:CanProperty(client, property, entity)
|
||||
if (client:IsAdmin()) then
|
||||
return true
|
||||
end
|
||||
|
||||
if (CLIENT and (property == "remover" or property == "collision")) then
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function GM:PhysgunPickup(client, entity)
|
||||
local bPickup = self.BaseClass:PhysgunPickup(client, entity)
|
||||
|
||||
if (!bPickup and entity:IsPlayer() and (client:IsSuperAdmin() or client:IsAdmin() and !entity:IsSuperAdmin())) then
|
||||
bPickup = true
|
||||
end
|
||||
|
||||
if (bPickup) then
|
||||
if (entity:IsPlayer()) then
|
||||
entity:SetMoveType(MOVETYPE_NONE)
|
||||
elseif (!entity.ixCollisionGroup) then
|
||||
entity.ixCollisionGroup = entity:GetCollisionGroup()
|
||||
entity:SetCollisionGroup(COLLISION_GROUP_WEAPON)
|
||||
end
|
||||
end
|
||||
|
||||
return bPickup
|
||||
end
|
||||
|
||||
function GM:PhysgunDrop(client, entity)
|
||||
if (entity:IsPlayer()) then
|
||||
entity:SetMoveType(MOVETYPE_WALK)
|
||||
elseif (entity.ixCollisionGroup) then
|
||||
entity:SetCollisionGroup(entity.ixCollisionGroup)
|
||||
entity.ixCollisionGroup = nil
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
local TOOL_DANGEROUS = {}
|
||||
TOOL_DANGEROUS["dynamite"] = true
|
||||
TOOL_DANGEROUS["duplicator"] = true
|
||||
|
||||
function GM:CanTool(client, trace, tool)
|
||||
if (client:IsAdmin()) then
|
||||
return true
|
||||
end
|
||||
|
||||
if (TOOL_DANGEROUS[tool]) then
|
||||
return false
|
||||
end
|
||||
|
||||
return self.BaseClass:CanTool(client, trace, tool)
|
||||
end
|
||||
end
|
||||
|
||||
function GM:Move(client, moveData)
|
||||
local char = client:GetCharacter()
|
||||
|
||||
if (char) then
|
||||
if (client:GetNetVar("actEnterAngle")) then
|
||||
moveData:SetForwardSpeed(0)
|
||||
moveData:SetSideSpeed(0)
|
||||
moveData:SetVelocity(vector_origin)
|
||||
end
|
||||
|
||||
if (client:GetMoveType() == MOVETYPE_WALK and moveData:KeyDown(IN_WALK)) then
|
||||
local mf, ms = 0, 0
|
||||
local speed = client:GetWalkSpeed()
|
||||
local ratio = ix.config.Get("walkRatio")
|
||||
|
||||
if (moveData:KeyDown(IN_FORWARD)) then
|
||||
mf = ratio
|
||||
elseif (moveData:KeyDown(IN_BACK)) then
|
||||
mf = -ratio
|
||||
end
|
||||
|
||||
if (moveData:KeyDown(IN_MOVELEFT)) then
|
||||
ms = -ratio
|
||||
elseif (moveData:KeyDown(IN_MOVERIGHT)) then
|
||||
ms = ratio
|
||||
end
|
||||
|
||||
moveData:SetForwardSpeed(mf * speed)
|
||||
moveData:SetSideSpeed(ms * speed)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- I'm sorry. ~Aspect
|
||||
--[[
|
||||
function GM:CanTransferItem(itemObject, curInv, inventory)
|
||||
if (SERVER) then
|
||||
local client = itemObject.GetOwner and itemObject:GetOwner() or nil
|
||||
|
||||
if (IsValid(client) and curInv.GetReceivers) then
|
||||
local bAuthorized = false
|
||||
|
||||
for _, v in ipairs(curInv:GetReceivers()) do
|
||||
if (client == v) then
|
||||
bAuthorized = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if (!bAuthorized) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- we can transfer anything that isn't a bag
|
||||
if (!itemObject or !itemObject.isBag) then
|
||||
return
|
||||
end
|
||||
|
||||
-- don't allow bags to be put inside bags
|
||||
if (inventory.id != 0 and curInv.id != inventory.id) then
|
||||
if (inventory.vars and inventory.vars.isBag) then
|
||||
local owner = itemObject:GetOwner()
|
||||
|
||||
if (IsValid(owner)) then
|
||||
owner:NotifyLocalized("nestedBags")
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
elseif (inventory.id != 0 and curInv.id == inventory.id) then
|
||||
-- we are simply moving items around if we're transferring to the same inventory
|
||||
return
|
||||
end
|
||||
|
||||
inventory = ix.item.inventories[itemObject:GetData("id")]
|
||||
|
||||
-- don't allow transferring items that are in use
|
||||
if (inventory) then
|
||||
for _, v in pairs(inventory:GetItems()) do
|
||||
if (v:GetData("equip") == true) then
|
||||
local owner = itemObject:GetOwner()
|
||||
|
||||
if (owner and IsValid(owner)) then
|
||||
owner:NotifyLocalized("equippedBag")
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
--]]
|
||||
|
||||
function GM:CanPlayerEquipItem(client, item)
|
||||
local slots = ix.plugin.list["inventoryslots"]
|
||||
if slots then return slots:CanEquipOrUnequip(client, item, true) end
|
||||
return item.invID == client:GetCharacter():GetInventory():GetID()
|
||||
end
|
||||
|
||||
function GM:CanPlayerUnequipItem(client, item)
|
||||
local slots = ix.plugin.list["inventoryslots"]
|
||||
if slots then return slots:CanEquipOrUnequip(client, item, false) end
|
||||
return item.invID == client:GetCharacter():GetInventory():GetID()
|
||||
end
|
||||
|
||||
function GM:OnItemTransferred(item, curInv, inventory)
|
||||
local bagInventory = item.GetInventory and item:GetInventory()
|
||||
|
||||
if (!bagInventory) then
|
||||
return
|
||||
end
|
||||
|
||||
-- we need to retain the receiver if the owner changed while viewing as storage
|
||||
if (inventory.storageInfo and isfunction(curInv.GetOwner)) then
|
||||
bagInventory:AddReceiver(curInv:GetOwner())
|
||||
end
|
||||
end
|
||||
|
||||
function GM:ShowHelp() end
|
||||
|
||||
function GM:PreGamemodeLoaded()
|
||||
hook.Remove("PostDrawEffects", "RenderWidgets")
|
||||
hook.Remove("PlayerTick", "TickWidgets")
|
||||
hook.Remove("RenderScene", "RenderStereoscopy")
|
||||
end
|
||||
|
||||
function GM:PostGamemodeLoaded()
|
||||
baseclass.Set("ix_character", ix.meta.character)
|
||||
baseclass.Set("ix_inventory", ix.meta.inventory)
|
||||
baseclass.Set("ix_item", ix.meta.item)
|
||||
end
|
||||
|
||||
if (SERVER) then
|
||||
util.AddNetworkString("PlayerVehicle")
|
||||
|
||||
function GM:PlayerEnteredVehicle(client, vehicle, role)
|
||||
UpdateAnimationTable(client)
|
||||
|
||||
net.Start("PlayerVehicle")
|
||||
net.WriteEntity(client)
|
||||
net.WriteEntity(vehicle)
|
||||
net.WriteBool(true)
|
||||
net.Broadcast()
|
||||
end
|
||||
|
||||
function GM:PlayerLeaveVehicle(client, vehicle)
|
||||
UpdateAnimationTable(client)
|
||||
|
||||
net.Start("PlayerVehicle")
|
||||
net.WriteEntity(client)
|
||||
net.WriteEntity(vehicle)
|
||||
net.WriteBool(false)
|
||||
net.Broadcast()
|
||||
end
|
||||
else
|
||||
net.Receive("PlayerVehicle", function(length)
|
||||
local client = net.ReadEntity()
|
||||
local vehicle = net.ReadEntity()
|
||||
local bEntered = net.ReadBool()
|
||||
|
||||
UpdateAnimationTable(client, bEntered and vehicle or false)
|
||||
end)
|
||||
end
|
||||
951
gamemodes/helix/gamemode/core/hooks/sv_hooks.lua
Normal file
951
gamemodes/helix/gamemode/core/hooks/sv_hooks.lua
Normal file
@@ -0,0 +1,951 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
|
||||
function GM:PlayerInitialSpawn(client)
|
||||
client.ixJoinTime = RealTime()
|
||||
|
||||
if (client:IsBot()) then
|
||||
local botID = os.time() + client:EntIndex()
|
||||
local index = math.random(1, table.Count(ix.faction.indices))
|
||||
local faction = ix.faction.indices[index]
|
||||
|
||||
local model = faction and table.Random(faction:GetModels(client)) or "models/gman.mdl"
|
||||
if (istable(model)) then
|
||||
model = table.Random(model)
|
||||
end
|
||||
|
||||
local character = ix.char.New({
|
||||
name = client:Name(),
|
||||
faction = faction and faction.uniqueID or "unknown",
|
||||
model = model,
|
||||
}, botID, client, client:SteamID64())
|
||||
character.isBot = true
|
||||
|
||||
local inventory = ix.inventory.Create(ix.config.Get("inventoryWidth"), ix.config.Get("inventoryHeight"), botID)
|
||||
inventory:SetOwner(botID)
|
||||
inventory.noSave = true
|
||||
|
||||
character.vars.inv = {inventory}
|
||||
|
||||
ix.char.loaded[botID] = character
|
||||
|
||||
character:Setup()
|
||||
client:Spawn()
|
||||
|
||||
ix.chat.Send(nil, "connect", client:SteamName())
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
ix.config.Send(client)
|
||||
ix.date.Send(client)
|
||||
|
||||
client:LoadData(function(data)
|
||||
if (!IsValid(client)) then return end
|
||||
|
||||
-- Don't use the character cache if they've connected to another server using the same database
|
||||
local address = ix.util.GetAddress()
|
||||
local bNoCache = client:GetData("lastIP", address) != address
|
||||
client:SetData("lastIP", address)
|
||||
|
||||
net.Start("ixDataSync")
|
||||
net.WriteTable(data or {})
|
||||
net.WriteUInt(client.ixPlayTime or 0, 32)
|
||||
net.Send(client)
|
||||
|
||||
ix.char.Restore(client, function(charList)
|
||||
if (!IsValid(client)) then return end
|
||||
|
||||
MsgN("Loaded (" .. table.concat(charList, ", ") .. ") for " .. client:Name())
|
||||
|
||||
for _, v in ipairs(charList) do
|
||||
ix.char.loaded[v]:Sync(client)
|
||||
end
|
||||
|
||||
client.ixCharList = charList
|
||||
|
||||
net.Start("ixCharacterMenu")
|
||||
net.WriteUInt(#charList, 6)
|
||||
|
||||
for _, v in ipairs(charList) do
|
||||
net.WriteUInt(v, 32)
|
||||
end
|
||||
|
||||
net.Send(client)
|
||||
|
||||
client.ixLoaded = true
|
||||
client:SetData("intro", true)
|
||||
|
||||
for _, v in ipairs(player.GetAll()) do
|
||||
if (v:GetCharacter()) then
|
||||
v:GetCharacter():Sync(client)
|
||||
end
|
||||
end
|
||||
end, bNoCache)
|
||||
|
||||
ix.chat.Send(nil, "connect", client:SteamName())
|
||||
end)
|
||||
|
||||
client:SetNoDraw(true)
|
||||
client:SetNotSolid(true)
|
||||
client:Lock()
|
||||
client:SyncVars()
|
||||
|
||||
timer.Simple(1, function()
|
||||
if (!IsValid(client)) then
|
||||
return
|
||||
end
|
||||
|
||||
client:KillSilent()
|
||||
client:StripAmmo()
|
||||
end)
|
||||
end
|
||||
|
||||
function GM:PlayerUse(client, entity)
|
||||
if (client:IsRestricted() or (isfunction(entity.GetEntityMenu) and entity:GetClass() != "ix_item")) then
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function GM:KeyPress(client, key)
|
||||
if (key == IN_RELOAD) then
|
||||
timer.Create("ixToggleRaise"..client:SteamID(), ix.config.Get("weaponRaiseTime"), 1, function()
|
||||
if (IsValid(client)) then
|
||||
client:ToggleWepRaised()
|
||||
end
|
||||
end)
|
||||
elseif (key == IN_USE) then
|
||||
local data = {}
|
||||
data.start = client:GetShootPos()
|
||||
data.endpos = data.start + client:GetAimVector() * 96
|
||||
data.filter = client
|
||||
local entity = util.TraceLine(data).Entity
|
||||
|
||||
if (IsValid(entity) and hook.Run("PlayerUse", client, entity)) then
|
||||
if (entity:IsDoor()) then
|
||||
local result = hook.Run("CanPlayerUseDoor", client, entity)
|
||||
|
||||
if (result != false) then
|
||||
hook.Run("PlayerUseDoor", client, entity)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function GM:KeyRelease(client, key)
|
||||
if (key == IN_RELOAD) then
|
||||
timer.Remove("ixToggleRaise" .. client:SteamID())
|
||||
elseif (key == IN_USE) then
|
||||
timer.Remove("ixCharacterInteraction" .. client:SteamID())
|
||||
end
|
||||
end
|
||||
|
||||
function GM:CanPlayerInteractItem(client, action, item)
|
||||
if (client:IsRestricted()) then
|
||||
return false
|
||||
end
|
||||
|
||||
if (IsValid(client.ixRagdoll)) then
|
||||
client:NotifyLocalized("notNow")
|
||||
return false
|
||||
end
|
||||
|
||||
if (action == "drop" and hook.Run("CanPlayerDropItem", client, item) == false) then
|
||||
return false
|
||||
end
|
||||
|
||||
if (action == "take" and hook.Run("CanPlayerTakeItem", client, item) == false) then
|
||||
return false
|
||||
end
|
||||
|
||||
if (isentity(item) and item.ixSteamID and item.ixCharID
|
||||
and item.ixSteamID == client:SteamID() and item.ixCharID != client:GetCharacter():GetID()
|
||||
and !item:GetItemTable().bAllowMultiCharacterInteraction) then
|
||||
client:NotifyLocalized("itemOwned")
|
||||
return false
|
||||
end
|
||||
|
||||
return client:Alive()
|
||||
end
|
||||
|
||||
function GM:CanPlayerDropItem(client, item)
|
||||
|
||||
end
|
||||
|
||||
function GM:CanPlayerTakeItem(client, item)
|
||||
|
||||
end
|
||||
|
||||
function GM:PlayerShouldTakeDamage(client, attacker)
|
||||
return client:GetCharacter() != nil
|
||||
end
|
||||
|
||||
function GM:GetFallDamage(client, speed)
|
||||
return (speed - 580) * (100 / 444)
|
||||
end
|
||||
|
||||
function GM:EntityTakeDamage(entity, dmgInfo)
|
||||
local inflictor = dmgInfo:GetInflictor()
|
||||
|
||||
if (IsValid(inflictor) and inflictor:GetClass() == "ix_item") then
|
||||
dmgInfo:SetDamage(0)
|
||||
return
|
||||
end
|
||||
|
||||
if (IsValid(entity.ixPlayer)) then
|
||||
if (IsValid(entity.ixHeldOwner)) then
|
||||
dmgInfo:SetDamage(0)
|
||||
return
|
||||
end
|
||||
|
||||
if (dmgInfo:IsDamageType(DMG_CRUSH)) then
|
||||
if ((entity.ixFallGrace or 0) < CurTime()) then
|
||||
if (dmgInfo:GetDamage() <= 10) then
|
||||
dmgInfo:SetDamage(0)
|
||||
end
|
||||
|
||||
entity.ixFallGrace = CurTime() + 0.5
|
||||
else
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
entity.ixPlayer:TakeDamageInfo(dmgInfo)
|
||||
end
|
||||
end
|
||||
|
||||
function GM:PrePlayerLoadedCharacter(client, character, lastChar)
|
||||
-- Reset all bodygroups
|
||||
client:ResetBodygroups()
|
||||
|
||||
-- Remove all skins
|
||||
client:SetSkin(0)
|
||||
end
|
||||
|
||||
function GM:PlayerLoadedCharacter(client, character, lastChar)
|
||||
local query = mysql:Update("ix_characters")
|
||||
query:Where("id", character:GetID())
|
||||
query:Update("last_join_time", math.floor(os.time()))
|
||||
query:Execute()
|
||||
|
||||
if (lastChar) then
|
||||
local charEnts = lastChar:GetVar("charEnts") or {}
|
||||
|
||||
for _, v in ipairs(charEnts) do
|
||||
if (v and IsValid(v)) then
|
||||
v:Remove()
|
||||
end
|
||||
end
|
||||
|
||||
lastChar:SetVar("charEnts", nil)
|
||||
end
|
||||
|
||||
if (character) then
|
||||
for _, v in pairs(ix.class.list) do
|
||||
if (v.faction == client:Team() and v.isDefault) then
|
||||
character:SetClass(v.index)
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (IsValid(client.ixRagdoll)) then
|
||||
client.ixRagdoll.ixNoReset = true
|
||||
client.ixRagdoll.ixIgnoreDelete = true
|
||||
client.ixRagdoll:Remove()
|
||||
end
|
||||
|
||||
local faction = ix.faction.indices[character:GetFaction()]
|
||||
local uniqueID = "ixSalary" .. client:SteamID64()
|
||||
|
||||
if (faction and faction.pay and faction.pay > 0) then
|
||||
timer.Create(uniqueID, faction.payTime or 300, 0, function()
|
||||
if (IsValid(client)) then
|
||||
if (hook.Run("CanPlayerEarnSalary", client, faction) != false) then
|
||||
local pay = hook.Run("GetSalaryAmount", client, faction) or faction.pay
|
||||
|
||||
character:GiveMoney(pay)
|
||||
client:NotifyLocalized("salary", ix.currency.Get(pay))
|
||||
end
|
||||
else
|
||||
timer.Remove(uniqueID)
|
||||
end
|
||||
end)
|
||||
elseif (timer.Exists(uniqueID)) then
|
||||
timer.Remove(uniqueID)
|
||||
end
|
||||
|
||||
hook.Run("PlayerLoadout", client)
|
||||
end
|
||||
|
||||
function GM:CharacterLoaded(character)
|
||||
local client = character:GetPlayer()
|
||||
|
||||
if (IsValid(client)) then
|
||||
local uniqueID = "ixSaveChar"..client:SteamID()
|
||||
|
||||
timer.Create(uniqueID, ix.config.Get("saveInterval"), 0, function()
|
||||
if (IsValid(client) and client:GetCharacter()) then
|
||||
client:GetCharacter():Save()
|
||||
else
|
||||
timer.Remove(uniqueID)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function GM:PlayerSay(client, text)
|
||||
local chatType, message, anonymous = ix.chat.Parse(client, text, true)
|
||||
|
||||
if (chatType == "ic") then
|
||||
if (ix.command.Parse(client, message)) then
|
||||
return ""
|
||||
end
|
||||
end
|
||||
|
||||
text = ix.chat.Send(client, chatType, message, anonymous)
|
||||
|
||||
if (isstring(text)) then
|
||||
ix.log.Add(client, "chat", chatType and chatType:utf8upper() or "??", text)
|
||||
end
|
||||
|
||||
hook.Run("PostPlayerSay", client, chatType, message, anonymous)
|
||||
return ""
|
||||
end
|
||||
|
||||
function GM:CanAutoFormatMessage(client, chatType, message)
|
||||
return chatType == "ic" or chatType == "w" or chatType == "y"
|
||||
end
|
||||
|
||||
function GM:PlayerSpawn(client)
|
||||
client:SetNoDraw(false)
|
||||
client:UnLock()
|
||||
client:SetNotSolid(false)
|
||||
client:SetMoveType(MOVETYPE_WALK)
|
||||
client:SetRagdolled(false)
|
||||
client:SetAction()
|
||||
client:SetDSP(1)
|
||||
|
||||
hook.Run("PlayerLoadout", client)
|
||||
end
|
||||
|
||||
-- Shortcuts for (super)admin only things.
|
||||
local function IsAdmin(_, client)
|
||||
return client:IsAdmin()
|
||||
end
|
||||
|
||||
-- Set the gamemode hooks to the appropriate shortcuts.
|
||||
GM.PlayerGiveSWEP = IsAdmin
|
||||
GM.PlayerSpawnEffect = IsAdmin
|
||||
GM.PlayerSpawnSENT = IsAdmin
|
||||
|
||||
function GM:PlayerSpawnNPC(client, npcType, weapon)
|
||||
return client:IsAdmin() or client:GetCharacter():HasFlags("n")
|
||||
end
|
||||
|
||||
function GM:PlayerSpawnSWEP(client, weapon, info)
|
||||
return client:IsAdmin()
|
||||
end
|
||||
|
||||
function GM:PlayerSpawnProp(client)
|
||||
if (client:GetCharacter() and client:GetCharacter():HasFlags("e")) then
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function GM:PlayerSpawnRagdoll(client)
|
||||
if (client:GetCharacter() and client:GetCharacter():HasFlags("r")) then
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function GM:PlayerSpawnVehicle(client, model, name, data)
|
||||
if (client:GetCharacter()) then
|
||||
if (data.Category == "Chairs") then
|
||||
return client:GetCharacter():HasFlags("c")
|
||||
else
|
||||
return client:GetCharacter():HasFlags("C")
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function GM:PlayerSpawnedEffect(client, model, entity)
|
||||
entity:SetNetVar("owner", client:GetCharacter():GetID())
|
||||
end
|
||||
|
||||
function GM:PlayerSpawnedNPC(client, entity)
|
||||
entity:SetNetVar("owner", client:GetCharacter():GetID())
|
||||
end
|
||||
|
||||
function GM:PlayerSpawnedProp(client, model, entity)
|
||||
entity:SetNetVar("owner", client:GetCharacter():GetID())
|
||||
end
|
||||
|
||||
function GM:PlayerSpawnedRagdoll(client, model, entity)
|
||||
entity:SetNetVar("owner", client:GetCharacter():GetID())
|
||||
end
|
||||
|
||||
function GM:PlayerSpawnedSENT(client, entity)
|
||||
entity:SetNetVar("owner", client:GetCharacter():GetID())
|
||||
end
|
||||
|
||||
function GM:PlayerSpawnedSWEP(client, entity)
|
||||
entity:SetNetVar("owner", client:GetCharacter():GetID())
|
||||
end
|
||||
|
||||
function GM:PlayerSpawnedVehicle(client, entity)
|
||||
entity:SetNetVar("owner", client:GetCharacter():GetID())
|
||||
end
|
||||
|
||||
ix.allowedHoldableClasses = {
|
||||
["ix_item"] = true,
|
||||
["ix_money"] = true,
|
||||
["ix_shipment"] = true,
|
||||
["prop_physics"] = true,
|
||||
["prop_physics_override"] = true,
|
||||
["prop_physics_multiplayer"] = true,
|
||||
["prop_ragdoll"] = true
|
||||
}
|
||||
|
||||
function GM:CanPlayerHoldObject(client, entity)
|
||||
if (ix.allowedHoldableClasses[entity:GetClass()]) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local voiceDistance = 360000
|
||||
local function CalcPlayerCanHearPlayersVoice(listener)
|
||||
if (!IsValid(listener)) then
|
||||
return
|
||||
end
|
||||
|
||||
listener.ixVoiceHear = listener.ixVoiceHear or {}
|
||||
|
||||
local eyePos = listener:EyePos()
|
||||
for _, speaker in ipairs(player.GetAll()) do
|
||||
local speakerEyePos = speaker:EyePos()
|
||||
listener.ixVoiceHear[speaker] = eyePos:DistToSqr(speakerEyePos) < voiceDistance
|
||||
end
|
||||
end
|
||||
|
||||
function GM:InitializedConfig()
|
||||
ix.date.Initialize()
|
||||
|
||||
voiceDistance = ix.config.Get("voiceDistance")
|
||||
voiceDistance = voiceDistance * voiceDistance
|
||||
end
|
||||
|
||||
function GM:VoiceToggled(bAllowVoice)
|
||||
for _, v in ipairs(player.GetAll()) do
|
||||
local uniqueID = v:SteamID64() .. "ixCanHearPlayersVoice"
|
||||
|
||||
if (bAllowVoice) then
|
||||
timer.Create(uniqueID, 0.5, 0, function()
|
||||
CalcPlayerCanHearPlayersVoice(v)
|
||||
end)
|
||||
else
|
||||
timer.Remove(uniqueID)
|
||||
|
||||
v.ixVoiceHear = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function GM:VoiceDistanceChanged(distance)
|
||||
voiceDistance = distance * distance
|
||||
end
|
||||
|
||||
-- Called when weapons should be given to a player.
|
||||
function GM:PlayerLoadout(client)
|
||||
if (client.ixSkipLoadout) then
|
||||
client.ixSkipLoadout = nil
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
client:SetWeaponColor(Vector(client:GetInfo("cl_weaponcolor")))
|
||||
client:StripWeapons()
|
||||
client:StripAmmo()
|
||||
client:SetLocalVar("blur", nil)
|
||||
|
||||
local character = client:GetCharacter()
|
||||
|
||||
-- Check if they have loaded a character.
|
||||
if (character) then
|
||||
client:SetupHands()
|
||||
-- Set their player model to the character's model.
|
||||
client:SetModel(character:GetModel())
|
||||
client:Give("ix_hands")
|
||||
client:SetWalkSpeed(ix.config.Get("walkSpeed"))
|
||||
client:SetRunSpeed(ix.config.Get("runSpeed"))
|
||||
client:SetJumpPower(ix.config.Get("jumpPower"))
|
||||
client:SetHealth(character:GetData("health", client:GetMaxHealth()))
|
||||
|
||||
local faction = ix.faction.indices[client:Team()]
|
||||
|
||||
if (faction) then
|
||||
-- If their faction wants to do something when the player spawns, let it.
|
||||
if (faction.OnSpawn) then
|
||||
faction:OnSpawn(client)
|
||||
end
|
||||
|
||||
-- @todo add docs for player:Give() failing if player already has weapon - which means if a player is given a weapon
|
||||
-- here due to the faction weapons table, the weapon's :Give call in the weapon base will fail since the player
|
||||
-- will already have it by then. This will cause issues for weapons that have pac data since the parts are applied
|
||||
-- only if the weapon returned by :Give() is valid
|
||||
|
||||
-- If the faction has default weapons, give them to the player.
|
||||
if (faction.weapons) then
|
||||
for _, v in ipairs(faction.weapons) do
|
||||
client:Give(v)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Ditto, but for classes.
|
||||
local class = ix.class.list[client:GetCharacter():GetClass()]
|
||||
|
||||
if (class) then
|
||||
if (class.OnSpawn) then
|
||||
class:OnSpawn(client)
|
||||
end
|
||||
|
||||
if (class.weapons) then
|
||||
for _, v in ipairs(class.weapons) do
|
||||
client:Give(v)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Apply any flags as needed.
|
||||
ix.flag.OnSpawn(client)
|
||||
ix.attributes.Setup(client)
|
||||
|
||||
hook.Run("PostPlayerLoadout", client)
|
||||
|
||||
client:SelectWeapon("ix_hands")
|
||||
else
|
||||
client:SetNoDraw(true)
|
||||
client:Lock()
|
||||
client:SetNotSolid(true)
|
||||
end
|
||||
end
|
||||
|
||||
function GM:PostPlayerLoadout(client)
|
||||
-- Reload All Attrib Boosts
|
||||
local character = client:GetCharacter()
|
||||
|
||||
if (character:GetInventory()) then
|
||||
for _, v in pairs(character:GetInventory():GetItems()) do
|
||||
v:Call("OnLoadout", client)
|
||||
|
||||
if (v:GetData("equip") and v.attribBoosts) then
|
||||
for attribKey, attribValue in pairs(v.attribBoosts) do
|
||||
character:AddBoost(v.uniqueID, attribKey, attribValue)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (ix.config.Get("allowVoice")) then
|
||||
timer.Create(client:SteamID64() .. "ixCanHearPlayersVoice", 0.5, 0, function()
|
||||
CalcPlayerCanHearPlayersVoice(client)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
local deathSounds = {
|
||||
Sound("vo/npc/male01/pain07.wav"),
|
||||
Sound("vo/npc/male01/pain08.wav"),
|
||||
Sound("vo/npc/male01/pain09.wav")
|
||||
}
|
||||
|
||||
function GM:DoPlayerDeath(client, attacker, damageinfo)
|
||||
client:AddDeaths(1)
|
||||
|
||||
if (hook.Run("ShouldSpawnClientRagdoll", client) != false) then
|
||||
client:CreateRagdoll()
|
||||
end
|
||||
|
||||
if (IsValid(attacker) and attacker:IsPlayer()) then
|
||||
if (client == attacker) then
|
||||
attacker:AddFrags(-1)
|
||||
else
|
||||
attacker:AddFrags(1)
|
||||
end
|
||||
end
|
||||
|
||||
client:SetDSP(31)
|
||||
end
|
||||
|
||||
function GM:PlayerDeath(client, inflictor, attacker)
|
||||
local character = client:GetCharacter()
|
||||
|
||||
if (character) then
|
||||
if (IsValid(client.ixRagdoll)) then
|
||||
client.ixRagdoll.ixIgnoreDelete = true
|
||||
client:SetLocalVar("blur", nil)
|
||||
|
||||
if (hook.Run("ShouldRemoveRagdollOnDeath", client) != false) then
|
||||
client.ixRagdoll:Remove()
|
||||
end
|
||||
end
|
||||
|
||||
client:SetNetVar("deathStartTime", CurTime())
|
||||
client:SetNetVar("deathTime", CurTime() + ix.config.Get("spawnTime", 5))
|
||||
|
||||
character:SetData("health", nil)
|
||||
|
||||
local deathSound = hook.Run("GetPlayerDeathSound", client)
|
||||
|
||||
if (deathSound != false) then
|
||||
deathSound = deathSound or deathSounds[math.random(1, #deathSounds)]
|
||||
|
||||
if (client:IsFemale() and !deathSound:find("female")) then
|
||||
deathSound = deathSound:gsub("male", "female")
|
||||
end
|
||||
|
||||
client:EmitSound(deathSound)
|
||||
end
|
||||
|
||||
local weapon = attacker:IsPlayer() and attacker:GetActiveWeapon()
|
||||
|
||||
ix.log.Add(client, "playerDeath",
|
||||
attacker:GetName() ~= "" and attacker:GetName() or attacker:GetClass(), IsValid(weapon) and weapon:GetClass())
|
||||
end
|
||||
end
|
||||
|
||||
local painSounds = {
|
||||
Sound("vo/npc/male01/pain01.wav"),
|
||||
Sound("vo/npc/male01/pain02.wav"),
|
||||
Sound("vo/npc/male01/pain03.wav"),
|
||||
Sound("vo/npc/male01/pain04.wav"),
|
||||
Sound("vo/npc/male01/pain05.wav"),
|
||||
Sound("vo/npc/male01/pain06.wav")
|
||||
}
|
||||
|
||||
local drownSounds = {
|
||||
Sound("player/pl_drown1.wav"),
|
||||
Sound("player/pl_drown2.wav"),
|
||||
Sound("player/pl_drown3.wav"),
|
||||
}
|
||||
|
||||
function GM:GetPlayerPainSound(client)
|
||||
if (client:WaterLevel() >= 3) then
|
||||
return drownSounds[math.random(1, #drownSounds)]
|
||||
end
|
||||
end
|
||||
|
||||
function GM:PlayerHurt(client, attacker, health, damage)
|
||||
if ((client.ixNextPain or 0) < CurTime() and health > 0) then
|
||||
local painSound = hook.Run("GetPlayerPainSound", client) or painSounds[math.random(1, #painSounds)]
|
||||
|
||||
if (client:IsFemale() and !painSound:find("female")) then
|
||||
painSound = painSound:gsub("male", "female")
|
||||
end
|
||||
|
||||
client:EmitSound(painSound)
|
||||
client.ixNextPain = CurTime() + 0.33
|
||||
end
|
||||
|
||||
ix.log.Add(client, "playerHurt", damage, attacker:GetName() ~= "" and attacker:GetName() or attacker:GetClass())
|
||||
end
|
||||
|
||||
function GM:PlayerDeathThink(client)
|
||||
if (client:GetCharacter()) then
|
||||
local deathTime = client:GetNetVar("deathTime")
|
||||
|
||||
if (deathTime and deathTime <= CurTime()) then
|
||||
client:Spawn()
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function GM:PlayerDisconnected(client)
|
||||
client:SaveData()
|
||||
|
||||
local character = client:GetCharacter()
|
||||
|
||||
if (character) then
|
||||
local charEnts = character:GetVar("charEnts") or {}
|
||||
|
||||
for _, v in ipairs(charEnts) do
|
||||
if (v and IsValid(v)) then
|
||||
v:Remove()
|
||||
end
|
||||
end
|
||||
|
||||
hook.Run("OnCharacterDisconnect", client, character)
|
||||
character:Save()
|
||||
ix.chat.Send(nil, "disconnect", client:SteamName())
|
||||
end
|
||||
|
||||
if (IsValid(client.ixRagdoll)) then
|
||||
client.ixRagdoll:Remove()
|
||||
end
|
||||
|
||||
client:ClearNetVars()
|
||||
|
||||
if (!client.ixVoiceHear) then
|
||||
return
|
||||
end
|
||||
|
||||
for _, v in ipairs(player.GetAll()) do
|
||||
if (!v.ixVoiceHear) then
|
||||
continue
|
||||
end
|
||||
|
||||
v.ixVoiceHear[client] = nil
|
||||
end
|
||||
|
||||
timer.Remove(client:SteamID64() .. "ixCanHearPlayersVoice")
|
||||
end
|
||||
|
||||
function GM:InitPostEntity()
|
||||
local doors = ents.FindByClass("prop_door_rotating")
|
||||
|
||||
for _, v in ipairs(doors) do
|
||||
local parent = v:GetOwner()
|
||||
|
||||
if (IsValid(parent)) then
|
||||
v.ixPartner = parent
|
||||
parent.ixPartner = v
|
||||
else
|
||||
for _, v2 in ipairs(doors) do
|
||||
if (v2:GetOwner() == v) then
|
||||
v2.ixPartner = v
|
||||
v.ixPartner = v2
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
timer.Simple(2, function()
|
||||
ix.entityDataLoaded = true
|
||||
end)
|
||||
end
|
||||
|
||||
function GM:SaveData()
|
||||
ix.date.Save()
|
||||
end
|
||||
|
||||
function GM:ShutDown()
|
||||
ix.shuttingDown = true
|
||||
ix.config.Save()
|
||||
|
||||
hook.Run("SaveData")
|
||||
|
||||
for _, v in ipairs(player.GetAll()) do
|
||||
v:SaveData()
|
||||
|
||||
if (v:GetCharacter()) then
|
||||
v:GetCharacter():Save()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function GM:GetGameDescription()
|
||||
return "IX: "..(Schema and Schema.name or "Unknown")
|
||||
end
|
||||
|
||||
function GM:OnPlayerUseBusiness(client, item)
|
||||
-- You can manipulate purchased items with this hook.
|
||||
-- does not requires any kind of return.
|
||||
-- ex) item:SetData("businessItem", true)
|
||||
-- then every purchased item will be marked as Business Item.
|
||||
end
|
||||
|
||||
function GM:PlayerDeathSound()
|
||||
return true
|
||||
end
|
||||
|
||||
function GM:InitializedSchema()
|
||||
game.ConsoleCommand("sbox_persist ix_"..Schema.folder.."\n")
|
||||
end
|
||||
|
||||
function GM:PlayerCanHearPlayersVoice(listener, speaker)
|
||||
if (!speaker:Alive()) then
|
||||
return false
|
||||
end
|
||||
|
||||
local bCanHear = listener.ixVoiceHear and listener.ixVoiceHear[speaker]
|
||||
return bCanHear, true
|
||||
end
|
||||
|
||||
function GM:PlayerCanPickupWeapon(client, weapon)
|
||||
local data = {}
|
||||
data.start = client:GetShootPos()
|
||||
data.endpos = data.start + client:GetAimVector() * 96
|
||||
data.filter = client
|
||||
local trace = util.TraceLine(data)
|
||||
|
||||
if (trace.Entity == weapon and client:KeyDown(IN_USE)) then
|
||||
return true
|
||||
end
|
||||
|
||||
return client.ixWeaponGive
|
||||
end
|
||||
|
||||
function GM:OnPhysgunFreeze(weapon, physObj, entity, client)
|
||||
-- Object is already frozen (!?)
|
||||
if (entity.scaledSize) then return true end
|
||||
if (!physObj:IsMoveable()) then return false end
|
||||
if (entity:GetUnFreezable()) then return false end
|
||||
|
||||
physObj:EnableMotion(false)
|
||||
|
||||
-- With the jeep we need to pause all of its physics objects
|
||||
-- to stop it spazzing out and killing the server.
|
||||
if (entity:GetClass() == "prop_vehicle_jeep") then
|
||||
local objects = entity:GetPhysicsObjectCount()
|
||||
|
||||
for i = 0, objects - 1 do
|
||||
entity:GetPhysicsObjectNum(i):EnableMotion(false)
|
||||
end
|
||||
end
|
||||
|
||||
-- Add it to the player's frozen props
|
||||
client:AddFrozenPhysicsObject(entity, physObj)
|
||||
client:SendHint("PhysgunUnfreeze", 0.3)
|
||||
client:SuppressHint("PhysgunFreeze")
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function GM:CanPlayerSuicide(client)
|
||||
return false
|
||||
end
|
||||
|
||||
function GM:AllowPlayerPickup(client, entity)
|
||||
return false
|
||||
end
|
||||
|
||||
function GM:PreCleanupMap()
|
||||
hook.Run("SaveData")
|
||||
hook.Run("PersistenceSave")
|
||||
end
|
||||
|
||||
function GM:PostCleanupMap()
|
||||
ix.plugin.RunLoadData()
|
||||
end
|
||||
|
||||
function GM:CharacterPreSave(character)
|
||||
local client = character:GetPlayer()
|
||||
|
||||
for _, v in pairs(character:GetInventory():GetItems()) do
|
||||
if (v.OnSave) then
|
||||
v:Call("OnSave", client)
|
||||
end
|
||||
end
|
||||
|
||||
character:SetData("health", client:Alive() and client:Health() or nil)
|
||||
end
|
||||
|
||||
timer.Create("ixLifeGuard", 1, 0, function()
|
||||
for _, v in ipairs(player.GetAll()) do
|
||||
if (v:GetCharacter() and v:Alive() and hook.Run("ShouldPlayerDrowned", v) != false) then
|
||||
if (v:WaterLevel() >= 3) then
|
||||
if (!v.drowningTime) then
|
||||
v.drowningTime = CurTime() + 30
|
||||
v.nextDrowning = CurTime()
|
||||
v.drownDamage = v.drownDamage or 0
|
||||
end
|
||||
|
||||
if (v.drowningTime < CurTime()) then
|
||||
if (v.nextDrowning < CurTime()) then
|
||||
v:ScreenFade(1, Color(0, 0, 255, 100), 1, 0)
|
||||
v:TakeDamage(10)
|
||||
v.drownDamage = v.drownDamage + 10
|
||||
v.nextDrowning = CurTime() + 1
|
||||
end
|
||||
end
|
||||
else
|
||||
if (v.drowningTime) then
|
||||
v.drowningTime = nil
|
||||
v.nextDrowning = nil
|
||||
v.nextRecover = CurTime() + 2
|
||||
end
|
||||
|
||||
if (v.nextRecover and v.nextRecover < CurTime() and v.drownDamage > 0) then
|
||||
v.drownDamage = v.drownDamage - 10
|
||||
v:SetHealth(math.Clamp(v:Health() + 10, 0, v:GetMaxHealth()))
|
||||
v.nextRecover = CurTime() + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
net.Receive("ixStringRequest", function(length, client)
|
||||
local time = net.ReadUInt(32)
|
||||
local text = net.ReadString()
|
||||
|
||||
if (client.ixStrReqs and client.ixStrReqs[time]) then
|
||||
client.ixStrReqs[time](text)
|
||||
client.ixStrReqs[time] = nil
|
||||
end
|
||||
end)
|
||||
|
||||
net.Receive("ixConfirmationRequest", function(length, client)
|
||||
local time = net.ReadUInt(32)
|
||||
local confirmation = net.ReadBool()
|
||||
|
||||
if (client.ixConfReqs and client.ixConfReqs[time]) then
|
||||
client.ixConfReqs[time](confirmation)
|
||||
client.ixConfReqs[time] = nil
|
||||
end
|
||||
end)
|
||||
|
||||
function GM:GetPreferredCarryAngles(entity)
|
||||
if (entity:GetClass() == "ix_item") then
|
||||
local itemTable = entity:GetItemTable()
|
||||
|
||||
if (itemTable) then
|
||||
local preferedAngle = itemTable.preferedAngle
|
||||
|
||||
if (preferedAngle) then -- I don't want to return something
|
||||
return preferedAngle
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function GM:PluginShouldLoad(uniqueID)
|
||||
return !ix.plugin.unloaded[uniqueID]
|
||||
end
|
||||
|
||||
function GM:DatabaseConnected()
|
||||
-- Create the SQL tables if they do not exist.
|
||||
ix.db.LoadTables()
|
||||
ix.log.LoadTables()
|
||||
|
||||
MsgC(Color(0, 255, 0), "Database Type: " .. ix.db.config.adapter .. ".\n")
|
||||
|
||||
timer.Create("ixDatabaseThink", 0.5, 0, function()
|
||||
mysql:Think()
|
||||
end)
|
||||
|
||||
ix.plugin.RunLoadData()
|
||||
end
|
||||
Reference in New Issue
Block a user