diff --git a/CHANGELOG.md b/CHANGELOG.md index 28aa2f97..7c94b28c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,18 @@ Changelog --------- The following changes have been made for each official Clockwork build. +0.95.3 +------- + +* Consolidated cl_player, sv_player and sh_player into sh_player and optimized it by localizing Clockwork libraries. + * *Contributed by NightAngel.* +* Fixed some player model animations to look better and added 'heavy' animations for physgun, etc. + * *Contributed by NightAngel.* +* Made ironsights file check for the player library and include sh_player if it isn't included when ironsights are included, also fixed a small typo with the movement slow using spread config instead of slow config. + * *Contributed by NightAngel.* +* Localized Clockwork libraries in sv_kernel for micro optimizations and fixed some mistakes that would slow down PlayerThink hooks. + * *Contributed by NightAngel.* + 0.95.2 ------- diff --git a/Clockwork/garrysmod/gamemodes/clockwork/clockwork.txt b/Clockwork/garrysmod/gamemodes/clockwork/clockwork.txt index b52beb42..58a35f21 100644 --- a/Clockwork/garrysmod/gamemodes/clockwork/clockwork.txt +++ b/Clockwork/garrysmod/gamemodes/clockwork/clockwork.txt @@ -5,7 +5,7 @@ "settings" { } - "version" "0.95.2" + "version" "0.95.3" "author" "Cloud Sixteen" "description" "A roleplaying framework developed by Cloud Sixteen for the people." "workshopid" "474315121" diff --git a/Clockwork/garrysmod/gamemodes/clockwork/framework/libraries/client/cl_player.lua b/Clockwork/garrysmod/gamemodes/clockwork/framework/libraries/client/cl_player.lua deleted file mode 100644 index 03e60f75..00000000 --- a/Clockwork/garrysmod/gamemodes/clockwork/framework/libraries/client/cl_player.lua +++ /dev/null @@ -1,711 +0,0 @@ ---[[ - © 2015 CloudSixteen.com do not share, re-distribute or modify - without permission of its author (kurozael@gmail.com). - - Clockwork was created by Conna Wiles (also known as kurozael.) - http://cloudsixteen.com/license/clockwork.html ---]] - -local Clockwork = Clockwork; -local IsValid = IsValid; -local CurTime = CurTime; -local EyePos = EyePos; -local pairs = pairs; -local type = type; -local player = player; -local string = string; -local table = table; -local util = util; - -Clockwork.player = Clockwork.kernel:NewLibrary("Player"); - --- A function to get whether the local player can hold a weight. -function Clockwork.player:CanHoldWeight(weight) - local inventoryWeight = Clockwork.inventory:CalculateWeight( - Clockwork.inventory:GetClient() - ); - - if (inventoryWeight + weight > Clockwork.player:GetMaxWeight()) then - return false; - else - return true; - end; -end; - --- A function to get whether the local player can fit a space. -function Clockwork.player:CanHoldSpace(space) - local inventorySpace = Clockwork.inventory:CalculateSpace( - Clockwork.inventory:GetClient() - ); - - if (inventorySpace + space > Clockwork.player:GetMaxSpace()) then - return false; - else - return true; - end; -end; - --- A function to get the maximum amount of weight the local player can carry. -function Clockwork.player:GetMaxWeight() - local itemsList = Clockwork.inventory:GetAsItemsList( - Clockwork.inventory:GetClient() - ); - - local weight = Clockwork.Client:GetSharedVar("InvWeight") or Clockwork.config:Get("default_inv_weight"):Get(); - - for k, v in pairs(itemsList) do - local addInvWeight = v("addInvSpace"); - - if (addInvWeight) then - weight = weight + addInvWeight; - end; - end; - - return weight; -end; - --- A function to get the maximum amount of space the local player can carry. -function Clockwork.player:GetMaxSpace() - local itemsList = Clockwork.inventory:GetAsItemsList( - Clockwork.inventory:GetClient() - ); - local space = Clockwork.Client:GetSharedVar("InvSpace") or Clockwork.config:Get("default_inv_space"):Get(); - - for k, v in pairs(itemsList) do - local addInvSpace = v("addInvVolume"); - - if (addInvSpace) then - space = space + addInvSpace; - end; - end; - - return space; -end; - --- A function to find a player by an identifier. -function Clockwork.player:FindByID(identifier) - for k, v in pairs(player.GetAll()) do - if (v:HasInitialized() and (v:SteamID() == identifier - or string.find(string.lower(v:Name()), string.lower(identifier), 1, true))) then - return v; - end; - end; -end; - --- A function to get the local player's clothes data. -function Clockwork.player:GetClothesData() - return Clockwork.ClothesData; -end; - --- A function to get the local player's accessory data. -function Clockwork.player:GetAccessoryData() - return Clockwork.AccessoryData; -end; - --- A function to get the local player's clothes item. -function Clockwork.player:GetClothesItem() - local clothesData = self:GetClothesData(); - - if (clothesData.itemID != nil and clothesData.uniqueID != nil) then - return Clockwork.inventory:FindItemByID( - Clockwork.inventory:GetClient(), - clothesData.uniqueID, clothesData.itemID - ); - end; -end; - --- A function to get whether the local player is wearing clothes. -function Clockwork.player:IsWearingClothes() - return (self:GetClothesItem() != nil); -end; - --- A function to get whether the local player has an accessory. -function Clockwork.player:HasAccessory(uniqueID) - local accessoryData = self:GetAccessoryData(); - - for k, v in pairs(accessoryData) do - if (string.lower(v) == string.lower(uniqueID)) then - return true; - end; - end; - - return false; -end; - --- A function to get whether the local player is wearing an accessory. -function Clockwork.player:IsWearingAccessory(itemTable) - local accessoryData = self:GetAccessoryData(); - local itemID = itemTable("itemID"); - - if (accessoryData[itemID]) then - return true; - else - return false; - end; -end; - --- A function to get whether the local player is wearing an item. -function Clockwork.player:IsWearingItem(itemTable) - local clothesItem = self:GetClothesItem(); - return (clothesItem and clothesItem:IsTheSameAs(itemTable)); -end; - --- A function to get whether a player is noclipping. -function Clockwork.player:IsNoClipping(player) - if (player:GetMoveType() == MOVETYPE_NOCLIP - and !player:InVehicle()) then - return true; - end; -end; - --- A function to get whether a player is an admin. -function Clockwork.player:IsAdmin(player) - if (self:HasFlags(player, "o")) then - return true; - end; -end; - --- A function to get whether the local player's data has streamed. -function Clockwork.player:HasDataStreamed() - return Clockwork.DataHasStreamed; -end; - --- A function to get whether a player can hear another player. -function Clockwork.player:CanHearPlayer(player, target, allowance) - if (Clockwork.config:Get("messages_must_see_player"):Get()) then - return self:CanSeePlayer(player, target, (allowance or 0.5), true); - else - return true; - end; -end; - --- A function to get whether the target recognises the local player. -function Clockwork.player:DoesTargetRecognise() - if (Clockwork.config:Get("recognise_system"):Get()) then - return Clockwork.Client:GetSharedVar("TargetKnows"); - else - return true; - end; -end; - --- A function to get a player's real trace. -function Clockwork.player:GetRealTrace(player, useFilterTrace) - if (!IsValid(player)) then - return; - end; - - local angles = player:GetAimVector() * 4096; - local eyePos = EyePos(); - - if (player != Clockwork.Client) then - eyePos = player:EyePos(); - end; - - local trace = util.TraceLine({ - endpos = eyePos + angles, - start = eyePos, - filter = player - }); - - local newTrace = util.TraceLine({ - endpos = eyePos + angles, - filter = player, - start = eyePos, - mask = CONTENTS_SOLID + CONTENTS_MOVEABLE + CONTENTS_OPAQUE + CONTENTS_DEBRIS + CONTENTS_HITBOX + CONTENTS_MONSTER - }); - - if ((IsValid(newTrace.Entity) and !newTrace.HitWorld and (!IsValid(trace.Entity) - or string.find(trace.Entity:GetClass(), "vehicle"))) or useFilterTrace) then - trace = newTrace; - end; - - return trace; -end; - --- A function to get the local player's action. -function Clockwork.player:GetAction(player, percentage) - local startActionTime = player:GetSharedVar("StartActTime"); - local actionDuration = player:GetSharedVar("ActDuration"); - local curTime = CurTime(); - local action = player:GetSharedVar("ActName"); - - if (curTime < startActionTime + actionDuration) then - if (percentage) then - return action, (100 / actionDuration) * (actionDuration - ((startActionTime + actionDuration) - curTime)); - else - return action, actionDuration, startActionTime; - end; - else - return "", 0, 0; - end; -end; - --- A function to get the local player's maximum characters. -function Clockwork.player:GetMaximumCharacters() - local whitelisted = Clockwork.character:GetWhitelisted(); - local maximum = Clockwork.config:Get("additional_characters"):Get(2); - - for k, v in pairs(Clockwork.faction.stored) do - if (!v.whitelist or table.HasValue(whitelisted, v.name)) then - maximum = maximum + 1; - end; - end; - - return maximum; -end; - --- A function to get whether a player's weapon is raised. -function Clockwork.player:GetWeaponRaised(player) - return player:GetSharedVar("IsWepRaised"); -end; - --- A function to get a player's unrecognised name. -function Clockwork.player:GetUnrecognisedName(player) - local unrecognisedPhysDesc = self:GetPhysDesc(player); - local unrecognisedName = Clockwork.config:Get("unrecognised_name"):Get(); - local usedPhysDesc; - - if (unrecognisedPhysDesc) then - unrecognisedName = unrecognisedPhysDesc; - usedPhysDesc = true; - end; - - return unrecognisedName, usedPhysDesc; -end; - --- A function to get whether a player can see an NPC. -function Clockwork.player:CanSeeNPC(player, target, allowance, ignoreEnts) - if (player:GetEyeTraceNoCursor().Entity == target) then - return true; - else - local trace = {}; - - trace.mask = CONTENTS_SOLID + CONTENTS_MOVEABLE + CONTENTS_OPAQUE + CONTENTS_DEBRIS + CONTENTS_HITBOX + CONTENTS_MONSTER; - trace.start = player:GetShootPos(); - trace.endpos = target:GetShootPos(); - trace.filter = {player, target}; - - if (ignoreEnts) then - if (type(ignoreEnts) == "table") then - table.Add(trace.filter, ignoreEnts); - else - table.Add(trace.filter, ents.GetAll()); - end; - end; - - trace = util.TraceLine(trace); - - if (trace.Fraction >= (allowance or 0.75)) then - return true; - end; - end; -end; - --- A function to get whether a player can see a player. -function Clockwork.player:CanSeePlayer(player, target, allowance, ignoreEnts) - if (player:GetEyeTraceNoCursor().Entity == target) then - return true; - elseif (target:GetEyeTraceNoCursor().Entity == player) then - return true; - else - local trace = {}; - - trace.mask = CONTENTS_SOLID + CONTENTS_MOVEABLE + CONTENTS_OPAQUE + CONTENTS_DEBRIS + CONTENTS_HITBOX + CONTENTS_MONSTER; - trace.start = player:GetShootPos(); - trace.endpos = target:GetShootPos(); - trace.filter = {player, target}; - - if (ignoreEnts) then - if (type(ignoreEnts) == "table") then - table.Add(trace.filter, ignoreEnts); - else - table.Add(trace.filter, ents.GetAll()); - end; - end; - - trace = util.TraceLine(trace); - - if (trace.Fraction >= (allowance or 0.75)) then - return true; - end; - end; -end; - --- A function to get whether a player can see an entity. -function Clockwork.player:CanSeeEntity(player, target, allowance, ignoreEnts) - if (player:GetEyeTraceNoCursor().Entity == target) then - return true; - else - local trace = {}; - - trace.mask = CONTENTS_SOLID + CONTENTS_MOVEABLE + CONTENTS_OPAQUE + CONTENTS_DEBRIS + CONTENTS_HITBOX + CONTENTS_MONSTER; - trace.start = player:GetShootPos(); - trace.endpos = target:LocalToWorld(target:OBBCenter()); - trace.filter = {player, target}; - - if (ignoreEnts) then - if (type(ignoreEnts) == "table") then - table.Add(trace.filter, ignoreEnts); - else - table.Add(trace.filter, ents.GetAll()); - end; - end; - - trace = util.TraceLine(trace); - - if (trace.Fraction >= (allowance or 0.75)) then - return true; - end; - end; -end; - --- A function to get whether a player can see a position. -function Clockwork.player:CanSeePosition(player, position, allowance, ignoreEnts) - local trace = {}; - - trace.mask = CONTENTS_SOLID + CONTENTS_MOVEABLE + CONTENTS_OPAQUE + CONTENTS_DEBRIS + CONTENTS_HITBOX + CONTENTS_MONSTER; - trace.start = player:GetShootPos(); - trace.endpos = position; - trace.filter = player; - - if (ignoreEnts) then - if (type(ignoreEnts) == "table") then - table.Add(trace.filter, ignoreEnts); - else - table.Add(trace.filter, ents.GetAll()); - end; - end; - - trace = util.TraceLine(trace); - - if (trace.Fraction >= (allowance or 0.75)) then - return true; - end; -end; - --- A function to get a player's wages name. -function Clockwork.player:GetWagesName(player) - return Clockwork.class:Query(player:Team(), "wagesName", Clockwork.config:Get("wages_name"):Get()); -end; - --- A function to check whether a player is ragdolled -function Clockwork.player:IsRagdolled(player, exception, entityless) - if (player:GetRagdollEntity() or entityless) then - if (player:GetSharedVar("IsRagdoll") == 0) then - return false; - elseif (player:GetSharedVar("IsRagdoll") == exception) then - return false; - else - return (player:GetSharedVar("IsRagdoll") != RAGDOLL_NONE); - end; - end; -end; - --- A function to get whether the local player recognises another player. -function Clockwork.player:DoesRecognise(player, status, isAccurate) - if (!status) then - return self:DoesRecognise(player, RECOGNISE_PARTIAL); - elseif (Clockwork.config:Get("recognise_system"):Get()) then - local key = self:GetCharacterKey(player); - local realValue = false; - - if (self:GetCharacterKey(Clockwork.Client) == key) then - return true; - elseif (Clockwork.RecognisedNames[key]) then - if (isAccurate) then - realValue = (Clockwork.RecognisedNames[key] == status); - else - realValue = (Clockwork.RecognisedNames[key] >= status); - end; - end; - - return Clockwork.plugin:Call("PlayerDoesRecognisePlayer", player, status, isAccurate, realValue); - else - return true; - end; -end; - --- A function to get a player's character key. -function Clockwork.player:GetCharacterKey(player) - if (IsValid(player)) then - return player:GetSharedVar("Key"); - end; -end; - --- A function to get a player's ragdoll state. -function Clockwork.player:GetRagdollState(player) - if (player:GetSharedVar("IsRagdoll") == 0) then - return false; - else - return player:GetSharedVar("IsRagdoll"); - end; -end; - --- A function to get a player's physical description. -function Clockwork.player:GetPhysDesc(player) - if (!player) then - player = Clockwork.Client; - end; - - local physDesc = player:GetSharedVar("PhysDesc"); - local team = player:Team(); - - if (physDesc == "") then - physDesc = Clockwork.class:Query(team, "defaultPhysDesc", ""); - end; - - if (physDesc == "") then - physDesc = Clockwork.config:Get("default_physdesc"):Get(); - end; - - if (!physDesc or physDesc == "") then - physDesc = "This character has no physical description set."; - else - physDesc = Clockwork.kernel:ModifyPhysDesc(physDesc); - end; - - local override = Clockwork.plugin:Call("GetPlayerPhysDescOverride", player, physDesc); - - if (override) then - physDesc = override; - end; - - return physDesc; -end; - --- A function to get the local player's wages. -function Clockwork.player:GetWages() - return Clockwork.Client:GetSharedVar("Wages"); -end; - --- A function to get the local player's cash. -function Clockwork.player:GetCash() - return Clockwork.Client:GetSharedVar("Cash"); -end; - --- A function to get a player's ragdoll entity. -function Clockwork.player:GetRagdollEntity(player) - local ragdollEntity = player:GetSharedVar("Ragdoll"); - - if (IsValid(ragdollEntity)) then - return ragdollEntity; - end; -end; - --- A function to get a player's default skin. -function Clockwork.player:GetDefaultSkin(player) - local model, skin = Clockwork.class:GetAppropriateModel(player:Team(), player); - - return skin; -end; - --- A function to get a player's default model. -function Clockwork.player:GetDefaultModel(player) - local model, skin = Clockwork.class:GetAppropriateModel(player:Team(), player); - return model; -end; - --- A function to check if a player has any flags. -function Clockwork.player:HasAnyFlags(player, flags, bByDefault) - local playerFlags = player:GetSharedVar("Flags") - - if (playerFlags != "") then - if (Clockwork.class:HasAnyFlags(player:Team(), flags) and !bByDefault) then - return true; - end; - - for i = 1, #flags do - local flag = string.utf8sub(flags, i, i); - local bSuccess = true; - - if (!bByDefault) then - local hasFlag = Clockwork.plugin:Call("PlayerDoesHaveFlag", player, flag); - - if (hasFlag != false) then - if (hasFlag) then - return true; - end; - else - bSuccess = nil; - end; - end; - - if (bSuccess) then - if (flag == "s") then - if (player:IsSuperAdmin()) then - return true; - end; - elseif (flag == "a") then - if (player:IsAdmin()) then - return true; - end; - elseif (flag == "o") then - if (player:IsSuperAdmin() or player:IsAdmin()) then - return true; - elseif (player:IsUserGroup("operator")) then - return true; - end; - elseif (string.find(playerFlags, flag)) then - return true; - end; - end; - end; - end; -end; - --- A function to check if a player has access. -function Clockwork.player:HasFlags(player, flags, bByDefault) - local playerFlags = player:GetSharedVar("Flags") - - if (playerFlags != "") then - if (Clockwork.class:HasFlags(player:Team(), flags) and !bByDefault) then - return true; - end; - - for i = 1, #flags do - local flag = string.utf8sub(flags, i, i); - local bSuccess; - - if (!bByDefault) then - local hasFlag = Clockwork.plugin:Call("PlayerDoesHaveFlag", player, flag); - - if (hasFlag != false) then - if (hasFlag) then - bSuccess = true; - end; - else - return; - end; - end; - - if (!bSuccess) then - if (flag == "s") then - if (!player:IsSuperAdmin()) then - return; - end; - elseif (flag == "a") then - if (!player:IsAdmin()) then - return; - end; - elseif (flag == "o") then - if (!player:IsSuperAdmin() and !player:IsAdmin()) then - if (!player:IsUserGroup("operator")) then - return; - end; - end; - elseif (!string.find(playerFlags, flag)) then - return false; - end; - end; - end; - - return true; - end; -end; - --- A function to set a shared variable for a player. -function Clockwork.player:SetSharedVar(player, key, value) - if (IsValid(player)) then - local sharedVars = Clockwork.kernel:GetSharedVars():Player(); - - if (!sharedVars) then - return; - elseif (not sharedVars[key]) then - return; - end; - - local sharedVarData = sharedVars[key]; - - if (sharedVarData.bPlayerOnly) then - if (value == nil) then - sharedVarData.value = Clockwork.kernel:GetDefaultNetworkedValue(sharedVarData.class); - else - sharedVarData.value = value; - end; - else - local class = Clockwork.kernel:ConvertNetworkedClass(sharedVarData.class); - - if (class) then - player["SetNetworked"..class](player, key, value); - end; - end; - end; -end; - --- A function to get a player's shared variable. -function Clockwork.player:GetSharedVar(player, key, sharedTable) - if (IsValid(player)) then - if (!sharedTable) then - local sharedVars = Clockwork.kernel:GetSharedVars():Player(); - - if (!sharedVars) then - return; - elseif (not sharedVars[key]) then - return; - end; - - local sharedVarData = sharedVars[key]; - - if (sharedVarData.bPlayerOnly) then - if (!sharedVarData.value) then - return Clockwork.kernel:GetDefaultNetworkedValue(sharedVarData.class); - else - return sharedVarData.value; - end; - else - local class = Clockwork.kernel:ConvertNetworkedClass(sharedVarData.class); - - if (class) then - return player["GetNetworked"..class](player, key); - end; - end; - else - sharedTable = Clockwork.SharedTables[sharedTable]; - - if (sharedTable) then - return sharedTable[key]; - end; - end; - end; -end; - --- A function to get whether the local player is drunk. -function Clockwork.player:GetDrunk() - local isDrunk = Clockwork.Client:GetSharedVar("IsDrunk"); - - if (isDrunk and isDrunk > 0) then - return isDrunk; - end; -end; - --- A function to get a player's chat icon. -function Clockwork.player:GetChatIcon(player) - local icon; - - for k, v in pairs(Clockwork.icon:GetAll()) do - if (v.callback(player)) then - if (!icon) then - icon = v.path; - end; - - if (v.isPlayer) then - icon = v.path; - break; - end; - end; - end; - - if (!icon) then - local faction = player:GetFaction(); - - icon = "icon16/user.png"; - - if (faction and Clockwork.faction.stored[faction]) then - if (Clockwork.faction.stored[faction].whitelist) then - icon = "icon16/add.png"; - end; - end; - end; - - return icon; -end; \ No newline at end of file diff --git a/Clockwork/garrysmod/gamemodes/clockwork/framework/libraries/server/sv_player.lua b/Clockwork/garrysmod/gamemodes/clockwork/framework/libraries/server/sv_player.lua deleted file mode 100644 index 2fc221c6..00000000 --- a/Clockwork/garrysmod/gamemodes/clockwork/framework/libraries/server/sv_player.lua +++ /dev/null @@ -1,3498 +0,0 @@ ---[[ - © 2015 CloudSixteen.com do not share, re-distribute or modify - without permission of its author (kurozael@gmail.com). - - Clockwork was created by Conna Wiles (also known as kurozael.) - http://cloudsixteen.com/license/clockwork.html ---]] - -local Clockwork = Clockwork; -local Json = Json; -local tostring = tostring; -local tonumber = tonumber; -local IsValid = IsValid; -local CurTime = CurTime; -local Vector = Vector; -local Angle = Angle; -local Color = Color; -local pairs = pairs; -local type = type; -local player = player; -local string = string; -local table = table; -local ents = ents; -local math = math; -local util = util; - -Clockwork.player = Clockwork.kernel:NewLibrary("Player"); -Clockwork.player.property = Clockwork.player.property or {}; -Clockwork.player.stored = Clockwork.player.stored or {}; - --- A function to run an inventory action for a player. -function Clockwork.player:InventoryAction(player, itemTable, action) - return self:RunClockworkCommand(player, "InvAction", action, itemTable("uniqueID"), tostring(itemTable("itemID"))); -end; - --- A function to get a player's gear. -function Clockwork.player:GetGear(player, gearClass) - if (player.cwGearTab and IsValid(player.cwGearTab[gearClass])) then - return player.cwGearTab[gearClass]; - end; -end; - --- A function to create a character from data. -function Clockwork.player:CreateCharacterFromData(player, data) - if (player.cwIsCreatingChar) then - return; - end; - - local minimumPhysDesc = Clockwork.config:Get("minimum_physdesc"):Get(); - local attributesTable = Clockwork.attribute:GetAll(); - local factionTable = Clockwork.faction:FindByID(data.faction); - local attributes = nil; - local info = {}; - - if (table.Count(attributesTable) > 0) then - for k, v in pairs(attributesTable) do - if (v.isOnCharScreen) then - attributes = true; - break; - end; - end; - end; - - if (!factionTable) then - return Clockwork.player:SetCreateFault( - player, "You did not choose a faction, or the faction that you chose is not valid!" - ); - end; - - info.attributes = {}; - info.faction = factionTable.name; - info.gender = data.gender; - info.model = data.model; - info.data = {}; - - if (data.plugin) then - for k, v in pairs(data.plugin) do - info.data[k] = v; - end; - end; - - local classes = false; - - for k, v in pairs(Clockwork.class:GetAll()) do - if (v.isOnCharScreen and (v.factions - and table.HasValue(v.factions, factionTable.name))) then - classes = true; - end; - end; - - if (classes) then - local classTable = Clockwork.class:FindByID(data.class); - - if (!classTable) then - return Clockwork.player:SetCreateFault( - player, "You did not choose a class, or the class that you chose is not valid!" - ); - else - info.data["class"] = classTable.name; - end; - end; - - if (attributes and type(data.attributes) == "table") then - local maximumPoints = Clockwork.config:Get("default_attribute_points"):Get(); - local pointsSpent = 0; - - if (factionTable.attributePointsScale) then - maximumPoints = math.Round(maximumPoints * factionTable.attributePointsScale); - end; - - if (factionTable.maximumAttributePoints) then - maximumPoints = factionTable.maximumAttributePoints; - end; - - for k, v in pairs(data.attributes) do - local attributeTable = Clockwork.attribute:FindByID(k); - - if (attributeTable and attributeTable.isOnCharScreen) then - local uniqueID = attributeTable.uniqueID; - local amount = math.Clamp(v, 0, attributeTable.maximum); - - info.attributes[uniqueID] = { - amount = amount, - progress = 0 - }; - - pointsSpent = pointsSpent + amount; - end; - end; - - if (pointsSpent > maximumPoints) then - return Clockwork.player:SetCreateFault( - player, "You have chosen more "..Clockwork.option:GetKey("name_attribute", true).." points than you can afford to spend!" - ); - end; - elseif (attributes) then - return Clockwork.player:SetCreateFault( - player, "You did not choose any "..Clockwork.option:GetKey("name_attributes", true).." or the ones that you did are not valid!" - ); - end; - - if (!factionTable.GetName) then - if (!factionTable.useFullName) then - if (data.forename and data.surname) then - data.forename = string.gsub(data.forename, "^.", string.upper); - data.surname = string.gsub(data.surname, "^.", string.upper); - - if (string.find(data.forename, "[%p%s%d]") or string.find(data.surname, "[%p%s%d]")) then - return Clockwork.player:SetCreateFault( - player, "Your forename and surname must not contain punctuation, spaces or digits!" - ); - end; - - if (!string.find(data.forename, "[aeiou]") or !string.find(data.surname, "[aeiou]")) then - return Clockwork.player:SetCreateFault( - player, "Your forename and surname must both contain at least one vowel!" - ); - end; - - if (string.utf8len(data.forename) < 2 or string.utf8len(data.surname) < 2) then - return Clockwork.player:SetCreateFault( - player, "Your forename and surname must both be at least 2 characters long!" - ); - end; - - if (string.utf8len(data.forename) > 16 or string.utf8len(data.surname) > 16) then - return Clockwork.player:SetCreateFault( - player, "Your forename and surname must not be greater than 16 characters long!" - ); - end; - else - return Clockwork.player:SetCreateFault( - player, "You did not choose a name, or the name that you chose is not valid!" - ); - end; - elseif (!data.fullName or data.fullName == "") then - return Clockwork.player:SetCreateFault( - player, "You did not choose a name, or the name that you chose is not valid!" - ); - end; - end; - - if (Clockwork.command:FindByID("CharPhysDesc") != nil) then - if (type(data.physDesc) != "string") then - return Clockwork.player:SetCreateFault( - player, "You did not enter a physical description!" - ); - elseif (string.utf8len(data.physDesc) < minimumPhysDesc) then - return Clockwork.player:SetCreateFault( - player, "The physical description must be at least "..minimumPhysDesc.." characters long!" - ); - end; - - info.data["PhysDesc"] = Clockwork.kernel:ModifyPhysDesc(data.physDesc); - end; - - if (!factionTable.GetModel and !info.model) then - return Clockwork.player:SetCreateFault( - player, "You did not choose a model, or the model that you chose is not valid!" - ); - end; - - if (!Clockwork.faction:IsGenderValid(info.faction, info.gender)) then - return Clockwork.player:SetCreateFault( - player, "You did not choose a gender, or the gender that you chose is not valid!" - ); - end; - - if (factionTable.whitelist and !Clockwork.player:IsWhitelisted(player, info.faction)) then - return Clockwork.player:SetCreateFault( - player, "You are not on the "..info.faction.." whitelist!" - ); - elseif (Clockwork.faction:IsModelValid(factionTable.name, info.gender, info.model) - or (factionTable.GetModel and !info.model)) then - local charactersTable = Clockwork.config:Get("mysql_characters_table"):Get(); - local schemaFolder = Clockwork.kernel:GetSchemaFolder(); - local characterID = nil; - local characters = player:GetCharacters(); - - if (Clockwork.faction:HasReachedMaximum(player, factionTable.name)) then - return Clockwork.player:SetCreateFault( - player, "You cannot create any more characters in this faction." - ); - end; - - for i = 1, Clockwork.player:GetMaximumCharacters(player) do - if (!characters[i]) then - characterID = i; - break; - end; - end; - - if (characterID) then - if (factionTable.GetName) then - info.name = factionTable:GetName(player, info, data); - elseif (!factionTable.useFullName) then - info.name = data.forename.." "..data.surname; - else - info.name = data.fullName; - end; - - if (factionTable.GetModel) then - info.model = factionTable:GetModel(player, info, data); - else - info.model = data.model; - end; - - if (factionTable.OnCreation) then - local fault = factionTable:OnCreation(player, info); - - if (fault == false or type(fault) == "string") then - return Clockwork.player:SetCreateFault( - player, fault or "There was an error creating this character!" - ); - end; - end; - - for k, v in pairs(characters) do - if (v.name == info.name) then - return Clockwork.player:SetCreateFault( - player, "You already have a character with the name '"..info.name.."'!" - ); - end; - end; - - local fault = Clockwork.plugin:Call("PlayerAdjustCharacterCreationInfo", player, info, data); - - if (fault == false or type(fault) == "string") then - return Clockwork.player:SetCreateFault( - player, fault or "There was an error creating this character!" - ); - end; - - local queryObj = Clockwork.database:Select(charactersTable); - queryObj:AddWhere("_Schema = ?", schemaFolder); - queryObj:AddWhere("_Name = ?", info.name); - queryObj:SetCallback(function(result) - if (!IsValid(player)) then return; end; - - if (Clockwork.database:IsResult(result)) then - Clockwork.player:SetCreateFault( - player, "A character with the name '"..info.name.."' already exists!" - ); - player.cwIsCreatingChar = nil; - else - Clockwork.player:LoadCharacter(player, characterID, - { - attributes = info.attributes, - faction = info.faction, - gender = info.gender, - model = info.model, - name = info.name, - data = info.data - }, - function() - Clockwork.kernel:PrintLog(LOGTYPE_MINOR, - player:SteamName().." has created a "..info.faction.." character called '"..info.name.."'." - ); - - Clockwork.datastream:Start(player, "CharacterFinish", {bSuccess = true}); - - player.cwIsCreatingChar = nil; - - local characters = player:GetCharacters(); - - if (table.Count(characters) == 1) then - Clockwork.player:UseCharacter(player, characterID); - end; - end - ); - end; - end); - queryObj:Pull(); - else - return Clockwork.player:SetCreateFault(player, "You cannot create any more characters!"); - end; - else - return Clockwork.player:SetCreateFault( - player, "You did not choose a model, or the model that you chose is not valid!" - ); - end; -end; - --- A function to open the character menu. -function Clockwork.player:SetCharacterMenuOpen(player, bReset) - if (player:HasInitialized()) then - Clockwork.datastream:Start(player, "CharacterOpen", (bReset == true)); - - if (bReset) then - player.cwCharMenuReset = true; - player:KillSilent(); - end; - end; -end; - --- A function to start a sound for a player. -function Clockwork.player:StartSound(player, uniqueID, sound, fVolume) - if (!player.cwSoundsPlaying) then - player.cwSoundsPlaying = {}; - end; - - if (!player.cwSoundsPlaying[uniqueID] - or player.cwSoundsPlaying[uniqueID] != sound) then - player.cwSoundsPlaying[uniqueID] = sound; - - Clockwork.datastream:Start(player, "StartSound", { - uniqueID = uniqueID, sound = sound, volume = (fVolume or 0.75) - }); - end; -end; - --- A function to stop a sound for a player. -function Clockwork.player:StopSound(player, uniqueID, iFadeOut) - if (!player.cwSoundsPlaying) then - player.cwSoundsPlaying = {}; - end; - - if (player.cwSoundsPlaying[uniqueID]) then - player.cwSoundsPlaying[uniqueID] = nil; - - Clockwork.datastream:Start(player, "StopSound", { - uniqueID = uniqueID, fadeOut = (iFadeOut or 0) - }); - end; -end; - --- A function to remove a player's gear. -function Clockwork.player:RemoveGear(player, gearClass) - if (player.cwGearTab and IsValid(player.cwGearTab[gearClass])) then - player.cwGearTab[gearClass]:Remove(); - player.cwGearTab[gearClass] = nil; - end; -end; - --- A function to strip all of a player's gear. -function Clockwork.player:StripGear(player) - if (!player.cwGearTab) then return; end; - - for k, v in pairs(player.cwGearTab) do - if (IsValid(v)) then v:Remove(); end; - end; - - player.cwGearTab = {}; -end; - --- A function to create a player's gear. -function Clockwork.player:CreateGear(player, gearClass, itemTable, bMustHave) - if (!player.cwGearTab) then - player.cwGearTab = {}; - end; - - if (IsValid(player.cwGearTab[gearClass])) then - player.cwGearTab[gearClass]:Remove(); - end; - - if (itemTable("isAttachment")) then - local position = player:GetPos(); - local angles = player:GetAngles(); - local model = itemTable("attachmentModel", itemTable("model")); - - player.cwGearTab[gearClass] = ents.Create("cw_gear"); - player.cwGearTab[gearClass]:SetParent(player); - player.cwGearTab[gearClass]:SetAngles(angles); - player.cwGearTab[gearClass]:SetModel(model); - player.cwGearTab[gearClass]:SetPos(position); - player.cwGearTab[gearClass]:Spawn(); - - if (itemTable("attachmentMaterial")) then - player.cwGearTab[gearClass]:SetMaterial(itemTable("attachmentMaterial")); - end; - - if (itemTable("attachmentColor")) then - player.cwGearTab[gearClass]:SetColor( - Clockwork.kernel:UnpackColor(itemTable("attachmentColor")) - ); - else - player.cwGearTab[gearClass]:SetColor(Color(255, 255, 255, 255)); - end; - - if (IsValid(player.cwGearTab[gearClass])) then - player.cwGearTab[gearClass]:SetOwner(player); - player.cwGearTab[gearClass]:SetMustHave(bMustHave); - player.cwGearTab[gearClass]:SetItemTable(gearClass, itemTable); - end; - end; -end; - --- A function to get whether a player is noclipping. -function Clockwork.player:IsNoClipping(player) - if (player:GetMoveType() == MOVETYPE_NOCLIP - and !player:InVehicle()) then - return true; - end; -end; - --- A function to get whether a player is an admin. -function Clockwork.player:IsAdmin(player) - if (self:HasFlags(player, "o")) then - return true; - end; -end; - --- A function to get whether a player can hear another player. -function Clockwork.player:CanHearPlayer(player, target, iAllowance) - if (Clockwork.config:Get("messages_must_see_player"):Get()) then - return self:CanSeePlayer(player, target, (iAllowance or 0.5), true); - else - return true; - end; -end; - --- A functon to get all property. -function Clockwork.player:GetAllProperty() - for k, v in pairs(self.property) do - if (!IsValid(v)) then - self.property[k] = nil; - end; - end; - - return self.property; -end; - --- A function to set a player's action. -function Clockwork.player:SetAction(player, action, duration, priority, Callback) - local currentAction = self:GetAction(player); - - if (type(action) != "string" or action == "") then - Clockwork.kernel:DestroyTimer("Action"..player:UniqueID()); - - player:SetSharedVar("StartActTime", 0); - player:SetSharedVar("ActDuration", 0); - player:SetSharedVar("ActName", ""); - - return; - elseif (duration == false or duration == 0) then - if (currentAction == action) then - return self:SetAction(player, false); - else - return false; - end; - end; - - if (player.cwAction) then - if ((priority and priority > player.cwAction[2]) - or currentAction == "" or action == player.cwAction[1]) then - player.cwAction = nil; - end; - end; - - if (!player.cwAction) then - local curTime = CurTime(); - - player:SetSharedVar("StartActTime", curTime); - player:SetSharedVar("ActDuration", duration); - player:SetSharedVar("ActName", action); - - if (priority) then - player.cwAction = {action, priority}; - else - player.cwAction = nil; - end; - - Clockwork.kernel:CreateTimer("Action"..player:UniqueID(), duration, 1, function() - if (Callback) then - Callback(); - end; - end); - end; -end; - --- A function to set the player's character menu state. -function Clockwork.player:SetCharacterMenuState(player, state) - Clockwork.datastream:Start(player, "CharacterMenu", state); -end; - --- A function to get a player's action. -function Clockwork.player:GetAction(player, percentage) - local startActionTime = player:GetSharedVar("StartActTime"); - local actionDuration = player:GetSharedVar("ActDuration"); - local curTime = CurTime(); - local action = player:GetSharedVar("ActName"); - - if (startActionTime and CurTime() < startActionTime + actionDuration) then - if (percentage) then - return action, (100 / actionDuration) * (actionDuration - ((startActionTime + actionDuration) - curTime)); - else - return action, actionDuration, startActionTime; - end; - else - return "", 0, 0; - end; -end; - --- A function to run a Clockwork command on a player. -function Clockwork.player:RunClockworkCommand(player, command, ...) - return Clockwork.command:ConsoleCommand(player, "cwCmd", {command, ...}); -end; - --- A function to get a player's wages name. -function Clockwork.player:GetWagesName(player) - return Clockwork.class:Query(player:Team(), "wagesName", Clockwork.config:Get("wages_name"):Get()); -end; - --- A function to get whether a player can see an entity. -function Clockwork.player:CanSeeEntity(player, target, iAllowance, tIgnoreEnts) - if (player:GetEyeTraceNoCursor().Entity != target) then - return self:CanSeePosition(player, target:LocalToWorld(target:OBBCenter()), iAllowance, tIgnoreEnts, target); - else - return true; - end; -end; - ---[[ - Duplicate functions, keeping them like this for backward compatiblity. ---]] -Clockwork.player.CanSeePlayer = Clockwork.player.CanSeeEntity; -Clockwork.player.CanSeeNPC = Clockwork.player.CanSeeEntity; - --- A function to get whether a player can see a position. -function Clockwork.player:CanSeePosition(player, position, iAllowance, tIgnoreEnts, targetEnt) - local trace = {}; - - trace.mask = CONTENTS_SOLID + CONTENTS_MOVEABLE + CONTENTS_OPAQUE + CONTENTS_DEBRIS + CONTENTS_HITBOX + CONTENTS_MONSTER; - trace.start = player:GetShootPos(); - trace.endpos = position; - trace.filter = {player, targetEnt}; - - if (tIgnoreEnts) then - if (type(tIgnoreEnts) == "table") then - table.Add(trace.filter, tIgnoreEnts); - else - table.Add(trace.filter, ents.GetAll()); - end; - end; - - trace = util.TraceLine(trace); - - if (trace.Fraction >= (iAllowance or 0.75)) then - return true; - end; -end; - --- A function to update whether a player's weapon is raised. -function Clockwork.player:UpdateWeaponRaised(player) - local bIsRaised = self:GetWeaponRaised(player); - local weapon = player:GetActiveWeapon(); - - player:SetSharedVar("IsWepRaised", bIsRaised); - - if (IsValid(weapon)) then - Clockwork.kernel:HandleWeaponFireDelay(player, bIsRaised, weapon, CurTime()); - end; -end; - --- A function to get whether a player's weapon is raised. -function Clockwork.player:GetWeaponRaised(player, bIsCached) - if (bIsCached) then - return player:GetSharedVar("IsWepRaised"); - end; - - local weapon = player:GetActiveWeapon(); - - if (IsValid(weapon) and !weapon.NeverRaised) then - if (weapon.GetRaised) then - local bIsRaised = weapon:GetRaised(); - - if (bIsRaised != nil) then - return bIsRaised; - end; - end; - - return Clockwork.plugin:Call("GetPlayerWeaponRaised", player, weapon:GetClass(), weapon); - end; - - return false; -end; - --- A function to toggle whether a player's weapon is raised. -function Clockwork.player:ToggleWeaponRaised(player) - self:SetWeaponRaised(player, !player.cwWeaponRaiseClass); -end; - --- A function to set whether a player's weapon is raised. -function Clockwork.player:SetWeaponRaised(player, bIsRaised) - local weapon = player:GetActiveWeapon(); - - if (IsValid(weapon)) then - if (type(bIsRaised) == "number") then - player.cwAutoWepRaised = weapon:GetClass(); - player:UpdateWeaponRaised(); - - Clockwork.kernel:CreateTimer("WeaponRaised"..player:UniqueID(), bIsRaised, 1, function() - if (IsValid(player)) then - player.cwAutoWepRaised = nil; - player:UpdateWeaponRaised(); - end; - end); - elseif (bIsRaised) then - if (!player.cwWeaponRaiseClass) then - if (weapon.OnRaised) then - weapon:OnRaised(); - end; - end; - - player.cwWeaponRaiseClass = weapon:GetClass(); - player.cwAutoWepRaised = nil; - player:UpdateWeaponRaised(); - else - if (player.cwWeaponRaiseClass) then - if (weapon.OnLowered) then - weapon:OnLowered(); - end; - end; - - player.cwWeaponRaiseClass = nil; - player.cwAutoWepRaised = nil; - player:UpdateWeaponRaised(); - end; - end; -end; - --- A function to setup a player's remove property delays. -function Clockwork.player:SetupRemovePropertyDelays(player, bAllCharacters) - local uniqueID = player:UniqueID(); - local key = player:GetCharacterKey(); - - for k, v in pairs(self:GetAllProperty()) do - local removeDelay = Clockwork.entity:QueryProperty(v, "removeDelay"); - - if (IsValid(v) and removeDelay) then - if (uniqueID == Clockwork.entity:QueryProperty(v, "uniqueID") - and (bAllCharacters or key == Clockwork.entity:QueryProperty(v, "key"))) then - Clockwork.kernel:CreateTimer("RemoveDelay"..v:EntIndex(), removeDelay, 1, function(entity) - if (IsValid(entity)) then - entity:Remove(); - end; - end, v); - end; - end; - end; -end; - --- A function to disable a player's property. -function Clockwork.player:DisableProperty(player, bCharacterOnly) - local uniqueID = player:UniqueID(); - local key = player:GetCharacterKey(); - - for k, v in pairs(self:GetAllProperty()) do - if (IsValid(v) and uniqueID == Clockwork.entity:QueryProperty(v, "uniqueID") - and (!bCharacterOnly or key == Clockwork.entity:QueryProperty(v, "key"))) then - Clockwork.entity:SetPropertyVar(v, "owner", NULL); - - if (Clockwork.entity:QueryProperty(v, "networked")) then - v:SetNetworkedEntity("Owner", NULL); - end; - - v:SetOwnerKey(nil); - v:SetNetworkedBool("Owned", false); - v:SetNetworkedInt("Key", 0); - - if (v.SetPlayer) then - v:SetVar("Founder", NULL); - v:SetVar("FounderIndex", 0); - v:SetNetworkedString("FounderName", ""); - end; - end; - end; -end; - --- A function to give property to a player. -function Clockwork.player:GiveProperty(player, entity, networked, removeDelay) - Clockwork.kernel:DestroyTimer("RemoveDelay"..entity:EntIndex()); - Clockwork.entity:ClearProperty(entity); - - entity.cwPropertyTab = { - key = player:GetCharacterKey(), - owner = player, - owned = true, - uniqueID = player:UniqueID(), - networked = networked, - removeDelay = removeDelay - }; - - if (entity.SetPlayer) then - entity:SetPlayer(player); - end; - - if (networked) then - entity:SetNetworkedEntity("Owner", player); - end; - - entity:SetOwnerKey(player:GetCharacterKey()); - entity:SetNetworkedBool("Owned", true); - - if (tonumber(entity.cwPropertyTab.key)) then - entity:SetNetworkedInt("Key", entity.cwPropertyTab.key); - end; - - self.property[entity:EntIndex()] = entity; - Clockwork.plugin:Call("PlayerPropertyGiven", player, entity, networked, removeDelay); -end; - --- A function to give property to an offline player. -function Clockwork.player:GivePropertyOffline(key, uniqueID, entity, networked, removeDelay) - Clockwork.entity:ClearProperty(entity); - - if (key and uniqueID) then - local propertyUniqueID = Clockwork.entity:QueryProperty(entity, "uniqueID"); - local owner = player.GetByUniqueID(uniqueID); - - if (IsValid(owner) and owner:GetCharacterKey() == key) then - self:GiveProperty(owner, entity, networked, removeDelay); - return; - else - owner = nil; - end; - - if (propertyUniqueID) then - Clockwork.kernel:DestroyTimer("RemoveDelay"..entity:EntIndex().." "..cwPropertyTabUniqueID); - end; - - entity.cwPropertyTab = { - key = key, - owner = owner, - owned = true, - uniqueID = uniqueID, - networked = networked, - removeDelay = removeDelay - }; - - if (IsValid(entity.cwPropertyTab.owner)) then - if (entity.SetPlayer) then - entity:SetPlayer(entity.cwPropertyTab.owner); - end; - - if (networked) then - entity:SetNetworkedEntity("Owner", entity.cwPropertyTab.owner); - end; - end; - - entity:SetNetworkedBool("Owned", true); - entity:SetNetworkedInt("Key", key); - entity:SetOwnerKey(key); - - self.property[entity:EntIndex()] = entity; - Clockwork.plugin:Call("PlayerPropertyGivenOffline", key, uniqueID, entity, networked, removeDelay); - end; -end; - --- A function to take property from an offline player. -function Clockwork.player:TakePropertyOffline(key, uniqueID, entity, bAnyCharacter) - if (key and uniqueID) then - local owner = player.GetByUniqueID(uniqueID); - - if (IsValid(owner) and owner:GetCharacterKey() == key) then - self:TakeProperty(owner, entity); - return; - end; - - if (Clockwork.entity:QueryProperty(entity, "uniqueID") == uniqueID - and Clockwork.entity:QueryProperty(entity, "key") == key) then - entity.cwPropertyTab = nil; - entity:SetNetworkedEntity("Owner", NULL); - entity:SetNetworkedBool("Owned", false); - entity:SetNetworkedInt("Key", 0); - entity:SetOwnerKey(nil); - - if (entity.SetPlayer) then - entity:SetVar("Founder", nil); - entity:SetVar("FounderIndex", nil); - entity:SetNetworkedString("FounderName", ""); - end; - - self.property[entity:EntIndex()] = nil; - Clockwork.plugin:Call("PlayerPropertyTakenOffline", key, uniqueID, entity); - end; - end; -end; - --- A function to take property from a player. -function Clockwork.player:TakeProperty(player, entity) - if (Clockwork.entity:GetOwner(entity) == player) then - entity.cwPropertyTab = nil; - - entity:SetNetworkedEntity("Owner", NULL); - entity:SetNetworkedBool("Owned", false); - entity:SetNetworkedInt("Key", 0); - entity:SetOwnerKey(nil); - - if (entity.SetPlayer) then - entity:SetVar("Founder", nil); - entity:SetVar("FounderIndex", nil); - entity:SetNetworkedString("FounderName", ""); - end; - - self.property[entity:EntIndex()] = nil; - Clockwork.plugin:Call("PlayerPropertyTaken", player, entity); - end; -end; - --- A function to set a player to their default skin. -function Clockwork.player:SetDefaultSkin(player) - player:SetSkin(self:GetDefaultSkin(player)); -end; - --- A function to get a player's default skin. -function Clockwork.player:GetDefaultSkin(player) - return Clockwork.plugin:Call("GetPlayerDefaultSkin", player); -end; - --- A function to set a player to their default model. -function Clockwork.player:SetDefaultModel(player) - player:SetModel(self:GetDefaultModel(player)); -end; - --- A function to get a player's default model. -function Clockwork.player:GetDefaultModel(player) - return Clockwork.plugin:Call("GetPlayerDefaultModel", player); -end; - --- A function to get whether a player is drunk. -function Clockwork.player:GetDrunk(player) - if (player.cwDrunkTab) then return #player.cwDrunkTab; end; -end; - --- A function to set whether a player is drunk. -function Clockwork.player:SetDrunk(player, expire) - local curTime = CurTime(); - - if (expire == false) then - player.cwDrunkTab = nil; - elseif (!player.cwDrunkTab) then - player.cwDrunkTab = {curTime + expire}; - else - player.cwDrunkTab[#player.cwDrunkTab + 1] = curTime + expire; - end; - - player:SetSharedVar("IsDrunk", self:GetDrunk(player) or 0); -end; - --- A function to strip a player's default ammo. -function Clockwork.player:StripDefaultAmmo(player, weapon, itemTable) - if (!itemTable) then - itemTable = Clockwork.item:GetByWeapon(weapon); - end; - - if (itemTable) then - local secondaryDefaultAmmo = itemTable("secondaryDefaultAmmo"); - local primaryDefaultAmmo = itemTable("primaryDefaultAmmo"); - - if (primaryDefaultAmmo) then - local ammoClass = weapon:GetPrimaryAmmoType(); - - if (weapon:Clip1() != -1) then - weapon:SetClip1(0); - end; - - if (type(primaryDefaultAmmo) == "number") then - player:SetAmmo( - math.max(player:GetAmmoCount(ammoClass) - primaryDefaultAmmo, 0), ammoClass - ); - end; - end; - - if (secondaryDefaultAmmo) then - local ammoClass = weapon:GetSecondaryAmmoType(); - - if (weapon:Clip2() != -1) then - weapon:SetClip2(0); - end; - - if (type(secondaryDefaultAmmo) == "number") then - player:SetAmmo( - math.max(player:GetAmmoCount(ammoClass) - secondaryDefaultAmmo, 0), ammoClass - ); - end; - end; - end; -end; - --- A function to check if a player is whitelisted for a faction. -function Clockwork.player:IsWhitelisted(player, faction) - return table.HasValue(player:GetData("Whitelisted"), faction); -end; - --- A function to set whether a player is whitelisted for a faction. -function Clockwork.player:SetWhitelisted(player, faction, isWhitelisted) - local whitelisted = player:GetData("Whitelisted"); - - if (isWhitelisted) then - if (!self:IsWhitelisted(player, faction)) then - whitelisted[table.Count(whitelisted) + 1] = faction; - end; - else - for k, v in pairs(whitelisted) do - if (v == faction) then - whitelisted[k] = nil; - end; - end; - end; - - Clockwork.datastream:Start( - player, "SetWhitelisted", {faction, isWhitelisted} - ); -end; - --- A function to create a Condition timer. -function Clockwork.player:ConditionTimer(player, delay, Condition, Callback) - local realDelay = CurTime() + delay; - local uniqueID = player:UniqueID(); - - if (player.cwConditionTimer) then - player.cwConditionTimer.Callback(false); - player.cwConditionTimer = nil; - end; - - player.cwConditionTimer = { - delay = realDelay, - Callback = Callback, - Condition = Condition - }; - - Clockwork.kernel:CreateTimer("CondTimer"..uniqueID, 0, 0, function() - if (!IsValid(player)) then - Clockwork.kernel:DestroyTimer("CondTimer"..uniqueID); - Callback(false); - return; - end; - - if (Condition()) then - if (CurTime() >= realDelay) then - Callback(true); player.cwConditionTimer = nil; - Clockwork.kernel:DestroyTimer("CondTimer"..uniqueID); - end; - else - Callback(false); player.cwConditionTimer = nil; - Clockwork.kernel:DestroyTimer("CondTimer"..uniqueID); - end; - end); -end; - --- A function to create an entity Condition timer. -function Clockwork.player:EntityConditionTimer(player, target, entity, delay, distance, Condition, Callback) - local realEntity = entity or target; - local realDelay = CurTime() + delay; - local uniqueID = player:UniqueID(); - - if (player.cwConditionEntTimer) then - player.cwConditionEntTimer.Callback(false); - player.cwConditionEntTimer = nil; - end; - - player.cwConditionEntTimer = { - delay = realDelay, target = target, - entity = realEntity, distance = distance, - Callback = Callback, Condition = Condition - }; - - Clockwork.kernel:CreateTimer("EntityCondTimer"..uniqueID, 0, 0, function() - if (!IsValid(player)) then - Clockwork.kernel:DestroyTimer("EntityCondTimer"..uniqueID); - Callback(false); - return; - end; - - local traceLine = player:GetEyeTraceNoCursor(); - - if (IsValid(target) and IsValid(realEntity) and traceLine.Entity == realEntity - and traceLine.Entity:GetPos():Distance(player:GetShootPos()) <= distance - and Condition()) then - if (CurTime() >= realDelay) then - Callback(true); player.cwConditionEntTimer = nil; - Clockwork.kernel:DestroyTimer("EntityCondTimer"..uniqueID); - end; - else - Callback(false); player.cwConditionEntTimer = nil; - Clockwork.kernel:DestroyTimer("EntityCondTimer"..uniqueID); - end; - end); -end; - --- A function to get a player's spawn ammo. -function Clockwork.player:GetSpawnAmmo(player, ammo) - if (ammo) then - return player.cwSpawnAmmo[ammo]; - else - return player.cwSpawnAmmo; - end; -end; - --- A function to get a player's spawn weapon. -function Clockwork.player:GetSpawnWeapon(player, weapon) - if (weapon) then - return player.cwSpawnWeps[weapon]; - else - return player.cwSpawnWeps; - end; -end; - --- A function to take spawn ammo from a player. -function Clockwork.player:TakeSpawnAmmo(player, ammo, amount) - if (player.cwSpawnAmmo[ammo]) then - if (player.cwSpawnAmmo[ammo] < amount) then - amount = player.cwSpawnAmmo[ammo]; - - player.cwSpawnAmmo[ammo] = nil; - else - player.cwSpawnAmmo[ammo] = player.cwSpawnAmmo[ammo] - amount; - end; - - player:RemoveAmmo(amount, ammo); - end; -end; - --- A function to give the player spawn ammo. -function Clockwork.player:GiveSpawnAmmo(player, ammo, amount) - if (player.cwSpawnAmmo[ammo]) then - player.cwSpawnAmmo[ammo] = player.cwSpawnAmmo[ammo] + amount; - else - player.cwSpawnAmmo[ammo] = amount; - end; - - player:GiveAmmo(amount, ammo); -end; - --- A function to take a player's spawn weapon. -function Clockwork.player:TakeSpawnWeapon(player, class) - player.cwSpawnWeps[class] = nil; - player:StripWeapon(class); -end; - --- A function to give a player a spawn weapon. -function Clockwork.player:GiveSpawnWeapon(player, class) - player.cwSpawnWeps[class] = true; - player:Give(class); -end; - --- A function to give a player an item weapon. -function Clockwork.player:GiveItemWeapon(player, itemTable) - if (Clockwork.item:IsWeapon(itemTable)) then - player:Give(itemTable("weaponClass"), itemTable); - return true; - end; -end; - --- A function to give a player a spawn item weapon. -function Clockwork.player:GiveSpawnItemWeapon(player, itemTable) - if (Clockwork.item:IsWeapon(itemTable)) then - player.cwSpawnWeps[itemTable("weaponClass")] = true; - player:Give(itemTable("weaponClass"), itemTable); - - return true; - end; -end; - --- A function to give flags to a character. -function Clockwork.player:GiveFlags(player, flags) - for i = 1, #flags do - local flag = string.utf8sub(flags, i, i); - - if (!string.find(player:GetFlags(), flag)) then - player:SetCharacterData("Flags", player:GetFlags()..flag, true); - - Clockwork.plugin:Call("PlayerFlagsGiven", player, flag); - end; - end; -end; - --- A function to give flags to a player. -function Clockwork.player:GivePlayerFlags(player, flags) - for i = 1, #flags do - local flag = string.utf8sub(flags, i, i); - - if (!string.find(player:GetPlayerFlags(), flag)) then - player:SetData("Flags", player:GetPlayerFlags()..flag, true); - - Clockwork.plugin:Call("PlayerFlagsGiven", player, flag); - end; - end; -end; - --- A function to play a sound to a player. -function Clockwork.player:PlaySound(player, sound) - Clockwork.datastream:Start(player, "PlaySound",sound); -end; - --- A function to get a player's maximum characters. -function Clockwork.player:GetMaximumCharacters(player) - local maximum = Clockwork.config:Get("additional_characters"):Get(); - - for k, v in pairs(Clockwork.faction.stored) do - if (!v.whitelist or self:IsWhitelisted(player, v.name)) then - maximum = maximum + 1; - end; - end; - - return maximum; -end; - --- A function to query a player's character. -function Clockwork.player:Query(player, key, default) - local character = player:GetCharacter(); - - if (character) then - key = Clockwork.kernel:SetCamelCase(key, true); - - if (character[key] != nil) then - return character[key]; - end; - end; - - return default; -end; - --- A function to set a player to a safe position. -function Clockwork.player:SetSafePosition(player, position, filter) - position = self:GetSafePosition(player, position, filter); - - if (position) then - player:SetMoveType(MOVETYPE_NOCLIP); - player:SetPos(position); - - if (player:IsInWorld()) then - player:SetMoveType(MOVETYPE_WALK); - else - player:Spawn(); - end; - end; -end; - --- A function to get the safest position near a position. -function Clockwork.player:GetSafePosition(player, position, filter) - local closestPosition = nil; - local distanceAmount = 8; - local directions = {}; - local yawForward = player:EyeAngles().yaw; - local angles = { - math.NormalizeAngle(yawForward - 180), - math.NormalizeAngle(yawForward - 135), - math.NormalizeAngle(yawForward + 135), - math.NormalizeAngle(yawForward + 45), - math.NormalizeAngle(yawForward + 90), - math.NormalizeAngle(yawForward - 45), - math.NormalizeAngle(yawForward - 90), - math.NormalizeAngle(yawForward) - }; - - position = position + Vector(0, 0, 32); - - if (!filter) then - filter = {player}; - elseif (type(filter) != "table") then - filter = {filter}; - end; - - if (!table.HasValue(filter, player)) then - filter[#filter + 1] = player; - end; - - for i = 1, 8 do - for k, v in pairs(angles) do - directions[#directions + 1] = {v, distanceAmount}; - end; - - distanceAmount = distanceAmount * 2; - end; - - -- A function to get a lower position. - local function GetLowerPosition(testPosition, ignoreHeight) - local trace = { - filter = filter, - endpos = testPosition - Vector(0, 0, 256), - start = testPosition - }; - - return util.TraceLine(trace).HitPos + Vector(0, 0, 32); - end; - - local trace = { - filter = filter, - endpos = position + Vector(0, 0, 256), - start = position - }; - - local safePosition = GetLowerPosition(util.TraceLine(trace).HitPos); - - if (safePosition) then - position = safePosition; - end; - - for k, v in pairs(directions) do - local angleVector = Angle(0, v[1], 0):Forward(); - local testPosition = position + (angleVector * v[2]); - - local trace = { - filter = filter, - endpos = testPosition, - start = position - }; - - local traceLine = util.TraceEntity(trace, player); - - if (traceLine.Hit) then - trace = { - filter = filter, - endpos = traceLine.HitPos - (angleVector * v[2]), - start = traceLine.HitPos - }; - - traceLine = util.TraceEntity(trace, player); - - if (!traceLine.Hit) then - position = traceLine.HitPos; - end; - end; - - if (!traceLine.Hit) then - break; - end; - end; - - for k, v in pairs(directions) do - local angleVector = Angle(0, v[1], 0):Forward(); - local testPosition = position + (angleVector * v[2]); - - local trace = { - filter = filter, - endpos = testPosition, - start = position - }; - - local traceLine = util.TraceEntity(trace, player); - - if (!traceLine.Hit) then - return traceLine.HitPos; - end; - end; - - return position; -end; - --- Called to convert a player's data to a string. -function Clockwork.player:ConvertDataString(player, data) - local bSuccess, value = pcall(Clockwork.json.Decode, Clockwork.json, data); - - if (bSuccess and value != nil) then - return value; - else - return {}; - end; -end; - --- A function to return a player's property. -function Clockwork.player:ReturnProperty(player) - local uniqueID = player:UniqueID(); - local key = player:GetCharacterKey(); - - for k, v in pairs(self:GetAllProperty()) do - if (IsValid(v)) then - if (uniqueID == Clockwork.entity:QueryProperty(v, "uniqueID")) then - if (key == Clockwork.entity:QueryProperty(v, "key")) then - self:GiveProperty(player, v, Clockwork.entity:QueryProperty(v, "networked")); - end; - end; - end; - end; - - Clockwork.plugin:Call("PlayerReturnProperty", player); -end; - --- A function to take flags from a character. -function Clockwork.player:TakeFlags(player, flags) - for i = 1, #flags do - local flag = string.utf8sub(flags, i, i); - - if (string.find(player:GetFlags(), flag)) then - player:SetCharacterData("Flags", string.gsub(player:GetFlags(), flag, ""), true); - - Clockwork.plugin:Call("PlayerFlagsTaken", player, flag); - end; - end; -end; - --- A function to take flags from a player. -function Clockwork.player:TakePlayerFlags(player, flags) - for i = 1, #flags do - local flag = string.utf8sub(flags, i, i); - - if (string.find(player:GetPlayerFlags(), flag)) then - player:SetData("Flags", string.gsub(player:GetFlags(), flag, ""), true); - - Clockwork.plugin:Call("PlayerFlagsTaken", player, flag); - end; - end; -end; - --- A function to set whether a player's menu is open. -function Clockwork.player:SetMenuOpen(player, isOpen) - Clockwork.datastream:Start(player, "MenuOpen", isOpen); -end; - --- A function to set whether a player has intialized. -function Clockwork.player:SetInitialized(player, initialized) - player:SetSharedVar("Initialized", initialized); -end; - --- A function to check if a player has any flags. -function Clockwork.player:HasAnyFlags(player, flags, bByDefault) - if (player:GetCharacter()) then - local playerFlags = player:GetFlags(); - - if (Clockwork.class:HasAnyFlags(player:Team(), flags) and !bByDefault) then - return true; - end; - - for i = 1, #flags do - local flag = string.utf8sub(flags, i, i); - local bSuccess = true; - - if (!bByDefault) then - local hasFlag = Clockwork.plugin:Call("PlayerDoesHaveFlag", player, flag); - - if (hasFlag != false) then - if (hasFlag) then - return true; - end; - else - bSuccess = nil; - end; - end; - - if (bSuccess) then - if (flag == "s") then - if (player:IsSuperAdmin()) then - return true; - end; - elseif (flag == "a") then - if (player:IsAdmin()) then - return true; - end; - elseif (flag == "o") then - if (player:IsSuperAdmin() or player:IsAdmin()) then - return true; - elseif (player:IsUserGroup("operator")) then - return true; - end; - elseif (string.find(playerFlags, flag)) then - return true; - end; - end; - end; - end; -end; - --- A function to check if a player has flags. -function Clockwork.player:HasFlags(player, flags, bByDefault) - if (player:GetCharacter()) then - local playerFlags = player:GetFlags(); - - if (Clockwork.class:HasFlags(player:Team(), flags) and !bByDefault) then - return true; - end; - - for i = 1, #flags do - local flag = string.utf8sub(flags, i, i); - local bSuccess; - - if (!bByDefault) then - local hasFlag = Clockwork.plugin:Call("PlayerDoesHaveFlag", player, flag); - - if (hasFlag != false) then - if (hasFlag) then - bSuccess = true; - end; - else - return; - end; - end; - - if (!bSuccess) then - if (flag == "s") then - if (!player:IsSuperAdmin()) then - return; - end; - elseif (flag == "a") then - if (!player:IsAdmin()) then - return; - end; - elseif (flag == "o") then - if (!player:IsSuperAdmin() and !player:IsAdmin()) then - if (!player:IsUserGroup("operator")) then - return; - end; - end; - elseif (!string.find(playerFlags, flag)) then - return; - end; - end; - end; - - return true; - end; -end; - --- A function to use a player's death code. -function Clockwork.player:UseDeathCode(player, commandTable, arguments) - Clockwork.plugin:Call("PlayerDeathCodeUsed", player, commandTable, arguments); - - self:TakeDeathCode(player); -end; - --- A function to get whether a player has a death code. -function Clockwork.player:GetDeathCode(player, authenticated) - if (player.cwDeathCodeIdx and (!authenticated or player.cwDeathCodeAuth)) then - return player.cwDeathCodeIdx; - end; -end; - --- A function to take a player's death code. -function Clockwork.player:TakeDeathCode(player) - player.cwDeathCodeAuth = nil; - player.cwDeathCodeIdx = nil; -end; - --- A function to give a player their death code. -function Clockwork.player:GiveDeathCode(player) - player.cwDeathCodeIdx = math.random(0, 99999); - player.cwDeathCodeAuth = nil; - - Clockwork.datastream:Start(player, "ChatBoxDeathCode", player.cwDeathCodeIdx); -end; - --- A function to take a door from a player. -function Clockwork.player:TakeDoor(player, door, bForce, bThisDoorOnly, bChildrenOnly) - local doorCost = Clockwork.config:Get("door_cost"):Get(); - - if (!bThisDoorOnly) then - local doorParent = Clockwork.entity:GetDoorParent(door); - - if (!doorParent or bChildrenOnly) then - for k, v in pairs(Clockwork.entity:GetDoorChildren(door)) do - if (IsValid(v)) then - self:TakeDoor(player, v, true, true); - end; - end; - else - return self:TakeDoor(player, doorParent, bForce); - end; - end; - - if (Clockwork.plugin:Call("PlayerCanUnlockEntity", player, door)) then - door:Fire("Unlock", "", 0); - door:EmitSound("doors/door_latch3.wav"); - end; - - Clockwork.entity:SetDoorText(door, false); - self:TakeProperty(player, door); - - Clockwork.plugin:Call("PlayerDoorTaken", player, door) - - if (door:GetClass() == "prop_dynamic") then - if (!door:IsMapEntity()) then - door:Remove(); - end; - end; - - if (!force and doorCost > 0) then - self:GiveCash(player, doorCost / 2, "selling a door"); - end; -end; - --- A function to make a player say text as a radio broadcast. -function Clockwork.player:SayRadio(player, text, check, noEavesdrop) - local eavesdroppers = {}; - local listeners = {}; - local canRadio = true; - local info = {listeners = {}, noEavesdrop = noEavesdrop, text = text}; - - Clockwork.plugin:Call("PlayerAdjustRadioInfo", player, info); - - for k, v in pairs(info.listeners) do - if (type(k) == "Player") then - listeners[k] = k; - elseif (type(v) == "Player") then - listeners[v] = v; - end; - end; - - if (!info.noEavesdrop) then - for k, v in pairs(cwPlayer.GetAll()) do - if (v:HasInitialized() and !listeners[v]) then - if (v:GetShootPos():Distance(player:GetShootPos()) <= Clockwork.config:Get("talk_radius"):Get()) then - eavesdroppers[v] = v; - end; - end; - end; - end; - - if (check) then - canRadio = Clockwork.plugin:Call("PlayerCanRadio", player, info.text, listeners, eavesdroppers); - end; - - if (canRadio) then - info = Clockwork.chatBox:Add(listeners, player, "radio", info.text); - - if (info and IsValid(info.speaker)) then - Clockwork.chatBox:Add(eavesdroppers, info.speaker, "radio_eavesdrop", info.text); - - Clockwork.plugin:Call("PlayerRadioUsed", player, info.text, listeners, eavesdroppers); - end; - end; -end; - --- A function to get a player's faction table. -function Clockwork.player:GetFactionTable(player) - return Clockwork.faction.stored[player:GetFaction()]; -end; - --- A function to give a door to a player. -function Clockwork.player:GiveDoor(player, door, name, unsellable, override) - if (Clockwork.entity:IsDoor(door)) then - local doorParent = Clockwork.entity:GetDoorParent(door); - - if (doorParent and !override) then - self:GiveDoor(player, doorParent, name, unsellable); - else - for k, v in pairs(Clockwork.entity:GetDoorChildren(door)) do - if (IsValid(v)) then - self:GiveDoor(player, v, name, unsellable, true); - end; - end; - - door.unsellable = unsellable; - door.accessList = {}; - - Clockwork.entity:SetDoorText(door, name or "A purchased door."); - self:GiveProperty(player, door, true); - - Clockwork.plugin:Call("PlayerDoorGiven", player, door) - - if (Clockwork.plugin:Call("PlayerCanUnlockEntity", player, door)) then - door:EmitSound("doors/door_latch3.wav"); - door:Fire("Unlock", "", 0); - end; - end; - end; -end; - --- A function to get a player's real trace. -function Clockwork.player:GetRealTrace(player, useFilterTrace) - local eyePos = player:EyePos(); - local trace = player:GetEyeTraceNoCursor(); - - local newTrace = util.TraceLine({ - endpos = eyePos + (player:GetAimVector() * 4096), - filter = player, - start = eyePos, - mask = CONTENTS_SOLID + CONTENTS_MOVEABLE + CONTENTS_OPAQUE + CONTENTS_DEBRIS + CONTENTS_HITBOX + CONTENTS_MONSTER - }); - - if ((IsValid(newTrace.Entity) and (!IsValid(trace.Entity) - or trace.Entity:IsVehicle()) and !newTrace.HitWorld) or useFilterTrace) then - trace = newTrace; - end; - - return trace; -end; - --- A function to check if a player recognises another player. -function Clockwork.player:DoesRecognise(player, target, status, isAccurate) - if (!status) then - return self:DoesRecognise(player, target, RECOGNISE_PARTIAL); - elseif (Clockwork.config:Get("recognise_system"):Get()) then - local recognisedNames = player:GetRecognisedNames(); - local realValue = false; - local key = target:GetCharacterKey(); - - if (recognisedNames and recognisedNames[key]) then - if (isAccurate) then - realValue = (recognisedNames[key] == status); - else - realValue = (recognisedNames[key] >= status); - end; - end; - - return Clockwork.plugin:Call("PlayerDoesRecognisePlayer", player, target, status, isAccurate, realValue); - else - return true; - end; -end; - --- A function to send a player a creation fault. -function Clockwork.player:SetCreateFault(player, fault) - if (!fault) then - fault = "There has been an unknown error, please contact the administrator!"; - end; - - Clockwork.datastream:Start(player, "CharacterFinish", {bSuccess = false, fault = fault}); -end; - --- A function to force a player to delete a character. -function Clockwork.player:ForceDeleteCharacter(player, characterID) - local charactersTable = Clockwork.config:Get("mysql_characters_table"):Get(); - local schemaFolder = Clockwork.kernel:GetSchemaFolder(); - local character = player.cwCharacterList[characterID]; - - if (character) then - local queryObj = Clockwork.database:Delete(charactersTable); - queryObj:AddWhere("_Schema = ?", schemaFolder); - queryObj:AddWhere("_SteamID = ?", player:SteamID()); - queryObj:AddWhere("_CharacterID = ?", characterID); - queryObj:Push(); - - if (!Clockwork.plugin:Call("PlayerDeleteCharacter", player, character)) then - Clockwork.kernel:PrintLog(LOGTYPE_GENERIC, player:SteamName().." has deleted the character '"..character.name.."'."); - end; - - player.cwCharacterList[characterID] = nil; - - Clockwork.datastream:Start(player, "CharacterRemove", characterID); - end; -end; - --- A function to delete a player's character. -function Clockwork.player:DeleteCharacter(player, characterID) - local character = player.cwCharacterList[characterID]; - - if (character) then - if (player:GetCharacter() != character) then - local fault = Clockwork.plugin:Call("PlayerCanDeleteCharacter", player, character); - - if (fault == nil or fault == true) then - self:ForceDeleteCharacter(player, characterID); - - return true; - elseif (type(fault) != "string") then - return false, "You cannot delete this character!"; - else - return false, fault; - end; - else - return false, "You cannot delete the character you are using!"; - end; - else - return false, "This character does not exist!"; - end; -end; - --- A function to use a player's character. -function Clockwork.player:UseCharacter(player, characterID) - local isCharacterMenuReset = player:IsCharacterMenuReset(); - local currentCharacter = player:GetCharacter(); - local character = player.cwCharacterList[characterID]; - - if (!character) then - return false, "This character does not exist!"; - end; - - if (currentCharacter != character or isCharacterMenuReset) then - local factionTable = Clockwork.faction:FindByID(character.faction); - local fault = Clockwork.plugin:Call("PlayerCanUseCharacter", player, character); - - if (fault == nil or fault == true) then - local players = #Clockwork.faction:GetPlayers(character.faction); - local limit = Clockwork.faction:GetLimit(factionTable.name); - - if (isCharacterMenuReset and character.faction == currentCharacter.faction) then - players = players - 1; - end; - - if (Clockwork.plugin:Call("PlayerCanBypassFactionLimit", player, character)) then - limit = nil; - end; - - if (limit and players == limit) then - return false, "The "..character.faction.." faction is full ("..limit.."/"..limit..")!"; - else - if (currentCharacter) then - local fault = Clockwork.plugin:Call("PlayerCanSwitchCharacter", player, character); - - if (fault != nil and fault != true) then - return false, fault or "You cannot switch to this character!"; - end; - end; - - Clockwork.kernel:PrintLog(LOGTYPE_GENERIC, player:SteamName().." has loaded the character '"..character.name.."'."); - - if (isCharacterMenuReset) then - player.cwCharMenuReset = false; - player:Spawn(); - else - self:LoadCharacter(player, characterID); - end; - - return true; - end; - else - return false, fault or "You cannot use this character!"; - end; - else - return false, "You are already using this character!"; - end; -end; - --- A function to get a player's character. -function Clockwork.player:GetCharacter(player) - return player.cwCharacter; -end; - --- A function to get a player's unrecognised name. -function Clockwork.player:GetUnrecognisedName(player, bFormatted) - local unrecognisedPhysDesc = self:GetPhysDesc(player); - local unrecognisedName = Clockwork.config:Get("unrecognised_name"):Get(); - local usedPhysDesc = false; - - if (unrecognisedPhysDesc != "") then - unrecognisedName = unrecognisedPhysDesc; - usedPhysDesc = true; - end; - - if (bFormatted) then - if (string.utf8len(unrecognisedName) > 24) then - unrecognisedName = string.utf8sub(unrecognisedName, 1, 21).."..."; - end; - - unrecognisedName = "["..unrecognisedName.."]"; - end; - - return unrecognisedName, usedPhysDesc; -end; - --- A function to format text based on a relationship. -function Clockwork.player:FormatRecognisedText(player, text, ...) - local arguments = {...}; - - for i = 1, #arguments do - if (string.find(text, "%%s") and IsValid(arguments[i])) then - local unrecognisedName = "["..self:GetUnrecognisedName(arguments[i]).."]"; - - if (self:DoesRecognise(player, arguments[i])) then - unrecognisedName = arguments[i]:Name(); - end; - - text = string.gsub(text, "%%s", unrecognisedName, 1); - end; - end; - - return text; -end; - --- A function to restore a recognised name. -function Clockwork.player:RestoreRecognisedName(player, target) - local recognisedNames = player:GetRecognisedNames(); - local key = target:GetCharacterKey(); - - if (recognisedNames[key]) then - if (Clockwork.plugin:Call("PlayerCanRestoreRecognisedName", player, target)) then - self:SetRecognises(player, target, recognisedNames[key], true); - else - recognisedNames[key] = nil; - end; - end; -end; - --- A function to restore a player's recognised names. -function Clockwork.player:RestoreRecognisedNames(player) - Clockwork.datastream:Start(player, "ClearRecognisedNames", true); - - if (Clockwork.config:Get("save_recognised_names"):Get()) then - for k, v in pairs(cwPlayer.GetAll()) do - if (v:HasInitialized()) then - self:RestoreRecognisedName(player, v); - self:RestoreRecognisedName(v, player); - end; - end; - end; -end; - --- A function to set whether a player recognises a player. -function Clockwork.player:SetRecognises(player, target, status, bForce) - local recognisedNames = player:GetRecognisedNames(); - local name = target:Name(); - local key = target:GetCharacterKey(); - - --[[ I have no idea why this would happen. --]] - if (key == nil) then return end; - - if (status == RECOGNISE_SAVE) then - if (Clockwork.config:Get("save_recognised_names"):Get()) then - if (!Clockwork.plugin:Call("PlayerCanSaveRecognisedName", player, target)) then - status = RECOGNISE_TOTAL; - end; - else - status = RECOGNISE_TOTAL; - end; - end; - - if (!status or bForce or !self:DoesRecognise(player, target, status)) then - recognisedNames[key] = status or nil; - - Clockwork.datastream:Start(player, "RecognisedName", { - key = key, status = (status or 0) - }); - end; -end; - --- A function to get a player's physical description. -function Clockwork.player:GetPhysDesc(player) - local physDesc = player:GetSharedVar("PhysDesc"); - local team = player:Team(); - - if (physDesc == "") then - physDesc = Clockwork.class:Query(team, "defaultPhysDesc", ""); - end; - - if (physDesc == "") then - physDesc = Clockwork.config:Get("default_physdesc"):Get(); - end; - - if (!physDesc or physDesc == "") then - physDesc = "This character has no physical description set."; - else - physDesc = Clockwork.kernel:ModifyPhysDesc(physDesc); - end; - - local override = Clockwork.plugin:Call("GetPlayerPhysDescOverride", player, physDesc); - - if (override) then - physDesc = override; - end; - - return physDesc; -end; - --- A function to clear a player's recognised names list. -function Clockwork.player:ClearRecognisedNames(player, status, isAccurate) - if (!status) then - local character = player:GetCharacter(); - - if (character) then - character.recognisedNames = {}; - - Clockwork.datastream:Start(player, "ClearRecognisedNames", true); - end; - else - for k, v in pairs(cwPlayer.GetAll()) do - if (v:HasInitialized()) then - if (self:DoesRecognise(player, v, status, isAccurate)) then - self:SetRecognises(player, v, false); - end; - end; - end; - end; - - Clockwork.plugin:Call("PlayerRecognisedNamesCleared", player, status, isAccurate); -end; - --- A function to clear a player's name from being recognised. -function Clockwork.player:ClearName(player, status, isAccurate) - for k, v in pairs(cwPlayer.GetAll()) do - if (v:HasInitialized()) then - if (!status or self:DoesRecognise(v, player, status, isAccurate)) then - self:SetRecognises(v, player, false); - end; - end; - end; - - Clockwork.plugin:Call("PlayerNameCleared", player, status, isAccurate); -end; - --- A function to holsters all of a player's weapons. -function Clockwork.player:HolsterAll(player) - for k, v in pairs(player:GetWeapons()) do - local class = v:GetClass(); - local itemTable = Clockwork.item:GetByWeapon(v); - - if (itemTable and Clockwork.plugin:Call("PlayerCanHolsterWeapon", player, itemTable, v, true, true)) then - Clockwork.plugin:Call("PlayerHolsterWeapon", player, itemTable, v, true); - player:StripWeapon(class); - player:GiveItem(itemTable, true); - end; - end; - - player:SelectWeapon("cw_hands"); -end; - --- A function to set a shared variable for a player. -function Clockwork.player:SetSharedVar(player, key, value, sharedTable) - if (IsValid(player)) then - if (!sharedTable) then - local sharedVars = Clockwork.kernel:GetSharedVars():Player(); - - if (!sharedVars) then - MsgC(Color(255, 100, 0, 255), "[Clockwork:PlayerSharedVars] Couldn't get the sharedVars table.\n"); - return; - elseif (not sharedVars[key]) then - MsgC(Color(255, 100, 0, 255), "[Clockwork:PlayerSharedVars] Couldn't find key '"..key.."' in sharedVars table. Is it registered?\n"); - return; - end; - - local sharedVarData = sharedVars[key]; - - if (sharedVarData.bPlayerOnly) then - local realValue = value; - - if (value == nil) then - realValue = Clockwork.kernel:GetDefaultNetworkedValue(sharedVarData.class); - end; - - if (player.cwSharedVars[key] != realValue) then - player.cwSharedVars[key] = realValue; - - Clockwork.datastream:Start(player, "SharedVar", {key = key, value = realValue}); - end; - else - local class = Clockwork.kernel:ConvertNetworkedClass(sharedVarData.class); - - if (class) then - if (value == nil) then - value = Clockwork.kernel:GetDefaultClassValue(class); - end; - - player["SetNetworked"..class](player, key, value); - else - MsgC(Color(255, 100, 0, 255), "[Clockwork:PlayerSharedVars] Couldn't find network class for key '"..key.."'."); - end; - end; - else - Clockwork.datastream:Start(player, "SetSharedTableVar", {sharedTable = sharedTable, key = key, value = value}) - end; - end; -end; - --- A function to get a player's shared variable. -function Clockwork.player:GetSharedVar(player, key) - if (IsValid(player)) then - local sharedVars = Clockwork.kernel:GetSharedVars():Player(); - - if (!sharedVars) then - MsgC(Color(255, 100, 0, 255), "[Clockwork:PlayerSharedVars] Couldn't get the sharedVars table.\n"); - return; - elseif (not sharedVars[key]) then - MsgC(Color(255, 100, 0, 255), "[Clockwork:PlayerSharedVars] Couldn't find key '"..key.."' in sharedVars table. Is it registered?\n"); - return; - end; - - local sharedVarData = sharedVars[key]; - - if (sharedVarData.bPlayerOnly) then - if (!player.cwSharedVars[key]) then - return Clockwork.kernel:GetDefaultNetworkedValue(sharedVarData.class); - else - return player.cwSharedVars[key]; - end; - else - local class = Clockwork.kernel:ConvertNetworkedClass(sharedVarData.class); - - if (class) then - return player["GetNetworked"..class](player, key); - else - MsgC(Color(255, 100, 0, 255), "[Clockwork:PlayerSharedVars] Couldn't find network class for key '"..key.."'."); - end; - end; - end; -end; - --- A function to set whether a player's character is banned. -function Clockwork.player:SetBanned(player, banned) - player:SetCharacterData("CharBanned", banned); - player:SaveCharacter(); - player:SetSharedVar("CharBanned", banned); -end; - --- A function to set a player's name. -function Clockwork.player:SetName(player, name, saveless) - local previousName = player:Name(); - local newName = name; - - player:SetCharacterData("Name", newName, true); - player:SetSharedVar("Name", newName); - - if (!player.cwFirstSpawn) then - Clockwork.plugin:Call("PlayerNameChanged", player, previousName, newName); - end; - - if (!saveless) then - player:SaveCharacter(); - end; -end; - --- A function to get a player's generator count. -function Clockwork.player:GetGeneratorCount(player) - local generators = Clockwork.generator:GetAll(); - local count = 0; - - for k, v in pairs(generators) do - count = count + self:GetPropertyCount(player, k); - end; - - return count; -end; - --- A function to get a player's property entities. -function Clockwork.player:GetPropertyEntities(player, class) - local uniqueID = player:UniqueID(); - local entities = {}; - local key = player:GetCharacterKey(); - - for k, v in pairs(self:GetAllProperty()) do - if (uniqueID == Clockwork.entity:QueryProperty(v, "uniqueID")) then - if (key == Clockwork.entity:QueryProperty(v, "key")) then - if (!class or v:GetClass() == class) then - entities[#entities + 1] = v; - end; - end; - end; - end; - - return entities; -end; - --- A function to get a player's property count. -function Clockwork.player:GetPropertyCount(player, class) - local uniqueID = player:UniqueID(); - local count = 0; - local key = player:GetCharacterKey(); - - for k, v in pairs(self:GetAllProperty()) do - if (uniqueID == Clockwork.entity:QueryProperty(v, "uniqueID")) then - if (key == Clockwork.entity:QueryProperty(v, "key")) then - if (!class or v:GetClass() == class) then - count = count + 1; - end; - end; - end; - end; - - return count; -end; - --- A function to get a player's door count. -function Clockwork.player:GetDoorCount(player) - local uniqueID = player:UniqueID(); - local count = 0; - local key = player:GetCharacterKey(); - - for k, v in pairs(self:GetAllProperty()) do - if (Clockwork.entity:IsDoor(v) and !Clockwork.entity:GetDoorParent(v)) then - if (uniqueID == Clockwork.entity:QueryProperty(v, "uniqueID")) then - if (player:GetCharacterKey() == Clockwork.entity:QueryProperty(v, "key")) then - count = count + 1; - end; - end; - end; - end; - - return count; -end; - --- A function to take a player's door access. -function Clockwork.player:TakeDoorAccess(player, door) - if (door.accessList) then - door.accessList[player:GetCharacterKey()] = false; - end; -end; - --- A function to give a player door access. -function Clockwork.player:GiveDoorAccess(player, door, access) - local key = player:GetCharacterKey(); - - if (!door.accessList) then - door.accessList = { - [key] = access - }; - else - door.accessList[key] = access; - end; -end; - --- A function to check if a player has door access. -function Clockwork.player:HasDoorAccess(player, door, access, isAccurate) - if (!access) then - return self:HasDoorAccess(player, door, DOOR_ACCESS_BASIC, isAccurate); - else - local doorParent = Clockwork.entity:GetDoorParent(door); - local key = player:GetCharacterKey(); - - if (doorParent and Clockwork.entity:DoorHasSharedAccess(doorParent) - and (!door.accessList or door.accessList[key] == nil)) then - return Clockwork.plugin:Call("PlayerDoesHaveDoorAccess", player, doorParent, access, isAccurate); - else - return Clockwork.plugin:Call("PlayerDoesHaveDoorAccess", player, door, access, isAccurate); - end; - end; -end; - --- A function to check if a player can afford an amount. -function Clockwork.player:CanAfford(player, amount) - if (Clockwork.config:Get("cash_enabled"):Get()) then - return (player:GetCash() >= amount); - else - return true; - end; -end; - --- A function to give a player an amount of cash. -function Clockwork.player:GiveCash(player, amount, reason, bNoMsg) - if (Clockwork.config:Get("cash_enabled"):Get()) then - local positiveHintColor = "positive_hint"; - local negativeHintColor = "negative_hint"; - local roundedAmount = math.Round(amount); - local cash = math.Round(math.max(player:GetCash() + roundedAmount, 0)); - - player:SetCharacterData("Cash", cash, true); - player:SetSharedVar("Cash", cash); - - if (roundedAmount < 0) then - roundedAmount = math.abs(roundedAmount); - - if (!bNoMsg) then - if (reason) then - Clockwork.hint:Send( - player, "Your character has lost the sum of "..Clockwork.kernel:FormatCash(roundedAmount).." ("..reason..").", 4, negativeHintColor - ); - else - Clockwork.hint:Send( - player, "Your character has lost the sum of "..Clockwork.kernel:FormatCash(roundedAmount)..".", 4, negativeHintColor - ); - end; - end; - elseif (roundedAmount > 0) then - if (!bNoMsg) then - if (reason) then - Clockwork.hint:Send( - player, "Your character has gained the sum of "..Clockwork.kernel:FormatCash(roundedAmount).." ("..reason..").", 4, positiveHintColor - ); - else - Clockwork.hint:Send( - player, "Your character has gained the sum of "..Clockwork.kernel:FormatCash(roundedAmount)..".", 4, positiveHintColor - ); - end; - end; - end; - - Clockwork.plugin:Call("PlayerCashUpdated", player, roundedAmount, reason, bNoMsg); - end; -end; - -Clockwork.player:AddToMetaTable("Player", "GiveCash"); - --- A function to show cinematic text to a player. -function Clockwork.player:CinematicText(player, text, color, barLength, hangTime) - Clockwork.datastream:Start(player, "CinematicText", { - text = text, - color = color, - barLength = barLength, - hangTime = hangTime - }); -end; - --- A function to show cinematic text to each player. -function Clockwork.player:CinematicTextAll(text, color, hangTime) - for k, v in pairs(cwPlayer.GetAll()) do - if (v:HasInitialized()) then - self:CinematicText(v, text, color, hangTime); - end; - end; -end; - --- A function to find a player by an identifier. -function Clockwork.player:FindByID(identifier) - for k, v in pairs(player.GetAll()) do - if (v:HasInitialized() and (v:SteamID() == identifier or v:UniqueID() == identifier - or string.find(string.lower(v:Name()), string.lower(identifier), 1, true))) then - return v; - end; - end; -end; - --- A function to get if a player is protected. -function Clockwork.player:IsProtected(identifier) - local steamID = nil; - local ownerSteamID = Clockwork.config:Get("owner_steamid"):Get(); - local bSuccess, value = pcall(IsValid, identifier); - - if (!bSuccess or value == false) then - local playerObj = self:FindByID(identifier); - - if (IsValid(playerObj)) then - steamID = playerObj:SteamID(); - end; - else - steamID = identifier:SteamID(); - end; - - if (string.find(ownerSteamID, ",")) then - ownerSteamID = string.gsub(ownerSteamID, " ", ""); - ownerSteamID = string.Split(ownerSteamID, ","); - - for k, v in pairs(ownerSteamID) do - if (steamID and steamID == v) then - return true; - end; - end; - else - if (steamID and steamID == ownerSteamID) then - return true; - end; - end; - - return false; -end; - --- A function to notify each player in a radius. -function Clockwork.player:NotifyInRadius(text, class, position, radius) - local listeners = {}; - - for k, v in pairs(cwPlayer.GetAll()) do - if (v:HasInitialized()) then - if (position:Distance(v:GetPos()) <= radius) then - listeners[#listeners + 1] = v; - end; - end; - end; - - self:Notify(listeners, text, class); -end; - --- A function to notify each player. -function Clockwork.player:NotifyAll(text, icon) - self:Notify(nil, text, true, icon); -end; - ---[[ - @codebase Server - @details A function to notify admins by rank. - @param String The rank and up that will be notified. - @param String The text that will be sent to each admin. - @param String The name of the icon that will be used in the message, can be nil. ---]] -function Clockwork.player:NotifyAdmins(adminLevel, text, icon) - for k, v in pairs(player.GetAll()) do - if (adminLevel == "operator" or adminLevel == "o") then - if (v:IsAdmin()) then - self:Notify(v, text, true, icon); - end; - elseif (adminLevel == "admin" or adminLevel == "a") then - if (v:IsAdmin() and !v:IsUserGroup("operator")) then - self:Notify(v, text, true, icon); - end; - elseif (adminLevel == "superadmin" or adminLevel == "s") then - if (v:IsSuperAdmin()) then - self:Notify(v, text, true, icon); - end; - end; - end; -end; - --- A function to notify a player. -function Clockwork.player:Notify(player, text, class, icon) - if (type(player) == "table") then - for k, v in pairs(player) do - self:Notify(v, text, class); - end; - elseif (class == true) then - if (icon) then - local data = {icon = icon}; - Clockwork.chatBox:Add(player, nil, "notify_all", text, data); - else - Clockwork.chatBox:Add(player, nil, "notify_all", text); - end; - elseif (!class) then - if (icon) then - local data = {icon = icon}; - Clockwork.chatBox:Add(player, nil, "notify", text, data); - else - Clockwork.chatBox:Add(player, nil, "notify", text); - end; - else - Clockwork.datastream:Start(player, "Notification", {text = text, class = class}); - end; -end; - -Clockwork.player:AddToMetaTable("Player", "Notify"); - --- A function to set a player's weapons list from a table. -function Clockwork.player:SetWeapons(player, weapons, bForceReturn) - for k, v in pairs(weapons) do - if (!player:HasWeapon(v.weaponData["class"])) then - if (!v.teamIndex or player:Team() == v.teamIndex) then - player:Give( - v.weaponData["class"], v.weaponData["itemTable"], bForceReturn - ); - end; - end; - end; -end; - --- A function to give ammo to a player from a table. -function Clockwork.player:GiveAmmo(player, ammo) - for k, v in pairs(ammo) do player:GiveAmmo(v, k); end; -end; - --- A function to set a player's ammo list from a table. -function Clockwork.player:SetAmmo(player, ammo) - for k, v in pairs(ammo) do player:SetAmmo(v, k); end; -end; - --- A function to get a player's ammo list as a table. -function Clockwork.player:GetAmmo(player, bDoStrip) - local spawnAmmo = self:GetSpawnAmmo(player); - local ammoTypes = {}; - local ammo = {}; - - for k, v in pairs(Clockwork.item:GetAll()) do - if (v.ammoClass) then - ammoTypes[v.ammoClass] = true; - end; - end; - - Clockwork.plugin:Call("AdjustAmmoTypes", ammoTypes); - - if (ammoTypes) then - for k, v in pairs(ammoTypes) do - if (v) then - ammo[k] = player:GetAmmoCount(k); - end; - end; - end; - - if (spawnAmmo) then - for k, v in pairs(spawnAmmo) do - if (ammo[k]) then - ammo[k] = math.max(ammo[k] - v, 0); - end; - end; - end; - - if (bDoStrip) then - player:RemoveAllAmmo(); - end; - - return ammo; -end; - --- A function to get a player's weapons list as a table. -function Clockwork.player:GetWeapons(player, bDoKeep) - local weapons = {}; - - for k, v in pairs(player:GetWeapons()) do - local itemTable = Clockwork.item:GetByWeapon(v); - local teamIndex = player:Team(); - local class = v:GetClass(); - - if (!self:GetSpawnWeapon(player, class)) then - teamIndex = nil; - end; - - weapons[#weapons + 1] = { - weaponData = { - itemTable = itemTable, - class = class - }, - teamIndex = teamIndex - }; - - if (!bDoKeep) then - player:StripWeapon(class); - end; - end; - - return weapons; -end; - --- A function to get the total weight of a player's equipped weapons. -function Clockwork.player:GetEquippedWeight(player) - local weight = 0; - - for k, v in pairs(player:GetWeapons()) do - local itemTable = Clockwork.item:GetByWeapon(v); - - if (itemTable) then - weight = weight + itemTable("weight"); - end; - end; - - return weight; -end; - --- A function to get the total space of a player's equipped weapons. -function Clockwork.player:GetEquippedSpace(player) - local space = 0; - - for k, v in pairs(player:GetWeapons()) do - local itemTable = Clockwork.item:GetByWeapon(v); - - if (itemTable) then - space = space + itemTable("space"); - end; - end; - - return space; -end; - --- A function to get a player's holstered weapon. -function Clockwork.player:GetHolsteredWeapon(player) - for k, v in pairs(player:GetWeapons()) do - local itemTable = Clockwork.item:GetByWeapon(v); - local class = v:GetClass(); - - if (itemTable) then - if (self:GetWeaponClass(player) != class) then - return class; - end; - end; - end; -end; - --- A function to check whether a player is ragdolled. -function Clockwork.player:IsRagdolled(player, exception, bNoEntity) - if (player:GetRagdollEntity() or bNoEntity) then - local ragdolled = player:GetSharedVar("IsRagdoll"); - - if (ragdolled == exception) then - return false; - else - return (ragdolled != RAGDOLL_NONE); - end; - end; -end; - --- A function to set a player's unragdoll time. -function Clockwork.player:SetUnragdollTime(player, delay) - player.cwRagdollPaused = nil; - - if (delay) then - self:SetAction(player, "unragdoll", delay, 2, function() - if (IsValid(player) and player:Alive()) then - self:SetRagdollState(player, RAGDOLL_NONE); - end; - end); - else - self:SetAction(player, "unragdoll", false); - end; -end; - --- A function to pause a player's unragdoll time. -function Clockwork.player:PauseUnragdollTime(player) - if (!player.cwRagdollPaused) then - local unragdollTime = self:GetUnragdollTime(player); - local curTime = CurTime(); - - if (player:IsRagdolled()) then - if (unragdollTime > 0) then - player.cwRagdollPaused = unragdollTime - curTime; - self:SetAction(player, "unragdoll", false); - end; - end; - end; -end; - --- A function to start a player's unragdoll time. -function Clockwork.player:StartUnragdollTime(player) - if (player.cwRagdollPaused) then - if (player:IsRagdolled()) then - self:SetUnragdollTime(player, player.cwRagdollPaused); - - player.cwRagdollPaused = nil; - end; - end; -end; - --- A function to get a player's unragdoll time. -function Clockwork.player:GetUnragdollTime(player) - local action, actionDuration, startActionTime = self:GetAction(player); - - if (action == "unragdoll") then - return startActionTime + actionDuration; - else - return 0; - end; -end; - --- A function to get a player's ragdoll state. -function Clockwork.player:GetRagdollState(player) - return player:GetSharedVar("IsRagdoll"); -end; - --- A function to get a player's ragdoll entity. -function Clockwork.player:GetRagdollEntity(player) - if (player.cwRagdollTab) then - if (IsValid(player.cwRagdollTab.entity)) then - return player.cwRagdollTab.entity; - end; - end; -end; - --- A function to get a player's ragdoll table. -function Clockwork.player:GetRagdollTable(player) - return player.cwRagdollTab; -end; - --- A function to do a player's ragdoll decay check. -function Clockwork.player:DoRagdollDecayCheck(player, ragdoll) - local index = ragdoll:EntIndex(); - - Clockwork.kernel:CreateTimer("DecayCheck"..index, 60, 0, function() - local ragdollIsValid = IsValid(ragdoll); - local playerIsValid = IsValid(player); - - if (!playerIsValid and ragdollIsValid) then - if (!Clockwork.entity:IsDecaying(ragdoll)) then - local decayTime = Clockwork.config:Get("body_decay_time"):Get(); - - if (decayTime > 0 and Clockwork.plugin:Call("PlayerCanRagdollDecay", player, ragdoll, decayTime)) then - Clockwork.entity:Decay(ragdoll, decayTime); - end; - else - Clockwork.kernel:DestroyTimer("DecayCheck"..index); - end; - elseif (!ragdollIsValid) then - Clockwork.kernel:DestroyTimer("DecayCheck"..index); - end; - end); -end; - --- A function to set a player's ragdoll immunity. -function Clockwork.player:SetRagdollImmunity(player, delay) - if (delay) then - player:GetRagdollTable().immunity = CurTime() + delay; - else - player:GetRagdollTable().immunity = 0; - end; -end; - --- A function to set a player's ragdoll state. -function Clockwork.player:SetRagdollState(player, state, delay, decay, force, multiplier, velocityCallback) - if (state == RAGDOLL_KNOCKEDOUT or state == RAGDOLL_FALLENOVER) then - if (player:IsRagdolled()) then - if (Clockwork.plugin:Call("PlayerCanRagdoll", player, state, delay, decay, player.cwRagdollTab)) then - self:SetUnragdollTime(player, delay); - player:SetSharedVar("IsRagdoll", state); - player.cwRagdollTab.delay = delay; - player.cwRagdollTab.decay = decay; - Clockwork.plugin:Call("PlayerRagdolled", player, state, player.cwRagdollTab); - end; - elseif (Clockwork.plugin:Call("PlayerCanRagdoll", player, state, delay, decay)) then - local velocity = player:GetVelocity() + (player:GetAimVector() * 128); - local ragdoll = ents.Create("prop_ragdoll"); - - ragdoll:SetMaterial(player:GetMaterial()); - ragdoll:SetAngles(player:GetAngles()); - ragdoll:SetColor(player:GetColor()); - ragdoll:SetModel(player:GetModel()); - ragdoll:SetSkin(player:GetSkin()); - ragdoll:SetPos(player:GetPos()); - ragdoll:Spawn(); - - player.cwRagdollTab = {}; - player.cwRagdollTab.eyeAngles = player:EyeAngles(); - player.cwRagdollTab.immunity = CurTime() + Clockwork.config:Get("ragdoll_immunity_time"):Get(); - player.cwRagdollTab.moveType = MOVETYPE_WALK; - player.cwRagdollTab.entity = ragdoll; - player.cwRagdollTab.health = player:Health(); - player.cwRagdollTab.armor = player:Armor(); - player.cwRagdollTab.delay = delay; - player.cwRagdollTab.decay = decay; - - if (!player:IsOnGround()) then - player.cwRagdollTab.immunity = 0; - end; - - if (IsValid(ragdoll)) then - local headIndex = ragdoll:LookupBone("ValveBiped.Bip01_Head1"); - - ragdoll:SetCollisionGroup(COLLISION_GROUP_WEAPON); - - for i = 1, ragdoll:GetPhysicsObjectCount() do - local physicsObject = ragdoll:GetPhysicsObjectNum(i); - local boneIndex = ragdoll:TranslatePhysBoneToBone(i); - local position, angle = player:GetBonePosition(boneIndex); - - if (IsValid(physicsObject)) then - physicsObject:SetPos(position); - physicsObject:SetAngles(angle); - - if (!velocityCallback) then - if (boneIndex == headIndex) then - physicsObject:SetVelocity(velocity * 1.5); - else - physicsObject:SetVelocity(velocity); - end; - - if (force) then - if (boneIndex == headIndex) then - physicsObject:ApplyForceCenter(force * 1.5); - else - physicsObject:ApplyForceCenter(force); - end; - end; - else - velocityCallback(physicsObject, boneIndex, ragdoll, velocity, force); - end; - end; - end; - end; - - if (player:Alive()) then - if (IsValid(player:GetActiveWeapon())) then - player.cwRagdollTab.weapon = self:GetWeaponClass(player); - end; - - player.cwRagdollTab.weapons = self:GetWeapons(player, true); - - if (delay) then - self:SetUnragdollTime(player, delay); - end; - end; - - if (player:InVehicle()) then - player:ExitVehicle(); - player.cwRagdollTab.eyeAngles = Angle(0, 0, 0); - end; - - if (player:IsOnFire()) then - ragdoll:Ignite(8, 0); - end; - - player:Spectate(OBS_MODE_CHASE); - player:RunCommand("-duck"); - player:RunCommand("-voicerecord"); - player:SetMoveType(MOVETYPE_OBSERVER); - player:StripWeapons(true); - player:SpectateEntity(ragdoll); - player:CrosshairDisable(); - - if (player:FlashlightIsOn()) then - player:Flashlight(false); - end; - - player.cwRagdollPaused = nil; - - player:SetSharedVar("IsRagdoll", state); - player:SetSharedVar("Ragdoll", ragdoll); - - if (state != RAGDOLL_FALLENOVER) then - self:GiveDeathCode(player); - end; - - Clockwork.entity:SetPlayer(ragdoll, player); - self:DoRagdollDecayCheck(player, ragdoll); - - Clockwork.plugin:Call("PlayerRagdolled", player, state, player.cwRagdollTab); - end; - elseif (state == RAGDOLL_NONE or state == RAGDOLL_RESET) then - if (player:IsRagdolled(nil, true)) then - local ragdollTable = player:GetRagdollTable(); - - if (Clockwork.plugin:Call("PlayerCanUnragdoll", player, state, ragdollTable)) then - player:UnSpectate(); - player:CrosshairEnable(); - - if (state != RAGDOLL_RESET) then - self:LightSpawn(player, nil, nil, true); - end; - - if (state != RAGDOLL_RESET) then - if (IsValid(ragdollTable.entity)) then - local velocity = ragdollTable.entity:GetVelocity(); - local position = Clockwork.entity:GetPelvisPosition(ragdollTable.entity); - - if (position) then - self:SetSafePosition(player, position, ragdollTable.entity); - end; - - player:SetSkin(ragdollTable.entity:GetSkin()); - player:SetColor(ragdollTable.entity:GetColor()); - player:SetMaterial(ragdollTable.entity:GetMaterial()); - - if (!ragdollTable.model) then - player:SetModel(ragdollTable.entity:GetModel()); - else - player:SetModel(ragdollTable.model); - end; - - if (!ragdollTable.skin) then - player:SetSkin(ragdollTable.entity:GetSkin()); - else - player:SetSkin(ragdollTable.skin); - end; - - player:SetVelocity(velocity); - end; - - player:SetArmor(ragdollTable.armor); - player:SetHealth(ragdollTable.health); - player:SetMoveType(ragdollTable.moveType); - player:SetEyeAngles(ragdollTable.eyeAngles); - end; - - if (IsValid(ragdollTable.entity)) then - Clockwork.kernel:DestroyTimer("DecayCheck"..ragdollTable.entity:EntIndex()); - - if (ragdollTable.decay) then - if (Clockwork.plugin:Call("PlayerCanRagdollDecay", player, ragdollTable.entity, ragdollTable.decay)) then - Clockwork.entity:Decay(ragdollTable.entity, ragdollTable.decay); - end; - else - ragdollTable.entity:Remove(); - end; - end; - - if (state != RAGDOLL_RESET) then - self:SetWeapons(player, ragdollTable.weapons, true); - - if (ragdollTable.weapon) then - player:SelectWeapon(ragdollTable.weapon); - end; - end; - - self:SetUnragdollTime(player, false); - player:SetSharedVar("IsRagdoll", RAGDOLL_NONE); - player:SetSharedVar("Ragdoll", NULL); - Clockwork.plugin:Call("PlayerUnragdolled", player, state, ragdollTable); - - player.cwRagdollPaused = nil; - player.cwRagdollTab = {}; - end; - end; - end; -end; - --- A function to make a player drop their weapons. -function Clockwork.player:DropWeapons(player) - local ragdollEntity = player:GetRagdollEntity(); - - if (player:IsRagdolled()) then - local ragdollWeapons = player:GetRagdollWeapons(); - - for k, v in pairs(ragdollWeapons) do - local itemTable = v.weaponData["itemTable"]; - - if (itemTable and Clockwork.plugin:Call("PlayerCanDropWeapon", player, itemTable, NULL, true)) then - local info = { - itemTable = itemTable, - position = ragdollEntity:GetPos() + Vector(0, 0, math.random(1, 48)), - angles = Angle(0, 0, 0) - }; - - player:TakeItem(info.itemTable, true); - ragdollWeapons[k] = nil; - - if (Clockwork.plugin:Call("PlayerAdjustDropWeaponInfo", player, info)) then - local entity = Clockwork.entity:CreateItem(player, info.itemTable, info.position, info.angles); - - if (IsValid(entity)) then - Clockwork.plugin:Call("PlayerDropWeapon", player, info.itemTable, entity, NULL); - end; - end; - end; - end; - else - for k, v in pairs(player:GetWeapons()) do - local itemTable = Clockwork.item:GetByWeapon(v); - - if (itemTable and Clockwork.plugin:Call("PlayerCanDropWeapon", player, itemTable, v, true)) then - local info = { - itemTable = itemTable, - position = player:GetPos() + Vector(0, 0, math.random(1, 48)), - angles = Angle(0, 0, 0) - }; - - if (Clockwork.plugin:Call("PlayerAdjustDropWeaponInfo", player, info)) then - local entity = Clockwork.entity:CreateItem( - player, info.itemTable, info.position, info.angles - ); - - if (IsValid(entity)) then - Clockwork.plugin:Call("PlayerDropWeapon", player, info.itemTable, entity, v); - player:StripWeapon(v:GetClass()); - player:TakeItem(info.itemTable, true); - end; - end; - end; - end; - end; -end; - --- A function to lightly spawn a player. -function Clockwork.player:LightSpawn(player, weapons, ammo, bForceReturn) - if (player:IsRagdolled() and !bForceReturn) then - self:SetRagdollState(player, RAGDOLL_NONE); - end; - - player.cwLightSpawn = true; - - local moveType = player:GetMoveType(); - local material = player:GetMaterial(); - local position = player:GetPos(); - local angles = player:EyeAngles(); - local weapon = player:GetActiveWeapon(); - local health = player:Health(); - local armor = player:Armor(); - local model = player:GetModel(); - local color = player:GetColor(); - local skin = player:GetSkin(); - - if (ammo) then - if (type(ammo) != "table") then - ammo = self:GetAmmo(player, true); - end; - end; - - if (weapons) then - if (type(weapons) != "table") then - weapons = self:GetWeapons(player); - end; - - if (IsValid(weapon)) then - weapon = weapon:GetClass(); - end; - end; - - player.cwSpawnCallback = function(player, gamemodeHook) - if (weapons) then - Clockwork:PlayerLoadout(player); - - self:SetWeapons(player, weapons, bForceReturn); - - if (type(weapon) == "string") then - player:SelectWeapon(weapon); - end; - end; - - if (ammo) then - self:GiveAmmo(player, ammo); - end; - - player:SetPos(position); - player:SetSkin(skin); - player:SetModel(model); - player:SetColor(color); - player:SetArmor(armor); - player:SetHealth(health); - player:SetMaterial(material); - player:SetMoveType(moveType); - player:SetEyeAngles(angles); - - if (gamemodeHook) then - special = special or false; - - Clockwork.plugin:Call("PostPlayerLightSpawn", player, weapons, ammo, special); - end; - - player:ResetSequence( - player:GetSequence() - ); - end; - - player:Spawn(); -end; - --- A function to convert a table to camel case. -function Clockwork.player:ConvertToCamelCase(baseTable) - local newTable = {}; - - for k, v in pairs(baseTable) do - local key = Clockwork.kernel:SetCamelCase(string.gsub(k, "_", ""), true); - - if (key and key != "") then - newTable[key] = v; - end; - end; - - return newTable; -end; - --- A function to get a player's characters. -function Clockwork.player:GetCharacters(player, Callback) - if (!IsValid(player)) then return; end; - - local charactersTable = Clockwork.config:Get("mysql_characters_table"):Get(); - local schemaFolder = Clockwork.kernel:GetSchemaFolder(); - local queryObj = Clockwork.database:Select(charactersTable); - queryObj:AddWhere("_Schema = ?", schemaFolder); - queryObj:AddWhere("_SteamID = ?", player:SteamID()); - queryObj:SetCallback(function(result) - if (!IsValid(player)) then return; end; - - if (Clockwork.database:IsResult(result)) then - local characters = {}; - - for k, v in pairs(result) do - characters[k] = self:ConvertToCamelCase(v); - end; - - Callback(characters); - else - Callback(); - end; - end); - queryObj:Pull(); -end; - --- A function to add a character to the character screen. -function Clockwork.player:CharacterScreenAdd(player, character) - local info = { - name = character.name, - model = character.model, - banned = character.data["CharBanned"], - faction = character.faction, - characterID = character.characterID - }; - - if (character.data["PhysDesc"]) then - if (string.utf8len(character.data["PhysDesc"]) > 64) then - info.details = string.utf8sub(character.data["PhysDesc"], 1, 64).."..."; - else - info.details = character.data["PhysDesc"]; - end; - end; - - if (character.data["CharBanned"]) then - info.details = "This character is banned."; - end; - - Clockwork.plugin:Call("PlayerAdjustCharacterScreenInfo", player, character, info); - Clockwork.datastream:Start(player, "CharacterAdd", info); -end; - --- A function to convert a character's MySQL variables to Lua variables. -function Clockwork.player:ConvertCharacterMySQL(baseTable) - baseTable.recognisedNames = self:ConvertCharacterRecognisedNamesString(baseTable.recognisedNames); - baseTable.characterID = tonumber(baseTable.characterID); - baseTable.attributes = self:ConvertCharacterDataString(baseTable.attributes); - baseTable.inventory = Clockwork.inventory:ToLoadable( - self:ConvertCharacterDataString(baseTable.inventory) - ); - baseTable.cash = tonumber(baseTable.cash); - baseTable.ammo = self:ConvertCharacterDataString(baseTable.ammo); - baseTable.data = self:ConvertCharacterDataString(baseTable.data); - baseTable.key = tonumber(baseTable.key); -end; - --- A function to get a player's character ID. -function Clockwork.player:GetCharacterID(player) - local character = player:GetCharacter(); - - if (character) then - for k, v in pairs(player:GetCharacters()) do - if (v == character) then - return k; - end; - end; - end; -end; - --- A function to load a player's character. -function Clockwork.player:LoadCharacter(player, characterID, tMergeCreate, Callback, bForce) - local character = {}; - local unixTime = os.time(); - - if (tMergeCreate) then - character = {}; - character.name = name; - character.data = {}; - character.ammo = {}; - character.cash = Clockwork.config:Get("default_cash"):Get(); - character.model = "models/police.mdl"; - character.flags = "b"; - character.schema = Clockwork.kernel:GetSchemaFolder(); - character.gender = GENDER_MALE; - character.faction = FACTION_CITIZEN; - character.steamID = player:SteamID(); - character.steamName = player:SteamName(); - character.inventory = {}; - character.attributes = {}; - character.onNextLoad = ""; - character.lastPlayed = unixTime; - character.timeCreated = unixTime; - character.characterID = characterID; - character.recognisedNames = {}; - - if (!player.cwCharacterList[characterID]) then - table.Merge(character, tMergeCreate); - - if (character and type(character) == "table") then - character.inventory = {}; - Clockwork.plugin:Call( - "GetPlayerDefaultInventory", player, character, character.inventory - ); - - if (!bForce) then - local fault = Clockwork.plugin:Call("PlayerCanCreateCharacter", player, character, characterID); - - if (fault == false or type(fault) == "string") then - return self:SetCreateFault(player, fault or "You cannot create this character!"); - end; - end; - - self:SaveCharacter(player, true, character, function(key) - player.cwCharacterList[characterID] = character; - player.cwCharacterList[characterID].key = key; - - Clockwork.plugin:Call("PlayerCharacterCreated", player, character); - self:CharacterScreenAdd(player, character); - - if (Callback) then - Callback(); - end; - end); - end; - end; - else - character = player.cwCharacterList[characterID]; - - if (character) then - if (player:GetCharacter()) then - self:SaveCharacter(player); - self:UpdateCharacter(player); - - Clockwork.plugin:Call("PlayerCharacterUnloaded", player); - end; - - player.cwCharacter = character; - - if (player:Alive()) then - player:KillSilent(); - end; - - if (self:SetBasicSharedVars(player)) then - Clockwork.plugin:Call("PlayerCharacterLoaded", player); - player:SaveCharacter(); - end; - end; - end; -end; - --- A function to set a player's basic shared variables. -function Clockwork.player:SetBasicSharedVars(player) - local gender = player:GetGender(); - local faction = player:GetFaction(); - - player:SetSharedVar("Flags", player:GetFlags()); - player:SetSharedVar("Model", self:GetDefaultModel(player)); - player:SetSharedVar("Name", player:Name()); - player:SetSharedVar("Key", player:GetCharacterKey()); - - if (Clockwork.faction.stored[faction]) then - player:SetSharedVar("Faction", Clockwork.faction.stored[faction].index); - end; - - if (gender == GENDER_MALE) then - player:SetSharedVar("Gender", 2); - else - player:SetSharedVar("Gender", 1); - end; - - return true; -end; - --- A function to get the character's ammo as a string. -function Clockwork.player:GetCharacterAmmoString(player, character, bRawTable) - local ammo = table.Copy(character.ammo); - - for k, v in pairs(self:GetAmmo(player)) do - if (v > 0) then - ammo[k] = v; - end; - end; - - if (!bRawTable) then - return Clockwork.json:Encode(ammo); - else - return ammo; - end; -end; - --- A function to get the character's data as a string. -function Clockwork.player:GetCharacterDataString(player, character, bRawTable) - local data = table.Copy(character.data); - Clockwork.plugin:Call("PlayerSaveCharacterData", player, data); - - if (!bRawTable) then - return Clockwork.json:Encode(data); - else - return data; - end; -end; - --- A function to get the character's recognised names as a string. -function Clockwork.player:GetCharacterRecognisedNamesString(player, character) - local recognisedNames = {}; - - for k, v in pairs(character.recognisedNames) do - if (v == RECOGNISE_SAVE) then - recognisedNames[#recognisedNames + 1] = k; - end; - end; - - return Clockwork.json:Encode(recognisedNames); -end; - --- A function to get the character's inventory as a string. -function Clockwork.player:GetCharacterInventoryString(player, character, bRawTable) - local inventory = Clockwork.inventory:CreateDuplicate(character.inventory); - Clockwork.plugin:Call("PlayerAddToSavedInventory", player, character, function(itemTable) - Clockwork.inventory:AddInstance(inventory, itemTable); - end); - - if (!bRawTable) then - return Clockwork.json:Encode(Clockwork.inventory:ToSaveable(inventory)); - else - return inventory; - end; -end; - --- A function to convert a character's recognised names string to a table. -function Clockwork.player:ConvertCharacterRecognisedNamesString(data) - local bSuccess, value = pcall(Clockwork.json.Decode, Clockwork.json, data); - - if (bSuccess and value != nil) then - local recognisedNames = {}; - - for k, v in pairs(value) do - recognisedNames[v] = RECOGNISE_SAVE; - end; - - return recognisedNames; - else - return {}; - end; -end; - --- A function to convert a character's data string to a table. -function Clockwork.player:ConvertCharacterDataString(data) - local bSuccess, value = pcall(Clockwork.json.Decode, Clockwork.json, data); - - if (bSuccess and value != nil) then - return value; - else - return {}; - end; -end; - --- A function to load a player's data. -function Clockwork.player:LoadData(player, Callback) - local playersTable = Clockwork.config:Get("mysql_players_table"):Get(); - local schemaFolder = Clockwork.kernel:GetSchemaFolder(); - local unixTime = os.time(); - local steamID = player:SteamID(); - - local queryObj = Clockwork.database:Select(playersTable); - queryObj:AddWhere("_Schema = ?", schemaFolder); - queryObj:AddWhere("_SteamID = ?", steamID); - queryObj:SetCallback(function(result) - if (!IsValid(player) or player.cwData) then - return; - end; - - local onNextPlay = ""; - - if (Clockwork.database:IsResult(result)) then - player.cwTimeJoined = tonumber(result[1]._TimeJoined); - player.cwLastPlayed = tonumber(result[1]._LastPlayed); - player.cwUserGroup = result[1]._UserGroup; - player.cwData = Clockwork.player:ConvertDataString(player, result[1]._Data); - - local bSuccess, value = pcall(Clockwork.json.Decode, Clockwork.json, result[1]._Donations); - - if (bSuccess and value != nil) then - player.cwDonations = value; - else - player.cwDonations = {}; - end; - - onNextPlay = result[1]._OnNextPlay; - else - player.cwTimeJoined = unixTime; - player.cwLastPlayed = unixTime; - player.cwDonations = {}; - player.cwUserGroup = "user"; - player.cwData = Clockwork.player:SaveData(player, true); - end; - - if (Clockwork.player:IsProtected(player)) then - player.cwUserGroup = "superadmin"; - end; - - if (!player.cwUserGroup or player.cwUserGroup == "") then - player.cwUserGroup = "user"; - end; - - if (!Clockwork.config:Get("use_own_group_system"):Get() - and player.cwUserGroup != "user") then - player:SetUserGroup(player.cwUserGroup); - end; - - Clockwork.plugin:Call("PlayerRestoreData", player, player.cwData); - - if (Callback and IsValid(player)) then - Callback(player); - end; - - if (onNextPlay != "") then - local updateObj = Clockwork.database:Update(playersTable); - updateObj:SetValue("_OnNextPlay", ""); - updateObj:SetValue("_SteamID", steamID); - updateObj:SetValue("_Schema", schemaFolder); - updateObj:Push(); - - PLAYER = player; - RunString(onNextPlay); - PLAYER = nil; - end; - end); - queryObj:Pull(); - - timer.Simple(2, function() - if (IsValid(player) and !player.cwData) then - self:LoadData(player, Callback); - end; - end); -end; - --- A function to save a players's data. -function Clockwork.player:SaveData(player, bCreate) - if (!bCreate) then - local schemaFolder = Clockwork.kernel:GetSchemaFolder(); - local steamName = Clockwork.database:Escape(player:SteamName()); - local ipAddress = player:IPAddress(); - local userGroup = player:GetClockworkUserGroup(); - local steamID = player:SteamID(); - local data = table.Copy(player.cwData); - - Clockwork.plugin:Call("PlayerSaveData", player, data); - - local playersTable = Clockwork.config:Get("mysql_players_table"):Get(); - local queryObj = Clockwork.database:Update(playersTable); - queryObj:AddWhere("_Schema = ?", schemaFolder); - queryObj:AddWhere("_SteamID = ?", steamID); - queryObj:SetValue("_LastPlayed", os.time()); - queryObj:SetValue("_SteamName", steamName); - queryObj:SetValue("_IPAddress", ipAddress); - queryObj:SetValue("_UserGroup", userGroup); - queryObj:SetValue("_SteamID", steamID); - queryObj:SetValue("_Schema", schemaFolder); - queryObj:SetValue("_Data", Clockwork.json:Encode(data)); - queryObj:Push(); - else - local playersTable = Clockwork.config:Get("mysql_players_table"):Get(); - local queryObj = Clockwork.database:Insert(playersTable); - queryObj:SetValue("_Data", ""); - queryObj:SetValue("_Schema", Clockwork.kernel:GetSchemaFolder()); - queryObj:SetValue("_SteamID", player:SteamID()); - queryObj:SetValue("_Donations", ""); - queryObj:SetValue("_UserGroup", "user"); - queryObj:SetValue("_IPAddress", player:IPAddress()); - queryObj:SetValue("_SteamName", player:SteamName()); - queryObj:SetValue("_OnNextPlay", ""); - queryObj:SetValue("_LastPlayed", os.time()); - queryObj:SetValue("_TimeJoined", os.time()); - queryObj:Push(); - - return {}; - end; -end; - --- A function to update a player's character. -function Clockwork.player:UpdateCharacter(player) - player.cwCharacter.inventory = self:GetCharacterInventoryString(player, player.cwCharacter, true); - player.cwCharacter.ammo = self:GetCharacterAmmoString(player, player.cwCharacter, true); - player.cwCharacter.data = self:GetCharacterDataString(player, player.cwCharacter, true); -end; - --- A function to save a player's character. -function Clockwork.player:SaveCharacter(player, bCreate, character, Callback) - if (bCreate) then - local charactersTable = Clockwork.config:Get("mysql_characters_table"):Get(); - local values = ""; - local amount = 1; - local keys = ""; - - if (!character or type(character) != "table") then - character = player:GetCharacter(); - end; - - local queryObj = Clockwork.database:Insert(charactersTable); - for k, v in pairs(character) do - local tableKey = "_"..Clockwork.kernel:SetCamelCase(k, false); - - if (k == "recognisedNames") then - queryObj:SetValue(tableKey, Clockwork.json:Encode(character.recognisedNames)); - elseif (k == "attributes") then - queryObj:SetValue(tableKey, Clockwork.json:Encode(character.attributes)); - elseif (k == "inventory") then - queryObj:SetValue(tableKey, Clockwork.json:Encode(Clockwork.inventory:ToSaveable(character.inventory))); - elseif (k == "ammo") then - queryObj:SetValue(tableKey, Clockwork.json:Encode(character.ammo)); - elseif (k == "data") then - queryObj:SetValue(tableKey, Clockwork.json:Encode(v)); - else - queryObj:SetValue(tableKey, v); - end; - end; - if (system.IsWindows()) then - queryObj:SetCallback(function(result, status, lastID) - if (Callback and tonumber(lastID)) then - Callback(tonumber(lastID)); - end; - end); - elseif (system.IsLinux()) then - queryObj:SetCallback(function(result, status, lastID) - if (Callback) then - Callback(tonumber(lastID)); - end; - end); - end; - queryObj:SetFlag(2); - queryObj:Push(); - elseif (player:HasInitialized()) then - local currentCharacter = player:GetCharacter(); - local charactersTable = Clockwork.config:Get("mysql_characters_table"):Get(); - local schemaFolder = Clockwork.kernel:GetSchemaFolder(); - local unixTime = os.time(); - local steamID = player:SteamID(); - - if (!character) then - character = player:GetCharacter(); - end; - - local queryObj = Clockwork.database:Update(charactersTable); - queryObj:AddWhere("_Schema = ?", schemaFolder); - queryObj:AddWhere("_SteamID = ?", steamID); - queryObj:AddWhere("_CharacterID = ?", character.characterID); - queryObj:SetValue("_RecognisedNames", self:GetCharacterRecognisedNamesString(player, character)); - queryObj:SetValue("_Attributes", Clockwork.json:Encode(character.attributes)); - queryObj:SetValue("_LastPlayed", unixTime); - queryObj:SetValue("_SteamName", player:SteamName()); - queryObj:SetValue("_Faction", character.faction); - queryObj:SetValue("_Gender", character.gender); - queryObj:SetValue("_Schema", character.schema); - queryObj:SetValue("_Model", character.model); - queryObj:SetValue("_Flags", character.flags); - queryObj:SetValue("_Cash", character.cash); - queryObj:SetValue("_Name", character.name); - - if (currentCharacter == character) then - queryObj:SetValue("_Inventory", self:GetCharacterInventoryString(player, character)); - queryObj:SetValue("_Ammo", self:GetCharacterAmmoString(player, character)); - queryObj:SetValue("_Data", self:GetCharacterDataString(player, character)); - else - queryObj:SetValue("_Inventory", Clockwork.json:Encode(Clockwork.inventory:ToSaveable(character.inventory))); - queryObj:SetValue("_Ammo", Clockwork.json:Encode(character.ammo)); - queryObj:SetValue("_Data", Clockwork.json:Encode(character.data)); - end; - queryObj:Push(); - - --[[ Save the player's data after pushing the update. --]] - Clockwork.player:SaveData(player); - end; -end; - --- A function to get the class of a player's active weapon. -function Clockwork.player:GetWeaponClass(player, safe) - if (IsValid(player:GetActiveWeapon())) then - return player:GetActiveWeapon():GetClass(); - else - return safe; - end; -end; - --- A function to call a player's think hook. -function Clockwork.player:CallThinkHook(player, setSharedVars, curTime) - local player = player; - local infoTable = player.cwInfoTable; - local setSharedVars = setSharedVars; - local curTime = curTime; - local cwConfig = Clockwork.config; - local cwClass = Clockwork.class; - local cwPlugin = Clockwork.plugin; - - infoTable.inventoryWeight = cwConfig:Get("default_inv_weight"):Get(); - infoTable.inventorySpace = cwConfig:Get("default_inv_space"):Get(); - infoTable.crouchedSpeed = player.cwCrouchedSpeed; - infoTable.jumpPower = player.cwJumpPower; - infoTable.walkSpeed = player.cwWalkSpeed; - infoTable.isRunning = player:IsRunning(); - infoTable.isJogging = player:IsJogging(); - infoTable.runSpeed = player.cwRunSpeed; - infoTable.wages = cwClass:Query(player:Team(), "wages", 0); - - if (!player:IsJogging(true)) then - infoTable.isJogging = nil; - player:SetSharedVar("IsJogMode", false); - end; - - if (setSharedVars) then - cwPlugin:Call("PlayerSetSharedVars", player, curTime); - player.cwNextSetSharedVars = nil; - end; - - cwPlugin:Call("PlayerThink", player, curTime, infoTable); - player.cwNextThink = nil; -end; - --- A function to get a player's wages. -function Clockwork.player:GetWages(player) - return player:GetSharedVar("Wages"); -end; - --- A function to set a character's flags. -function Clockwork.player:SetFlags(player, flags) - Clockwork.player:TakeFlags(player, player:GetFlags()); - Clockwork.player:GiveFlags(player, flags); -end; - --- A function to set a player's flags. -function Clockwork.player:SetPlayerFlags(player, flags) - Clockwork.player:TakePlayerFlags(player, player:GetPlayerFlags()); - Clockwork.player:GivePlayerFlags(player, flags); -end; - --- A function to set a player's rank within their faction. -function Clockwork.player:SetFactionRank(player, rank) - if (rank) then - local faction = Clockwork.faction:FindByID(player:GetFaction()); - - if (faction and istable(faction.ranks)) then - for k, v in pairs(faction.ranks) do - if (k == rank) then - player:SetCharacterData("factionrank", k); - - if (v.class and Clockwork.class.stored[v.class]) then - Clockwork.class:Set(player, v.class); - end; - - if (v.model) then - player:SetModel(v.model); - end; - - if (istable(v.weapons)) then - for k, v in pairs(v.weapons) do - self:GiveSpawnWeapon(player, v); - end; - end; - - break; - end; - end; - end; - end; -end; - --- A function to get a player's global flags. -function Clockwork.player:GetPlayerFlags(player) - return player:GetData("Flags") or ""; -end; \ No newline at end of file diff --git a/Clockwork/garrysmod/gamemodes/clockwork/framework/libraries/sh_animation.lua b/Clockwork/garrysmod/gamemodes/clockwork/framework/libraries/sh_animation.lua index 7989d7ca..43c495e4 100644 --- a/Clockwork/garrysmod/gamemodes/clockwork/framework/libraries/sh_animation.lua +++ b/Clockwork/garrysmod/gamemodes/clockwork/framework/libraries/sh_animation.lua @@ -600,28 +600,28 @@ Clockwork.animation.stored.player = { ["crouch_pistol_aim_idle"] = "cidle_revolver", ["stand_grenade_aim_walk"] = "walk_grenade", ["crouch_pistol_aim_walk"] = "cwalk_revolver", - ["crouch_heavy_aim_idle"] = ACT_RANGE_AIM_SMG1_LOW, + ["crouch_heavy_aim_idle"] = "cidle_physgun", ["crouch_blunt_aim_idle"] = "cidle_melee", ["stand_grenade_aim_run"] = "run_grenade", ["crouch_blunt_aim_walk"] = "cwalk_melee", - ["crouch_heavy_aim_walk"] = ACT_WALK, + ["crouch_heavy_aim_walk"] = "cwalk_physgun", ["stand_pistol_aim_walk"] = "walk_revolver", ["stand_pistol_aim_idle"] = "idle_revolver", ["crouch_fist_aim_walk"] = "cwalk_fist", ["crouch_slam_aim_walk"] = "cwalk_slam", ["stand_pistol_aim_run"] = "run_revolver", ["crouch_fist_aim_idle"] = "cidle_fist", - ["stand_heavy_aim_idle"] = ACT_IDLE_ANGRY_RPG, + ["stand_heavy_aim_idle"] = "idle_physgun", ["stand_blunt_aim_idle"] = "idle_melee", ["crouch_slam_aim_idle"] = "cidle_slam", ["stand_blunt_aim_walk"] = "walk_melee", - ["stand_heavy_aim_walk"] = ACT_WALK, + ["stand_heavy_aim_walk"] = "walk_physgun", ["stand_fist_aim_idle"] = "idle_fist", ["crouch_smg_aim_walk"] = "cwalk_smg1", ["crouch_smg_aim_idle"] = "cidle_smg1", ["stand_fist_aim_walk"] = "walk_fist", ["stand_blunt_aim_run"] = "run_melee", - ["stand_heavy_aim_run"] = ACT_RUN_AIM_RIFLE_STIMULATED, + ["stand_heavy_aim_run"] = "run_physgun", ["crouch_grenade_walk"] = "cwalk_all", ["crouch_grenade_idle"] = "cidle_all", ["stand_slam_aim_idle"] = "idle_slam", @@ -638,26 +638,26 @@ Clockwork.animation.stored.player = { ["crouch_blunt_idle"] = ACT_MP_CROUCH_IDLE, ["stand_pistol_walk"] = ACT_MP_WALK, ["crouch_blunt_walk"] = "cwalk_all", - ["crouch_heavy_walk"] = ACT_WALK, + ["crouch_heavy_walk"] = "cwalk_passive", ["stand_pistol_idle"] = ACT_MP_STAND_IDLE, - ["crouch_heavy_idle"] = ACT_COVER_LOW_RPG, + ["crouch_heavy_idle"] = "cidle_passive", ["stand_smg_aim_run"] = "run_smg1", - ["stand_heavy_walk"] = ACT_WALK, + ["stand_heavy_walk"] = "walk_passive", ["stand_blunt_walk"] = ACT_MP_WALK, ["stand_blunt_idle"] = ACT_MP_STAND_IDLE, ["crouch_fist_idle"] = ACT_MP_CROUCH_IDLE, ["crouch_fist_walk"] = "cwalk_all", ["crouch_slam_idle"] = ACT_MP_CROUCH_IDLE, ["stand_pistol_run"] = ACT_MP_RUN, - ["stand_heavy_idle"] = ACT_IDLE_SHOTGUN_AGITATED, + ["stand_heavy_idle"] = "idle_passive", ["crouch_slam_walk"] = "cwalk_all", - ["stand_heavy_run"] = ACT_RUN_RPG_RELAXED, + ["stand_heavy_run"] = "run_passive", ["stand_slam_idle"] = ACT_MP_STAND_IDLE, ["stand_fist_walk"] = ACT_MP_WALK, ["stand_slam_walk"] = ACT_MP_WALK, ["stand_blunt_run"] = ACT_MP_RUN, - ["crouch_smg_walk"] = "cwalk_all", - ["crouch_smg_idle"] = ACT_MP_CROUCH_IDLE, + ["crouch_smg_walk"] = "cwalk_passive", + ["crouch_smg_idle"] = "cidle_passive", ["stand_fist_idle"] = ACT_MP_STAND_IDLE, ["stand_slam_run"] = ACT_MP_RUN, ["grenade_attack"] = ACT_RANGE_ATTACK_THROW, @@ -832,7 +832,7 @@ end; -- A function to make a model use the black skin for hands viewmodels. function Clockwork.animation:AddBlackModel(model) - blackModels[model] = true; + blackModels[string.lower(model)] = true; end; -- A function to make a model use the zombie skin for citizen hands. @@ -874,7 +874,7 @@ end; -- A function to make a model use the refugee viewmodel hands. function Clockwork.animation:AddRefugeeHands(model) self:AddHandsModel(model, { - body = 11, + body = 01, model = "models/weapons/c_arms_refugee.mdl", skin = 0 }); @@ -912,9 +912,15 @@ end; -- A function to adjust the hands info with checks for if a model is set to use the black skin. function Clockwork.animation:AdjustHandsInfo(model, info) - for k, v in pairs(blackModels) do - if (string.find(model, k)) then - info.skin = 1; + if (info.model == "models/weapons/c_arms_citizen.mdl" or info.model == "models/weapons/c_arms_refugee.mdl") then + for k, v in pairs(blackModels) do + if (string.find(model, k)) then + info.skin = 1; + + break; + elseif (info.skin == 1) then + info.skin = 0; + end; end; end; diff --git a/Clockwork/garrysmod/gamemodes/clockwork/framework/libraries/sh_ironsights.lua b/Clockwork/garrysmod/gamemodes/clockwork/framework/libraries/sh_ironsights.lua index 38fcd78f..ff379fd7 100644 --- a/Clockwork/garrysmod/gamemodes/clockwork/framework/libraries/sh_ironsights.lua +++ b/Clockwork/garrysmod/gamemodes/clockwork/framework/libraries/sh_ironsights.lua @@ -11,6 +11,7 @@ --]] if (!Clockwork.datastream) then include("sh_datastream.lua"); end; if (!Clockwork.plugin) then include("sh_plugin.lua"); end; +if (!Clockwork.player) then include("sh_player.lua"); end; --[[ Micro Optimizations because local variables are faster than table @@ -98,7 +99,7 @@ if (SERVER) then function Clockwork.ironsights:PlayerThink(player, curTime, infoTable) if (self:GetIronSights(player) and cwPly:GetWeaponRaised(player)) then - infoTable.walkSpeed = infoTable.walkSpeed * cwConfig:Get("ironsights_spread"):Get() or 0.5; + infoTable.walkSpeed = infoTable.walkSpeed * cwConfig:Get("ironsights_slow"):Get() or 0.5; end; end; diff --git a/Clockwork/garrysmod/gamemodes/clockwork/framework/libraries/sh_player.lua b/Clockwork/garrysmod/gamemodes/clockwork/framework/libraries/sh_player.lua index 9d07d32e..0aeb1baa 100644 --- a/Clockwork/garrysmod/gamemodes/clockwork/framework/libraries/sh_player.lua +++ b/Clockwork/garrysmod/gamemodes/clockwork/framework/libraries/sh_player.lua @@ -1,12 +1,4232 @@ ---[[ - © 2015 CloudSixteen.com do not share, re-distribute or modify +--[[ + © 2015 CloudSixteen.com do not share, re-distribute or modify without permission of its author (kurozael@gmail.com). Clockwork was created by Conna Wiles (also known as kurozael.) http://cloudsixteen.com/license/clockwork.html --]] -Clockwork.player = Clockwork.kernel:NewLibrary("Player"); +local Clockwork = Clockwork; +local Json = Json; +local tostring = tostring; +local tonumber = tonumber; +local IsValid = IsValid; +local CurTime = CurTime; +local Vector = Vector; +local Angle = Angle; +local Color = Color; +local pairs = pairs; +local type = type; +local player = player; +local string = string; +local table = table; +local ents = ents; +local math = math; +local util = util; + +if (!Clockwork.datastream) then include("sh_datastream.lua"); end; +if (!Clockwork.plugin) then include("sh_plugin.lua"); end; +if (!Clockwork.config) then include("sh_config.lua"); end; +if (!Clockwork.attribute) then include("sh_attribute.lua"); end; +if (!Clockwork.faction) then include("sh_faction.lua"); end; +if (!Clockwork.class) then include("sh_class.lua"); end; +if (!Clockwork.command) then include("sh_command.lua"); end; +if (!Clockwork.attribute) then include("sh_attribute.lua"); end; +if (!Clockwork.option) then include("sh_option.lua"); end; +if (!Clockwork.entity) then include("sh_entity.lua"); end; +if (!Clockwork.item) then include("sh_item.lua"); end; +if (!Clockwork.json) then include("sh_json.lua"); end; +if (!Clockwork.generator) then include("sh_generator.lua"); end; +if (!Clockwork.inventory) then include("sh_inventory.lua"); end; + +local cwCfg = Clockwork.config; +local cwAttribute = Clockwork.attribute; +local cwFaction = Clockwork.faction; +local cwClass = Clockwork.class; +local cwCommand = Clockwork.command; +local cwKernel = Clockwork.kernel; +local cwDatastream = Clockwork.datastream; +local cwOption = Clockwork.option; +local cwPlugin = Clockwork.plugin; +local cwEntity = Clockwork.entity; +local cwItem = Clockwork.item; +local cwJson = Clockwork.json; +local cwGenerator = Clockwork.generator; +local cwInventory = Clockwork.inventory; + +Clockwork.player = cwKernel:NewLibrary("Player"); + +if (CLIENT) then + +-- A function to get whether the local player can hold a weight. +function Clockwork.player:CanHoldWeight(weight) + local inventoryWeight = Clockwork.inventory:CalculateWeight( + Clockwork.inventory:GetClient() + ); + + if (inventoryWeight + weight > Clockwork.player:GetMaxWeight()) then + return false; + else + return true; + end; +end; + +-- A function to get whether the local player can fit a space. +function Clockwork.player:CanHoldSpace(space) + local inventorySpace = Clockwork.inventory:CalculateSpace( + Clockwork.inventory:GetClient() + ); + + if (inventorySpace + space > Clockwork.player:GetMaxSpace()) then + return false; + else + return true; + end; +end; + +-- A function to get the maximum amount of weight the local player can carry. +function Clockwork.player:GetMaxWeight() + local itemsList = Clockwork.inventory:GetAsItemsList( + Clockwork.inventory:GetClient() + ); + + local weight = Clockwork.Client:GetSharedVar("InvWeight") or Clockwork.config:Get("default_inv_weight"):Get(); + + for k, v in pairs(itemsList) do + local addInvWeight = v("addInvSpace"); + + if (addInvWeight) then + weight = weight + addInvWeight; + end; + end; + + return weight; +end; + +-- A function to get the maximum amount of space the local player can carry. +function Clockwork.player:GetMaxSpace() + local itemsList = Clockwork.inventory:GetAsItemsList( + Clockwork.inventory:GetClient() + ); + local space = Clockwork.Client:GetSharedVar("InvSpace") or Clockwork.config:Get("default_inv_space"):Get(); + + for k, v in pairs(itemsList) do + local addInvSpace = v("addInvVolume"); + + if (addInvSpace) then + space = space + addInvSpace; + end; + end; + + return space; +end; + +-- A function to find a player by an identifier. +function Clockwork.player:FindByID(identifier) + for k, v in pairs(player.GetAll()) do + if (v:HasInitialized() and (v:SteamID() == identifier + or string.find(string.lower(v:Name()), string.lower(identifier), 1, true))) then + return v; + end; + end; +end; + +-- A function to get the local player's clothes data. +function Clockwork.player:GetClothesData() + return Clockwork.ClothesData; +end; + +-- A function to get the local player's accessory data. +function Clockwork.player:GetAccessoryData() + return Clockwork.AccessoryData; +end; + +-- A function to get the local player's clothes item. +function Clockwork.player:GetClothesItem() + local clothesData = self:GetClothesData(); + + if (clothesData.itemID != nil and clothesData.uniqueID != nil) then + return Clockwork.inventory:FindItemByID( + Clockwork.inventory:GetClient(), + clothesData.uniqueID, clothesData.itemID + ); + end; +end; + +-- A function to get whether the local player is wearing clothes. +function Clockwork.player:IsWearingClothes() + return (self:GetClothesItem() != nil); +end; + +-- A function to get whether the local player has an accessory. +function Clockwork.player:HasAccessory(uniqueID) + local accessoryData = self:GetAccessoryData(); + + for k, v in pairs(accessoryData) do + if (string.lower(v) == string.lower(uniqueID)) then + return true; + end; + end; + + return false; +end; + +-- A function to get whether the local player is wearing an accessory. +function Clockwork.player:IsWearingAccessory(itemTable) + local accessoryData = self:GetAccessoryData(); + local itemID = itemTable("itemID"); + + if (accessoryData[itemID]) then + return true; + else + return false; + end; +end; + +-- A function to get whether the local player is wearing an item. +function Clockwork.player:IsWearingItem(itemTable) + local clothesItem = self:GetClothesItem(); + return (clothesItem and clothesItem:IsTheSameAs(itemTable)); +end; + +-- A function to get whether a player is noclipping. +function Clockwork.player:IsNoClipping(player) + if (player:GetMoveType() == MOVETYPE_NOCLIP + and !player:InVehicle()) then + return true; + end; +end; + +-- A function to get whether a player is an admin. +function Clockwork.player:IsAdmin(player) + if (self:HasFlags(player, "o")) then + return true; + end; +end; + +-- A function to get whether the local player's data has streamed. +function Clockwork.player:HasDataStreamed() + return Clockwork.DataHasStreamed; +end; + +-- A function to get whether a player can hear another player. +function Clockwork.player:CanHearPlayer(player, target, allowance) + if (Clockwork.config:Get("messages_must_see_player"):Get()) then + return self:CanSeePlayer(player, target, (allowance or 0.5), true); + else + return true; + end; +end; + +-- A function to get whether the target recognises the local player. +function Clockwork.player:DoesTargetRecognise() + if (Clockwork.config:Get("recognise_system"):Get()) then + return Clockwork.Client:GetSharedVar("TargetKnows"); + else + return true; + end; +end; + +-- A function to get a player's real trace. +function Clockwork.player:GetRealTrace(player, useFilterTrace) + if (!IsValid(player)) then + return; + end; + + local angles = player:GetAimVector() * 4096; + local eyePos = EyePos(); + + if (player != Clockwork.Client) then + eyePos = player:EyePos(); + end; + + local trace = util.TraceLine({ + endpos = eyePos + angles, + start = eyePos, + filter = player + }); + + local newTrace = util.TraceLine({ + endpos = eyePos + angles, + filter = player, + start = eyePos, + mask = CONTENTS_SOLID + CONTENTS_MOVEABLE + CONTENTS_OPAQUE + CONTENTS_DEBRIS + CONTENTS_HITBOX + CONTENTS_MONSTER + }); + + if ((IsValid(newTrace.Entity) and !newTrace.HitWorld and (!IsValid(trace.Entity) + or string.find(trace.Entity:GetClass(), "vehicle"))) or useFilterTrace) then + trace = newTrace; + end; + + return trace; +end; + +-- A function to get the local player's action. +function Clockwork.player:GetAction(player, percentage) + local startActionTime = player:GetSharedVar("StartActTime"); + local actionDuration = player:GetSharedVar("ActDuration"); + local curTime = CurTime(); + local action = player:GetSharedVar("ActName"); + + if (curTime < startActionTime + actionDuration) then + if (percentage) then + return action, (100 / actionDuration) * (actionDuration - ((startActionTime + actionDuration) - curTime)); + else + return action, actionDuration, startActionTime; + end; + else + return "", 0, 0; + end; +end; + +-- A function to get the local player's maximum characters. +function Clockwork.player:GetMaximumCharacters() + local whitelisted = Clockwork.character:GetWhitelisted(); + local maximum = Clockwork.config:Get("additional_characters"):Get(2); + + for k, v in pairs(Clockwork.faction.stored) do + if (!v.whitelist or table.HasValue(whitelisted, v.name)) then + maximum = maximum + 1; + end; + end; + + return maximum; +end; + +-- A function to get whether a player's weapon is raised. +function Clockwork.player:GetWeaponRaised(player) + return player:GetSharedVar("IsWepRaised"); +end; + +-- A function to get a player's unrecognised name. +function Clockwork.player:GetUnrecognisedName(player) + local unrecognisedPhysDesc = self:GetPhysDesc(player); + local unrecognisedName = Clockwork.config:Get("unrecognised_name"):Get(); + local usedPhysDesc; + + if (unrecognisedPhysDesc) then + unrecognisedName = unrecognisedPhysDesc; + usedPhysDesc = true; + end; + + return unrecognisedName, usedPhysDesc; +end; + +-- A function to get whether a player can see an NPC. +function Clockwork.player:CanSeeNPC(player, target, allowance, ignoreEnts) + if (player:GetEyeTraceNoCursor().Entity == target) then + return true; + else + local trace = {}; + + trace.mask = CONTENTS_SOLID + CONTENTS_MOVEABLE + CONTENTS_OPAQUE + CONTENTS_DEBRIS + CONTENTS_HITBOX + CONTENTS_MONSTER; + trace.start = player:GetShootPos(); + trace.endpos = target:GetShootPos(); + trace.filter = {player, target}; + + if (ignoreEnts) then + if (type(ignoreEnts) == "table") then + table.Add(trace.filter, ignoreEnts); + else + table.Add(trace.filter, ents.GetAll()); + end; + end; + + trace = util.TraceLine(trace); + + if (trace.Fraction >= (allowance or 0.75)) then + return true; + end; + end; +end; + +-- A function to get whether a player can see a player. +function Clockwork.player:CanSeePlayer(player, target, allowance, ignoreEnts) + if (player:GetEyeTraceNoCursor().Entity == target) then + return true; + elseif (target:GetEyeTraceNoCursor().Entity == player) then + return true; + else + local trace = {}; + + trace.mask = CONTENTS_SOLID + CONTENTS_MOVEABLE + CONTENTS_OPAQUE + CONTENTS_DEBRIS + CONTENTS_HITBOX + CONTENTS_MONSTER; + trace.start = player:GetShootPos(); + trace.endpos = target:GetShootPos(); + trace.filter = {player, target}; + + if (ignoreEnts) then + if (type(ignoreEnts) == "table") then + table.Add(trace.filter, ignoreEnts); + else + table.Add(trace.filter, ents.GetAll()); + end; + end; + + trace = util.TraceLine(trace); + + if (trace.Fraction >= (allowance or 0.75)) then + return true; + end; + end; +end; + +-- A function to get whether a player can see an entity. +function Clockwork.player:CanSeeEntity(player, target, allowance, ignoreEnts) + if (player:GetEyeTraceNoCursor().Entity == target) then + return true; + else + local trace = {}; + + trace.mask = CONTENTS_SOLID + CONTENTS_MOVEABLE + CONTENTS_OPAQUE + CONTENTS_DEBRIS + CONTENTS_HITBOX + CONTENTS_MONSTER; + trace.start = player:GetShootPos(); + trace.endpos = target:LocalToWorld(target:OBBCenter()); + trace.filter = {player, target}; + + if (ignoreEnts) then + if (type(ignoreEnts) == "table") then + table.Add(trace.filter, ignoreEnts); + else + table.Add(trace.filter, ents.GetAll()); + end; + end; + + trace = util.TraceLine(trace); + + if (trace.Fraction >= (allowance or 0.75)) then + return true; + end; + end; +end; + +-- A function to get whether a player can see a position. +function Clockwork.player:CanSeePosition(player, position, allowance, ignoreEnts) + local trace = {}; + + trace.mask = CONTENTS_SOLID + CONTENTS_MOVEABLE + CONTENTS_OPAQUE + CONTENTS_DEBRIS + CONTENTS_HITBOX + CONTENTS_MONSTER; + trace.start = player:GetShootPos(); + trace.endpos = position; + trace.filter = player; + + if (ignoreEnts) then + if (type(ignoreEnts) == "table") then + table.Add(trace.filter, ignoreEnts); + else + table.Add(trace.filter, ents.GetAll()); + end; + end; + + trace = util.TraceLine(trace); + + if (trace.Fraction >= (allowance or 0.75)) then + return true; + end; +end; + +-- A function to get a player's wages name. +function Clockwork.player:GetWagesName(player) + return Clockwork.class:Query(player:Team(), "wagesName", Clockwork.config:Get("wages_name"):Get()); +end; + +-- A function to check whether a player is ragdolled +function Clockwork.player:IsRagdolled(player, exception, entityless) + if (player:GetRagdollEntity() or entityless) then + if (player:GetSharedVar("IsRagdoll") == 0) then + return false; + elseif (player:GetSharedVar("IsRagdoll") == exception) then + return false; + else + return (player:GetSharedVar("IsRagdoll") != RAGDOLL_NONE); + end; + end; +end; + +-- A function to get whether the local player recognises another player. +function Clockwork.player:DoesRecognise(player, status, isAccurate) + if (!status) then + return self:DoesRecognise(player, RECOGNISE_PARTIAL); + elseif (Clockwork.config:Get("recognise_system"):Get()) then + local key = self:GetCharacterKey(player); + local realValue = false; + + if (self:GetCharacterKey(Clockwork.Client) == key) then + return true; + elseif (Clockwork.RecognisedNames[key]) then + if (isAccurate) then + realValue = (Clockwork.RecognisedNames[key] == status); + else + realValue = (Clockwork.RecognisedNames[key] >= status); + end; + end; + + return Clockwork.plugin:Call("PlayerDoesRecognisePlayer", player, status, isAccurate, realValue); + else + return true; + end; +end; + +-- A function to get a player's character key. +function Clockwork.player:GetCharacterKey(player) + if (IsValid(player)) then + return player:GetSharedVar("Key"); + end; +end; + +-- A function to get a player's ragdoll state. +function Clockwork.player:GetRagdollState(player) + if (player:GetSharedVar("IsRagdoll") == 0) then + return false; + else + return player:GetSharedVar("IsRagdoll"); + end; +end; + +-- A function to get a player's physical description. +function Clockwork.player:GetPhysDesc(player) + if (!player) then + player = Clockwork.Client; + end; + + local physDesc = player:GetSharedVar("PhysDesc"); + local team = player:Team(); + + if (physDesc == "") then + physDesc = Clockwork.class:Query(team, "defaultPhysDesc", ""); + end; + + if (physDesc == "") then + physDesc = Clockwork.config:Get("default_physdesc"):Get(); + end; + + if (!physDesc or physDesc == "") then + physDesc = "This character has no physical description set."; + else + physDesc = Clockwork.kernel:ModifyPhysDesc(physDesc); + end; + + local override = Clockwork.plugin:Call("GetPlayerPhysDescOverride", player, physDesc); + + if (override) then + physDesc = override; + end; + + return physDesc; +end; + +-- A function to get the local player's wages. +function Clockwork.player:GetWages() + return Clockwork.Client:GetSharedVar("Wages"); +end; + +-- A function to get the local player's cash. +function Clockwork.player:GetCash() + return Clockwork.Client:GetSharedVar("Cash"); +end; + +-- A function to get a player's ragdoll entity. +function Clockwork.player:GetRagdollEntity(player) + local ragdollEntity = player:GetSharedVar("Ragdoll"); + + if (IsValid(ragdollEntity)) then + return ragdollEntity; + end; +end; + +-- A function to get a player's default skin. +function Clockwork.player:GetDefaultSkin(player) + local model, skin = Clockwork.class:GetAppropriateModel(player:Team(), player); + + return skin; +end; + +-- A function to get a player's default model. +function Clockwork.player:GetDefaultModel(player) + local model, skin = Clockwork.class:GetAppropriateModel(player:Team(), player); + return model; +end; + +-- A function to check if a player has any flags. +function Clockwork.player:HasAnyFlags(player, flags, bByDefault) + local playerFlags = player:GetSharedVar("Flags") + + if (playerFlags != "") then + if (Clockwork.class:HasAnyFlags(player:Team(), flags) and !bByDefault) then + return true; + end; + + for i = 1, #flags do + local flag = string.utf8sub(flags, i, i); + local bSuccess = true; + + if (!bByDefault) then + local hasFlag = Clockwork.plugin:Call("PlayerDoesHaveFlag", player, flag); + + if (hasFlag != false) then + if (hasFlag) then + return true; + end; + else + bSuccess = nil; + end; + end; + + if (bSuccess) then + if (flag == "s") then + if (player:IsSuperAdmin()) then + return true; + end; + elseif (flag == "a") then + if (player:IsAdmin()) then + return true; + end; + elseif (flag == "o") then + if (player:IsSuperAdmin() or player:IsAdmin()) then + return true; + elseif (player:IsUserGroup("operator")) then + return true; + end; + elseif (string.find(playerFlags, flag)) then + return true; + end; + end; + end; + end; +end; + +-- A function to check if a player has access. +function Clockwork.player:HasFlags(player, flags, bByDefault) + local playerFlags = player:GetSharedVar("Flags") + + if (playerFlags != "") then + if (Clockwork.class:HasFlags(player:Team(), flags) and !bByDefault) then + return true; + end; + + for i = 1, #flags do + local flag = string.utf8sub(flags, i, i); + local bSuccess; + + if (!bByDefault) then + local hasFlag = Clockwork.plugin:Call("PlayerDoesHaveFlag", player, flag); + + if (hasFlag != false) then + if (hasFlag) then + bSuccess = true; + end; + else + return; + end; + end; + + if (!bSuccess) then + if (flag == "s") then + if (!player:IsSuperAdmin()) then + return; + end; + elseif (flag == "a") then + if (!player:IsAdmin()) then + return; + end; + elseif (flag == "o") then + if (!player:IsSuperAdmin() and !player:IsAdmin()) then + if (!player:IsUserGroup("operator")) then + return; + end; + end; + elseif (!string.find(playerFlags, flag)) then + return false; + end; + end; + end; + + return true; + end; +end; + +-- A function to set a shared variable for a player. +function Clockwork.player:SetSharedVar(player, key, value) + if (IsValid(player)) then + local sharedVars = Clockwork.kernel:GetSharedVars():Player(); + + if (!sharedVars) then + return; + elseif (not sharedVars[key]) then + return; + end; + + local sharedVarData = sharedVars[key]; + + if (sharedVarData.bPlayerOnly) then + if (value == nil) then + sharedVarData.value = Clockwork.kernel:GetDefaultNetworkedValue(sharedVarData.class); + else + sharedVarData.value = value; + end; + else + local class = Clockwork.kernel:ConvertNetworkedClass(sharedVarData.class); + + if (class) then + player["SetNetworked"..class](player, key, value); + end; + end; + end; +end; + +-- A function to get a player's shared variable. +function Clockwork.player:GetSharedVar(player, key, sharedTable) + if (IsValid(player)) then + if (!sharedTable) then + local sharedVars = Clockwork.kernel:GetSharedVars():Player(); + + if (!sharedVars) then + return; + elseif (not sharedVars[key]) then + return; + end; + + local sharedVarData = sharedVars[key]; + + if (sharedVarData.bPlayerOnly) then + if (!sharedVarData.value) then + return Clockwork.kernel:GetDefaultNetworkedValue(sharedVarData.class); + else + return sharedVarData.value; + end; + else + local class = Clockwork.kernel:ConvertNetworkedClass(sharedVarData.class); + + if (class) then + return player["GetNetworked"..class](player, key); + end; + end; + else + sharedTable = Clockwork.SharedTables[sharedTable]; + + if (sharedTable) then + return sharedTable[key]; + end; + end; + end; +end; + +-- A function to get whether the local player is drunk. +function Clockwork.player:GetDrunk() + local isDrunk = Clockwork.Client:GetSharedVar("IsDrunk"); + + if (isDrunk and isDrunk > 0) then + return isDrunk; + end; +end; + +-- A function to get a player's chat icon. +function Clockwork.player:GetChatIcon(player) + local icon; + + for k, v in pairs(Clockwork.icon:GetAll()) do + if (v.callback(player)) then + if (!icon) then + icon = v.path; + end; + + if (v.isPlayer) then + icon = v.path; + break; + end; + end; + end; + + if (!icon) then + local faction = player:GetFaction(); + + icon = "icon16/user.png"; + + if (faction and Clockwork.faction.stored[faction]) then + if (Clockwork.faction.stored[faction].whitelist) then + icon = "icon16/add.png"; + end; + end; + end; + + return icon; +end; + +else -- if (SERVER) then + +if (!Clockwork.database) then include("server/sv_database.lua"); end; +if (!Clockwork.chatBox) then include("server/sv_chatbox.lua"); end; +if (!Clockwork.hint) then include("sv_hint.lua"); end; + +local cwHint = Clockwork.hint; +local cwChatbox = Clockwork.chatBox; +local cwDatabase = Clockwork.database; + +Clockwork.player.property = Clockwork.player.property or {}; +Clockwork.player.stored = Clockwork.player.stored or {}; + +-- A function to run an inventory action for a player. +function Clockwork.player:InventoryAction(player, itemTable, action) + return self:RunClockworkCommand(player, "InvAction", action, itemTable("uniqueID"), tostring(itemTable("itemID"))); +end; + +-- A function to get a player's gear. +function Clockwork.player:GetGear(player, gearClass) + if (player.cwGearTab and IsValid(player.cwGearTab[gearClass])) then + return player.cwGearTab[gearClass]; + end; +end; + +-- A function to create a character from data. +function Clockwork.player:CreateCharacterFromData(player, data) + if (player.cwIsCreatingChar) then + return; + end; + + local minimumPhysDesc = cwCfg:Get("minimum_physdesc"):Get(); + local attributesTable = cwAttribute:GetAll(); + local factionTable = cwFaction:FindByID(data.faction); + local attributes = nil; + local info = {}; + + if (table.Count(attributesTable) > 0) then + for k, v in pairs(attributesTable) do + if (v.isOnCharScreen) then + attributes = true; + break; + end; + end; + end; + + if (!factionTable) then + return self:SetCreateFault( + player, "You did not choose a faction, or the faction that you chose is not valid!" + ); + end; + + info.attributes = {}; + info.faction = factionTable.name; + info.gender = data.gender; + info.model = data.model; + info.data = {}; + + if (data.plugin) then + for k, v in pairs(data.plugin) do + info.data[k] = v; + end; + end; + + local classes = false; + + for k, v in pairs(cwClass:GetAll()) do + if (v.isOnCharScreen and (v.factions + and table.HasValue(v.factions, factionTable.name))) then + classes = true; + end; + end; + + if (classes) then + local classTable = cwClass:FindByID(data.class); + + if (!classTable) then + return self:SetCreateFault( + player, "You did not choose a class, or the class that you chose is not valid!" + ); + else + info.data["class"] = classTable.name; + end; + end; + + if (attributes and type(data.attributes) == "table") then + local maximumPoints = cwCfg:Get("default_attribute_points"):Get(); + local pointsSpent = 0; + + if (factionTable.attributePointsScale) then + maximumPoints = math.Round(maximumPoints * factionTable.attributePointsScale); + end; + + if (factionTable.maximumAttributePoints) then + maximumPoints = factionTable.maximumAttributePoints; + end; + + for k, v in pairs(data.attributes) do + local attributeTable = cwAttribute:FindByID(k); + + if (attributeTable and attributeTable.isOnCharScreen) then + local uniqueID = attributeTable.uniqueID; + local amount = math.Clamp(v, 0, attributeTable.maximum); + + info.attributes[uniqueID] = { + amount = amount, + progress = 0 + }; + + pointsSpent = pointsSpent + amount; + end; + end; + + if (pointsSpent > maximumPoints) then + return self:SetCreateFault( + player, "You have chosen more "..cwOption:GetKey("name_attribute", true).." points than you can afford to spend!" + ); + end; + elseif (attributes) then + return self:SetCreateFault( + player, "You did not choose any "..cwOption:GetKey("name_attributes", true).." or the ones that you did are not valid!" + ); + end; + + if (!factionTable.GetName) then + if (!factionTable.useFullName) then + if (data.forename and data.surname) then + data.forename = string.gsub(data.forename, "^.", string.upper); + data.surname = string.gsub(data.surname, "^.", string.upper); + + if (string.find(data.forename, "[%p%s%d]") or string.find(data.surname, "[%p%s%d]")) then + return self:SetCreateFault( + player, "Your forename and surname must not contain punctuation, spaces or digits!" + ); + end; + + if (!string.find(data.forename, "[aeiou]") or !string.find(data.surname, "[aeiou]")) then + return self:SetCreateFault( + player, "Your forename and surname must both contain at least one vowel!" + ); + end; + + if (string.utf8len(data.forename) < 2 or string.utf8len(data.surname) < 2) then + return self:SetCreateFault( + player, "Your forename and surname must both be at least 2 characters long!" + ); + end; + + if (string.utf8len(data.forename) > 16 or string.utf8len(data.surname) > 16) then + return self:SetCreateFault( + player, "Your forename and surname must not be greater than 16 characters long!" + ); + end; + else + return self:SetCreateFault( + player, "You did not choose a name, or the name that you chose is not valid!" + ); + end; + elseif (!data.fullName or data.fullName == "") then + return self:SetCreateFault( + player, "You did not choose a name, or the name that you chose is not valid!" + ); + end; + end; + + if (cwCommand:FindByID("CharPhysDesc") != nil) then + if (type(data.physDesc) != "string") then + return self:SetCreateFault( + player, "You did not enter a physical description!" + ); + elseif (string.utf8len(data.physDesc) < minimumPhysDesc) then + return self:SetCreateFault( + player, "The physical description must be at least "..minimumPhysDesc.." characters long!" + ); + end; + + info.data["PhysDesc"] = cwKernel:ModifyPhysDesc(data.physDesc); + end; + + if (!factionTable.GetModel and !info.model) then + return self:SetCreateFault( + player, "You did not choose a model, or the model that you chose is not valid!" + ); + end; + + if (!cwFaction:IsGenderValid(info.faction, info.gender)) then + return self:SetCreateFault( + player, "You did not choose a gender, or the gender that you chose is not valid!" + ); + end; + + if (factionTable.whitelist and !self:IsWhitelisted(player, info.faction)) then + return self:SetCreateFault( + player, "You are not on the "..info.faction.." whitelist!" + ); + elseif (cwFaction:IsModelValid(factionTable.name, info.gender, info.model) + or (factionTable.GetModel and !info.model)) then + local charactersTable = cwCfg:Get("mysql_characters_table"):Get(); + local schemaFolder = cwKernel:GetSchemaFolder(); + local characterID = nil; + local characters = player:GetCharacters(); + + if (cwFaction:HasReachedMaximum(player, factionTable.name)) then + return self:SetCreateFault( + player, "You cannot create any more characters in this faction." + ); + end; + + for i = 1, self:GetMaximumCharacters(player) do + if (!characters[i]) then + characterID = i; + break; + end; + end; + + if (characterID) then + if (factionTable.GetName) then + info.name = factionTable:GetName(player, info, data); + elseif (!factionTable.useFullName) then + info.name = data.forename.." "..data.surname; + else + info.name = data.fullName; + end; + + if (factionTable.GetModel) then + info.model = factionTable:GetModel(player, info, data); + else + info.model = data.model; + end; + + if (factionTable.OnCreation) then + local fault = factionTable:OnCreation(player, info); + + if (fault == false or type(fault) == "string") then + return self:SetCreateFault( + player, fault or "There was an error creating this character!" + ); + end; + end; + + for k, v in pairs(characters) do + if (v.name == info.name) then + return self:SetCreateFault( + player, "You already have a character with the name '"..info.name.."'!" + ); + end; + end; + + local fault = cwPlugin:Call("PlayerAdjustCharacterCreationInfo", player, info, data); + + if (fault == false or type(fault) == "string") then + return self:SetCreateFault( + player, fault or "There was an error creating this character!" + ); + end; + + local queryObj = cwDatabase:Select(charactersTable); + queryObj:AddWhere("_Schema = ?", schemaFolder); + queryObj:AddWhere("_Name = ?", info.name); + queryObj:SetCallback(function(result) + if (!IsValid(player)) then return; end; + + if (cwDatabase:IsResult(result)) then + self:SetCreateFault( + player, "A character with the name '"..info.name.."' already exists!" + ); + player.cwIsCreatingChar = nil; + else + self:LoadCharacter(player, characterID, + { + attributes = info.attributes, + faction = info.faction, + gender = info.gender, + model = info.model, + name = info.name, + data = info.data + }, + function() + cwKernel:PrintLog(LOGTYPE_MINOR, + player:SteamName().." has created a "..info.faction.." character called '"..info.name.."'." + ); + + cwDatastream:Start(player, "CharacterFinish", {bSuccess = true}); + + player.cwIsCreatingChar = nil; + + local characters = player:GetCharacters(); + + if (table.Count(characters) == 1) then + self:UseCharacter(player, characterID); + end; + end + ); + end; + end); + queryObj:Pull(); + else + return self:SetCreateFault(player, "You cannot create any more characters!"); + end; + else + return self:SetCreateFault( + player, "You did not choose a model, or the model that you chose is not valid!" + ); + end; +end; + +-- A function to open the character menu. +function Clockwork.player:SetCharacterMenuOpen(player, bReset) + if (player:HasInitialized()) then + cwDatastream:Start(player, "CharacterOpen", (bReset == true)); + + if (bReset) then + player.cwCharMenuReset = true; + player:KillSilent(); + end; + end; +end; + +-- A function to start a sound for a player. +function Clockwork.player:StartSound(player, uniqueID, sound, fVolume) + if (!player.cwSoundsPlaying) then + player.cwSoundsPlaying = {}; + end; + + if (!player.cwSoundsPlaying[uniqueID] + or player.cwSoundsPlaying[uniqueID] != sound) then + player.cwSoundsPlaying[uniqueID] = sound; + + cwDatastream:Start(player, "StartSound", { + uniqueID = uniqueID, sound = sound, volume = (fVolume or 0.75) + }); + end; +end; + +-- A function to stop a sound for a player. +function Clockwork.player:StopSound(player, uniqueID, iFadeOut) + if (!player.cwSoundsPlaying) then + player.cwSoundsPlaying = {}; + end; + + if (player.cwSoundsPlaying[uniqueID]) then + player.cwSoundsPlaying[uniqueID] = nil; + + cwDatastream:Start(player, "StopSound", { + uniqueID = uniqueID, fadeOut = (iFadeOut or 0) + }); + end; +end; + +-- A function to remove a player's gear. +function Clockwork.player:RemoveGear(player, gearClass) + if (player.cwGearTab and IsValid(player.cwGearTab[gearClass])) then + player.cwGearTab[gearClass]:Remove(); + player.cwGearTab[gearClass] = nil; + end; +end; + +-- A function to strip all of a player's gear. +function Clockwork.player:StripGear(player) + if (!player.cwGearTab) then return; end; + + for k, v in pairs(player.cwGearTab) do + if (IsValid(v)) then v:Remove(); end; + end; + + player.cwGearTab = {}; +end; + +-- A function to create a player's gear. +function Clockwork.player:CreateGear(player, gearClass, itemTable, bMustHave) + if (!player.cwGearTab) then + player.cwGearTab = {}; + end; + + if (IsValid(player.cwGearTab[gearClass])) then + player.cwGearTab[gearClass]:Remove(); + end; + + if (itemTable("isAttachment")) then + local position = player:GetPos(); + local angles = player:GetAngles(); + local model = itemTable("attachmentModel", itemTable("model")); + + player.cwGearTab[gearClass] = ents.Create("cw_gear"); + player.cwGearTab[gearClass]:SetParent(player); + player.cwGearTab[gearClass]:SetAngles(angles); + player.cwGearTab[gearClass]:SetModel(model); + player.cwGearTab[gearClass]:SetPos(position); + player.cwGearTab[gearClass]:Spawn(); + + if (itemTable("attachmentMaterial")) then + player.cwGearTab[gearClass]:SetMaterial(itemTable("attachmentMaterial")); + end; + + if (itemTable("attachmentColor")) then + player.cwGearTab[gearClass]:SetColor( + cwKernel:UnpackColor(itemTable("attachmentColor")) + ); + else + player.cwGearTab[gearClass]:SetColor(Color(255, 255, 255, 255)); + end; + + if (IsValid(player.cwGearTab[gearClass])) then + player.cwGearTab[gearClass]:SetOwner(player); + player.cwGearTab[gearClass]:SetMustHave(bMustHave); + player.cwGearTab[gearClass]:SetItemTable(gearClass, itemTable); + end; + end; +end; + +-- A function to get whether a player is noclipping. +function Clockwork.player:IsNoClipping(player) + if (player:GetMoveType() == MOVETYPE_NOCLIP + and !player:InVehicle()) then + return true; + end; +end; + +-- A function to get whether a player is an admin. +function Clockwork.player:IsAdmin(player) + if (self:HasFlags(player, "o")) then + return true; + end; +end; + +-- A function to get whether a player can hear another player. +function Clockwork.player:CanHearPlayer(player, target, iAllowance) + if (cwCfg:Get("messages_must_see_player"):Get()) then + return self:CanSeePlayer(player, target, (iAllowance or 0.5), true); + else + return true; + end; +end; + +-- A functon to get all property. +function Clockwork.player:GetAllProperty() + for k, v in pairs(self.property) do + if (!IsValid(v)) then + self.property[k] = nil; + end; + end; + + return self.property; +end; + +-- A function to set a player's action. +function Clockwork.player:SetAction(player, action, duration, priority, Callback) + local currentAction = self:GetAction(player); + + if (type(action) != "string" or action == "") then + cwKernel:DestroyTimer("Action"..player:UniqueID()); + + player:SetSharedVar("StartActTime", 0); + player:SetSharedVar("ActDuration", 0); + player:SetSharedVar("ActName", ""); + + return; + elseif (duration == false or duration == 0) then + if (currentAction == action) then + return self:SetAction(player, false); + else + return false; + end; + end; + + if (player.cwAction) then + if ((priority and priority > player.cwAction[2]) + or currentAction == "" or action == player.cwAction[1]) then + player.cwAction = nil; + end; + end; + + if (!player.cwAction) then + local curTime = CurTime(); + + player:SetSharedVar("StartActTime", curTime); + player:SetSharedVar("ActDuration", duration); + player:SetSharedVar("ActName", action); + + if (priority) then + player.cwAction = {action, priority}; + else + player.cwAction = nil; + end; + + cwKernel:CreateTimer("Action"..player:UniqueID(), duration, 1, function() + if (Callback) then + Callback(); + end; + end); + end; +end; + +-- A function to set the player's character menu state. +function Clockwork.player:SetCharacterMenuState(player, state) + cwDatastream:Start(player, "CharacterMenu", state); +end; + +-- A function to get a player's action. +function Clockwork.player:GetAction(player, percentage) + local startActionTime = player:GetSharedVar("StartActTime"); + local actionDuration = player:GetSharedVar("ActDuration"); + local curTime = CurTime(); + local action = player:GetSharedVar("ActName"); + + if (startActionTime and CurTime() < startActionTime + actionDuration) then + if (percentage) then + return action, (100 / actionDuration) * (actionDuration - ((startActionTime + actionDuration) - curTime)); + else + return action, actionDuration, startActionTime; + end; + else + return "", 0, 0; + end; +end; + +-- A function to run a Clockwork command on a player. +function Clockwork.player:RunClockworkCommand(player, command, ...) + return cwCommand:ConsoleCommand(player, "cwCmd", {command, ...}); +end; + +-- A function to get a player's wages name. +function Clockwork.player:GetWagesName(player) + return cwClass:Query(player:Team(), "wagesName", cwCfg:Get("wages_name"):Get()); +end; + +-- A function to get whether a player can see an entity. +function Clockwork.player:CanSeeEntity(player, target, iAllowance, tIgnoreEnts) + if (player:GetEyeTraceNoCursor().Entity != target) then + return self:CanSeePosition(player, target:LocalToWorld(target:OBBCenter()), iAllowance, tIgnoreEnts, target); + else + return true; + end; +end; + +--[[ + Duplicate functions, keeping them like this for backward compatiblity. +--]] +Clockwork.player.CanSeePlayer = Clockwork.player.CanSeeEntity; +Clockwork.player.CanSeeNPC = Clockwork.player.CanSeeEntity; + +-- A function to get whether a player can see a position. +function Clockwork.player:CanSeePosition(player, position, iAllowance, tIgnoreEnts, targetEnt) + local trace = {}; + + trace.mask = CONTENTS_SOLID + CONTENTS_MOVEABLE + CONTENTS_OPAQUE + CONTENTS_DEBRIS + CONTENTS_HITBOX + CONTENTS_MONSTER; + trace.start = player:GetShootPos(); + trace.endpos = position; + trace.filter = {player, targetEnt}; + + if (tIgnoreEnts) then + if (type(tIgnoreEnts) == "table") then + table.Add(trace.filter, tIgnoreEnts); + else + table.Add(trace.filter, ents.GetAll()); + end; + end; + + trace = util.TraceLine(trace); + + if (trace.Fraction >= (iAllowance or 0.75)) then + return true; + end; +end; + +-- A function to update whether a player's weapon is raised. +function Clockwork.player:UpdateWeaponRaised(player) + local bIsRaised = self:GetWeaponRaised(player); + local weapon = player:GetActiveWeapon(); + + player:SetSharedVar("IsWepRaised", bIsRaised); + + if (IsValid(weapon)) then + cwKernel:HandleWeaponFireDelay(player, bIsRaised, weapon, CurTime()); + end; +end; + +-- A function to get whether a player's weapon is raised. +function Clockwork.player:GetWeaponRaised(player, bIsCached) + if (bIsCached) then + return player:GetSharedVar("IsWepRaised"); + end; + + local weapon = player:GetActiveWeapon(); + + if (IsValid(weapon) and !weapon.NeverRaised) then + if (weapon.GetRaised) then + local bIsRaised = weapon:GetRaised(); + + if (bIsRaised != nil) then + return bIsRaised; + end; + end; + + return cwPlugin:Call("GetPlayerWeaponRaised", player, weapon:GetClass(), weapon); + end; + + return false; +end; + +-- A function to toggle whether a player's weapon is raised. +function Clockwork.player:ToggleWeaponRaised(player) + self:SetWeaponRaised(player, !player.cwWeaponRaiseClass); +end; + +-- A function to set whether a player's weapon is raised. +function Clockwork.player:SetWeaponRaised(player, bIsRaised) + local weapon = player:GetActiveWeapon(); + + if (IsValid(weapon)) then + if (type(bIsRaised) == "number") then + player.cwAutoWepRaised = weapon:GetClass(); + player:UpdateWeaponRaised(); + + cwKernel:CreateTimer("WeaponRaised"..player:UniqueID(), bIsRaised, 1, function() + if (IsValid(player)) then + player.cwAutoWepRaised = nil; + player:UpdateWeaponRaised(); + end; + end); + elseif (bIsRaised) then + if (!player.cwWeaponRaiseClass) then + if (weapon.OnRaised) then + weapon:OnRaised(); + end; + end; + + player.cwWeaponRaiseClass = weapon:GetClass(); + player.cwAutoWepRaised = nil; + player:UpdateWeaponRaised(); + else + if (player.cwWeaponRaiseClass) then + if (weapon.OnLowered) then + weapon:OnLowered(); + end; + end; + + player.cwWeaponRaiseClass = nil; + player.cwAutoWepRaised = nil; + player:UpdateWeaponRaised(); + end; + end; +end; + +-- A function to setup a player's remove property delays. +function Clockwork.player:SetupRemovePropertyDelays(player, bAllCharacters) + local uniqueID = player:UniqueID(); + local key = player:GetCharacterKey(); + + for k, v in pairs(self:GetAllProperty()) do + local removeDelay = cwEntity:QueryProperty(v, "removeDelay"); + + if (IsValid(v) and removeDelay) then + if (uniqueID == cwEntity:QueryProperty(v, "uniqueID") + and (bAllCharacters or key == cwEntity:QueryProperty(v, "key"))) then + cwKernel:CreateTimer("RemoveDelay"..v:EntIndex(), removeDelay, 1, function(entity) + if (IsValid(entity)) then + entity:Remove(); + end; + end, v); + end; + end; + end; +end; + +-- A function to disable a player's property. +function Clockwork.player:DisableProperty(player, bCharacterOnly) + local uniqueID = player:UniqueID(); + local key = player:GetCharacterKey(); + + for k, v in pairs(self:GetAllProperty()) do + if (IsValid(v) and uniqueID == cwEntity:QueryProperty(v, "uniqueID") + and (!bCharacterOnly or key == cwEntity:QueryProperty(v, "key"))) then + cwEntity:SetPropertyVar(v, "owner", NULL); + + if (cwEntity:QueryProperty(v, "networked")) then + v:SetNetworkedEntity("Owner", NULL); + end; + + v:SetOwnerKey(nil); + v:SetNetworkedBool("Owned", false); + v:SetNetworkedInt("Key", 0); + + if (v.SetPlayer) then + v:SetVar("Founder", NULL); + v:SetVar("FounderIndex", 0); + v:SetNetworkedString("FounderName", ""); + end; + end; + end; +end; + +-- A function to give property to a player. +function Clockwork.player:GiveProperty(player, entity, networked, removeDelay) + cwKernel:DestroyTimer("RemoveDelay"..entity:EntIndex()); + cwEntity:ClearProperty(entity); + + entity.cwPropertyTab = { + key = player:GetCharacterKey(), + owner = player, + owned = true, + uniqueID = player:UniqueID(), + networked = networked, + removeDelay = removeDelay + }; + + if (entity.SetPlayer) then + entity:SetPlayer(player); + end; + + if (networked) then + entity:SetNetworkedEntity("Owner", player); + end; + + entity:SetOwnerKey(player:GetCharacterKey()); + entity:SetNetworkedBool("Owned", true); + + if (tonumber(entity.cwPropertyTab.key)) then + entity:SetNetworkedInt("Key", entity.cwPropertyTab.key); + end; + + self.property[entity:EntIndex()] = entity; + cwPlugin:Call("PlayerPropertyGiven", player, entity, networked, removeDelay); +end; + +-- A function to give property to an offline player. +function Clockwork.player:GivePropertyOffline(key, uniqueID, entity, networked, removeDelay) + cwEntity:ClearProperty(entity); + + if (key and uniqueID) then + local propertyUniqueID = cwEntity:QueryProperty(entity, "uniqueID"); + local owner = player.GetByUniqueID(uniqueID); + + if (IsValid(owner) and owner:GetCharacterKey() == key) then + self:GiveProperty(owner, entity, networked, removeDelay); + return; + else + owner = nil; + end; + + if (propertyUniqueID) then + cwKernel:DestroyTimer("RemoveDelay"..entity:EntIndex().." "..cwPropertyTabUniqueID); + end; + + entity.cwPropertyTab = { + key = key, + owner = owner, + owned = true, + uniqueID = uniqueID, + networked = networked, + removeDelay = removeDelay + }; + + if (IsValid(entity.cwPropertyTab.owner)) then + if (entity.SetPlayer) then + entity:SetPlayer(entity.cwPropertyTab.owner); + end; + + if (networked) then + entity:SetNetworkedEntity("Owner", entity.cwPropertyTab.owner); + end; + end; + + entity:SetNetworkedBool("Owned", true); + entity:SetNetworkedInt("Key", key); + entity:SetOwnerKey(key); + + self.property[entity:EntIndex()] = entity; + cwPlugin:Call("PlayerPropertyGivenOffline", key, uniqueID, entity, networked, removeDelay); + end; +end; + +-- A function to take property from an offline player. +function Clockwork.player:TakePropertyOffline(key, uniqueID, entity, bAnyCharacter) + if (key and uniqueID) then + local owner = player.GetByUniqueID(uniqueID); + + if (IsValid(owner) and owner:GetCharacterKey() == key) then + self:TakeProperty(owner, entity); + return; + end; + + if (cwEntity:QueryProperty(entity, "uniqueID") == uniqueID + and cwEntity:QueryProperty(entity, "key") == key) then + entity.cwPropertyTab = nil; + entity:SetNetworkedEntity("Owner", NULL); + entity:SetNetworkedBool("Owned", false); + entity:SetNetworkedInt("Key", 0); + entity:SetOwnerKey(nil); + + if (entity.SetPlayer) then + entity:SetVar("Founder", nil); + entity:SetVar("FounderIndex", nil); + entity:SetNetworkedString("FounderName", ""); + end; + + self.property[entity:EntIndex()] = nil; + cwPlugin:Call("PlayerPropertyTakenOffline", key, uniqueID, entity); + end; + end; +end; + +-- A function to take property from a player. +function Clockwork.player:TakeProperty(player, entity) + if (cwEntity:GetOwner(entity) == player) then + entity.cwPropertyTab = nil; + + entity:SetNetworkedEntity("Owner", NULL); + entity:SetNetworkedBool("Owned", false); + entity:SetNetworkedInt("Key", 0); + entity:SetOwnerKey(nil); + + if (entity.SetPlayer) then + entity:SetVar("Founder", nil); + entity:SetVar("FounderIndex", nil); + entity:SetNetworkedString("FounderName", ""); + end; + + self.property[entity:EntIndex()] = nil; + cwPlugin:Call("PlayerPropertyTaken", player, entity); + end; +end; + +-- A function to set a player to their default skin. +function Clockwork.player:SetDefaultSkin(player) + player:SetSkin(self:GetDefaultSkin(player)); +end; + +-- A function to get a player's default skin. +function Clockwork.player:GetDefaultSkin(player) + return cwPlugin:Call("GetPlayerDefaultSkin", player); +end; + +-- A function to set a player to their default model. +function Clockwork.player:SetDefaultModel(player) + player:SetModel(self:GetDefaultModel(player)); +end; + +-- A function to get a player's default model. +function Clockwork.player:GetDefaultModel(player) + return cwPlugin:Call("GetPlayerDefaultModel", player); +end; + +-- A function to get whether a player is drunk. +function Clockwork.player:GetDrunk(player) + if (player.cwDrunkTab) then return #player.cwDrunkTab; end; +end; + +-- A function to set whether a player is drunk. +function Clockwork.player:SetDrunk(player, expire) + local curTime = CurTime(); + + if (expire == false) then + player.cwDrunkTab = nil; + elseif (!player.cwDrunkTab) then + player.cwDrunkTab = {curTime + expire}; + else + player.cwDrunkTab[#player.cwDrunkTab + 1] = curTime + expire; + end; + + player:SetSharedVar("IsDrunk", self:GetDrunk(player) or 0); +end; + +-- A function to strip a player's default ammo. +function Clockwork.player:StripDefaultAmmo(player, weapon, itemTable) + if (!itemTable) then + itemTable = cwItem:GetByWeapon(weapon); + end; + + if (itemTable) then + local secondaryDefaultAmmo = itemTable("secondaryDefaultAmmo"); + local primaryDefaultAmmo = itemTable("primaryDefaultAmmo"); + + if (primaryDefaultAmmo) then + local ammoClass = weapon:GetPrimaryAmmoType(); + + if (weapon:Clip1() != -1) then + weapon:SetClip1(0); + end; + + if (type(primaryDefaultAmmo) == "number") then + player:SetAmmo( + math.max(player:GetAmmoCount(ammoClass) - primaryDefaultAmmo, 0), ammoClass + ); + end; + end; + + if (secondaryDefaultAmmo) then + local ammoClass = weapon:GetSecondaryAmmoType(); + + if (weapon:Clip2() != -1) then + weapon:SetClip2(0); + end; + + if (type(secondaryDefaultAmmo) == "number") then + player:SetAmmo( + math.max(player:GetAmmoCount(ammoClass) - secondaryDefaultAmmo, 0), ammoClass + ); + end; + end; + end; +end; + +-- A function to check if a player is whitelisted for a faction. +function Clockwork.player:IsWhitelisted(player, faction) + return table.HasValue(player:GetData("Whitelisted"), faction); +end; + +-- A function to set whether a player is whitelisted for a faction. +function Clockwork.player:SetWhitelisted(player, faction, isWhitelisted) + local whitelisted = player:GetData("Whitelisted"); + + if (isWhitelisted) then + if (!self:IsWhitelisted(player, faction)) then + whitelisted[table.Count(whitelisted) + 1] = faction; + end; + else + for k, v in pairs(whitelisted) do + if (v == faction) then + whitelisted[k] = nil; + end; + end; + end; + + cwDatastream:Start( + player, "SetWhitelisted", {faction, isWhitelisted} + ); +end; + +-- A function to create a Condition timer. +function Clockwork.player:ConditionTimer(player, delay, Condition, Callback) + local realDelay = CurTime() + delay; + local uniqueID = player:UniqueID(); + + if (player.cwConditionTimer) then + player.cwConditionTimer.Callback(false); + player.cwConditionTimer = nil; + end; + + player.cwConditionTimer = { + delay = realDelay, + Callback = Callback, + Condition = Condition + }; + + cwKernel:CreateTimer("CondTimer"..uniqueID, 0, 0, function() + if (!IsValid(player)) then + cwKernel:DestroyTimer("CondTimer"..uniqueID); + Callback(false); + return; + end; + + if (Condition()) then + if (CurTime() >= realDelay) then + Callback(true); player.cwConditionTimer = nil; + cwKernel:DestroyTimer("CondTimer"..uniqueID); + end; + else + Callback(false); player.cwConditionTimer = nil; + cwKernel:DestroyTimer("CondTimer"..uniqueID); + end; + end); +end; + +-- A function to create an entity Condition timer. +function Clockwork.player:EntityConditionTimer(player, target, entity, delay, distance, Condition, Callback) + local realEntity = entity or target; + local realDelay = CurTime() + delay; + local uniqueID = player:UniqueID(); + + if (player.cwConditionEntTimer) then + player.cwConditionEntTimer.Callback(false); + player.cwConditionEntTimer = nil; + end; + + player.cwConditionEntTimer = { + delay = realDelay, target = target, + entity = realEntity, distance = distance, + Callback = Callback, Condition = Condition + }; + + cwKernel:CreateTimer("EntityCondTimer"..uniqueID, 0, 0, function() + if (!IsValid(player)) then + cwKernel:DestroyTimer("EntityCondTimer"..uniqueID); + Callback(false); + return; + end; + + local traceLine = player:GetEyeTraceNoCursor(); + + if (IsValid(target) and IsValid(realEntity) and traceLine.Entity == realEntity + and traceLine.Entity:GetPos():Distance(player:GetShootPos()) <= distance + and Condition()) then + if (CurTime() >= realDelay) then + Callback(true); player.cwConditionEntTimer = nil; + cwKernel:DestroyTimer("EntityCondTimer"..uniqueID); + end; + else + Callback(false); player.cwConditionEntTimer = nil; + cwKernel:DestroyTimer("EntityCondTimer"..uniqueID); + end; + end); +end; + +-- A function to get a player's spawn ammo. +function Clockwork.player:GetSpawnAmmo(player, ammo) + if (ammo) then + return player.cwSpawnAmmo[ammo]; + else + return player.cwSpawnAmmo; + end; +end; + +-- A function to get a player's spawn weapon. +function Clockwork.player:GetSpawnWeapon(player, weapon) + if (weapon) then + return player.cwSpawnWeps[weapon]; + else + return player.cwSpawnWeps; + end; +end; + +-- A function to take spawn ammo from a player. +function Clockwork.player:TakeSpawnAmmo(player, ammo, amount) + if (player.cwSpawnAmmo[ammo]) then + if (player.cwSpawnAmmo[ammo] < amount) then + amount = player.cwSpawnAmmo[ammo]; + + player.cwSpawnAmmo[ammo] = nil; + else + player.cwSpawnAmmo[ammo] = player.cwSpawnAmmo[ammo] - amount; + end; + + player:RemoveAmmo(amount, ammo); + end; +end; + +-- A function to give the player spawn ammo. +function Clockwork.player:GiveSpawnAmmo(player, ammo, amount) + if (player.cwSpawnAmmo[ammo]) then + player.cwSpawnAmmo[ammo] = player.cwSpawnAmmo[ammo] + amount; + else + player.cwSpawnAmmo[ammo] = amount; + end; + + player:GiveAmmo(amount, ammo); +end; + +-- A function to take a player's spawn weapon. +function Clockwork.player:TakeSpawnWeapon(player, class) + player.cwSpawnWeps[class] = nil; + player:StripWeapon(class); +end; + +-- A function to give a player a spawn weapon. +function Clockwork.player:GiveSpawnWeapon(player, class) + player.cwSpawnWeps[class] = true; + player:Give(class); +end; + +-- A function to give a player an item weapon. +function Clockwork.player:GiveItemWeapon(player, itemTable) + if (cwItem:IsWeapon(itemTable)) then + player:Give(itemTable("weaponClass"), itemTable); + return true; + end; +end; + +-- A function to give a player a spawn item weapon. +function Clockwork.player:GiveSpawnItemWeapon(player, itemTable) + if (cwItem:IsWeapon(itemTable)) then + player.cwSpawnWeps[itemTable("weaponClass")] = true; + player:Give(itemTable("weaponClass"), itemTable); + + return true; + end; +end; + +-- A function to give flags to a character. +function Clockwork.player:GiveFlags(player, flags) + for i = 1, #flags do + local flag = string.utf8sub(flags, i, i); + + if (!string.find(player:GetFlags(), flag)) then + player:SetCharacterData("Flags", player:GetFlags()..flag, true); + + cwPlugin:Call("PlayerFlagsGiven", player, flag); + end; + end; +end; + +-- A function to give flags to a player. +function Clockwork.player:GivePlayerFlags(player, flags) + for i = 1, #flags do + local flag = string.utf8sub(flags, i, i); + + if (!string.find(player:GetPlayerFlags(), flag)) then + player:SetData("Flags", player:GetPlayerFlags()..flag, true); + + cwPlugin:Call("PlayerFlagsGiven", player, flag); + end; + end; +end; + +-- A function to play a sound to a player. +function Clockwork.player:PlaySound(player, sound) + cwDatastream:Start(player, "PlaySound",sound); +end; + +-- A function to get a player's maximum characters. +function Clockwork.player:GetMaximumCharacters(player) + local maximum = cwCfg:Get("additional_characters"):Get(); + + for k, v in pairs(cwFaction:GetAll()) do + if (!v.whitelist or self:IsWhitelisted(player, v.name)) then + maximum = maximum + 1; + end; + end; + + return maximum; +end; + +-- A function to query a player's character. +function Clockwork.player:Query(player, key, default) + local character = player:GetCharacter(); + + if (character) then + key = cwKernel:SetCamelCase(key, true); + + if (character[key] != nil) then + return character[key]; + end; + end; + + return default; +end; + +-- A function to set a player to a safe position. +function Clockwork.player:SetSafePosition(player, position, filter) + position = self:GetSafePosition(player, position, filter); + + if (position) then + player:SetMoveType(MOVETYPE_NOCLIP); + player:SetPos(position); + + if (player:IsInWorld()) then + player:SetMoveType(MOVETYPE_WALK); + else + player:Spawn(); + end; + end; +end; + +-- A function to get the safest position near a position. +function Clockwork.player:GetSafePosition(player, position, filter) + local closestPosition = nil; + local distanceAmount = 8; + local directions = {}; + local yawForward = player:EyeAngles().yaw; + local angles = { + math.NormalizeAngle(yawForward - 180), + math.NormalizeAngle(yawForward - 135), + math.NormalizeAngle(yawForward + 135), + math.NormalizeAngle(yawForward + 45), + math.NormalizeAngle(yawForward + 90), + math.NormalizeAngle(yawForward - 45), + math.NormalizeAngle(yawForward - 90), + math.NormalizeAngle(yawForward) + }; + + position = position + Vector(0, 0, 32); + + if (!filter) then + filter = {player}; + elseif (type(filter) != "table") then + filter = {filter}; + end; + + if (!table.HasValue(filter, player)) then + filter[#filter + 1] = player; + end; + + for i = 1, 8 do + for k, v in pairs(angles) do + directions[#directions + 1] = {v, distanceAmount}; + end; + + distanceAmount = distanceAmount * 2; + end; + + -- A function to get a lower position. + local function GetLowerPosition(testPosition, ignoreHeight) + local trace = { + filter = filter, + endpos = testPosition - Vector(0, 0, 256), + start = testPosition + }; + + return util.TraceLine(trace).HitPos + Vector(0, 0, 32); + end; + + local trace = { + filter = filter, + endpos = position + Vector(0, 0, 256), + start = position + }; + + local safePosition = GetLowerPosition(util.TraceLine(trace).HitPos); + + if (safePosition) then + position = safePosition; + end; + + for k, v in pairs(directions) do + local angleVector = Angle(0, v[1], 0):Forward(); + local testPosition = position + (angleVector * v[2]); + + local trace = { + filter = filter, + endpos = testPosition, + start = position + }; + + local traceLine = util.TraceEntity(trace, player); + + if (traceLine.Hit) then + trace = { + filter = filter, + endpos = traceLine.HitPos - (angleVector * v[2]), + start = traceLine.HitPos + }; + + traceLine = util.TraceEntity(trace, player); + + if (!traceLine.Hit) then + position = traceLine.HitPos; + end; + end; + + if (!traceLine.Hit) then + break; + end; + end; + + for k, v in pairs(directions) do + local angleVector = Angle(0, v[1], 0):Forward(); + local testPosition = position + (angleVector * v[2]); + + local trace = { + filter = filter, + endpos = testPosition, + start = position + }; + + local traceLine = util.TraceEntity(trace, player); + + if (!traceLine.Hit) then + return traceLine.HitPos; + end; + end; + + return position; +end; + +-- Called to convert a player's data to a string. +function Clockwork.player:ConvertDataString(player, data) + local bSuccess, value = pcall(cwJson.Decode, cwJson, data); + + if (bSuccess and value != nil) then + return value; + else + return {}; + end; +end; + +-- A function to return a player's property. +function Clockwork.player:ReturnProperty(player) + local uniqueID = player:UniqueID(); + local key = player:GetCharacterKey(); + + for k, v in pairs(self:GetAllProperty()) do + if (IsValid(v)) then + if (uniqueID == cwEntity:QueryProperty(v, "uniqueID")) then + if (key == cwEntity:QueryProperty(v, "key")) then + self:GiveProperty(player, v, cwEntity:QueryProperty(v, "networked")); + end; + end; + end; + end; + + cwPlugin:Call("PlayerReturnProperty", player); +end; + +-- A function to take flags from a character. +function Clockwork.player:TakeFlags(player, flags) + for i = 1, #flags do + local flag = string.utf8sub(flags, i, i); + + if (string.find(player:GetFlags(), flag)) then + player:SetCharacterData("Flags", string.gsub(player:GetFlags(), flag, ""), true); + + cwPlugin:Call("PlayerFlagsTaken", player, flag); + end; + end; +end; + +-- A function to take flags from a player. +function Clockwork.player:TakePlayerFlags(player, flags) + for i = 1, #flags do + local flag = string.utf8sub(flags, i, i); + + if (string.find(player:GetPlayerFlags(), flag)) then + player:SetData("Flags", string.gsub(player:GetFlags(), flag, ""), true); + + cwPlugin:Call("PlayerFlagsTaken", player, flag); + end; + end; +end; + +-- A function to set whether a player's menu is open. +function Clockwork.player:SetMenuOpen(player, isOpen) + cwDatastream:Start(player, "MenuOpen", isOpen); +end; + +-- A function to set whether a player has intialized. +function Clockwork.player:SetInitialized(player, initialized) + player:SetSharedVar("Initialized", initialized); +end; + +-- A function to check if a player has any flags. +function Clockwork.player:HasAnyFlags(player, flags, bByDefault) + if (player:GetCharacter()) then + local playerFlags = player:GetFlags(); + + if (cwClass:HasAnyFlags(player:Team(), flags) and !bByDefault) then + return true; + end; + + for i = 1, #flags do + local flag = string.utf8sub(flags, i, i); + local bSuccess = true; + + if (!bByDefault) then + local hasFlag = cwPlugin:Call("PlayerDoesHaveFlag", player, flag); + + if (hasFlag != false) then + if (hasFlag) then + return true; + end; + else + bSuccess = nil; + end; + end; + + if (bSuccess) then + if (flag == "s") then + if (player:IsSuperAdmin()) then + return true; + end; + elseif (flag == "a") then + if (player:IsAdmin()) then + return true; + end; + elseif (flag == "o") then + if (player:IsSuperAdmin() or player:IsAdmin()) then + return true; + elseif (player:IsUserGroup("operator")) then + return true; + end; + elseif (string.find(playerFlags, flag)) then + return true; + end; + end; + end; + end; +end; + +-- A function to check if a player has flags. +function Clockwork.player:HasFlags(player, flags, bByDefault) + if (player:GetCharacter()) then + local playerFlags = player:GetFlags(); + + if (cwClass:HasFlags(player:Team(), flags) and !bByDefault) then + return true; + end; + + for i = 1, #flags do + local flag = string.utf8sub(flags, i, i); + local bSuccess; + + if (!bByDefault) then + local hasFlag = cwPlugin:Call("PlayerDoesHaveFlag", player, flag); + + if (hasFlag != false) then + if (hasFlag) then + bSuccess = true; + end; + else + return; + end; + end; + + if (!bSuccess) then + if (flag == "s") then + if (!player:IsSuperAdmin()) then + return; + end; + elseif (flag == "a") then + if (!player:IsAdmin()) then + return; + end; + elseif (flag == "o") then + if (!player:IsSuperAdmin() and !player:IsAdmin()) then + if (!player:IsUserGroup("operator")) then + return; + end; + end; + elseif (!string.find(playerFlags, flag)) then + return; + end; + end; + end; + + return true; + end; +end; + +-- A function to use a player's death code. +function Clockwork.player:UseDeathCode(player, commandTable, arguments) + cwPlugin:Call("PlayerDeathCodeUsed", player, commandTable, arguments); + + self:TakeDeathCode(player); +end; + +-- A function to get whether a player has a death code. +function Clockwork.player:GetDeathCode(player, authenticated) + if (player.cwDeathCodeIdx and (!authenticated or player.cwDeathCodeAuth)) then + return player.cwDeathCodeIdx; + end; +end; + +-- A function to take a player's death code. +function Clockwork.player:TakeDeathCode(player) + player.cwDeathCodeAuth = nil; + player.cwDeathCodeIdx = nil; +end; + +-- A function to give a player their death code. +function Clockwork.player:GiveDeathCode(player) + player.cwDeathCodeIdx = math.random(0, 99999); + player.cwDeathCodeAuth = nil; + + cwDatastream:Start(player, "ChatBoxDeathCode", player.cwDeathCodeIdx); +end; + +-- A function to take a door from a player. +function Clockwork.player:TakeDoor(player, door, bForce, bThisDoorOnly, bChildrenOnly) + local doorCost = cwCfg:Get("door_cost"):Get(); + + if (!bThisDoorOnly) then + local doorParent = cwEntity:GetDoorParent(door); + + if (!doorParent or bChildrenOnly) then + for k, v in pairs(cwEntity:GetDoorChildren(door)) do + if (IsValid(v)) then + self:TakeDoor(player, v, true, true); + end; + end; + else + return self:TakeDoor(player, doorParent, bForce); + end; + end; + + if (cwPlugin:Call("PlayerCanUnlockEntity", player, door)) then + door:Fire("Unlock", "", 0); + door:EmitSound("doors/door_latch3.wav"); + end; + + cwEntity:SetDoorText(door, false); + self:TakeProperty(player, door); + + cwPlugin:Call("PlayerDoorTaken", player, door) + + if (door:GetClass() == "prop_dynamic") then + if (!door:IsMapEntity()) then + door:Remove(); + end; + end; + + if (!force and doorCost > 0) then + self:GiveCash(player, doorCost / 2, "selling a door"); + end; +end; + +-- A function to make a player say text as a radio broadcast. +function Clockwork.player:SayRadio(player, text, check, noEavesdrop) + local eavesdroppers = {}; + local listeners = {}; + local canRadio = true; + local info = {listeners = {}, noEavesdrop = noEavesdrop, text = text}; + + cwPlugin:Call("PlayerAdjustRadioInfo", player, info); + + for k, v in pairs(info.listeners) do + if (type(k) == "Player") then + listeners[k] = k; + elseif (type(v) == "Player") then + listeners[v] = v; + end; + end; + + if (!info.noEavesdrop) then + for k, v in pairs(cwPlayer.GetAll()) do + if (v:HasInitialized() and !listeners[v]) then + if (v:GetShootPos():Distance(player:GetShootPos()) <= cwCfg:Get("talk_radius"):Get()) then + eavesdroppers[v] = v; + end; + end; + end; + end; + + if (check) then + canRadio = cwPlugin:Call("PlayerCanRadio", player, info.text, listeners, eavesdroppers); + end; + + if (canRadio) then + info = cwChatbox:Add(listeners, player, "radio", info.text); + + if (info and IsValid(info.speaker)) then + cwChatbox:Add(eavesdroppers, info.speaker, "radio_eavesdrop", info.text); + + cwPlugin:Call("PlayerRadioUsed", player, info.text, listeners, eavesdroppers); + end; + end; +end; + +-- A function to get a player's faction table. +function Clockwork.player:GetFactionTable(player) + return cwFaction:GetAll()[player:GetFaction()]; +end; + +-- A function to give a door to a player. +function Clockwork.player:GiveDoor(player, door, name, unsellable, override) + if (cwEntity:IsDoor(door)) then + local doorParent = cwEntity:GetDoorParent(door); + + if (doorParent and !override) then + self:GiveDoor(player, doorParent, name, unsellable); + else + for k, v in pairs(cwEntity:GetDoorChildren(door)) do + if (IsValid(v)) then + self:GiveDoor(player, v, name, unsellable, true); + end; + end; + + door.unsellable = unsellable; + door.accessList = {}; + + cwEntity:SetDoorText(door, name or "A purchased door."); + self:GiveProperty(player, door, true); + + cwPlugin:Call("PlayerDoorGiven", player, door) + + if (cwPlugin:Call("PlayerCanUnlockEntity", player, door)) then + door:EmitSound("doors/door_latch3.wav"); + door:Fire("Unlock", "", 0); + end; + end; + end; +end; + +-- A function to get a player's real trace. +function Clockwork.player:GetRealTrace(player, useFilterTrace) + local eyePos = player:EyePos(); + local trace = player:GetEyeTraceNoCursor(); + + local newTrace = util.TraceLine({ + endpos = eyePos + (player:GetAimVector() * 4096), + filter = player, + start = eyePos, + mask = CONTENTS_SOLID + CONTENTS_MOVEABLE + CONTENTS_OPAQUE + CONTENTS_DEBRIS + CONTENTS_HITBOX + CONTENTS_MONSTER + }); + + if ((IsValid(newTrace.Entity) and (!IsValid(trace.Entity) + or trace.Entity:IsVehicle()) and !newTrace.HitWorld) or useFilterTrace) then + trace = newTrace; + end; + + return trace; +end; + +-- A function to check if a player recognises another player. +function Clockwork.player:DoesRecognise(player, target, status, isAccurate) + if (!status) then + return self:DoesRecognise(player, target, RECOGNISE_PARTIAL); + elseif (cwCfg:Get("recognise_system"):Get()) then + local recognisedNames = player:GetRecognisedNames(); + local realValue = false; + local key = target:GetCharacterKey(); + + if (recognisedNames and recognisedNames[key]) then + if (isAccurate) then + realValue = (recognisedNames[key] == status); + else + realValue = (recognisedNames[key] >= status); + end; + end; + + return cwPlugin:Call("PlayerDoesRecognisePlayer", player, target, status, isAccurate, realValue); + else + return true; + end; +end; + +-- A function to send a player a creation fault. +function Clockwork.player:SetCreateFault(player, fault) + if (!fault) then + fault = "There has been an unknown error, please contact the administrator!"; + end; + + cwDatastream:Start(player, "CharacterFinish", {bSuccess = false, fault = fault}); +end; + +-- A function to force a player to delete a character. +function Clockwork.player:ForceDeleteCharacter(player, characterID) + local charactersTable = cwCfg:Get("mysql_characters_table"):Get(); + local schemaFolder = cwKernel:GetSchemaFolder(); + local character = player.cwCharacterList[characterID]; + + if (character) then + local queryObj = cwDatabase:Delete(charactersTable); + queryObj:AddWhere("_Schema = ?", schemaFolder); + queryObj:AddWhere("_SteamID = ?", player:SteamID()); + queryObj:AddWhere("_CharacterID = ?", characterID); + queryObj:Push(); + + if (!cwPlugin:Call("PlayerDeleteCharacter", player, character)) then + cwKernel:PrintLog(LOGTYPE_GENERIC, player:SteamName().." has deleted the character '"..character.name.."'."); + end; + + player.cwCharacterList[characterID] = nil; + + cwDatastream:Start(player, "CharacterRemove", characterID); + end; +end; + +-- A function to delete a player's character. +function Clockwork.player:DeleteCharacter(player, characterID) + local character = player.cwCharacterList[characterID]; + + if (character) then + if (player:GetCharacter() != character) then + local fault = cwPlugin:Call("PlayerCanDeleteCharacter", player, character); + + if (fault == nil or fault == true) then + self:ForceDeleteCharacter(player, characterID); + + return true; + elseif (type(fault) != "string") then + return false, "You cannot delete this character!"; + else + return false, fault; + end; + else + return false, "You cannot delete the character you are using!"; + end; + else + return false, "This character does not exist!"; + end; +end; + +-- A function to use a player's character. +function Clockwork.player:UseCharacter(player, characterID) + local isCharacterMenuReset = player:IsCharacterMenuReset(); + local currentCharacter = player:GetCharacter(); + local character = player.cwCharacterList[characterID]; + + if (!character) then + return false, "This character does not exist!"; + end; + + if (currentCharacter != character or isCharacterMenuReset) then + local factionTable = cwFaction:FindByID(character.faction); + local fault = cwPlugin:Call("PlayerCanUseCharacter", player, character); + + if (fault == nil or fault == true) then + local players = #cwFaction:GetPlayers(character.faction); + local limit = cwFaction:GetLimit(factionTable.name); + + if (isCharacterMenuReset and character.faction == currentCharacter.faction) then + players = players - 1; + end; + + if (cwPlugin:Call("PlayerCanBypassFactionLimit", player, character)) then + limit = nil; + end; + + if (limit and players == limit) then + return false, "The "..character.faction.." faction is full ("..limit.."/"..limit..")!"; + else + if (currentCharacter) then + local fault = cwPlugin:Call("PlayerCanSwitchCharacter", player, character); + + if (fault != nil and fault != true) then + return false, fault or "You cannot switch to this character!"; + end; + end; + + cwKernel:PrintLog(LOGTYPE_GENERIC, player:SteamName().." has loaded the character '"..character.name.."'."); + + if (isCharacterMenuReset) then + player.cwCharMenuReset = false; + player:Spawn(); + else + self:LoadCharacter(player, characterID); + end; + + return true; + end; + else + return false, fault or "You cannot use this character!"; + end; + else + return false, "You are already using this character!"; + end; +end; + +-- A function to get a player's character. +function Clockwork.player:GetCharacter(player) + return player.cwCharacter; +end; + +-- A function to get a player's unrecognised name. +function Clockwork.player:GetUnrecognisedName(player, bFormatted) + local unrecognisedPhysDesc = self:GetPhysDesc(player); + local unrecognisedName = cwCfg:Get("unrecognised_name"):Get(); + local usedPhysDesc = false; + + if (unrecognisedPhysDesc != "") then + unrecognisedName = unrecognisedPhysDesc; + usedPhysDesc = true; + end; + + if (bFormatted) then + if (string.utf8len(unrecognisedName) > 24) then + unrecognisedName = string.utf8sub(unrecognisedName, 1, 21).."..."; + end; + + unrecognisedName = "["..unrecognisedName.."]"; + end; + + return unrecognisedName, usedPhysDesc; +end; + +-- A function to format text based on a relationship. +function Clockwork.player:FormatRecognisedText(player, text, ...) + local arguments = {...}; + + for i = 1, #arguments do + if (string.find(text, "%%s") and IsValid(arguments[i])) then + local unrecognisedName = "["..self:GetUnrecognisedName(arguments[i]).."]"; + + if (self:DoesRecognise(player, arguments[i])) then + unrecognisedName = arguments[i]:Name(); + end; + + text = string.gsub(text, "%%s", unrecognisedName, 1); + end; + end; + + return text; +end; + +-- A function to restore a recognised name. +function Clockwork.player:RestoreRecognisedName(player, target) + local recognisedNames = player:GetRecognisedNames(); + local key = target:GetCharacterKey(); + + if (recognisedNames[key]) then + if (cwPlugin:Call("PlayerCanRestoreRecognisedName", player, target)) then + self:SetRecognises(player, target, recognisedNames[key], true); + else + recognisedNames[key] = nil; + end; + end; +end; + +-- A function to restore a player's recognised names. +function Clockwork.player:RestoreRecognisedNames(player) + cwDatastream:Start(player, "ClearRecognisedNames", true); + + if (cwCfg:Get("save_recognised_names"):Get()) then + for k, v in pairs(cwPlayer.GetAll()) do + if (v:HasInitialized()) then + self:RestoreRecognisedName(player, v); + self:RestoreRecognisedName(v, player); + end; + end; + end; +end; + +-- A function to set whether a player recognises a player. +function Clockwork.player:SetRecognises(player, target, status, bForce) + local recognisedNames = player:GetRecognisedNames(); + local name = target:Name(); + local key = target:GetCharacterKey(); + + --[[ I have no idea why this would happen. --]] + if (key == nil) then return end; + + if (status == RECOGNISE_SAVE) then + if (cwCfg:Get("save_recognised_names"):Get()) then + if (!cwPlugin:Call("PlayerCanSaveRecognisedName", player, target)) then + status = RECOGNISE_TOTAL; + end; + else + status = RECOGNISE_TOTAL; + end; + end; + + if (!status or bForce or !self:DoesRecognise(player, target, status)) then + recognisedNames[key] = status or nil; + + cwDatastream:Start(player, "RecognisedName", { + key = key, status = (status or 0) + }); + end; +end; + +-- A function to get a player's physical description. +function Clockwork.player:GetPhysDesc(player) + local physDesc = player:GetSharedVar("PhysDesc"); + local team = player:Team(); + + if (physDesc == "") then + physDesc = cwClass:Query(team, "defaultPhysDesc", ""); + end; + + if (physDesc == "") then + physDesc = cwCfg:Get("default_physdesc"):Get(); + end; + + if (!physDesc or physDesc == "") then + physDesc = "This character has no physical description set."; + else + physDesc = cwKernel:ModifyPhysDesc(physDesc); + end; + + local override = cwPlugin:Call("GetPlayerPhysDescOverride", player, physDesc); + + if (override) then + physDesc = override; + end; + + return physDesc; +end; + +-- A function to clear a player's recognised names list. +function Clockwork.player:ClearRecognisedNames(player, status, isAccurate) + if (!status) then + local character = player:GetCharacter(); + + if (character) then + character.recognisedNames = {}; + + cwDatastream:Start(player, "ClearRecognisedNames", true); + end; + else + for k, v in pairs(cwPlayer.GetAll()) do + if (v:HasInitialized()) then + if (self:DoesRecognise(player, v, status, isAccurate)) then + self:SetRecognises(player, v, false); + end; + end; + end; + end; + + cwPlugin:Call("PlayerRecognisedNamesCleared", player, status, isAccurate); +end; + +-- A function to clear a player's name from being recognised. +function Clockwork.player:ClearName(player, status, isAccurate) + for k, v in pairs(cwPlayer.GetAll()) do + if (v:HasInitialized()) then + if (!status or self:DoesRecognise(v, player, status, isAccurate)) then + self:SetRecognises(v, player, false); + end; + end; + end; + + cwPlugin:Call("PlayerNameCleared", player, status, isAccurate); +end; + +-- A function to holsters all of a player's weapons. +function Clockwork.player:HolsterAll(player) + for k, v in pairs(player:GetWeapons()) do + local class = v:GetClass(); + local itemTable = cwItem:GetByWeapon(v); + + if (itemTable and cwPlugin:Call("PlayerCanHolsterWeapon", player, itemTable, v, true, true)) then + cwPlugin:Call("PlayerHolsterWeapon", player, itemTable, v, true); + player:StripWeapon(class); + player:GiveItem(itemTable, true); + end; + end; + + player:SelectWeapon("cw_hands"); +end; + +-- A function to set a shared variable for a player. +function Clockwork.player:SetSharedVar(player, key, value, sharedTable) + if (IsValid(player)) then + if (!sharedTable) then + local sharedVars = cwKernel:GetSharedVars():Player(); + + if (!sharedVars) then + MsgC(Color(255, 100, 0, 255), "[Clockwork:PlayerSharedVars] Couldn't get the sharedVars table.\n"); + return; + elseif (not sharedVars[key]) then + MsgC(Color(255, 100, 0, 255), "[Clockwork:PlayerSharedVars] Couldn't find key '"..key.."' in sharedVars table. Is it registered?\n"); + return; + end; + + local sharedVarData = sharedVars[key]; + + if (sharedVarData.bPlayerOnly) then + local realValue = value; + + if (value == nil) then + realValue = cwKernel:GetDefaultNetworkedValue(sharedVarData.class); + end; + + if (player.cwSharedVars[key] != realValue) then + player.cwSharedVars[key] = realValue; + + cwDatastream:Start(player, "SharedVar", {key = key, value = realValue}); + end; + else + local class = cwKernel:ConvertNetworkedClass(sharedVarData.class); + + if (class) then + if (value == nil) then + value = cwKernel:GetDefaultClassValue(class); + end; + + player["SetNetworked"..class](player, key, value); + else + MsgC(Color(255, 100, 0, 255), "[Clockwork:PlayerSharedVars] Couldn't find network class for key '"..key.."'."); + end; + end; + else + cwDatastream:Start(player, "SetSharedTableVar", {sharedTable = sharedTable, key = key, value = value}) + end; + end; +end; + +-- A function to get a player's shared variable. +function Clockwork.player:GetSharedVar(player, key) + if (IsValid(player)) then + local sharedVars = cwKernel:GetSharedVars():Player(); + + if (!sharedVars) then + MsgC(Color(255, 100, 0, 255), "[Clockwork:PlayerSharedVars] Couldn't get the sharedVars table.\n"); + return; + elseif (not sharedVars[key]) then + MsgC(Color(255, 100, 0, 255), "[Clockwork:PlayerSharedVars] Couldn't find key '"..key.."' in sharedVars table. Is it registered?\n"); + return; + end; + + local sharedVarData = sharedVars[key]; + + if (sharedVarData.bPlayerOnly) then + if (!player.cwSharedVars[key]) then + return cwKernel:GetDefaultNetworkedValue(sharedVarData.class); + else + return player.cwSharedVars[key]; + end; + else + local class = cwKernel:ConvertNetworkedClass(sharedVarData.class); + + if (class) then + return player["GetNetworked"..class](player, key); + else + MsgC(Color(255, 100, 0, 255), "[Clockwork:PlayerSharedVars] Couldn't find network class for key '"..key.."'."); + end; + end; + end; +end; + +-- A function to set whether a player's character is banned. +function Clockwork.player:SetBanned(player, banned) + player:SetCharacterData("CharBanned", banned); + player:SaveCharacter(); + player:SetSharedVar("CharBanned", banned); +end; + +-- A function to set a player's name. +function Clockwork.player:SetName(player, name, saveless) + local previousName = player:Name(); + local newName = name; + + player:SetCharacterData("Name", newName, true); + player:SetSharedVar("Name", newName); + + if (!player.cwFirstSpawn) then + cwPlugin:Call("PlayerNameChanged", player, previousName, newName); + end; + + if (!saveless) then + player:SaveCharacter(); + end; +end; + +-- A function to get a player's generator count. +function Clockwork.player:GetGeneratorCount(player) + local generators = cwGenerator:GetAll(); + local count = 0; + + for k, v in pairs(generators) do + count = count + self:GetPropertyCount(player, k); + end; + + return count; +end; + +-- A function to get a player's property entities. +function Clockwork.player:GetPropertyEntities(player, class) + local uniqueID = player:UniqueID(); + local entities = {}; + local key = player:GetCharacterKey(); + + for k, v in pairs(self:GetAllProperty()) do + if (uniqueID == cwEntity:QueryProperty(v, "uniqueID")) then + if (key == cwEntity:QueryProperty(v, "key")) then + if (!class or v:GetClass() == class) then + entities[#entities + 1] = v; + end; + end; + end; + end; + + return entities; +end; + +-- A function to get a player's property count. +function Clockwork.player:GetPropertyCount(player, class) + local uniqueID = player:UniqueID(); + local count = 0; + local key = player:GetCharacterKey(); + + for k, v in pairs(self:GetAllProperty()) do + if (uniqueID == cwEntity:QueryProperty(v, "uniqueID")) then + if (key == cwEntity:QueryProperty(v, "key")) then + if (!class or v:GetClass() == class) then + count = count + 1; + end; + end; + end; + end; + + return count; +end; + +-- A function to get a player's door count. +function Clockwork.player:GetDoorCount(player) + local uniqueID = player:UniqueID(); + local count = 0; + local key = player:GetCharacterKey(); + + for k, v in pairs(self:GetAllProperty()) do + if (cwEntity:IsDoor(v) and !cwEntity:GetDoorParent(v)) then + if (uniqueID == cwEntity:QueryProperty(v, "uniqueID")) then + if (player:GetCharacterKey() == cwEntity:QueryProperty(v, "key")) then + count = count + 1; + end; + end; + end; + end; + + return count; +end; + +-- A function to take a player's door access. +function Clockwork.player:TakeDoorAccess(player, door) + if (door.accessList) then + door.accessList[player:GetCharacterKey()] = false; + end; +end; + +-- A function to give a player door access. +function Clockwork.player:GiveDoorAccess(player, door, access) + local key = player:GetCharacterKey(); + + if (!door.accessList) then + door.accessList = { + [key] = access + }; + else + door.accessList[key] = access; + end; +end; + +-- A function to check if a player has door access. +function Clockwork.player:HasDoorAccess(player, door, access, isAccurate) + if (!access) then + return self:HasDoorAccess(player, door, DOOR_ACCESS_BASIC, isAccurate); + else + local doorParent = cwEntity:GetDoorParent(door); + local key = player:GetCharacterKey(); + + if (doorParent and cwEntity:DoorHasSharedAccess(doorParent) + and (!door.accessList or door.accessList[key] == nil)) then + return cwPlugin:Call("PlayerDoesHaveDoorAccess", player, doorParent, access, isAccurate); + else + return cwPlugin:Call("PlayerDoesHaveDoorAccess", player, door, access, isAccurate); + end; + end; +end; + +-- A function to check if a player can afford an amount. +function Clockwork.player:CanAfford(player, amount) + if (cwCfg:Get("cash_enabled"):Get()) then + return (player:GetCash() >= amount); + else + return true; + end; +end; + +-- A function to give a player an amount of cash. +function Clockwork.player:GiveCash(player, amount, reason, bNoMsg) + if (cwCfg:Get("cash_enabled"):Get()) then + local positiveHintColor = "positive_hint"; + local negativeHintColor = "negative_hint"; + local roundedAmount = math.Round(amount); + local cash = math.Round(math.max(player:GetCash() + roundedAmount, 0)); + + player:SetCharacterData("Cash", cash, true); + player:SetSharedVar("Cash", cash); + + if (roundedAmount < 0) then + roundedAmount = math.abs(roundedAmount); + + if (!bNoMsg) then + if (reason) then + cwHint:Send( + player, "Your character has lost the sum of "..cwKernel:FormatCash(roundedAmount).." ("..reason..").", 4, negativeHintColor + ); + else + cwHint:Send( + player, "Your character has lost the sum of "..cwKernel:FormatCash(roundedAmount)..".", 4, negativeHintColor + ); + end; + end; + elseif (roundedAmount > 0) then + if (!bNoMsg) then + if (reason) then + cwHint:Send( + player, "Your character has gained the sum of "..cwKernel:FormatCash(roundedAmount).." ("..reason..").", 4, positiveHintColor + ); + else + cwHint:Send( + player, "Your character has gained the sum of "..cwKernel:FormatCash(roundedAmount)..".", 4, positiveHintColor + ); + end; + end; + end; + + cwPlugin:Call("PlayerCashUpdated", player, roundedAmount, reason, bNoMsg); + end; +end; + +Clockwork.player:AddToMetaTable("Player", "GiveCash"); + +-- A function to show cinematic text to a player. +function Clockwork.player:CinematicText(player, text, color, barLength, hangTime) + cwDatastream:Start(player, "CinematicText", { + text = text, + color = color, + barLength = barLength, + hangTime = hangTime + }); +end; + +-- A function to show cinematic text to each player. +function Clockwork.player:CinematicTextAll(text, color, hangTime) + for k, v in pairs(cwPlayer.GetAll()) do + if (v:HasInitialized()) then + self:CinematicText(v, text, color, hangTime); + end; + end; +end; + +-- A function to find a player by an identifier. +function Clockwork.player:FindByID(identifier) + for k, v in pairs(player.GetAll()) do + if (v:HasInitialized() and (v:SteamID() == identifier or v:UniqueID() == identifier + or string.find(string.lower(v:Name()), string.lower(identifier), 1, true))) then + return v; + end; + end; +end; + +-- A function to get if a player is protected. +function Clockwork.player:IsProtected(identifier) + local steamID = nil; + local ownerSteamID = cwCfg:Get("owner_steamid"):Get(); + local bSuccess, value = pcall(IsValid, identifier); + + if (!bSuccess or value == false) then + local playerObj = self:FindByID(identifier); + + if (IsValid(playerObj)) then + steamID = playerObj:SteamID(); + end; + else + steamID = identifier:SteamID(); + end; + + if (string.find(ownerSteamID, ",")) then + ownerSteamID = string.gsub(ownerSteamID, " ", ""); + ownerSteamID = string.Split(ownerSteamID, ","); + + for k, v in pairs(ownerSteamID) do + if (steamID and steamID == v) then + return true; + end; + end; + else + if (steamID and steamID == ownerSteamID) then + return true; + end; + end; + + return false; +end; + +-- A function to notify each player in a radius. +function Clockwork.player:NotifyInRadius(text, class, position, radius) + local listeners = {}; + + for k, v in pairs(cwPlayer.GetAll()) do + if (v:HasInitialized()) then + if (position:Distance(v:GetPos()) <= radius) then + listeners[#listeners + 1] = v; + end; + end; + end; + + self:Notify(listeners, text, class); +end; + +-- A function to notify each player. +function Clockwork.player:NotifyAll(text, icon) + self:Notify(nil, text, true, icon); +end; + +--[[ + @codebase Server + @details A function to notify admins by rank. + @param String The rank and up that will be notified. + @param String The text that will be sent to each admin. + @param String The name of the icon that will be used in the message, can be nil. +--]] +function Clockwork.player:NotifyAdmins(adminLevel, text, icon) + for k, v in pairs(player.GetAll()) do + if (adminLevel == "operator" or adminLevel == "o") then + if (v:IsAdmin()) then + self:Notify(v, text, true, icon); + end; + elseif (adminLevel == "admin" or adminLevel == "a") then + if (v:IsAdmin() and !v:IsUserGroup("operator")) then + self:Notify(v, text, true, icon); + end; + elseif (adminLevel == "superadmin" or adminLevel == "s") then + if (v:IsSuperAdmin()) then + self:Notify(v, text, true, icon); + end; + end; + end; +end; + +-- A function to notify a player. +function Clockwork.player:Notify(player, text, class, icon) + if (type(player) == "table") then + for k, v in pairs(player) do + self:Notify(v, text, class); + end; + elseif (class == true) then + if (icon) then + local data = {icon = icon}; + cwChatbox:Add(player, nil, "notify_all", text, data); + else + cwChatbox:Add(player, nil, "notify_all", text); + end; + elseif (!class) then + if (icon) then + local data = {icon = icon}; + cwChatbox:Add(player, nil, "notify", text, data); + else + cwChatbox:Add(player, nil, "notify", text); + end; + else + cwDatastream:Start(player, "Notification", {text = text, class = class}); + end; +end; + +Clockwork.player:AddToMetaTable("Player", "Notify"); + +-- A function to set a player's weapons list from a table. +function Clockwork.player:SetWeapons(player, weapons, bForceReturn) + for k, v in pairs(weapons) do + if (!player:HasWeapon(v.weaponData["class"])) then + if (!v.teamIndex or player:Team() == v.teamIndex) then + player:Give( + v.weaponData["class"], v.weaponData["itemTable"], bForceReturn + ); + end; + end; + end; +end; + +-- A function to give ammo to a player from a table. +function Clockwork.player:GiveAmmo(player, ammo) + for k, v in pairs(ammo) do player:GiveAmmo(v, k); end; +end; + +-- A function to set a player's ammo list from a table. +function Clockwork.player:SetAmmo(player, ammo) + for k, v in pairs(ammo) do player:SetAmmo(v, k); end; +end; + +-- A function to get a player's ammo list as a table. +function Clockwork.player:GetAmmo(player, bDoStrip) + local spawnAmmo = self:GetSpawnAmmo(player); + local ammoTypes = {}; + local ammo = {}; + + for k, v in pairs(cwItem:GetAll()) do + if (v.ammoClass) then + ammoTypes[v.ammoClass] = true; + end; + end; + + cwPlugin:Call("AdjustAmmoTypes", ammoTypes); + + if (ammoTypes) then + for k, v in pairs(ammoTypes) do + if (v) then + ammo[k] = player:GetAmmoCount(k); + end; + end; + end; + + if (spawnAmmo) then + for k, v in pairs(spawnAmmo) do + if (ammo[k]) then + ammo[k] = math.max(ammo[k] - v, 0); + end; + end; + end; + + if (bDoStrip) then + player:RemoveAllAmmo(); + end; + + return ammo; +end; + +-- A function to get a player's weapons list as a table. +function Clockwork.player:GetWeapons(player, bDoKeep) + local weapons = {}; + + for k, v in pairs(player:GetWeapons()) do + local itemTable = cwItem:GetByWeapon(v); + local teamIndex = player:Team(); + local class = v:GetClass(); + + if (!self:GetSpawnWeapon(player, class)) then + teamIndex = nil; + end; + + weapons[#weapons + 1] = { + weaponData = { + itemTable = itemTable, + class = class + }, + teamIndex = teamIndex + }; + + if (!bDoKeep) then + player:StripWeapon(class); + end; + end; + + return weapons; +end; + +-- A function to get the total weight of a player's equipped weapons. +function Clockwork.player:GetEquippedWeight(player) + local weight = 0; + + for k, v in pairs(player:GetWeapons()) do + local itemTable = cwItem:GetByWeapon(v); + + if (itemTable) then + weight = weight + itemTable("weight"); + end; + end; + + return weight; +end; + +-- A function to get the total space of a player's equipped weapons. +function Clockwork.player:GetEquippedSpace(player) + local space = 0; + + for k, v in pairs(player:GetWeapons()) do + local itemTable = cwItem:GetByWeapon(v); + + if (itemTable) then + space = space + itemTable("space"); + end; + end; + + return space; +end; + +-- A function to get a player's holstered weapon. +function Clockwork.player:GetHolsteredWeapon(player) + for k, v in pairs(player:GetWeapons()) do + local itemTable = cwItem:GetByWeapon(v); + local class = v:GetClass(); + + if (itemTable) then + if (self:GetWeaponClass(player) != class) then + return class; + end; + end; + end; +end; + +-- A function to check whether a player is ragdolled. +function Clockwork.player:IsRagdolled(player, exception, bNoEntity) + if (player:GetRagdollEntity() or bNoEntity) then + local ragdolled = player:GetSharedVar("IsRagdoll"); + + if (ragdolled == exception) then + return false; + else + return (ragdolled != RAGDOLL_NONE); + end; + end; +end; + +-- A function to set a player's unragdoll time. +function Clockwork.player:SetUnragdollTime(player, delay) + player.cwRagdollPaused = nil; + + if (delay) then + self:SetAction(player, "unragdoll", delay, 2, function() + if (IsValid(player) and player:Alive()) then + self:SetRagdollState(player, RAGDOLL_NONE); + end; + end); + else + self:SetAction(player, "unragdoll", false); + end; +end; + +-- A function to pause a player's unragdoll time. +function Clockwork.player:PauseUnragdollTime(player) + if (!player.cwRagdollPaused) then + local unragdollTime = self:GetUnragdollTime(player); + local curTime = CurTime(); + + if (player:IsRagdolled()) then + if (unragdollTime > 0) then + player.cwRagdollPaused = unragdollTime - curTime; + self:SetAction(player, "unragdoll", false); + end; + end; + end; +end; + +-- A function to start a player's unragdoll time. +function Clockwork.player:StartUnragdollTime(player) + if (player.cwRagdollPaused) then + if (player:IsRagdolled()) then + self:SetUnragdollTime(player, player.cwRagdollPaused); + + player.cwRagdollPaused = nil; + end; + end; +end; + +-- A function to get a player's unragdoll time. +function Clockwork.player:GetUnragdollTime(player) + local action, actionDuration, startActionTime = self:GetAction(player); + + if (action == "unragdoll") then + return startActionTime + actionDuration; + else + return 0; + end; +end; + +-- A function to get a player's ragdoll state. +function Clockwork.player:GetRagdollState(player) + return player:GetSharedVar("IsRagdoll"); +end; + +-- A function to get a player's ragdoll entity. +function Clockwork.player:GetRagdollEntity(player) + if (player.cwRagdollTab) then + if (IsValid(player.cwRagdollTab.entity)) then + return player.cwRagdollTab.entity; + end; + end; +end; + +-- A function to get a player's ragdoll table. +function Clockwork.player:GetRagdollTable(player) + return player.cwRagdollTab; +end; + +-- A function to do a player's ragdoll decay check. +function Clockwork.player:DoRagdollDecayCheck(player, ragdoll) + local index = ragdoll:EntIndex(); + + cwKernel:CreateTimer("DecayCheck"..index, 60, 0, function() + local ragdollIsValid = IsValid(ragdoll); + local playerIsValid = IsValid(player); + + if (!playerIsValid and ragdollIsValid) then + if (!cwEntity:IsDecaying(ragdoll)) then + local decayTime = cwCfg:Get("body_decay_time"):Get(); + + if (decayTime > 0 and cwPlugin:Call("PlayerCanRagdollDecay", player, ragdoll, decayTime)) then + cwEntity:Decay(ragdoll, decayTime); + end; + else + cwKernel:DestroyTimer("DecayCheck"..index); + end; + elseif (!ragdollIsValid) then + cwKernel:DestroyTimer("DecayCheck"..index); + end; + end); +end; + +-- A function to set a player's ragdoll immunity. +function Clockwork.player:SetRagdollImmunity(player, delay) + if (delay) then + player:GetRagdollTable().immunity = CurTime() + delay; + else + player:GetRagdollTable().immunity = 0; + end; +end; + +-- A function to set a player's ragdoll state. +function Clockwork.player:SetRagdollState(player, state, delay, decay, force, multiplier, velocityCallback) + if (state == RAGDOLL_KNOCKEDOUT or state == RAGDOLL_FALLENOVER) then + if (player:IsRagdolled()) then + if (cwPlugin:Call("PlayerCanRagdoll", player, state, delay, decay, player.cwRagdollTab)) then + self:SetUnragdollTime(player, delay); + player:SetSharedVar("IsRagdoll", state); + player.cwRagdollTab.delay = delay; + player.cwRagdollTab.decay = decay; + cwPlugin:Call("PlayerRagdolled", player, state, player.cwRagdollTab); + end; + elseif (cwPlugin:Call("PlayerCanRagdoll", player, state, delay, decay)) then + local velocity = player:GetVelocity() + (player:GetAimVector() * 128); + local ragdoll = ents.Create("prop_ragdoll"); + + ragdoll:SetMaterial(player:GetMaterial()); + ragdoll:SetAngles(player:GetAngles()); + ragdoll:SetColor(player:GetColor()); + ragdoll:SetModel(player:GetModel()); + ragdoll:SetSkin(player:GetSkin()); + ragdoll:SetPos(player:GetPos()); + ragdoll:Spawn(); + + player.cwRagdollTab = {}; + player.cwRagdollTab.eyeAngles = player:EyeAngles(); + player.cwRagdollTab.immunity = CurTime() + cwCfg:Get("ragdoll_immunity_time"):Get(); + player.cwRagdollTab.moveType = MOVETYPE_WALK; + player.cwRagdollTab.entity = ragdoll; + player.cwRagdollTab.health = player:Health(); + player.cwRagdollTab.armor = player:Armor(); + player.cwRagdollTab.delay = delay; + player.cwRagdollTab.decay = decay; + + if (!player:IsOnGround()) then + player.cwRagdollTab.immunity = 0; + end; + + if (IsValid(ragdoll)) then + local headIndex = ragdoll:LookupBone("ValveBiped.Bip01_Head1"); + + ragdoll:SetCollisionGroup(COLLISION_GROUP_WEAPON); + + for i = 1, ragdoll:GetPhysicsObjectCount() do + local physicsObject = ragdoll:GetPhysicsObjectNum(i); + local boneIndex = ragdoll:TranslatePhysBoneToBone(i); + local position, angle = player:GetBonePosition(boneIndex); + + if (IsValid(physicsObject)) then + physicsObject:SetPos(position); + physicsObject:SetAngles(angle); + + if (!velocityCallback) then + if (boneIndex == headIndex) then + physicsObject:SetVelocity(velocity * 1.5); + else + physicsObject:SetVelocity(velocity); + end; + + if (force) then + if (boneIndex == headIndex) then + physicsObject:ApplyForceCenter(force * 1.5); + else + physicsObject:ApplyForceCenter(force); + end; + end; + else + velocityCallback(physicsObject, boneIndex, ragdoll, velocity, force); + end; + end; + end; + end; + + if (player:Alive()) then + if (IsValid(player:GetActiveWeapon())) then + player.cwRagdollTab.weapon = self:GetWeaponClass(player); + end; + + player.cwRagdollTab.weapons = self:GetWeapons(player, true); + + if (delay) then + self:SetUnragdollTime(player, delay); + end; + end; + + if (player:InVehicle()) then + player:ExitVehicle(); + player.cwRagdollTab.eyeAngles = Angle(0, 0, 0); + end; + + if (player:IsOnFire()) then + ragdoll:Ignite(8, 0); + end; + + player:Spectate(OBS_MODE_CHASE); + player:RunCommand("-duck"); + player:RunCommand("-voicerecord"); + player:SetMoveType(MOVETYPE_OBSERVER); + player:StripWeapons(true); + player:SpectateEntity(ragdoll); + player:CrosshairDisable(); + + if (player:FlashlightIsOn()) then + player:Flashlight(false); + end; + + player.cwRagdollPaused = nil; + + player:SetSharedVar("IsRagdoll", state); + player:SetSharedVar("Ragdoll", ragdoll); + + if (state != RAGDOLL_FALLENOVER) then + self:GiveDeathCode(player); + end; + + cwEntity:SetPlayer(ragdoll, player); + self:DoRagdollDecayCheck(player, ragdoll); + + cwPlugin:Call("PlayerRagdolled", player, state, player.cwRagdollTab); + end; + elseif (state == RAGDOLL_NONE or state == RAGDOLL_RESET) then + if (player:IsRagdolled(nil, true)) then + local ragdollTable = player:GetRagdollTable(); + + if (cwPlugin:Call("PlayerCanUnragdoll", player, state, ragdollTable)) then + player:UnSpectate(); + player:CrosshairEnable(); + + if (state != RAGDOLL_RESET) then + self:LightSpawn(player, nil, nil, true); + end; + + if (state != RAGDOLL_RESET) then + if (IsValid(ragdollTable.entity)) then + local velocity = ragdollTable.entity:GetVelocity(); + local position = cwEntity:GetPelvisPosition(ragdollTable.entity); + + if (position) then + self:SetSafePosition(player, position, ragdollTable.entity); + end; + + player:SetSkin(ragdollTable.entity:GetSkin()); + player:SetColor(ragdollTable.entity:GetColor()); + player:SetMaterial(ragdollTable.entity:GetMaterial()); + + if (!ragdollTable.model) then + player:SetModel(ragdollTable.entity:GetModel()); + else + player:SetModel(ragdollTable.model); + end; + + if (!ragdollTable.skin) then + player:SetSkin(ragdollTable.entity:GetSkin()); + else + player:SetSkin(ragdollTable.skin); + end; + + player:SetVelocity(velocity); + end; + + player:SetArmor(ragdollTable.armor); + player:SetHealth(ragdollTable.health); + player:SetMoveType(ragdollTable.moveType); + player:SetEyeAngles(ragdollTable.eyeAngles); + end; + + if (IsValid(ragdollTable.entity)) then + cwKernel:DestroyTimer("DecayCheck"..ragdollTable.entity:EntIndex()); + + if (ragdollTable.decay) then + if (cwPlugin:Call("PlayerCanRagdollDecay", player, ragdollTable.entity, ragdollTable.decay)) then + cwEntity:Decay(ragdollTable.entity, ragdollTable.decay); + end; + else + ragdollTable.entity:Remove(); + end; + end; + + if (state != RAGDOLL_RESET) then + self:SetWeapons(player, ragdollTable.weapons, true); + + if (ragdollTable.weapon) then + player:SelectWeapon(ragdollTable.weapon); + end; + end; + + self:SetUnragdollTime(player, false); + player:SetSharedVar("IsRagdoll", RAGDOLL_NONE); + player:SetSharedVar("Ragdoll", NULL); + cwPlugin:Call("PlayerUnragdolled", player, state, ragdollTable); + + player.cwRagdollPaused = nil; + player.cwRagdollTab = {}; + end; + end; + end; +end; + +-- A function to make a player drop their weapons. +function Clockwork.player:DropWeapons(player) + local ragdollEntity = player:GetRagdollEntity(); + + if (player:IsRagdolled()) then + local ragdollWeapons = player:GetRagdollWeapons(); + + for k, v in pairs(ragdollWeapons) do + local itemTable = v.weaponData["itemTable"]; + + if (itemTable and cwPlugin:Call("PlayerCanDropWeapon", player, itemTable, NULL, true)) then + local info = { + itemTable = itemTable, + position = ragdollEntity:GetPos() + Vector(0, 0, math.random(1, 48)), + angles = Angle(0, 0, 0) + }; + + player:TakeItem(info.itemTable, true); + ragdollWeapons[k] = nil; + + if (cwPlugin:Call("PlayerAdjustDropWeaponInfo", player, info)) then + local entity = cwEntity:CreateItem(player, info.itemTable, info.position, info.angles); + + if (IsValid(entity)) then + cwPlugin:Call("PlayerDropWeapon", player, info.itemTable, entity, NULL); + end; + end; + end; + end; + else + for k, v in pairs(player:GetWeapons()) do + local itemTable = cwItem:GetByWeapon(v); + + if (itemTable and cwPlugin:Call("PlayerCanDropWeapon", player, itemTable, v, true)) then + local info = { + itemTable = itemTable, + position = player:GetPos() + Vector(0, 0, math.random(1, 48)), + angles = Angle(0, 0, 0) + }; + + if (cwPlugin:Call("PlayerAdjustDropWeaponInfo", player, info)) then + local entity = cwEntity:CreateItem( + player, info.itemTable, info.position, info.angles + ); + + if (IsValid(entity)) then + cwPlugin:Call("PlayerDropWeapon", player, info.itemTable, entity, v); + player:StripWeapon(v:GetClass()); + player:TakeItem(info.itemTable, true); + end; + end; + end; + end; + end; +end; + +-- A function to lightly spawn a player. +function Clockwork.player:LightSpawn(player, weapons, ammo, bForceReturn) + if (player:IsRagdolled() and !bForceReturn) then + self:SetRagdollState(player, RAGDOLL_NONE); + end; + + player.cwLightSpawn = true; + + local moveType = player:GetMoveType(); + local material = player:GetMaterial(); + local position = player:GetPos(); + local angles = player:EyeAngles(); + local weapon = player:GetActiveWeapon(); + local health = player:Health(); + local armor = player:Armor(); + local model = player:GetModel(); + local color = player:GetColor(); + local skin = player:GetSkin(); + + if (ammo) then + if (type(ammo) != "table") then + ammo = self:GetAmmo(player, true); + end; + end; + + if (weapons) then + if (type(weapons) != "table") then + weapons = self:GetWeapons(player); + end; + + if (IsValid(weapon)) then + weapon = weapon:GetClass(); + end; + end; + + player.cwSpawnCallback = function(player, gamemodeHook) + if (weapons) then + Clockwork:PlayerLoadout(player); + + self:SetWeapons(player, weapons, bForceReturn); + + if (type(weapon) == "string") then + player:SelectWeapon(weapon); + end; + end; + + if (ammo) then + self:GiveAmmo(player, ammo); + end; + + player:SetPos(position); + player:SetSkin(skin); + player:SetModel(model); + player:SetColor(color); + player:SetArmor(armor); + player:SetHealth(health); + player:SetMaterial(material); + player:SetMoveType(moveType); + player:SetEyeAngles(angles); + + if (gamemodeHook) then + special = special or false; + + cwPlugin:Call("PostPlayerLightSpawn", player, weapons, ammo, special); + end; + + player:ResetSequence( + player:GetSequence() + ); + end; + + player:Spawn(); +end; + +-- A function to convert a table to camel case. +function Clockwork.player:ConvertToCamelCase(baseTable) + local newTable = {}; + + for k, v in pairs(baseTable) do + local key = cwKernel:SetCamelCase(string.gsub(k, "_", ""), true); + + if (key and key != "") then + newTable[key] = v; + end; + end; + + return newTable; +end; + +-- A function to get a player's characters. +function Clockwork.player:GetCharacters(player, Callback) + if (!IsValid(player)) then return; end; + + local charactersTable = cwCfg:Get("mysql_characters_table"):Get(); + local schemaFolder = cwKernel:GetSchemaFolder(); + local queryObj = cwDatabase:Select(charactersTable); + queryObj:AddWhere("_Schema = ?", schemaFolder); + queryObj:AddWhere("_SteamID = ?", player:SteamID()); + queryObj:SetCallback(function(result) + if (!IsValid(player)) then return; end; + + if (cwDatabase:IsResult(result)) then + local characters = {}; + + for k, v in pairs(result) do + characters[k] = self:ConvertToCamelCase(v); + end; + + Callback(characters); + else + Callback(); + end; + end); + queryObj:Pull(); +end; + +-- A function to add a character to the character screen. +function Clockwork.player:CharacterScreenAdd(player, character) + local info = { + name = character.name, + model = character.model, + banned = character.data["CharBanned"], + faction = character.faction, + characterID = character.characterID + }; + + if (character.data["PhysDesc"]) then + if (string.utf8len(character.data["PhysDesc"]) > 64) then + info.details = string.utf8sub(character.data["PhysDesc"], 1, 64).."..."; + else + info.details = character.data["PhysDesc"]; + end; + end; + + if (character.data["CharBanned"]) then + info.details = "This character is banned."; + end; + + cwPlugin:Call("PlayerAdjustCharacterScreenInfo", player, character, info); + cwDatastream:Start(player, "CharacterAdd", info); +end; + +-- A function to convert a character's MySQL variables to Lua variables. +function Clockwork.player:ConvertCharacterMySQL(baseTable) + baseTable.recognisedNames = self:ConvertCharacterRecognisedNamesString(baseTable.recognisedNames); + baseTable.characterID = tonumber(baseTable.characterID); + baseTable.attributes = self:ConvertCharacterDataString(baseTable.attributes); + baseTable.inventory = cwInventory:ToLoadable( + self:ConvertCharacterDataString(baseTable.inventory) + ); + baseTable.cash = tonumber(baseTable.cash); + baseTable.ammo = self:ConvertCharacterDataString(baseTable.ammo); + baseTable.data = self:ConvertCharacterDataString(baseTable.data); + baseTable.key = tonumber(baseTable.key); +end; + +-- A function to get a player's character ID. +function Clockwork.player:GetCharacterID(player) + local character = player:GetCharacter(); + + if (character) then + for k, v in pairs(player:GetCharacters()) do + if (v == character) then + return k; + end; + end; + end; +end; + +-- A function to load a player's character. +function Clockwork.player:LoadCharacter(player, characterID, tMergeCreate, Callback, bForce) + local character = {}; + local unixTime = os.time(); + + if (tMergeCreate) then + character = {}; + character.name = name; + character.data = {}; + character.ammo = {}; + character.cash = cwCfg:Get("default_cash"):Get(); + character.model = "models/police.mdl"; + character.flags = "b"; + character.schema = cwKernel:GetSchemaFolder(); + character.gender = GENDER_MALE; + character.faction = FACTION_CITIZEN; + character.steamID = player:SteamID(); + character.steamName = player:SteamName(); + character.inventory = {}; + character.attributes = {}; + character.onNextLoad = ""; + character.lastPlayed = unixTime; + character.timeCreated = unixTime; + character.characterID = characterID; + character.recognisedNames = {}; + + if (!player.cwCharacterList[characterID]) then + table.Merge(character, tMergeCreate); + + if (character and type(character) == "table") then + character.inventory = {}; + cwPlugin:Call( + "GetPlayerDefaultInventory", player, character, character.inventory + ); + + if (!bForce) then + local fault = cwPlugin:Call("PlayerCanCreateCharacter", player, character, characterID); + + if (fault == false or type(fault) == "string") then + return self:SetCreateFault(player, fault or "You cannot create this character!"); + end; + end; + + self:SaveCharacter(player, true, character, function(key) + player.cwCharacterList[characterID] = character; + player.cwCharacterList[characterID].key = key; + + cwPlugin:Call("PlayerCharacterCreated", player, character); + self:CharacterScreenAdd(player, character); + + if (Callback) then + Callback(); + end; + end); + end; + end; + else + character = player.cwCharacterList[characterID]; + + if (character) then + if (player:GetCharacter()) then + self:SaveCharacter(player); + self:UpdateCharacter(player); + + cwPlugin:Call("PlayerCharacterUnloaded", player); + end; + + player.cwCharacter = character; + + if (player:Alive()) then + player:KillSilent(); + end; + + if (self:SetBasicSharedVars(player)) then + cwPlugin:Call("PlayerCharacterLoaded", player); + player:SaveCharacter(); + end; + end; + end; +end; + +-- A function to set a player's basic shared variables. +function Clockwork.player:SetBasicSharedVars(player) + local gender = player:GetGender(); + local faction = player:GetFaction(); + + player:SetSharedVar("Flags", player:GetFlags()); + player:SetSharedVar("Model", self:GetDefaultModel(player)); + player:SetSharedVar("Name", player:Name()); + player:SetSharedVar("Key", player:GetCharacterKey()); + + if (cwFaction:GetAll()[faction]) then + player:SetSharedVar("Faction", cwFaction:GetAll()[faction].index); + end; + + if (gender == GENDER_MALE) then + player:SetSharedVar("Gender", 2); + else + player:SetSharedVar("Gender", 1); + end; + + return true; +end; + +-- A function to get the character's ammo as a string. +function Clockwork.player:GetCharacterAmmoString(player, character, bRawTable) + local ammo = table.Copy(character.ammo); + + for k, v in pairs(self:GetAmmo(player)) do + if (v > 0) then + ammo[k] = v; + end; + end; + + if (!bRawTable) then + return cwJson:Encode(ammo); + else + return ammo; + end; +end; + +-- A function to get the character's data as a string. +function Clockwork.player:GetCharacterDataString(player, character, bRawTable) + local data = table.Copy(character.data); + cwPlugin:Call("PlayerSaveCharacterData", player, data); + + if (!bRawTable) then + return cwJson:Encode(data); + else + return data; + end; +end; + +-- A function to get the character's recognised names as a string. +function Clockwork.player:GetCharacterRecognisedNamesString(player, character) + local recognisedNames = {}; + + for k, v in pairs(character.recognisedNames) do + if (v == RECOGNISE_SAVE) then + recognisedNames[#recognisedNames + 1] = k; + end; + end; + + return cwJson:Encode(recognisedNames); +end; + +-- A function to get the character's inventory as a string. +function Clockwork.player:GetCharacterInventoryString(player, character, bRawTable) + local inventory = cwInventory:CreateDuplicate(character.inventory); + cwPlugin:Call("PlayerAddToSavedInventory", player, character, function(itemTable) + cwInventory:AddInstance(inventory, itemTable); + end); + + if (!bRawTable) then + return cwJson:Encode(cwInventory:ToSaveable(inventory)); + else + return inventory; + end; +end; + +-- A function to convert a character's recognised names string to a table. +function Clockwork.player:ConvertCharacterRecognisedNamesString(data) + local bSuccess, value = pcall(cwJson.Decode, cwJson, data); + + if (bSuccess and value != nil) then + local recognisedNames = {}; + + for k, v in pairs(value) do + recognisedNames[v] = RECOGNISE_SAVE; + end; + + return recognisedNames; + else + return {}; + end; +end; + +-- A function to convert a character's data string to a table. +function Clockwork.player:ConvertCharacterDataString(data) + local bSuccess, value = pcall(cwJson.Decode, cwJson, data); + + if (bSuccess and value != nil) then + return value; + else + return {}; + end; +end; + +-- A function to load a player's data. +function Clockwork.player:LoadData(player, Callback) + local playersTable = cwCfg:Get("mysql_players_table"):Get(); + local schemaFolder = cwKernel:GetSchemaFolder(); + local unixTime = os.time(); + local steamID = player:SteamID(); + + local queryObj = cwDatabase:Select(playersTable); + queryObj:AddWhere("_Schema = ?", schemaFolder); + queryObj:AddWhere("_SteamID = ?", steamID); + queryObj:SetCallback(function(result) + if (!IsValid(player) or player.cwData) then + return; + end; + + local onNextPlay = ""; + + if (cwDatabase:IsResult(result)) then + player.cwTimeJoined = tonumber(result[1]._TimeJoined); + player.cwLastPlayed = tonumber(result[1]._LastPlayed); + player.cwUserGroup = result[1]._UserGroup; + player.cwData = self:ConvertDataString(player, result[1]._Data); + + local bSuccess, value = pcall(cwJson.Decode, cwJson, result[1]._Donations); + + if (bSuccess and value != nil) then + player.cwDonations = value; + else + player.cwDonations = {}; + end; + + onNextPlay = result[1]._OnNextPlay; + else + player.cwTimeJoined = unixTime; + player.cwLastPlayed = unixTime; + player.cwDonations = {}; + player.cwUserGroup = "user"; + player.cwData = self:SaveData(player, true); + end; + + if (self:IsProtected(player)) then + player.cwUserGroup = "superadmin"; + end; + + if (!player.cwUserGroup or player.cwUserGroup == "") then + player.cwUserGroup = "user"; + end; + + if (!cwCfg:Get("use_own_group_system"):Get() + and player.cwUserGroup != "user") then + player:SetUserGroup(player.cwUserGroup); + end; + + cwPlugin:Call("PlayerRestoreData", player, player.cwData); + + if (Callback and IsValid(player)) then + Callback(player); + end; + + if (onNextPlay != "") then + local updateObj = cwDatabase:Update(playersTable); + updateObj:SetValue("_OnNextPlay", ""); + updateObj:SetValue("_SteamID", steamID); + updateObj:SetValue("_Schema", schemaFolder); + updateObj:Push(); + + PLAYER = player; + RunString(onNextPlay); + PLAYER = nil; + end; + end); + queryObj:Pull(); + + timer.Simple(2, function() + if (IsValid(player) and !player.cwData) then + self:LoadData(player, Callback); + end; + end); +end; + +-- A function to save a players's data. +function Clockwork.player:SaveData(player, bCreate) + if (!bCreate) then + local schemaFolder = cwKernel:GetSchemaFolder(); + local steamName = cwDatabase:Escape(player:SteamName()); + local ipAddress = player:IPAddress(); + local userGroup = player:GetClockworkUserGroup(); + local steamID = player:SteamID(); + local data = table.Copy(player.cwData); + + cwPlugin:Call("PlayerSaveData", player, data); + + local playersTable = cwCfg:Get("mysql_players_table"):Get(); + local queryObj = cwDatabase:Update(playersTable); + queryObj:AddWhere("_Schema = ?", schemaFolder); + queryObj:AddWhere("_SteamID = ?", steamID); + queryObj:SetValue("_LastPlayed", os.time()); + queryObj:SetValue("_SteamName", steamName); + queryObj:SetValue("_IPAddress", ipAddress); + queryObj:SetValue("_UserGroup", userGroup); + queryObj:SetValue("_SteamID", steamID); + queryObj:SetValue("_Schema", schemaFolder); + queryObj:SetValue("_Data", cwJson:Encode(data)); + queryObj:Push(); + else + local playersTable = cwCfg:Get("mysql_players_table"):Get(); + local queryObj = cwDatabase:Insert(playersTable); + queryObj:SetValue("_Data", ""); + queryObj:SetValue("_Schema", cwKernel:GetSchemaFolder()); + queryObj:SetValue("_SteamID", player:SteamID()); + queryObj:SetValue("_Donations", ""); + queryObj:SetValue("_UserGroup", "user"); + queryObj:SetValue("_IPAddress", player:IPAddress()); + queryObj:SetValue("_SteamName", player:SteamName()); + queryObj:SetValue("_OnNextPlay", ""); + queryObj:SetValue("_LastPlayed", os.time()); + queryObj:SetValue("_TimeJoined", os.time()); + queryObj:Push(); + + return {}; + end; +end; + +-- A function to update a player's character. +function Clockwork.player:UpdateCharacter(player) + player.cwCharacter.inventory = self:GetCharacterInventoryString(player, player.cwCharacter, true); + player.cwCharacter.ammo = self:GetCharacterAmmoString(player, player.cwCharacter, true); + player.cwCharacter.data = self:GetCharacterDataString(player, player.cwCharacter, true); +end; + +-- A function to save a player's character. +function Clockwork.player:SaveCharacter(player, bCreate, character, Callback) + if (bCreate) then + local charactersTable = cwCfg:Get("mysql_characters_table"):Get(); + local values = ""; + local amount = 1; + local keys = ""; + + if (!character or type(character) != "table") then + character = player:GetCharacter(); + end; + + local queryObj = cwDatabase:Insert(charactersTable); + for k, v in pairs(character) do + local tableKey = "_"..cwKernel:SetCamelCase(k, false); + + if (k == "recognisedNames") then + queryObj:SetValue(tableKey, cwJson:Encode(character.recognisedNames)); + elseif (k == "attributes") then + queryObj:SetValue(tableKey, cwJson:Encode(character.attributes)); + elseif (k == "inventory") then + queryObj:SetValue(tableKey, cwJson:Encode(cwInventory:ToSaveable(character.inventory))); + elseif (k == "ammo") then + queryObj:SetValue(tableKey, cwJson:Encode(character.ammo)); + elseif (k == "data") then + queryObj:SetValue(tableKey, cwJson:Encode(v)); + else + queryObj:SetValue(tableKey, v); + end; + end; + if (system.IsWindows()) then + queryObj:SetCallback(function(result, status, lastID) + if (Callback and tonumber(lastID)) then + Callback(tonumber(lastID)); + end; + end); + elseif (system.IsLinux()) then + queryObj:SetCallback(function(result, status, lastID) + if (Callback) then + Callback(tonumber(lastID)); + end; + end); + end; + queryObj:SetFlag(2); + queryObj:Push(); + elseif (player:HasInitialized()) then + local currentCharacter = player:GetCharacter(); + local charactersTable = cwCfg:Get("mysql_characters_table"):Get(); + local schemaFolder = cwKernel:GetSchemaFolder(); + local unixTime = os.time(); + local steamID = player:SteamID(); + + if (!character) then + character = player:GetCharacter(); + end; + + local queryObj = cwDatabase:Update(charactersTable); + queryObj:AddWhere("_Schema = ?", schemaFolder); + queryObj:AddWhere("_SteamID = ?", steamID); + queryObj:AddWhere("_CharacterID = ?", character.characterID); + queryObj:SetValue("_RecognisedNames", self:GetCharacterRecognisedNamesString(player, character)); + queryObj:SetValue("_Attributes", cwJson:Encode(character.attributes)); + queryObj:SetValue("_LastPlayed", unixTime); + queryObj:SetValue("_SteamName", player:SteamName()); + queryObj:SetValue("_Faction", character.faction); + queryObj:SetValue("_Gender", character.gender); + queryObj:SetValue("_Schema", character.schema); + queryObj:SetValue("_Model", character.model); + queryObj:SetValue("_Flags", character.flags); + queryObj:SetValue("_Cash", character.cash); + queryObj:SetValue("_Name", character.name); + + if (currentCharacter == character) then + queryObj:SetValue("_Inventory", self:GetCharacterInventoryString(player, character)); + queryObj:SetValue("_Ammo", self:GetCharacterAmmoString(player, character)); + queryObj:SetValue("_Data", self:GetCharacterDataString(player, character)); + else + queryObj:SetValue("_Inventory", cwJson:Encode(cwInventory:ToSaveable(character.inventory))); + queryObj:SetValue("_Ammo", cwJson:Encode(character.ammo)); + queryObj:SetValue("_Data", cwJson:Encode(character.data)); + end; + queryObj:Push(); + + --[[ Save the player's data after pushing the update. --]] + Clockwork.player:SaveData(player); + end; +end; + +-- A function to get the class of a player's active weapon. +function Clockwork.player:GetWeaponClass(player, safe) + if (IsValid(player:GetActiveWeapon())) then + return player:GetActiveWeapon():GetClass(); + else + return safe; + end; +end; + +-- A function to call a player's think hook. +function Clockwork.player:CallThinkHook(player, setSharedVars, curTime) + local infoTable = player.cwInfoTable; + + infoTable.inventoryWeight = cwCfg:Get("default_inv_weight"):Get(); + infoTable.inventorySpace = cwCfg:Get("default_inv_space"):Get(); + infoTable.crouchedSpeed = player.cwCrouchedSpeed; + infoTable.jumpPower = player.cwJumpPower; + infoTable.walkSpeed = player.cwWalkSpeed; + infoTable.isRunning = player:IsRunning(); + infoTable.isJogging = player:IsJogging(); + infoTable.runSpeed = player.cwRunSpeed; + infoTable.wages = cwClass:Query(player:Team(), "wages", 0); + + if (!player:IsJogging(true)) then + infoTable.isJogging = nil; + player:SetSharedVar("IsJogMode", false); + end; + + if (setSharedVars) then + cwPlugin:Call("PlayerSetSharedVars", player, curTime); + player.cwNextSetSharedVars = nil; + end; + + cwPlugin:Call("PlayerThink", player, curTime, infoTable); + player.cwNextThink = nil; +end; + +-- A function to get a player's wages. +function Clockwork.player:GetWages(player) + return player:GetSharedVar("Wages"); +end; + +-- A function to set a character's flags. +function Clockwork.player:SetFlags(player, flags) + self:TakeFlags(player, player:GetFlags()); + self:GiveFlags(player, flags); +end; + +-- A function to set a player's flags. +function Clockwork.player:SetPlayerFlags(player, flags) + self:TakePlayerFlags(player, player:GetPlayerFlags()); + self:GivePlayerFlags(player, flags); +end; + +-- A function to set a player's rank within their faction. +function Clockwork.player:SetFactionRank(player, rank) + if (rank) then + local faction = cwFaction:FindByID(player:GetFaction()); + + if (faction and istable(faction.ranks)) then + for k, v in pairs(faction.ranks) do + if (k == rank) then + player:SetCharacterData("factionrank", k); + + if (v.class and cwClass:GetAll()[v.class]) then + cwClass:Set(player, v.class); + end; + + if (v.model) then + player:SetModel(v.model); + end; + + if (istable(v.weapons)) then + for k, v in pairs(v.weapons) do + self:GiveSpawnWeapon(player, v); + end; + end; + + break; + end; + end; + end; + end; +end; + +-- A function to get a player's global flags. +function Clockwork.player:GetPlayerFlags(player) + return player:GetData("Flags") or ""; +end; + +end; + Clockwork.player.playerData = Clockwork.player.playerData or {}; Clockwork.player.characterData = Clockwork.player.characterData or {}; diff --git a/Clockwork/garrysmod/gamemodes/clockwork/framework/sh_boot.lua b/Clockwork/garrysmod/gamemodes/clockwork/framework/sh_boot.lua index 2fb40533..ee354bd4 100644 --- a/Clockwork/garrysmod/gamemodes/clockwork/framework/sh_boot.lua +++ b/Clockwork/garrysmod/gamemodes/clockwork/framework/sh_boot.lua @@ -28,7 +28,7 @@ end; Clockwork.ClockworkFolder = Clockwork.ClockworkFolder or GM.Folder; Clockwork.SchemaFolder = Clockwork.SchemaFolder or GM.Folder; -Clockwork.KernelVersion = "0.95.2"; +Clockwork.KernelVersion = "0.95.3"; Clockwork.KernelBuild = "beta"; Clockwork.DeveloperVersion = true; Clockwork.Website = "http://kurozael.com"; diff --git a/Clockwork/garrysmod/gamemodes/clockwork/framework/sv_kernel.lua b/Clockwork/garrysmod/gamemodes/clockwork/framework/sv_kernel.lua index bf3c987a..b153ae40 100644 --- a/Clockwork/garrysmod/gamemodes/clockwork/framework/sv_kernel.lua +++ b/Clockwork/garrysmod/gamemodes/clockwork/framework/sv_kernel.lua @@ -42,12 +42,35 @@ local math = math; local game = game; local os = os; +local cwConfig = Clockwork.config; +local cwPly = Clockwork.player; +local cwPlugin = Clockwork.plugin; +local cwStorage = Clockwork.storage; +local cwEvent = Clockwork.event; +local cwLimb = Clockwork.limb; +local cwItem = Clockwork.item; +local cwEntity = Clockwork.entity; +local cwKernel = Clockwork.kernel; +local cwOption = Clockwork.option; +local cwBans = Clockwork.bans; +local cwDatabase = Clockwork.database; +local cwDatastream = Clockwork.datastream; +local cwFaction = Clockwork.faction; +local cwInventory = Clockwork.inventory; +local cwHint = Clockwork.hint; +local cwCommand = Clockwork.command; +local cwClass = Clockwork.class; +local cwQuiz = Clockwork.quiz; +local cwAttribute = Clockwork.attribute; +local cwAttributes = Clockwork.attributes; +local cwVoice = Clockwork.voice; + --[[ Downloads the content addon for clients. --]] resource.AddWorkshop("474315121") --[[ Do this internally, because it's one less step for schemas. --]] AddCSLuaFile( - Clockwork.kernel:GetSchemaGamemodePath().."/cl_init.lua" + cwKernel:GetSchemaGamemodePath().."/cl_init.lua" ); --[[ @@ -89,7 +112,7 @@ function hook.Call(name, gamemode, ...) local arguments = {...}; if (name == "EntityTakeDamage") then - if (Clockwork.kernel:DoEntityTakeDamageHook(arguments)) then + if (cwKernel:DoEntityTakeDamageHook(arguments)) then return; end; elseif (name == "PlayerDisconnected") then @@ -99,7 +122,7 @@ function hook.Call(name, gamemode, ...) end; local startTime = SysTime(); - local bStatus, value = pcall(Clockwork.plugin.RunHooks, Clockwork.plugin, name, nil, unpack(arguments)); + local bStatus, value = pcall(cwPlugin.RunHooks, cwPlugin, name, nil, unpack(arguments)); local timeTook = SysTime() - startTime; hook.Timings[name] = timeTook; @@ -226,32 +249,32 @@ function Clockwork:PlayerThink(player, curTime, infoTable) local bPlayerBreathSnd = false; local storageTable = player:GetStorageTable(); - if (!Clockwork.config:Get("cash_enabled"):Get()) then + if (!cwConfig:Get("cash_enabled"):Get()) then player:SetCharacterData("Cash", 0, true); infoTable.wages = 0; end; if (player.cwReloadHoldTime and curTime >= player.cwReloadHoldTime) then - Clockwork.player:ToggleWeaponRaised(player); + cwPly:ToggleWeaponRaised(player); player.cwReloadHoldTime = nil; - player.cwNextShootTime = curTime + Clockwork.config:Get("shoot_after_raise_time"):Get(); + player.cwNextShootTime = curTime + cwConfig:Get("shoot_after_raise_time"):Get(); end; if (player:IsRagdolled()) then player:SetMoveType(MOVETYPE_OBSERVER); end; - if (storageTable and Clockwork.plugin:Call("PlayerStorageShouldClose", player, storageTable)) then - Clockwork.storage:Close(player); + if (storageTable and cwPlugin:Call("PlayerStorageShouldClose", player, storageTable)) then + cwStorage:Close(player); end; player:SetSharedVar("InvWeight", math.ceil(infoTable.inventoryWeight)); player:SetSharedVar("InvSpace", math.ceil(infoTable.inventorySpace)); player:SetSharedVar("Wages", math.ceil(infoTable.wages)); - if (Clockwork.event:CanRun("limb_damage", "disability")) then - local leftLeg = Clockwork.limb:GetDamage(player, HITGROUP_LEFTLEG, true); - local rightLeg = Clockwork.limb:GetDamage(player, HITGROUP_RIGHTLEG, true); + if (cwEvent:CanRun("limb_damage", "disability")) then + local leftLeg = cwLimb:GetDamage(player, HITGROUP_LEFTLEG, true); + local rightLeg = cwLimb:GetDamage(player, HITGROUP_RIGHTLEG, true); local legDamage = math.max(leftLeg, rightLeg); if (legDamage > 0) then @@ -272,7 +295,7 @@ function Clockwork:PlayerThink(player, curTime, infoTable) infoTable.runSpeed = infoTable.walkSpeed; end; - if (Clockwork.plugin:Call("PlayerShouldSmoothSprint", player, infoTable)) then + if (cwPlugin:Call("PlayerShouldSmoothSprint", player, infoTable)) then --[[ The target run speed is what we're aiming for! --]] player.cwTargetRunSpeed = infoTable.runSpeed; @@ -309,7 +332,7 @@ function Clockwork:PlayerThink(player, curTime, infoTable) player:SetRunSpeed(math.max(infoTable.runSpeed, 0), true); local activeWeapon = player:GetActiveWeapon(); - local weaponItemTable = Clockwork.item:GetByWeapon(activeWeapon); + local weaponItemTable = cwItem:GetByWeapon(activeWeapon); if (weaponItemTable and weaponItemTable:IsInstance()) then local clipOne = activeWeapon:Clip1(); @@ -335,16 +358,16 @@ function Clockwork:PlayerThink(player, curTime, infoTable) return; end; - if (entity:GetClass() != "prop_door_rotating" or Clockwork.player:IsNoClipping(player)) then + if (entity:GetClass() != "prop_door_rotating" or cwPly:IsNoClipping(player)) then return; end; - local doorPartners = Clockwork.entity:GetDoorPartners(entity); + local doorPartners = cwEntity:GetDoorPartners(entity); for k, v in pairs(doorPartners) do - if ((!Clockwork.entity:IsDoorLocked(v) and Clockwork.config:Get("bash_in_door_enabled"):Get()) + if ((!cwEntity:IsDoorLocked(v) and cwConfig:Get("bash_in_door_enabled"):Get()) and (!v.cwNextBashDoor or curTime >= v.cwNextBashDoor)) then - Clockwork.entity:BashInDoor(v, player); + cwEntity:BashInDoor(v, player); player:ViewPunch( Angle(math.Rand(-32, 32), math.Rand(-80, 80), math.Rand(-16, 16)) @@ -355,7 +378,7 @@ end; -- Called when a player should smooth sprint. function Clockwork:PlayerShouldSmoothSprint(player, infoTable) - return Clockwork.config:Get("player_should_smooth_sprint"):GetBoolean(); + return cwConfig:Get("player_should_smooth_sprint"):GetBoolean(); end; -- Called when a player fires a weapon. @@ -401,25 +424,25 @@ function Clockwork:ClockworkInitialized() self.config:Get("door_cost"):Set(0, nil, true, true); end; - if (Clockwork.config:Get("use_own_group_system"):Get()) then + if (cwConfig:Get("use_own_group_system"):Get()) then self.command:SetHidden("PlySetGroup", true); self.command:SetHidden("PlyDemote", true); end; - local gradientTexture = Clockwork.option:GetKey("gradient"); - local schemaLogo = Clockwork.option:GetKey("schema_logo"); - local introImage = Clockwork.option:GetKey("intro_image"); + local gradientTexture = cwOption:GetKey("gradient"); + local schemaLogo = cwOption:GetKey("schema_logo"); + local introImage = cwOption:GetKey("intro_image"); if (gradientTexture != "gui/gradient_up") then - Clockwork.kernel:AddFile("materials/"..gradientTexture..".png"); + cwKernel:AddFile("materials/"..gradientTexture..".png"); end; if (schemaLogo != "") then - Clockwork.kernel:AddFile("materials/"..schemaLogo..".png"); + cwKernel:AddFile("materials/"..schemaLogo..".png"); end; if (introImage != "") then - Clockwork.kernel:AddFile("materials/"..introImage..".png"); + cwKernel:AddFile("materials/"..introImage..".png"); end; local toolGun = weapons.GetStored("gmod_tool"); @@ -431,12 +454,12 @@ end; -- Called when the Clockwork database has connected. function Clockwork:ClockworkDatabaseConnected() - Clockwork.bans:Load(); + cwBans:Load(); end; -- Called when the Clockwork database connection fails. function Clockwork:ClockworkDatabaseConnectionFailed() - Clockwork.database:Error(errText); + cwDatabase:Error(errText); end; -- Called when Clockwork should log and event. @@ -460,7 +483,7 @@ end; -- Called when a player's saved inventory should be added to. function Clockwork:PlayerAddToSavedInventory(player, character, Callback) for k, v in pairs(player:GetWeapons()) do - local weaponItemTable = Clockwork.item:GetByWeapon(v); + local weaponItemTable = cwItem:GetByWeapon(v); if (weaponItemTable) then Callback(weaponItemTable); end; @@ -647,12 +670,12 @@ end; -- Called when a player's default inventory is needed. function Clockwork:GetPlayerDefaultInventory(player, character, inventory) - local startingInv = Clockwork.faction:FindByID(character.faction).startingInv; + local startingInv = cwFaction:FindByID(character.faction).startingInv; if (istable(startingInv)) then for k, v in pairs(startingInv) do - Clockwork.inventory:AddInstance( - inventory, Clockwork.item:CreateInstance(k), v + cwInventory:AddInstance( + inventory, cwItem:CreateInstance(k), v ); end; end; @@ -904,7 +927,7 @@ end; function Clockwork:SetupMove(player, moveData) if (player:Alive() and !player:IsRagdolled()) then local frameTime = FrameTime(); - local isDrunk = Clockwork.player:GetDrunk(player); + local isDrunk = cwPly:GetDrunk(player); local curTime = CurTime(); if (isDrunk and player.cwDrunkSwerve) then @@ -1011,7 +1034,7 @@ function Clockwork:PlayerSpawn(player) player:ShouldDropWeapon(false); if (!player.cwLightSpawn) then - local FACTION = Clockwork.faction:FindByID(player:GetFaction()); + local FACTION = cwFaction:FindByID(player:GetFaction()); local relation = FACTION.entRelationship; local playerRank, rank = player:GetFactionRank(); @@ -1068,7 +1091,7 @@ function Clockwork:PlayerSpawn(player) itemQuantity = table.Count(inventory[k]); if (itemQuantity < v) then - player:GiveItem(Clockwork.item:CreateInstance(k), true); + player:GiveItem(cwItem:CreateInstance(k), true); end; end; end; @@ -1175,12 +1198,16 @@ function Clockwork:PlayerSetHandsModel(player, entity) bodyGroups = string.Explode("", bodyGroups); for k, v in pairs(bodyGroups) do - entity:SetBodygroup(k, tonumber(v)); + local num = tonumber(v); + + if (num) then + entity:SetBodygroup(k, num); + end; end; end; end; - Clockwork.plugin:Call("PostCModelHandsSet", player, model, entity, info); + cwPlugin:Call("PostCModelHandsSet", player, model, entity, info); end; -- Called every frame. @@ -1492,7 +1519,7 @@ end; -- Called when a player's data stream info should be sent. function Clockwork:PlayerSendDataStreamInfo(player) - Clockwork.datastream:Start(player, "SharedTables", self.SharedTables); + cwDatastream:Start(player, "SharedTables", self.SharedTables); if (self.OverrideColorMod and self.OverrideColorMod != nil) then self.datastream:Start(player, "SystemColGet", self.OverrideColorMod); @@ -1522,7 +1549,7 @@ function Clockwork:PlayerRestoreCharacterData(player, data) data["Accessories"] = {}; end; - Clockwork.player:RestoreCharacterData(player, data); + cwPly:RestoreCharacterData(player, data); end; -- Called when a player's limb damage is bIsHealed. @@ -1554,7 +1581,7 @@ end; -- Called when a player's data should be saved. function Clockwork:PlayerSaveData(player, data) - Clockwork.player:RestoreData(player, data); + cwPly:RestoreData(player, data); if (data["Whitelisted"] and table.Count(data["Whitelisted"]) == 0) then data["Whitelisted"] = nil; @@ -1599,15 +1626,15 @@ function Clockwork:Tick() local plyTable = player.GetAll(); if (!self.NextHint or curTime >= self.NextHint) then - Clockwork.hint:Distribute(); - self.NextHint = curTime + Clockwork.config:Get("hint_interval"):Get(); + cwHint:Distribute(); + self.NextHint = curTime + cwConfig:Get("hint_interval"):Get(); end; if (!self.NextWagesTime or curTime >= self.NextWagesTime) then - Clockwork.kernel:DistributeWagesCash(); + cwKernel:DistributeWagesCash(); local info = { - interval = Clockwork.config:Get("wages_interval"):Get(); + interval = cwConfig:Get("wages_interval"):Get(); }; self.plugin:Call("ModifyWagesInterval", info); @@ -1616,10 +1643,10 @@ function Clockwork:Tick() end; if (!self.NextGeneratorTime or curTime >= self.NextGeneratorTime) then - Clockwork.kernel:DistributeGeneratorCash(); + cwKernel:DistributeGeneratorCash(); local info = { - interval = Clockwork.config:Get("generator_interval"):Get(); + interval = cwConfig:Get("generator_interval"):Get(); }; self.plugin:Call("ModifyGeneratorInterval", info); @@ -1628,16 +1655,16 @@ function Clockwork:Tick() end; if (!self.NextDateTimeThink or sysTime >= self.NextDateTimeThink) then - Clockwork.kernel:PerformDateTimeThink(); - self.NextDateTimeThink = sysTime + Clockwork.config:Get("minute_time"):Get(); + cwKernel:PerformDateTimeThink(); + self.NextDateTimeThink = sysTime + cwConfig:Get("minute_time"):Get(); end; if (!self.NextSaveData or sysTime >= self.NextSaveData) then - Clockwork.plugin:Call("PreSaveData"); - Clockwork.plugin:Call("SaveData"); - Clockwork.plugin:Call("PostSaveData"); + cwPlugin:Call("PreSaveData"); + cwPlugin:Call("SaveData"); + cwPlugin:Call("PostSaveData"); - self.NextSaveData = sysTime + Clockwork.config:Get("save_data_interval"):Get(); + self.NextSaveData = sysTime + cwConfig:Get("save_data_interval"):Get(); end; if (!self.NextCheckEmpty) then @@ -1663,7 +1690,7 @@ function Clockwork:Tick() end; if (curTime >= v.cwNextThink) then - Clockwork.player:CallThinkHook( + cwPly:CallThinkHook( v, (curTime >= v.cwNextSetSharedVars), curTime ); end; @@ -1854,7 +1881,7 @@ end; function Clockwork:PlayerCanDeleteCharacter(player, character) if (self.config:Get("cash_enabled"):Get() and character.cash < self.config:Get("default_cash"):Get()) then if (!character.data["CharBanned"]) then - return "You cannot delete characters with less than "..Clockwork.kernel:FormatCash(self.config:Get("default_cash"):Get(), nil, true).."."; + return "You cannot delete characters with less than "..cwKernel:FormatCash(self.config:Get("default_cash"):Get(), nil, true).."."; end; end; end; @@ -1876,12 +1903,12 @@ function Clockwork:PlayerCanUseCharacter(player, character) return character.name.." is banned and cannot be used!"; end; - local faction = Clockwork.faction:FindByID(character.faction); + local faction = cwFaction:FindByID(character.faction); local playerRank, rank = player:GetFactionRank(character); local factionCount = 0; local rankCount = 0; - for k, v in ipairs(cwPlayer.GetAll()) do + for k, v in ipairs(_player.GetAll()) do if (v:HasInitialized()) then if (v:GetFaction() == character.faction) then if (player != v) then @@ -1907,17 +1934,17 @@ end; -- Called when a player's weapons should be given. function Clockwork:PlayerGiveWeapons(player) local rankName, rank = player:GetFactionRank(); - local faction = Clockwork.faction:FindByID(player:GetFaction()); + local faction = cwFaction:FindByID(player:GetFaction()); if (rank and rank.weapons) then for k, v in pairs(rank.weapons) do - Clockwork.player:GiveSpawnWeapon(player, v); + cwPly:GiveSpawnWeapon(player, v); end; end; if (faction and faction.weapons) then for k, v in pairs(faction.weapons) do - Clockwork.player:GiveSpawnWeapon(player, v); + cwPly:GiveSpawnWeapon(player, v); end; end; end; @@ -2077,8 +2104,8 @@ end; -- Called when a player's model should be set. function Clockwork:PlayerSetModel(player) - Clockwork.player:SetDefaultModel(player); - Clockwork.player:SetDefaultSkin(player); + cwPly:SetDefaultModel(player); + cwPly:SetDefaultSkin(player); end; -- Called to check if a player does have door access. @@ -2305,13 +2332,13 @@ end; -- Called when a player speaks from the client. function Clockwork:PlayerSay(player, text, bPublic) - local prefix = Clockwork.config:Get("command_prefix"):Get(); + local prefix = cwConfig:Get("command_prefix"):Get(); local prefixLength = string.len(prefix); if (string.sub(text, 1, prefixLength) == prefix) then - local arguments = Clockwork.kernel:ExplodeByTags(text, " ", "\"", "\"", true); + local arguments = cwKernel:ExplodeByTags(text, " ", "\"", "\"", true); local command = string.sub(arguments[1], prefixLength + 1); - local realCommand = Clockwork.command:GetAlias()[command] or command; + local realCommand = cwCommand:GetAlias()[command] or command; return string.Replace(text, prefix..command, prefix..realCommand); end; @@ -2617,7 +2644,7 @@ function Clockwork:EntityHandleMenuOption(player, entity, option, arguments) end; end; - Clockwork.plugin:Call( + cwPlugin:Call( "PlayerPickupItem", player, itemTable, entity, bQuickUse ); @@ -2720,7 +2747,7 @@ function Clockwork:EntityHandleMenuOption(player, entity, option, arguments) inventory = entity.cwInventory, isOneSided = true, OnClose = function(player, storageTable, entity) - if (IsValid(entity) and Clockwork.inventory:IsEmpty(entity.cwInventory)) then + if (IsValid(entity) and cwInventory:IsEmpty(entity.cwInventory)) then entity:Explode(entity:BoundingRadius() * 2); entity:Remove(); end; @@ -2773,7 +2800,7 @@ function Clockwork:PlayerSpawnedProp(player, model, entity) self.player:GiveCash(player, -info.cost, info.name); entity.cwGiveRefundTab = {CurTime() + 10, player, info.cost}; else - self.player:Notify(player, L(player, "YouNeedAnother", Clockwork.kernel:FormatCash(info.cost - player:GetCash(), nil, true))); + self.player:Notify(player, L(player, "YouNeedAnother", cwKernel:FormatCash(info.cost - player:GetCash(), nil, true))); entity:Remove(); return; end; @@ -3043,10 +3070,10 @@ function Clockwork:PlayerCharacterInitialized(player) player:NetworkAccessories(); end); - Clockwork.datastream:Start(player, "CharacterInit", player:GetCharacterKey()); + cwDatastream:Start(player, "CharacterInit", player:GetCharacterKey()); - local faction = Clockwork.faction:FindByID(player:GetFaction()); - local spawnRank = Clockwork.faction:GetDefaultRank(player:GetFaction()) or Clockwork.faction:GetLowestRank(player:GetFaction()); + local faction = cwFaction:FindByID(player:GetFaction()); + local spawnRank = cwFaction:GetDefaultRank(player:GetFaction()) or cwFaction:GetLowestRank(player:GetFaction()); player:SetFactionRank(player:GetFactionRank() or spawnRank); @@ -3057,9 +3084,9 @@ function Clockwork:PlayerCharacterInitialized(player) local rankName, rankTable = player:GetFactionRank(); if (rankTable) then - if (rankTable.class and Clockwork.class.stored[rankTable.class]) then + if (rankTable.class and cwClass:GetAll()[rankTable.class]) then - Clockwork.class:Set(player, rankTable.class); + cwClass:Set(player, rankTable.class); end; if (rankTable.model) then @@ -3125,7 +3152,7 @@ function Clockwork:PlayerCharacterLoaded(player) local playerFlags = player:GetPlayerFlags(); if (onNextLoad != "") then - local queryObj = Clockwork.database:Update(charactersTable); + local queryObj = cwDatabase:Update(charactersTable); queryObj:SetValue("_OnNextLoad", ""); queryObj:AddWhere("_Schema = ?", schemaFolder); queryObj:AddWhere("_SteamID = ?", steamID); @@ -3141,7 +3168,7 @@ function Clockwork:PlayerCharacterLoaded(player) CHARACTER = nil; end; - local itemsList = Clockwork.inventory:GetAsItemsList( + local itemsList = cwInventory:GetAsItemsList( player:GetInventory() ); @@ -3152,7 +3179,7 @@ function Clockwork:PlayerCharacterLoaded(player) end; if (playerFlags) then - Clockwork.player:GiveFlags(player, playerFlags); + cwPly:GiveFlags(player, playerFlags); end; end; @@ -3166,7 +3193,7 @@ function Clockwork:PlayerConfigInitialized(player) if (!player:IsBot()) then timer.Simple(FrameTime() * 32, function() if (IsValid(player)) then - Clockwork.datastream:Start(player, "DataStreaming", true); + cwDatastream:Start(player, "DataStreaming", true); end; end); else @@ -3227,9 +3254,9 @@ function Clockwork:PlayerAdjustDeathInfo(player, info) end; -- Called when chat box info should be adjusted. function Clockwork:ChatBoxAdjustInfo(info) if (info.class == "ic") then - Clockwork.kernel:PrintLog(LOGTYPE_GENERIC, info.speaker:Name().." says: \""..info.text.."\""); + cwKernel:PrintLog(LOGTYPE_GENERIC, info.speaker:Name().." says: \""..info.text.."\""); elseif (info.class == "looc") then - Clockwork.kernel:PrintLog(LOGTYPE_GENERIC, "[LOOC] "..info.speaker:Name()..": "..info.text); + cwKernel:PrintLog(LOGTYPE_GENERIC, "[LOOC] "..info.speaker:Name()..": "..info.text); end; end; @@ -3379,7 +3406,7 @@ function Clockwork:ItemEntityDestroyed(itemEntity, itemTable) end; function Clockwork:ItemGetNetworkObservers(itemTable, info) local uniqueID = itemTable("uniqueID"); local itemID = itemTable("itemID"); - local entity = Clockwork.item:FindEntityByInstance(itemTable); + local entity = cwItem:FindEntityByInstance(itemTable); if (entity) then info.sendToAll = true; @@ -3435,7 +3462,7 @@ function Clockwork:PlayerLoadout(player) if (weapons) then for k, v in pairs(weapons) do if (!player:HasItemByID(v)) then - local itemTable = Clockwork.item:CreateInstance(v); + local itemTable = cwItem:CreateInstance(v); if (!self.player:GiveSpawnItemWeapon(player, itemTable)) then player:Give(v); @@ -3464,7 +3491,7 @@ end; -- Called when a player presses F1. function Clockwork:ShowHelp(player) - Clockwork.datastream:Start(player, "InfoToggle", true); + cwDatastream:Start(player, "InfoToggle", true); end; -- Called when a player presses F2. @@ -3516,7 +3543,7 @@ function Clockwork:ShowTeam(ply) if (self.config:Get("recognise_system"):Get()) then if (doRecogniseMenu) then - Clockwork.datastream:Start(ply, "RecogniseMenu", true); + cwDatastream:Start(ply, "RecogniseMenu", true); end; end; end; @@ -3786,7 +3813,7 @@ function Clockwork:KeyPress(player, key) local velocity = player:GetVelocity():Length(); if (velocity > 0 and !player:KeyDown(IN_SPEED)) then - if (player:GetSharedVar("IsJogMode") or !Clockwork.config:Get("enable_jogging"):Get()) then + if (player:GetSharedVar("IsJogMode") or !cwConfig:Get("enable_jogging"):Get()) then player:SetSharedVar("IsJogMode", false); else player:SetSharedVar("IsJogMode", true); @@ -3805,12 +3832,12 @@ function Clockwork:KeyPress(player, key) player.cwReloadHoldTime = CurTime() + 0.25; end; elseif (key == IN_ATTACK or key == IN_ATTACK2) then - if (Clockwork.player:GetWeaponRaised(player) == false) then + if (cwPly:GetWeaponRaised(player) == false) then local weapon = player:GetActiveWeapon(); - local bQuickRaise = Clockwork.plugin:Call("PlayerCanQuickRaise", player, weapon, key); + local bQuickRaise = cwPlugin:Call("PlayerCanQuickRaise", player, weapon, key); if (bQuickRaise) then - Clockwork.player:ToggleWeaponRaised(player); + cwPly:ToggleWeaponRaised(player); end; end; end; @@ -3851,8 +3878,8 @@ function Clockwork:PlayerSpawnedNPC(player, npc) prevRelation = prevRelation or {}; prevRelation[player:SteamID()] = prevRelation[player:SteamID()] or {}; - for k, v in pairs(cwPlayer.GetAll()) do - faction = Clockwork.faction:FindByID(v:GetFaction()); + for k, v in pairs(_player.GetAll()) do + faction = cwFaction:FindByID(v:GetFaction()); relation = faction.entRelationship; if (istable(relation)) then @@ -3884,7 +3911,7 @@ end; @param Number The amount that is being progressed for editing purposes. --]] function Clockwork:OnAttributeProgress(player, attribute, amount) - amount = amount * Clockwork.config:Get("scale_attribute_progress"):Get(); + amount = amount * cwConfig:Get("scale_attribute_progress"):Get(); end; --[[ @@ -3926,14 +3953,14 @@ end; function Clockwork:PostCommandUsed(player, command, arguments) end; -- GetTargetRecognises datastream callback. -Clockwork.datastream:Hook("GetTargetRecognises", function(player, data) +cwDatastream:Hook("GetTargetRecognises", function(player, data) if (IsValid(data) and data:IsPlayer()) then - player:SetSharedVar("TargetKnows", Clockwork.player:DoesRecognise(data, player)); + player:SetSharedVar("TargetKnows", cwPly:DoesRecognise(data, player)); end; end); -- EntityMenuOption datastream callback. -Clockwork.datastream:Hook("EntityMenuOption", function(player, data) +cwDatastream:Hook("EntityMenuOption", function(player, data) local entity = data[1]; local option = data[2]; local shootPos = player:GetShootPos(); @@ -3942,13 +3969,13 @@ Clockwork.datastream:Hook("EntityMenuOption", function(player, data) if (IsValid(entity) and type(option) == "string") then if (entity:NearestPoint(shootPos):Distance(shootPos) <= 80) then - if (Clockwork.plugin:Call("PlayerUse", player, entity)) then + if (cwPlugin:Call("PlayerUse", player, entity)) then if (!player.nextEntityHandle or player.nextEntityHandle <= curTime) then - Clockwork.plugin:Call("EntityHandleMenuOption", player, entity, option, arguments); + cwPlugin:Call("EntityHandleMenuOption", player, entity, option, arguments); - player.nextEntityHandle = curTime + Clockwork.config:Get("entity_handle_time"):Get(); + player.nextEntityHandle = curTime + cwConfig:Get("entity_handle_time"):Get(); else - Clockwork.player:Notify(player, L(player, "EntityOptionWaitTime")); + cwPly:Notify(player, L(player, "EntityOptionWaitTime")); end; end; end; @@ -3956,7 +3983,7 @@ Clockwork.datastream:Hook("EntityMenuOption", function(player, data) end); -- MenuOption datastream callback. -Clockwork.datastream:Hook("MenuOption", function(player, data) +cwDatastream:Hook("MenuOption", function(player, data) local item = data.item; local option = data.option; local entity = data.entity; @@ -3967,7 +3994,7 @@ Clockwork.datastream:Hook("MenuOption", function(player, data) data = {data}; end; - local itemTable = Clockwork.item:FindInstance(item); + local itemTable = cwItem:FindInstance(item); if (itemTable and itemTable:IsInstance() and type(option) == "string") then if (itemTable.HandleOptions) then if (player:HasItemInstance(itemTable)) then @@ -3980,13 +4007,13 @@ Clockwork.datastream:Hook("MenuOption", function(player, data) end); -- DataStreamInfoSent datastream callback. -Clockwork.datastream:Hook("DataStreamInfoSent", function(player, data) +cwDatastream:Hook("DataStreamInfoSent", function(player, data) if (!player.cwDataStreamInfoSent) then - Clockwork.plugin:Call("PlayerDataStreamInfoSent", player); + cwPlugin:Call("PlayerDataStreamInfoSent", player); timer.Simple(FrameTime() * 32, function() if (IsValid(player)) then - Clockwork.datastream:Start(player, "DataStreamed", true); + cwDatastream:Start(player, "DataStreamed", true); end; end); @@ -3995,18 +4022,18 @@ Clockwork.datastream:Hook("DataStreamInfoSent", function(player, data) end); -- LocalPlayerCreated datastream callback. -Clockwork.datastream:Hook("LocalPlayerCreated", function(player, data) +cwDatastream:Hook("LocalPlayerCreated", function(player, data) if (IsValid(player) and !player:HasConfigInitialized()) then - Clockwork.kernel:CreateTimer("SendCfg"..player:UniqueID(), FrameTime(), 1, function() + cwKernel:CreateTimer("SendCfg"..player:UniqueID(), FrameTime(), 1, function() if (IsValid(player)) then - Clockwork.config:Send(player); + cwConfig:Send(player); end; end); end; end); -- InteractCharacter datastream callback. -Clockwork.datastream:Hook("InteractCharacter", function(player, data) +cwDatastream:Hook("InteractCharacter", function(player, data) local characterID = data.characterID; local action = data.action; @@ -4014,134 +4041,134 @@ Clockwork.datastream:Hook("InteractCharacter", function(player, data) local character = player:GetCharacters()[characterID]; if (character) then - local fault = Clockwork.plugin:Call("PlayerCanInteractCharacter", player, action, character); + local fault = cwPlugin:Call("PlayerCanInteractCharacter", player, action, character); if (fault == false or type(fault) == "string") then - return Clockwork.player:SetCreateFault(fault or "You cannot interact with this character!"); + return cwPly:SetCreateFault(fault or "You cannot interact with this character!"); elseif (action == "delete") then - local bSuccess, fault = Clockwork.player:DeleteCharacter(player, characterID); + local bSuccess, fault = cwPly:DeleteCharacter(player, characterID); if (!bSuccess) then - Clockwork.player:SetCreateFault(player, fault); + cwPly:SetCreateFault(player, fault); end; elseif (action == "use") then - local bSuccess, fault = Clockwork.player:UseCharacter(player, characterID); + local bSuccess, fault = cwPly:UseCharacter(player, characterID); if (!bSuccess) then - Clockwork.player:SetCreateFault(player, fault); + cwPly:SetCreateFault(player, fault); end; else - Clockwork.plugin:Call("PlayerSelectCustomCharacterOption", player, action, character); + cwPlugin:Call("PlayerSelectCustomCharacterOption", player, action, character); end; end; end; end); -- GetQuizStatus datastream callback. -Clockwork.datastream:Hook("GetQuizStatus", function(player, data) - if (!Clockwork.quiz:GetEnabled() or Clockwork.quiz:GetCompleted(player)) then - Clockwork.datastream:Start(player, "QuizCompleted", true); +cwDatastream:Hook("GetQuizStatus", function(player, data) + if (!cwQuiz:GetEnabled() or cwQuiz:GetCompleted(player)) then + cwDatastream:Start(player, "QuizCompleted", true); else - Clockwork.datastream:Start(player, "QuizCompleted", false); + cwDatastream:Start(player, "QuizCompleted", false); end; end); -- DoorManagement datastream callback. -Clockwork.datastream:Hook("DoorManagement", function(player, data) +cwDatastream:Hook("DoorManagement", function(player, data) if (IsValid(data[1]) and player:GetEyeTraceNoCursor().Entity == data[1]) then if (data[1]:GetPos():Distance(player:GetPos()) <= 192) then if (data[2] == "Purchase") then - if (!Clockwork.entity:GetOwner(data[1])) then + if (!cwEntity:GetOwner(data[1])) then if (hook.Call("PlayerCanOwnDoor", Clockwork, player, data[1])) then - local doors = Clockwork.player:GetDoorCount(player); + local doors = cwPly:GetDoorCount(player); - if (doors == Clockwork.config:Get("max_doors"):Get()) then - Clockwork.player:Notify(player, L(player, "CannotPurchaseAnotherDoor")); + if (doors == cwConfig:Get("max_doors"):Get()) then + cwPly:Notify(player, L(player, "CannotPurchaseAnotherDoor")); else - local doorCost = Clockwork.config:Get("door_cost"):Get(); + local doorCost = cwConfig:Get("door_cost"):Get(); - if (doorCost == 0 or Clockwork.player:CanAfford(player, doorCost)) then - local doorName = Clockwork.entity:GetDoorName(data[1]); + if (doorCost == 0 or cwPly:CanAfford(player, doorCost)) then + local doorName = cwEntity:GetDoorName(data[1]); if (doorName == "false" or doorName == "hidden" or doorName == "") then doorName = "Door"; end; if (doorCost > 0) then - Clockwork.player:GiveCash(player, -doorCost, doorName); + cwPly:GiveCash(player, -doorCost, doorName); end; - Clockwork.player:GiveDoor(player, data[1]); + cwPly:GiveDoor(player, data[1]); else local amount = doorCost - player:GetCash(); - Clockwork.player:Notify(player, L(player, "YouNeedAnother", - Clockwork.kernel:FormatCash(amount, nil, true)) + cwPly:Notify(player, L(player, "YouNeedAnother", + cwKernel:FormatCash(amount, nil, true)) ); end; end; end; end; elseif (data[2] == "Access") then - if (Clockwork.player:HasDoorAccess(player, data[1], DOOR_ACCESS_COMPLETE)) then - if (IsValid(data[3]) and data[3] != player and data[3] != Clockwork.entity:GetOwner(data[1])) then + if (cwPly:HasDoorAccess(player, data[1], DOOR_ACCESS_COMPLETE)) then + if (IsValid(data[3]) and data[3] != player and data[3] != cwEntity:GetOwner(data[1])) then if (data[4] == DOOR_ACCESS_COMPLETE) then - if (Clockwork.player:HasDoorAccess(data[3], data[1], DOOR_ACCESS_COMPLETE)) then - Clockwork.player:GiveDoorAccess(data[3], data[1], DOOR_ACCESS_BASIC); + if (cwPly:HasDoorAccess(data[3], data[1], DOOR_ACCESS_COMPLETE)) then + cwPly:GiveDoorAccess(data[3], data[1], DOOR_ACCESS_BASIC); else - Clockwork.player:GiveDoorAccess(data[3], data[1], DOOR_ACCESS_COMPLETE); + cwPly:GiveDoorAccess(data[3], data[1], DOOR_ACCESS_COMPLETE); end; elseif (data[4] == DOOR_ACCESS_BASIC) then - if (Clockwork.player:HasDoorAccess(data[3], data[1], DOOR_ACCESS_BASIC)) then - Clockwork.player:TakeDoorAccess(data[3], data[1]); + if (cwPly:HasDoorAccess(data[3], data[1], DOOR_ACCESS_BASIC)) then + cwPly:TakeDoorAccess(data[3], data[1]); else - Clockwork.player:GiveDoorAccess(data[3], data[1], DOOR_ACCESS_BASIC); + cwPly:GiveDoorAccess(data[3], data[1], DOOR_ACCESS_BASIC); end; end; - if (Clockwork.player:HasDoorAccess(data[3], data[1], DOOR_ACCESS_COMPLETE)) then - Clockwork.datastream:Start(player, "DoorAccess", {data[3], DOOR_ACCESS_COMPLETE}); - elseif (Clockwork.player:HasDoorAccess(data[3], data[1], DOOR_ACCESS_BASIC)) then - Clockwork.datastream:Start(player, "DoorAccess", {data[3], DOOR_ACCESS_BASIC}); + if (cwPly:HasDoorAccess(data[3], data[1], DOOR_ACCESS_COMPLETE)) then + cwDatastream:Start(player, "DoorAccess", {data[3], DOOR_ACCESS_COMPLETE}); + elseif (cwPly:HasDoorAccess(data[3], data[1], DOOR_ACCESS_BASIC)) then + cwDatastream:Start(player, "DoorAccess", {data[3], DOOR_ACCESS_BASIC}); else - Clockwork.datastream:Start(player, "DoorAccess", {data[3]}); + cwDatastream:Start(player, "DoorAccess", {data[3]}); end; end; end; elseif (data[2] == "Unshare") then - if (Clockwork.entity:IsDoorParent(data[1])) then + if (cwEntity:IsDoorParent(data[1])) then if (data[3] == "Text") then - Clockwork.datastream:Start(player, "SetSharedText", false); + cwDatastream:Start(player, "SetSharedText", false); data[1].cwDoorSharedTxt = nil; else - Clockwork.datastream:Start(player, "SetSharedAccess", false); + cwDatastream:Start(player, "SetSharedAccess", false); data[1].cwDoorSharedAxs = nil; end; end; elseif (data[2] == "Share") then - if (Clockwork.entity:IsDoorParent(data[1])) then + if (cwEntity:IsDoorParent(data[1])) then if (data[3] == "Text") then - Clockwork.datastream:Start(player, "SetSharedText", true); + cwDatastream:Start(player, "SetSharedText", true); data[1].cwDoorSharedTxt = true; else - Clockwork.datastream:Start(player, "SetSharedAccess", true); + cwDatastream:Start(player, "SetSharedAccess", true); data[1].cwDoorSharedAxs = true; end; end; elseif (data[2] == "Text" and data[3] != "") then - if (Clockwork.player:HasDoorAccess(player, data[1], DOOR_ACCESS_COMPLETE)) then + if (cwPly:HasDoorAccess(player, data[1], DOOR_ACCESS_COMPLETE)) then if (!string.find(string.gsub(string.lower(data[3]), "%s", ""), "thisdoorcanbepurchased") and string.find(data[3], "%w")) then - Clockwork.entity:SetDoorText(data[1], string.utf8sub(data[3], 1, 32)); + cwEntity:SetDoorText(data[1], string.utf8sub(data[3], 1, 32)); end; end; elseif (data[2] == "Sell") then - if (Clockwork.entity:GetOwner(data[1]) == player) then - if (!Clockwork.entity:IsDoorUnsellable(data[1])) then - Clockwork.player:TakeDoor(player, data[1]); + if (cwEntity:GetOwner(data[1]) == player) then + if (!cwEntity:IsDoorUnsellable(data[1])) then + cwPly:TakeDoor(player, data[1]); end; end; end; @@ -4150,34 +4177,34 @@ Clockwork.datastream:Hook("DoorManagement", function(player, data) end); -- CreateCharacter datastream callback. -Clockwork.datastream:Hook("CreateCharacter", function(player, data) - Clockwork.player:CreateCharacterFromData(player, data); +cwDatastream:Hook("CreateCharacter", function(player, data) + cwPly:CreateCharacterFromData(player, data); end); -- RecogniseOption datastream callback. -Clockwork.datastream:Hook("RecogniseOption", function(player, data) +cwDatastream:Hook("RecogniseOption", function(player, data) local recogniseData = data; - if (Clockwork.config:Get("recognise_system"):Get()) then + if (cwConfig:Get("recognise_system"):Get()) then if (type(recogniseData) == "string") then local playSound = false; if (recogniseData == "look") then local target = player:GetEyeTraceNoCursor().Entity; - if (target:HasInitialized() and !Clockwork.player:IsNoClipping(target) and target != player) then - Clockwork.player:SetRecognises(target, player, RECOGNISE_SAVE); + if (target:HasInitialized() and !cwPly:IsNoClipping(target) and target != player) then + cwPly:SetRecognises(target, player, RECOGNISE_SAVE); playSound = true; end; else local position = player:GetPos(); local plyTable = _player.GetAll(); - local talkRadius = Clockwork.config:Get("talk_radius"):Get(); + local talkRadius = cwConfig:Get("talk_radius"):Get(); for k, v in pairs(plyTable) do if (v:HasInitialized() and player != v) then - if (!Clockwork.player:IsNoClipping(v)) then + if (!cwPly:IsNoClipping(v)) then local distance = v:GetPos():Distance(position); local recognise = false; @@ -4196,7 +4223,7 @@ Clockwork.datastream:Hook("RecogniseOption", function(player, data) end; if (recognise) then - Clockwork.player:SetRecognises(v, player, RECOGNISE_SAVE); + cwPly:SetRecognises(v, player, RECOGNISE_SAVE); if (!playSound) then playSound = true; @@ -4208,37 +4235,37 @@ Clockwork.datastream:Hook("RecogniseOption", function(player, data) end; if (playSound) then - Clockwork.player:PlaySound(player, "buttons/button17.wav"); + cwPly:PlaySound(player, "buttons/button17.wav"); end; end; end; end); -- QuizCompleted datastream callback. -Clockwork.datastream:Hook("QuizCompleted", function(player, data) - if (player.cwQuizAnswers and !Clockwork.quiz:GetCompleted(player)) then - local questionsAmount = Clockwork.quiz:GetQuestionsAmount(); +cwDatastream:Hook("QuizCompleted", function(player, data) + if (player.cwQuizAnswers and !cwQuiz:GetCompleted(player)) then + local questionsAmount = cwQuiz:GetQuestionsAmount(); local correctAnswers = 0; - local quizQuestions = Clockwork.quiz:GetQuestions(); + local quizQuestions = cwQuiz:GetQuestions(); for k, v in pairs(quizQuestions) do if (player.cwQuizAnswers[k]) then - if (Clockwork.quiz:IsAnswerCorrect(k, player.cwQuizAnswers[k])) then + if (cwQuiz:IsAnswerCorrect(k, player.cwQuizAnswers[k])) then correctAnswers = correctAnswers + 1; end; end; end; - if (correctAnswers < math.Round(questionsAmount * (Clockwork.quiz:GetPercentage() / 100))) then - Clockwork.quiz:CallKickCallback(player, correctAnswers); + if (correctAnswers < math.Round(questionsAmount * (cwQuiz:GetPercentage() / 100))) then + cwQuiz:CallKickCallback(player, correctAnswers); else - Clockwork.quiz:SetCompleted(player, true); + cwQuiz:SetCompleted(player, true); end; end; end); -- UnequipItem datastream callback. -Clockwork.datastream:Hook("UnequipItem", function(player, data) +cwDatastream:Hook("UnequipItem", function(player, data) local arguments = data[3]; local uniqueID = data[1]; local itemID = data[2]; @@ -4263,7 +4290,7 @@ Clockwork.datastream:Hook("UnequipItem", function(player, data) end); -- QuizAnswer datastream callback. -Clockwork.datastream:Hook("QuizAnswer", function(player, data) +cwDatastream:Hook("QuizAnswer", function(player, data) if (!player.cwQuizAnswers) then player.cwQuizAnswers = {}; end; @@ -4271,7 +4298,7 @@ Clockwork.datastream:Hook("QuizAnswer", function(player, data) local question = data[1]; local answer = data[2]; - if (Clockwork.quiz:GetQuestion(question)) then + if (cwQuiz:GetQuestion(question)) then player.cwQuizAnswers[question] = answer; end; end); @@ -4313,10 +4340,10 @@ end; -- A function to make a player fire bullets. function entityMeta:FireBullets(bulletInfo) if (self:IsPlayer()) then - Clockwork.plugin:Call("PlayerAdjustBulletInfo", self, bulletInfo); + cwPlugin:Call("PlayerAdjustBulletInfo", self, bulletInfo); end; - Clockwork.plugin:Call("EntityFireBullets", self, bulletInfo); + cwPlugin:Call("EntityFireBullets", self, bulletInfo); return self:ClockworkFireBullets(bulletInfo); end; @@ -4340,26 +4367,26 @@ end; -- A function to save a player's character. function playerMeta:SaveCharacter() - Clockwork.player:SaveCharacter(self); + cwPly:SaveCharacter(self); end; -- A function to give a player an item weapon. function playerMeta:GiveItemWeapon(itemTable) - Clockwork.player:GiveItemWeapon(self, itemTable); + cwPly:GiveItemWeapon(self, itemTable); end; -- A function to give a weapon to a player. function playerMeta:Give(class, itemTable, bForceReturn) local iTeamIndex = self:Team(); - if (!Clockwork.plugin:Call("PlayerCanBeGivenWeapon", self, class, itemTable)) then + if (!cwPlugin:Call("PlayerCanBeGivenWeapon", self, class, itemTable)) then return; end; if (self:IsRagdolled() and !bForceReturn) then local ragdollWeapons = self:GetRagdollWeapons(); - local spawnWeapon = Clockwork.player:GetSpawnWeapon(self, class); - local bCanHolster = (itemTable and Clockwork.plugin:Call("PlayerCanHolsterWeapon", self, itemTable, true, true)); + local spawnWeapon = cwPly:GetSpawnWeapon(self, class); + local bCanHolster = (itemTable and cwPlugin:Call("PlayerCanHolsterWeapon", self, itemTable, true, true)); if (!spawnWeapon) then iTeamIndex = nil; end; @@ -4388,8 +4415,8 @@ function playerMeta:Give(class, itemTable, bForceReturn) local weapon = self:GetWeapon(class); if (IsValid(weapon) and itemTable) then - Clockwork.datastream:Start(self, "WeaponItemData", { - definition = Clockwork.item:GetDefinition(itemTable, true), + cwDatastream:Start(self, "WeaponItemData", { + definition = cwItem:GetDefinition(itemTable, true), weapon = weapon:EntIndex() }); @@ -4404,7 +4431,7 @@ function playerMeta:Give(class, itemTable, bForceReturn) end; end; - Clockwork.plugin:Call("PlayerGivenWeapon", self, class, itemTable); + cwPlugin:Call("PlayerGivenWeapon", self, class, itemTable); end; -- A function to get a player's data. @@ -4426,7 +4453,7 @@ function entityMeta:SetSkin(skin) self:ClockworkSetSkin(skin); if (self:IsPlayer()) then - Clockwork.plugin:Call("PlayerSkinChanged", self, skin); + cwPlugin:Call("PlayerSkinChanged", self, skin); if (self:IsRagdolled()) then self:GetRagdollTable().skin = skin; @@ -4439,7 +4466,7 @@ function entityMeta:SetModel(model) self:ClockworkSetModel(model); if (self:IsPlayer()) then - Clockwork.plugin:Call("PlayerModelChanged", self, model); + cwPlugin:Call("PlayerModelChanged", self, model); if (self:IsRagdolled()) then self:GetRagdollTable().model = model; @@ -4459,12 +4486,12 @@ end; -- A function to get whether an entity is a map entity. function entityMeta:IsMapEntity() - return Clockwork.entity:IsMapEntity(self); + return cwEntity:IsMapEntity(self); end; -- A function to get an entity's start position. function entityMeta:GetStartPosition() - return Clockwork.entity:GetStartPosition(self); + return cwEntity:GetStartPosition(self); end; -- A function to emit a hit sound for an entity. @@ -4507,19 +4534,19 @@ end; function playerMeta:SetArmor(armor) local oldArmor = self:Armor(); self:ClockworkSetArmor(armor); - Clockwork.plugin:Call("PlayerArmorSet", self, armor, oldArmor); + cwPlugin:Call("PlayerArmorSet", self, armor, oldArmor); end; -- A function to set a player's health. function playerMeta:SetHealth(health) local oldHealth = self:Health(); self:ClockworkSetHealth(health); - Clockwork.plugin:Call("PlayerHealthSet", self, health, oldHealth); + cwPlugin:Call("PlayerHealthSet", self, health, oldHealth); end; -- A function to get whether a player is noclipping. function playerMeta:IsNoClipping() - return Clockwork.player:IsNoClipping(self); + return cwPly:IsNoClipping(self); end; -- A function to get whether a player is running. @@ -4574,10 +4601,10 @@ function playerMeta:HandleAttributeProgress(curTime) self.cwAttrProgressTime = curTime + 30; for k, v in pairs(self.cwAttrProgress) do - local attributeTable = Clockwork.attribute:FindByID(k); + local attributeTable = cwAttribute:FindByID(k); if (attributeTable) then - Clockwork.datastream:Start(self, "AttributeProgress", { + cwDatastream:Start(self, "AttributeProgress", { index = attributeTable.index, amount = v }); end; @@ -4638,7 +4665,7 @@ end; -- A function to update whether a player's weapon is raised. function playerMeta:UpdateWeaponRaised() - Clockwork.player:UpdateWeaponRaised(self); + cwPly:UpdateWeaponRaised(self); end; -- A function to update whether a player's weapon has fired. @@ -4651,7 +4678,7 @@ function playerMeta:UpdateWeaponFired() if (clipOne < self.cwClipOneInfo.ammo) then self.cwClipOneInfo.ammo = clipOne; - Clockwork.plugin:Call("PlayerFireWeapon", self, activeWeapon, CLIP_ONE, activeWeapon:GetPrimaryAmmoType()); + cwPlugin:Call("PlayerFireWeapon", self, activeWeapon, CLIP_ONE, activeWeapon:GetPrimaryAmmoType()); end; else self.cwClipOneInfo.weapon = activeWeapon; @@ -4663,7 +4690,7 @@ function playerMeta:UpdateWeaponFired() if (clipTwo < self.cwClipTwoInfo.ammo) then self.cwClipTwoInfo.ammo = clipTwo; - Clockwork.plugin:Call("PlayerFireWeapon", self, activeWeapon, CLIP_TWO, activeWeapon:GetSecondaryAmmoType()); + cwPlugin:Call("PlayerFireWeapon", self, activeWeapon, CLIP_TWO, activeWeapon:GetSecondaryAmmoType()); end; else self.cwClipTwoInfo.weapon = activeWeapon; @@ -4701,17 +4728,17 @@ end; -- A function to get whether a player is using their hands. function playerMeta:IsUsingHands() - return Clockwork.player:GetWeaponClass(self) == "cw_hands"; + return cwPly:GetWeaponClass(self) == "cw_hands"; end; -- A function to get whether a player is using their hands. function playerMeta:IsUsingKeys() - return Clockwork.player:GetWeaponClass(self) == "cw_keys"; + return cwPly:GetWeaponClass(self) == "cw_keys"; end; -- A function to get a player's wages. function playerMeta:GetWages() - return Clockwork.player:GetWages(self); + return cwPly:GetWages(self); end; -- A function to get a player's community ID. @@ -4727,7 +4754,7 @@ end; -- A function to get whether a player is ragdolled. function playerMeta:IsRagdolled(exception, entityless) - return Clockwork.player:IsRagdolled(self, exception, entityless); + return cwPly:IsRagdolled(self, exception, entityless); end; -- A function to get whether a player is kicked. @@ -4766,12 +4793,12 @@ end; -- A function to ban a player. function playerMeta:Ban(duration, reason) - Clockwork.bans:Add(self:SteamID(), duration * 60, reason); + cwBans:Add(self:SteamID(), duration * 60, reason); end; -- A function to get a player's cash. function playerMeta:GetCash() - if (Clockwork.config:Get("cash_enabled"):Get()) then + if (cwConfig:Get("cash_enabled"):Get()) then return self:QueryCharacter("Cash"); else return 0; @@ -4814,22 +4841,22 @@ function playerMeta:GetRecognisedNames() end; -- A function to get a player's character table. -function playerMeta:GetCharacter() return Clockwork.player:GetCharacter(self); end; +function playerMeta:GetCharacter() return cwPly:GetCharacter(self); end; -- A function to get a player's storage table. -function playerMeta:GetStorageTable() return Clockwork.storage:GetTable(self); end; +function playerMeta:GetStorageTable() return cwStorage:GetTable(self); end; -- A function to get a player's ragdoll table. -function playerMeta:GetRagdollTable() return Clockwork.player:GetRagdollTable(self); end; +function playerMeta:GetRagdollTable() return cwPly:GetRagdollTable(self); end; -- A function to get a player's ragdoll state. -function playerMeta:GetRagdollState() return Clockwork.player:GetRagdollState(self); end; +function playerMeta:GetRagdollState() return cwPly:GetRagdollState(self); end; -- A function to get a player's storage entity. -function playerMeta:GetStorageEntity() return Clockwork.storage:GetEntity(self); end; +function playerMeta:GetStorageEntity() return cwStorage:GetEntity(self); end; -- A function to get a player's ragdoll entity. -function playerMeta:GetRagdollEntity() return Clockwork.player:GetRagdollEntity(self); end; +function playerMeta:GetRagdollEntity() return cwPly:GetRagdollEntity(self); end; -- A function to get a player's ragdoll weapons. function playerMeta:GetRagdollWeapons() @@ -4894,28 +4921,28 @@ end; -- A function to get whether an entity is being held. function entityMeta:IsBeingHeld() if (IsValid(self)) then - return Clockwork.plugin:Call("GetEntityBeingHeld", self); + return cwPlugin:Call("GetEntityBeingHeld", self); end; end; -- A function to run a command on a player. function playerMeta:RunCommand(...) - Clockwork.datastream:Start(self, "RunCommand", {...}); + cwDatastream:Start(self, "RunCommand", {...}); end; -- A function to run a Clockwork command on a player. function playerMeta:RunClockworkCmd(command, ...) - Clockwork.player:RunClockworkCommand(self, command, ...) + cwPly:RunClockworkCommand(self, command, ...) end; -- A function to get a player's wages name. function playerMeta:GetWagesName() - return Clockwork.player:GetWagesName(self); + return cwPly:GetWagesName(self); end; -- A function to create a player'a animation stop delay. function playerMeta:CreateAnimationStopDelay(delay) - Clockwork.kernel:CreateTimer("ForcedAnim"..self:UniqueID(), delay, 1, function() + cwKernel:CreateTimer("ForcedAnim"..self:UniqueID(), delay, 1, function() if (IsValid(self)) then local forcedAnimation = self:GetForcedAnimation(); @@ -4960,7 +4987,7 @@ function playerMeta:SetForcedAnimation(animation, delay, OnAnimate, OnFinish) }; if (bIsPermanent) then - Clockwork.kernel:DestroyTimer( + cwKernel:DestroyTimer( "ForcedAnim"..self:UniqueID() ); else @@ -5050,7 +5077,7 @@ function playerMeta:SetClockworkUserGroup(userGroup) self:SetUserGroup(userGroup); self:SaveCharacter(); - Clockwork.plugin:Call("OnPlayerUserGroupSet", self, userGroup); + cwPlugin:Call("OnPlayerUserGroupSet", self, userGroup); end; end; @@ -5072,21 +5099,21 @@ end; -- A function to get a player's items by ID. function playerMeta:GetItemsByID(uniqueID) - return Clockwork.inventory:GetItemsByID( + return cwInventory:GetItemsByID( self:GetInventory(), uniqueID ); end; -- A function to find a player's items by name. function playerMeta:FindItemsByName(uniqueID, name) - return Clockwork.inventory:FindItemsByName( + return cwInventory:FindItemsByName( self:GetInventory(), uniqueID, name ); end; -- A function to get the maximum weight a player can carry. function playerMeta:GetMaxWeight() - local itemsList = Clockwork.inventory:GetAsItemsList(self:GetInventory()); + local itemsList = cwInventory:GetAsItemsList(self:GetInventory()); local weight = self:GetSharedVar("InvWeight"); for k, v in pairs(itemsList) do @@ -5101,7 +5128,7 @@ end; -- A function to get the maximum space a player can carry. function playerMeta:GetMaxSpace() - local itemsList = Clockwork.inventory:GetAsItemsList(self:GetInventory()); + local itemsList = cwInventory:GetAsItemsList(self:GetInventory()); local space = self:GetSharedVar("InvSpace"); for k, v in pairs(itemsList) do @@ -5116,7 +5143,7 @@ end; -- A function to get whether a player can hold a weight. function playerMeta:CanHoldWeight(weight) - local inventoryWeight = Clockwork.inventory:CalculateWeight( + local inventoryWeight = cwInventory:CalculateWeight( self:GetInventory() ); @@ -5129,11 +5156,11 @@ end; -- A function to get whether a player can hold a weight. function playerMeta:CanHoldSpace(space) - if (!Clockwork.inventory:UseSpaceSystem()) then + if (!cwInventory:UseSpaceSystem()) then return true; end; - local inventorySpace = Clockwork.inventory:CalculateSpace( + local inventorySpace = cwInventory:CalculateSpace( self:GetInventory() ); @@ -5146,38 +5173,38 @@ end; -- A function to get a player's inventory weight. function playerMeta:GetInventoryWeight() - return Clockwork.inventory:CalculateWeight(self:GetInventory()); + return cwInventory:CalculateWeight(self:GetInventory()); end; -- A function to get a player's inventory weight. function playerMeta:GetInventorySpace() - return Clockwork.inventory:CalculateSpace(self:GetInventory()); + return cwInventory:CalculateSpace(self:GetInventory()); end; -- A function to get whether a player has an item by ID. function playerMeta:HasItemByID(uniqueID) - return Clockwork.inventory:HasItemByID( + return cwInventory:HasItemByID( self:GetInventory(), uniqueID ); end; -- A function to count how many items a player has by ID. function playerMeta:GetItemCountByID(uniqueID) - return Clockwork.inventory:GetItemCountByID( + return cwInventory:GetItemCountByID( self:GetInventory(), uniqueID ); end; -- A function to get whether a player has a certain amount of items by ID. function playerMeta:HasItemCountByID(uniqueID, amount) - return Clockwork.inventory:HasItemCountByID( + return cwInventory:HasItemCountByID( self:GetInventory(), uniqueID, amount ); end; -- A function to find a player's item by ID. function playerMeta:FindItemByID(uniqueID, itemID) - return Clockwork.inventory:FindItemByID( + return cwInventory:FindItemByID( self:GetInventory(), uniqueID, itemID ); end; @@ -5185,7 +5212,7 @@ end; -- A function to get whether a player has an item as a weapon. function playerMeta:HasItemAsWeapon(itemTable) for k, v in pairs(self:GetWeapons()) do - local weaponItemTable = Clockwork.item:GetByWeapon(v); + local weaponItemTable = cwItem:GetByWeapon(v); if (itemTable:IsTheSameAs(weaponItemTable)) then return true; end; @@ -5197,7 +5224,7 @@ end; -- A function to find a player's weapon item by ID. function playerMeta:FindWeaponItemByID(uniqueID, itemID) for k, v in pairs(self:GetWeapons()) do - local weaponItemTable = Clockwork.item:GetByWeapon(v); + local weaponItemTable = cwItem:GetByWeapon(v); if (weaponItemTable and weaponItemTable("uniqueID") == uniqueID and weaponItemTable("itemID") == itemID) then return weaponItemTable; @@ -5207,14 +5234,14 @@ end; -- A function to get whether a player has an item instance. function playerMeta:HasItemInstance(itemTable) - return Clockwork.inventory:HasItemInstance( + return cwInventory:HasItemInstance( self:GetInventory(), itemTable ); end; -- A function to get a player's item instance. function playerMeta:GetItemInstance(uniqueID, itemID) - return Clockwork.inventory:FindItemByID( + return cwInventory:FindItemByID( self:GetInventory(), uniqueID, itemID ); end; @@ -5237,13 +5264,13 @@ end; -- A function to rebuild a player's inventory. function playerMeta:RebuildInventory() - Clockwork.inventory:Rebuild(self); + cwInventory:Rebuild(self); end; -- A function to give an item to a player. function playerMeta:GiveItem(itemTable, bForce) if (type(itemTable) == "string") then - itemTable = Clockwork.item:CreateInstance(itemTable); + itemTable = cwItem:CreateInstance(itemTable); end; if (!itemTable or !itemTable:IsInstance()) then @@ -5259,11 +5286,11 @@ function playerMeta:GiveItem(itemTable, bForce) itemTable:OnGiveToPlayer(self); end; - Clockwork.kernel:PrintLog(LOGTYPE_GENERIC, self:Name().." has gained a "..itemTable("name").." "..itemTable("itemID").."."); + cwKernel:PrintLog(LOGTYPE_GENERIC, self:Name().." has gained a "..itemTable("name").." "..itemTable("itemID").."."); - Clockwork.inventory:AddInstance(inventory, itemTable); - Clockwork.datastream:Start(self, "InvGive", Clockwork.item:GetDefinition(itemTable, true)); - Clockwork.plugin:Call("PlayerItemGiven", self, itemTable, bForce); + cwInventory:AddInstance(inventory, itemTable); + cwDatastream:Start(self, "InvGive", cwItem:GetDefinition(itemTable, true)); + cwPlugin:Call("PlayerItemGiven", self, itemTable, bForce); return itemTable; else @@ -5284,11 +5311,11 @@ function playerMeta:TakeItem(itemTable) itemTable:OnTakeFromPlayer(self); end; - Clockwork.kernel:PrintLog(LOGTYPE_GENERIC, self:Name().." has lost a "..itemTable("name").." "..itemTable("itemID").."."); + cwKernel:PrintLog(LOGTYPE_GENERIC, self:Name().." has lost a "..itemTable("name").." "..itemTable("itemID").."."); - Clockwork.plugin:Call("PlayerItemTaken", self, itemTable); - Clockwork.inventory:RemoveInstance(inventory, itemTable); - Clockwork.datastream:Start(self, "InvTake", {itemTable("index"), itemTable("itemID")}); + cwPlugin:Call("PlayerItemTaken", self, itemTable); + cwInventory:RemoveInstance(inventory, itemTable); + cwDatastream:Start(self, "InvTake", {itemTable("index"), itemTable("itemID")}); return true; end; @@ -5308,22 +5335,22 @@ end -- A function to update a player's attribute. function playerMeta:UpdateAttribute(attribute, amount) - return Clockwork.attributes:Update(self, attribute, amount); + return cwAttributes:Update(self, attribute, amount); end; -- A function to progress a player's attribute. function playerMeta:ProgressAttribute(attribute, amount, gradual) - return Clockwork.attributes:Progress(self, attribute, amount, gradual); + return cwAttributes:Progress(self, attribute, amount, gradual); end; -- A function to boost a player's attribute. function playerMeta:BoostAttribute(identifier, attribute, amount, duration) - return Clockwork.attributes:Boost(self, identifier, attribute, amount, duration); + return cwAttributes:Boost(self, identifier, attribute, amount, duration); end; -- A function to get whether a boost is active for a player. function playerMeta:IsBoostActive(identifier, attribute, amount, duration) - return Clockwork.attributes:IsBoostActive(self, identifier, attribute, amount, duration); + return cwAttributes:IsBoostActive(self, identifier, attribute, amount, duration); end; -- A function to get a player's characters. @@ -5363,7 +5390,7 @@ end; -- A function to query a player's character table. function playerMeta:QueryCharacter(key, default) if (self:GetCharacter()) then - return Clockwork.player:Query(self, key, default); + return cwPly:Query(self, key, default); else return default; end; @@ -5371,12 +5398,12 @@ end; -- A function to get a player's shared variable. function playerMeta:GetSharedVar(key) - return Clockwork.player:GetSharedVar(self, key); + return cwPly:GetSharedVar(self, key); end; -- A function to set a shared variable for a player. function playerMeta:SetSharedVar(key, value, sharedTable) - Clockwork.player:SetSharedVar(self, key, value, sharedTable); + cwPly:SetSharedVar(self, key, value, sharedTable); end; -- A function to get a player's character data. @@ -5478,7 +5505,7 @@ function playerMeta:SetClothesData(itemTable) local clothesItem = self:GetClothesItem(); if (itemTable) then - local model = Clockwork.class:GetAppropriateModel(self:Team(), self, true); + local model = cwClass:GetAppropriateModel(self:Team(), self, true); if (!model) then if (clothesItem and itemTable != clothesItem) then @@ -5506,7 +5533,7 @@ end; -- A function to get the entity a player is holding. function playerMeta:GetHoldingEntity() - return Clockwork.plugin:Call("PlayerGetHoldingEntity", self) or self.cwIsHoldingEnt; + return cwPlugin:Call("PlayerGetHoldingEntity", self) or self.cwIsHoldingEnt; end; -- A function to get whether a player's character menu is reset. @@ -5516,27 +5543,27 @@ end; -- A function to get the player's active voice channel. function playerMeta:GetActiveChannel() - return Clockwork.voice:GetActiveChannel(self); + return cwVoice:GetActiveChannel(self); end; -- A function to check if a player can afford an amount. function playerMeta:CanAfford(amount) - return Clockwork.player:CanAfford(self, amount); + return cwPly:CanAfford(self, amount); end; -- A function to get a player's rank within their faction. function playerMeta:GetFactionRank(character) - return Clockwork.player:GetFactionRank(self, character); + return cwPly:GetFactionRank(self, character); end; -- A function to set a player's rank within their faction. function playerMeta:SetFactionRank(rank) - return Clockwork.player:SetFactionRank(self, rank); + return cwPly:SetFactionRank(self, rank); end; -- A function to get a player's global flags. function playerMeta:GetPlayerFlags() - return Clockwork.player:GetPlayerFlags(self); + return cwPly:GetPlayerFlags(self); end; playerMeta.GetName = playerMeta.Name; @@ -5546,12 +5573,12 @@ concommand.Add("cwStatus", function(player, command, arguments) local plyTable = player.GetAll(); if (IsValid(player)) then - if (Clockwork.player:IsAdmin(player)) then + if (cwPly:IsAdmin(player)) then player:PrintMessage(2, "# User ID | Name | Steam Name | Steam ID | IP Address"); for k, v in pairs(plyTable) do if (v:HasInitialized()) then - local status = Clockwork.plugin:Call("PlayerCanSeeStatus", player, v); + local status = cwPlugin:Call("PlayerCanSeeStatus", player, v); if (status) then player:PrintMessage(2, status); @@ -5596,7 +5623,7 @@ concommand.Add("cwc", function(player, command, arguments) if (!IsValid(player)) then -- PlySetGroup if (arguments[1] == cmdTable.sg) then - local target = Clockwork.player:FindByID(arguments[2]); + local target = cwPly:FindByID(arguments[2]); local userGroup = arguments[3]; if (userGroup != "superadmin" and userGroup != "admin" and userGroup != "operator") then @@ -5606,11 +5633,11 @@ concommand.Add("cwc", function(player, command, arguments) end; if (target) then - if (!Clockwork.player:IsProtected(target)) then + if (!cwPly:IsProtected(target)) then print("Console has set "..target:Name().."'s user group to "..userGroup.."."); - Clockwork.player:NotifyAll("Console has set "..target:Name().."'s user group to "..userGroup.."."); + cwPly:NotifyAll("Console has set "..target:Name().."'s user group to "..userGroup.."."); target:SetClockworkUserGroup(userGroup); - Clockwork.player:LightSpawn(target, true, true); + cwPly:LightSpawn(target, true, true); else MsgC(Color(255, 100, 0, 255), target:Name().." is protected!\n"); end; @@ -5621,17 +5648,17 @@ concommand.Add("cwc", function(player, command, arguments) return; -- PlyDemote elseif (arguments[1] == cmdTable.d) then - local target = Clockwork.player:FindByID(arguments[2]); + local target = cwPly:FindByID(arguments[2]); if (target) then - if (!Clockwork.player:IsProtected(target)) then + if (!cwPly:IsProtected(target)) then local userGroup = target:GetClockworkUserGroup(); if (userGroup != "user") then print("Console has demoted "..target:Name().." from "..userGroup.." to user."); - Clockwork.player:NotifyAll("Console has demoted "..target:Name().." from "..userGroup.." to user."); + cwPly:NotifyAll("Console has demoted "..target:Name().." from "..userGroup.." to user."); target:SetClockworkUserGroup("user"); - Clockwork.player:LightSpawn(target, true, true); + cwPly:LightSpawn(target, true, true); else MsgC(Color(255, 100, 0, 255), "This player is only a user and cannot be demoted!\n"); end; @@ -5645,7 +5672,7 @@ concommand.Add("cwc", function(player, command, arguments) return; -- SetCash elseif (arguments[1] == cmdTable.sc) then - local target = Clockwork.player:FindByID(arguments[2]) + local target = cwPly:FindByID(arguments[2]) local cash = math.floor(tonumber((arguments[3] or 0))); if (target) then @@ -5654,10 +5681,10 @@ concommand.Add("cwc", function(player, command, arguments) local targetName = target:Name(); local giveCash = cash - target:GetCash(); - Clockwork.player:GiveCash(target, giveCash); + cwPly:GiveCash(target, giveCash); - print("Console has set "..targetName.."'s cash to "..Clockwork.kernel:FormatCash(cash, nil, true).."."); - Clockwork.player:Notify(target, "Your cash was set to "..Clockwork.kernel:FormatCash(cash, nil, true).." by "..playerName.."."); + print("Console has set "..targetName.."'s cash to "..cwKernel:FormatCash(cash, nil, true).."."); + cwPly:Notify(target, "Your cash was set to "..cwKernel:FormatCash(cash, nil, true).." by "..playerName.."."); else MsgC(Color(255, 100, 0, 255), "This is not a valid amount!\n"); end; @@ -5668,19 +5695,19 @@ concommand.Add("cwc", function(player, command, arguments) return; -- PlyWhitelist elseif (arguments[1] == cmdTable.w) then - local target = Clockwork.player:FindByID(arguments[2]) + local target = cwPly:FindByID(arguments[2]) if (target) then - local factionTable = Clockwork.faction:FindByID(table.concat(arguments, " ", 3)); + local factionTable = cwFaction:FindByID(table.concat(arguments, " ", 3)); if (factionTable) then if (factionTable.whitelist) then - if (!Clockwork.player:IsWhitelisted(target, factionTable.name)) then - Clockwork.player:SetWhitelisted(target, factionTable.name, true); - Clockwork.player:SaveCharacter(target); + if (!cwPly:IsWhitelisted(target, factionTable.name)) then + cwPly:SetWhitelisted(target, factionTable.name, true); + cwPly:SaveCharacter(target); print("Console has added "..target:Name().." to the "..factionTable.name.." whitelist."); - Clockwork.player:NotifyAll("Console has added "..target:Name().." to the "..factionTable.name.." whitelist."); + cwPly:NotifyAll("Console has added "..target:Name().." to the "..factionTable.name.." whitelist."); else MsgC(Color(255, 100, 0, 255), target:Name().." is already on the "..factionTable.name.." whitelist!\n"); end; @@ -5697,19 +5724,19 @@ concommand.Add("cwc", function(player, command, arguments) return; -- PlyUnWhitelist elseif (arguments[1] == cmdTable.uw) then - local target = Clockwork.player:FindByID(arguments[2]) + local target = cwPly:FindByID(arguments[2]) if (target) then - local factionTable = Clockwork.faction:FindByID(table.concat(arguments, " ", 3)); + local factionTable = cwFaction:FindByID(table.concat(arguments, " ", 3)); if (factionTable) then if (factionTable.whitelist) then - if (Clockwork.player:IsWhitelisted(target, factionTable.name)) then - Clockwork.player:SetWhitelisted(target, factionTable.name, false); - Clockwork.player:SaveCharacter(target); + if (cwPly:IsWhitelisted(target, factionTable.name)) then + cwPly:SetWhitelisted(target, factionTable.name, false); + cwPly:SaveCharacter(target); print("Console has removed "..target:Name().." from the "..factionTable.name.." whitelist."); - Clockwork.player:NotifyAll("Console has removed "..target:Name().." from the "..factionTable.name.." whitelist."); + cwPly:NotifyAll("Console has removed "..target:Name().." from the "..factionTable.name.." whitelist."); else MsgC(Color(255, 100, 0, 255), target:Name().." is not on the "..factionTable.name.." whitelist!\n"); end; @@ -5726,7 +5753,7 @@ concommand.Add("cwc", function(player, command, arguments) return; -- PlyBan elseif (arguments[1] == cmdTable.b) then - local schemaFolder = Clockwork.kernel:GetSchemaFolder(); + local schemaFolder = cwKernel:GetSchemaFolder(); local duration = tonumber(arguments[3]); local reason = table.concat(arguments, " ", 4); @@ -5734,9 +5761,9 @@ concommand.Add("cwc", function(player, command, arguments) reason = nil; end; - if (!Clockwork.player:IsProtected(arguments[2])) then + if (!cwPly:IsProtected(arguments[2])) then if (duration) then - Clockwork.bans:Add(arguments[2], duration * 60, reason, function(steamName, duration, reason) + cwBans:Add(arguments[2], duration * 60, reason, function(steamName, duration, reason) if (IsValid(player)) then if (steamName) then if (duration > 0) then @@ -5744,14 +5771,14 @@ concommand.Add("cwc", function(player, command, arguments) if (hours >= 1) then print("Console has banned '"..steamName.."' for "..hours.." hour(s) ("..reason..")."); - Clockwork.player:NotifyAll("Console has banned '"..steamName.."' for "..hours.." hour(s) ("..reason..")."); + cwPly:NotifyAll("Console has banned '"..steamName.."' for "..hours.." hour(s) ("..reason..")."); else print("Console has banned '"..steamName.."' for "..math.Round(duration / 60).." minute(s) ("..reason..")."); - Clockwork.player:NotifyAll("Console has banned '"..steamName.."' for "..math.Round(duration / 60).." minute(s) ("..reason..")."); + cwPly:NotifyAll("Console has banned '"..steamName.."' for "..math.Round(duration / 60).." minute(s) ("..reason..")."); end; else print("Console has banned '"..steamName.."' permanently ("..reason..")."); - Clockwork.player:NotifyAll("Console has banned '"..steamName.."' permanently ("..reason..")."); + cwPly:NotifyAll("Console has banned '"..steamName.."' permanently ("..reason..")."); end; else MsgC(Color(255, 100, 0, 255), "This is not a valid identifier!\n"); @@ -5762,7 +5789,7 @@ concommand.Add("cwc", function(player, command, arguments) MsgC(Color(255, 100, 0, 255), "This is not a valid duration!\n"); end; else - local target = Clockwork.player:FindByID(arguments[2]); + local target = cwPly:FindByID(arguments[2]); if (target) then MsgC(Color(255, 100, 0, 255), target:Name().." is protected!\n"); @@ -5774,7 +5801,7 @@ concommand.Add("cwc", function(player, command, arguments) return; -- PlyKick elseif (arguments[1] == cmdTable.k) then - local target = Clockwork.player:FindByID(arguments[2]); + local target = cwPly:FindByID(arguments[2]); local reason = table.concat(arguments, " ", 3); if (!reason or reason == "") then @@ -5782,9 +5809,9 @@ concommand.Add("cwc", function(player, command, arguments) end; if (target) then - if (!Clockwork.player:IsProtected(arguments[2])) then + if (!cwPly:IsProtected(arguments[2])) then print("Console has kicked '"..target:Name().."' ("..reason..")."); - Clockwork.player:NotifyAll("Console has kicked '"..target:Name().."' ("..reason..")."); + cwPly:NotifyAll("Console has kicked '"..target:Name().."' ("..reason..")."); target:Kick(reason); target.kicked = true; else @@ -5797,7 +5824,7 @@ concommand.Add("cwc", function(player, command, arguments) return; -- CharSetName elseif (arguments[1] == cmdTable.sn) then - local target = Clockwork.player:FindByID(arguments[2]) + local target = cwPly:FindByID(arguments[2]) if (target) then if (arguments[3] == "nil") then @@ -5808,9 +5835,9 @@ concommand.Add("cwc", function(player, command, arguments) local name = table.concat(arguments, " ", 3); print("Console has set "..target:Name().."'s name to "..name.."."); - Clockwork.player:NotifyAll("Console has set "..target:Name().."'s name to "..name.."."); + cwPly:NotifyAll("Console has set "..target:Name().."'s name to "..name.."."); - Clockwork.player:SetName(target, name); + cwPly:SetName(target, name); end; else MsgC(Color(255, 100, 0, 255), arguments[2].." is not a valid character!\n"); @@ -5819,7 +5846,7 @@ concommand.Add("cwc", function(player, command, arguments) return; -- CharSetModel elseif (arguments[1] == cmdTable.sm) then - local target = Clockwork.player:FindByID(arguments[2]) + local target = cwPly:FindByID(arguments[2]) if (target) then local model = table.concat(arguments, " ", 3); @@ -5828,7 +5855,7 @@ concommand.Add("cwc", function(player, command, arguments) target:SetModel(model); print("Console has set "..target:Name().."'s model to "..model.."."); - Clockwork.player:NotifyAll("Console has set "..target:Name().."'s model to "..model.."."); + cwPly:NotifyAll("Console has set "..target:Name().."'s model to "..model.."."); else MsgC(Color(255, 100, 0, 255), arguments[2].." is not a valid character!\n"); end; @@ -5843,7 +5870,7 @@ concommand.Add("cwc", function(player, command, arguments) end; print("Console is restarting the map in "..delay.." seconds!"); - Clockwork.player:NotifyAll("Console is restarting the map in "..delay.." seconds!"); + cwPly:NotifyAll("Console is restarting the map in "..delay.." seconds!"); timer.Simple(delay, function() RunConsoleCommand("changelevel", game.GetMap()); @@ -5852,7 +5879,7 @@ concommand.Add("cwc", function(player, command, arguments) return; -- GiveFlags elseif (arguments[1] == cmdTable.gf) then - local target = Clockwork.player:FindByID(arguments[2]) + local target = cwPly:FindByID(arguments[2]) if (target) then if (string.find(arguments[3], "a") or string.find(arguments[3], "s") or string.find(arguments[3], "o")) then @@ -5863,10 +5890,10 @@ concommand.Add("cwc", function(player, command, arguments) if (!arguments[3]) then print("You haven't entered any flags!"); return; end; - Clockwork.player:GiveFlags(target, arguments[3]); + cwPly:GiveFlags(target, arguments[3]); print("Console gave "..target:Name().." '"..arguments[3].."' flags."); - Clockwork.player:NotifyAll("Console gave "..target:Name().." '"..arguments[3].."' flags."); + cwPly:NotifyAll("Console gave "..target:Name().." '"..arguments[3].."' flags."); else MsgC(Color(255, 100, 0, 255), arguments[2].." is not a valid character!\n"); end; @@ -5874,21 +5901,21 @@ concommand.Add("cwc", function(player, command, arguments) return; -- TakeFlags elseif (arguments[1] == cmdTable.tf) then - local target = Clockwork.player:FindByID(arguments[2]) + local target = cwPly:FindByID(arguments[2]) if (target) then if (string.find(arguments[3], "a") or string.find(arguments[3], "s") or string.find(arguments[3], "o")) then - Clockwork.player:Notify(player, "You cannot take 'o', 'a' or 's' flags!"); + cwPly:Notify(player, "You cannot take 'o', 'a' or 's' flags!"); return; end; if (!arguments[3]) then print("You haven't entered any flags!"); return; end; - Clockwork.player:TakeFlags(target, arguments[3]); + cwPly:TakeFlags(target, arguments[3]); print("Console took '"..arguments[3].."' flags from "..target:Name().."."); - Clockwork.player:NotifyAll("Console took '"..arguments[3].."' flags from "..target:Name().."."); + cwPly:NotifyAll("Console took '"..arguments[3].."' flags from "..target:Name().."."); else MsgC(Color(255, 100, 0, 255), arguments[2].." is not a valid character!\n"); end; @@ -5900,7 +5927,7 @@ concommand.Add("cwc", function(player, command, arguments) end; -- if not too bad, players are not allowed to use this swag else - Clockwork.player.Notify(player, "You are not allowed to use server-side commands!"); + cwPly.Notify(player, "You are not allowed to use server-side commands!"); end; end);