--[[ Testing/Dev version only DO NOT USE TODO/Roadmap: try to fix thermal thrust bug with SetActivePlayerWeapon() Disable buildings function Enable buildings function IsStunned() func IsDisabled() func (buildings only) GetPlayerClass() func Heal player func see if I can make certain attributes work again util.BlastDamage() func GetParent() func Vector:Abs() --]] --Misc/Global Functions timer.Simple(1, function() print( "Running Expanded Lib Test Branch Version 1.5" ) end) function IsValidAlivePlayer(ent) return IsValid(ent) and ent:IsPlayer() and ent:IsAlive(); end function IsValidAliveRealPlayer(ent) return IsValid(ent) and ent:IsRealPlayer() and ent:IsAlive(); end function IsValidRealPlayer(ent) return IsValid(ent) and ent:IsRealPlayer(); end function IsValidPlayer(ent) return IsValid(ent) and ent:IsPlayer(); end function IsDamageType( damagetype, filter ) return ( damagetype & filter ) == filter end function IsValidWeapon( ply, wep ) return wep and ( ply:GetPlayerItemByName( wep:GetItemName() ):IsValid() or ply:GetPlayerItemByName( wep ):IsValid() ) end function tobool( val ) if ( ( val == nil ) or ( val == false ) or ( val == 0 ) or ( val == "0" ) or ( val == "false" ) ) then return false end return true end function PlaySound(sound, position) local ent = ents.CreateWithKeys("info_target", {}, true, true); ent:SetAbsOrigin(position); ent:PlaySound(sound); ent:Remove(); end function CreateClientSidedProp( classname, table, client ) local prop = ents.CreateWithKeys( classname, table, true, true ) prop:Enable() prop:HideToAll() prop:ShowTo( client ) return prop end function GetRandomPointInCircle( Radius ) --welcome to fucked up math local pi = math.pi local theta = math.random() * Radius * pi local r = math.random() + math.random() if r >= 1 then r = 2 - r end --local dist = ( r * math.cos( theta ) )^2 + ( r * math.sin( theta ) )^2 --dist = math.sqrt( dist ) --print( dist * Radius ) --print( ( r * math.cos( theta ) ) * Radius, ( r * math.sin( theta ) ) * Radius ) return Vector( ( r * math.cos( theta ) ) * Radius, ( r * math.sin( theta ) ) * Radius, 0 ) end function CustomHitbox( origin, maxs, mins, filt ) local st1 = origin + Vector( maxs[1], maxs[2], maxs[3] ) local ed1 = origin + Vector( mins[1], mins[2], mins[3] ) local st2 = origin + Vector( maxs[1], maxs[2], mins[3] ) local ed2 = origin + Vector( mins[1], mins[2], maxs[3] ) local st3 = origin + Vector( mins[1], maxs[2], maxs[3] ) local ed3 = origin + Vector( maxs[1], mins[2], mins[3] ) local st4 = origin + Vector( mins[1], maxs[2], mins[3] ) local ed4 = origin + Vector( maxs[1], mins[2], maxs[3] ) local tr1 = util.Trace( { start = st1, endpos = ed1, filter = filt } ) local tr2 = util.Trace( { start = st2, endpos = ed2, filter = filt } ) local tr3 = util.Trace( { start = st3, endpos = ed3, filter = filt } ) local tr4 = util.Trace( { start = st4, endpos = ed4, filter = filt } ) if tr1.Hit or tr2.Hit or tr3.Hit or tr4.Hit then return false else return true end end --Ents ents.FindByHandleIndex = function( filter, class ) if not filter then return nil end if not class then for _, ent in pairs( ents.GetAll( ) ) do if ent:GetHandleIndex() == filter then return ent end end return nil else for _, ent in pairs( ents.FindAllByClass( class ) ) do if ent:GetHandleIndex() == filter then return ent end end return nil end end ents.FindByNetIndex = function( filter, class ) if not filter then return nil end if not class then for _, ent in pairs( ents.GetAll( ) ) do if ent:GetNetIndex() == filter then return ent end end return nil else for _, ent in pairs( ents.FindAllByClass( class ) ) do if ent:GetNetIndex() == filter then return ent end end return nil end end ents.GetAllRealPlayers = function() local players = {} for index, ply in pairs(ents.GetAllPlayers()) do if ply:IsRealPlayer() then table.insert( players, ply ) end end return players end ents.GetAllAlivePlayers = function() local ply = {} for _, player in pairs( ents.GetAllPlayers() ) do if player:IsPlayer() and player:IsAlive() then table.insert( ply, player ) end end return ply end ents.GetAllAliveRealPlayers = function() local ply = {} for _, player in pairs( ents.GetAllPlayers() ) do if player:IsRealPlayer() and player:IsAlive() then table.insert( ply, player ) end end return ply end --Table table.RandomChance = function(t) local rand = math.random() local cumulativeProbability = 0 for key, item in pairs(t) do if (type(item) == "table") then cumulativeProbability = cumulativeProbability + item.chance; else cumulativeProbability = cumulativeProbability + item; end if (rand <= cumulativeProbability) then return key; end end end --CVector CVector.FaceVector = function(self, target) if target then local targetAngles = ( target - self ):ToAngles() targetAngles = Vector(targetAngles[1], targetAngles[2], 0) return targetAngles end end CVector.Unpack = function(self) return self[1], self[2], self[3] end --CEntity CEntity.GetModel = function(self) if self:IsValid() then return self.m_ModelName end end CEntity.HasLineOfSight = function( self, tar ) if self and tar then local ignore_tbl = { self, tar } for _, ply in pairs(ents.GetAllPlayers()) do table.insert(ignore_tbl, ply) end local Trace = util.Trace({ start = self:GetAbsOrigin() + Vector(0,0,16), endpos = tar:GetEyePos(), mask = MASK_SOLID, filter = ents.GetAllPlayers() }) local Trace2 = util.Trace({ start = self:GetAbsOrigin(), endpos = tar:GetAbsOrigin(), mask = MASK_SOLID, filter = ents.GetAllPlayers() }) if ( not Trace.Hit ) or ( not Trace2.Hit ) then return true else return false end end end CEntity.PlayParentedParticle = function(self, particle, offset, remove_after, RemoveFunction) if (not IsValid(self)) then return; end particle = ents.CreateWithKeys("info_particle_system", { effect_name=particle, start_active=1, ["$modules"]="fakeparent", ["$positiononly"]=1, }, true, true) local entity_origin = self:GetAbsOrigin(); if (offset) then entity_origin = entity_origin + offset; end particle.m_vecOrigin = entity_origin; particle["$SetFakeParent"](particle, self); particle["Start"](particle); timer.Create(remove_after, function() pcall(particle["Remove"], particle); if (RemoveFunction) then pcall(RemoveFunction); end end, 1); return particle; end CEntity.GetOwner = function(self) if self:IsValid() then return self.m_hOwnerEntity end end CEntity.GetBuilder = function(self) if self:IsValid() then return self.m_hBuilder end end CEntity.GetTeam = function(self) if self:IsValid() then return self.m_iTeamNum end end CEntity.OnTeam = function(self, team) if self:IsValid() then return self.m_iTeamNum == team end end CEntity.SetModelScale = function(self, scale, over_time, increment) if (not IsValid(self)) then return; end if (over_time and over_time > 0) then if (not increment or increment <= 0) then increment = 0.01; end local current_scale = self.m_flModelScale; if (scale - current_scale == 0) then return; elseif (scale - current_scale < 0) then increment = -increment; end local exec_times = math.floor(math.abs((scale - current_scale) / increment)); local counter = 0; timer.Create(over_time / exec_times, function() if (not IsValid(self)) then return; end counter = counter + 1; current_scale = current_scale + increment; if (counter == exec_times and current_scale ~= scale) then self.m_flModelScale = scale; else self.m_flModelScale = current_scale; end end, exec_times); else self.m_flModelScale = scale; end end --Players CEntity.IsInvuln = function(self) if (not IsValidPlayer(self)) then return end if (self:InCond(TF_COND_INVULNERABLE) or self:InCond(TF_COND_INVULNERABLE_CARD_EFFECT) or self:InCond(TF_COND_INVULNERABLE_HIDE_UNLESS_DAMAGED) or self:InCond(TF_COND_INVULNERABLE_USER_BUFF)) then return true end return false end CEntity.IsCritBoosted = function(self) if (not IsValidPlayer(self)) then return end if (self:InCond(TF_COND_CRITBOOSTED) or self:InCond(TF_COND_CRITBOOSTED_PUMPKIN) or self:InCond(TF_COND_CRITBOOSTED_USER_BUFF) or self:InCond(TF_COND_CRITBOOSTED_BONUS_TIME) or self:InCond(TF_COND_CRITBOOSTED_CTF_CAPTURE) or self:InCond(TF_COND_CRITBOOSTED_ON_KILL) or self:InCond(TF_COND_CRITBOOSTED_RAGE_BUFF) or self:InCond(TF_COND_CRITBOOSTED_CARD_EFFECT) or self:InCond(TF_COND_CRITBOOSTED_RUNE_TEMP) or self:InCond(TF_COND_CRITBOOSTED_FIRST_BLOOD)) then return true end return false end CEntity.IsMiniCritBoosted = function(self) if (not IsValidPlayer(self)) then return end if (self:InCond(TF_COND_OFFENSEBUFF) or self:InCond(TF_COND_NOHEALINGDAMAGEBUFF) or self:InCond(TF_COND_ENERGY_BUFF) or self:InCond(TF_COND_MINICRITBOOSTED_ON_KILL)) then return true end return false end CEntity.IsMidair = function(self) if (IsValidAlivePlayer(self)) then return not (self.movetype == MOVETYPE_WALK and (self.m_fFlags & FL_ONGROUND ~= 0)); end end CEntity.GetEyePos = function(self) if (not IsValidPlayer(self)) then return; end local eyepos = self:GetAbsOrigin(); eyepos.z = eyepos.z + self["m_vecViewOffset[2]"]; return eyepos end CEntity.GetEyeAngles = function(self) if (IsValidPlayer(self)) then return Vector( self.m_angEyeAngles[1], self.m_angEyeAngles[2], 0 ) end end CEntity.GetEyeAnglesExact = function(self) if (IsValidPlayer(self)) then return Vector( self.m_angEyeAngles[1], self.m_angEyeAngles[2], self.m_angEyeAngles[3] ) end end CEntity.GetActivePlayerWeapon = function(self) if (IsValidPlayer(self)) then return self.m_hActiveWeapon end end CEntity.GetActiveWeapon = function(self) if (IsValidPlayer(self)) then return self.m_hActiveWeapon end end CEntity.SetActivePlayerWeapon = function(self, wep) if ( IsValidPlayer(self) ) and ( self.m_hActiveWeapon ) and ( self.m_hActiveWeapon:IsValid() ) then if IsValidWeapon( self, wep ) and ( wep.m_iViewModelIndex ~= nil ) and ( wep.m_iViewModelIndex ~= 0 ) then self.m_hActiveWeapon = wep end end end CEntity.SetActiveWeapon = function(self, wep) if ( IsValidPlayer(self) ) and ( self.m_hActiveWeapon ) and ( self.m_hActiveWeapon:IsValid() ) then if IsValidWeapon( self, wep ) and ( wep.m_iViewModelIndex ~= nil ) and ( wep.m_iViewModelIndex ~= 0 ) then self.m_hActiveWeapon = wep end end end CEntity.GetPlayerVelocity = function(self) if (IsValidPlayer(self)) then return self.m_vecAbsVelocity end end CEntity.SetPlayerVelocity = function(self, vel) if (IsValidAlivePlayer(self)) then self.m_vecAbsVelocity = vel end end --Math math.clamp = function( value, min, max ) if min and max then if min > max then min, max = max, min end if value > max then value = max end if min > value then value = min end return value elseif min and ( not max ) then return math.min( value ) elseif max and ( not min ) then return math.max( value ) end end math.round = function(num, decimals) if (not decimals or decimals <= 0) then return math.floor(num + 0.5) else local mod = 10 ^ decimals return math.floor((num * mod) + 0.5) / mod end end math.randomfloat = function(m, n) if (m) then if (n) then if (n == m) then return m; elseif (m > n) then m, n = n, m; end -- n should be greater than m local dif = n - m; local mod = dif * math.random(); return m + mod; else return m * math.random(); end else return math.random(); end end math.remap = function( value, inMin, inMax, outMin, outMax ) return outMin + ( ( ( value - inMin ) / ( inMax - inMin ) ) * ( outMax - outMin ) ) end math.average = function( ... ) local total = 0 for _, val in pairs({ ... }) do total = total + val end total = total / #{ ... } return total end function lerp(start, goal, exp) return start + (goal - start) * exp end function lerpvector(start, goal, exp) local return_vec = Vector(0, 0, 0) return_vec[1] = start[1] + (goal[1] - start[1]) * exp return_vec[2] = start[2] + (goal[2] - start[2]) * exp return_vec[3] = start[3] + (goal[3] - start[3]) * exp return return_vec end --Hooks local function PlayerChat(event_table) local text = event_table.text local userid = event_table.userid local player = ents.GetPlayerByUserId(userid) if ( player ) and ( player:IsValid() ) and ( player ~= nil ) then pcall( OnPlayerChat, player, text ) end end local function PickupCurrency(event_table) --prints error -- local cash = event_table.currency -- local player = ents.FindByNetIndex( event_table.player, "player" ) -- if ( player ) and ( player:IsValid() ) and ( player ~= nil ) then -- pcall( OnPickupCurrency, player, cash ) -- end end local function TankDestroyed() pcall( OnTankDestroyed ) end local function PlayerDeath(event_table) local userid = event_table.userid local player = ents.GetPlayerByUserId( userid ) local attacker_id = event_table.attacker local attacker = ents.GetPlayerByUserId( attacker_id ) local weapon = event_table.weapon local damagetype = event_table.damagebits local assister_id = event_table.assister local assister = ents.GetPlayerByUserId( assister_id ) local silent_kill = event_table.silent_kill local crit_type = event_table.crit_type if ( player ) and ( player:IsValid() ) and ( player ~= nil ) then pcall( OnPlayerDeath, player, attacker, weapon, damagetype, assister, crit_type, silent_kill ) end end AddEventCallback("player_say", PlayerChat) AddEventCallback("mvm_pickup_currency", PickupCurrency) AddEventCallback("mvm_tank_destroyed_by_players", TankDestroyed) AddEventCallback("player_death", PlayerDeath)