diff --git a/lua/starfall/libs_sh/ents.lua b/lua/starfall/libs_sh/ents.lua index fc561ef..518d81a 100644 --- a/lua/starfall/libs_sh/ents.lua +++ b/lua/starfall/libs_sh/ents.lua @@ -85,6 +85,67 @@ function ents_methods:isValid() return isValid(unwrap(self)) end +--- Checks if the entity is world +-- @shared +-- @return True if world, false if not +function ents_methods:isWorld() + SF.CheckType(self,ents_metamethods) + local ent = unwrap(self) + return (ent and ent:IsValid() and ent:IsWorld()) +end + +--- Is some player holding the entity? +-- @shared +-- @return Return true if some player is holding this entity +function ents_methods:isPlayerHolding() + SF.CheckType(self,ents_metamethods) + local ent = unwrap(self) + if not isValid(ent) then return nil, "invalid entity" end + return ent:IsPlayerHolding() +end + +--- Is the entity on fire? +-- @shared +-- @return Return true if this entity is on fire +function ents_methods:isOnFire() + SF.CheckType(self,ents_metamethods) + local ent = unwrap(self) + if not isValid(ent) then return nil, "invalid entity" end + return ent:IsOnFire() +end + +--- Is the entity on ground? +-- @shared +-- @return Return true if this entity is on ground +function ents_methods:isOnGround() + SF.CheckType(self,ents_metamethods) + local ent = unwrap(self) + if not isValid(ent) then return nil, "invalid entity" end + return ent:IsOnGround() +end + +--- Is the entity under water? +-- @shared +-- @return Return true if this entity is under water +function ents_methods:isUnderWater() + SF.CheckType(self,ents_metamethods) + local ent = unwrap(self) + if not isValid(ent) then return nil, "invalid entity" end + return (ent:WaterLevel() > 0) +end + +--- Is the entity frozen? +-- @shared +-- @return Returns true if entity is frozen +function ents_methods:isFrozen() + SF.CheckType( self, player_metamethods ) + local phys = getPhysObject(unwrap(self)) + if not phys then return false, "entity has no physics object or is not valid" end + return phys:IsMoveable() +end + +-- ---------------- Basic info methods -------- -- + --- Returns the EntIndex of the entity -- @shared -- @return The numerical index of the entity @@ -105,6 +166,28 @@ function ents_methods:class() return ent:GetClass() end +--- Gets the model of an entity +-- @shared +-- @return The entity model name +function ents_methods:model() + SF.CheckType(self,ents_metamethods) + local ent = unwrap(self) + if not isValid(ent) then return nil, "invalid entity" end + return ent:GetModel() +end + +--- Gets the entity health +-- @shared +-- @return The entity health +function ents_methods:health() + SF.CheckType(self,ents_metamethods) + local ent = unwrap(self) + if not isValid(ent) then return nil, "invalid entity" end + return ent:Health() +end + +-- ---------------- Positional methods -------- -- + --- Returns the position of the entity -- @shared -- @return The position vector @@ -115,34 +198,44 @@ function ents_methods:pos() return ent:GetPos() end ---- Returns the x, y, z size of the entity's outer bounding box (local to the entity) +--- Returns the forward direction of the entity -- @shared --- @return The outer bounding box size -function ents_methods:obbSize() +-- @return Returns the forward vector of the entity, as a normalized direction vector +function ents_methods:forward() SF.CheckType(self,ents_metamethods) local ent = unwrap(self) if not isValid(ent) then return nil, "invalid entity" end - return ent:OBBMaxs() - ent:OBBMins() + return ent:GetForward() end ---- Returns the world position of the entity's outer bounding box +--- Returns the rightward direction of the entity -- @shared --- @return The position vector of the outer bounding box center -function ents_methods:obbCenter() +-- @return Returns the rightward vector of the entity, as a normalized direction vector +function ents_methods:right() SF.CheckType(self,ents_metamethods) local ent = unwrap(self) if not isValid(ent) then return nil, "invalid entity" end - return ent:LocalToWorld(ent:OBBCenter()) + return ent:GetRight() end ---- Returns the world position of the entity's mass center +--- Returns the upward direction of the entity -- @shared --- @return The position vector of the mass center -function ents_methods:massCenter() +-- @return Returns the upward vector of the entity, as a normalized direction vector +function ents_methods:up() SF.CheckType(self,ents_metamethods) local ent = unwrap(self) if not isValid(ent) then return nil, "invalid entity" end - return ent:LocalToWorld(ent:GetMassCenter()) + return ent:GetUp() +end + +--- Returns the velocity of the entity +-- @shared +-- @return The velocity vector +function ents_methods:vel() + SF.CheckType(self,ents_metamethods) + local ent = unwrap(self) + if not isValid(ent) then return nil, "invalid entity" end + return ent:GetVelocity() end --- Returns the angle of the entity @@ -155,55 +248,136 @@ function ents_methods:ang() return ent:GetAngles() end ---- Returns the mass of the entity +--- Returns the angular velocity of the entity -- @shared --- @return The numerical mass -function ents_methods:mass() +-- @return The angular velocity angle +function ents_methods:angVel() SF.CheckType(self,ents_metamethods) - - local ent = unwrap(self) - local phys = getPhysObject(ent) + local phys = getPhysObject(unwrap(self)) if not phys then return false, "entity has no physics object or is not valid" end - - return phys:GetMass() + local vel = phys:GetAngleVelocity() + return Angle(vel.y, vel.z, vel.x) end ---- Returns the principle moments of inertia of the entity +--- Returns the angular velocity of the entity as vector -- @shared --- @return The principle moments of inertia as a vector -function ents_methods:inertia() +-- @return The angular velocity vector +function ents_methods:angVelVector() SF.CheckType(self,ents_metamethods) - - local ent = unwrap(self) - local phys = getPhysObject(ent) + local phys = getPhysObject(unwrap(self)) if not phys then return false, "entity has no physics object or is not valid" end - - return phys:GetInertia() + return phys:GetAngleVelocity() end ---- Returns the velocity of the entity +-- Returns the mins and maxs of the entity's bounding box -- @shared --- @return The velocity vector -function ents_methods:vel() +-- @return The mins and maxs of the entity's bounding box +function ents_methods:obb() SF.CheckType(self,ents_metamethods) local ent = unwrap(self) if not isValid(ent) then return nil, "invalid entity" end - return ent:GetVelocity() + return ent:OBBMins(),ent:OBBMaxs() end ---- Returns the angular velocity of the entity +--- Returns the x, y, z size of the entity's outer bounding box (local to the entity) -- @shared --- @return The angular velocity vector -function ents_methods:angVelVector() +-- @return The outer bounding box size +function ents_methods:obbSize() + SF.CheckType(self,ents_metamethods) + local ent = unwrap(self) + if not isValid(ent) then return nil, "invalid entity" end + return ent:OBBMaxs() - ent:OBBMins() +end + +--- Returns the world position of the entity's outer bounding box +-- @shared +-- @param loc - If true then return as local position +-- @return The position vector of the outer bounding box center +function ents_methods:obbCenter(loc) + SF.CheckType(self,ents_metamethods) + local ent = unwrap(self) + if not isValid(ent) then return nil, "invalid entity" end + if loc then return ent:OBBCenter() end + return ent:LocalToWorld(ent:OBBCenter()) +end + +--- Returns the radius of the entity's bounding box +-- @shared +-- @return The radius number +function ents_methods:radius() + SF.CheckType(self,ents_metamethods) + local ent = unwrap(self) + if not isValid(ent) then return nil, "invalid entity" end + return ent:BoundingRadius() +end + +-- Returns the mins and max of the physics object +-- @shared +-- @return The mins and max of the physics object +function ents_methods:aabb() SF.CheckType(self,ents_metamethods) local phys = getPhysObject(unwrap(self)) - if not phys then return false, "entity has no physics object or is not valid" end - return phys:GetAngleVelocity() + if not phys then return false, "entity has no physics object or is not valid" end + return phys:GetAABB() +end + +-- Returns the x, y, z size of the physics object +-- @shared +-- @return The the x, y, z size of the physics object +function ents_methods:aabbSize() + SF.CheckType(self,ents_metamethods) + local phys = getPhysObject(unwrap(self)) + if not phys then return false, "entity has no physics object or is not valid" end + local min,max = phys:GetAABB() + return max - min +end + +--- Returns the world position of the entity's mass center +-- @shared +-- @param loc - If true then return as local position +-- @return The position vector of the mass center +function ents_methods:massCenter(loc) + SF.CheckType(self,ents_metamethods) + local ent = unwrap(self) + if not isValid(ent) then return nil, "invalid entity" end + if loc then return ent:GetMassCenter() end + return ent:LocalToWorld(ent:GetMassCenter()) +end + +--- Returns the mass of the entity +-- @shared +-- @return The numerical mass +function ents_methods:mass() + SF.CheckType(self,ents_metamethods) + local phys = getPhysObject(unwrap(self)) + if not phys then return false, "entity has no physics object or is not valid" end + return phys:GetMass() +end + +--- Gets the volume of the entity +-- @shared +-- @return Returns the volume of the entity +function ents_methods:volume() + SF.CheckType(self,ents_metamethods) + local phys = getPhysObject(unwrap(self)) + if not phys then return false, "entity has no physics object or is not valid" end + return phys:GetVolume() +end + +--- Returns the principle moments of inertia of the entity +-- @shared +-- @return The principle moments of inertia as a vector +function ents_methods:inertia() + SF.CheckType(self,ents_metamethods) + local phys = getPhysObject(unwrap(self)) + if not phys then return false, "entity has no physics object or is not valid" end + return phys:GetInertia() end ---- Converts a vector in entity local space to world space +--- Converts a vector/angle in entity local space to world space -- @shared -- @param data Local space vector +-- @return Returns the transformed vector/angle function ents_methods:toWorld(data) SF.CheckType(self,ents_metamethods) local ent = unwrap(self) @@ -218,9 +392,10 @@ function ents_methods:toWorld(data) end end ---- Converts a vector in world space to entity local space +--- Converts a vector/angle in world space to entity local space -- @shared -- @param data Local space vector +-- @return Returns the transformed vector/angle function ents_methods:toLocal(data) SF.CheckType(self,ents_metamethods) local ent = unwrap(self) @@ -235,17 +410,46 @@ function ents_methods:toLocal(data) end end ---- Gets the model of an entity +--- Transforms an axis local to entity to a global axis -- @shared -function ents_methods:model() +-- @param localAxis Local space vector +-- @return Returns the transformed vector +function ents_methods:toWorldAxis(localAxis) SF.CheckType(self,ents_metamethods) + SF.CheckType(localAxis,"Vector") local ent = unwrap(self) if not isValid(ent) then return nil, "invalid entity" end - return ent:GetModel() + + return ent:LocalToWorld(localAxis)-ent:GetPos() +end + +--- Transforms a world axis to an axis local to entity +-- @shared +-- @param worldAxis Local space vector +-- @return Returns the transformed vector +function ents_methods:toWorldAxis(worldAxis) + SF.CheckType(self,ents_metamethods) + SF.CheckType(worldAxis,"Vector") + local ent = unwrap(self) + if not isValid(ent) then return nil, "invalid entity" end + + return ent:WorldToLocal(worldAxis)+ent:GetPos() end ---- Gets the entitiy's eye angles +--- Performs a Ray OBBox intersection with the entity +-- @param point The position vector +-- @return Returns the closest point on the edge of the entity's bounding box to the given vector +function ents_methods:nearestPoint(point) + SF.CheckType(self,ents_metamethods) + SF.CheckType(point,"Vector") + local ent = unwrap(self) + if not isValid(ent) then return nil, "invalid entity" end + return ent:NearestPoint(point) +end + +--- Gets the entity's eye angles -- @shared +-- @return Returns the direction a player/npc/ragdoll is looking as a world-oriented angle function ents_methods:eyeAngles() SF.CheckType(self,ents_metamethods) local ent = unwrap(self) @@ -255,9 +459,78 @@ end --- Gets the entity's eye position -- @shared +-- @return Returns the position of an Player/NPC's view, or two vectors for ragdolls (one for each eye) function ents_methods:eyePos() SF.CheckType(self,ents_metamethods) local ent = unwrap(self) if not isValid(ent) then return nil, "invalid entity" end return ent:EyePos() end + +-- ---------------- Look methods -------- -- + +--- Get material of entity +-- @shared +-- @return Returns material name +function ents_methods:material() + SF.CheckType(self,ents_metamethods) + local ent = unwrap(self) + if not isValid(ent) then return nil, "invalid entity" end + return ent:GetMaterial() or "" +end + +--- Get current skin of entity +-- @shared +-- @return Returns skin number +function ents_methods:skin() + SF.CheckType(self,ents_metamethods) + local ent = unwrap(self) + if not isValid(ent) then return nil, "invalid entity" end + return ent:GetSkin() or 0 +end + +--- Get number of skins of entity +-- @shared +-- @return Returns number of skins +function ents_methods:skinCount() + SF.CheckType(self,ents_metamethods) + local ent = unwrap(self) + if not isValid(ent) then return nil, "invalid entity" end + return ent:SkinCount() or 0 +end + +-- ---------------- Attachments methods -------- -- + +--- Get attachment position +-- @shared +-- @param attachment Attachment ID or name +-- @return Position of attachment +function ents_methods:attachmentPos(attachment) + SF.CheckType(self,ents_metamethods) + local ent = unwrap(self) + if not isValid(ent) then return nil, "invalid entity" end + if type(attachment) == "string" then + attachment = ent:LookupAttachment(attachment) + elseif not type(attachment) == "number" then + SF.CheckType(attachment,"string or number") -- force error + end + local attach = ent:GetAttachment(attachment) + return attach.Pos +end + +--- Get attachment angle +-- @shared +-- @param attachment Attachment ID or name +-- @return Angle of attachment +function ents_methods:attachmentAng(attachment) + SF.CheckType(self,ents_metamethods) + local ent = unwrap(self) + if not isValid(ent) then return nil, "invalid entity" end + if type(attachment) == "string" then + attachment = ent:LookupAttachment(attachment) + elseif not type(attachment) == "number" then + SF.CheckType(attachment,"string or number") -- force error + end + local attach = ent:GetAttachment(attachment) + return attach.Ang +end diff --git a/lua/starfall/libs_sh/ents_npc.lua b/lua/starfall/libs_sh/ents_npc.lua new file mode 100644 index 0000000..612712a --- /dev/null +++ b/lua/starfall/libs_sh/ents_npc.lua @@ -0,0 +1,42 @@ +------------------------------------------------------------------------------- +-- NPC functions. +------------------------------------------------------------------------------- + +assert(SF.Entities) + +SF.NPC = {} +local npc_methods, npc_metamethods = SF.Typedef("NPC", SF.Entities.Metatable) + +SF.NPC.Methods = npc_methods +SF.NPC.Metatable = npc_metamethods + +-- Overload entity wrap functions to handle NPC +local dsetmeta = debug.setmetatable +local old_ent_wrap = SF.Entities.Wrap +function SF.Entities.Wrap(obj) + local w = old_ent_wrap(obj) + if type(obj) == "NPC" then + dsetmeta(w, npc_metamethods) + end + return w +end + +local function isValid(entity) + return (SF.Entities.IsValid(entity) and entity:IsNPC()) +end + +-- ------------------------- Entity Methods ------------------------- -- + +local ents_methods = SF.Entities.Methods +local ents_metatable = SF.Entities.Metatable + +local wrap, unwrap = SF.Entities.Wrap, SF.Entities.Unwrap + +function ents_methods:isNPC( ) + SF.CheckType( self, ents_metatable ) + local ent = SF.Entities.Unwrap( self ) + if not SF.Entities.IsValid(ent) then return false, "invalid entity" end + return ent:IsNPC( ) +end + +-- ------------------------- NPC Methods ------------------------- -- diff --git a/lua/starfall/libs_sh/ents_players.lua b/lua/starfall/libs_sh/ents_players.lua new file mode 100644 index 0000000..0b1e890 --- /dev/null +++ b/lua/starfall/libs_sh/ents_players.lua @@ -0,0 +1,451 @@ +------------------------------------------------------------------------------- +-- Player functions. +------------------------------------------------------------------------------- + +assert(SF.Entities) + +SF.Players = {} +local player_methods, player_metamethods = SF.Typedef("Player", SF.Entities.Metatable) + +SF.Players.Methods = player_methods +SF.Players.Metatable = player_metamethods + +-- Overload entity wrap functions to handle players +local dsetmeta = debug.setmetatable +local old_ent_wrap = SF.Entities.Wrap +function SF.Entities.Wrap(obj) + local w = old_ent_wrap(obj) + if type(obj) == "Player" then + dsetmeta(w, player_metamethods) + end + return w +end + +local function isValid(entity) + return SF.Entities.IsValid(entity) and entity:IsPlayer() +end + +-- ------------------------- Entity Methods ------------------------- -- + +local ents_methods = SF.Entities.Methods +local ents_metatable = SF.Entities.Metatable + +local wrap, unwrap = SF.Entities.Wrap, SF.Entities.Unwrap + +function ents_methods:isPlayer() + SF.CheckType( self, ents_metatable ) + local ent = unwrap( self ) + if not SF.Entities.IsValid(ent) then return false, "invalid entity" end + return ent:IsPlayer() +end + +-- ---------------------------- Player methods ---------------------------------- -- + +function player_methods:isAlive( ) + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return false, "invalid entity" end + return ent:Alive() +end + +function player_methods:armor( ) + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return nil, "invalid entity" end + return ent:Armor() +end + +function player_methods:isCrouching( ) + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return false, "invalid entity" end + return ent:Crouching() +end + +function player_methods:deaths( ) + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return nil, "invalid entity" end + return ent:Deaths() +end + +function player_methods:isFlashlightOn( ) + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return false, "invalid entity" end + return ent:FlashlightIsOn() +end + +function player_methods:frags( ) + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return nil, "invalid entity" end + return ent:Frags() +end + +function player_methods:fov() + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + return ent:GetFOV() +end + +function player_methods:jumpPower( ) + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return nil, "invalid entity" end + return ent:GetJumpPower() +end + +function player_methods:maxSpeed( ) + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return nil, "invalid entity" end + return ent:GetMaxSpeed() +end + +function player_methods:runSpeed( ) + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return nil, "invalid entity" end + return ent:GetRunSpeed() +end + +function player_methods:inVehicle( ) + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return false, "invalid entity" end + return ent:InVehicle() +end + +function player_methods:isAdmin( ) + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return false, "invalid entity" end + return ent:IsAdmin( ) +end + +function player_methods:isBot( ) + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return false, "invalid entity" end + return ent:IsBot( ) +end + +function player_methods:isConnected( ) + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return false, "invalid entity" end + return ent:IsConnected( ) +end + +function player_methods:isSuperAdmin( ) + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return false, "invalid entity" end + return ent:IsSuperAdmin( ) +end + +function player_methods:isUserGroup( group ) + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return false, "invalid entity" end + return ent:IsUserGroup( group ) +end + +function player_methods:isFrozen( ) + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return false, "invalid entity" end + return ent:IsFrozen( ) +end + +function player_methods:inNoclip() + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return false, "invalid entity" end + return ent:GetMoveType() ~= MOVETYPE_NOCLIP +end + +function player_methods:timeConnected() + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return nil, "invalid entity" end + then return ent:TimeConnected() +end + +function player_methods:name() + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return nil, "invalid entity" end + return ent:Name() +end + +function player_methods:nick() + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return nil, "invalid entity" end + return ent:Nick() +end + +function player_methods:ping() + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return nil, "invalid entity" end + return ent:Ping() +end + +function player_methods:steamID( ) + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return nil, "invalid entity" end + return ent:SteamID() +end + +function player_methods:steamID64( ) + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return nil, "invalid entity" end + return ent:SteamID64( ) +end + +function player_methods:team( ) + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return nil, "invalid entity" end + return ent:Team() +end + +function player_methods:uniqueID( ) + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return nil, "invalid entity" end + return ent:UniqueID() +end + +function player_methods:userID() + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return nil, "invalid entity" end + return ent:UserID() +end + +if CLIENT then + function player_methods:getFriendStatus( ) + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return nil, "invalid entity" end + return ent:GetFriendStatus( ) + end + + function player_methods:isMuted( ) + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return false, "invalid entity" end + return ent:IsMuted( ) + end +end + +function player_methods:eye() + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return nil, "invalid entity" end + return ent:GetAimVector() +end + +function player_methods:eyeAngles() + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return nil, "invalid entity" end + return ent:EyeAngles() +end + +--- Equivalent to rangerOffset(16384, :shootPos(), :eye()), but faster (causing less lag) +function player_methods:eyeTrace() + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return nil, "invalid entity" end + local ret = ent:GetEyeTraceNoCursor() + ret.RealStartPos = ent:GetShootPos() + if ret.Entity then ret.Entity = wrap(ret.Entity) end -- wrap the entity + return ret +end + +function player_methods:shootPos( ) + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return nil, "invalid entity" end + return ent:GetShootPos() +end + +function player_methods:aimVector( ) + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return nil, "invalid entity" end + return ent:GetAimVector() +end + +function player_methods:aimEntity() + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return nil, "invalid entity" end + + local hit = this:GetEyeTraceNoCursor().Entity + if not SF.Entities.IsValid(hit) then return nil end + return wrap(hit) +end + +function player_methods:aimPos() + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return nil, "invalid entity" end + return ent:GetEyeTraceNoCursor().HitPos +end + +function player_methods:aimNormal() + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return nil, "invalid entity" end + return ent:GetEyeTraceNoCursor().HitNormal +end + +-- ---------------- Tools / Weapons functions -------- -- + +function player_methods:weapon(weaponclassname) + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return nil, "invalid entity" end + + if weaponclassname then + SF.CheckType(weaponclassname,"string") + return wrap(ent:GetWeapon(weaponclassname)) + else + return wrap(ent:GetActiveWeapon()) + end +end + +function player_methods:ammoCount(ammo_type) + SF.CheckType( self, player_metamethods ) + + if type(ammo_type) == "number" then + ammo_type = tostring(ammo_type) + elseif not type(ammo_type) == "string" then + SF.CheckType(ammo_type,"string or number") -- force error + end + + local ent = unwrap( self ) + if not isValid(ent) then return nil, "invalid entity" end + + return ent:GetAmmoCount(ammo_type) +end + +function player_methods:tool() + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return nil, "invalid entity" end + + local weapon = ent:GetActiveWeapon() + if not weapon and weapon:IsValid() and weapon:IsWeapon() then return "" end + if weapon:GetClass() ~= "gmod_tool" then return "" end + + return weapon.Mode +end + +-- ---------------- Key functions ----------------------- -- + +function player_methods:keyAttack1() + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return false, "invalid entity" end + return ent:KeyDown(IN_ATTACK) +end + +function player_methods:keyAttack2() + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return false, "invalid entity" end + return ent:KeyDown(IN_ATTACK2) +end + +function player_methods:keyUse() + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return false, "invalid entity" end + return ent:KeyDown(IN_USE) +end + +function player_methods:keyCancel() + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return false, "invalid entity" end + return ent:KeyDown(IN_CANCEL) +end + +function player_methods:keyReload() + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return false, "invalid entity" end + return ent:KeyDown(IN_RELOAD) +end + +function player_methods:keyZoom() + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return false, "invalid entity" end + return ent:KeyDown(IN_ZOOM) +end + +function player_methods:keyJump() + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return false, "invalid entity" end + return ent:KeyDown(IN_JUMP) +end + +function player_methods:keyDuck() + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return false, "invalid entity" end + return ent:KeyDown(IN_DUCK) +end + +function player_methods:keyMoveForward() + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return false, "invalid entity" end + return ent:KeyDown(IN_FORWARD) +end + +function player_methods:keyMoveBack() + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return false, "invalid entity" end + return ent:KeyDown(IN_BACK) +end + +function player_methods:keyMoveLeft() + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return false, "invalid entity" end + return ent:KeyDown(IN_MOVELEFT) +end + +function player_methods:keyMoveRight() + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return false, "invalid entity" end + return ent:KeyDown(IN_MOVERIGHT) +end + +function player_methods:keyTurnLeft() + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return false, "invalid entity" end + return ent:KeyDown(IN_LEFT) +end + +function player_methods:keyTurnRight() + SF.CheckType( self, player_metamethods ) + local ent = unwrap( self ) + if not isValid(ent) then return false, "invalid entity" end + return ent:KeyDown(IN_RIGHT) +end \ No newline at end of file diff --git a/lua/starfall/libs_sh/ents_vehicles.lua b/lua/starfall/libs_sh/ents_vehicles.lua new file mode 100644 index 0000000..69381b9 --- /dev/null +++ b/lua/starfall/libs_sh/ents_vehicles.lua @@ -0,0 +1,118 @@ +------------------------------------------------------------------------------- +-- Vehicle functions +------------------------------------------------------------------------------- + +assert(SF.Entities) + +SF.Vehicles = {} +local vehicle_methods, vehicle_metamethods = SF.Typedef("Vehicle", SF.Entities.Metatable) + +SF.Vehicles.Methods = vehicle_methods +SF.Vehicles.Metatable = vehicle_metamethods + +-- Overload entity wrap functions to handle vehicles +local dsetmeta = debug.setmetatable +local old_ent_wrap = SF.Entities.Wrap +function SF.Entities.Wrap(obj) + local w = old_ent_wrap(obj) + if type(obj) == "Vehicle" then + dsetmeta(w, vehicle_metamethods) + end + return w +end + +local function isValid(entity) + return (SF.Entities.IsValid(entity) and entity:IsVehicle()) +end + +-- ------------------------- Entity Methods ------------------------- -- + +local ents_methods = SF.Entities.Methods +local ents_metatable = SF.Entities.Metatable + +local wrap, unwrap = SF.Entities.Wrap, SF.Entities.Unwrap + +--- Is the entity vehicle? +-- @return Returns true if entity is vehicle +function ents_methods:isVehicle() + SF.CheckType(self,ents_metatable) + + local ent = unwrap(self) + if not SF.Entities.IsValid(ent) then return false, "invalid entity" end + + return ent:IsVehicle() +end + +-- ------------------------- Vehicle Methods ------------------------- -- + +--- Locks vehicle pod +-- @param lock Lock? +function vehicle_methods:lockPod(lock) + SF.CheckType(self,vehicle_metamethods) + SF.CheckType(lock,"boolean") + + local ent = unwrap(self) + if not isValid(ent) then return nil, "invalid vehicle entity" end + + if not SF.Entities.GetOwner(ent) == SF.instance.player then return false, "access denied" end + + if lock then + ent:Fire("Lock", "", 0) + else + ent:Fire("Unlock", "", 0) + end +end + +--- Kill vehicle driver +function vehicle_methods:killDriver() + SF.CheckType(self,vehicle_metamethods) + + local ent = unwrap(self) + if not isValid(ent) then return nil, "invalid vehicle entity" end + + if not SF.Entities.GetOwner(ent) == SF.instance.player then return false, "access denied" end + + local ply = ent:GetDriver() + if ply and ply:IsValid() and ply:IsPlayer() then ply:Kill() end +end + +--- Ejects driver from vehicle +function vehicle_methods:ejectDriver() + SF.CheckType(self,vehicle_metamethods) + + local ent = unwrap(self) + if not isValid(ent) then return nil, "invalid vehicle entity" end + + if not SF.Entities.GetOwner(ent) == SF.instance.player then return false, "access denied" end + + local ply = ent:GetDriver() + if ply and ply:IsValid() and ply:IsPlayer() then ply:ExitVehicle() end +end + +--- Get vehicle driver +-- @return Returns vehicle driver +function vehicle_methods:driver() + SF.CheckType(self,vehicle_metamethods) + + local ent = unwrap(self) + if not isValid(ent) then return nil, "invalid vehicle entity" end + + local ply = ent:GetDriver() + if ply and ply:IsValid() and ply:IsPlayer() then return nil, "invalid driver" end + + return wrap(ply) +end + +--- Get vehicle passenger if available +-- @return Returns vehicle passenger +function vehicle_methods:passenger() + SF.CheckType(self,vehicle_metamethods) + + local ent = unwrap(self) + if not isValid(ent) then return nil, "invalid vehicle entity" end + + local ply = ent:GetPassenger() + if ply and ply:IsValid() and ply:IsPlayer() then return nil, "invalid passenger" end + + return wrap(ply) +end diff --git a/lua/starfall/libs_sh/ents_weapons.lua b/lua/starfall/libs_sh/ents_weapons.lua new file mode 100644 index 0000000..0753c5c --- /dev/null +++ b/lua/starfall/libs_sh/ents_weapons.lua @@ -0,0 +1,78 @@ +------------------------------------------------------------------------------- +-- Weapon functions. +------------------------------------------------------------------------------- + +assert(SF.Entities) + +SF.Weapons = {} +local weapon_methods, weapon_metamethods = SF.Typedef("Weapon", SF.Entities.Metatable) + +SF.Weapons.Methods = weapon_methods +SF.Weapons.Metatable = weapon_metamethods + +-- Overload entity wrap functions to handle NPC +local dsetmeta = debug.setmetatable +local old_ent_wrap = SF.Entities.Wrap +function SF.Entities.Wrap(obj) + local w = old_ent_wrap(obj) + if type(obj) == "Weapon" then + dsetmeta(w, weapon_metamethods) + end + return w +end + +local function isValid(entity) + return (SF.Entities.IsValid(entity) and entity:IsWeapon()) +end + +-- ------------------------- Entity Methods ------------------------- -- + +local ents_methods = SF.Entities.Methods +local ents_metatable = SF.Entities.Metatable + +local wrap, unwrap = SF.Entities.Wrap, SF.Entities.Unwrap + +function ents_methods:isWeapon() + SF.CheckType(self,ents_metamethods) + local ent = unwrap(self) + if not SF.Entities.IsValid(ent) then return nil, "invalid entity" end + return ent:IsWeapon() +end + +-- ------------------------- Weapon Methods ------------------------- -- + +--- Primary ammo type +-- @return Returns the type of ammo that the weapon's primary fire takes. +function weapon_methods:primaryAmmoType() + SF.CheckType(self,weapon_metamethods) + local ent = unwrap(self) + if not isValid(ent) then return nil, "invalid weapon entity" end + return ent:GetPrimaryAmmoType() +end + +--- Secondary ammo type +-- @return Returns the type of ammo that the weapon's secondary fire takes. +function weapon_methods:secondaryAmmoType() + SF.CheckType(self,weapon_metamethods) + local ent = unwrap(self) + if not isValid(ent) then return nil, "invalid weapon entity" end + return ent:GetSecondaryAmmoType() +end + +--- Get primary clip +-- @return Returns the number of bullets in the primary fire's clip. Returns -1 if the weapon doesn't have a primary fire, or if it doesn't take ammo. +function nweapon_methods:clip1() + SF.CheckType(self,weapon_metamethods) + local ent = unwrap(self) + if not isValid(ent) then return nil, "invalid weapon entity" end + return ent:Clip1() +end + +--- Get secondary clip +-- @return Returns the number of bullets in the secondary fire's clip. Returns -1 if the weapon doesn't have a secondary fire, or if it doesn't take ammo. +function weapon_methods:clip2() + SF.CheckType(self,weapon_metamethods) + local ent = unwrap(self) + if not isValid(ent) then return nil, "invalid weapon entity" end + return ent:Clip2() +end diff --git a/lua/starfall/libs_sh/players.lua b/lua/starfall/libs_sh/players.lua deleted file mode 100644 index 61626cc..0000000 --- a/lua/starfall/libs_sh/players.lua +++ /dev/null @@ -1,228 +0,0 @@ -------------------------------------------------------------------------------- --- Player functions. -------------------------------------------------------------------------------- - -SF.Players = {} -local player_methods, player_metamethods = SF.Typedef("Player", SF.Entities.Metatable) - -SF.Players.Methods = player_methods -SF.Players.Metatable = player_metamethods - --- Overload entity wrap functions to handle players -local dsetmeta = debug.setmetatable -local old_ent_wrap = SF.Entities.Wrap -function SF.Entities.Wrap(obj) - local w = old_ent_wrap(obj) - if type(obj) == "Player" then - dsetmeta(w, player_metamethods) - end - return w -end - --- ------------------------------------------------------------------------- -- - -function player_methods:alive( ) - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:Alive() -end - -function player_methods:armor( ) - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:Armor() -end - -function player_methods:crouching( ) - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:Crouching() -end - -function player_methods:deaths( ) - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:Deaths() -end - -function player_methods:flashlightIsOn( ) - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:FlashlightIsOn() -end - -function player_methods:frags( ) - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:Frags() -end - -function player_methods:activeWeapon( ) - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:GetActiveWeapon():ClassName() -end - -function player_methods:aimVector( ) - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:GetAimVector() -end - -function player_methods:fov() - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:GetFOV() -end - -function player_methods:jumpPower( ) - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:GetJumpPower() -end - -function player_methods:maxSpeed( ) - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:GetMaxSpeed() -end - -function player_methods:name( ) - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:GetName() -end - -function player_methods:runSpeed( ) - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:GetRunSpeed() -end - -function player_methods:shootPos( ) - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:GetShootPos() -end - -function player_methods:inVehicle( ) - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:InVehicle() -end - -function player_methods:isAdmin( ) - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:IsAdmin( ) -end - -function player_methods:isBot( ) - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:IsBot( ) -end - -function player_methods:isConnected( ) - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:IsConnected( ) -end - -function player_methods:isFrozen( ) - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:IsFrozen( ) -end - -function player_methods:isNPC( ) - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:IsNPC( ) -end - -function player_methods:isPlayer( ) - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:IsPlayer() -end - -function player_methods:isSuperAdmin( ) - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:IsSuperAdmin( ) -end - -function player_methods:isUserGroup( group ) - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:IsUserGroup( group ) -end - -function player_methods:name() - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:Name() -end - -function player_methods:nick() - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:Nick() -end - -function player_methods:ping() - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:Ping() -end - -function player_methods:steamID( ) - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:SteamID() -end - -function player_methods:steamID64( ) - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:SteamID64( ) -end - -function player_methods:team( ) - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:Team() -end - -function player_methods:teamName( ) - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and team.GetName(ent:Team()) -end - -function player_methods:uniqueID( ) - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:UniqueID() -end - -function player_methods:userID() - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:UserID() -end - -if CLIENT then - function player_methods:getFriendStatus( ) - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:GetFriendStatus( ) - end - - function player_methods:isMuted( ) - SF.CheckType( self, player_metamethods ) - local ent = SF.Entities.Unwrap( self ) - return ent and ent:IsMuted( ) - end -end diff --git a/lua/starfall/libs_sh/team.lua b/lua/starfall/libs_sh/team.lua new file mode 100644 index 0000000..4cdb8d7 --- /dev/null +++ b/lua/starfall/libs_sh/team.lua @@ -0,0 +1,67 @@ +-- -------------------------- Team functions ------------------------ -- + +--- Team Library +-- @shared +local teams_lib, _ = SF.Libraries.Register("team") + +--- Get team name +-- @param teamID Team ID +-- @return Team name +function teams_lib.name(teamID) + SF.CheckType(teamID, "number") + local str = team.GetName(teamID) + if str == nil then return "" end + return str +end + +--- Get team score +-- @param teamID Team ID +-- @return Team score +function teams_lib.score(teamID) + SF.CheckType(teamID, "number") + return team.GetScore(teamID) +end + +--- Get number of players in team +-- @param teamID Team ID +-- @return Team number of players +function teams_lib.players(teamID) + SF.CheckType(teamID, "number") + return team.NumPlayers(teamID) +end + +--- Get total team deaths +-- @param teamID Team ID +-- @return Team deaths +function teams_lib.deaths(teamID) + SF.CheckType(teamID, "number") + return team.TotalDeaths(teamID) +end + +--- Get total team frags +-- @param teamID Team ID +-- @return Team frags +function teams_lib.frags(teamID) + SF.CheckType(teamID, "number") + return team.TotalFrags(teamID) +end + +--- Get team color +-- @param teamID Team ID +-- @return r,g,b team color +function teams_lib.color(teamID) + SF.CheckType(teamID, "number") + local col = team.GetColor(teamID) + return col.r, col.g, col.b +end + +--- Get all teams ID +-- @return Teams ID array +function teams_lib.allTeams() + local team_indexes = {} + for index,_ in pairs(team.GetAllTeams()) do + team_indexes[#team_indexes+1] = index + end + table.sort(team_indexes) + return team_indexes +end diff --git a/lua/starfall/libs_sv/ents.lua b/lua/starfall/libs_sv/ents.lua index 4467a93..861ff89 100644 --- a/lua/starfall/libs_sv/ents.lua +++ b/lua/starfall/libs_sv/ents.lua @@ -303,3 +303,61 @@ function ents_methods:enableGravity(grav) phys:Wake() return true end + +--- Sets entity mass +-- @param mass Entity new mass (0.001 - 50000) +function ents_methods:setMass(mass) + SF.CheckType(self,ents_metatable) + SF.CheckType(mass,"number") + + local ent = unwrap(self) + if not isValid(ent) then return false, "entity not valid" end + if not canModify(SF.instance.player, ent) or SF.instance.permissions:checkPermission("Modify All Entities") then return false, "access denied" end + local phys = getPhysObject(ent) + if not phys then return false, "entity has no physics object" end + if ent:IsPlayer() then return false, "cannot set mass of player" end + + local mass = math.Clamp(mass, 0.001, 50000) + + phys:SetMass(mass) + + if not phys:GetMass() == mass then return false, "setting mass failed" end + + return true +end + +--- Sets the entity material +-- @param material Material +-- @return Returns true on success +function ents_methods:setMaterial(material) + SF.CheckType(self,ents_metatable) + SF.CheckType(material, "string") + + local ent = unwrap(self) + if not isValid(ent) then return false, "invalid entity" end + if not canModify(SF.instance.player, ent) or SF.instance.permissions:checkPermission("Modify All Entities") then return false, "access denied" end + + ent:SetMaterial(material) + + if not ent:GetMaterial() == material then return false, "failed to set material" end + + return true +end + +--- Sets the entity skin +-- @param skin Skin number +-- @return Returns true on success +function ents_methods:setSkin(skin) + SF.CheckType(self,ents_metatable) + SF.CheckType(skin, "number") + + local ent = unwrap(self) + if not isValid(ent) then return false, "invalid entity" end + if not canModify(SF.instance.player, ent) or SF.instance.permissions:checkPermission("Modify All Entities") then return false, "access denied" end + + ent:SetSkin(skin) + + if not ent:GetSkin() == skin then return false, "failed to set skin" end + + return true +end diff --git a/lua/starfall/libs_sv/ents_npc.lua b/lua/starfall/libs_sv/ents_npc.lua new file mode 100644 index 0000000..71942a7 --- /dev/null +++ b/lua/starfall/libs_sv/ents_npc.lua @@ -0,0 +1,112 @@ +------ NPC server functions ---- + +assert(SF.NPC) + +local function isValid(entity) + return (SF.Entities.IsValid(entity) and entity:IsNPC()) +end + +local npc_methods = SF.NPC.Methods +local npc_metamethods = SF.NPC.Metatable + +function npc_methods:npcGoWalk(pos) + SF.CheckType( self, npc_metamethods ) + SF.CheckType( pos, "Vector" ) + local ent = SF.Entities.Unwrap( self ) + if not isValid(ent) then return nil, "invalid npc entity" end + if not SF.Entities.GetOwner(ent) == SF.instance.player then return false, "access denied" end + + ent:SetLastPosition( pos ) + ent:SetSchedule( SCHED_FORCED_GO ) +end + +function npc_methods:npcGoRun(pos) + SF.CheckType( self, npc_metamethods ) + SF.CheckType( pos, "Vector" ) + local ent = SF.Entities.Unwrap( self ) + if not isValid(ent) then return nil, "invalid npc entity" end + if not SF.Entities.GetOwner(ent) == SF.instance.player then return false, "access denied" end + + ent:SetLastPosition( pos ) + ent:SetSchedule( SCHED_FORCED_GO_RUN ) +end + +function npc_methods:npcAttack() + SF.CheckType( self, npc_metamethods ) + local ent = SF.Entities.Unwrap( self ) + if not isValid(ent) then return nil, "invalid npc entity" end + if not SF.Entities.GetOwner(ent) == SF.instance.player then return false, "access denied" end + ent:SetSchedule( SCHED_MELEE_ATTACK1 ) +end + +function npc_methods:npcShoot() + SF.CheckType( self, npc_metamethods ) + local ent = SF.Entities.Unwrap( self ) + if not isValid(ent) then return nil, "invalid npc entity" end + if not SF.Entities.GetOwner(ent) == SF.instance.player then return false, "access denied" end + if !ent:HasCondition( COND_NO_WEAPON ) then return, "no weapon" end + ent:SetSchedule( SCHED_RANGE_ATTACK1 ) +end + +function npc_methods:npcFace(pos) + SF.CheckType( self, npc_metamethods ) + SF.CheckType(pos,"Vector") + local ent = SF.Entities.Unwrap( self ) + if not isValid(ent) then return nil, "invalid npc entity" end + if not SF.Entities.GetOwner(ent) == SF.instance.player then return false, "access denied" end + local Vec = pos - ent:GetPos() + local ang = Vec:Angle() + ent:SetAngles( Angle(0,ang.y,0) ) +end + +function npc_methods:npcGiveWeapon(weaponName) + SF.CheckType( self, npc_metamethods ) + + if not weaponName then weaponName = "smg1" end + + SF.CheckType(weaponName,"string") + + local ent = SF.Entities.Unwrap( self ) + if not isValid(ent) then return nil, "invalid npc entity" end + if not SF.Entities.GetOwner(ent) == SF.instance.player then return false, "access denied" end + + local weapon = ent:GetActiveWeapon() + if weapon and weapon:IsValid() then + if weapon:GetClass() == "weapon_"..weaponName then return end + weapon:Remove() + end + + ent:Give( "ai_weapon_"..weaponName ) +end + +function npc_methods:npcStop() + SF.CheckType( self, npc_metamethods ) + local ent = SF.Entities.Unwrap( self ) + if not isValid(ent) then return nil, "invalid npc entity" end + if not SF.Entities.GetOwner(ent) == SF.instance.player then return false, "access denied" end + ent:SetSchedule( SCHED_NONE ) +end + +function npc_methods:npcGetTarget() + SF.CheckType( self, npc_metamethods ) + local ent = SF.Entities.Unwrap( self ) + if not isValid(ent) then return nil, "invalid npc entity" end + if not SF.Entities.GetOwner(ent) == SF.instance.player then return false, "access denied" end + return SF.Entities.Wrap(ent:GetEnemy()) +end + +function npc_methods:npcSetTarget(target) + SF.CheckType( self, npc_metamethods ) + local ent = SF.Entities.Unwrap( self ) + if not isValid(ent) then return nil, "invalid npc entity" end + if not SF.Entities.GetOwner(ent) == SF.instance.player then return false, "access denied" end + + target = SF.Entities.Unwrap(ent) + if target and target:IsValid() and (target:IsNPC() or target:IsPlayer()) then + ent:SetEnemy(target) + end + + if not ent:GetEnemy() == target then return false end + + return true +end