--[[ | This file was obtained through the combined efforts | of Madbluntz & Plymouth Antiquarian Society. | | Credits: lifestorm, Gregory Wayne Rossel JR., | Maloy, DrPepper10 @ RIP, Atle! | | Visit for more: https://plymouth.thetwilightzone.ru/ --]] -- shared extensions to player table local plymeta = FindMetaTable( "Player" ) if not plymeta then return end local math = math function plymeta:IsTerror() return self:Team() == TEAM_TERROR end function plymeta:IsSpec() return self:Team() == TEAM_SPEC end AccessorFunc(plymeta, "role", "Role", FORCE_NUMBER) -- Role access function plymeta:GetTraitor() return self:GetRole() == ROLE_TRAITOR end function plymeta:GetDetective() return self:GetRole() == ROLE_DETECTIVE end plymeta.IsTraitor = plymeta.GetTraitor plymeta.IsDetective = plymeta.GetDetective function plymeta:IsSpecial() return self:GetRole() != ROLE_INNOCENT end -- Player is alive and in an active round function plymeta:IsActive() return self:IsTerror() and GetRoundState() == ROUND_ACTIVE end -- convenience functions for common patterns function plymeta:IsRole(role) return self:GetRole() == role end function plymeta:IsActiveRole(role) return self:IsRole(role) and self:IsActive() end function plymeta:IsActiveTraitor() return self:IsActiveRole(ROLE_TRAITOR) end function plymeta:IsActiveDetective() return self:IsActiveRole(ROLE_DETECTIVE) end function plymeta:IsActiveSpecial() return self:IsSpecial() and self:IsActive() end local role_strings = { [ROLE_TRAITOR] = "traitor", [ROLE_INNOCENT] = "innocent", [ROLE_DETECTIVE] = "detective" }; local GetRTranslation = CLIENT and LANG.GetRawTranslation or util.passthrough -- Returns printable role function plymeta:GetRoleString() return GetRTranslation(role_strings[self:GetRole()]) or "???" end -- Returns role language string id, caller must translate if desired function plymeta:GetRoleStringRaw() return role_strings[self:GetRole()] end function plymeta:GetBaseKarma() return self:GetNWFloat("karma", 1000) end function plymeta:HasEquipmentWeapon() for _, wep in ipairs(self:GetWeapons()) do if IsValid(wep) and wep:IsEquipment() then return true end end return false end function plymeta:CanCarryWeapon(wep) if (not wep) or (not wep.Kind) then return false end return self:CanCarryType(wep.Kind) end function plymeta:CanCarryType(t) if not t then return false end for _, w in ipairs(self:GetWeapons()) do if w.Kind and w.Kind == t then return false end end return true end function plymeta:IsDeadTerror() return (self:IsSpec() and not self:Alive()) end function plymeta:HasBought(id) return self.bought and table.HasValue(self.bought, id) end function plymeta:GetCredits() return self.equipment_credits or 0 end function plymeta:GetEquipmentItems() return self.equipment_items or EQUIP_NONE end -- Given an equipment id, returns if player owns this. Given nil, returns if -- player has any equipment item. function plymeta:HasEquipmentItem(id) if not id then return self:GetEquipmentItems() != EQUIP_NONE else return util.BitSet(self:GetEquipmentItems(), id) end end function plymeta:HasEquipment() return self:HasEquipmentItem() or self:HasEquipmentWeapon() end -- Override GetEyeTrace for an optional trace mask param. Technically traces -- like GetEyeTraceNoCursor but who wants to type that all the time, and we -- never use cursor tracing anyway. function plymeta:GetEyeTrace(mask) mask = mask or MASK_SOLID if CLIENT then local framenum = FrameNumber() if self.LastPlayerTrace == framenum and self.LastPlayerTraceMask == mask then return self.PlayerTrace end self.LastPlayerTrace = framenum self.LastPlayerTraceMask = mask end local tr = util.GetPlayerTrace(self) tr.mask = mask tr = util.TraceLine(tr) self.PlayerTrace = tr return tr end if CLIENT then function plymeta:AnimApplyGesture(act, weight) self:AnimRestartGesture(GESTURE_SLOT_CUSTOM, act, true) -- true = autokill self:AnimSetGestureWeight(GESTURE_SLOT_CUSTOM, weight) end local simple_runners = { ACT_GMOD_GESTURE_DISAGREE, ACT_GMOD_GESTURE_BECON, ACT_GMOD_GESTURE_AGREE, ACT_GMOD_GESTURE_WAVE, ACT_GMOD_GESTURE_BOW, ACT_SIGNAL_FORWARD, ACT_SIGNAL_GROUP, ACT_SIGNAL_HALT, ACT_GMOD_TAUNT_CHEER, ACT_GMOD_GESTURE_ITEM_PLACE, ACT_GMOD_GESTURE_ITEM_DROP, ACT_GMOD_GESTURE_ITEM_GIVE } local function MakeSimpleRunner(act) return function (ply, w) -- just let this gesture play itself and get out of its way if w == 0 then ply:AnimApplyGesture(act, 1) return 1 else return 0 end end end -- act -> gesture runner fn local act_runner = { -- ear grab needs weight control -- sadly it's currently the only one [ACT_GMOD_IN_CHAT] = function (ply, w) local dest = ply:IsSpeaking() and 1 or 0 w = math.Approach(w, dest, FrameTime() * 10) if w > 0 then ply:AnimApplyGesture(ACT_GMOD_IN_CHAT, w) end return w end }; -- Insert all the "simple" gestures that do not need weight control for _, a in ipairs(simple_runners) do act_runner[a] = MakeSimpleRunner(a) end local show_gestures = CreateConVar("ttt_show_gestures", "1", FCVAR_ARCHIVE) -- Perform the gesture using the GestureRunner system. If custom_runner is -- non-nil, it will be used instead of the default runner for the act. function plymeta:AnimPerformGesture(act, custom_runner) if not show_gestures:GetBool() then return end local runner = custom_runner or act_runner[act] if not runner then return false end self.GestureWeight = 0 self.GestureRunner = runner return true end -- Perform a gesture update function plymeta:AnimUpdateGesture() if self.GestureRunner then self.GestureWeight = self:GestureRunner(self.GestureWeight) if self.GestureWeight <= 0 then self.GestureRunner = nil end end end function GM:UpdateAnimation(ply, vel, maxseqgroundspeed) ply:AnimUpdateGesture() return self.BaseClass.UpdateAnimation(self, ply, vel, maxseqgroundspeed) end function GM:GrabEarAnimation(ply) end net.Receive("TTT_PerformGesture", function() local ply = net.ReadPlayer() local act = net.ReadUInt(16) if IsValid(ply) and act then ply:AnimPerformGesture(act) end end) else -- SERVER -- On the server, we just send the client a message that the player is -- performing a gesture. This allows the client to decide whether it should -- play, depending on eg. a cvar. function plymeta:AnimPerformGesture(act) if not act then return end net.Start("TTT_PerformGesture") net.WritePlayer(self) net.WriteUInt(act, 16) net.Broadcast() end end