Server-Side Hooks
Server-side hook system for the Lilia framework.
Overview
Server-side hooks in the Lilia framework handle game logic, data persistence, player management, and other server-specific functionality. All server hooks follow the standard Garry's Mod hook system and can be overridden or extended by addons and modules.
AddWarning
Purpose
Adds a warning to a character's record in the administration system
When Called
When an admin issues a warning to a player
Parameters
charID(number): The character ID of the warned playerwarned(string): The name of the warned playerwarnedSteamID(string): The Steam ID of the warned playertimestamp(number): Unix timestamp when the warning was issuedmessage(string): The warning message/reasonwarner(string): The name of the admin who issued the warningwarnerSteamID(string): The Steam ID of the admin who issued the warning
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Add a basic warning
hook.Run("AddWarning", charID, playerName, steamID, os.time(), "Rule violation", adminName, adminSteamID)
Medium Complexity:
-- Medium: Add warning with custom message
local reason = "Excessive RDM - 3 kills in 5 minutes"
local timestamp = os.time()
hook.Run("AddWarning", target:getChar():getID(), target:Nick(), target:SteamID(),
timestamp, reason, client:Nick(), client:SteamID())
High Complexity:
-- High: Add warning with validation and logging
hook.Add("AddWarning", "MyAddon", function(charID, warned, warnedSteamID, timestamp, message, warner, warnerSteamID)
-- Log the warning to a custom system
print(string.format("Warning issued: %s warned %s for: %s", warner, warned, message))
-- Send notification to other admins
for _, admin in ipairs(player.GetAll()) do
if admin:IsAdmin() then
admin:ChatPrint(string.format("[WARNING] %s warned %s: %s", warner, warned, message))
end
end
-- Check for warning limits
local warnings = hook.Run("GetWarnings", charID)
if #warnings >= 3 then
-- Auto-kick after 3 warnings
local target = player.GetBySteamID(warnedSteamID)
if IsValid(target) then
target:Kick("Too many warnings")
end
end
end)
AdjustCreationData
Purpose
Allows modification of character creation data before the character is created
When Called
During character creation process, before the character is saved to database
Parameters
client(Player): The player creating the characterdata(table): The current character data being creatednewData(table): Additional data to be merged with the character dataoriginalData(table): The original character data before any modifications
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Add default money to new characters
hook.Add("AdjustCreationData", "MyAddon", function(client, data, newData, originalData)
data.money = data.money + 1000 -- Give extra starting money
end)
Medium Complexity:
-- Medium: Modify character based on faction
hook.Add("AdjustCreationData", "FactionBonuses", function(client, data, newData, originalData)
if data.faction == "police" then
data.money = data.money + 500 -- Police get extra money
data.desc = data.desc .. "\n\n[Police Officer]"
elseif data.faction == "citizen" then
data.money = data.money + 200 -- Citizens get small bonus
end
end)
High Complexity:
-- High: Complex character creation system with validation
hook.Add("AdjustCreationData", "AdvancedCreation", function(client, data, newData, originalData)
-- Validate character name
if string.len(data.name) < 3 then
data.name = data.name .. " Jr."
end
-- Add faction-specific bonuses
local factionBonuses = {
["police"] = {money = 1000, items = {"weapon_pistol"}},
["medic"] = {money = 800, items = {"medkit"}},
["citizen"] = {money = 200, items = {}}
}
local bonus = factionBonuses[data.faction]
if bonus then
data.money = data.money + bonus.money
data.startingItems = data.startingItems or {}
for _, item in ipairs(bonus.items) do
table.insert(data.startingItems, item)
end
end
-- Add creation timestamp
data.creationTime = os.time()
data.creationIP = client:IPAddress()
end)
BagInventoryReady
Purpose
Called when a bag item's inventory is ready and accessible
When Called
When a bag item's inventory is created or restored from database
Parameters
self(Item): The bag item instanceinventory(Inventory): The inventory instance that was created/loaded
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log when bag inventory is ready
hook.Add("BagInventoryReady", "MyAddon", function(self, inventory)
print("Bag inventory ready for item: " .. self.uniqueID)
end)
Medium Complexity:
-- Medium: Add special items to bag inventory
hook.Add("BagInventoryReady", "SpecialBags", function(self, inventory)
if self.uniqueID == "magic_bag" then
-- Add a magic item to the bag
local magicItem = lia.item.instance("magic_crystal")
if magicItem then
inventory:add(magicItem)
end
end
end)
High Complexity:
-- High: Complex bag inventory system with validation
hook.Add("BagInventoryReady", "AdvancedBags", function(self, inventory)
local char = self:getOwner()
if not char then return end
-- Set up faction-specific bag contents
local faction = char:getFaction()
local bagContents = {
["police"] = {
{item = "handcuffs", quantity = 1},
{item = "police_badge", quantity = 1},
{item = "radio", quantity = 1}
},
["medic"] = {
{item = "medkit", quantity = 2},
{item = "bandage", quantity = 5},
{item = "stethoscope", quantity = 1}
},
["citizen"] = {
{item = "wallet", quantity = 1},
{item = "phone", quantity = 1}
}
}
local contents = bagContents[faction]
if contents then
for _, content in ipairs(contents) do
local item = lia.item.instance(content.item)
if item then
item:setData("quantity", content.quantity)
inventory:add(item)
end
end
end
end
-- Set up access rules based on character data
local charLevel = char:getData("level", 1)
if charLevel >= 10 then
-- High level characters get extra space
inventory:setData("maxWeight", inventory:getData("maxWeight", 100) * 1.5)
end
-- Log the bag creation
print(string.format("Bag inventory created for %s (Level %d, Faction: %s)",
char:getName(), charLevel, faction))
end)
BagInventoryRemoved
Purpose
Called when a bag item's inventory is removed or destroyed
When Called
When a bag item is deleted or its inventory is cleaned up
Parameters
self(Item): The bag item instanceinv(Inventory): The inventory instance that was removed
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log when bag inventory is removed
hook.Add("BagInventoryRemoved", "MyAddon", function(self, inv)
print("Bag inventory removed for item: " .. self.uniqueID)
end)
Medium Complexity:
-- Medium: Clean up custom data when bag is removed
hook.Add("BagInventoryRemoved", "CleanupBags", function(self, inv)
local char = self:getOwner()
if char then
char:setData("bagCount", (char:getData("bagCount", 0) - 1))
end
end)
High Complexity:
-- High: Complex cleanup with item recovery
hook.Add("BagInventoryRemoved", "AdvancedCleanup", function(self, inv)
local char = self:getOwner()
if not char then return end
-- Check if bag had valuable items
local valuableItems = {}
for _, item in pairs(inv:getItems()) do
if item.uniqueID == "gold_bar" or item.uniqueID == "diamond" then
table.insert(valuableItems, item)
end
end
-- Transfer valuable items to character inventory
if #valuableItems > 0 then
local charInv = char:getInv()
for _, item in ipairs(valuableItems) do
charInv:add(item)
end
char:getPlayer():ChatPrint("Valuable items recovered from destroyed bag!")
end
end)
CanBeTransfered
Purpose
Determines if a character can be transferred to a different faction
When Called
When attempting to transfer a character to another faction
Parameters
targetChar(Character): The character being transferredfaction(string): The target faction nameclient(Player): The player requesting the transfer
Returns
- boolean - True if transfer is allowed, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all transfers
hook.Add("CanBeTransfered", "MyAddon", function(targetChar, faction, client)
return true
end)
Medium Complexity:
-- Medium: Check faction restrictions
hook.Add("CanBeTransfered", "FactionRestrictions", function(targetChar, faction, client)
local currentFaction = targetChar:getFaction()
if currentFaction == "police" and faction == "criminal" then
return false -- Police can't become criminals
end
return true
end)
High Complexity:
-- High: Complex transfer validation system
hook.Add("CanBeTransfered", "AdvancedTransfers", function(targetChar, faction, client)
local charLevel = targetChar:getData("level", 1)
local charMoney = targetChar:getMoney()
-- Check level requirements
local factionRequirements = {
["police"] = 5,
["medic"] = 3,
["mayor"] = 10
}
local requiredLevel = factionRequirements[faction]
if requiredLevel and charLevel < requiredLevel then
client:ChatPrint("You need to be level " .. requiredLevel .. " to join " .. faction)
return false
end
-- Check money requirements
local transferCost = 1000
if charMoney < transferCost then
client:ChatPrint("You need $" .. transferCost .. " to transfer factions")
return false
end
-- Check cooldown
local lastTransfer = targetChar:getData("lastFactionTransfer", 0)
if os.time() - lastTransfer < 3600 then -- 1 hour cooldown
client:ChatPrint("You must wait before transferring factions again")
return false
end
return true
end)
CanCharBeTransfered
Purpose
Determines if a character can be transferred (alias for CanBeTransfered)
When Called
When attempting to transfer a character to another faction
Parameters
targetChar(Character): The character being transferredfaction(string): The target faction nameclient(Player): The player requesting the transfer
Returns
- boolean - True if transfer is allowed, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: Use same logic as CanBeTransfered
hook.Add("CanCharBeTransfered", "MyAddon", function(targetChar, faction, client)
return hook.Run("CanBeTransfered", targetChar, faction, client)
end)
Medium Complexity:
-- Medium: Add additional character-specific checks
hook.Add("CanCharBeTransfered", "CharChecks", function(targetChar, faction, client)
-- Check if character is banned
if targetChar:isBanned() then
return false
end
-- Check character age
local charAge = targetChar:getData("age", 18)
if faction == "police" and charAge < 21 then
return false -- Must be 21+ to be police
end
return hook.Run("CanBeTransfered", targetChar, faction, client)
end)
High Complexity:
-- High: Advanced character transfer system
hook.Add("CanCharBeTransfered", "AdvancedCharTransfers", function(targetChar, faction, client)
local charData = targetChar:getData()
-- Check character reputation
local reputation = charData.reputation or 0
if faction == "police" and reputation < 50 then
client:ChatPrint("You need a good reputation to join the police")
return false
end
-- Check for outstanding warrants
if charData.warrants and #charData.warrants > 0 then
client:ChatPrint("You have outstanding warrants and cannot transfer")
return false
end
-- Check faction capacity
local factionCount = 0
for _, char in pairs(lia.char.getCharacters()) do
if char:getFaction() == faction then
factionCount = factionCount + 1
end
end
local maxFactionMembers = {
["police"] = 10,
["medic"] = 5,
["mayor"] = 1
}
local maxMembers = maxFactionMembers[faction]
if maxMembers and factionCount >= maxMembers then
client:ChatPrint("That faction is full")
return false
end
return hook.Run("CanBeTransfered", targetChar, faction, client)
end)
CanDeleteChar
Purpose
Determines if a character can be deleted
When Called
When a player attempts to delete a character
Parameters
client(Player): The player requesting the deletioncharacter(Character): The character to be deleted
Returns
- boolean - True if deletion is allowed, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all character deletions
hook.Add("CanDeleteChar", "MyAddon", function(client, character)
return true
end)
Medium Complexity:
-- Medium: Prevent deletion of high-level characters
hook.Add("CanDeleteChar", "LevelRestrictions", function(client, character)
local charLevel = character:getData("level", 1)
if charLevel > 10 then
client:ChatPrint("You cannot delete characters above level 10")
return false
end
return true
end)
High Complexity:
-- High: Complex deletion validation system
hook.Add("CanDeleteChar", "AdvancedDeletion", function(client, character)
local charMoney = character:getMoney()
local charLevel = character:getData("level", 1)
-- Check if character has valuable items
local hasValuables = false
local charInv = character:getInv()
for _, item in pairs(charInv:getItems()) do
if item.uniqueID == "gold_bar" or item.uniqueID == "diamond" then
hasValuables = true
break
end
end
if hasValuables then
client:ChatPrint("You must remove all valuable items before deleting this character")
return false
end
-- Check if character is in a faction
local faction = character:getFaction()
if faction ~= "citizen" then
client:ChatPrint("You must leave your faction before deleting this character")
return false
end
-- Check cooldown
local lastDeletion = client:getData("lastCharDeletion", 0)
if os.time() - lastDeletion < 86400 then -- 24 hour cooldown
client:ChatPrint("You must wait 24 hours before deleting another character")
return false
end
return true
end)
CanInviteToClass
Purpose
Called to check if a player can invite another to a class
When Called
When attempting to invite a player to a class
Parameters
client(Player): The player attempting the invitetarget(Player): The player being invited
Returns
- boolean - True to allow, false to deny
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow admins only
hook.Add("CanInviteToClass", "MyAddon", function(client, target)
return client:IsAdmin()
end)
Medium Complexity:
-- Medium: Check faction and rank
hook.Add("CanInviteToClass", "ClassInviteCheck", function(client, target)
local char = client:getChar()
if not char then return false end
local rank = char:getData("rank", 0)
return rank >= 3
end)
High Complexity:
-- High: Complex class invitation system
hook.Add("CanInviteToClass", "AdvancedClassInvite", function(client, target)
local char = client:getChar()
local targetChar = target:getChar()
if not char or not targetChar then return false end
-- Check if client has permission
local rank = char:getData("rank", 0)
if rank < 3 then
client:ChatPrint("You need rank 3 or higher to invite players")
return false
end
-- Check if target is in same faction
if char:getFaction() ~= targetChar:getFaction() then
client:ChatPrint("Target must be in your faction")
return false
end
-- Check cooldown
local lastInvite = char:getData("lastClassInvite", 0)
if os.time() - lastInvite < 60 then
client:ChatPrint("Please wait before inviting again")
return false
end
char:setData("lastClassInvite", os.time())
return true
end)
CanInviteToFaction
Purpose
Called to check if a player can invite another to a faction
When Called
When attempting to invite a player to a faction
Parameters
client(Player): The player attempting the invitetarget(Player): The player being invited
Returns
- boolean - True to allow, false to deny
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow admins only
hook.Add("CanInviteToFaction", "MyAddon", function(client, target)
return client:IsAdmin()
end)
Medium Complexity:
-- Medium: Check faction leader status
hook.Add("CanInviteToFaction", "FactionInviteCheck", function(client, target)
local char = client:getChar()
if not char then return false end
return char:getData("factionLeader", false)
end)
High Complexity:
-- High: Complex faction invitation system
hook.Add("CanInviteToFaction", "AdvancedFactionInvite", function(client, target)
local char = client:getChar()
local targetChar = target:getChar()
if not char or not targetChar then return false end
-- Check if client is faction leader
if not char:getData("factionLeader", false) then
client:ChatPrint("Only faction leaders can invite players")
return false
end
-- Check faction member limit
local faction = char:getFaction()
local memberCount = 0
for _, ply in ipairs(player.GetAll()) do
local plyChar = ply:getChar()
if plyChar and plyChar:getFaction() == faction then
memberCount = memberCount + 1
end
end
local maxMembers = 20
if memberCount >= maxMembers then
client:ChatPrint("Faction is at maximum capacity")
return false
end
-- Check cooldown
local lastInvite = char:getData("lastFactionInvite", 0)
if os.time() - lastInvite < 120 then
client:ChatPrint("Please wait before inviting again")
return false
end
char:setData("lastFactionInvite", os.time())
return true
end)
CanItemBeTransfered
Purpose
Called to check if an item can be transferred between inventories
When Called
When attempting to move an item from one inventory to another
Parameters
item(Item): The item being transferredfromInventory(Inventory): The source inventorytoInventory(Inventory): The destination inventoryclient(Player): The player performing the transfer
Returns
- boolean - True if transfer is allowed, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all transfers
hook.Add("CanItemBeTransfered", "MyAddon", function(item, fromInventory, toInventory, client)
return true
end)
Medium Complexity:
-- Medium: Check inventory types
hook.Add("CanItemBeTransfered", "InventoryTypeCheck", function(item, fromInventory, toInventory, client)
-- Prevent transferring to vendor inventories
if toInventory.isVendor then
return false
end
-- Check if item is transferable
if item:getData("noTransfer", false) then
return false
end
return true
end)
High Complexity:
-- High: Complex transfer validation system
hook.Add("CanItemBeTransfered", "AdvancedTransferValidation", function(item, fromInventory, toInventory, client)
local char = client:getChar()
if not char then return false end
-- Check if item is transferable
if item:getData("noTransfer", false) then
client:ChatPrint("This item cannot be transferred")
return false
end
-- Check inventory types
if toInventory.isVendor then
client:ChatPrint("Cannot transfer items to vendor inventories")
return false
end
-- Check weight limits
local itemWeight = item:getWeight()
local currentWeight = toInventory:getWeight()
local maxWeight = toInventory:getMaxWeight()
if currentWeight + itemWeight > maxWeight then
client:ChatPrint("Not enough space in destination inventory")
return false
end
-- Check faction restrictions
local itemFaction = item:getData("faction")
if itemFaction then
local charFaction = char:getFaction()
if itemFaction ~= charFaction then
client:ChatPrint("You cannot transfer faction-restricted items")
return false
end
end
-- Check level requirements
local requiredLevel = item:getData("requiredLevel", 1)
local charLevel = char:getData("level", 1)
if charLevel < requiredLevel then
client:ChatPrint("You need to be level " .. requiredLevel .. " to transfer this item")
return false
end
-- Check if item is equipped
if item:getData("equipped", false) then
client:ChatPrint("Cannot transfer equipped items")
return false
end
-- Check for special item restrictions
if item.uniqueID == "weapon_pistol" then
-- Special handling for weapons
if not char:hasFlags("w") then
client:ChatPrint("You need weapon flags to transfer weapons")
return false
end
end
return true
end)
CanPerformVendorEdit
Purpose
Called to check if a player can edit a vendor
When Called
When attempting to modify vendor settings
Parameters
self(Entity): The vendor entityvendor(table): The vendor data table
Returns
- boolean - True to allow, false to deny
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow admins only
hook.Add("CanPerformVendorEdit", "MyAddon", function(self, vendor)
local client = self.activator
return client and client:IsAdmin()
end)
Medium Complexity:
-- Medium: Check vendor ownership
hook.Add("CanPerformVendorEdit", "VendorEditCheck", function(self, vendor)
local client = self.activator
if not client then return false end
local char = client:getChar()
if not char then return false end
local owner = vendor.owner
return owner == char:getID() or client:IsAdmin()
end)
High Complexity:
-- High: Complex vendor editing system
hook.Add("CanPerformVendorEdit", "AdvancedVendorEdit", function(self, vendor)
local client = self.activator
if not client then return false end
local char = client:getChar()
if not char then return false end
-- Admins can always edit
if client:IsAdmin() then return true end
-- Check vendor ownership
local owner = vendor.owner
if owner ~= char:getID() then
client:ChatPrint("You don't own this vendor")
return false
end
-- Check edit cooldown
local lastEdit = char:getData("lastVendorEdit", 0)
if os.time() - lastEdit < 30 then
client:ChatPrint("Please wait before editing again")
return false
end
char:setData("lastVendorEdit", os.time())
return true
end)
CanPersistEntity
Purpose
Called to check if an entity can be persisted
When Called
When determining if an entity should be saved across map changes
Parameters
entity(Entity): The entity to check
Returns
- boolean - True to persist, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: Persist all props
hook.Add("CanPersistEntity", "MyAddon", function(entity)
return entity:GetClass() == "prop_physics"
end)
Medium Complexity:
-- Medium: Persist specific entities
hook.Add("CanPersistEntity", "EntityPersistCheck", function(entity)
local persistClasses = {
["prop_physics"] = true,
["prop_dynamic"] = true,
["lia_item"] = true
}
return persistClasses[entity:GetClass()] or false
end)
High Complexity:
-- High: Complex entity persistence system
hook.Add("CanPersistEntity", "AdvancedEntityPersist", function(entity)
if not IsValid(entity) then return false end
-- Check entity class
local persistClasses = {
["prop_physics"] = true,
["prop_dynamic"] = true,
["lia_item"] = true,
["lia_vendor"] = true
}
if not persistClasses[entity:GetClass()] then
return false
end
-- Check if entity is marked as temporary
if entity:getNetVar("temporary", false) then
return false
end
-- Check entity age
local spawnTime = entity:getNetVar("spawnTime", 0)
if os.time() - spawnTime < 60 then
return false
end
-- Check entity owner
local owner = entity:getNetVar("owner")
if owner then
local ownerPly = player.GetBySteamID(owner)
if not IsValid(ownerPly) then
return false
end
end
return true
end)
CanPickupMoney
Purpose
Called to check if money can be picked up
When Called
When a player attempts to pick up money
Parameters
activator(Player): The player trying to pick up moneyself(Entity): The money entity
Returns
- boolean - True to allow, false to deny
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all money pickup
hook.Add("CanPickupMoney", "MyAddon", function(activator, self)
return true
end)
Medium Complexity:
-- Medium: Check distance and amount
hook.Add("CanPickupMoney", "CheckMoneyPickup", function(activator, self)
local distance = activator:GetPos():Distance(self:GetPos())
if distance > 100 then
return false
end
local amount = self:getNetVar("amount", 0)
if amount <= 0 then
return false
end
return true
end)
High Complexity:
-- High: Complex money pickup system
hook.Add("CanPickupMoney", "AdvancedMoneyPickup", function(activator, self)
if not IsValid(activator) or not IsValid(self) then return false end
local char = activator:getChar()
if not char then return false end
-- Check distance
local distance = activator:GetPos():Distance(self:GetPos())
if distance > 100 then
activator:ChatPrint("You are too far away to pick up the money")
return false
end
-- Check amount
local amount = self:getNetVar("amount", 0)
if amount <= 0 then
return false
end
-- Check if money is owned
local owner = self:getNetVar("owner")
if owner and owner ~= char:getID() then
local ownerChar = lia.char.loaded[owner]
if ownerChar and ownerChar:getData("alive", true) then
activator:ChatPrint("This money belongs to someone else")
return false
end
end
-- Check faction restrictions
local faction = char:getFaction()
if faction == "ghost" then
return false
end
-- Check if player is tied
if char:getData("tied", false) then
activator:ChatPrint("You cannot pick up money while tied")
return false
end
return true
end)
CanPlayerAccessDoor
Purpose
Called to check if a player can access a door
When Called
When a player attempts to interact with a door
Parameters
client(Player): The player attempting accessself(Entity): The door entityaccess(number): The access level being checked
Returns
- boolean - True to allow, false to deny
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all players
hook.Add("CanPlayerAccessDoor", "MyAddon", function(client, self, access)
return true
end)
Medium Complexity:
-- Medium: Check door ownership
hook.Add("CanPlayerAccessDoor", "DoorAccessCheck", function(client, self, access)
local char = client:getChar()
if not char then return false end
local owner = self:getNetVar("owner")
return owner == char:getID()
end)
High Complexity:
-- High: Complex door access system
hook.Add("CanPlayerAccessDoor", "AdvancedDoorAccess", function(client, self, access)
local char = client:getChar()
if not char then return false end
-- Admins can access all doors
if client:IsAdmin() then return true end
-- Check door ownership
local owner = self:getNetVar("owner")
if owner == char:getID() then return true end
-- Check faction access
local allowedFactions = self:getNetVar("allowedFactions", {})
if table.HasValue(allowedFactions, char:getFaction()) then
return true
end
-- Check if player has key
local doorID = self:getNetVar("doorID")
if doorID and char:getInv():hasItem("door_key_" .. doorID) then
return true
end
return false
end)
CanPlayerAccessVendor
Purpose
Called to check if a player can access a vendor
When Called
When a player attempts to interact with a vendor
Parameters
activator(Player): The player attempting accessself(Entity): The vendor entity
Returns
- boolean - True to allow, false to deny
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all players
hook.Add("CanPlayerAccessVendor", "MyAddon", function(activator, self)
return true
end)
Medium Complexity:
-- Medium: Check faction restrictions
hook.Add("CanPlayerAccessVendor", "VendorAccessCheck", function(activator, self)
local char = activator:getChar()
if not char then return false end
local allowedFactions = self:getNetVar("allowedFactions", {})
if #allowedFactions > 0 and not table.HasValue(allowedFactions, char:getFaction()) then
return false
end
return true
end)
High Complexity:
-- High: Complex vendor access system
hook.Add("CanPlayerAccessVendor", "AdvancedVendorAccess", function(activator, self)
local char = activator:getChar()
if not char then return false end
-- Check faction restrictions
local allowedFactions = self:getNetVar("allowedFactions", {})
if #allowedFactions > 0 and not table.HasValue(allowedFactions, char:getFaction()) then
activator:ChatPrint("Your faction cannot access this vendor")
return false
end
-- Check level requirements
local requiredLevel = self:getNetVar("requiredLevel", 0)
local charLevel = char:getData("level", 1)
if charLevel < requiredLevel then
activator:ChatPrint("You need to be level " .. requiredLevel .. " to access this vendor")
return false
end
-- Check reputation
local requiredRep = self:getNetVar("requiredReputation", 0)
local charRep = char:getData("reputation", 0)
if charRep < requiredRep then
activator:ChatPrint("You need " .. requiredRep .. " reputation to access this vendor")
return false
end
return true
end)
CanPlayerChooseWeapon
Purpose
Called to check if a player can choose a weapon
When Called
When a player attempts to select a weapon
Parameters
weapon(Weapon): The weapon being chosen
Returns
- boolean - True to allow, false to deny
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all weapons
hook.Add("CanPlayerChooseWeapon", "MyAddon", function(weapon)
return true
end)
Medium Complexity:
-- Medium: Restrict specific weapons
hook.Add("CanPlayerChooseWeapon", "RestrictWeapons", function(weapon)
local restrictedWeapons = {"weapon_crowbar", "weapon_stunstick"}
return not table.HasValue(restrictedWeapons, weapon:GetClass())
end)
High Complexity:
-- High: Complex weapon selection system
hook.Add("CanPlayerChooseWeapon", "AdvancedWeaponSelection", function(weapon)
local client = weapon:GetOwner()
if not IsValid(client) then return false end
local char = client:getChar()
if not char then return false end
-- Check faction restrictions
local faction = char:getFaction()
local weaponClass = weapon:GetClass()
if faction == "police" then
local policeWeapons = {"weapon_pistol", "weapon_stunstick"}
return table.HasValue(policeWeapons, weaponClass)
elseif faction == "medic" then
local medicWeapons = {"weapon_medkit", "weapon_stunstick"}
return table.HasValue(medicWeapons, weaponClass)
end
-- Check level requirements
local requiredLevel = weapon:getData("requiredLevel", 1)
local charLevel = char:getData("level", 1)
if charLevel < requiredLevel then
return false
end
-- Check if weapon is broken
local durability = weapon:getData("durability", 100)
if durability <= 0 then
return false
end
return true
end)
CanPlayerCreateChar
Purpose
Determines if a player can create a new character
When Called
When a player attempts to create a new character
Parameters
client(Player): The player creating the characterdata(table): The character creation data
Returns
- boolean - True if creation is allowed, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all character creation
hook.Add("CanPlayerCreateChar", "MyAddon", function(client, data)
return true
end)
Medium Complexity:
-- Medium: Check character limit
hook.Add("CanPlayerCreateChar", "CharLimit", function(client, data)
local charCount = #client.liaCharList or 0
local maxChars = hook.Run("GetMaxPlayerChar", client) or 5
if charCount >= maxChars then
client:ChatPrint("You have reached the maximum number of characters")
return false
end
return true
end)
High Complexity:
-- High: Complex character creation validation
hook.Add("CanPlayerCreateChar", "AdvancedCreation", function(client, data)
-- Check if player is banned
if client:IsBanned() then
client:ChatPrint("You are banned and cannot create characters")
return false
end
-- Check character name validity
local name = data.name or ""
if string.len(name) < 3 then
client:ChatPrint("Character name must be at least 3 characters long")
return false
end
if string.len(name) > 32 then
client:ChatPrint("Character name must be less than 32 characters")
return false
end
-- Check for inappropriate names
local bannedWords = {"admin", "moderator", "staff", "test"}
for _, word in ipairs(bannedWords) do
if string.find(string.lower(name), string.lower(word)) then
client:ChatPrint("That name is not allowed")
return false
end
end
-- Check faction restrictions
local faction = data.faction
local playerLevel = client:getData("level", 1)
local factionRequirements = {
["police"] = 5,
["medic"] = 3,
["mayor"] = 10
}
local requiredLevel = factionRequirements[faction]
if requiredLevel and playerLevel < requiredLevel then
client:ChatPrint("You need to be level " .. requiredLevel .. " to create a " .. faction .. " character")
return false
end
-- Check character count
local charCount = #client.liaCharList or 0
local maxChars = hook.Run("GetMaxPlayerChar", client) or 5
if charCount >= maxChars then
client:ChatPrint("You have reached the maximum number of characters")
return false
end
return true
end)
CanPlayerDropItem
Purpose
Called to check if a player can drop an item
When Called
When a player attempts to drop an item
Parameters
client(Player): The player attempting to drop the itemitem(Item): The item being dropped
Returns
- boolean - True if dropping is allowed, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all item drops
hook.Add("CanPlayerDropItem", "MyAddon", function(client, item)
return true
end)
Medium Complexity:
-- Medium: Check item restrictions
hook.Add("CanPlayerDropItem", "ItemDropCheck", function(client, item)
-- Prevent dropping important items
if item:getData("noDrop", false) then
client:ChatPrint("This item cannot be dropped")
return false
end
-- Check if item is equipped
if item:getData("equipped", false) then
client:ChatPrint("Cannot drop equipped items")
return false
end
return true
end)
High Complexity:
-- High: Complex item drop validation system
hook.Add("CanPlayerDropItem", "AdvancedDropValidation", function(client, item)
local char = client:getChar()
if not char then return false end
-- Check if item is droppable
if item:getData("noDrop", false) then
client:ChatPrint("This item cannot be dropped")
return false
end
-- Check if item is equipped
if item:getData("equipped", false) then
client:ChatPrint("Cannot drop equipped items")
return false
end
-- Check faction restrictions
local itemFaction = item:getData("faction")
if itemFaction then
local charFaction = char:getFaction()
if itemFaction ~= charFaction then
client:ChatPrint("You cannot drop faction-restricted items")
return false
end
end
-- Check level requirements
local requiredLevel = item:getData("requiredLevel", 1)
local charLevel = char:getData("level", 1)
if charLevel < requiredLevel then
client:ChatPrint("You need to be level " .. requiredLevel .. " to drop this item")
return false
end
-- Check for special item restrictions
if item.uniqueID == "weapon_pistol" then
-- Special handling for weapons
if not char:hasFlags("w") then
client:ChatPrint("You need weapon flags to drop weapons")
return false
end
elseif item.uniqueID == "money" then
-- Special handling for money
local amount = item:getData("amount", 0)
if amount > 1000 then
client:ChatPrint("Cannot drop more than $1000 at once")
return false
end
end
-- Check location restrictions
local pos = client:GetPos()
local restrictedAreas = {
{pos = Vector(0, 0, 0), radius = 100}, -- Example restricted area
}
for _, area in ipairs(restrictedAreas) do
if pos:Distance(area.pos) < area.radius then
client:ChatPrint("Cannot drop items in this area")
return false
end
end
-- Check for admin restrictions
if char:getData("adminRestricted", false) then
client:ChatPrint("You are restricted from dropping items")
return false
end
return true
end)
CanPlayerEarnSalary
Purpose
Called to check if a player can earn salary
When Called
When salary payment is being processed
Parameters
client(Player): The player being checked
Returns
- boolean - True to allow, false to deny
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all players
hook.Add("CanPlayerEarnSalary", "MyAddon", function(client)
return true
end)
Medium Complexity:
-- Medium: Check if player is AFK
hook.Add("CanPlayerEarnSalary", "SalaryAFKCheck", function(client)
local isAFK = client:getNetVar("afk", false)
if isAFK then
return false
end
return true
end)
High Complexity:
-- High: Complex salary eligibility system
hook.Add("CanPlayerEarnSalary", "AdvancedSalaryCheck", function(client)
local char = client:getChar()
if not char then return false end
-- Check if player is AFK
local isAFK = client:getNetVar("afk", false)
if isAFK then
return false
end
-- Check minimum playtime
local playTime = client:GetUTimeTotalTime()
if playTime < 3600 then
return false
end
-- Check faction requirements
local faction = char:getFaction()
if faction == "citizen" then
-- Citizens need to be employed
if not char:getData("employed", false) then
return false
end
end
return true
end)
CanPlayerEquipItem
Purpose
Called to check if a player can equip an item
When Called
When a player attempts to equip an item
Parameters
client(Player): The player attempting to equip the itemitem(Item): The item being equipped
Returns
- boolean - True if equipping is allowed, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all item equips
hook.Add("CanPlayerEquipItem", "MyAddon", function(client, item)
return true
end)
Medium Complexity:
-- Medium: Check item type restrictions
hook.Add("CanPlayerEquipItem", "ItemEquipCheck", function(client, item)
-- Check if item is equippable
if not item:getData("equippable", false) then
client:ChatPrint("This item cannot be equipped")
return false
end
-- Check if already equipped
if item:getData("equipped", false) then
client:ChatPrint("This item is already equipped")
return false
end
return true
end)
High Complexity:
-- High: Complex item equip validation system
hook.Add("CanPlayerEquipItem", "AdvancedEquipValidation", function(client, item)
local char = client:getChar()
if not char then return false end
-- Check if item is equippable
if not item:getData("equippable", false) then
client:ChatPrint("This item cannot be equipped")
return false
end
-- Check if already equipped
if item:getData("equipped", false) then
client:ChatPrint("This item is already equipped")
return false
end
-- Check faction restrictions
local itemFaction = item:getData("faction")
if itemFaction then
local charFaction = char:getFaction()
if itemFaction ~= charFaction then
client:ChatPrint("You cannot equip faction-restricted items")
return false
end
end
-- Check level requirements
local requiredLevel = item:getData("requiredLevel", 1)
local charLevel = char:getData("level", 1)
if charLevel < requiredLevel then
client:ChatPrint("You need to be level " .. requiredLevel .. " to equip this item")
return false
end
-- Check attribute requirements
local requiredAttribs = item:getData("requiredAttribs", {})
for attr, value in pairs(requiredAttribs) do
local charAttr = char:getAttrib(attr, 0)
if charAttr < value then
client:ChatPrint("You need " .. attr .. " " .. value .. " to equip this item")
return false
end
end
-- Check for conflicting items
local itemType = item:getData("itemType")
if itemType then
local equippedItems = char:getInv():getItems()
for _, equippedItem in pairs(equippedItems) do
if equippedItem:getData("equipped", false) and equippedItem:getData("itemType") == itemType then
client:ChatPrint("You already have a " .. itemType .. " equipped")
return false
end
end
end
-- Check for special item restrictions
if item.uniqueID == "weapon_pistol" then
-- Special handling for weapons
if not char:hasFlags("w") then
client:ChatPrint("You need weapon flags to equip weapons")
return false
end
elseif item.uniqueID == "armor_vest" then
-- Special handling for armor
local charClass = char:getClass()
if charClass == "citizen" then
client:ChatPrint("Citizens cannot equip armor")
return false
end
end
-- Check for admin restrictions
if char:getData("adminRestricted", false) then
client:ChatPrint("You are restricted from equipping items")
return false
end
return true
end)
CanPlayerHoldObject
Purpose
Called to check if a player can hold an object
When Called
When a player attempts to pick up or hold an entity
Parameters
client(Player): The player attempting to hold the objectentity(Entity): The entity being held
Returns
- boolean - True if holding is allowed, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all object holding
hook.Add("CanPlayerHoldObject", "MyAddon", function(client, entity)
return true
end)
Medium Complexity:
-- Medium: Check entity type restrictions
hook.Add("CanPlayerHoldObject", "ObjectHoldCheck", function(client, entity)
-- Prevent holding certain entity types
if entity:GetClass() == "prop_physics" then
return true
end
return false
end)
High Complexity:
-- High: Complex object holding validation
hook.Add("CanPlayerHoldObject", "AdvancedHoldValidation", function(client, entity)
local char = client:getChar()
if not char then return false end
-- Check entity validity
if not IsValid(entity) then return false end
-- Check entity class
local allowedClasses = {"prop_physics", "prop_physics_multiplayer"}
if not table.HasValue(allowedClasses, entity:GetClass()) then
return false
end
-- Check faction restrictions
local faction = char:getFaction()
if faction == "prisoner" then
client:ChatPrint("Prisoners cannot hold objects")
return false
end
-- Check level requirements
local charLevel = char:getData("level", 1)
if charLevel < 5 then
client:ChatPrint("You need to be level 5 to hold objects")
return false
end
return true
end)
CanPlayerInteractItem
Purpose
Called to check if a player can interact with an item
When Called
When a player attempts to perform an action on an item
Parameters
client(Player): The player attempting the interactionaction(string): The action being performedself(Item): The item being interacted withdata(table): Additional data for the interaction
Returns
- boolean - True if interaction is allowed, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all item interactions
hook.Add("CanPlayerInteractItem", "MyAddon", function(client, action, self, data)
return true
end)
Medium Complexity:
-- Medium: Check action restrictions
hook.Add("CanPlayerInteractItem", "ItemInteractionCheck", function(client, action, self, data)
-- Check if action is allowed
if action == "use" then
return true
elseif action == "drop" then
if self:getData("noDrop", false) then
return false
end
return true
end
return false
end)
High Complexity:
-- High: Complex item interaction validation
hook.Add("CanPlayerInteractItem", "AdvancedInteractionValidation", function(client, action, self, data)
local char = client:getChar()
if not char then return false end
-- Check action restrictions
if action == "use" then
-- Check if item is usable
if self:getData("noUse", false) then
client:ChatPrint("This item cannot be used")
return false
end
elseif action == "drop" then
-- Check if item is droppable
if self:getData("noDrop", false) then
client:ChatPrint("This item cannot be dropped")
return false
end
elseif action == "equip" then
-- Check if item is equippable
if not self:getData("equippable", false) then
client:ChatPrint("This item cannot be equipped")
return false
end
end
-- Check faction restrictions
local itemFaction = self:getData("faction")
if itemFaction then
local charFaction = char:getFaction()
if itemFaction ~= charFaction then
client:ChatPrint("You cannot interact with faction-restricted items")
return false
end
end
return true
end)
CanPlayerJoinClass
Purpose
Called to check if a player can join a class
When Called
When a player attempts to join a specific class
Parameters
client(Player): The player attempting to join the classclass(number): The class ID being joinedinfo(table): Additional class information
Returns
- boolean - True if joining is allowed, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all class joins
hook.Add("CanPlayerJoinClass", "MyAddon", function(client, class, info)
return true
end)
Medium Complexity:
-- Medium: Check faction requirements
hook.Add("CanPlayerJoinClass", "ClassJoinCheck", function(client, class, info)
local char = client:getChar()
if not char then return false end
local faction = char:getFaction()
if faction == info.faction then
return true
end
return false
end)
High Complexity:
-- High: Complex class join validation
hook.Add("CanPlayerJoinClass", "AdvancedClassJoin", function(client, class, info)
local char = client:getChar()
if not char then return false end
-- Check faction requirements
if info.faction and char:getFaction() ~= info.faction then
client:ChatPrint("You must be in the " .. info.faction .. " faction to join this class")
return false
end
-- Check level requirements
if info.level and char:getData("level", 1) < info.level then
client:ChatPrint("You need to be level " .. info.level .. " to join this class")
return false
end
-- Check flag requirements
if info.flags and not char:hasFlags(info.flags) then
client:ChatPrint("You don't have the required flags to join this class")
return false
end
return true
end)
CanPlayerKnock
Purpose
Called to check if a player can knock on doors
When Called
When a player attempts to knock on a door
Parameters
client(Player): The player attempting to knock
Returns
- boolean - True if knocking is allowed, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all knocking
hook.Add("CanPlayerKnock", "MyAddon", function(client)
return true
end)
Medium Complexity:
-- Medium: Check character status
hook.Add("CanPlayerKnock", "KnockCheck", function(client)
local char = client:getChar()
if not char then return false end
if char:getData("unconscious", false) then
return false
end
return true
end)
High Complexity:
-- High: Complex knock validation
hook.Add("CanPlayerKnock", "AdvancedKnockValidation", function(client)
local char = client:getChar()
if not char then return false end
-- Check if player is unconscious
if char:getData("unconscious", false) then
client:ChatPrint("You cannot knock while unconscious")
return false
end
-- Check if player is gagged
if char:getData("gagged", false) then
client:ChatPrint("You cannot knock while gagged")
return false
end
-- Check knock cooldown
local lastKnock = char:getData("lastKnock", 0)
if os.time() - lastKnock < 2 then
client:ChatPrint("Please wait before knocking again")
return false
end
char:setData("lastKnock", os.time())
return true
end)
CanPlayerLock
Purpose
Called to check if a player can lock a door
When Called
When a player attempts to lock a door
Parameters
client(Player): The player attempting to lock the doordoor(Entity): The door entity being locked
Returns
- boolean - True if locking is allowed, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all door locking
hook.Add("CanPlayerLock", "MyAddon", function(client, door)
return true
end)
Medium Complexity:
-- Medium: Check door ownership
hook.Add("CanPlayerLock", "DoorLockCheck", function(client, door)
local owner = door:getNetVar("owner")
if owner == client:SteamID() then
return true
end
return false
end)
High Complexity:
-- High: Complex door lock validation
hook.Add("CanPlayerLock", "AdvancedDoorLock", function(client, door)
local char = client:getChar()
if not char then return false end
-- Check door ownership
local owner = door:getNetVar("owner")
if owner and owner ~= client:SteamID() then
client:ChatPrint("You don't own this door")
return false
end
-- Check if door is lockable
if door:getNetVar("noLock", false) then
client:ChatPrint("This door cannot be locked")
return false
end
-- Check faction permissions
local doorFaction = door:getNetVar("faction")
if doorFaction and char:getFaction() ~= doorFaction then
client:ChatPrint("You don't have permission to lock this door")
return false
end
return true
end)
CanPlayerModifyConfig
Purpose
Called to check if a player can modify configuration
When Called
When a player attempts to change a config value
Parameters
client(Player): The player attempting to modify configkey(string): The configuration key being modified
Returns
- boolean - True if modification is allowed, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: Only allow admins
hook.Add("CanPlayerModifyConfig", "MyAddon", function(client, key)
return client:IsAdmin()
end)
Medium Complexity:
-- Medium: Check specific config permissions
hook.Add("CanPlayerModifyConfig", "ConfigModCheck", function(client, key)
if client:IsSuperAdmin() then
return true
elseif client:IsAdmin() and key ~= "serverPassword" then
return true
end
return false
end)
High Complexity:
-- High: Complex config modification validation
hook.Add("CanPlayerModifyConfig", "AdvancedConfigMod", function(client, key)
-- Super admins can modify anything
if client:IsSuperAdmin() then
return true
end
-- Regular admins have limited access
if client:IsAdmin() then
local restrictedKeys = {"serverPassword", "rconPassword", "adminFlags"}
if table.HasValue(restrictedKeys, key) then
client:ChatPrint("You don't have permission to modify this config")
return false
end
return true
end
-- Check custom permissions
local char = client:getChar()
if char and char:hasFlags("c") then
return true
end
client:ChatPrint("You don't have permission to modify config")
return false
end)
CanPlayerOpenScoreboard
Purpose
Called to check if a player can open the scoreboard
When Called
When a player attempts to open the scoreboard
Parameters
client(Player): The player attempting to open the scoreboard
Returns
- boolean - True if opening is allowed, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all scoreboard access
hook.Add("CanPlayerOpenScoreboard", "MyAddon", function(client)
return true
end)
Medium Complexity:
-- Medium: Check character status
hook.Add("CanPlayerOpenScoreboard", "ScoreboardCheck", function(client)
local char = client:getChar()
if not char then return false end
if char:getData("unconscious", false) then
return false
end
return true
end)
High Complexity:
-- High: Complex scoreboard access validation
hook.Add("CanPlayerOpenScoreboard", "AdvancedScoreboardAccess", function(client)
local char = client:getChar()
if not char then return false end
-- Check if player is unconscious
if char:getData("unconscious", false) then
return false
end
-- Check faction restrictions
local faction = char:getFaction()
if faction == "prisoner" then
return false
end
-- Check level requirements
if char:getData("level", 1) < 1 then
return false
end
return true
end)
CanPlayerRotateItem
Purpose
Called to check if a player can rotate an item in inventory
When Called
When a player attempts to rotate an item
Parameters
client(Player): The player attempting to rotate the itemitem(Item): The item being rotated
Returns
- boolean - True if rotation is allowed, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all item rotation
hook.Add("CanPlayerRotateItem", "MyAddon", function(client, item)
return true
end)
Medium Complexity:
-- Medium: Check item properties
hook.Add("CanPlayerRotateItem", "RotateCheck", function(client, item)
-- Check if item is rotatable
if item:getData("noRotate", false) then
return false
end
return true
end)
High Complexity:
-- High: Complex item rotation validation
hook.Add("CanPlayerRotateItem", "AdvancedRotation", function(client, item)
local char = client:getChar()
if not char then return false end
-- Check if item is rotatable
if item:getData("noRotate", false) then
client:ChatPrint("This item cannot be rotated")
return false
end
-- Check if item is equipped
if item:getData("equipped", false) then
client:ChatPrint("Cannot rotate equipped items")
return false
end
return true
end)
CanPlayerSeeLogCategory
Purpose
Called to check if a player can see a log category
When Called
When determining which log categories a player can view
Parameters
client(Player): The player checking log accessk(string): The log category key
Returns
- boolean - True if viewing is allowed, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow admins to see all logs
hook.Add("CanPlayerSeeLogCategory", "MyAddon", function(client, k)
return client:IsAdmin()
end)
Medium Complexity:
-- Medium: Different permissions for different categories
hook.Add("CanPlayerSeeLogCategory", "LogCategoryCheck", function(client, k)
if client:IsSuperAdmin() then
return true
elseif client:IsAdmin() and k ~= "admin" then
return true
end
return false
end)
High Complexity:
-- High: Complex log category access control
hook.Add("CanPlayerSeeLogCategory", "AdvancedLogAccess", function(client, k)
-- Super admins see everything
if client:IsSuperAdmin() then
return true
end
-- Regular admins have limited access
if client:IsAdmin() then
local restrictedCategories = {"admin", "system", "security"}
if table.HasValue(restrictedCategories, k) then
return false
end
return true
end
-- Check custom permissions
local char = client:getChar()
if char and char:hasFlags("l") then
return true
end
return false
end)
CanPlayerSpawnStorage
Purpose
Called to check if a player can spawn storage entities
When Called
When a player attempts to spawn a storage container
Parameters
client(Player): The player attempting to spawn storageentity(Entity): The storage entity being spawnedinfo(table): Information about the storage entity
Returns
- boolean - True if spawning is allowed, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all storage spawning
hook.Add("CanPlayerSpawnStorage", "MyAddon", function(client, entity, info)
return true
end)
Medium Complexity:
-- Medium: Check faction permissions
hook.Add("CanPlayerSpawnStorage", "StorageSpawnCheck", function(client, entity, info)
local char = client:getChar()
if not char then return false end
if char:hasFlags("s") then
return true
end
return false
end)
High Complexity:
-- High: Complex storage spawn validation
hook.Add("CanPlayerSpawnStorage", "AdvancedStorageSpawn", function(client, entity, info)
local char = client:getChar()
if not char then return false end
-- Check storage flags
if not char:hasFlags("s") then
client:ChatPrint("You need storage flags to spawn storage")
return false
end
-- Check faction restrictions
if info.faction and char:getFaction() ~= info.faction then
client:ChatPrint("You cannot spawn this faction's storage")
return false
end
-- Check level requirements
if info.level and char:getData("level", 1) < info.level then
client:ChatPrint("You need to be level " .. info.level .. " to spawn this storage")
return false
end
-- Check storage limit
local storageCount = char:getData("storageCount", 0)
if storageCount >= 5 then
client:ChatPrint("You have reached the maximum storage limit")
return false
end
return true
end)
CanPlayerSwitchChar
Purpose
Called to check if a player can switch characters
When Called
When a player attempts to switch from one character to another
Parameters
client(Player): The player attempting to switchcurrentChar(Character): The current charactercharacter(Character): The character being switched to
Returns
- boolean - True if switching is allowed, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all character switching
hook.Add("CanPlayerSwitchChar", "MyAddon", function(client, currentChar, character)
return true
end)
Medium Complexity:
-- Medium: Check switch cooldown
hook.Add("CanPlayerSwitchChar", "SwitchCooldown", function(client, currentChar, character)
local lastSwitch = currentChar:getData("lastSwitch", 0)
if os.time() - lastSwitch < 300 then -- 5 minute cooldown
client:ChatPrint("Please wait before switching characters")
return false
end
return true
end)
High Complexity:
-- High: Complex character switch validation
hook.Add("CanPlayerSwitchChar", "AdvancedCharSwitch", function(client, currentChar, character)
-- Check switch cooldown
local lastSwitch = currentChar:getData("lastSwitch", 0)
if os.time() - lastSwitch < 300 then
client:ChatPrint("Please wait " .. (300 - (os.time() - lastSwitch)) .. " seconds before switching")
return false
end
-- Check if current character is in combat
if currentChar:getData("inCombat", false) then
client:ChatPrint("You cannot switch characters while in combat")
return false
end
-- Check if current character is unconscious
if currentChar:getData("unconscious", false) then
client:ChatPrint("You cannot switch characters while unconscious")
return false
end
-- Check faction switch limits
if currentChar:getFaction() ~= character:getFaction() then
local factionSwitches = currentChar:getData("factionSwitches", 0)
if factionSwitches >= 3 then
client:ChatPrint("You have reached the maximum faction switch limit")
return false
end
currentChar:setData("factionSwitches", factionSwitches + 1)
end
-- Update last switch time
currentChar:setData("lastSwitch", os.time())
return true
end)
CanPlayerTakeItem
Purpose
Called to check if a player can take an item
When Called
When a player attempts to take an item from the ground or another source
Parameters
client(Player): The player attempting to take the itemitem(Item): The item being taken
Returns
- boolean - True if taking is allowed, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all item takes
hook.Add("CanPlayerTakeItem", "MyAddon", function(client, item)
return true
end)
Medium Complexity:
-- Medium: Check item restrictions
hook.Add("CanPlayerTakeItem", "ItemTakeCheck", function(client, item)
-- Check if item is takeable
if item:getData("noTake", false) then
client:ChatPrint("This item cannot be taken")
return false
end
-- Check if item is owned by someone else
local owner = item:getData("owner")
if owner and owner ~= client:SteamID() then
client:ChatPrint("This item belongs to someone else")
return false
end
return true
end)
High Complexity:
-- High: Complex item take validation system
hook.Add("CanPlayerTakeItem", "AdvancedTakeValidation", function(client, item)
local char = client:getChar()
if not char then return false end
-- Check if item is takeable
if item:getData("noTake", false) then
client:ChatPrint("This item cannot be taken")
return false
end
-- Check if item is owned by someone else
local owner = item:getData("owner")
if owner and owner ~= client:SteamID() then
client:ChatPrint("This item belongs to someone else")
return false
end
-- Check faction restrictions
local itemFaction = item:getData("faction")
if itemFaction then
local charFaction = char:getFaction()
if itemFaction ~= charFaction then
client:ChatPrint("You cannot take faction-restricted items")
return false
end
end
-- Check level requirements
local requiredLevel = item:getData("requiredLevel", 1)
local charLevel = char:getData("level", 1)
if charLevel < requiredLevel then
client:ChatPrint("You need to be level " .. requiredLevel .. " to take this item")
return false
end
-- Check weight limits
local itemWeight = item:getWeight()
local inventory = char:getInv()
local currentWeight = inventory:getWeight()
local maxWeight = inventory:getMaxWeight()
if currentWeight + itemWeight > maxWeight then
client:ChatPrint("Not enough space in your inventory")
return false
end
-- Check for special item restrictions
if item.uniqueID == "weapon_pistol" then
-- Special handling for weapons
if not char:hasFlags("w") then
client:ChatPrint("You need weapon flags to take weapons")
return false
end
elseif item.uniqueID == "money" then
-- Special handling for money
local amount = item:getData("amount", 0)
if amount > 10000 then
client:ChatPrint("Cannot take more than $10,000 at once")
return false
end
end
-- Check location restrictions
local pos = client:GetPos()
local itemPos = item:getData("position")
if itemPos and pos:Distance(itemPos) > 100 then
client:ChatPrint("Item is too far away")
return false
end
-- Check for admin restrictions
if char:getData("adminRestricted", false) then
client:ChatPrint("You are restricted from taking items")
return false
end
return true
end)
CanPlayerThrowPunch
Purpose
Called to check if a player can throw a punch
When Called
When a player attempts to punch
Parameters
client(Player): The player attempting to punch
Returns
- boolean - True to allow, false to deny
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all players
hook.Add("CanPlayerThrowPunch", "MyAddon", function(client)
return true
end)
Medium Complexity:
-- Medium: Check stamina
hook.Add("CanPlayerThrowPunch", "PunchStaminaCheck", function(client)
local stamina = client:getNetVar("stamina", 100)
if stamina < 10 then
client:ChatPrint("Not enough stamina to punch")
return false
end
return true
end)
High Complexity:
-- High: Complex punch system
hook.Add("CanPlayerThrowPunch", "AdvancedPunchSystem", function(client)
local char = client:getChar()
if not char then return false end
-- Check stamina
local stamina = client:getNetVar("stamina", 100)
if stamina < 10 then
client:ChatPrint("Not enough stamina to punch")
return false
end
-- Check cooldown
local lastPunch = char:getData("lastPunch", 0)
if CurTime() - lastPunch < 1 then
return false
end
-- Check if player is tied
if char:getData("tied", false) then
return false
end
char:setData("lastPunch", CurTime())
return true
end)
CanPlayerTradeWithVendor
Purpose
Called to check if a player can trade with a vendor
When Called
When a player attempts to buy/sell from a vendor
Parameters
client(Player): The player attempting to tradevendor(table): The vendor dataitemType(string): The item type being tradedisSellingToVendor(boolean): True if selling, false if buying
Returns
- boolean - True to allow, false to deny
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all trades
hook.Add("CanPlayerTradeWithVendor", "MyAddon", function(client, vendor, itemType, isSellingToVendor)
return true
end)
Medium Complexity:
-- Medium: Check faction restrictions
hook.Add("CanPlayerTradeWithVendor", "VendorTradeCheck", function(client, vendor, itemType, isSellingToVendor)
local char = client:getChar()
if not char then return false end
local allowedFactions = vendor.allowedFactions
if allowedFactions and not table.HasValue(allowedFactions, char:getFaction()) then
client:ChatPrint("Your faction cannot trade with this vendor")
return false
end
return true
end)
High Complexity:
-- High: Complex vendor trading system
hook.Add("CanPlayerTradeWithVendor", "AdvancedVendorTrade", function(client, vendor, itemType, isSellingToVendor)
local char = client:getChar()
if not char then return false end
-- Check faction restrictions
local allowedFactions = vendor.allowedFactions
if allowedFactions and not table.HasValue(allowedFactions, char:getFaction()) then
client:ChatPrint("Your faction cannot trade with this vendor")
return false
end
-- Check level requirements
local requiredLevel = vendor.requiredLevel or 0
local charLevel = char:getData("level", 1)
if charLevel < requiredLevel then
client:ChatPrint("You need to be level " .. requiredLevel .. " to trade with this vendor")
return false
end
-- Check reputation
local requiredRep = vendor.requiredReputation or 0
local charRep = char:getData("reputation", 0)
if charRep < requiredRep then
client:ChatPrint("You need " .. requiredRep .. " reputation to trade with this vendor")
return false
end
-- Check trade cooldown
local lastTrade = char:getData("lastVendorTrade", 0)
if os.time() - lastTrade < 5 then
client:ChatPrint("Please wait before trading again")
return false
end
char:setData("lastVendorTrade", os.time())
return true
end)
CanPlayerUnequipItem
Purpose
Called to check if a player can unequip an item
When Called
When a player attempts to unequip an item
Parameters
client(Player): The player attempting to unequip the itemitem(Item): The item being unequipped
Returns
- boolean - True if unequipping is allowed, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all item unequips
hook.Add("CanPlayerUnequipItem", "MyAddon", function(client, item)
return true
end)
Medium Complexity:
-- Medium: Check if item is equipped
hook.Add("CanPlayerUnequipItem", "ItemUnequipCheck", function(client, item)
-- Check if item is equipped
if not item:getData("equipped", false) then
client:ChatPrint("This item is not equipped")
return false
end
-- Check if item is unequippable
if item:getData("noUnequip", false) then
client:ChatPrint("This item cannot be unequipped")
return false
end
return true
end)
High Complexity:
-- High: Complex item unequip validation system
hook.Add("CanPlayerUnequipItem", "AdvancedUnequipValidation", function(client, item)
local char = client:getChar()
if not char then return false end
-- Check if item is equipped
if not item:getData("equipped", false) then
client:ChatPrint("This item is not equipped")
return false
end
-- Check if item is unequippable
if item:getData("noUnequip", false) then
client:ChatPrint("This item cannot be unequipped")
return false
end
-- Check faction restrictions
local itemFaction = item:getData("faction")
if itemFaction then
local charFaction = char:getFaction()
if itemFaction ~= charFaction then
client:ChatPrint("You cannot unequip faction-restricted items")
return false
end
end
-- Check level requirements
local requiredLevel = item:getData("requiredLevel", 1)
local charLevel = char:getData("level", 1)
if charLevel < requiredLevel then
client:ChatPrint("You need to be level " .. requiredLevel .. " to unequip this item")
return false
end
-- Check for special item restrictions
if item.uniqueID == "weapon_pistol" then
-- Special handling for weapons
if not char:hasFlags("w") then
client:ChatPrint("You need weapon flags to unequip weapons")
return false
end
elseif item.uniqueID == "armor_vest" then
-- Special handling for armor
local charClass = char:getClass()
if charClass == "citizen" then
client:ChatPrint("Citizens cannot unequip armor")
return false
end
end
-- Check for admin restrictions
if char:getData("adminRestricted", false) then
client:ChatPrint("You are restricted from unequipping items")
return false
end
-- Check inventory space
local inventory = char:getInv()
if inventory:getWeight() + item:getWeight() > inventory:getMaxWeight() then
client:ChatPrint("Not enough space in your inventory")
return false
end
return true
end)
CanPlayerUnlock
Purpose
Called to check if a player can unlock a door
When Called
When a player attempts to unlock a door
Parameters
client(Player): The player attempting to unlock the doordoor(Entity): The door entity being unlocked
Returns
- boolean - True if unlocking is allowed, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all door unlocking
hook.Add("CanPlayerUnlock", "MyAddon", function(client, door)
return true
end)
Medium Complexity:
-- Medium: Check door ownership
hook.Add("CanPlayerUnlock", "DoorUnlockCheck", function(client, door)
local owner = door:getNetVar("owner")
if owner == client:SteamID() then
return true
end
return false
end)
High Complexity:
-- High: Complex door unlock validation
hook.Add("CanPlayerUnlock", "AdvancedDoorUnlock", function(client, door)
local char = client:getChar()
if not char then return false end
-- Check door ownership
local owner = door:getNetVar("owner")
if owner and owner ~= client:SteamID() then
client:ChatPrint("You don't own this door")
return false
end
-- Check faction permissions
local doorFaction = door:getNetVar("faction")
if doorFaction and char:getFaction() ~= doorFaction then
client:ChatPrint("You don't have permission to unlock this door")
return false
end
return true
end)
CanPlayerUseChar
Purpose
Called to check if a player can use a character
When Called
When a player attempts to load a character
Parameters
client(Player): The player attempting to use the charactercharacter(Character): The character being used
Returns
- boolean - True if using is allowed, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all character usage
hook.Add("CanPlayerUseChar", "MyAddon", function(client, character)
return true
end)
Medium Complexity:
-- Medium: Check character ownership
hook.Add("CanPlayerUseChar", "CharUseCheck", function(client, character)
if character:getSteamID() == client:SteamID() then
return true
end
return false
end)
High Complexity:
-- High: Complex character use validation
hook.Add("CanPlayerUseChar", "AdvancedCharUse", function(client, character)
-- Check character ownership
if character:getSteamID() ~= client:SteamID() then
client:ChatPrint("This character doesn't belong to you")
return false
end
-- Check if character is banned
if character:getData("banned", false) then
client:ChatPrint("This character is banned")
return false
end
-- Check if character is deleted
if character:getData("deleted", false) then
client:ChatPrint("This character has been deleted")
return false
end
return true
end)
CanPlayerUseCommand
Purpose
Called to check if a player can use a command
When Called
When a player attempts to execute a command
Parameters
client(Player): The player attempting to use the commandcommand(string): The command being executed
Returns
- boolean - True if command use is allowed, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all commands
hook.Add("CanPlayerUseCommand", "MyAddon", function(client, command)
return true
end)
Medium Complexity:
-- Medium: Check admin commands
hook.Add("CanPlayerUseCommand", "CommandCheck", function(client, command)
local adminCommands = {"kick", "ban", "slay"}
if table.HasValue(adminCommands, command) then
return client:IsAdmin()
end
return true
end)
High Complexity:
-- High: Complex command permission system
hook.Add("CanPlayerUseCommand", "AdvancedCommandPerms", function(client, command)
local char = client:getChar()
if not char then return false end
-- Check admin commands
local adminCommands = {"kick", "ban", "slay", "bring", "goto"}
if table.HasValue(adminCommands, command) then
if not client:IsAdmin() then
client:ChatPrint("You need admin permissions to use this command")
return false
end
end
-- Check faction-specific commands
local factionCommands = {
["police"] = {"arrest", "warrant", "unarrest"},
["medic"] = {"heal", "revive"}
}
local faction = char:getFaction()
for fac, commands in pairs(factionCommands) do
if table.HasValue(commands, command) then
if faction ~= fac then
client:ChatPrint("You need to be in the " .. fac .. " faction to use this command")
return false
end
end
end
-- Check command cooldowns
local lastCommand = char:getData("lastCommand_" .. command, 0)
if os.time() - lastCommand < 5 then
client:ChatPrint("Please wait before using this command again")
return false
end
char:setData("lastCommand_" .. command, os.time())
return true
end)
CanPlayerUseDoor
Purpose
Called to check if a player can use a door
When Called
When a player attempts to interact with a door
Parameters
client(Player): The player attempting to use the doordoor(Entity): The door entity being used
Returns
- boolean - True if door use is allowed, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all door usage
hook.Add("CanPlayerUseDoor", "MyAddon", function(client, door)
return true
end)
Medium Complexity:
-- Medium: Check door ownership
hook.Add("CanPlayerUseDoor", "DoorUseCheck", function(client, door)
local owner = door:getNetVar("owner")
if owner and owner ~= client:SteamID() then
return false
end
return true
end)
High Complexity:
-- High: Complex door use validation
hook.Add("CanPlayerUseDoor", "AdvancedDoorUse", function(client, door)
local char = client:getChar()
if not char then return false end
-- Check door ownership
local owner = door:getNetVar("owner")
if owner and owner ~= client:SteamID() then
-- Check if door is shared
local sharedWith = door:getNetVar("sharedWith", {})
if not table.HasValue(sharedWith, client:SteamID()) then
client:ChatPrint("You don't have permission to use this door")
return false
end
end
-- Check faction permissions
local doorFaction = door:getNetVar("faction")
if doorFaction and char:getFaction() ~= doorFaction then
client:ChatPrint("You don't have permission to use this faction's door")
return false
end
-- Check if door is locked
if door:getNetVar("locked", false) then
client:ChatPrint("This door is locked")
return false
end
return true
end)
CanPlayerViewInventory
Purpose
Called to check if a player can view inventories
When Called
When a player attempts to open any inventory
Returns
- boolean - True if viewing inventories is allowed, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all inventory viewing
hook.Add("CanPlayerViewInventory", "MyAddon", function()
return true
end)
Medium Complexity:
-- Medium: Check player status
hook.Add("CanPlayerViewInventory", "InventoryViewCheck", function()
local client = LocalPlayer()
if not client then return false end
local char = client:getChar()
if not char then return false end
-- Check if player is unconscious
if char:getData("unconscious", false) then
client:ChatPrint("You cannot view inventories while unconscious")
return false
end
return true
end)
High Complexity:
-- High: Complex inventory view validation system
hook.Add("CanPlayerViewInventory", "AdvancedInventoryView", function()
local client = LocalPlayer()
if not client then return false end
local char = client:getChar()
if not char then return false end
-- Check if player is unconscious
if char:getData("unconscious", false) then
client:ChatPrint("You cannot view inventories while unconscious")
return false
end
-- Check if player is dead
if client:Health() <= 0 then
client:ChatPrint("You cannot view inventories while dead")
return false
end
-- Check if player is gagged
if char:getData("gagged", false) then
client:ChatPrint("You cannot view inventories while gagged")
return false
end
-- Check if player is muted
if char:getData("muted", false) then
client:ChatPrint("You cannot view inventories while muted")
return false
end
-- Check for admin restrictions
if char:getData("adminRestricted", false) then
client:ChatPrint("You are restricted from viewing inventories")
return false
end
-- Check faction restrictions
local faction = char:getFaction()
if faction == "prisoner" then
client:ChatPrint("Prisoners cannot view inventories")
return false
end
-- Check level requirements
local charLevel = char:getData("level", 1)
if charLevel < 1 then
client:ChatPrint("You need to be level 1 to view inventories")
return false
end
-- Check for special conditions
local pos = client:GetPos()
local restrictedAreas = {
{pos = Vector(0, 0, 0), radius = 100}, -- Example restricted area
}
for _, area in ipairs(restrictedAreas) do
if pos:Distance(area.pos) < area.radius then
client:ChatPrint("Cannot view inventories in this area")
return false
end
end
return true
end)
CanRunItemAction
Purpose
Called to check if an item action can be run
When Called
When attempting to execute an item action
Parameters
itemTable(table): The item table containing the actionk(string): The action key being executed
Returns
- boolean - True if action can be run, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all item actions
hook.Add("CanRunItemAction", "MyAddon", function(itemTable, k)
return true
end)
Medium Complexity:
-- Medium: Check action restrictions
hook.Add("CanRunItemAction", "ActionCheck", function(itemTable, k)
-- Check if action exists
if not itemTable[k] then
return false
end
-- Check if action is disabled
if itemTable:getData("actionDisabled", false) then
return false
end
return true
end)
High Complexity:
-- High: Complex item action validation
hook.Add("CanRunItemAction", "AdvancedActionValidation", function(itemTable, k)
-- Check if action exists
if not itemTable[k] then
return false
end
-- Check if action is disabled
if itemTable:getData("actionDisabled", false) then
return false
end
-- Check faction restrictions
local actionFaction = itemTable:getData("actionFaction")
if actionFaction then
local char = LocalPlayer():getChar()
if char and char:getFaction() ~= actionFaction then
return false
end
end
-- Check level requirements
local requiredLevel = itemTable:getData("requiredLevel", 1)
local char = LocalPlayer():getChar()
if char then
local charLevel = char:getData("level", 1)
if charLevel < requiredLevel then
return false
end
end
return true
end)
CanSaveData
Purpose
Called to check if entity data can be saved
When Called
When attempting to save entity data to the database
Parameters
ent(Entity): The entity being savedinventory(Inventory): The inventory associated with the entity
Returns
- boolean - True if data can be saved, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all data saving
hook.Add("CanSaveData", "MyAddon", function(ent, inventory)
return true
end)
Medium Complexity:
-- Medium: Check entity validity
hook.Add("CanSaveData", "DataSaveCheck", function(ent, inventory)
-- Check if entity is valid
if not IsValid(ent) then
return false
end
-- Check if entity is persistent
if not ent:getNetVar("persistent", false) then
return false
end
return true
end)
High Complexity:
-- High: Complex data save validation
hook.Add("CanSaveData", "AdvancedDataSave", function(ent, inventory)
-- Check if entity is valid
if not IsValid(ent) then
return false
end
-- Check if entity is persistent
if not ent:getNetVar("persistent", false) then
return false
end
-- Check if entity has owner
local owner = ent:getNetVar("owner")
if not owner then
return false
end
-- Check if owner is online
local ownerPlayer = player.GetBySteamID(owner)
if not IsValid(ownerPlayer) then
return false
end
-- Check if entity is in valid location
local pos = ent:GetPos()
if pos.z < -1000 or pos.z > 1000 then
return false
end
return true
end)
CharCleanUp
Purpose
Called when a character is cleaned up
When Called
When a character is being removed from memory
Parameters
character(Character): The character being cleaned up
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log character cleanup
hook.Add("CharCleanUp", "MyAddon", function(character)
print("Character cleaned up: " .. character:getName())
end)
Medium Complexity:
-- Medium: Clean up character data
hook.Add("CharCleanUp", "CharDataCleanup", function(character)
-- Clear character data
character:setData("lastCleanup", os.time())
-- Clear temporary data
character:setData("tempData", nil)
character:setData("cachedData", nil)
print("Character data cleaned up: " .. character:getName())
end)
High Complexity:
-- High: Complex character cleanup system
hook.Add("CharCleanUp", "AdvancedCharCleanup", function(character)
-- Clear character data
character:setData("lastCleanup", os.time())
-- Clear temporary data
character:setData("tempData", nil)
character:setData("cachedData", nil)
-- Clear active effects
character:setData("activeEffects", {})
-- Clear active quests
character:setData("activeQuests", {})
-- Clear recognition data
character:setData("recognitions", {})
-- Clear inventory cache
local inventory = character:getInv()
if inventory then
inventory:setData("cachedItems", nil)
end
-- Clear position data
character:setData("lastPos", nil)
character:setData("lastAng", nil)
-- Log cleanup
print(string.format("Character %s (ID: %d) cleaned up",
character:getName(), character:getID()))
end)
CharDeleted
Purpose
Called when a character is deleted
When Called
When a character is successfully deleted
Parameters
client(Player): The player whose character was deletedcharacter(Character): The character that was deleted
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log character deletion
hook.Add("CharDeleted", "MyAddon", function(client, character)
print(client:Name() .. " deleted character: " .. character:getName())
end)
Medium Complexity:
-- Medium: Handle character deletion effects
hook.Add("CharDeleted", "CharDeletionEffects", function(client, character)
-- Clear character data
character:setData("deleted", true)
character:setData("deletionTime", os.time())
-- Notify other players
for _, ply in ipairs(player.GetAll()) do
if ply ~= client then
ply:ChatPrint(character:getName() .. " was deleted")
end
end
end)
High Complexity:
-- High: Complex character deletion system
hook.Add("CharDeleted", "AdvancedCharDeletion", function(client, character)
-- Set deletion data
character:setData("deleted", true)
character:setData("deletionTime", os.time())
-- Clear character inventory
local inventory = character:getInv()
if inventory then
local items = inventory:getItems()
for _, item in pairs(items) do
inventory:remove(item)
end
end
-- Clear character money
character:setMoney(0)
-- Clear character attributes
local attributes = character:getAttribs()
for attr, _ in pairs(attributes) do
character:setAttrib(attr, 0)
end
-- Clear character data
character:setData("level", 1)
character:setData("experience", 0)
character:setData("activeQuests", {})
character:setData("activeEffects", {})
-- Check for faction-specific effects
local faction = character:getFaction()
if faction == "police" then
-- Police character deleted
for _, ply in ipairs(player.GetAll()) do
local plyChar = ply:getChar()
if plyChar and plyChar:getFaction() == "police" and ply ~= client then
ply:ChatPrint("[POLICE] " .. character:getName() .. " was deleted")
end
end
elseif faction == "medic" then
-- Medic character deleted
for _, ply in ipairs(player.GetAll()) do
local plyChar = ply:getChar()
if plyChar and plyChar:getFaction() == "medic" and ply ~= client then
ply:ChatPrint("[MEDICAL] " .. character:getName() .. " was deleted")
end
end
end
-- Notify other players
for _, ply in ipairs(player.GetAll()) do
if ply ~= client then
ply:ChatPrint(character:getName() .. " was deleted")
end
end
-- Log deletion
print(string.format("%s deleted character %s (Faction: %s)",
client:Name(), character:getName(), faction))
end)
CharForceRecognized
Purpose
Called to force character recognition
When Called
When a character is forced to be recognized
Parameters
ply(Player): The player being recognizedrange(number): The recognition range
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log forced recognition
hook.Add("CharForceRecognized", "MyAddon", function(ply, range)
print(ply:Name() .. " was force recognized")
end)
Medium Complexity:
-- Medium: Handle forced recognition effects
hook.Add("CharForceRecognized", "ForceRecognitionEffects", function(ply, range)
local char = ply:getChar()
if char then
-- Set recognition data
char:setData("forceRecognized", true)
char:setData("recognitionTime", os.time())
-- Notify player
ply:ChatPrint("You have been force recognized")
end
end)
High Complexity:
-- High: Complex force recognition system
hook.Add("CharForceRecognized", "AdvancedForceRecognition", function(ply, range)
local char = ply:getChar()
if not char then return end
-- Set recognition data
char:setData("forceRecognized", true)
char:setData("recognitionTime", os.time())
char:setData("recognitionRange", range)
-- Check for faction-specific effects
local faction = char:getFaction()
if faction == "police" then
-- Police force recognition
for _, target in ipairs(player.GetAll()) do
if target ~= ply then
local targetChar = target:getChar()
if targetChar and targetChar:getFaction() == "police" then
target:ChatPrint("[POLICE] " .. char:getName() .. " was force recognized")
end
end
end
elseif faction == "medic" then
-- Medic force recognition
for _, target in ipairs(player.GetAll()) do
if target ~= ply then
local targetChar = target:getChar()
if targetChar and targetChar:getFaction() == "medic" then
target:ChatPrint("[MEDICAL] " .. char:getName() .. " was force recognized")
end
end
end
end
-- Notify player
ply:ChatPrint("You have been force recognized")
-- Log force recognition
print(string.format("%s was force recognized (Faction: %s, Range: %d)",
ply:Name(), faction, range))
end)
CharHasFlags
Purpose
Called to check if a character has specific flags
When Called
When checking if a character has certain permissions
Parameters
self(Character): The character being checkedflags(string): The flags to check for
Returns
- boolean - True if character has flags, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: Check basic flags
hook.Add("CharHasFlags", "MyAddon", function(self, flags)
return self:getData("flags", ""):find(flags) ~= nil
end)
Medium Complexity:
-- Medium: Check faction-based flags
hook.Add("CharHasFlags", "FactionFlags", function(self, flags)
local faction = self:getFaction()
local factionFlags = {
["police"] = "w",
["medic"] = "m",
["citizen"] = ""
}
local hasFactionFlags = factionFlags[faction] or ""
return hasFactionFlags:find(flags) ~= nil
end)
High Complexity:
-- High: Complex flag checking system
hook.Add("CharHasFlags", "AdvancedFlagCheck", function(self, flags)
-- Check basic flags
local charFlags = self:getData("flags", "")
if charFlags:find(flags) then
return true
end
-- Check faction-based flags
local faction = self:getFaction()
local factionFlags = {
["police"] = "w",
["medic"] = "m",
["citizen"] = ""
}
local hasFactionFlags = factionFlags[faction] or ""
if hasFactionFlags:find(flags) then
return true
end
-- Check level-based flags
local charLevel = self:getData("level", 1)
if charLevel >= 10 and flags == "v" then
return true
end
-- Check admin flags
local client = self:getPlayer()
if client and client:IsAdmin() and flags == "a" then
return true
end
return false
end)
CharLoaded
Purpose
Called when a character is loaded
When Called
When a character is successfully loaded from the database
Parameters
id(number): The ID of the character that was loaded
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log character loading
hook.Add("CharLoaded", "MyAddon", function(id)
print("Character loaded: " .. id)
end)
Medium Complexity:
-- Medium: Handle character loading effects
hook.Add("CharLoaded", "CharLoadingEffects", function(id)
local character = lia.char.getByID(id)
if character then
-- Set loading data
character:setData("loaded", true)
character:setData("loadTime", os.time())
print("Character " .. character:getName() .. " loaded successfully")
end
end)
High Complexity:
-- High: Complex character loading system
hook.Add("CharLoaded", "AdvancedCharLoading", function(id)
local character = lia.char.getByID(id)
if not character then return end
-- Set loading data
character:setData("loaded", true)
character:setData("loadTime", os.time())
-- Get character data
local name = character:getName()
local faction = character:getFaction()
local level = character:getData("level", 1)
-- Check for faction-specific loading effects
if faction == "police" then
-- Police character loaded
for _, ply in ipairs(player.GetAll()) do
local plyChar = ply:getChar()
if plyChar and plyChar:getFaction() == "police" then
ply:ChatPrint("[POLICE] " .. name .. " has joined the force")
end
end
elseif faction == "medic" then
-- Medic character loaded
for _, ply in ipairs(player.GetAll()) do
local plyChar = ply:getChar()
if plyChar and plyChar:getFaction() == "medic" then
ply:ChatPrint("[MEDICAL] " .. name .. " has joined the medical staff")
end
end
end
-- Check for level-based effects
if level >= 10 then
print("High level character loaded: " .. name .. " (Level " .. level .. ")")
end
-- Log character loading
print(string.format("Character %s (ID: %d, Faction: %s, Level: %d) loaded successfully",
name, id, faction, level))
end)
CharPostSave
Purpose
Called after a character is saved
When Called
After character data has been saved to the database
Parameters
self(Character): The character that was saved
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log character save
hook.Add("CharPostSave", "MyAddon", function(self)
print("Character " .. self:getName() .. " saved")
end)
Medium Complexity:
-- Medium: Update save timestamp
hook.Add("CharPostSave", "SaveTimestamp", function(self)
self:setData("lastSave", os.time())
print("Character " .. self:getName() .. " saved at " .. os.date("%H:%M:%S"))
end)
High Complexity:
-- High: Complex post-save handling
hook.Add("CharPostSave", "AdvancedPostSave", function(self)
-- Update save timestamp
self:setData("lastSave", os.time())
-- Increment save count
local saveCount = self:getData("saveCount", 0) + 1
self:setData("saveCount", saveCount)
-- Create backup every 10 saves
if saveCount % 10 == 0 then
lia.char.createBackup(self:getID())
print("Backup created for character " .. self:getName())
end
print(string.format("Character %s saved (Save #%d)", self:getName(), saveCount))
end)
CharPreSave
Purpose
Called before a character is saved
When Called
Before character data is saved to the database
Parameters
character(Character): The character being saved
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log character save
hook.Add("CharPreSave", "MyAddon", function(character)
print("Saving character: " .. character:getName())
end)
Medium Complexity:
-- Medium: Validate character data
hook.Add("CharPreSave", "SaveValidation", function(character)
-- Validate money
local money = character:getMoney()
if money < 0 then
character:setMoney(0)
print("Fixed negative money for " .. character:getName())
end
end)
High Complexity:
-- High: Complex pre-save validation
hook.Add("CharPreSave", "AdvancedPreSave", function(character)
-- Validate money
local money = character:getMoney()
if money < 0 then
character:setMoney(0)
elseif money > 1000000 then
character:setMoney(1000000)
end
-- Validate attributes
local attributes = character:getAttribs()
for attr, value in pairs(attributes) do
if value < 0 then
character:setAttrib(attr, 0)
elseif value > 100 then
character:setAttrib(attr, 100)
end
end
-- Update save preparation timestamp
character:setData("preSaveTime", os.time())
print("Character " .. character:getName() .. " validated and ready for save")
end)
CharRestored
Purpose
Called when a character is restored
When Called
When a character is restored from backup or death
Parameters
character(Character): The character being restored
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log character restoration
hook.Add("CharRestored", "MyAddon", function(character)
print("Character " .. character:getName() .. " restored")
end)
Medium Complexity:
-- Medium: Handle restoration effects
hook.Add("CharRestored", "RestorationEffects", function(character)
character:setData("restored", true)
character:setData("restoreTime", os.time())
print("Character " .. character:getName() .. " restored successfully")
end)
High Complexity:
-- High: Complex character restoration
hook.Add("CharRestored", "AdvancedRestoration", function(character)
-- Set restoration data
character:setData("restored", true)
character:setData("restoreTime", os.time())
-- Restore health and stamina
local client = character:getPlayer()
if client then
client:SetHealth(100)
client:setNetVar("stamina", 100)
end
-- Clear negative effects
character:setData("unconscious", false)
character:setData("bleeding", false)
print("Character " .. character:getName() .. " fully restored")
end)
ChatParsed
Purpose
Called when chat is parsed
When Called
When a chat message is processed and parsed
Parameters
client(Player): The player who sent the messagechatType(string): The type of chat (ic, ooc, etc)message(string): The message contentanonymous(boolean): Whether the message is anonymous
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log parsed chat
hook.Add("ChatParsed", "MyAddon", function(client, chatType, message, anonymous)
print(client:Name() .. " sent " .. chatType .. " message: " .. message)
end)
Medium Complexity:
-- Medium: Filter chat messages
hook.Add("ChatParsed", "ChatFilter", function(client, chatType, message, anonymous)
-- Filter spam
if string.len(message) > 500 then
client:ChatPrint("Message too long")
return false
end
end)
High Complexity:
-- High: Complex chat parsing
hook.Add("ChatParsed", "AdvancedChatParse", function(client, chatType, message, anonymous)
local char = client:getChar()
if not char then return false end
-- Check for spam
local lastMessage = char:getData("lastMessage", "")
if lastMessage == message then
client:ChatPrint("Don't spam the same message")
return false
end
char:setData("lastMessage", message)
-- Check message length
if string.len(message) > 500 then
client:ChatPrint("Message too long (max 500 characters)")
return false
end
-- Log chat
lia.log.add(client, "chat", chatType, message)
end)
CheckFactionLimitReached
Purpose
Called to check if a faction limit has been reached
When Called
When checking if more players can join a faction
Parameters
faction(number): The faction ID being checkedcharacter(Character): The character attempting to joinclient(Player): The player attempting to join
Returns
- boolean - True if limit is reached, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: No faction limits
hook.Add("CheckFactionLimitReached", "MyAddon", function(faction, character, client)
return false
end)
Medium Complexity:
-- Medium: Basic faction limits
hook.Add("CheckFactionLimitReached", "FactionLimits", function(faction, character, client)
local factionData = lia.faction.indices[faction]
if factionData and factionData.limit then
local count = 0
for _, ply in ipairs(player.GetAll()) do
local char = ply:getChar()
if char and char:getFaction() == faction then
count = count + 1
end
end
return count >= factionData.limit
end
return false
end)
High Complexity:
-- High: Complex faction limit system
hook.Add("CheckFactionLimitReached", "AdvancedFactionLimits", function(faction, character, client)
local factionData = lia.faction.indices[faction]
if not factionData then return false end
-- Count current faction members
local count = 0
for _, ply in ipairs(player.GetAll()) do
local char = ply:getChar()
if char and char:getFaction() == faction then
count = count + 1
end
end
-- Check base limit
local limit = factionData.limit or math.huge
-- Adjust limit based on server population
local playerCount = #player.GetAll()
if playerCount < 10 then
limit = math.floor(limit * 0.5)
elseif playerCount > 50 then
limit = math.floor(limit * 1.5)
end
-- Check if limit is reached
if count >= limit then
client:ChatPrint("Faction limit reached (" .. count .. "/" .. limit .. ")")
return true
end
return false
end)
CommandRan
Purpose
Called when a command is executed
When Called
After a command has been run by a player
Parameters
client(Player): The player who ran the commandcommand(string): The command that was executedarguments(table): The arguments passed to the commandresults(any): The results returned by the command
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log command execution
hook.Add("CommandRan", "MyAddon", function(client, command, arguments, results)
print(client:Name() .. " ran command: " .. command)
end)
Medium Complexity:
-- Medium: Track command usage
hook.Add("CommandRan", "CommandUsageTracking", function(client, command, arguments, results)
local char = client:getChar()
if char then
local commandCount = char:getData("commandCount", 0) + 1
char:setData("commandCount", commandCount)
end
end)
High Complexity:
-- High: Complex command execution tracking
hook.Add("CommandRan", "AdvancedCommandTracking", function(client, command, arguments, results)
local char = client:getChar()
if not char then return end
-- Track command usage
local commandCount = char:getData("commandCount", 0) + 1
char:setData("commandCount", commandCount)
-- Track command history
local commandHistory = char:getData("commandHistory", {})
table.insert(commandHistory, {
command = command,
arguments = arguments,
timestamp = os.time(),
results = results
})
-- Keep only last 50 commands
if #commandHistory > 50 then
table.remove(commandHistory, 1)
end
char:setData("commandHistory", commandHistory)
-- Log command execution
lia.log.add(client, "command", command, table.concat(arguments, " "))
print(string.format("%s ran command: %s (Args: %d, Success: %s)",
client:Name(), command, #arguments, tostring(results ~= false)))
end)
ConfigChanged
Purpose
Called when a configuration value changes
When Called
When a config option is modified
Parameters
key(string): The configuration key that changedvalue(any): The new valueoldValue(any): The previous valueclient(Player): The player who changed the config (if applicable)
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log config changes
hook.Add("ConfigChanged", "MyAddon", function(key, value, oldValue, client)
print("Config changed: " .. key .. " = " .. tostring(value))
end)
Medium Complexity:
-- Medium: Handle specific config changes
hook.Add("ConfigChanged", "ConfigHandling", function(key, value, oldValue, client)
if key == "maxPlayers" then
game.MaxPlayers = value
elseif key == "serverName" then
RunConsoleCommand("hostname", value)
end
end)
High Complexity:
-- High: Complex config change handling
hook.Add("ConfigChanged", "AdvancedConfigChange", function(key, value, oldValue, client)
-- Log config change
if client then
lia.log.add(client, "config", key, tostring(oldValue) .. " -> " .. tostring(value))
end
-- Handle specific config changes
if key == "maxPlayers" then
game.MaxPlayers = value
print("Max players updated to: " .. value)
elseif key == "serverName" then
RunConsoleCommand("hostname", value)
print("Server name updated to: " .. value)
elseif key == "password" then
if value and value ~= "" then
RunConsoleCommand("sv_password", value)
print("Server password set")
else
RunConsoleCommand("sv_password", "")
print("Server password removed")
end
end
-- Notify admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("[CONFIG] " .. key .. " changed to: " .. tostring(value))
end
end
end)
CreateCharacter
Purpose
Called when creating a character
When Called
When a new character is being created
Parameters
data(table): The character creation data
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log character creation
hook.Add("CreateCharacter", "MyAddon", function(data)
print("Creating character: " .. data.name)
end)
Medium Complexity:
-- Medium: Add default items
hook.Add("CreateCharacter", "DefaultItems", function(data)
data.items = data.items or {}
table.insert(data.items, "wallet")
table.insert(data.items, "phone")
end)
High Complexity:
-- High: Complex character creation
hook.Add("CreateCharacter", "AdvancedCreation", function(data)
-- Add default items
data.items = data.items or {}
table.insert(data.items, "wallet")
table.insert(data.items, "phone")
-- Add faction-specific items
local factionItems = {
["police"] = {"handcuffs", "radio"},
["medic"] = {"medkit", "bandage"}
}
local items = factionItems[data.faction]
if items then
for _, item in ipairs(items) do
table.insert(data.items, item)
end
end
-- Set creation timestamp
data.createdAt = os.time()
print("Character " .. data.name .. " created with " .. #data.items .. " items")
end)
CreateDefaultInventory
Purpose
Called to create a character's default inventory
When Called
When a new character needs an inventory created
Parameters
character(Character): The character receiving the inventory
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log inventory creation
hook.Add("CreateDefaultInventory", "MyAddon", function(character)
print("Creating inventory for: " .. character:getName())
end)
Medium Complexity:
-- Medium: Set inventory size based on faction
hook.Add("CreateDefaultInventory", "FactionInventory", function(character)
local faction = character:getFaction()
local sizes = {
["police"] = {w = 8, h = 6},
["medic"] = {w = 7, h = 5},
["citizen"] = {w = 6, h = 4}
}
local size = sizes[faction] or {w = 6, h = 4}
character:getInv():setSize(size.w, size.h)
end)
High Complexity:
-- High: Complex inventory setup
hook.Add("CreateDefaultInventory", "AdvancedInventorySetup", function(character)
local faction = character:getFaction()
-- Set inventory size based on faction
local sizes = {
["police"] = {w = 8, h = 6},
["medic"] = {w = 7, h = 5},
["citizen"] = {w = 6, h = 4}
}
local size = sizes[faction] or {w = 6, h = 4}
local inv = character:getInv()
inv:setSize(size.w, size.h)
-- Set weight limits
local weights = {
["police"] = 50,
["medic"] = 40,
["citizen"] = 30
}
inv:setData("maxWeight", weights[faction] or 30)
-- Add starting items
local startingItems = {
["police"] = {"handcuffs", "radio"},
["medic"] = {"medkit"},
["citizen"] = {"wallet"}
}
local items = startingItems[faction] or {}
for _, itemID in ipairs(items) do
local item = lia.item.instance(itemID)
if item then
inv:add(item)
end
end
print("Inventory created for " .. character:getName() .. " (" .. size.w .. "x" .. size.h .. ")")
end)
CreateSalaryTimers
Purpose
Called to create salary timers
When Called
When salary system is being initialized
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Create basic salary timer
hook.Add("CreateSalaryTimers", "MyAddon", function()
timer.Create("SalaryTimer", 300, 0, function()
for _, ply in ipairs(player.GetAll()) do
local char = ply:getChar()
if char then
char:giveMoney(100)
end
end
end)
end)
Medium Complexity:
-- Medium: Faction-based salary timers
hook.Add("CreateSalaryTimers", "FactionSalaryTimers", function()
timer.Create("SalaryTimer", 300, 0, function()
for _, ply in ipairs(player.GetAll()) do
local char = ply:getChar()
if char then
local faction = char:getFaction()
local salary = 100
if faction == "police" then
salary = 200
elseif faction == "medic" then
salary = 150
end
char:giveMoney(salary)
ply:ChatPrint("You received $" .. salary .. " salary")
end
end
end)
end)
High Complexity:
-- High: Complex salary timer system
hook.Add("CreateSalaryTimers", "AdvancedSalaryTimers", function()
timer.Create("SalaryTimer", 300, 0, function()
for _, ply in ipairs(player.GetAll()) do
local char = ply:getChar()
if not char then continue end
-- Check if player can earn salary
if not hook.Run("CanPlayerEarnSalary", ply) then
continue
end
-- Calculate base salary
local faction = char:getFaction()
local baseSalary = hook.Run("GetSalaryAmount", ply, faction) or 100
-- Apply level bonus
local level = char:getData("level", 1)
local levelBonus = math.floor(level * 5)
-- Apply rank bonus
local rank = char:getData("rank", 0)
local rankBonus = rank * 25
-- Calculate total salary
local totalSalary = baseSalary + levelBonus + rankBonus
-- Give salary
char:giveMoney(totalSalary)
ply:ChatPrint("You received $" .. totalSalary .. " salary")
-- Update statistics
local totalEarned = char:getData("totalSalaryEarned", 0)
char:setData("totalSalaryEarned", totalEarned + totalSalary)
end
end)
end)
CustomClassValidation
Purpose
Called for custom class validation
When Called
When validating a player's class change
Parameters
client(Player): The player changing classnewClass(string): The new class being validated
Returns
- boolean - True to allow, false to deny
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all class changes
hook.Add("CustomClassValidation", "MyAddon", function(client, newClass)
return true
end)
Medium Complexity:
-- Medium: Check level requirements
hook.Add("CustomClassValidation", "ClassLevelCheck", function(client, newClass)
local char = client:getChar()
if not char then return false end
local classLevels = {
["warrior"] = 1,
["mage"] = 5,
["rogue"] = 10
}
local requiredLevel = classLevels[newClass] or 1
local charLevel = char:getData("level", 1)
if charLevel < requiredLevel then
client:ChatPrint("You need to be level " .. requiredLevel .. " to become a " .. newClass)
return false
end
return true
end)
High Complexity:
-- High: Complex class validation system
hook.Add("CustomClassValidation", "AdvancedClassValidation", function(client, newClass)
local char = client:getChar()
if not char then return false end
-- Check level requirements
local classLevels = {
["warrior"] = 1,
["mage"] = 5,
["rogue"] = 10,
["paladin"] = 15
}
local requiredLevel = classLevels[newClass] or 1
local charLevel = char:getData("level", 1)
if charLevel < requiredLevel then
client:ChatPrint("You need to be level " .. requiredLevel .. " to become a " .. newClass)
return false
end
-- Check faction restrictions
local faction = char:getFaction()
local classFactions = {
["paladin"] = {"police", "medic"},
["rogue"] = {"citizen"}
}
local allowedFactions = classFactions[newClass]
if allowedFactions and not table.HasValue(allowedFactions, faction) then
client:ChatPrint("Your faction cannot become a " .. newClass)
return false
end
-- Check prerequisites
local classPrereqs = {
["paladin"] = {"warrior"},
["mage"] = {"apprentice"}
}
local prereqs = classPrereqs[newClass]
if prereqs then
local completedClasses = char:getData("completedClasses", {})
for _, prereq in ipairs(prereqs) do
if not table.HasValue(completedClasses, prereq) then
client:ChatPrint("You must complete " .. prereq .. " class first")
return false
end
end
end
return true
end)
CustomLogHandler
Purpose
Called for custom log handling
When Called
When a log message is being processed
Parameters
message(string): The log messagecategory(string): The log category
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Print all logs
hook.Add("CustomLogHandler", "MyAddon", function(message, category)
print("[" .. category .. "] " .. message)
end)
Medium Complexity:
-- Medium: Filter logs by category
hook.Add("CustomLogHandler", "LogFilter", function(message, category)
local importantCategories = {"admin", "error", "warning"}
if table.HasValue(importantCategories, category) then
print("[IMPORTANT][" .. category .. "] " .. message)
end
end)
High Complexity:
-- High: Complex log handling system
hook.Add("CustomLogHandler", "AdvancedLogHandler", function(message, category)
-- Print to console
print("[" .. category .. "] " .. message)
-- Save to database
lia.db.query("INSERT INTO logs (timestamp, category, message) VALUES (?, ?, ?)", os.time(), category, message)
-- Notify admins of important logs
local importantCategories = {"admin", "error", "warning", "exploit"}
if table.HasValue(importantCategories, category) then
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("[LOG][" .. category .. "] " .. message)
end
end
end
-- Send to Discord webhook for critical logs
if category == "error" or category == "exploit" then
local embed = {
title = "Critical Log: " .. category,
description = message,
color = 16711680,
timestamp = os.date("!%Y-%m-%dT%H:%M:%S")
}
hook.Run("DiscordRelaySend", embed)
end
end)
DatabaseConnected
Purpose
Called when database is connected
When Called
When the database connection is established
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log connection
hook.Add("DatabaseConnected", "MyAddon", function()
print("Database connected")
end)
Medium Complexity:
-- Medium: Initialize tables
hook.Add("DatabaseConnected", "DatabaseInit", function()
lia.db.query("CREATE TABLE IF NOT EXISTS custom_data (id INTEGER PRIMARY KEY, data TEXT)")
print("Database connected and tables initialized")
end)
High Complexity:
-- High: Complex database initialization
hook.Add("DatabaseConnected", "AdvancedDatabaseInit", function()
-- Create tables
local tables = {
"CREATE TABLE IF NOT EXISTS custom_data (id INTEGER PRIMARY KEY, data TEXT)",
"CREATE TABLE IF NOT EXISTS player_stats (steamid TEXT PRIMARY KEY, kills INTEGER, deaths INTEGER)",
"CREATE TABLE IF NOT EXISTS achievements (id INTEGER PRIMARY KEY, name TEXT, description TEXT)"
}
for _, query in ipairs(tables) do
lia.db.query(query)
end
-- Create indexes
lia.db.query("CREATE INDEX IF NOT EXISTS idx_player_stats_steamid ON player_stats(steamid)")
print("Database connected and fully initialized")
end)
DeleteCharacter
Purpose
Called when a character is deleted
When Called
When a character deletion is processed
Parameters
id(number): The character ID being deleted
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log deletion
hook.Add("DeleteCharacter", "MyAddon", function(id)
print("Character " .. id .. " deleted")
end)
Medium Complexity:
-- Medium: Clean up character data
hook.Add("DeleteCharacter", "CharacterCleanup", function(id)
lia.db.query("DELETE FROM character_items WHERE charid = ?", id)
lia.db.query("DELETE FROM character_stats WHERE charid = ?", id)
print("Character " .. id .. " deleted and data cleaned up")
end)
High Complexity:
-- High: Complex character deletion system
hook.Add("DeleteCharacter", "AdvancedCharacterDeletion", function(id)
-- Clean up character data
lia.db.query("DELETE FROM character_items WHERE charid = ?", id)
lia.db.query("DELETE FROM character_stats WHERE charid = ?", id)
lia.db.query("DELETE FROM character_achievements WHERE charid = ?", id)
-- Archive character data
lia.db.query("INSERT INTO character_archive SELECT * FROM characters WHERE id = ?", id)
-- Notify admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("Character " .. id .. " has been deleted")
end
end
print("Character " .. id .. " deleted and archived")
end)
DiscordRelaySend
Purpose
Called to send a Discord relay message
When Called
When sending a message to Discord
Parameters
embed(table): The Discord embed data
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log Discord send
hook.Add("DiscordRelaySend", "MyAddon", function(embed)
print("Sending Discord message: " .. (embed.title or "No title"))
end)
Medium Complexity:
-- Medium: Add server info to embed
hook.Add("DiscordRelaySend", "DiscordServerInfo", function(embed)
embed.footer = {
text = "Server: " .. GetHostName()
}
print("Sending Discord message with server info")
end)
High Complexity:
-- High: Complex Discord relay system
hook.Add("DiscordRelaySend", "AdvancedDiscordRelay", function(embed)
-- Add server info
embed.footer = {
text = "Server: " .. GetHostName() .. " | Players: " .. #player.GetAll()
}
-- Add timestamp if not present
if not embed.timestamp then
embed.timestamp = os.date("!%Y-%m-%dT%H:%M:%S")
end
-- Add color based on type
if not embed.color then
if string.find(embed.title or "", "Error") then
embed.color = 16711680 -- Red
elseif string.find(embed.title or "", "Warning") then
embed.color = 16776960 -- Yellow
else
embed.color = 65280 -- Green
end
end
print("Sending Discord message: " .. (embed.title or "No title"))
end)
DiscordRelayUnavailable
Purpose
Called when Discord relay is unavailable
When Called
When Discord relay connection fails
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log unavailability
hook.Add("DiscordRelayUnavailable", "MyAddon", function()
print("Discord relay is unavailable")
end)
Medium Complexity:
-- Medium: Notify admins
hook.Add("DiscordRelayUnavailable", "DiscordNotify", function()
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("Discord relay is unavailable")
end
end
end)
High Complexity:
-- High: Complex Discord failover system
hook.Add("DiscordRelayUnavailable", "AdvancedDiscordFailover", function()
-- Log to file
file.Append("discord_errors.txt", os.date() .. ": Discord relay unavailable\n")
-- Notify admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("[ERROR] Discord relay is unavailable")
end
end
-- Attempt reconnection
timer.Simple(60, function()
print("Attempting to reconnect Discord relay...")
-- Reconnection logic here
end)
end)
DiscordRelayed
Purpose
Called when a message is relayed to Discord
When Called
After a message is successfully sent to Discord
Parameters
embed(table): The Discord embed that was sent
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log successful relay
hook.Add("DiscordRelayed", "MyAddon", function(embed)
print("Message relayed to Discord")
end)
Medium Complexity:
-- Medium: Track relay statistics
hook.Add("DiscordRelayed", "DiscordStats", function(embed)
local relayCount = lia.data.get("discordRelayCount", 0)
lia.data.set("discordRelayCount", relayCount + 1)
print("Message relayed to Discord (Total: " .. (relayCount + 1) .. ")")
end)
High Complexity:
-- High: Complex Discord relay tracking
hook.Add("DiscordRelayed", "AdvancedDiscordTracking", function(embed)
-- Update statistics
local relayCount = lia.data.get("discordRelayCount", 0)
lia.data.set("discordRelayCount", relayCount + 1)
-- Log to database
lia.db.query("INSERT INTO discord_logs (timestamp, title, description) VALUES (?, ?, ?)",
os.time(), embed.title or "No title", embed.description or "No description")
-- Track relay types
local relayTypes = lia.data.get("discordRelayTypes", {})
local msgType = embed.title or "unknown"
relayTypes[msgType] = (relayTypes[msgType] or 0) + 1
lia.data.set("discordRelayTypes", relayTypes)
print("Message relayed to Discord: " .. msgType)
end)
DoorEnabledToggled
Purpose
Called when a door's enabled state is toggled
When Called
When a door is enabled or disabled
Parameters
client(Player): The player toggling the statedoor(Entity): The door entitynewState(boolean): The new enabled state
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log door state change
hook.Add("DoorEnabledToggled", "MyAddon", function(client, door, newState)
print(client:Name() .. " set door to " .. (newState and "enabled" or "disabled"))
end)
Medium Complexity:
-- Medium: Notify nearby players
hook.Add("DoorEnabledToggled", "DoorStateNotify", function(client, door, newState)
local doorPos = door:GetPos()
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(doorPos) < 500 then
ply:ChatPrint("A door has been " .. (newState and "enabled" or "disabled"))
end
end
end)
High Complexity:
-- High: Complex door state management
hook.Add("DoorEnabledToggled", "AdvancedDoorState", function(client, door, newState)
-- Log the change
print(client:Name() .. " set door to " .. (newState and "enabled" or "disabled"))
-- Update door data
door:setNetVar("enabled", newState)
door:setNetVar("lastToggled", os.time())
door:setNetVar("lastToggledBy", client:SteamID())
-- Notify nearby players
local doorPos = door:GetPos()
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(doorPos) < 500 then
ply:ChatPrint(client:Name() .. " " .. (newState and "enabled" or "disabled") .. " a door")
end
end
-- Log to database
lia.db.query("INSERT INTO door_logs (timestamp, steamid, doorid, action) VALUES (?, ?, ?, ?)",
os.time(), client:SteamID(), door:MapCreationID(), newState and "enabled" or "disabled")
end)
DoorHiddenToggled
Purpose
Called when a door's hidden state is toggled
When Called
When a door is made hidden or visible
Parameters
client(Player): The player toggling the door visibilityentity(Entity): The door entitynewState(boolean): The new hidden state
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log door visibility change
hook.Add("DoorHiddenToggled", "MyAddon", function(client, entity, newState)
print(client:Name() .. " toggled door visibility to " .. tostring(newState))
end)
Medium Complexity:
-- Medium: Notify nearby players
hook.Add("DoorHiddenToggled", "NotifyDoorVisibility", function(client, entity, newState)
local doorPos = entity:GetPos()
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(doorPos) < 500 then
ply:ChatPrint("A door has been " .. (newState and "hidden" or "made visible"))
end
end
end)
High Complexity:
-- High: Complex door visibility system
hook.Add("DoorHiddenToggled", "AdvancedDoorVisibility", function(client, entity, newState)
-- Update door data
entity:setNetVar("hidden", newState)
entity:setNetVar("lastToggled", os.time())
entity:setNetVar("lastToggledBy", client:SteamID())
-- Log to database
lia.db.query("INSERT INTO door_logs (timestamp, steamid, doorid, action) VALUES (?, ?, ?, ?)",
os.time(), client:SteamID(), entity:MapCreationID(), newState and "hidden" or "unhidden")
-- Notify nearby players
local doorPos = entity:GetPos()
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(doorPos) < 500 and ply ~= client then
ply:ChatPrint(client:Name() .. " " .. (newState and "hid" or "unhid") .. " a door")
end
end
-- Update door physics
if newState then
entity:SetNoDraw(true)
entity:SetCollisionGroup(COLLISION_GROUP_IN_VEHICLE)
else
entity:SetNoDraw(false)
entity:SetCollisionGroup(COLLISION_GROUP_NONE)
end
end)
DoorLockToggled
Purpose
Called when a door's lock state is toggled
When Called
When a door is locked or unlocked
Parameters
client(Player): The player toggling the door lockdoor(Entity): The door entitystate(boolean): True if locked, false if unlocked
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log door lock changes
hook.Add("DoorLockToggled", "MyAddon", function(client, door, state)
local status = state and "locked" or "unlocked"
print(client:Name() .. " " .. status .. " door " .. door:EntIndex())
end)
Medium Complexity:
-- Medium: Track door lock statistics
hook.Add("DoorLockToggled", "DoorTracking", function(client, door, state)
local doorData = door:getNetVar("doorData", {})
doorData.lockCount = (doorData.lockCount or 0) + 1
doorData.lastLocked = os.time()
door:setNetVar("doorData", doorData)
local char = client:getChar()
if char then
char:setData("doorsLocked", (char:getData("doorsLocked", 0) + 1))
end
end)
High Complexity:
-- High: Complex door locking system
hook.Add("DoorLockToggled", "AdvancedDoorLocking", function(client, door, state)
local char = client:getChar()
if not char then return end
-- Check if player has permission to lock doors
if not char:hasFlags("D") then
client:ChatPrint("You don't have permission to lock doors")
return false
end
-- Check if door is owned by player
local doorOwner = door:getNetVar("owner")
if doorOwner and doorOwner ~= char:getID() then
client:ChatPrint("You don't own this door")
return false
end
-- Check for lock cooldown
local lastLock = char:getData("lastDoorLock", 0)
local lockCooldown = 5 -- 5 seconds
if os.time() - lastLock < lockCooldown then
client:ChatPrint("Please wait before locking another door")
return false
end
-- Update door data
local doorData = door:getNetVar("doorData", {})
doorData.lockCount = (doorData.lockCount or 0) + 1
doorData.lastLocked = os.time()
doorData.lockedBy = char:getID()
door:setNetVar("doorData", doorData)
-- Update character statistics
char:setData("doorsLocked", (char:getData("doorsLocked", 0) + 1))
char:setData("lastDoorLock", os.time())
-- Check for achievement
local doorsLocked = char:getData("doorsLocked", 0)
if doorsLocked >= 100 and not char:getData("achievement_locksmith", false) then
char:setData("achievement_locksmith", true)
client:ChatPrint("Achievement unlocked: Locksmith!")
end
-- Notify nearby players
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(door:GetPos()) < 500 then
local status = state and "locked" or "unlocked"
ply:ChatPrint(client:Name() .. " " .. status .. " a door")
end
end
-- Log door lock
print(string.format("%s %s door %s at %s",
client:Name(), state and "locked" or "unlocked", door:EntIndex(), os.date("%Y-%m-%d %H:%M:%S")))
end)
DoorOwnableToggled
Purpose
Called when a door's ownable status is toggled
When Called
When a door is set to be ownable or not ownable
Parameters
client(Player): The player toggling the ownable statusdoor(Entity): The door entitynewState(boolean): The new ownable state (true = ownable, false = not ownable)
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log ownable toggle
hook.Add("DoorOwnableToggled", "MyAddon", function(client, door, newState)
print(client:Name() .. " set door ownable to: " .. tostring(newState))
end)
Medium Complexity:
-- Medium: Handle ownable state changes
hook.Add("DoorOwnableToggled", "OwnableHandling", function(client, door, newState)
local doorData = door:getNetVar("doorData", {})
doorData.ownable = newState
door:setNetVar("doorData", doorData)
if not newState then
-- Clear owner when door becomes non-ownable
door:setNetVar("owner", nil)
end
end)
High Complexity:
-- High: Complex ownable toggle system
hook.Add("DoorOwnableToggled", "AdvancedOwnableToggle", function(client, door, newState)
local char = client:getChar()
if not char then return end
-- Update door data
local doorData = door:getNetVar("doorData", {})
doorData.ownable = newState
doorData.ownableChangedBy = char:getID()
doorData.ownableChangedAt = os.time()
door:setNetVar("doorData", doorData)
if not newState then
-- Clear owner and related data
local owner = door:getNetVar("owner")
if owner then
door:setNetVar("owner", nil)
door:setNetVar("locked", false)
door:setNetVar("sharedWith", {})
-- Notify previous owner
for _, ply in ipairs(player.GetAll()) do
if ply:SteamID() == owner then
ply:ChatPrint("Your door has been set to non-ownable")
end
end
end
end
-- Notify nearby players
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(door:GetPos()) < 500 then
ply:ChatPrint("Door " .. door:EntIndex() .. " is now " .. (newState and "ownable" or "not ownable"))
end
end
-- Log ownable toggle
print(string.format("%s set door %s ownable to: %s",
client:Name(), door:EntIndex(), tostring(newState)))
end)
DoorPriceSet
Purpose
Called when a door's price is set
When Called
When a door's purchase/rent price is changed
Parameters
client(Player): The player setting the pricedoor(Entity): The door entityprice(number): The new price
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log price change
hook.Add("DoorPriceSet", "MyAddon", function(client, door, price)
print(client:Name() .. " set door price to $" .. price)
end)
Medium Complexity:
-- Medium: Validate price range
hook.Add("DoorPriceSet", "DoorPriceValidation", function(client, door, price)
if price < 0 or price > 10000 then
client:ChatPrint("Price must be between $0 and $10000")
return false
end
door:setNetVar("price", price)
client:ChatPrint("Door price set to $" .. price)
end)
High Complexity:
-- High: Complex door pricing system
hook.Add("DoorPriceSet", "AdvancedDoorPricing", function(client, door, price)
-- Validate price range
if price < 0 or price > 10000 then
client:ChatPrint("Price must be between $0 and $10000")
return false
end
-- Check admin override
if not client:IsAdmin() then
local char = client:getChar()
if not char then return false end
-- Check door ownership
local owner = door:getNetVar("owner")
if owner ~= char:getID() then
client:ChatPrint("You don't own this door")
return false
end
end
-- Set price
door:setNetVar("price", price)
door:setNetVar("priceSetBy", client:SteamID())
door:setNetVar("priceSetTime", os.time())
-- Notify nearby players
local doorPos = door:GetPos()
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(doorPos) < 500 and ply ~= client then
ply:ChatPrint("A door's price was set to $" .. price)
end
end
client:ChatPrint("Door price set to $" .. price)
-- Log to database
lia.db.query("INSERT INTO door_logs (timestamp, steamid, doorid, action, value) VALUES (?, ?, ?, ?, ?)",
os.time(), client:SteamID(), door:MapCreationID(), "price_set", price)
end)
DoorTitleSet
Purpose
Called when a door's title is set
When Called
When a door's display name is changed
Parameters
client(Player): The player setting the titledoor(Entity): The door entityname(string): The new door title
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log title change
hook.Add("DoorTitleSet", "MyAddon", function(client, door, name)
print(client:Name() .. " set door title to: " .. name)
end)
Medium Complexity:
-- Medium: Validate title length
hook.Add("DoorTitleSet", "DoorTitleValidation", function(client, door, name)
if #name > 50 then
client:ChatPrint("Door title must be 50 characters or less")
return false
end
door:setNetVar("title", name)
client:ChatPrint("Door title set to: " .. name)
end)
High Complexity:
-- High: Complex door title system
hook.Add("DoorTitleSet", "AdvancedDoorTitle", function(client, door, name)
-- Validate title length
if #name > 50 then
client:ChatPrint("Door title must be 50 characters or less")
return false
end
-- Filter inappropriate content
local bannedWords = {"spam", "hack", "cheat"}
for _, word in ipairs(bannedWords) do
if string.find(string.lower(name), string.lower(word)) then
client:ChatPrint("Door title contains inappropriate content")
return false
end
end
-- Check admin override
if not client:IsAdmin() then
local char = client:getChar()
if not char then return false end
-- Check door ownership
local owner = door:getNetVar("owner")
if owner ~= char:getID() then
client:ChatPrint("You don't own this door")
return false
end
end
-- Set title
door:setNetVar("title", name)
door:setNetVar("titleSetBy", client:SteamID())
door:setNetVar("titleSetTime", os.time())
-- Notify nearby players
local doorPos = door:GetPos()
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(doorPos) < 500 and ply ~= client then
ply:ChatPrint("A door's title was changed to: " .. name)
end
end
client:ChatPrint("Door title set to: " .. name)
-- Log to database
lia.db.query("INSERT INTO door_logs (timestamp, steamid, doorid, action, value) VALUES (?, ?, ?, ?, ?)",
os.time(), client:SteamID(), door:MapCreationID(), "title_set", name)
end)
FetchSpawns
Purpose
Called to fetch spawn points
When Called
When spawn points need to be loaded or refreshed
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log spawn fetching
hook.Add("FetchSpawns", "MyAddon", function()
print("Fetching spawn points")
end)
Medium Complexity:
-- Medium: Load spawn points from database
hook.Add("FetchSpawns", "SpawnLoading", function()
local spawns = lia.db.query("SELECT * FROM spawns")
lia.spawns = spawns
print("Loaded " .. #spawns .. " spawn points")
end)
High Complexity:
-- High: Complex spawn point system
hook.Add("FetchSpawns", "AdvancedSpawnSystem", function()
-- Load spawns from database
local spawns = lia.db.query("SELECT * FROM spawns WHERE active = 1")
-- Categorize spawns by faction
lia.spawns = {
police = {},
medic = {},
citizen = {},
criminal = {}
}
for _, spawn in ipairs(spawns) do
local faction = spawn.faction or "citizen"
if lia.spawns[faction] then
table.insert(lia.spawns[faction], {
pos = Vector(spawn.x, spawn.y, spawn.z),
ang = Angle(spawn.pitch, spawn.yaw, spawn.roll),
name = spawn.name
})
end
end
-- Log spawn counts
for faction, factionSpawns in pairs(lia.spawns) do
print(faction .. " spawns: " .. #factionSpawns)
end
end)
ForceRecognizeRange
Purpose
Called to force recognition range
When Called
When setting the recognition range for a player
Parameters
ply(Player): The player to set recognition range forrange(number): The recognition rangefakeName(string): The fake name to use (optional)
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log recognition range setting
hook.Add("ForceRecognizeRange", "MyAddon", function(ply, range, fakeName)
print("Set recognition range for " .. ply:Name() .. ": " .. range)
end)
Medium Complexity:
-- Medium: Set recognition data
hook.Add("ForceRecognizeRange", "RecognitionRange", function(ply, range, fakeName)
local char = ply:getChar()
if char then
char:setData("recognitionRange", range)
if fakeName then
char:setData("fakeName", fakeName)
end
end
end)
High Complexity:
-- High: Complex recognition range system
hook.Add("ForceRecognizeRange", "AdvancedRecognitionRange", function(ply, range, fakeName)
local char = ply:getChar()
if not char then return end
-- Set recognition range
char:setData("recognitionRange", range)
char:setData("recognitionRangeSet", os.time())
-- Set fake name if provided
if fakeName and fakeName ~= "" then
char:setData("fakeName", fakeName)
char:setData("usingFakeName", true)
else
char:setData("fakeName", nil)
char:setData("usingFakeName", false)
end
-- Notify player
ply:ChatPrint("Recognition range set to " .. range .. " units")
if fakeName then
ply:ChatPrint("Fake name set to: " .. fakeName)
end
-- Log recognition range change
print(string.format("Recognition range set for %s: %d units (Fake name: %s)",
ply:Name(), range, fakeName or "None"))
end)
GetAllCaseClaims
Purpose
Called to get all case claims
When Called
When retrieving all active case claims
Returns
- table - Table of all case claims
Realm
Server
Example Usage
Low Complexity:
-- Simple: Return empty claims table
hook.Add("GetAllCaseClaims", "MyAddon", function()
return {}
end)
Medium Complexity:
-- Medium: Load claims from database
hook.Add("GetAllCaseClaims", "ClaimsLoading", function()
local claims = lia.db.query("SELECT * FROM case_claims WHERE active = 1")
return claims or {}
end)
High Complexity:
-- High: Complex case claims system
hook.Add("GetAllCaseClaims", "AdvancedCaseClaims", function()
-- Load claims from database
local claims = lia.db.query("SELECT * FROM case_claims WHERE active = 1")
-- Process and format claims
local processedClaims = {}
for _, claim in ipairs(claims or {}) do
local processedClaim = {
id = claim.id,
caseNumber = claim.case_number,
claimant = claim.claimant,
amount = claim.amount,
status = claim.status,
createdAt = claim.created_at,
description = claim.description
}
-- Add claimant character info
local char = lia.char.getByID(claim.claimant)
if char then
processedClaim.claimantName = char:getName()
processedClaim.claimantFaction = char:getFaction()
end
table.insert(processedClaims, processedClaim)
end
-- Sort by creation date
table.sort(processedClaims, function(a, b)
return a.createdAt > b.createdAt
end)
return processedClaims
end)
GetAttributeMax
Purpose
Called to get the maximum value for an attribute
When Called
When calculating attribute limits
Parameters
target(Player): The player whose attribute max is being checkedattrKey(string): The attribute key
Returns
- number - The maximum attribute value
Realm
Shared
Example Usage
Low Complexity:
-- Simple: Return default max
hook.Add("GetAttributeMax", "MyAddon", function(target, attrKey)
return 100
end)
Medium Complexity:
-- Medium: Attribute-specific maxes
hook.Add("GetAttributeMax", "AttributeMaxes", function(target, attrKey)
local maxes = {
["str"] = 100,
["dex"] = 80,
["int"] = 120
}
return maxes[attrKey] or 100
end)
High Complexity:
-- High: Complex attribute max system
hook.Add("GetAttributeMax", "AdvancedAttributeMax", function(target, attrKey)
local char = target:getChar()
if not char then return 100 end
-- Base max
local baseMax = 100
-- Faction bonuses
local faction = char:getFaction()
if faction == "warrior" and attrKey == "str" then
baseMax = baseMax + 20
elseif faction == "mage" and attrKey == "int" then
baseMax = baseMax + 30
end
-- Level bonuses
local level = char:getData("level", 1)
baseMax = baseMax + (level * 2)
-- Item bonuses
local inventory = char:getInv()
if inventory then
for _, item in pairs(inventory:getItems()) do
if item:getData("equipped", false) then
local attrBonus = item.attrBonus or {}
if attrBonus[attrKey] then
baseMax = baseMax + attrBonus[attrKey]
end
end
end
end
return baseMax
end)
GetAttributeStartingMax
Purpose
Called to get the starting maximum for an attribute
When Called
When a character is created
Parameters
client(Player): The player creating the characterk(string): The attribute key
Returns
- number - The starting maximum attribute value
Realm
Server
Example Usage
Low Complexity:
-- Simple: Return default starting max
hook.Add("GetAttributeStartingMax", "MyAddon", function(client, k)
return 50
end)
Medium Complexity:
-- Medium: Attribute-specific starting maxes
hook.Add("GetAttributeStartingMax", "AttributeStartingMaxes", function(client, k)
local startingMaxes = {
["str"] = 50,
["dex"] = 40,
["int"] = 60
}
return startingMaxes[k] or 50
end)
High Complexity:
-- High: Complex starting attribute system
hook.Add("GetAttributeStartingMax", "AdvancedStartingAttributes", function(client, k)
-- Base starting max
local baseMax = 50
-- Check if player has played before
local playTime = client:GetUTimeTotalTime()
if playTime > 36000 then -- 10 hours
baseMax = baseMax + 10
end
-- Check for donator status
if client:getNetVar("donator", false) then
baseMax = baseMax + 5
end
-- Attribute-specific bonuses
local attrBonuses = {
["str"] = 0,
["dex"] = -10,
["int"] = 10
}
baseMax = baseMax + (attrBonuses[k] or 0)
return baseMax
end)
GetCharMaxStamina
Purpose
Gets the maximum stamina for a character
When Called
When calculating character stamina limits
Parameters
char(Character): The character to get max stamina for
Returns
- number - The maximum stamina value
Realm
Server
Example Usage
Low Complexity:
-- Simple: Return default max stamina
hook.Add("GetCharMaxStamina", "MyAddon", function(char)
return 100
end)
Medium Complexity:
-- Medium: Base stamina on constitution
hook.Add("GetCharMaxStamina", "ConstitutionStamina", function(char)
local con = char:getAttrib("con", 0)
return 100 + (con * 5)
end)
High Complexity:
-- High: Complex stamina system
hook.Add("GetCharMaxStamina", "AdvancedStamina", function(char)
local baseStamina = 100
-- Constitution bonus
local con = char:getAttrib("con", 0)
local conBonus = con * 5
-- Level bonus
local charLevel = char:getData("level", 1)
local levelBonus = charLevel * 2
-- Faction bonus
local faction = char:getFaction()
local factionBonuses = {
["police"] = 20,
["medic"] = 15,
["athlete"] = 50,
["citizen"] = 0
}
local factionBonus = factionBonuses[faction] or 0
-- Equipment bonuses
local inventory = char:getInv()
local equipmentBonus = 0
for _, item in pairs(inventory:getItems()) do
if item:getData("equipped", false) then
local staminaBonus = item:getData("staminaBonus", 0)
equipmentBonus = equipmentBonus + staminaBonus
end
end
-- Perk bonuses
local perks = char:getData("perks", {})
local perkBonus = 0
for _, perk in ipairs(perks) do
if perk.type == "stamina" then
perkBonus = perkBonus + perk.value
end
end
-- Calculate final stamina
local finalStamina = baseStamina + conBonus + levelBonus + factionBonus + equipmentBonus + perkBonus
-- Apply debuffs
local debuffs = char:getData("debuffs", {})
for _, debuff in ipairs(debuffs) do
if debuff.type == "stamina" then
finalStamina = finalStamina * (1 - debuff.value)
end
end
return math.max(math.floor(finalStamina), 10) -- Minimum of 10
end)
GetDamageScale
Purpose
Called to get damage scale for a hitgroup
When Called
When calculating damage to a player
Parameters
hitgroup(number): The hitgroup that was hitdmgInfo(CTakeDamageInfo): The damage infodamageScale(number): The current damage scale
Returns
- number - The modified damage scale
Realm
Server
Example Usage
Low Complexity:
-- Simple: Return default scale
hook.Add("GetDamageScale", "MyAddon", function(hitgroup, dmgInfo, damageScale)
return damageScale
end)
Medium Complexity:
-- Medium: Hitgroup-specific scaling
hook.Add("GetDamageScale", "HitgroupScaling", function(hitgroup, dmgInfo, damageScale)
if hitgroup == HITGROUP_HEAD then
return damageScale * 2
elseif hitgroup == HITGROUP_LEFTLEG or hitgroup == HITGROUP_RIGHTLEG then
return damageScale * 0.5
end
return damageScale
end)
High Complexity:
-- High: Complex damage scaling system
hook.Add("GetDamageScale", "AdvancedDamageScale", function(hitgroup, dmgInfo, damageScale)
local attacker = dmgInfo:GetAttacker()
local victim = dmgInfo:GetInflictor()
-- Hitgroup scaling
if hitgroup == HITGROUP_HEAD then
damageScale = damageScale * 2
elseif hitgroup == HITGROUP_CHEST then
damageScale = damageScale * 1.2
elseif hitgroup == HITGROUP_LEFTLEG or hitgroup == HITGROUP_RIGHTLEG then
damageScale = damageScale * 0.5
end
-- Armor scaling
if IsValid(victim) and victim:IsPlayer() then
local char = victim:getChar()
if char then
local armor = char:getData("armor", 0)
if armor > 0 then
damageScale = damageScale * (1 - (armor / 200))
end
end
end
return damageScale
end)
GetDefaultCharDesc
Purpose
Called to get default character description
When Called
When creating a new character
Parameters
client(Player): The player creating the characterfactionIndex(number): The faction indexcontext(table): Additional context data
Returns
- string - The default description
Realm
Server
Example Usage
Low Complexity:
-- Simple: Return generic description
hook.Add("GetDefaultCharDesc", "MyAddon", function(client, factionIndex, context)
return "A new character"
end)
Medium Complexity:
-- Medium: Faction-specific descriptions
hook.Add("GetDefaultCharDesc", "FactionDescriptions", function(client, factionIndex, context)
local factionDescs = {
[1] = "A citizen of the city",
[2] = "A police officer",
[3] = "A medical professional"
}
return factionDescs[factionIndex] or "A new character"
end)
High Complexity:
-- High: Complex description generation
hook.Add("GetDefaultCharDesc", "AdvancedCharDesc", function(client, factionIndex, context)
local faction = lia.faction.indices[factionIndex]
if not faction then return "A new character" end
-- Generate description based on faction and context
local desc = "A " .. (faction.name or "character")
if context and context.model then
local gender = hook.Run("GetModelGender", context.model) or "person"
desc = "A " .. gender .. " working as a " .. (faction.name or "character")
end
return desc
end)
GetDefaultCharName
Purpose
Called to get default character name
When Called
When creating a new character
Parameters
client(Player): The player creating the characterfactionIndex(number): The faction indexcontext(table): Additional context data
Returns
- string - The default name
Realm
Server
Example Usage
Low Complexity:
-- Simple: Return generic name
hook.Add("GetDefaultCharName", "MyAddon", function(client, factionIndex, context)
return "John Doe"
end)
Medium Complexity:
-- Medium: Faction-specific names
hook.Add("GetDefaultCharName", "FactionNames", function(client, factionIndex, context)
local factionNames = {
[1] = "Citizen #" .. math.random(1000, 9999),
[2] = "Officer " .. client:Name(),
[3] = "Dr. " .. client:Name()
}
return factionNames[factionIndex] or "John Doe"
end)
High Complexity:
-- High: Complex name generation
hook.Add("GetDefaultCharName", "AdvancedCharName", function(client, factionIndex, context)
local faction = lia.faction.indices[factionIndex]
if not faction then return "John Doe" end
-- Generate name based on faction
local firstName = client:Name()
local lastName = "Doe"
if faction.uniqueID == "police" then
return "Officer " .. firstName .. " " .. lastName
elseif faction.uniqueID == "medic" then
return "Dr. " .. firstName .. " " .. lastName
elseif faction.uniqueID == "citizen" then
return firstName .. " " .. lastName
end
return firstName .. " " .. lastName
end)
GetDefaultInventorySize
Purpose
Called to get default inventory size
When Called
When creating a character's inventory
Parameters
client(Player): The playerchar(Character): The character
Returns
- table - {width, height} inventory size
Realm
Server
Example Usage
Low Complexity:
-- Simple: Return default size
hook.Add("GetDefaultInventorySize", "MyAddon", function(client, char)
return {6, 4}
end)
Medium Complexity:
-- Medium: Faction-based sizes
hook.Add("GetDefaultInventorySize", "FactionInventorySize", function(client, char)
local faction = char:getFaction()
if faction == "police" then
return {8, 6}
elseif faction == "medic" then
return {7, 5}
end
return {6, 4}
end)
High Complexity:
-- High: Complex inventory sizing
hook.Add("GetDefaultInventorySize", "AdvancedInventorySize", function(client, char)
local baseSize = {6, 4}
-- Faction bonuses
local faction = char:getFaction()
if faction == "police" then
baseSize = {8, 6}
elseif faction == "medic" then
baseSize = {7, 5}
end
-- Donator bonus
if client:getNetVar("donator", false) then
baseSize[1] = baseSize[1] + 2
baseSize[2] = baseSize[2] + 1
end
-- Level bonus
local level = char:getData("level", 1)
if level >= 10 then
baseSize[1] = baseSize[1] + 1
end
if level >= 20 then
baseSize[2] = baseSize[2] + 1
end
return baseSize
end)
GetDefaultInventoryType
Purpose
Called to get default inventory type
When Called
When creating a character's inventory
Parameters
character(Character): The character
Returns
- string - The inventory type
Realm
Server
Example Usage
Low Complexity:
-- Simple: Return default type
hook.Add("GetDefaultInventoryType", "MyAddon", function(character)
return "grid"
end)
Medium Complexity:
-- Medium: Faction-based types
hook.Add("GetDefaultInventoryType", "FactionInventoryType", function(character)
local faction = character:getFaction()
if faction == "police" then
return "police_grid"
elseif faction == "medic" then
return "medical_grid"
end
return "grid"
end)
High Complexity:
-- High: Complex inventory type system
hook.Add("GetDefaultInventoryType", "AdvancedInventoryType", function(character)
local faction = character:getFaction()
local level = character:getData("level", 1)
-- Faction-specific types
if faction == "police" then
if level >= 10 then
return "police_advanced_grid"
end
return "police_grid"
elseif faction == "medic" then
if level >= 10 then
return "medical_advanced_grid"
end
return "medical_grid"
end
-- Default type with level progression
if level >= 20 then
return "advanced_grid"
end
return "grid"
end)
GetEntitySaveData
Purpose
Called to get entity save data
When Called
When saving entity data to the database
Parameters
ent(Entity): The entity to get save data for
Returns
- table - The save data for the entity
Realm
Server
Example Usage
Low Complexity:
-- Simple: Return basic save data
hook.Add("GetEntitySaveData", "MyAddon", function(ent)
return {
pos = ent:GetPos(),
ang = ent:GetAngles(),
model = ent:GetModel()
}
end)
Medium Complexity:
-- Medium: Add custom entity data
hook.Add("GetEntitySaveData", "EntityData", function(ent)
local data = {
pos = ent:GetPos(),
ang = ent:GetAngles(),
model = ent:GetModel(),
class = ent:GetClass()
}
-- Add custom data
if ent.customData then
data.customData = ent.customData
end
return data
end)
High Complexity:
-- High: Complex entity save data system
hook.Add("GetEntitySaveData", "AdvancedEntitySave", function(ent)
local data = {
pos = ent:GetPos(),
ang = ent:GetAngles(),
model = ent:GetModel(),
class = ent:GetClass(),
health = ent:Health(),
maxHealth = ent:GetMaxHealth()
}
-- Add networked variables
local netVars = ent:getNetVar("saveData", {})
for key, value in pairs(netVars) do
data[key] = value
end
-- Add custom entity data
if ent.customData then
data.customData = ent.customData
end
-- Add owner information
local owner = ent:getNetVar("owner")
if owner then
data.owner = owner
end
-- Add creation timestamp
data.createdAt = ent:getNetVar("createdAt", os.time())
return data
end)
GetHandsAttackSpeed
Purpose
Called to get hands attack speed
When Called
When calculating unarmed attack speed for a player
Parameters
client(Player): The player whose attack speed is being calculated
Returns
- number - The attack speed multiplier
Realm
Server
Example Usage
Low Complexity:
-- Simple: Return default attack speed
hook.Add("GetHandsAttackSpeed", "MyAddon", function(client)
return 1.0
end)
Medium Complexity:
-- Medium: Base speed on dexterity
hook.Add("GetHandsAttackSpeed", "DexteritySpeed", function(client)
local char = client:getChar()
if not char then return 1.0 end
local dex = char:getAttrib("dex", 0)
return 1.0 + (dex * 0.1)
end)
High Complexity:
-- High: Complex attack speed system
hook.Add("GetHandsAttackSpeed", "AdvancedAttackSpeed", function(client)
local char = client:getChar()
if not char then return 1.0 end
local baseSpeed = 1.0
-- Dexterity bonus
local dex = char:getAttrib("dex", 0)
local dexBonus = dex * 0.1
-- Level bonus
local level = char:getData("level", 1)
local levelBonus = level * 0.05
-- Faction bonus
local faction = char:getFaction()
local factionBonuses = {
["athlete"] = 0.3,
["police"] = 0.1,
["citizen"] = 0.0
}
local factionBonus = factionBonuses[faction] or 0.0
-- Equipment bonus
local equipmentBonus = 0.0
local inventory = char:getInv()
if inventory then
for _, item in pairs(inventory:getItems()) do
if item:getData("equipped", false) and item.uniqueID == "boxing_gloves" then
equipmentBonus = equipmentBonus + 0.2
end
end
end
return baseSpeed + dexBonus + levelBonus + factionBonus + equipmentBonus
end)
GetItemDropModel
Purpose
Called to get item drop model
When Called
When determining the model for a dropped item
Parameters
itemTable(table): The item tableself(Item): The item instance
Returns
- string - The model path for the dropped item
Realm
Server
Example Usage
Low Complexity:
-- Simple: Return default model
hook.Add("GetItemDropModel", "MyAddon", function(itemTable, self)
return itemTable.model or "models/props_junk/cardboard_box004a.mdl"
end)
Medium Complexity:
-- Medium: Use item-specific models
hook.Add("GetItemDropModel", "ItemModels", function(itemTable, self)
local models = {
["weapon_pistol"] = "models/weapons/w_pistol.mdl",
["medkit"] = "models/items/medkit.mdl",
["money"] = "models/props/cs_assault/money.mdl"
}
return models[itemTable.uniqueID] or itemTable.model or "models/props_junk/cardboard_box004a.mdl"
end)
High Complexity:
-- High: Complex item model system
hook.Add("GetItemDropModel", "AdvancedItemModels", function(itemTable, self)
-- Check for custom model in item data
local customModel = self:getData("dropModel")
if customModel then
return customModel
end
-- Check for faction-specific models
local char = self:getOwner()
if char then
local faction = char:getFaction()
local factionModels = {
["police"] = {
["weapon_pistol"] = "models/weapons/w_pistol_police.mdl"
},
["medic"] = {
["medkit"] = "models/items/medkit_advanced.mdl"
}
}
local factionModel = factionModels[faction] and factionModels[faction][itemTable.uniqueID]
if factionModel then
return factionModel
end
end
-- Check for quality-based models
local quality = self:getData("quality", "common")
local qualityModels = {
["rare"] = itemTable.rareModel,
["epic"] = itemTable.epicModel,
["legendary"] = itemTable.legendaryModel
}
local qualityModel = qualityModels[quality]
if qualityModel then
return qualityModel
end
-- Return default model
return itemTable.model or "models/props_junk/cardboard_box004a.mdl"
end)
GetItemStackKey
Purpose
Called to get item stack key
When Called
When determining how items should be stacked together
Parameters
item(Item): The item to get stack key for
Returns
- string - The stack key for grouping items
Realm
Server
Example Usage
Low Complexity:
-- Simple: Use item ID as stack key
hook.Add("GetItemStackKey", "MyAddon", function(item)
return item.uniqueID
end)
Medium Complexity:
-- Medium: Include item data in stack key
hook.Add("GetItemStackKey", "ItemDataStacking", function(item)
local key = item.uniqueID
-- Include quality in stack key
local quality = item:getData("quality", "common")
if quality ~= "common" then
key = key .. "_" .. quality
end
return key
end)
High Complexity:
-- High: Complex item stacking system
hook.Add("GetItemStackKey", "AdvancedItemStacking", function(item)
local key = item.uniqueID
-- Include quality in stack key
local quality = item:getData("quality", "common")
if quality ~= "common" then
key = key .. "_" .. quality
end
-- Include durability for stackable items
local durability = item:getData("durability")
if durability then
local durabilityTier = math.floor(durability / 20) * 20
key = key .. "_dur" .. durabilityTier
end
-- Include enchantments
local enchantments = item:getData("enchantments", {})
if #enchantments > 0 then
table.sort(enchantments)
key = key .. "_ench" .. table.concat(enchantments, "_")
end
-- Include custom data
local customData = item:getData("stackData")
if customData then
key = key .. "_" .. customData
end
return key
end)
GetItemStacks
Purpose
Called to get item stacks in an inventory
When Called
When retrieving stacked items from an inventory
Parameters
inventory(Inventory): The inventory to get stacks from
Returns
- table - Table of item stacks
Realm
Server
Example Usage
Low Complexity:
-- Simple: Return empty stacks
hook.Add("GetItemStacks", "MyAddon", function(inventory)
return {}
end)
Medium Complexity:
-- Medium: Group items by ID
hook.Add("GetItemStacks", "BasicStacking", function(inventory)
local stacks = {}
local items = inventory:getItems()
for _, item in pairs(items) do
local key = item.uniqueID
if not stacks[key] then
stacks[key] = {}
end
table.insert(stacks[key], item)
end
return stacks
end)
High Complexity:
-- High: Complex item stacking system
hook.Add("GetItemStacks", "AdvancedStacking", function(inventory)
local stacks = {}
local items = inventory:getItems()
for _, item in pairs(items) do
-- Get stack key using the hook
local key = hook.Run("GetItemStackKey", item) or item.uniqueID
if not stacks[key] then
stacks[key] = {
items = {},
count = 0,
totalWeight = 0,
stackData = {
uniqueID = item.uniqueID,
name = item.name,
model = item.model
}
}
end
table.insert(stacks[key].items, item)
stacks[key].count = stacks[key].count + 1
stacks[key].totalWeight = stacks[key].totalWeight + item:getWeight()
end
-- Sort stacks by count
local sortedStacks = {}
for key, stack in pairs(stacks) do
table.insert(sortedStacks, {key = key, data = stack})
end
table.sort(sortedStacks, function(a, b)
return a.data.count > b.data.count
end)
return sortedStacks
end)
GetMaxPlayerChar
Purpose
Called to get maximum character count for a player
When Called
When checking how many characters a player can have
Parameters
client(Player): The player to check character limit for
Returns
- number - The maximum number of characters allowed
Realm
Server
Example Usage
Low Complexity:
-- Simple: Return default limit
hook.Add("GetMaxPlayerChar", "MyAddon", function(client)
return 3
end)
Medium Complexity:
-- Medium: Different limits for different players
hook.Add("GetMaxPlayerChar", "PlayerLimits", function(client)
if client:IsAdmin() then
return 10
else
return 3
end
end)
High Complexity:
-- High: Complex character limit system
hook.Add("GetMaxPlayerChar", "AdvancedCharLimits", function(client)
local baseLimit = 3
-- Admin bonus
if client:IsSuperAdmin() then
baseLimit = baseLimit + 5
elseif client:IsAdmin() then
baseLimit = baseLimit + 2
end
-- Donator bonus
local char = client:getChar()
if char then
local donatorLevel = char:getData("donatorLevel", 0)
baseLimit = baseLimit + donatorLevel
end
-- Play time bonus
local playTime = client:GetTotalPlayTime()
local hours = playTime / 3600
if hours >= 100 then
baseLimit = baseLimit + 1
elseif hours >= 500 then
baseLimit = baseLimit + 2
elseif hours >= 1000 then
baseLimit = baseLimit + 3
end
-- Faction bonus
if char then
local faction = char:getFaction()
local factionBonuses = {
["police"] = 1,
["medic"] = 1,
["citizen"] = 0
}
baseLimit = baseLimit + (factionBonuses[faction] or 0)
end
return math.max(1, baseLimit)
end)
GetMaxSkillPoints
Purpose
Called to get maximum skill points for a player
When Called
When calculating skill point limits
Parameters
client(Player): The player
Returns
- number - The maximum skill points
Realm
Shared
Example Usage
Low Complexity:
-- Simple: Return default max
hook.Add("GetMaxSkillPoints", "MyAddon", function(client)
return 100
end)
Medium Complexity:
-- Medium: Level-based skill points
hook.Add("GetMaxSkillPoints", "LevelSkillPoints", function(client)
local char = client:getChar()
if not char then return 100 end
local level = char:getData("level", 1)
return 50 + (level * 5)
end)
High Complexity:
-- High: Complex skill point system
hook.Add("GetMaxSkillPoints", "AdvancedSkillPoints", function(client)
local char = client:getChar()
if not char then return 100 end
-- Base points
local basePoints = 50
-- Level bonus
local level = char:getData("level", 1)
basePoints = basePoints + (level * 5)
-- Faction bonus
local faction = char:getFaction()
if faction == "warrior" then
basePoints = basePoints + 20
elseif faction == "mage" then
basePoints = basePoints + 30
end
-- Donator bonus
if client:getNetVar("donator", false) then
basePoints = basePoints + 25
end
return basePoints
end)
GetMaxStartingAttributePoints
Purpose
Called to get maximum starting attribute points
When Called
During character creation
Parameters
client(Player): The player creating the charactercount(number): The current count
Returns
- number - The maximum starting attribute points
Realm
Server
Example Usage
Low Complexity:
-- Simple: Return default count
hook.Add("GetMaxStartingAttributePoints", "MyAddon", function(client, count)
return 10
end)
Medium Complexity:
-- Medium: Playtime-based points
hook.Add("GetMaxStartingAttributePoints", "PlaytimePoints", function(client, count)
local playTime = client:GetUTimeTotalTime()
if playTime > 36000 then -- 10 hours
return 15
end
return 10
end)
High Complexity:
-- High: Complex starting points system
hook.Add("GetMaxStartingAttributePoints", "AdvancedStartingPoints", function(client, count)
local basePoints = 10
-- Playtime bonus
local playTime = client:GetUTimeTotalTime()
if playTime > 36000 then
basePoints = basePoints + 5
end
-- Donator bonus
if client:getNetVar("donator", false) then
basePoints = basePoints + 3
end
-- Achievement bonus
local achievements = client:getNetVar("achievements", {})
if #achievements >= 10 then
basePoints = basePoints + 2
end
return basePoints
end)
GetMoneyModel
Purpose
Called to get money model
When Called
When spawning money entity
Parameters
amount(number): The money amount
Returns
- string - The model path
Realm
Server
Example Usage
Low Complexity:
-- Simple: Return default model
hook.Add("GetMoneyModel", "MyAddon", function(amount)
return "models/props_lab/box01a.mdl"
end)
Medium Complexity:
-- Medium: Amount-based models
hook.Add("GetMoneyModel", "AmountBasedModels", function(amount)
if amount >= 1000 then
return "models/props/cs_office/briefcase.mdl"
elseif amount >= 100 then
return "models/props_lab/box01a.mdl"
end
return "models/props_junk/cardboard_box001a.mdl"
end)
High Complexity:
-- High: Complex money model system
hook.Add("GetMoneyModel", "AdvancedMoneyModels", function(amount)
-- Different models based on amount tiers
if amount >= 10000 then
return "models/props/cs_office/briefcase.mdl"
elseif amount >= 5000 then
return "models/props_c17/suitcase001a.mdl"
elseif amount >= 1000 then
return "models/props_lab/box01a.mdl"
elseif amount >= 100 then
return "models/props_junk/cardboard_box002a.mdl"
else
return "models/props_junk/cardboard_box001a.mdl"
end
end)
GetOOCDelay
Purpose
Called to get OOC chat delay
When Called
When checking OOC chat cooldown
Parameters
speaker(Player): The player speaking
Returns
- number - The delay in seconds
Realm
Server
Example Usage
Low Complexity:
Medium Complexity:
-- Medium: Admin bypass
hook.Add("GetOOCDelay", "AdminOOCBypass", function(speaker)
if speaker:IsAdmin() then
return 0
end
return 3
end)
High Complexity:
-- High: Complex OOC delay system
hook.Add("GetOOCDelay", "AdvancedOOCDelay", function(speaker)
-- Admins have no delay
if speaker:IsAdmin() then
return 0
end
-- Donators have reduced delay
if speaker:getNetVar("donator", false) then
return 1
end
-- New players have longer delay
local playTime = speaker:GetUTimeTotalTime()
if playTime < 3600 then -- Less than 1 hour
return 5
end
return 3
end)
GetPlayTime
Purpose
Called to get player playtime
When Called
When retrieving player playtime
Parameters
client(Player): The player
Returns
- number - The playtime in seconds
Realm
Server
Example Usage
Low Complexity:
-- Simple: Return UTime playtime
hook.Add("GetPlayTime", "MyAddon", function(client)
return client:GetUTimeTotalTime()
end)
Medium Complexity:
-- Medium: Add session time
hook.Add("GetPlayTime", "PlayTimeWithSession", function(client)
local totalTime = client:GetUTimeTotalTime()
local sessionTime = client:GetUTimeSessionTime()
return totalTime + sessionTime
end)
High Complexity:
-- High: Complex playtime tracking
hook.Add("GetPlayTime", "AdvancedPlayTime", function(client)
local char = client:getChar()
if not char then
return client:GetUTimeTotalTime()
end
-- Get character-specific playtime
local charPlayTime = char:getData("playTime", 0)
-- Add current session time
local sessionStart = char:getData("sessionStart", os.time())
local sessionTime = os.time() - sessionStart
return charPlayTime + sessionTime
end)
GetPlayerDeathSound
Purpose
Called to get player death sound
When Called
When a player dies
Parameters
client(Player): The dying playerisFemale(boolean): Whether the player is female
Returns
- string - The death sound path
Realm
Server
Example Usage
Low Complexity:
-- Simple: Return default sound
hook.Add("GetPlayerDeathSound", "MyAddon", function(client, isFemale)
return "vo/npc/male01/pain09.wav"
end)
Medium Complexity:
-- Medium: Gender-based sounds
hook.Add("GetPlayerDeathSound", "GenderDeathSounds", function(client, isFemale)
if isFemale then
return "vo/npc/female01/pain09.wav"
end
return "vo/npc/male01/pain09.wav"
end)
High Complexity:
-- High: Complex death sound system
hook.Add("GetPlayerDeathSound", "AdvancedDeathSounds", function(client, isFemale)
local char = client:getChar()
if not char then
return isFemale and "vo/npc/female01/pain09.wav" or "vo/npc/male01/pain09.wav"
end
-- Faction-specific sounds
local faction = char:getFaction()
if faction == "combine" then
return "npc/combine_soldier/die" .. math.random(1, 3) .. ".wav"
elseif faction == "zombie" then
return "npc/zombie/zombie_die" .. math.random(1, 3) .. ".wav"
end
-- Gender-based sounds
if isFemale then
return "vo/npc/female01/pain0" .. math.random(7, 9) .. ".wav"
end
return "vo/npc/male01/pain0" .. math.random(7, 9) .. ".wav"
end)
GetPlayerPainSound
Purpose
Called to get player pain sound
When Called
When a player takes damage
Parameters
client(Player): The player taking damagepaintype(number): The type of painisFemale(boolean): Whether the player is female
Returns
- string - The pain sound path
Realm
Server
Example Usage
Low Complexity:
-- Simple: Return default sound
hook.Add("GetPlayerPainSound", "MyAddon", function(client, paintype, isFemale)
return "vo/npc/male01/pain01.wav"
end)
Medium Complexity:
-- Medium: Gender-based pain sounds
hook.Add("GetPlayerPainSound", "GenderPainSounds", function(client, paintype, isFemale)
if isFemale then
return "vo/npc/female01/pain0" .. math.random(1, 6) .. ".wav"
end
return "vo/npc/male01/pain0" .. math.random(1, 6) .. ".wav"
end)
High Complexity:
-- High: Complex pain sound system
hook.Add("GetPlayerPainSound", "AdvancedPainSounds", function(client, paintype, isFemale)
local char = client:getChar()
if not char then
return isFemale and "vo/npc/female01/pain01.wav" or "vo/npc/male01/pain01.wav"
end
-- Faction-specific sounds
local faction = char:getFaction()
if faction == "combine" then
return "npc/combine_soldier/pain" .. math.random(1, 3) .. ".wav"
elseif faction == "zombie" then
return "npc/zombie/zombie_pain" .. math.random(1, 6) .. ".wav"
end
-- Pain type-based sounds
local soundNum = 1
if paintype == 1 then -- Light damage
soundNum = math.random(1, 3)
elseif paintype == 2 then -- Medium damage
soundNum = math.random(4, 6)
else -- Heavy damage
soundNum = math.random(7, 9)
end
-- Gender-based sounds
if isFemale then
return "vo/npc/female01/pain0" .. soundNum .. ".wav"
end
return "vo/npc/male01/pain0" .. soundNum .. ".wav"
end)
GetPlayerPunchDamage
Purpose
Called to get player punch damage
When Called
When calculating unarmed punch damage for a player
Parameters
client(Player): The player whose punch damage is being calculated
Returns
- number - The punch damage amount
Realm
Server
Example Usage
Low Complexity:
-- Simple: Return default punch damage
hook.Add("GetPlayerPunchDamage", "MyAddon", function(client)
return 10
end)
Medium Complexity:
-- Medium: Base damage on strength
hook.Add("GetPlayerPunchDamage", "StrengthDamage", function(client)
local char = client:getChar()
if not char then return 10 end
local str = char:getAttrib("str", 0)
return 10 + (str * 2)
end)
High Complexity:
-- High: Complex punch damage system
hook.Add("GetPlayerPunchDamage", "AdvancedPunchDamage", function(client)
local char = client:getChar()
if not char then return 10 end
local baseDamage = 10
-- Strength bonus
local str = char:getAttrib("str", 0)
local strBonus = str * 2
-- Level bonus
local level = char:getData("level", 1)
local levelBonus = level * 0.5
-- Faction bonus
local faction = char:getFaction()
local factionBonuses = {
["athlete"] = 5,
["police"] = 2,
["citizen"] = 0
}
local factionBonus = factionBonuses[faction] or 0
-- Equipment bonus
local equipmentBonus = 0
local inventory = char:getInv()
if inventory then
for _, item in pairs(inventory:getItems()) do
if item:getData("equipped", false) then
if item.uniqueID == "boxing_gloves" then
equipmentBonus = equipmentBonus + 5
elseif item.uniqueID == "brass_knuckles" then
equipmentBonus = equipmentBonus + 8
end
end
end
end
return baseDamage + strBonus + levelBonus + factionBonus + equipmentBonus
end)
GetPlayerPunchRagdollTime
Purpose
Called to get player punch ragdoll time
When Called
When calculating how long a player stays ragdolled from a punch
Parameters
client(Player): The player being punched
Returns
- number - The ragdoll time in seconds
Realm
Server
Example Usage
Low Complexity:
-- Simple: Return default ragdoll time
hook.Add("GetPlayerPunchRagdollTime", "MyAddon", function(client)
return 3
end)
Medium Complexity:
-- Medium: Base time on constitution
hook.Add("GetPlayerPunchRagdollTime", "ConstitutionRagdoll", function(client)
local char = client:getChar()
if not char then return 3 end
local con = char:getAttrib("con", 0)
return math.max(1, 3 - (con * 0.1))
end)
High Complexity:
-- High: Complex ragdoll time system
hook.Add("GetPlayerPunchRagdollTime", "AdvancedRagdollTime", function(client)
local char = client:getChar()
if not char then return 3 end
local baseTime = 3
-- Constitution reduces ragdoll time
local con = char:getAttrib("con", 0)
local conReduction = con * 0.1
-- Level reduces ragdoll time
local level = char:getData("level", 1)
local levelReduction = level * 0.05
-- Faction affects ragdoll time
local faction = char:getFaction()
local factionModifiers = {
["athlete"] = -0.5,
["police"] = -0.2,
["citizen"] = 0,
["elderly"] = 0.5
}
local factionModifier = factionModifiers[faction] or 0
-- Equipment affects ragdoll time
local equipmentModifier = 0
local inventory = char:getInv()
if inventory then
for _, item in pairs(inventory:getItems()) do
if item:getData("equipped", false) then
if item.uniqueID == "armor_vest" then
equipmentModifier = equipmentModifier + 0.3
elseif item.uniqueID == "helmet" then
equipmentModifier = equipmentModifier + 0.2
end
end
end
end
return math.max(0.5, baseTime - conReduction - levelReduction + factionModifier + equipmentModifier)
end)
GetPriceOverride
Purpose
Called to get price override for items
When Called
When calculating item prices in vendors or trading
Parameters
self(Entity): The vendor or trading entityuniqueID(string): The item unique IDprice(number): The base priceisSellingToVendor(boolean): Whether the player is selling to vendor
Returns
- number - The overridden price
Realm
Server
Example Usage
Low Complexity:
-- Simple: Return original price
hook.Add("GetPriceOverride", "MyAddon", function(self, uniqueID, price, isSellingToVendor)
return price
end)
Medium Complexity:
-- Medium: Apply faction discounts
hook.Add("GetPriceOverride", "FactionDiscounts", function(self, uniqueID, price, isSellingToVendor)
local client = self:getNetVar("client")
if not client then return price end
local char = client:getChar()
if not char then return price end
local faction = char:getFaction()
if faction == "police" and uniqueID == "weapon_pistol" then
return price * 0.8 -- 20% discount
end
return price
end)
High Complexity:
-- High: Complex price override system
hook.Add("GetPriceOverride", "AdvancedPriceOverride", function(self, uniqueID, price, isSellingToVendor)
local client = self:getNetVar("client")
if not client then return price end
local char = client:getChar()
if not char then return price end
local finalPrice = price
-- Faction discounts
local faction = char:getFaction()
local factionDiscounts = {
["police"] = {
["weapon_pistol"] = 0.8,
["handcuffs"] = 0.5
},
["medic"] = {
["medkit"] = 0.7,
["bandage"] = 0.6
}
}
local discounts = factionDiscounts[faction]
if discounts and discounts[uniqueID] then
finalPrice = finalPrice * discounts[uniqueID]
end
-- Level discounts
local level = char:getData("level", 1)
if level >= 10 then
finalPrice = finalPrice * 0.95 -- 5% discount
elseif level >= 20 then
finalPrice = finalPrice * 0.9 -- 10% discount
end
-- Donator discounts
local donatorLevel = char:getData("donatorLevel", 0)
if donatorLevel > 0 then
finalPrice = finalPrice * (1 - (donatorLevel * 0.1))
end
-- Selling to vendor penalty
if isSellingToVendor then
finalPrice = finalPrice * 0.5 -- 50% of original price when selling
end
return math.max(1, finalPrice)
end)
GetRagdollTime
Purpose
Called to get ragdoll time
When Called
When calculating how long an entity stays ragdolled
Parameters
self(Entity): The ragdoll entitytime(number): The base ragdoll time
Returns
- number - The modified ragdoll time
Realm
Server
Example Usage
Low Complexity:
-- Simple: Return original time
hook.Add("GetRagdollTime", "MyAddon", function(self, time)
return time
end)
Medium Complexity:
-- Medium: Extend ragdoll time for certain entities
hook.Add("GetRagdollTime", "ExtendedRagdoll", function(self, time)
if self:GetClass() == "prop_ragdoll" then
return time * 1.5
end
return time
end)
High Complexity:
-- High: Complex ragdoll time system
hook.Add("GetRagdollTime", "AdvancedRagdollTime", function(self, time)
local finalTime = time
-- Check if it's a player ragdoll
local owner = self:getNetVar("owner")
if owner then
local ply = player.GetBySteamID(owner)
if IsValid(ply) then
local char = ply:getChar()
if char then
-- Constitution affects ragdoll time
local con = char:getAttrib("con", 0)
finalTime = finalTime - (con * 0.1)
-- Level affects ragdoll time
local level = char:getData("level", 1)
finalTime = finalTime - (level * 0.05)
-- Faction affects ragdoll time
local faction = char:getFaction()
local factionModifiers = {
["athlete"] = -0.5,
["police"] = -0.2,
["citizen"] = 0,
["elderly"] = 0.5
}
local factionModifier = factionModifiers[faction] or 0
finalTime = finalTime + factionModifier
end
end
end
-- Weather affects ragdoll time
if GetConVar("sv_weather"):GetBool() then
finalTime = finalTime * 1.2
end
return math.max(0.5, finalTime)
end)
GetSalaryAmount
Purpose
Called to get salary amount for a player
When Called
When calculating salary payment for a player
Parameters
client(Player): The player receiving salaryfaction(string): The player's factionclass(string): The player's class
Returns
- number - The salary amount
Realm
Server
Example Usage
Low Complexity:
-- Simple: Return base salary
hook.Add("GetSalaryAmount", "MyAddon", function(client, faction, class)
return 100
end)
Medium Complexity:
-- Medium: Different salaries by faction
hook.Add("GetSalaryAmount", "FactionSalaries", function(client, faction, class)
local salaries = {
["police"] = 200,
["medic"] = 150,
["citizen"] = 50
}
return salaries[faction] or 50
end)
High Complexity:
-- High: Complex salary system
hook.Add("GetSalaryAmount", "AdvancedSalary", function(client, faction, class)
local char = client:getChar()
if not char then return 0 end
local baseSalary = 50
-- Faction base salaries
local factionSalaries = {
["police"] = 200,
["medic"] = 150,
["citizen"] = 50,
["criminal"] = 0
}
baseSalary = factionSalaries[faction] or 50
-- Class bonuses
local classBonuses = {
["officer"] = 50,
["sergeant"] = 100,
["lieutenant"] = 150,
["nurse"] = 25,
["doctor"] = 75
}
local classBonus = classBonuses[class] or 0
-- Level bonus
local level = char:getData("level", 1)
local levelBonus = level * 10
-- Performance bonus
local performance = char:getData("performance", 0)
local performanceBonus = performance * 5
-- Donator bonus
local donatorLevel = char:getData("donatorLevel", 0)
local donatorBonus = donatorLevel * 25
return baseSalary + classBonus + levelBonus + performanceBonus + donatorBonus
end)
GetTicketsByRequester
Purpose
Called to get tickets by requester
When Called
When retrieving tickets created by a specific player
Parameters
steamID(string): The Steam ID of the requester
Returns
- table - Table of tickets created by the requester
Realm
Server
Example Usage
Low Complexity:
-- Simple: Return empty tickets
hook.Add("GetTicketsByRequester", "MyAddon", function(steamID)
return {}
end)
Medium Complexity:
-- Medium: Load tickets from database
hook.Add("GetTicketsByRequester", "TicketLoading", function(steamID)
local tickets = lia.db.query("SELECT * FROM tickets WHERE requester = ?", steamID)
return tickets or {}
end)
High Complexity:
-- High: Complex ticket retrieval system
hook.Add("GetTicketsByRequester", "AdvancedTicketRetrieval", function(steamID)
-- Load tickets from database
local tickets = lia.db.query("SELECT * FROM tickets WHERE requester = ? ORDER BY created_at DESC", steamID)
if not tickets then return {} end
-- Process tickets
local processedTickets = {}
for _, ticket in ipairs(tickets) do
local processedTicket = {
id = ticket.id,
title = ticket.title,
description = ticket.description,
status = ticket.status,
priority = ticket.priority,
createdAt = ticket.created_at,
updatedAt = ticket.updated_at,
assignedTo = ticket.assigned_to
}
-- Add requester character info
local requesterChar = lia.char.getByID(ticket.requester)
if requesterChar then
processedTicket.requesterName = requesterChar:getName()
processedTicket.requesterFaction = requesterChar:getFaction()
end
-- Add assignee character info
if ticket.assigned_to then
local assigneeChar = lia.char.getByID(ticket.assigned_to)
if assigneeChar then
processedTicket.assigneeName = assigneeChar:getName()
end
end
table.insert(processedTickets, processedTicket)
end
return processedTickets
end)
GetVendorSaleScale
Purpose
Called to get vendor sale scale
When Called
When calculating the sale price multiplier for a vendor
Parameters
self(Entity): The vendor entity
Returns
- number - The sale scale multiplier
Realm
Server
Example Usage
Low Complexity:
-- Simple: Return default scale
hook.Add("GetVendorSaleScale", "MyAddon", function(self)
return 1.0
end)
Medium Complexity:
-- Medium: Different scales for different vendors
hook.Add("GetVendorSaleScale", "VendorScales", function(self)
local vendorType = self:getNetVar("vendorType", "general")
local scales = {
["weapon"] = 0.8,
["medical"] = 0.9,
["general"] = 1.0
}
return scales[vendorType] or 1.0
end)
High Complexity:
-- High: Complex vendor sale scale system
hook.Add("GetVendorSaleScale", "AdvancedVendorScale", function(self)
local baseScale = 1.0
-- Vendor type affects scale
local vendorType = self:getNetVar("vendorType", "general")
local typeScales = {
["weapon"] = 0.8,
["medical"] = 0.9,
["food"] = 1.1,
["general"] = 1.0
}
baseScale = typeScales[vendorType] or 1.0
-- Vendor level affects scale
local vendorLevel = self:getNetVar("level", 1)
local levelModifier = 1 + (vendorLevel * 0.1)
-- Vendor reputation affects scale
local reputation = self:getNetVar("reputation", 0)
local reputationModifier = 1 + (reputation * 0.05)
-- Time of day affects scale
local hour = tonumber(os.date("%H"))
local timeModifier = 1.0
if hour >= 6 and hour <= 18 then
timeModifier = 1.1 -- Daytime bonus
else
timeModifier = 0.9 -- Nighttime penalty
end
-- Server population affects scale
local playerCount = #player.GetAll()
local populationModifier = 1 + (playerCount * 0.01)
return baseScale * levelModifier * reputationModifier * timeModifier * populationModifier
end)
GetWarnings
Purpose
Called to get warnings for a character
When Called
When retrieving warnings for a specific character
Parameters
charID(number): The character ID to get warnings for
Returns
- table - Table of warnings for the character
Realm
Server
Example Usage
Low Complexity:
Medium Complexity:
-- Medium: Load warnings from database
hook.Add("GetWarnings", "WarningLoading", function(charID)
local warnings = lia.db.query("SELECT * FROM warnings WHERE char_id = ?", charID)
return warnings or {}
end)
High Complexity:
-- High: Complex warning retrieval system
hook.Add("GetWarnings", "AdvancedWarningRetrieval", function(charID)
-- Load warnings from database
local warnings = lia.db.query("SELECT * FROM warnings WHERE char_id = ? ORDER BY created_at DESC", charID)
if not warnings then return {} end
-- Process warnings
local processedWarnings = {}
for _, warning in ipairs(warnings) do
local processedWarning = {
id = warning.id,
charID = warning.char_id,
warned = warning.warned,
warnedSteamID = warning.warned_steamid,
message = warning.message,
warner = warning.warner,
warnerSteamID = warning.warner_steamid,
timestamp = warning.created_at,
severity = warning.severity or "medium"
}
-- Add character names
local warnedChar = lia.char.getByID(warning.char_id)
if warnedChar then
processedWarning.warnedName = warnedChar:getName()
end
local warnerChar = lia.char.getByID(warning.warner)
if warnerChar then
processedWarning.warnerName = warnerChar:getName()
end
table.insert(processedWarnings, processedWarning)
end
return processedWarnings
end)
GetWarningsByIssuer
Purpose
Called to get warnings by issuer
When Called
When retrieving warnings issued by a specific player
Parameters
steamID(string): The Steam ID of the issuer
Returns
- table - Table of warnings issued by the player
Realm
Server
Example Usage
Low Complexity:
-- Simple: Return empty warnings
hook.Add("GetWarningsByIssuer", "MyAddon", function(steamID)
return {}
end)
Medium Complexity:
-- Medium: Load warnings from database
hook.Add("GetWarningsByIssuer", "IssuerWarnings", function(steamID)
local warnings = lia.db.query("SELECT * FROM warnings WHERE warner_steamid = ?", steamID)
return warnings or {}
end)
High Complexity:
-- High: Complex warning retrieval by issuer
hook.Add("GetWarningsByIssuer", "AdvancedIssuerWarnings", function(steamID)
-- Load warnings from database
local warnings = lia.db.query("SELECT * FROM warnings WHERE warner_steamid = ? ORDER BY created_at DESC", steamID)
if not warnings then return {} end
-- Process warnings
local processedWarnings = {}
for _, warning in ipairs(warnings) do
local processedWarning = {
id = warning.id,
charID = warning.char_id,
warned = warning.warned,
warnedSteamID = warning.warned_steamid,
message = warning.message,
warner = warning.warner,
warnerSteamID = warning.warner_steamid,
timestamp = warning.created_at,
severity = warning.severity or "medium"
}
-- Add character names
local warnedChar = lia.char.getByID(warning.char_id)
if warnedChar then
processedWarning.warnedName = warnedChar:getName()
processedWarning.warnedFaction = warnedChar:getFaction()
end
-- Add issuer character info
local issuerChar = lia.char.getByID(warning.warner)
if issuerChar then
processedWarning.issuerName = issuerChar:getName()
processedWarning.issuerFaction = issuerChar:getFaction()
end
table.insert(processedWarnings, processedWarning)
end
-- Calculate issuer statistics
local stats = {
totalWarnings = #processedWarnings,
recentWarnings = 0,
severityCounts = {}
}
local oneWeekAgo = os.time() - (7 * 24 * 60 * 60)
for _, warning in ipairs(processedWarnings) do
if warning.timestamp > oneWeekAgo then
stats.recentWarnings = stats.recentWarnings + 1
end
stats.severityCounts[warning.severity] = (stats.severityCounts[warning.severity] or 0) + 1
end
return processedWarnings, stats
end)
HandleItemTransferRequest
Purpose
Called to handle item transfer requests
When Called
When a player requests to transfer an item
Parameters
client(Player): The player making the requestitemID(string): The ID of the item to transferx(number): The X position in the inventoryy(number): The Y position in the inventoryinvID(string): The destination inventory ID
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log transfer request
hook.Add("HandleItemTransferRequest", "MyAddon", function(client, itemID, x, y, invID)
print(client:Name() .. " wants to transfer " .. itemID)
end)
Medium Complexity:
-- Medium: Validate transfer request
hook.Add("HandleItemTransferRequest", "TransferValidation", function(client, itemID, x, y, invID)
local char = client:getChar()
if not char then return end
local item = lia.item.instance(itemID)
if not item then
client:ChatPrint("Invalid item")
return
end
-- Check if player owns the item
local inventory = char:getInv()
if not inventory:hasItem(item) then
client:ChatPrint("You don't own this item")
return
end
end)
High Complexity:
-- High: Complex item transfer system
hook.Add("HandleItemTransferRequest", "AdvancedItemTransfer", function(client, itemID, x, y, invID)
local char = client:getChar()
if not char then return end
-- Get source inventory
local sourceInventory = char:getInv()
if not sourceInventory then return end
-- Get destination inventory
local destInventory = lia.inventory.getByID(invID)
if not destInventory then
client:ChatPrint("Invalid destination inventory")
return
end
-- Get item
local item = lia.item.instance(itemID)
if not item then
client:ChatPrint("Invalid item")
return
end
-- Check if player owns the item
if not sourceInventory:hasItem(item) then
client:ChatPrint("You don't own this item")
return
end
-- Check transfer permissions
if not hook.Run("CanItemBeTransfered", item, sourceInventory, destInventory, client) then
return
end
-- Check destination space
if not destInventory:canFit(item, x, y) then
client:ChatPrint("Not enough space in destination inventory")
return
end
-- Perform transfer
sourceInventory:remove(item)
destInventory:add(item, x, y)
-- Log transfer
lia.log.add(client, "item_transfer", itemID, "Transferred to inventory " .. invID)
client:ChatPrint("Item transferred successfully")
end)
InitializeStorage
Purpose
Called to initialize storage
When Called
When a storage entity is being initialized
Parameters
entity(Entity): The storage entity
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log storage initialization
hook.Add("InitializeStorage", "MyAddon", function(entity)
print("Initializing storage: " .. entity:EntIndex())
end)
Medium Complexity:
-- Medium: Set up basic storage data
hook.Add("InitializeStorage", "StorageSetup", function(entity)
entity:setNetVar("storageType", "general")
entity:setNetVar("maxWeight", 100)
entity:setNetVar("maxItems", 50)
end)
High Complexity:
-- High: Complex storage initialization system
hook.Add("InitializeStorage", "AdvancedStorageInit", function(entity)
-- Set storage type
local storageType = entity:getNetVar("storageType", "general")
-- Configure based on storage type
local configs = {
["general"] = {maxWeight = 100, maxItems = 50, size = {w = 6, h = 4}},
["weapon"] = {maxWeight = 200, maxItems = 20, size = {w = 4, h = 5}},
["medical"] = {maxWeight = 50, maxItems = 30, size = {w = 5, h = 6}},
["food"] = {maxWeight = 30, maxItems = 40, size = {w = 8, h = 5}}
}
local config = configs[storageType] or configs["general"]
-- Set storage properties
entity:setNetVar("maxWeight", config.maxWeight)
entity:setNetVar("maxItems", config.maxItems)
entity:setNetVar("inventorySize", config.size)
-- Set access permissions
local owner = entity:getNetVar("owner")
if owner then
entity:setNetVar("accessList", {owner})
end
-- Initialize inventory
local inventory = lia.inventory.new(entity:EntIndex(), "storage")
if inventory then
inventory:setSize(config.size.w, config.size.h)
inventory:setData("maxWeight", config.maxWeight)
inventory:setData("storageType", storageType)
entity:setNetVar("inventoryID", inventory:getID())
end
-- Set creation timestamp
entity:setNetVar("createdAt", os.time())
print("Storage initialized: " .. entity:EntIndex() .. " (Type: " .. storageType .. ")")
end)
InventoryDeleted
Purpose
Called when an inventory is deleted
When Called
When an inventory is removed from the system
Parameters
instance(Inventory): The inventory being deleted
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log inventory deletion
hook.Add("InventoryDeleted", "MyAddon", function(instance)
print("Inventory deleted: " .. instance:getID())
end)
Medium Complexity:
-- Medium: Clean up inventory data
hook.Add("InventoryDeleted", "CleanupInventory", function(instance)
-- Remove from cache
lia.inventoryCache[instance:getID()] = nil
print("Inventory deleted and cleaned up: " .. instance:getID())
end)
High Complexity:
-- High: Complex inventory deletion handling
hook.Add("InventoryDeleted", "AdvancedInventoryDeletion", function(instance)
local invID = instance:getID()
-- Archive inventory data
lia.db.query("INSERT INTO inventory_archive SELECT * FROM inventories WHERE id = ?", invID)
-- Clean up related data
lia.db.query("DELETE FROM inventory_items WHERE invid = ?", invID)
lia.db.query("DELETE FROM inventory_logs WHERE invid = ?", invID)
-- Remove from cache
lia.inventoryCache[invID] = nil
-- Notify owner
local owner = instance:getOwner()
if IsValid(owner) then
owner:ChatPrint("Your inventory has been deleted")
end
-- Log deletion
print("Inventory deleted: " .. invID)
lia.log.add("Inventory " .. invID .. " was deleted", "inventory")
end)
InventoryItemAdded
Purpose
Called when an item is added to an inventory
When Called
When an item is placed into an inventory
Parameters
inventory(Inventory): The inventory receiving the itemitem(Item): The item being added
Returns
- None
Realm
Shared
Example Usage
Low Complexity:
-- Simple: Log item addition
hook.Add("InventoryItemAdded", "MyAddon", function(inventory, item)
print("Item added: " .. item.name)
end)
Medium Complexity:
-- Medium: Update inventory weight
hook.Add("InventoryItemAdded", "UpdateInventoryWeight", function(inventory, item)
local currentWeight = inventory:getData("weight", 0)
local itemWeight = item.weight or 1
inventory:setData("weight", currentWeight + itemWeight)
end)
High Complexity:
-- High: Complex item addition handling
hook.Add("InventoryItemAdded", "AdvancedItemAddition", function(inventory, item)
if SERVER then
-- Update inventory weight
local currentWeight = inventory:getData("weight", 0)
local itemWeight = item.weight or 1
inventory:setData("weight", currentWeight + itemWeight)
-- Log to database
lia.db.query("INSERT INTO inventory_logs (timestamp, invid, itemid, action) VALUES (?, ?, ?, ?)",
os.time(), inventory:getID(), item:getID(), "added")
-- Notify owner
local owner = inventory:getOwner()
if IsValid(owner) then
owner:ChatPrint("Added " .. item.name .. " to inventory")
end
-- Check for set bonuses
local items = inventory:getItems()
local armorPieces = 0
for _, invItem in pairs(items) do
if string.find(invItem.uniqueID, "armor_") then
armorPieces = armorPieces + 1
end
end
if armorPieces >= 3 and IsValid(owner) then
local char = owner:getChar()
if char then
char:setData("armorSetBonus", true)
owner:ChatPrint("Armor set bonus activated!")
end
end
end
end)
InventoryItemRemoved
Purpose
Called when an item is removed from an inventory
When Called
When an item is taken out of an inventory
Parameters
self(Item): The item being removedinstance(Inventory): The inventory the item is being removed frompreserveItem(boolean): Whether to preserve the item after removal
Returns
- None
Realm
Shared
Example Usage
Low Complexity:
-- Simple: Log item removal
hook.Add("InventoryItemRemoved", "MyAddon", function(self, instance, preserveItem)
print("Item removed: " .. self.name)
end)
Medium Complexity:
-- Medium: Update inventory weight
hook.Add("InventoryItemRemoved", "UpdateWeightOnRemove", function(self, instance, preserveItem)
local currentWeight = instance:getData("weight", 0)
local itemWeight = self.weight or 1
instance:setData("weight", math.max(0, currentWeight - itemWeight))
end)
High Complexity:
-- High: Complex item removal handling
hook.Add("InventoryItemRemoved", "AdvancedItemRemoval", function(self, instance, preserveItem)
if SERVER then
-- Update inventory weight
local currentWeight = instance:getData("weight", 0)
local itemWeight = self.weight or 1
instance:setData("weight", math.max(0, currentWeight - itemWeight))
-- Log to database
lia.db.query("INSERT INTO inventory_logs (timestamp, invid, itemid, action) VALUES (?, ?, ?, ?)",
os.time(), instance:getID(), self:getID(), "removed")
-- Notify owner
local owner = instance:getOwner()
if IsValid(owner) then
owner:ChatPrint("Removed " .. self.name .. " from inventory")
end
-- Check for set bonus removal
if string.find(self.uniqueID, "armor_") then
local items = instance:getItems()
local armorPieces = 0
for _, invItem in pairs(items) do
if string.find(invItem.uniqueID, "armor_") and invItem ~= self then
armorPieces = armorPieces + 1
end
end
if armorPieces < 3 and IsValid(owner) then
local char = owner:getChar()
if char and char:getData("armorSetBonus", false) then
char:setData("armorSetBonus", false)
owner:ChatPrint("Armor set bonus deactivated")
end
end
end
end
end)
IsSuitableForTrunk
Purpose
Called to check if an entity is suitable for trunk storage
When Called
When determining if an entity can be used as a trunk/storage
Parameters
entity(Entity): The entity being checked
Returns
- boolean - True if suitable, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: Only vehicles are suitable
hook.Add("IsSuitableForTrunk", "MyAddon", function(entity)
return entity:IsVehicle()
end)
Medium Complexity:
-- Medium: Specific entity classes
hook.Add("IsSuitableForTrunk", "TrunkEntityCheck", function(entity)
local suitableClasses = {
["prop_vehicle_jeep"] = true,
["prop_vehicle_airboat"] = true,
["prop_physics"] = true
}
return suitableClasses[entity:GetClass()] or false
end)
High Complexity:
-- High: Complex trunk suitability system
hook.Add("IsSuitableForTrunk", "AdvancedTrunkCheck", function(entity)
if not IsValid(entity) then return false end
-- Check entity class
local suitableClasses = {
["prop_vehicle_jeep"] = true,
["prop_vehicle_airboat"] = true,
["prop_physics"] = true
}
if not suitableClasses[entity:GetClass()] then
return false
end
-- Check if entity has trunk flag
if entity:getNetVar("hasTrunk", false) == false then
return false
end
-- Check entity size for props
if entity:GetClass() == "prop_physics" then
local mins, maxs = entity:GetCollisionBounds()
local volume = (maxs.x - mins.x) * (maxs.y - mins.y) * (maxs.z - mins.z)
if volume < 1000 then -- Too small
return false
end
end
-- Check if entity is locked
if entity:getNetVar("locked", false) then
return false
end
return true
end)
ItemCombine
Purpose
Called when items are combined
When Called
When a player attempts to combine two items
Parameters
client(Player): The player combining itemsitem(Item): The first itemtarget(Item): The second item being combined with
Returns
- boolean - True to allow, false to deny
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all combinations
hook.Add("ItemCombine", "MyAddon", function(client, item, target)
return true
end)
Medium Complexity:
-- Medium: Specific item combinations
hook.Add("ItemCombine", "ItemCombinations", function(client, item, target)
-- Allow combining weapon parts
if item.uniqueID == "weapon_part_a" and target.uniqueID == "weapon_part_b" then
-- Create combined weapon
local newItem = lia.item.instance("weapon_combined")
if newItem then
local char = client:getChar()
if char then
char:getInv():add(newItem)
item:remove()
target:remove()
client:ChatPrint("Items combined successfully!")
return true
end
end
end
return false
end)
High Complexity:
-- High: Complex item combination system
hook.Add("ItemCombine", "AdvancedItemCombine", function(client, item, target)
local char = client:getChar()
if not char then return false end
-- Define combination recipes
local recipes = {
{items = {"weapon_part_a", "weapon_part_b"}, result = "weapon_combined", skill = 5},
{items = {"metal_ore", "metal_ore"}, result = "metal_bar", skill = 3},
{items = {"herb_a", "herb_b"}, result = "potion_health", skill = 7}
}
-- Check each recipe
for _, recipe in ipairs(recipes) do
local hasItems = (table.HasValue(recipe.items, item.uniqueID) and table.HasValue(recipe.items, target.uniqueID))
if hasItems then
-- Check skill requirement
local craftingSkill = char:getData("craftingSkill", 0)
if craftingSkill < recipe.skill then
client:ChatPrint("You need crafting skill level " .. recipe.skill .. " to combine these items")
return false
end
-- Create result item
local newItem = lia.item.instance(recipe.result)
if newItem then
char:getInv():add(newItem)
item:remove()
target:remove()
-- Grant experience
local currentSkill = char:getData("craftingSkill", 0)
char:setData("craftingSkill", currentSkill + 1)
client:ChatPrint("Items combined successfully! Crafting skill increased.")
return true
end
end
end
client:ChatPrint("These items cannot be combined")
return false
end)
ItemDeleted
Purpose
Called when an item is deleted
When Called
When an item is removed from the system
Parameters
instance(Item): The item being deleted
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log item deletion
hook.Add("ItemDeleted", "MyAddon", function(instance)
print("Item deleted: " .. instance.name)
end)
Medium Complexity:
-- Medium: Clean up item data
hook.Add("ItemDeleted", "CleanupItemData", function(instance)
-- Remove from cache
lia.itemCache[instance:getID()] = nil
print("Item deleted and cleaned up: " .. instance.name)
end)
High Complexity:
-- High: Complex item deletion handling
hook.Add("ItemDeleted", "AdvancedItemDeletion", function(instance)
local itemID = instance:getID()
-- Archive item data
lia.db.query("INSERT INTO item_archive SELECT * FROM items WHERE id = ?", itemID)
-- Clean up related data
lia.db.query("DELETE FROM item_data WHERE itemid = ?", itemID)
lia.db.query("DELETE FROM item_logs WHERE itemid = ?", itemID)
-- Remove from cache
lia.itemCache[itemID] = nil
-- Notify owner
local owner = instance:getOwner()
if IsValid(owner) then
owner:ChatPrint(instance.name .. " has been deleted")
end
-- Log deletion
print("Item deleted: " .. instance.name .. " (ID: " .. itemID .. ")")
lia.log.add("Item " .. instance.name .. " (" .. itemID .. ") was deleted", "item")
end)
ItemDraggedOutOfInventory
Purpose
Called when an item is dragged out of inventory
When Called
When a player drags an item outside the inventory panel
Parameters
client(Player): The player dragging the itemitem(Item): The item being dragged
Returns
- boolean - True to allow, false to deny
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all drags
hook.Add("ItemDraggedOutOfInventory", "MyAddon", function(client, item)
return true
end)
Medium Complexity:
-- Medium: Prevent dragging equipped items
hook.Add("ItemDraggedOutOfInventory", "PreventEquippedDrag", function(client, item)
if item:getData("equipped", false) then
client:ChatPrint("Cannot drag equipped items")
return false
end
return true
end)
High Complexity:
-- High: Complex drag validation
hook.Add("ItemDraggedOutOfInventory", "AdvancedDragValidation", function(client, item)
local char = client:getChar()
if not char then return false end
-- Prevent dragging equipped items
if item:getData("equipped", false) then
client:ChatPrint("Cannot drag equipped items")
return false
end
-- Prevent dragging bound items
if item:getData("bound", false) then
local boundTo = item:getData("boundTo")
if boundTo == char:getID() then
client:ChatPrint("This item is bound to you and cannot be dropped")
return false
end
end
-- Prevent dragging quest items
if item:getData("questItem", false) then
client:ChatPrint("Quest items cannot be dropped")
return false
end
-- Check cooldown
local lastDrag = char:getData("lastItemDrag", 0)
if CurTime() - lastDrag < 1 then
return false
end
char:setData("lastItemDrag", CurTime())
return true
end)
entity
Purpose
Called when an item function is called
When Called
When a player uses an item function
Parameters
self(Item): The item whose function was calledmethod(string): The function name that was calledclient(Player): The player calling the functionentity(Entity): The entity involved (if any)results(table): The results from the function
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log function calls
hook.Add("ItemFunctionCalled", "MyAddon", function(self, method, client, entity, results)
print(client:Name() .. " used " .. method .. " on " .. self.name)
end)
Medium Complexity:
-- Medium: Track function usage
hook.Add("ItemFunctionCalled", "TrackItemUsage", function(self, method, client, entity, results)
local char = client:getChar()
if char then
local usageCount = char:getData("itemUsage_" .. self.uniqueID, 0)
char:setData("itemUsage_" .. self.uniqueID, usageCount + 1)
end
end)
High Complexity:
-- High: Complex function tracking system
hook.Add("ItemFunctionCalled", "AdvancedFunctionTracking", function(self, method, client, entity, results)
local char = client:getChar()
if not char then return end
-- Log to database
lia.db.query("INSERT INTO item_function_logs (timestamp, itemid, method, charid, steamid) VALUES (?, ?, ?, ?, ?)",
os.time(), self:getID(), method, char:getID(), client:SteamID())
-- Track usage statistics
local usageCount = char:getData("itemUsage_" .. self.uniqueID, 0)
char:setData("itemUsage_" .. self.uniqueID, usageCount + 1)
-- Check for achievements
if usageCount + 1 >= 100 then
if not char:getData("achievement_itemMaster_" .. self.uniqueID, false) then
char:setData("achievement_itemMaster_" .. self.uniqueID, true)
client:ChatPrint("Achievement unlocked: Master of " .. self.name)
end
end
-- Handle specific methods
if method == "use" then
-- Decrease durability
local durability = self:getData("durability", 100)
self:setData("durability", math.max(0, durability - 1))
end
-- Notify nearby players
if method == "use" or method == "equip" then
for _, ply in ipairs(player.GetAll()) do
if ply ~= client and ply:GetPos():Distance(client:GetPos()) < 500 then
ply:ChatPrint(client:Name() .. " used " .. self.name)
end
end
end
end)
ItemFunctionCalled
Purpose
Called when an item function is called
When Called
When a player uses an item function
Parameters
self(Item): The item whose function was calledmethod(string): The function name that was calledclient(Player): The player calling the functionentity(Entity): The entity involved (if any)results(table): The results from the function
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log function calls
hook.Add("ItemFunctionCalled", "MyAddon", function(self, method, client, entity, results)
print(client:Name() .. " used " .. method .. " on " .. self.name)
end)
Medium Complexity:
-- Medium: Track function usage
hook.Add("ItemFunctionCalled", "TrackItemUsage", function(self, method, client, entity, results)
local char = client:getChar()
if char then
local usageCount = char:getData("itemUsage_" .. self.uniqueID, 0)
char:setData("itemUsage_" .. self.uniqueID, usageCount + 1)
end
end)
High Complexity:
-- High: Complex function tracking system
hook.Add("ItemFunctionCalled", "AdvancedFunctionTracking", function(self, method, client, entity, results)
local char = client:getChar()
if not char then return end
-- Log to database
lia.db.query("INSERT INTO item_function_logs (timestamp, itemid, method, charid, steamid) VALUES (?, ?, ?, ?, ?)",
os.time(), self:getID(), method, char:getID(), client:SteamID())
-- Track usage statistics
local usageCount = char:getData("itemUsage_" .. self.uniqueID, 0)
char:setData("itemUsage_" .. self.uniqueID, usageCount + 1)
-- Check for achievements
if usageCount + 1 >= 100 then
if not char:getData("achievement_itemMaster_" .. self.uniqueID, false) then
char:setData("achievement_itemMaster_" .. self.uniqueID, true)
client:ChatPrint("Achievement unlocked: Master of " .. self.name)
end
end
-- Handle specific methods
if method == "use" then
-- Decrease durability
local durability = self:getData("durability", 100)
self:setData("durability", math.max(0, durability - 1))
end
-- Notify nearby players
if method == "use" or method == "equip" then
for _, ply in ipairs(player.GetAll()) do
if ply ~= client and ply:GetPos():Distance(client:GetPos()) < 500 then
ply:ChatPrint(client:Name() .. " used " .. self.name)
end
end
end
end)
ItemTransfered
Purpose
Called when an item is transferred between inventories
When Called
When an item is successfully moved from one inventory to another
Parameters
context(table): The transfer context containing source, destination, item, etc.
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log item transfers
hook.Add("ItemTransfered", "MyAddon", function(context)
print("Item " .. context.item.uniqueID .. " transferred")
end)
Medium Complexity:
-- Medium: Track transfer statistics
hook.Add("ItemTransfered", "TransferTracking", function(context)
local fromChar = context.fromChar
local toChar = context.toChar
if fromChar then
fromChar:setData("itemsTransferredOut", (fromChar:getData("itemsTransferredOut", 0) + 1))
end
if toChar then
toChar:setData("itemsTransferredIn", (toChar:getData("itemsTransferredIn", 0) + 1))
end
end)
High Complexity:
-- High: Complex item transfer system
hook.Add("ItemTransfered", "AdvancedTransfers", function(context)
local fromChar = context.fromChar
local toChar = context.toChar
local item = context.item
local fromInv = context.fromInventory
local toInv = context.toInventory
-- Update transfer statistics
if fromChar then
fromChar:setData("itemsTransferredOut", (fromChar:getData("itemsTransferredOut", 0) + 1))
fromChar:setData("lastTransferOut", os.time())
end
if toChar then
toChar:setData("itemsTransferredIn", (toChar:getData("itemsTransferredIn", 0) + 1))
toChar:setData("lastTransferIn", os.time())
end
-- Check for transfer limits
local transferLimit = 100 -- Max transfers per hour
if fromChar then
local transfersThisHour = fromChar:getData("transfersThisHour", 0)
if transfersThisHour >= transferLimit then
fromChar:getPlayer():ChatPrint("Transfer limit reached for this hour")
return false
end
fromChar:setData("transfersThisHour", transfersThisHour + 1)
end
-- Check for valuable item transfers
local itemValue = item:getData("value", 0)
if itemValue > 1000 then
-- Log valuable transfers
print(string.format("Valuable item %s transferred from %s to %s (Value: $%d)",
item.uniqueID, fromChar and fromChar:getName() or "Unknown",
toChar and toChar:getName() or "Unknown", itemValue))
end
-- Check for faction restrictions
if fromChar and toChar then
local fromFaction = fromChar:getFaction()
local toFaction = toChar:getFaction()
if fromFaction == "police" and toFaction == "criminal" then
-- Police transferring to criminals - log this
print(string.format("Suspicious transfer: %s (Police) to %s (Criminal)",
fromChar:getName(), toChar:getName()))
end
end
-- Check for quest items
if item:getData("questItem", false) then
local questID = item:getData("questID")
if questID and toChar then
toChar:setData("questProgress", toChar:getData("questProgress", {})[questID] + 1)
toChar:getPlayer():ChatPrint("Quest progress updated!")
end
end
-- Check for bound items
if item:getData("bound", false) then
local boundTo = item:getData("boundTo")
if boundTo and toChar and boundTo ~= toChar:getID() then
toChar:getPlayer():ChatPrint("This item is bound to another character")
return false
end
end
-- Log transfer
print(string.format("Item %s transferred from %s to %s",
item.uniqueID, fromChar and fromChar:getName() or "Unknown",
toChar and toChar:getName() or "Unknown"))
end)
KeyLock
Purpose
Called when a key locks an entity
When Called
When a key is used to lock a door or entity
Parameters
owner(Player): The player using the keyentity(Entity): The entity being lockedtime(number): The time taken to lock
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log key lock
hook.Add("KeyLock", "MyAddon", function(owner, entity, time)
print(owner:Name() .. " locked " .. tostring(entity))
end)
Medium Complexity:
-- Medium: Track lock usage
hook.Add("KeyLock", "TrackLocks", function(owner, entity, time)
local char = owner:getChar()
if not char then return end
local locks = char:getData("locksUsed", 0)
char:setData("locksUsed", locks + 1)
end)
High Complexity:
-- High: Complex key lock system
hook.Add("KeyLock", "AdvancedKeyLock", function(owner, entity, time)
local char = owner:getChar()
if not char then return end
-- Update entity data
entity:setNetVar("locked", true)
entity:setNetVar("lockedBy", char:getID())
entity:setNetVar("lockedAt", os.time())
-- Log to database
lia.db.query("INSERT INTO lock_logs (timestamp, steamid, entityid, action) VALUES (?, ?, ?, ?)",
os.time(), owner:SteamID(), entity:EntIndex(), "locked")
-- Update character stats
local locks = char:getData("locksUsed", 0)
char:setData("locksUsed", locks + 1)
char:setData("lastLockTime", os.time())
-- Notify nearby players
local pos = entity:GetPos()
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(pos) < 500 and ply ~= owner then
ply:ChatPrint("You hear a lock clicking nearby")
end
end
end)
KeyUnlock
Purpose
Called when a key unlocks an entity
When Called
When a key is used to unlock a door or entity
Parameters
owner(Player): The player using the keyentity(Entity): The entity being unlockedtime(number): The time taken to unlock
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log key unlock
hook.Add("KeyUnlock", "MyAddon", function(owner, entity, time)
print(owner:Name() .. " unlocked " .. tostring(entity))
end)
Medium Complexity:
-- Medium: Track unlock usage
hook.Add("KeyUnlock", "TrackUnlocks", function(owner, entity, time)
local char = owner:getChar()
if not char then return end
local unlocks = char:getData("unlocksUsed", 0)
char:setData("unlocksUsed", unlocks + 1)
end)
High Complexity:
-- High: Complex key unlock system
hook.Add("KeyUnlock", "AdvancedKeyUnlock", function(owner, entity, time)
local char = owner:getChar()
if not char then return end
-- Update entity data
entity:setNetVar("locked", false)
entity:setNetVar("unlockedBy", char:getID())
entity:setNetVar("unlockedAt", os.time())
-- Log to database
lia.db.query("INSERT INTO lock_logs (timestamp, steamid, entityid, action) VALUES (?, ?, ?, ?)",
os.time(), owner:SteamID(), entity:EntIndex(), "unlocked")
-- Update character stats
local unlocks = char:getData("unlocksUsed", 0)
char:setData("unlocksUsed", unlocks + 1)
char:setData("lastUnlockTime", os.time())
-- Notify nearby players
local pos = entity:GetPos()
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(pos) < 500 and ply ~= owner then
ply:ChatPrint("You hear a lock clicking nearby")
end
end
end)
LiliaTablesLoaded
Purpose
Called when Lilia database tables are loaded
When Called
After database tables are created/loaded
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log tables loaded
hook.Add("LiliaTablesLoaded", "MyAddon", function()
print("Lilia tables loaded")
end)
Medium Complexity:
-- Medium: Create custom tables
hook.Add("LiliaTablesLoaded", "CreateCustomTables", function()
lia.db.query("CREATE TABLE IF NOT EXISTS my_table (id INTEGER PRIMARY KEY, data TEXT)")
print("Custom tables created")
end)
High Complexity:
-- High: Complex database initialization
hook.Add("LiliaTablesLoaded", "AdvancedDatabaseInit", function()
-- Create custom tables
local tables = {
"CREATE TABLE IF NOT EXISTS my_table (id INTEGER PRIMARY KEY, data TEXT)",
"CREATE TABLE IF NOT EXISTS my_stats (charid INTEGER, stat TEXT, value INTEGER)",
"CREATE TABLE IF NOT EXISTS my_logs (timestamp INTEGER, message TEXT)"
}
for _, query in ipairs(tables) do
lia.db.query(query)
end
-- Create indexes
lia.db.query("CREATE INDEX IF NOT EXISTS idx_my_stats_charid ON my_stats(charid)")
print("Custom database tables and indexes created")
end)
LoadData
Purpose
Called to load persistent data
When Called
When data needs to be loaded from storage
Returns
- None
Realm
Server
Example Usage
Low Complexity:
Medium Complexity:
-- Medium: Load custom data
hook.Add("LoadData", "LoadCustomData", function()
local data = lia.data.get("myAddonData", {})
MyAddon.data = data
print("Custom data loaded")
end)
High Complexity:
-- High: Complex data loading system
hook.Add("LoadData", "AdvancedDataLoad", function()
-- Load custom data
local data = lia.data.get("myAddonData", {})
MyAddon.data = data
-- Load from database
lia.db.query("SELECT * FROM my_table", function(results)
if results then
for _, row in ipairs(results) do
MyAddon.ProcessData(row)
end
end
end)
-- Initialize data structures
MyAddon.playerData = MyAddon.playerData or {}
MyAddon.sessionData = {}
print("All data loaded successfully")
end)
ModifyCharacterModel
Purpose
Called to modify a character's model
When Called
When a character's model is being set
Parameters
client(Player): The playercharacter(Character): The character whose model is being modified
Returns
- string - The modified model path
Realm
Server
Example Usage
Low Complexity:
-- Simple: Return default model
hook.Add("ModifyCharacterModel", "MyAddon", function(client, character)
return character:getModel()
end)
Medium Complexity:
-- Medium: Faction-based models
hook.Add("ModifyCharacterModel", "FactionModels", function(client, character)
local faction = character:getFaction()
if faction == "police" then
return "models/player/police.mdl"
elseif faction == "medic" then
return "models/player/medic.mdl"
end
return character:getModel()
end)
High Complexity:
-- High: Complex model modification system
hook.Add("ModifyCharacterModel", "AdvancedModelModification", function(client, character)
local baseModel = character:getModel()
-- Check for outfit override
local outfit = character:getData("outfit")
if outfit then
local outfitItem = lia.item.instances[outfit]
if outfitItem and outfitItem.model then
return outfitItem.model
end
end
-- Check faction models
local faction = lia.faction.indices[character:getFaction()]
if faction and faction.models then
local modelIndex = character:getData("modelIndex", 1)
if faction.models[modelIndex] then
return faction.models[modelIndex]
end
end
-- Check for transformation effects
if character:getData("transformed", false) then
local transformModel = character:getData("transformModel")
if transformModel then
return transformModel
end
end
return baseModel
end)
OnAdminSystemLoaded
Purpose
Called when admin system is loaded
When Called
After admin groups and privileges are initialized
Parameters
groups(table): The admin groups tableprivileges(table): The privileges table
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log admin system load
hook.Add("OnAdminSystemLoaded", "MyAddon", function(groups, privileges)
print("Admin system loaded")
end)
Medium Complexity:
-- Medium: Add custom admin groups
hook.Add("OnAdminSystemLoaded", "AddCustomAdminGroups", function(groups, privileges)
groups["moderator"] = {
name = "Moderator",
immunity = 50
}
print("Custom admin groups added")
end)
High Complexity:
-- High: Complex admin system customization
hook.Add("OnAdminSystemLoaded", "AdvancedAdminCustomization", function(groups, privileges)
-- Add custom admin groups
groups["moderator"] = {
name = "Moderator",
immunity = 50,
color = Color(0, 200, 0)
}
groups["headAdmin"] = {
name = "Head Admin",
immunity = 90,
color = Color(255, 0, 0)
}
-- Add custom privileges
privileges["canManageEvents"] = {
name = "Can Manage Events",
description = "Allows managing server events"
}
privileges["canEditVendors"] = {
name = "Can Edit Vendors",
description = "Allows editing vendor inventories"
}
print("Admin system customized with new groups and privileges")
end)
OnBackupCreated
Purpose
Called when a backup is created
When Called
After a data backup is successfully created
Parameters
metadata(table): The backup metadata
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log backup creation
hook.Add("OnBackupCreated", "MyAddon", function(metadata)
print("Backup created")
end)
Medium Complexity:
-- Medium: Log backup details
hook.Add("OnBackupCreated", "LogBackupDetails", function(metadata)
print("Backup created: " .. metadata.filename)
print("Size: " .. metadata.size .. " bytes")
end)
High Complexity:
-- High: Complex backup management
hook.Add("OnBackupCreated", "AdvancedBackupManagement", function(metadata)
-- Log backup creation
print("Backup created: " .. metadata.filename)
print("Size: " .. metadata.size .. " bytes")
print("Timestamp: " .. os.date("%Y-%m-%d %H:%M:%S", metadata.timestamp))
-- Store backup metadata
lia.db.query("INSERT INTO backups (timestamp, filename, size) VALUES (?, ?, ?)",
metadata.timestamp, metadata.filename, metadata.size)
-- Notify admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("[BACKUP] New backup created: " .. metadata.filename)
end
end
-- Clean up old backups
local maxBackups = 10
lia.db.query("SELECT COUNT(*) as count FROM backups", function(results)
if results and results[1] and results[1].count > maxBackups then
lia.db.query("DELETE FROM backups WHERE id IN (SELECT id FROM backups ORDER BY timestamp ASC LIMIT 1)")
print("Old backup deleted to maintain backup limit")
end
end)
end)
OnCharAttribBoosted
Purpose
Called when a character attribute is boosted
When Called
When a character's attribute is increased
Parameters
character(Character): The character whose attribute was boosted
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log attribute boost
hook.Add("OnCharAttribBoosted", "MyAddon", function(character)
print(character:getName() .. " boosted an attribute")
end)
Medium Complexity:
-- Medium: Track attribute boosts
hook.Add("OnCharAttribBoosted", "TrackAttributeBoosts", function(character)
local boosts = character:getData("attributeBoosts", 0)
character:setData("attributeBoosts", boosts + 1)
end)
High Complexity:
-- High: Complex attribute boost system
hook.Add("OnCharAttribBoosted", "AdvancedAttributeBoost", function(character)
local boosts = character:getData("attributeBoosts", 0)
character:setData("attributeBoosts", boosts + 1)
-- Log to database
lia.db.query("INSERT INTO attribute_logs (timestamp, charid, action) VALUES (?, ?, ?)",
os.time(), character:getID(), "boosted")
-- Notify player
local client = character:getPlayer()
if IsValid(client) then
client:ChatPrint("Attribute boosted! Total boosts: " .. (boosts + 1))
end
-- Check for achievements
if boosts + 1 >= 50 then
if not character:getData("achievement_attributeMaster", false) then
character:setData("achievement_attributeMaster", true)
if IsValid(client) then
client:ChatPrint("Achievement unlocked: Attribute Master!")
end
end
end
end)
OnCharAttribUpdated
Purpose
Called when a character attribute is updated
When Called
When a character's attribute value changes
Parameters
client(Player): The playercharacter(Character): The characterkey(string): The attribute keynewValue(number): The new attribute value
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log attribute updates
hook.Add("OnCharAttribUpdated", "MyAddon", function(client, character, key, newValue)
print(character:getName() .. " " .. key .. " updated to " .. newValue)
end)
Medium Complexity:
-- Medium: Track attribute changes
hook.Add("OnCharAttribUpdated", "TrackAttributeChanges", function(client, character, key, newValue)
local changes = character:getData("attributeChanges", {})
changes[key] = (changes[key] or 0) + 1
character:setData("attributeChanges", changes)
end)
High Complexity:
-- High: Complex attribute tracking system
hook.Add("OnCharAttribUpdated", "AdvancedAttributeTracking", function(client, character, key, newValue)
-- Log to database
lia.db.query("INSERT INTO attribute_logs (timestamp, charid, attribute, value) VALUES (?, ?, ?, ?)",
os.time(), character:getID(), key, newValue)
-- Track changes
local changes = character:getData("attributeChanges", {})
changes[key] = (changes[key] or 0) + 1
character:setData("attributeChanges", changes)
-- Notify player
client:ChatPrint(key .. " updated to " .. newValue)
-- Apply attribute effects
if key == "str" then
-- Strength affects melee damage
local damageBonus = newValue * 0.5
character:setData("meleeDamageBonus", damageBonus)
elseif key == "end" then
-- Endurance affects max health
local healthBonus = newValue * 2
client:SetMaxHealth(100 + healthBonus)
elseif key == "agi" then
-- Agility affects movement speed
local speedBonus = 1 + (newValue * 0.01)
client:SetRunSpeed(250 * speedBonus)
client:SetWalkSpeed(100 * speedBonus)
end
end)
OnCharCreated
Purpose
Called when a character is created
When Called
When a new character is successfully created
Parameters
client(Player): The player who created the charactercharacter(Character): The character that was createdoriginalData(table): The original character data before any modifications
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log character creation
hook.Add("OnCharCreated", "MyAddon", function(client, character, originalData)
print(client:Name() .. " created character: " .. character:getName())
end)
Medium Complexity:
-- Medium: Set up new character bonuses
hook.Add("OnCharCreated", "NewCharBonuses", function(client, character, originalData)
-- Give starting money bonus
local bonusMoney = 500
character:setMoney(character:getMoney() + bonusMoney)
-- Give starting items
local startingItems = {"wallet", "phone", "id_card"}
for _, itemID in ipairs(startingItems) do
local item = lia.item.instance(itemID)
if item then
character:getInv():add(item)
end
end
client:ChatPrint("Welcome! You received starting bonuses.")
end)
High Complexity:
-- High: Complex character creation system
hook.Add("OnCharCreated", "AdvancedCreation", function(client, character, originalData)
local faction = character:getFaction()
-- Set up faction-specific starting equipment
local factionEquipment = {
["police"] = {
items = {"police_badge", "handcuffs", "radio"},
money = 1000,
attributes = {str = 5, con = 4, dex = 3}
},
["medic"] = {
items = {"medkit", "stethoscope", "bandage"},
money = 800,
attributes = {int = 6, wis = 5, con = 4}
},
["citizen"] = {
items = {"wallet", "phone"},
money = 500,
attributes = {str = 3, con = 3, dex = 3}
}
}
local equipment = factionEquipment[faction]
if equipment then
-- Give faction-specific money
character:setMoney(character:getMoney() + equipment.money)
-- Give faction-specific items
for _, itemID in ipairs(equipment.items) do
local item = lia.item.instance(itemID)
if item then
character:getInv():add(item)
end
end
-- Set faction-specific attributes
for attr, value in pairs(equipment.attributes) do
character:setAttrib(attr, value)
end
end
-- Set up character data
character:setData("creationTime", os.time())
character:setData("creationIP", client:IPAddress())
character:setData("level", 1)
character:setData("experience", 0)
-- Send welcome message
client:ChatPrint("Character created successfully! Welcome to the server.")
-- Log creation
print(string.format("%s created %s character: %s",
client:Name(), faction, character:getName()))
end)
OnCharDelete
Purpose
Called when a character is deleted
When Called
When a character is successfully deleted
Parameters
client(Player): The player who deleted the characterid(number): The ID of the character that was deleted
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log character deletion
hook.Add("OnCharDelete", "MyAddon", function(client, id)
print(client:Name() .. " deleted character ID: " .. id)
end)
Medium Complexity:
-- Medium: Track deletion statistics
hook.Add("OnCharDelete", "DeletionTracking", function(client, id)
local char = client:getChar()
if char then
char:setData("charactersDeleted", (char:getData("charactersDeleted", 0) + 1))
char:setData("lastCharDelete", os.time())
end
end)
High Complexity:
-- High: Complex character deletion system
hook.Add("OnCharDelete", "AdvancedDeletion", function(client, id)
local char = client:getChar()
if not char then return end
-- Update deletion statistics
char:setData("charactersDeleted", (char:getData("charactersDeleted", 0) + 1))
char:setData("lastCharDelete", os.time())
-- Check for deletion cooldown
local lastDelete = char:getData("lastCharDelete", 0)
local deleteCooldown = 3600 -- 1 hour
if os.time() - lastDelete < deleteCooldown then
client:ChatPrint("You must wait before deleting another character")
return false
end
-- Check for valuable items
local charInv = char:getInv()
local valuableItems = {}
for _, item in pairs(charInv:getItems()) do
if item:getData("value", 0) > 1000 then
table.insert(valuableItems, item)
end
end
if #valuableItems > 0 then
client:ChatPrint("Warning: You have valuable items. Are you sure you want to delete this character?")
return false
end
-- Check for faction restrictions
local faction = char:getFaction()
if faction ~= "citizen" then
client:ChatPrint("You must leave your faction before deleting this character")
return false
end
-- Check for active quests
local activeQuests = char:getData("activeQuests", {})
if #activeQuests > 0 then
client:ChatPrint("You have active quests. Complete them before deleting this character")
return false
end
-- Log deletion
print(string.format("%s deleted character ID %d (Faction: %s)",
client:Name(), id, faction))
-- Notify admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() and ply ~= client then
ply:ChatPrint("[ADMIN] " .. client:Name() .. " deleted character ID " .. id)
end
end
end)
OnCharDisconnect
Purpose
Called when a character disconnects
When Called
When a player disconnects while having a character loaded
Parameters
client(Player): The player who disconnectedcharacter(Character): The character that was loaded when disconnecting
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log character disconnect
hook.Add("OnCharDisconnect", "MyAddon", function(client, character)
print(client:Name() .. " disconnected with character: " .. character:getName())
end)
Medium Complexity:
-- Medium: Save character data on disconnect
hook.Add("OnCharDisconnect", "CharDisconnectSave", function(client, character)
-- Save character position
character:setData("lastPos", client:GetPos())
character:setData("lastAng", client:GetAngles())
-- Save character health and armor
character:setData("lastHealth", client:Health())
character:setData("lastArmor", client:Armor())
-- Save disconnect time
character:setData("lastDisconnect", os.time())
end)
High Complexity:
-- High: Complex character disconnect system
hook.Add("OnCharDisconnect", "AdvancedCharDisconnect", function(client, character)
-- Save character state
character:setData("lastPos", client:GetPos())
character:setData("lastAng", client:GetAngles())
character:setData("lastHealth", client:Health())
character:setData("lastArmor", client:Armor())
character:setData("lastDisconnect", os.time())
-- Save inventory state
local inventory = character:getInv()
if inventory then
character:setData("inventoryState", inventory:getData())
end
-- Save character money
character:setData("lastMoney", character:getMoney())
-- Save character attributes
local attributes = character:getAttribs()
character:setData("lastAttributes", attributes)
-- Save character data
local charData = character:getData()
character:setData("lastCharData", charData)
-- Check for active effects
local activeEffects = character:getData("activeEffects", {})
if #activeEffects > 0 then
-- Pause active effects
for _, effect in ipairs(activeEffects) do
effect.paused = true
effect.pauseTime = os.time()
end
character:setData("activeEffects", activeEffects)
end
-- Check for active quests
local activeQuests = character:getData("activeQuests", {})
if #activeQuests > 0 then
-- Pause active quests
for _, quest in ipairs(activeQuests) do
quest.paused = true
quest.pauseTime = os.time()
end
character:setData("activeQuests", activeQuests)
end
-- Notify other players
for _, ply in ipairs(player.GetAll()) do
if ply ~= client then
ply:ChatPrint(character:getName() .. " has disconnected")
end
end
-- Log disconnect
print(string.format("%s disconnected with character %s (Faction: %s)",
client:Name(), character:getName(), character:getFaction()))
end)
OnCharFallover
Purpose
Called when a character falls over
When Called
When a character is knocked down/ragdolled
Parameters
character(Character): The character falling overclient(Player): The playerragdoll(Entity): The ragdoll entity created
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log fallover
hook.Add("OnCharFallover", "MyAddon", function(character, client, ragdoll)
print(character:getName() .. " fell over")
end)
Medium Complexity:
-- Medium: Set ragdoll data
hook.Add("OnCharFallover", "SetRagdollData", function(character, client, ragdoll)
ragdoll:setNetVar("charID", character:getID())
ragdoll:setNetVar("fallTime", os.time())
end)
High Complexity:
-- High: Complex fallover system
hook.Add("OnCharFallover", "AdvancedFallover", function(character, client, ragdoll)
-- Set ragdoll data
ragdoll:setNetVar("charID", character:getID())
ragdoll:setNetVar("fallTime", os.time())
ragdoll:setNetVar("charName", character:getName())
-- Track fallover count
local fallCount = character:getData("fallCount", 0)
character:setData("fallCount", fallCount + 1)
-- Apply faction-specific effects
local faction = character:getFaction()
if faction == "police" then
-- Police get up faster
timer.Simple(5, function()
if IsValid(ragdoll) and IsValid(client) then
client:SetRagdolled(false)
end
end)
end
-- Notify nearby players
for _, ply in ipairs(player.GetAll()) do
if ply ~= client and ply:GetPos():Distance(client:GetPos()) < 500 then
ply:ChatPrint(character:getName() .. " fell over")
end
end
end)
OnCharFlagsGiven
Purpose
Called when flags are given to a character
When Called
When a character receives new flags
Parameters
ply(Player): The player receiving flagsself(Character): The character receiving flagsaddedFlags(string): The flags that were added
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log flags given
hook.Add("OnCharFlagsGiven", "MyAddon", function(ply, self, addedFlags)
print(self:getName() .. " received flags: " .. addedFlags)
end)
Medium Complexity:
-- Medium: Track flag changes
hook.Add("OnCharFlagsGiven", "TrackFlagChanges", function(ply, self, addedFlags)
local flagHistory = self:getData("flagHistory", {})
table.insert(flagHistory, {action = "given", flags = addedFlags, time = os.time()})
self:setData("flagHistory", flagHistory)
end)
High Complexity:
-- High: Complex flag management system
hook.Add("OnCharFlagsGiven", "AdvancedFlagManagement", function(ply, self, addedFlags)
-- Log to database
lia.db.query("INSERT INTO flag_logs (timestamp, charid, action, flags) VALUES (?, ?, ?, ?)",
os.time(), self:getID(), "given", addedFlags)
-- Track flag history
local flagHistory = self:getData("flagHistory", {})
table.insert(flagHistory, {action = "given", flags = addedFlags, time = os.time()})
self:setData("flagHistory", flagHistory)
-- Notify player
ply:ChatPrint("You received flags: " .. addedFlags)
-- Apply flag-specific effects
for i = 1, #addedFlags do
local flag = addedFlags:sub(i, i)
if flag == "v" then
-- VIP flag
ply:ChatPrint("You are now a VIP!")
elseif flag == "a" then
-- Admin flag
ply:ChatPrint("You now have admin privileges!")
end
end
-- Notify admins
for _, admin in ipairs(player.GetAll()) do
if admin:IsAdmin() and admin ~= ply then
admin:ChatPrint("[FLAGS] " .. self:getName() .. " received flags: " .. addedFlags)
end
end
end)
OnCharFlagsTaken
Purpose
Called when flags are taken from a character
When Called
When a character loses flags
Parameters
ply(Player): The player losing flagsself(Character): The character losing flagsremovedFlags(string): The flags that were removed
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log flags taken
hook.Add("OnCharFlagsTaken", "MyAddon", function(ply, self, removedFlags)
print(self:getName() .. " lost flags: " .. removedFlags)
end)
Medium Complexity:
-- Medium: Track flag removals
hook.Add("OnCharFlagsTaken", "TrackFlagRemovals", function(ply, self, removedFlags)
local flagHistory = self:getData("flagHistory", {})
table.insert(flagHistory, {action = "taken", flags = removedFlags, time = os.time()})
self:setData("flagHistory", flagHistory)
end)
High Complexity:
-- High: Complex flag removal system
hook.Add("OnCharFlagsTaken", "AdvancedFlagRemoval", function(ply, self, removedFlags)
-- Log to database
lia.db.query("INSERT INTO flag_logs (timestamp, charid, action, flags) VALUES (?, ?, ?, ?)",
os.time(), self:getID(), "taken", removedFlags)
-- Track flag history
local flagHistory = self:getData("flagHistory", {})
table.insert(flagHistory, {action = "taken", flags = removedFlags, time = os.time()})
self:setData("flagHistory", flagHistory)
-- Notify player
ply:ChatPrint("You lost flags: " .. removedFlags)
-- Remove flag-specific effects
for i = 1, #removedFlags do
local flag = removedFlags:sub(i, i)
if flag == "v" then
-- VIP flag removed
ply:ChatPrint("Your VIP status has been revoked")
elseif flag == "a" then
-- Admin flag removed
ply:ChatPrint("Your admin privileges have been revoked")
end
end
-- Notify admins
for _, admin in ipairs(player.GetAll()) do
if admin:IsAdmin() and admin ~= ply then
admin:ChatPrint("[FLAGS] " .. self:getName() .. " lost flags: " .. removedFlags)
end
end
end)
OnCharGetup
Purpose
Called when a character gets up from being unconscious
When Called
When a character regains consciousness or is revived
Parameters
target(Player): The player whose character got upentity(Entity): The ragdoll entity that was removed
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log character getup
hook.Add("OnCharGetup", "MyAddon", function(target, entity)
print(target:Name() .. " got up")
end)
Medium Complexity:
-- Medium: Handle getup effects
hook.Add("OnCharGetup", "GetupEffects", function(target, entity)
local char = target:getChar()
if char then
-- Clear unconscious status
char:setData("unconscious", false)
char:setData("getupTime", os.time())
-- Restore some health
local currentHealth = target:Health()
local maxHealth = target:GetMaxHealth()
target:SetHealth(math.min(currentHealth + 25, maxHealth))
target:ChatPrint("You have regained consciousness")
end
end)
High Complexity:
-- High: Complex getup system
hook.Add("OnCharGetup", "AdvancedGetup", function(target, entity)
local char = target:getChar()
if not char then return end
-- Clear unconscious status
char:setData("unconscious", false)
char:setData("getupTime", os.time())
char:setData("revivalTime", nil)
-- Restore health based on faction
local faction = char:getFaction()
local healthRestore = {
["police"] = 50,
["medic"] = 75,
["citizen"] = 25
}
local restoreAmount = healthRestore[faction] or 25
local currentHealth = target:Health()
local maxHealth = target:GetMaxHealth()
target:SetHealth(math.min(currentHealth + restoreAmount, maxHealth))
-- Restore stamina
local currentStamina = target:getNetVar("stamina", 100)
target:setNetVar("stamina", math.min(currentStamina + 50, 100))
-- Resume active effects
local activeEffects = char:getData("activeEffects", {})
for _, effect in ipairs(activeEffects) do
if effect.paused then
effect.paused = false
effect.pauseTime = nil
end
end
char:setData("activeEffects", activeEffects)
-- Resume active quests
local activeQuests = char:getData("activeQuests", {})
for _, quest in ipairs(activeQuests) do
if quest.paused then
quest.paused = false
quest.pauseTime = nil
end
end
char:setData("activeQuests", activeQuests)
-- Check for revival achievements
local revivals = char:getData("revivals", 0) + 1
char:setData("revivals", revivals)
if revivals >= 10 and not char:getData("achievement_survivor", false) then
char:setData("achievement_survivor", true)
target:ChatPrint("Achievement unlocked: Survivor!")
end
-- Notify nearby players
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(target:GetPos()) < 500 then
ply:ChatPrint(char:getName() .. " has regained consciousness")
end
end
-- Log getup
print(string.format("%s got up (Faction: %s, Health: %d)",
char:getName(), faction, target:Health()))
end)
OnCharKick
Purpose
Called when a character is kicked
When Called
When a character is kicked from the server
Parameters
self(Character): The character being kickedclient(Player): The player being kicked
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log character kick
hook.Add("OnCharKick", "MyAddon", function(self, client)
print(self:getName() .. " was kicked")
end)
Medium Complexity:
-- Medium: Handle kick effects
hook.Add("OnCharKick", "KickEffects", function(self, client)
-- Save character data
self:setData("lastKick", os.time())
self:setData("kickCount", (self:getData("kickCount", 0) + 1))
-- Notify other players
for _, ply in ipairs(player.GetAll()) do
if ply ~= client then
ply:ChatPrint(self:getName() .. " was kicked from the server")
end
end
end)
High Complexity:
-- High: Complex kick system
hook.Add("OnCharKick", "AdvancedKick", function(self, client)
-- Save character data
self:setData("lastKick", os.time())
self:setData("kickCount", (self:getData("kickCount", 0) + 1))
-- Save character state
self:setData("lastPos", client:GetPos())
self:setData("lastAng", client:GetAngles())
self:setData("lastHealth", client:Health())
self:setData("lastArmor", client:Armor())
-- Save inventory state
local inventory = self:getInv()
if inventory then
self:setData("inventoryState", inventory:getData())
end
-- Check for kick reasons
local kickReason = client:getData("kickReason", "Unknown")
self:setData("lastKickReason", kickReason)
-- Check for faction-specific effects
local faction = self:getFaction()
if faction == "police" then
-- Police get backup call
for _, ply in ipairs(player.GetAll()) do
local plyChar = ply:getChar()
if plyChar and plyChar:getFaction() == "police" then
ply:ChatPrint("[BACKUP] " .. self:getName() .. " was kicked! Reason: " .. kickReason)
end
end
elseif faction == "medic" then
-- Medics get medical alert
for _, ply in ipairs(player.GetAll()) do
local plyChar = ply:getChar()
if plyChar and plyChar:getFaction() == "medic" then
ply:ChatPrint("[MEDICAL] " .. self:getName() .. " was kicked! Reason: " .. kickReason)
end
end
end
-- Check for active quests
local activeQuests = self:getData("activeQuests", {})
for _, quest in ipairs(activeQuests) do
if quest.type == "survival" then
quest.failed = true
quest.failTime = os.time()
end
end
-- Check for active effects
local activeEffects = self:getData("activeEffects", {})
for _, effect in ipairs(activeEffects) do
effect.paused = true
effect.pauseTime = os.time()
end
-- Notify other players
for _, ply in ipairs(player.GetAll()) do
if ply ~= client then
ply:ChatPrint(self:getName() .. " was kicked from the server")
end
end
-- Log kick
print(string.format("%s was kicked (Faction: %s, Reason: %s)",
self:getName(), faction, kickReason))
end)
OnCharNetVarChanged
Purpose
Called when a character's network variable changes
When Called
When a character's networked data is modified
Parameters
character(Character): The character whose variable changedkey(string): The name of the variable that changedoldVar(any): The previous value of the variablevalue(any): The new value of the variable
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log network variable changes
hook.Add("OnCharNetVarChanged", "MyAddon", function(character, key, oldVar, value)
print(character:getName() .. " netvar changed: " .. key .. " = " .. tostring(value))
end)
Medium Complexity:
-- Medium: Track specific variable changes
hook.Add("OnCharNetVarChanged", "NetVarTracking", function(character, key, oldVar, value)
if key == "health" then
local client = character:getPlayer()
if client then
client:ChatPrint("Health changed from " .. oldVar .. " to " .. value)
end
elseif key == "money" then
local client = character:getPlayer()
if client then
client:ChatPrint("Money changed from $" .. oldVar .. " to $" .. value)
end
end
end)
High Complexity:
-- High: Complex network variable system
hook.Add("OnCharNetVarChanged", "AdvancedNetVar", function(character, key, oldVar, value)
local client = character:getPlayer()
if not client then return end
-- Track variable change history
local changeHistory = character:getData("netVarHistory", {})
changeHistory[key] = changeHistory[key] or {}
table.insert(changeHistory[key], {
oldValue = oldVar,
newValue = value,
timestamp = os.time()
})
-- Keep only last 10 changes per variable
if #changeHistory[key] > 10 then
table.remove(changeHistory[key], 1)
end
character:setData("netVarHistory", changeHistory)
-- Handle specific variable changes
if key == "health" then
-- Health change effects
if value <= 0 and oldVar > 0 then
-- Character died
hook.Run("OnCharacterDeath", character)
elseif value > 0 and oldVar <= 0 then
-- Character revived
hook.Run("OnCharacterRevive", character)
end
-- Notify nearby players of health change
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(client:GetPos()) < 500 then
ply:ChatPrint(character:getName() .. "'s health: " .. value .. "/" .. client:GetMaxHealth())
end
end
elseif key == "money" then
-- Money change effects
local difference = value - oldVar
if difference > 0 then
client:ChatPrint("You gained $" .. difference)
elseif difference < 0 then
client:ChatPrint("You lost $" .. math.abs(difference))
end
-- Check for money milestones
if value >= 10000 and oldVar < 10000 then
client:ChatPrint("Congratulations! You've reached $10,000!")
elseif value >= 100000 and oldVar < 100000 then
client:ChatPrint("Congratulations! You've reached $100,000!")
end
elseif key == "level" then
-- Level change effects
if value > oldVar then
hook.Run("OnPlayerLevelUp", client, oldVar, value)
end
elseif key == "faction" then
-- Faction change effects
client:SetTeam(value)
client:ChatPrint("Faction changed to: " .. value)
-- Notify other players
for _, ply in ipairs(player.GetAll()) do
if ply ~= client then
ply:ChatPrint(character:getName() .. " joined faction: " .. value)
end
end
end
-- Log significant changes
if math.abs(value - oldVar) > 100 or key == "faction" then
print(string.format("%s netvar changed: %s from %s to %s",
character:getName(), key, tostring(oldVar), tostring(value)))
end
end)
OnCharPermakilled
Purpose
Called when a character is permanently killed
When Called
When a character is permanently removed from the game
Parameters
character(Character): The character being permanently killedclient(Player): The player whose character was killed
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log permanent character death
hook.Add("OnCharPermakilled", "MyAddon", function(character, client)
print(character:getName() .. " was permanently killed")
end)
Medium Complexity:
-- Medium: Handle permanent death effects
hook.Add("OnCharPermakilled", "PermaDeathEffects", function(character, client)
-- Clear character data
character:setData("permaKilled", true)
character:setData("permaKillTime", os.time())
-- Notify other players
for _, ply in ipairs(player.GetAll()) do
if ply ~= client then
ply:ChatPrint(character:getName() .. " was permanently killed")
end
end
end)
High Complexity:
-- High: Complex permanent death system
hook.Add("OnCharPermakilled", "AdvancedPermaDeath", function(character, client)
-- Set permanent death data
character:setData("permaKilled", true)
character:setData("permaKillTime", os.time())
character:setData("permaKillReason", "Unknown")
-- Clear character inventory
local inventory = character:getInv()
if inventory then
local items = inventory:getItems()
for _, item in pairs(items) do
inventory:remove(item)
end
end
-- Clear character money
character:setMoney(0)
-- Clear character attributes
local attributes = character:getAttribs()
for attr, _ in pairs(attributes) do
character:setAttrib(attr, 0)
end
-- Clear character data
character:setData("level", 1)
character:setData("experience", 0)
character:setData("activeQuests", {})
character:setData("activeEffects", {})
-- Check for faction-specific effects
local faction = character:getFaction()
if faction == "police" then
-- Police get backup call
for _, ply in ipairs(player.GetAll()) do
local plyChar = ply:getChar()
if plyChar and plyChar:getFaction() == "police" then
ply:ChatPrint("[BACKUP] " .. character:getName() .. " was permanently killed!")
end
end
elseif faction == "medic" then
-- Medics get medical alert
for _, ply in ipairs(player.GetAll()) do
local plyChar = ply:getChar()
if plyChar and plyChar:getFaction() == "medic" then
ply:ChatPrint("[MEDICAL] " .. character:getName() .. " was permanently killed!")
end
end
end
-- Check for active quests
local activeQuests = character:getData("activeQuests", {})
for _, quest in ipairs(activeQuests) do
quest.failed = true
quest.failTime = os.time()
quest.failReason = "Character permanently killed"
end
-- Check for active effects
local activeEffects = character:getData("activeEffects", {})
for _, effect in ipairs(activeEffects) do
effect.paused = true
effect.pauseTime = os.time()
end
-- Notify other players
for _, ply in ipairs(player.GetAll()) do
if ply ~= client then
ply:ChatPrint(character:getName() .. " was permanently killed")
end
end
-- Log permanent death
print(string.format("%s was permanently killed (Faction: %s, Level: %d)",
character:getName(), faction, character:getData("level", 1)))
end)
OnCharRecognized
Purpose
Called when a character recognizes another character
When Called
When a character successfully identifies another character
Parameters
client(Player): The player doing the recognizingtarget(Player): The player being recognized
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log character recognition
hook.Add("OnCharRecognized", "MyAddon", function(client, target)
print(client:Name() .. " recognized " .. target:Name())
end)
Medium Complexity:
-- Medium: Handle recognition effects
hook.Add("OnCharRecognized", "RecognitionEffects", function(client, target)
local clientChar = client:getChar()
local targetChar = target:getChar()
if clientChar and targetChar then
-- Add recognition data
local recognitions = clientChar:getData("recognitions", {})
recognitions[targetChar:getID()] = os.time()
clientChar:setData("recognitions", recognitions)
client:ChatPrint("You recognized " .. targetChar:getName())
end
end)
High Complexity:
-- High: Complex recognition system
hook.Add("OnCharRecognized", "AdvancedRecognition", function(client, target)
local clientChar = client:getChar()
local targetChar = target:getChar()
if not clientChar or not targetChar then return end
-- Add recognition data
local recognitions = clientChar:getData("recognitions", {})
recognitions[targetChar:getID()] = {
timestamp = os.time(),
location = client:GetPos(),
faction = targetChar:getFaction()
}
clientChar:setData("recognitions", recognitions)
-- Check for faction-specific recognition
local clientFaction = clientChar:getFaction()
local targetFaction = targetChar:getFaction()
if clientFaction == "police" and targetFaction == "criminal" then
-- Police recognizing criminal
client:ChatPrint("You recognized criminal: " .. targetChar:getName())
-- Notify other police
for _, ply in ipairs(player.GetAll()) do
local plyChar = ply:getChar()
if plyChar and plyChar:getFaction() == "police" and ply ~= client then
ply:ChatPrint("[POLICE] " .. clientChar:getName() .. " recognized criminal: " .. targetChar:getName())
end
end
elseif clientFaction == "criminal" and targetFaction == "police" then
-- Criminal recognizing police
client:ChatPrint("You recognized police officer: " .. targetChar:getName())
-- Notify other criminals
for _, ply in ipairs(player.GetAll()) do
local plyChar = ply:getChar()
if plyChar and plyChar:getFaction() == "criminal" and ply ~= client then
ply:ChatPrint("[CRIMINAL] " .. clientChar:getName() .. " recognized police: " .. targetChar:getName())
end
end
else
-- General recognition
client:ChatPrint("You recognized " .. targetChar:getName())
end
-- Check for recognition achievements
local recognitionCount = clientChar:getData("recognitionCount", 0) + 1
clientChar:setData("recognitionCount", recognitionCount)
if recognitionCount >= 50 and not clientChar:getData("achievement_recognizer", false) then
clientChar:setData("achievement_recognizer", true)
client:ChatPrint("Achievement unlocked: Recognizer!")
end
-- Check for faction recognition achievements
local factionRecognitions = clientChar:getData("factionRecognitions", {})
factionRecognitions[targetFaction] = (factionRecognitions[targetFaction] or 0) + 1
clientChar:setData("factionRecognitions", factionRecognitions)
if factionRecognitions[targetFaction] >= 10 and not clientChar:getData("achievement_faction_recognizer", false) then
clientChar:setData("achievement_faction_recognizer", true)
client:ChatPrint("Achievement unlocked: Faction Recognizer!")
end
-- Log recognition
print(string.format("%s recognized %s (Factions: %s -> %s)",
clientChar:getName(), targetChar:getName(), clientFaction, targetFaction))
end)
OnCharTradeVendor
Purpose
Called when a character trades with a vendor
When Called
When a character buys or sells items to/from a vendor
Parameters
client(Player): The player trading with the vendorvendor(Entity): The vendor entityitem(Item): The item being tradedisSellingToVendor(boolean): True if selling to vendor, false if buyingcharacter(Character): The character doing the tradingitemType(string): The type of item being tradedisFailed(boolean): Whether the trade failed
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log vendor trades
hook.Add("OnCharTradeVendor", "MyAddon", function(client, vendor, item, isSellingToVendor, character, itemType, isFailed)
local action = isSellingToVendor and "sold" or "bought"
print(character:getName() .. " " .. action .. " " .. item.uniqueID .. " from vendor")
end)
Medium Complexity:
-- Medium: Track trade statistics
hook.Add("OnCharTradeVendor", "TradeTracking", function(client, vendor, item, isSellingToVendor, character, itemType, isFailed)
if not isFailed then
local trades = character:getData("vendorTrades", 0) + 1
character:setData("vendorTrades", trades)
local action = isSellingToVendor and "sold" or "bought"
client:ChatPrint("You " .. action .. " " .. item.uniqueID .. " from vendor")
end
end)
High Complexity:
-- High: Complex vendor trading system
hook.Add("OnCharTradeVendor", "AdvancedVendorTrading", function(client, vendor, item, isSellingToVendor, character, itemType, isFailed)
if isFailed then
client:ChatPrint("Trade failed!")
return
end
-- Update trade statistics
local trades = character:getData("vendorTrades", 0) + 1
character:setData("vendorTrades", trades)
-- Update vendor statistics
local vendorData = vendor:getNetVar("vendorData", {})
vendorData.tradeCount = (vendorData.tradeCount or 0) + 1
vendorData.lastTrade = os.time()
vendor:setNetVar("vendorData", vendorData)
-- Check for trade achievements
if trades >= 100 and not character:getData("achievement_trader", false) then
character:setData("achievement_trader", true)
client:ChatPrint("Achievement unlocked: Trader!")
end
-- Check for faction-specific trading
local faction = character:getFaction()
if faction == "police" and isSellingToVendor then
-- Police selling items - check for contraband
if itemType == "weapon" or itemType == "drug" then
client:ChatPrint("Warning: Selling contraband as police officer!")
-- Notify other police
for _, ply in ipairs(player.GetAll()) do
local plyChar = ply:getChar()
if plyChar and plyChar:getFaction() == "police" and ply ~= client then
ply:ChatPrint("[POLICE] " .. character:getName() .. " sold contraband: " .. item.uniqueID)
end
end
end
elseif faction == "criminal" and not isSellingToVendor then
-- Criminal buying items - check for weapons
if itemType == "weapon" then
client:ChatPrint("You purchased a weapon from the vendor")
-- Notify other criminals
for _, ply in ipairs(player.GetAll()) do
local plyChar = ply:getChar()
if plyChar and plyChar:getFaction() == "criminal" and ply ~= client then
ply:ChatPrint("[CRIMINAL] " .. character:getName() .. " bought weapon: " .. item.uniqueID)
end
end
end
end
-- Check for bulk trading
local recentTrades = character:getData("recentTrades", {})
table.insert(recentTrades, os.time())
-- Remove trades older than 1 hour
local cutoff = os.time() - 3600
for i = #recentTrades, 1, -1 do
if recentTrades[i] < cutoff then
table.remove(recentTrades, i)
end
end
character:setData("recentTrades", recentTrades)
-- Check for bulk trading achievement
if #recentTrades >= 20 and not character:getData("achievement_bulk_trader", false) then
character:setData("achievement_bulk_trader", true)
client:ChatPrint("Achievement unlocked: Bulk Trader!")
end
-- Log trade
local action = isSellingToVendor and "sold" or "bought"
print(string.format("%s %s %s from vendor %s (Faction: %s)",
character:getName(), action, item.uniqueID, vendor:EntIndex(), faction))
end)
OnCharVarChanged
Purpose
Called when a character's variable changes
When Called
When a character's data variable is modified
Parameters
character(Character): The character whose variable changedvarName(string): The name of the variable that changedoldVar(any): The previous value of the variablenewVar(any): The new value of the variable
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log variable changes
hook.Add("OnCharVarChanged", "MyAddon", function(character, varName, oldVar, newVar)
print(character:getName() .. " var changed: " .. varName .. " = " .. tostring(newVar))
end)
Medium Complexity:
-- Medium: Track specific variable changes
hook.Add("OnCharVarChanged", "VarTracking", function(character, varName, oldVar, newVar)
if varName == "level" then
local client = character:getPlayer()
if client then
client:ChatPrint("Level changed from " .. oldVar .. " to " .. newVar)
end
elseif varName == "money" then
local client = character:getPlayer()
if client then
local difference = newVar - oldVar
if difference > 0 then
client:ChatPrint("You gained $" .. difference)
elseif difference < 0 then
client:ChatPrint("You lost $" .. math.abs(difference))
end
end
end
end)
High Complexity:
-- High: Complex variable change system
hook.Add("OnCharVarChanged", "AdvancedVarChange", function(character, varName, oldVar, newVar)
local client = character:getPlayer()
if not client then return end
-- Track variable change history
local changeHistory = character:getData("varHistory", {})
changeHistory[varName] = changeHistory[varName] or {}
table.insert(changeHistory[varName], {
oldValue = oldVar,
newValue = newVar,
timestamp = os.time()
})
-- Keep only last 20 changes per variable
if #changeHistory[varName] > 20 then
table.remove(changeHistory[varName], 1)
end
character:setData("varHistory", changeHistory)
-- Handle specific variable changes
if varName == "level" then
-- Level change effects
if newVar > oldVar then
hook.Run("OnPlayerLevelUp", client, oldVar, newVar)
end
elseif varName == "money" then
-- Money change effects
local difference = newVar - oldVar
if difference > 0 then
client:ChatPrint("You gained $" .. difference)
elseif difference < 0 then
client:ChatPrint("You lost $" .. math.abs(difference))
end
-- Check for money milestones
if newVar >= 10000 and oldVar < 10000 then
client:ChatPrint("Congratulations! You've reached $10,000!")
elseif newVar >= 100000 and oldVar < 100000 then
client:ChatPrint("Congratulations! You've reached $100,000!")
end
elseif varName == "faction" then
-- Faction change effects
client:SetTeam(newVar)
client:ChatPrint("Faction changed to: " .. newVar)
-- Notify other players
for _, ply in ipairs(player.GetAll()) do
if ply ~= client then
ply:ChatPrint(character:getName() .. " joined faction: " .. newVar)
end
end
elseif varName == "health" then
-- Health change effects
if newVar <= 0 and oldVar > 0 then
-- Character died
hook.Run("OnCharacterDeath", character)
elseif newVar > 0 and oldVar <= 0 then
-- Character revived
hook.Run("OnCharacterRevive", character)
end
elseif varName == "stamina" then
-- Stamina change effects
if newVar <= 0 and oldVar > 0 then
-- Stamina depleted
hook.Run("PlayerStaminaDepleted", client)
elseif newVar > 0 and oldVar <= 0 then
-- Stamina restored
hook.Run("PlayerStaminaGained", client)
end
end
-- Log significant changes
if math.abs(newVar - oldVar) > 100 or varName == "faction" or varName == "level" then
print(string.format("%s var changed: %s from %s to %s",
character:getName(), varName, tostring(oldVar), tostring(newVar)))
end
end)
OnCharacterCreated
Purpose
Called when a character is created
When Called
When a new character is successfully created
Parameters
character(Character): The character that was createdclient(Player): The player who created the character
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log character creation
hook.Add("OnCharacterCreated", "MyAddon", function(character, client)
print(client:Name() .. " created character: " .. character:getName())
end)
Medium Complexity:
-- Medium: Set up new character bonuses
hook.Add("OnCharacterCreated", "NewCharBonuses", function(character, client)
-- Give starting money bonus
local bonusMoney = 500
character:setMoney(character:getMoney() + bonusMoney)
-- Give starting items
local startingItems = {"wallet", "phone", "id_card"}
for _, itemID in ipairs(startingItems) do
local item = lia.item.instance(itemID)
if item then
character:getInv():add(item)
end
end
client:ChatPrint("Welcome! You received starting bonuses.")
end)
High Complexity:
-- High: Complex character creation system
hook.Add("OnCharacterCreated", "AdvancedCreation", function(character, client)
local faction = character:getFaction()
-- Set up faction-specific starting equipment
local factionEquipment = {
["police"] = {
items = {"police_badge", "handcuffs", "radio"},
money = 1000,
attributes = {str = 5, con = 4, dex = 3}
},
["medic"] = {
items = {"medkit", "stethoscope", "bandage"},
money = 800,
attributes = {int = 6, wis = 5, con = 4}
},
["citizen"] = {
items = {"wallet", "phone"},
money = 500,
attributes = {str = 3, con = 3, dex = 3}
}
}
local equipment = factionEquipment[faction]
if equipment then
-- Give faction-specific money
character:setMoney(character:getMoney() + equipment.money)
-- Give faction-specific items
for _, itemID in ipairs(equipment.items) do
local item = lia.item.instance(itemID)
if item then
character:getInv():add(item)
end
end
-- Set faction-specific attributes
for attr, value in pairs(equipment.attributes) do
character:setAttrib(attr, value)
end
end
-- Set up character data
character:setData("creationTime", os.time())
character:setData("creationIP", client:IPAddress())
character:setData("level", 1)
character:setData("experience", 0)
-- Send welcome message
client:ChatPrint("Character created successfully! Welcome to the server.")
-- Log creation
print(string.format("%s created %s character: %s",
client:Name(), faction, character:getName()))
end)
OnCharacterDeath
Purpose
Called when a character dies
When Called
When a character's health reaches zero or they are killed
Parameters
character(Character): The character that died
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log character death
hook.Add("OnCharacterDeath", "MyAddon", function(character)
print("Character " .. character:getName() .. " has died")
end)
Medium Complexity:
-- Medium: Handle death penalties
hook.Add("OnCharacterDeath", "DeathPenalties", function(character)
local client = character:getPlayer()
if not IsValid(client) then return end
-- Lose some money
local moneyLoss = math.min(character:getMoney() * 0.1, 1000)
character:setMoney(character:getMoney() - moneyLoss)
-- Lose some experience
local expLoss = math.min(character:getData("experience", 0) * 0.05, 100)
character:setData("experience", character:getData("experience", 0) - expLoss)
client:ChatPrint("You lost $" .. moneyLoss .. " and " .. expLoss .. " experience")
end)
High Complexity:
-- High: Complex death system
hook.Add("OnCharacterDeath", "AdvancedDeath", function(character)
local client = character:getPlayer()
if not IsValid(client) then return end
local faction = character:getFaction()
local deathTime = os.time()
-- Set up respawn timer
local respawnTime = 300 -- 5 minutes
if faction == "police" then
respawnTime = 180 -- 3 minutes for police
elseif faction == "medic" then
respawnTime = 240 -- 4 minutes for medics
end
character:setData("deathTime", deathTime)
character:setData("respawnTime", deathTime + respawnTime)
-- Handle inventory
local charInv = character:getInv()
local items = charInv:getItems()
-- Drop some items
local dropChance = 0.3
for _, item in pairs(items) do
if math.random() < dropChance then
charInv:remove(item)
-- Create dropped item entity
local pos = client:GetPos() + Vector(math.random(-50, 50), math.random(-50, 50), 0)
local ent = ents.Create("lia_item")
if IsValid(ent) then
ent:SetPos(pos)
ent:SetItem(item)
ent:Spawn()
end
end
end
-- Handle money loss
local moneyLoss = math.min(character:getMoney() * 0.15, 2000)
character:setMoney(character:getMoney() - moneyLoss)
-- Notify other players
for _, ply in ipairs(player.GetAll()) do
if ply ~= client then
ply:ChatPrint(character:getName() .. " has died")
end
end
-- Log death
print(string.format("%s (%s) died at %s",
character:getName(), faction, os.date("%Y-%m-%d %H:%M:%S")))
end)
OnCharacterDeleted
Purpose
Called when a character is deleted
When Called
When a character is successfully deleted from the database
Parameters
charID(number): The ID of the character that was deletedcharName(string): The name of the character that was deletedowner(Player): The player who owned the characteradmin(Player): The admin who deleted the character (if any)
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log character deletion
hook.Add("OnCharacterDeleted", "MyAddon", function(charID, charName, owner, admin)
print("Character " .. charName .. " (ID: " .. charID .. ") was deleted")
end)
Medium Complexity:
-- Medium: Track deletion statistics
hook.Add("OnCharacterDeleted", "DeletionTracking", function(charID, charName, owner, admin)
if owner then
local char = owner:getChar()
if char then
char:setData("charactersDeleted", (char:getData("charactersDeleted", 0) + 1))
char:setData("lastCharDelete", os.time())
end
end
-- Notify other players
for _, ply in ipairs(player.GetAll()) do
if ply ~= owner then
ply:ChatPrint("Character " .. charName .. " was deleted")
end
end
end)
High Complexity:
-- High: Complex character deletion system
hook.Add("OnCharacterDeleted", "AdvancedDeletion", function(charID, charName, owner, admin)
-- Update deletion statistics
if owner then
local char = owner:getChar()
if char then
char:setData("charactersDeleted", (char:getData("charactersDeleted", 0) + 1))
char:setData("lastCharDelete", os.time())
-- Check for deletion achievement
local deletions = char:getData("charactersDeleted", 0)
if deletions >= 5 and not char:getData("achievement_character_cleaner", false) then
char:setData("achievement_character_cleaner", true)
owner:ChatPrint("Achievement unlocked: Character Cleaner!")
end
end
end
-- Check for admin deletion
if admin then
-- Log admin deletion
print(string.format("Admin %s deleted character %s (ID: %d) owned by %s",
admin:Name(), charName, charID, owner and owner:Name() or "Unknown"))
-- Notify other admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() and ply ~= admin then
ply:ChatPrint("[ADMIN] " .. admin:Name() .. " deleted character " .. charName)
end
end
else
-- Player self-deletion
print(string.format("Player %s deleted character %s (ID: %d)",
owner and owner:Name() or "Unknown", charName, charID))
end
-- Check for faction-specific effects
if owner then
local char = owner:getChar()
if char then
local faction = char:getFaction()
if faction == "police" then
-- Police character deleted
for _, ply in ipairs(player.GetAll()) do
local plyChar = ply:getChar()
if plyChar and plyChar:getFaction() == "police" and ply ~= owner then
ply:ChatPrint("[POLICE] Character " .. charName .. " was deleted")
end
end
elseif faction == "medic" then
-- Medic character deleted
for _, ply in ipairs(player.GetAll()) do
local plyChar = ply:getChar()
if plyChar and plyChar:getFaction() == "medic" and ply ~= owner then
ply:ChatPrint("[MEDICAL] Character " .. charName .. " was deleted")
end
end
end
end
end
-- Notify other players
for _, ply in ipairs(player.GetAll()) do
if ply ~= owner then
ply:ChatPrint("Character " .. charName .. " was deleted")
end
end
-- Log deletion
print(string.format("Character %s (ID: %d) was deleted by %s",
charName, charID, admin and admin:Name() or (owner and owner:Name() or "Unknown")))
end)
OnCharacterFieldsUpdated
Purpose
Called when character fields are updated
When Called
When character field definitions are modified or updated
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log field updates
hook.Add("OnCharacterFieldsUpdated", "MyAddon", function()
print("Character fields have been updated")
end)
Medium Complexity:
-- Medium: Refresh character data
hook.Add("OnCharacterFieldsUpdated", "FieldRefresh", function()
-- Refresh all character data
for _, ply in ipairs(player.GetAll()) do
local char = ply:getChar()
if char then
char:sync()
end
end
print("Character fields updated and synced to all players")
end)
High Complexity:
-- High: Complex field update system
hook.Add("OnCharacterFieldsUpdated", "AdvancedFieldUpdate", function()
-- Refresh all character data
for _, ply in ipairs(player.GetAll()) do
local char = ply:getChar()
if char then
char:sync()
end
end
-- Update character field definitions
local fieldDefinitions = lia.char.getFieldDefinitions()
for fieldName, fieldData in pairs(fieldDefinitions) do
-- Validate field data
if not fieldData.type then
print("Warning: Field " .. fieldName .. " missing type definition")
end
if not fieldData.default then
print("Warning: Field " .. fieldName .. " missing default value")
end
end
-- Notify admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("[ADMIN] Character fields have been updated")
end
end
-- Log field update
print("Character fields updated successfully")
end)
OnCharacterLoaded
Purpose
Called when a character is loaded
When Called
When a character is successfully loaded for a player
Parameters
character(Character): The character that was loadedclient(Player): The player whose character was loaded
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log character loading
hook.Add("OnCharacterLoaded", "MyAddon", function(character, client)
print(client:Name() .. " loaded character: " .. character:getName())
end)
Medium Complexity:
-- Medium: Set up character data
hook.Add("OnCharacterLoaded", "CharSetup", function(character, client)
-- Set up character data
character:setData("lastLoad", os.time())
character:setData("loadCount", (character:getData("loadCount", 0) + 1))
-- Set up player model
local model = character:getModel()
if model then
client:SetModel(model)
end
client:ChatPrint("Character loaded: " .. character:getName())
end)
High Complexity:
-- High: Complex character loading system
hook.Add("OnCharacterLoaded", "AdvancedCharLoading", function(character, client)
-- Set up character data
character:setData("lastLoad", os.time())
character:setData("loadCount", (character:getData("loadCount", 0) + 1))
-- Set up player model
local model = character:getModel()
if model then
client:SetModel(model)
end
-- Set up player skin
local skin = character:getSkin()
client:SetSkin(skin)
-- Set up player bodygroups
local bodygroups = character:getBodygroups()
for group, value in pairs(bodygroups) do
local index = tonumber(group)
if index then
client:SetBodygroup(index, value)
end
end
-- Set up player team
local faction = character:getFaction()
client:SetTeam(faction)
-- Set up player health and armor
local health = character:getData("health", 100)
local armor = character:getData("armor", 0)
client:SetHealth(health)
client:SetArmor(armor)
-- Set up player stamina
local stamina = character:getData("stamina", 100)
client:setNetVar("stamina", stamina)
-- Set up player money
local money = character:getMoney()
client:setNetVar("money", money)
-- Set up player level
local level = character:getData("level", 1)
client:setNetVar("level", level)
-- Set up player experience
local experience = character:getData("experience", 0)
client:setNetVar("experience", experience)
-- Set up player attributes
local attributes = character:getAttribs()
for attr, value in pairs(attributes) do
client:setNetVar("attr_" .. attr, value)
end
-- Check for returning player bonuses
local lastLoad = character:getData("lastLoad", 0)
local timeSinceLoad = os.time() - lastLoad
if timeSinceLoad > 86400 then -- 24 hours
character:setData("returningPlayerBonus", true)
client:ChatPrint("Welcome back! You have a returning player bonus.")
end
-- Notify other players
for _, ply in ipairs(player.GetAll()) do
if ply ~= client then
ply:ChatPrint(character:getName() .. " has joined the server")
end
end
-- Log character load
print(string.format("%s loaded character %s (Faction: %s, Level: %d)",
client:Name(), character:getName(), faction, level))
end)
OnCharacterRevive
Purpose
Called when a character is revived
When Called
When a character is brought back to life from unconsciousness
Parameters
character(Character): The character that was revived
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log character revival
hook.Add("OnCharacterRevive", "MyAddon", function(character)
print(character:getName() .. " was revived")
end)
Medium Complexity:
-- Medium: Handle revival effects
hook.Add("OnCharacterRevive", "RevivalEffects", function(character)
local client = character:getPlayer()
if client then
-- Clear unconscious status
character:setData("unconscious", false)
character:setData("revivalTime", os.time())
-- Restore some health
local currentHealth = client:Health()
local maxHealth = client:GetMaxHealth()
client:SetHealth(math.min(currentHealth + 50, maxHealth))
client:ChatPrint("You have been revived!")
end
end)
High Complexity:
-- High: Complex revival system
hook.Add("OnCharacterRevive", "AdvancedRevival", function(character)
local client = character:getPlayer()
if not client then return end
-- Clear unconscious status
character:setData("unconscious", false)
character:setData("revivalTime", os.time())
-- Restore health based on faction
local faction = character:getFaction()
local healthRestore = {
["police"] = 75,
["medic"] = 100,
["citizen"] = 50
}
local restoreAmount = healthRestore[faction] or 50
local currentHealth = client:Health()
local maxHealth = client:GetMaxHealth()
client:SetHealth(math.min(currentHealth + restoreAmount, maxHealth))
-- Restore stamina
local currentStamina = client:getNetVar("stamina", 100)
client:setNetVar("stamina", math.min(currentStamina + 75, 100))
-- Resume active effects
local activeEffects = character:getData("activeEffects", {})
for _, effect in ipairs(activeEffects) do
if effect.paused then
effect.paused = false
effect.pauseTime = nil
end
end
character:setData("activeEffects", activeEffects)
-- Resume active quests
local activeQuests = character:getData("activeQuests", {})
for _, quest in ipairs(activeQuests) do
if quest.paused then
quest.paused = false
quest.pauseTime = nil
end
end
character:setData("activeQuests", activeQuests)
-- Check for revival achievements
local revivals = character:getData("revivals", 0) + 1
character:setData("revivals", revivals)
if revivals >= 5 and not character:getData("achievement_survivor", false) then
character:setData("achievement_survivor", true)
client:ChatPrint("Achievement unlocked: Survivor!")
end
-- Check for faction-specific revival effects
if faction == "police" then
-- Police get backup call
for _, ply in ipairs(player.GetAll()) do
local plyChar = ply:getChar()
if plyChar and plyChar:getFaction() == "police" then
ply:ChatPrint("[BACKUP] " .. character:getName() .. " has been revived!")
end
end
elseif faction == "medic" then
-- Medics get medical alert
for _, ply in ipairs(player.GetAll()) do
local plyChar = ply:getChar()
if plyChar and plyChar:getFaction() == "medic" then
ply:ChatPrint("[MEDICAL] " .. character:getName() .. " has been revived!")
end
end
end
-- Notify nearby players
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(client:GetPos()) < 500 then
ply:ChatPrint(character:getName() .. " has been revived!")
end
end
-- Log revival
print(string.format("%s was revived (Faction: %s, Health: %d)",
character:getName(), faction, client:Health()))
end)
OnCharacterSchemaValidated
Purpose
Called when character schema validation is completed
When Called
When character schema validation finishes
Parameters
validationResults(table): The results of the schema validation
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log schema validation
hook.Add("OnCharacterSchemaValidated", "MyAddon", function(validationResults)
print("Character schema validation completed")
end)
Medium Complexity:
-- Medium: Handle validation results
hook.Add("OnCharacterSchemaValidated", "SchemaValidation", function(validationResults)
if validationResults.valid then
print("Character schema validation passed")
else
print("Character schema validation failed: " .. validationResults.error)
end
end)
High Complexity:
-- High: Complex schema validation system
hook.Add("OnCharacterSchemaValidated", "AdvancedSchemaValidation", function(validationResults)
if validationResults.valid then
print("Character schema validation passed")
-- Update character field definitions
local fieldDefinitions = validationResults.fieldDefinitions
for fieldName, fieldData in pairs(fieldDefinitions) do
-- Validate field data
if not fieldData.type then
print("Warning: Field " .. fieldName .. " missing type definition")
end
if not fieldData.default then
print("Warning: Field " .. fieldName .. " missing default value")
end
end
-- Notify admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("[ADMIN] Character schema validation passed")
end
end
else
print("Character schema validation failed: " .. validationResults.error)
-- Notify admins of validation failure
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("[ADMIN] Character schema validation failed: " .. validationResults.error)
end
end
end
-- Log validation results
print(string.format("Character schema validation completed: %s",
validationResults.valid and "PASSED" or "FAILED"))
end)
OnCharacterUpdated
Purpose
Called when a character is updated
When Called
When a character's data is modified and saved
Parameters
charID(number): The ID of the character that was updatedupdateData(table): The data that was updated
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log character updates
hook.Add("OnCharacterUpdated", "MyAddon", function(charID, updateData)
print("Character " .. charID .. " was updated")
end)
Medium Complexity:
-- Medium: Track update statistics
hook.Add("OnCharacterUpdated", "UpdateTracking", function(charID, updateData)
-- Track update count
local updateCount = lia.char.getData("updateCount", 0) + 1
lia.char.setData("updateCount", updateCount)
-- Track last update time
lia.char.setData("lastUpdate", os.time())
end)
High Complexity:
-- High: Complex character update system
hook.Add("OnCharacterUpdated", "AdvancedCharacterUpdate", function(charID, updateData)
-- Get character
local character = lia.char.getByID(charID)
if not character then return end
-- Track update count
local updateCount = character:getData("updateCount", 0) + 1
character:setData("updateCount", updateCount)
-- Track last update time
character:setData("lastUpdate", os.time())
-- Track update history
local updateHistory = character:getData("updateHistory", {})
table.insert(updateHistory, {
data = updateData,
timestamp = os.time()
})
-- Keep only last 50 updates
if #updateHistory > 50 then
table.remove(updateHistory, 1)
end
character:setData("updateHistory", updateHistory)
-- Check for specific updates
if updateData.level then
-- Level update
local oldLevel = character:getData("oldLevel", 1)
if updateData.level > oldLevel then
hook.Run("OnPlayerLevelUp", character:getPlayer(), oldLevel, updateData.level)
end
character:setData("oldLevel", updateData.level)
end
if updateData.money then
-- Money update
local oldMoney = character:getData("oldMoney", 0)
local difference = updateData.money - oldMoney
if difference > 0 then
character:getPlayer():ChatPrint("You gained $" .. difference)
elseif difference < 0 then
character:getPlayer():ChatPrint("You lost $" .. math.abs(difference))
end
character:setData("oldMoney", updateData.money)
end
if updateData.faction then
-- Faction update
local oldFaction = character:getData("oldFaction", "citizen")
if updateData.faction ~= oldFaction then
character:getPlayer():SetTeam(updateData.faction)
character:getPlayer():ChatPrint("Faction changed to: " .. updateData.faction)
end
character:setData("oldFaction", updateData.faction)
end
-- Check for update achievements
if updateCount >= 100 and not character:getData("achievement_updater", false) then
character:setData("achievement_updater", true)
character:getPlayer():ChatPrint("Achievement unlocked: Updater!")
end
-- Log update
print(string.format("Character %s (ID: %d) was updated",
character:getName(), charID))
end)
OnCharactersRestored
Purpose
Called when characters are restored from backup
When Called
When character data is restored from a backup
Parameters
client(Player): The player whose characters were restoredcharacters(table): The restored character datastats(table): The restored character statistics
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log character restoration
hook.Add("OnCharactersRestored", "MyAddon", function(client, characters, stats)
print(client:Name() .. " had " .. #characters .. " characters restored")
end)
Medium Complexity:
-- Medium: Handle restoration effects
hook.Add("OnCharactersRestored", "RestorationEffects", function(client, characters, stats)
-- Notify player
client:ChatPrint("Your characters have been restored from backup")
-- Update character list
client.liaCharList = characters
-- Notify other players
for _, ply in ipairs(player.GetAll()) do
if ply ~= client then
ply:ChatPrint(client:Name() .. " had characters restored")
end
end
end)
High Complexity:
-- High: Complex character restoration system
hook.Add("OnCharactersRestored", "AdvancedCharacterRestoration", function(client, characters, stats)
-- Update character list
client.liaCharList = characters
-- Update character statistics
for charID, charStats in pairs(stats) do
local character = lia.char.getByID(charID)
if character then
character:setData("restoredStats", charStats)
character:setData("restorationTime", os.time())
end
end
-- Check for restoration achievements
local char = client:getChar()
if char then
local restorations = char:getData("restorations", 0) + 1
char:setData("restorations", restorations)
if restorations >= 5 and not char:getData("achievement_restorer", false) then
char:setData("achievement_restorer", true)
client:ChatPrint("Achievement unlocked: Restorer!")
end
end
-- Check for faction-specific restoration
local faction = char and char:getFaction()
if faction == "police" then
-- Police restoration
for _, ply in ipairs(player.GetAll()) do
local plyChar = ply:getChar()
if plyChar and plyChar:getFaction() == "police" and ply ~= client then
ply:ChatPrint("[POLICE] " .. client:Name() .. " had characters restored")
end
end
elseif faction == "medic" then
-- Medic restoration
for _, ply in ipairs(player.GetAll()) do
local plyChar = ply:getChar()
if plyChar and plyChar:getFaction() == "medic" and ply ~= client then
ply:ChatPrint("[MEDICAL] " .. client:Name() .. " had characters restored")
end
end
end
-- Notify player
client:ChatPrint("Your characters have been restored from backup")
-- Notify other players
for _, ply in ipairs(player.GetAll()) do
if ply ~= client then
ply:ChatPrint(client:Name() .. " had characters restored")
end
end
-- Log restoration
print(string.format("%s had %d characters restored",
client:Name(), #characters))
end)
OnCheaterCaught
Purpose
Called when a cheater is caught
When Called
When anti-cheat systems detect cheating behavior
Parameters
client(Player): The player who was caught cheating
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log cheater detection
hook.Add("OnCheaterCaught", "MyAddon", function(client)
print("Cheater caught: " .. client:Name())
end)
Medium Complexity:
-- Medium: Handle cheater punishment
hook.Add("OnCheaterCaught", "CheaterPunishment", function(client)
-- Kick the cheater
client:Kick("Cheating detected")
-- Notify admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("[ADMIN] Cheater caught: " .. client:Name())
end
end
end)
High Complexity:
-- High: Complex anti-cheat system
hook.Add("OnCheaterCaught", "AdvancedAntiCheat", function(client)
-- Get cheater data
local char = client:getChar()
local steamID = client:SteamID()
local ip = client:IPAddress()
-- Log cheater information
print(string.format("Cheater caught: %s (SteamID: %s, IP: %s)",
client:Name(), steamID, ip))
-- Add to cheater database
local cheaterData = {
name = client:Name(),
steamID = steamID,
ip = ip,
timestamp = os.time(),
charID = char and char:getID() or 0
}
-- Store cheater data
lia.data.set("cheaters", steamID, cheaterData)
-- Kick the cheater
client:Kick("Cheating detected - You have been banned")
-- Notify all admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("[ADMIN] Cheater caught: " .. client:Name())
ply:ChatPrint("[ADMIN] SteamID: " .. steamID)
ply:ChatPrint("[ADMIN] IP: " .. ip)
end
end
-- Log to file
local logFile = "cheaters.txt"
local logData = string.format("[%s] %s (SteamID: %s, IP: %s)\n",
os.date("%Y-%m-%d %H:%M:%S"), client:Name(), steamID, ip)
-- Write to log file
file.Append(logFile, logData)
-- Check for repeat offenders
local cheaterHistory = lia.data.get("cheaterHistory", {})
cheaterHistory[steamID] = (cheaterHistory[steamID] or 0) + 1
lia.data.set("cheaterHistory", cheaterHistory)
if cheaterHistory[steamID] >= 3 then
-- Repeat offender
print(string.format("Repeat cheater: %s (SteamID: %s) - %d offenses",
client:Name(), steamID, cheaterHistory[steamID]))
end
end)
OnCheaterStatusChanged
Purpose
Called when a cheater's status changes
When Called
When a player's cheater status is modified
Parameters
client(Player): The player whose status changedtarget(Player): The target player (if applicable)status(string): The new cheater status
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log cheater status changes
hook.Add("OnCheaterStatusChanged", "MyAddon", function(client, target, status)
print(client:Name() .. " cheater status changed to: " .. status)
end)
Medium Complexity:
-- Medium: Handle status change effects
hook.Add("OnCheaterStatusChanged", "StatusChangeEffects", function(client, target, status)
if status == "banned" then
client:Kick("You have been banned for cheating")
elseif status == "warned" then
client:ChatPrint("Warning: Cheating behavior detected")
elseif status == "cleared" then
client:ChatPrint("Your cheater status has been cleared")
end
end)
High Complexity:
-- High: Complex cheater status system
hook.Add("OnCheaterStatusChanged", "AdvancedCheaterStatus", function(client, target, status)
local char = client:getChar()
if not char then return end
-- Update cheater status
char:setData("cheaterStatus", status)
char:setData("statusChangeTime", os.time())
-- Handle status-specific effects
if status == "banned" then
-- Ban the player
client:Kick("You have been banned for cheating")
-- Add to ban database
local banData = {
steamID = client:SteamID(),
name = client:Name(),
reason = "Cheating",
timestamp = os.time(),
admin = target and target:Name() or "System"
}
lia.data.set("bans", client:SteamID(), banData)
-- Notify admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("[ADMIN] " .. client:Name() .. " has been banned for cheating")
end
end
elseif status == "warned" then
-- Warn the player
client:ChatPrint("Warning: Cheating behavior detected")
-- Add warning to character
local warnings = char:getData("warnings", 0) + 1
char:setData("warnings", warnings)
-- Check for warning limits
if warnings >= 3 then
client:Kick("You have received too many warnings")
end
-- Notify admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("[ADMIN] " .. client:Name() .. " has been warned for cheating")
end
end
elseif status == "cleared" then
-- Clear cheater status
client:ChatPrint("Your cheater status has been cleared")
-- Clear warnings
char:setData("warnings", 0)
-- Notify admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("[ADMIN] " .. client:Name() .. " cheater status has been cleared")
end
end
end
-- Log status change
print(string.format("Cheater status changed: %s -> %s (Admin: %s)",
client:Name(), status, target and target:Name() or "System"))
end)
OnColumnAdded
Purpose
Called when a database column is added
When Called
When a new column is added to a database table
Parameters
column(string): The name of the column that was addeddata(table): The column data and properties
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log column additions
hook.Add("OnColumnAdded", "MyAddon", function(column, data)
print("Column added: " .. column)
end)
Medium Complexity:
-- Medium: Handle column additions
hook.Add("OnColumnAdded", "ColumnHandling", function(column, data)
if column == "level" then
print("Level column added to character table")
elseif column == "money" then
print("Money column added to character table")
end
end)
High Complexity:
-- High: Complex column addition system
hook.Add("OnColumnAdded", "AdvancedColumnAddition", function(column, data)
-- Log column addition
print(string.format("Column added: %s (Type: %s, Default: %s)",
column, data.type or "unknown", tostring(data.default or "none")))
-- Handle specific column types
if data.type == "INTEGER" then
-- Integer column
print("Integer column added: " .. column)
elseif data.type == "TEXT" then
-- Text column
print("Text column added: " .. column)
elseif data.type == "BOOLEAN" then
-- Boolean column
print("Boolean column added: " .. column)
end
-- Check for required columns
local requiredColumns = {"id", "name", "steamid", "faction"}
if table.HasValue(requiredColumns, column) then
print("Required column added: " .. column)
end
-- Update column definitions
local columnDefinitions = lia.data.get("columnDefinitions", {})
columnDefinitions[column] = data
lia.data.set("columnDefinitions", columnDefinitions)
-- Notify admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("[ADMIN] Database column added: " .. column)
end
end
end)
OnColumnRemoved
Purpose
Called when a database column is removed
When Called
When a column is removed from a database table
Parameters
tableName(string): The name of the table the column was removed fromcolumnName(string): The name of the column that was removedsnapshot(table): A snapshot of the data before removal
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log column removals
hook.Add("OnColumnRemoved", "MyAddon", function(tableName, columnName, snapshot)
print("Column removed: " .. columnName .. " from " .. tableName)
end)
Medium Complexity:
-- Medium: Handle column removals
hook.Add("OnColumnRemoved", "ColumnRemovalHandling", function(tableName, columnName, snapshot)
if tableName == "characters" then
print("Character column removed: " .. columnName)
elseif tableName == "players" then
print("Player column removed: " .. columnName)
end
-- Log snapshot data
if snapshot then
print("Snapshot contains " .. #snapshot .. " records")
end
end)
High Complexity:
-- High: Complex column removal system
hook.Add("OnColumnRemoved", "AdvancedColumnRemoval", function(tableName, columnName, snapshot)
-- Log column removal
print(string.format("Column removed: %s from %s (Snapshot: %s)",
columnName, tableName, snapshot and "Yes" or "No"))
-- Handle specific table removals
if tableName == "characters" then
print("Character table column removed: " .. columnName)
-- Check if it's a critical column
local criticalColumns = {"id", "name", "steamid"}
if table.HasValue(criticalColumns, columnName) then
print("WARNING: Critical column removed from characters table!")
end
elseif tableName == "players" then
print("Player table column removed: " .. columnName)
end
-- Update column definitions
local columnDefinitions = lia.data.get("columnDefinitions", {})
if columnDefinitions[columnName] then
columnDefinitions[columnName] = nil
lia.data.set("columnDefinitions", columnDefinitions)
end
-- Handle snapshot data
if snapshot then
-- Store snapshot for potential restoration
local snapshotData = {
tableName = tableName,
columnName = columnName,
data = snapshot,
timestamp = os.time()
}
lia.data.set("columnSnapshots", columnName, snapshotData)
print("Snapshot stored for potential restoration")
end
-- Notify admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("[ADMIN] Database column removed: " .. columnName .. " from " .. tableName)
end
end
end)
OnConfigUpdated
Purpose
Called when a configuration is updated
When Called
When a configuration value is changed
Parameters
key(string): The configuration key that was updatedoldValue(any): The previous valuevalue(any): The new value
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log config updates
hook.Add("OnConfigUpdated", "MyAddon", function(key, oldValue, value)
print("Config updated: " .. key .. " = " .. tostring(value))
end)
Medium Complexity:
-- Medium: Handle specific config changes
hook.Add("OnConfigUpdated", "ConfigHandling", function(key, oldValue, value)
if key == "maxPlayers" then
game.MaxPlayers = value
elseif key == "serverName" then
RunConsoleCommand("hostname", value)
end
end)
High Complexity:
-- High: Complex config update system
hook.Add("OnConfigUpdated", "AdvancedConfigUpdate", function(key, oldValue, value)
-- Log config change
print(string.format("Config updated: %s from %s to %s",
key, tostring(oldValue), tostring(value)))
-- Handle specific config changes
if key == "maxPlayers" then
game.MaxPlayers = value
print("Max players updated to: " .. value)
elseif key == "serverName" then
RunConsoleCommand("hostname", value)
print("Server name updated to: " .. value)
elseif key == "password" then
if value and value ~= "" then
RunConsoleCommand("sv_password", value)
print("Server password set")
else
RunConsoleCommand("sv_password", "")
print("Server password removed")
end
end
-- Update config cache
lia.configCache = lia.configCache or {}
lia.configCache[key] = {
value = value,
oldValue = oldValue,
timestamp = os.time()
}
-- Notify admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("[CONFIG] " .. key .. " changed to: " .. tostring(value))
end
end
end)
OnCreatePlayerRagdoll
Purpose
Called when creating a player ragdoll
When Called
When a player ragdoll is being created
Parameters
self(Player): The player whose ragdoll is being createdentity(Entity): The ragdoll entityisDead(boolean): Whether the player is dead
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log ragdoll creation
hook.Add("OnCreatePlayerRagdoll", "MyAddon", function(self, entity, isDead)
print(self:Name() .. " ragdoll created")
end)
Medium Complexity:
-- Medium: Set up ragdoll data
hook.Add("OnCreatePlayerRagdoll", "RagdollSetup", function(self, entity, isDead)
entity:setNetVar("owner", self:SteamID())
entity:setNetVar("isDead", isDead)
entity:setNetVar("deathTime", os.time())
end)
High Complexity:
-- High: Complex ragdoll creation system
hook.Add("OnCreatePlayerRagdoll", "AdvancedRagdollCreation", function(self, entity, isDead)
local char = self:getChar()
if not char then return end
-- Set up ragdoll data
entity:setNetVar("owner", self:SteamID())
entity:setNetVar("isDead", isDead)
entity:setNetVar("deathTime", os.time())
entity:setNetVar("charID", char:getID())
entity:setNetVar("charName", char:getName())
entity:setNetVar("faction", char:getFaction())
-- Set up ragdoll appearance
entity:SetModel(self:GetModel())
entity:SetSkin(self:GetSkin())
-- Set up bodygroups
for i = 0, self:GetNumBodyGroups() - 1 do
entity:SetBodygroup(i, self:GetBodygroup(i))
end
-- Set up ragdoll position and angles
entity:SetPos(self:GetPos())
entity:SetAngles(self:GetAngles())
-- Apply faction-specific effects
local faction = char:getFaction()
if faction == "police" then
entity:SetColor(Color(0, 0, 255, 200))
elseif faction == "medic" then
entity:SetColor(Color(255, 255, 255, 200))
end
-- Set up ragdoll physics
local phys = entity:GetPhysicsObject()
if IsValid(phys) then
phys:SetVelocity(self:GetVelocity())
end
-- Log ragdoll creation
print(string.format("Ragdoll created for %s (Faction: %s, Dead: %s)",
self:Name(), faction, tostring(isDead)))
end)
OnDataSet
Purpose
Called when data is set
When Called
When persistent data is being saved
Parameters
key(string): The data keyvalue(any): The data valuegamemode(string): The gamemode namemap(string): The map name
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log data setting
hook.Add("OnDataSet", "MyAddon", function(key, value, gamemode, map)
print("Data set: " .. key .. " = " .. tostring(value))
end)
Medium Complexity:
-- Medium: Validate data before saving
hook.Add("OnDataSet", "DataValidation", function(key, value, gamemode, map)
if key == "playerMoney" and type(value) ~= "number" then
print("Invalid money value: " .. tostring(value))
return false
end
if key == "playerLevel" and (value < 1 or value > 100) then
print("Invalid level value: " .. tostring(value))
return false
end
end)
High Complexity:
-- High: Complex data management system
hook.Add("OnDataSet", "AdvancedDataManagement", function(key, value, gamemode, map)
-- Log data changes
print(string.format("Data set: %s = %s (Gamemode: %s, Map: %s)",
key, tostring(value), gamemode, map))
-- Validate data types
local dataTypes = {
["playerMoney"] = "number",
["playerLevel"] = "number",
["playerName"] = "string",
["playerFaction"] = "string"
}
local expectedType = dataTypes[key]
if expectedType and type(value) ~= expectedType then
print("Type mismatch for " .. key .. ": expected " .. expectedType .. ", got " .. type(value))
return false
end
-- Validate value ranges
if key == "playerMoney" and (value < 0 or value > 1000000) then
print("Money value out of range: " .. value)
return false
end
if key == "playerLevel" and (value < 1 or value > 100) then
print("Level value out of range: " .. value)
return false
end
-- Update data cache
lia.dataCache = lia.dataCache or {}
lia.dataCache[key] = {
value = value,
timestamp = os.time(),
gamemode = gamemode,
map = map
}
-- Notify admins of important changes
local importantKeys = {"playerMoney", "playerLevel", "playerFaction"}
if table.HasValue(importantKeys, key) then
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("[DATA] " .. key .. " set to " .. tostring(value))
end
end
end
end)
OnDatabaseConnected
Purpose
Called when database connection is established
When Called
When the database connection is successfully made
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log database connection
hook.Add("OnDatabaseConnected", "MyAddon", function()
print("Database connected successfully")
end)
Medium Complexity:
-- Medium: Initialize database tables
hook.Add("OnDatabaseConnected", "DatabaseInit", function()
-- Create necessary tables
lia.db.query("CREATE TABLE IF NOT EXISTS players (id INTEGER PRIMARY KEY, steamid TEXT, name TEXT)")
lia.db.query("CREATE TABLE IF NOT EXISTS characters (id INTEGER PRIMARY KEY, playerid INTEGER, name TEXT)")
print("Database connected and tables initialized")
end)
High Complexity:
-- High: Complex database initialization system
hook.Add("OnDatabaseConnected", "AdvancedDatabaseInit", function()
-- Log connection
print("Database connected successfully")
-- Create core tables
local tables = {
players = "CREATE TABLE IF NOT EXISTS players (id INTEGER PRIMARY KEY, steamid TEXT UNIQUE, name TEXT, lastseen INTEGER)"
characters = "CREATE TABLE IF NOT EXISTS characters (id INTEGER PRIMARY KEY, playerid INTEGER, name TEXT, faction TEXT, money INTEGER)"
items = "CREATE TABLE IF NOT EXISTS items (id INTEGER PRIMARY KEY, charid INTEGER, itemid TEXT, data TEXT)"
logs = "CREATE TABLE IF NOT EXISTS logs (id INTEGER PRIMARY KEY, timestamp INTEGER, type TEXT, message TEXT)"
}
for tableName, query in pairs(tables) do
lia.db.query(query)
print("Created table: " .. tableName)
end
-- Create indexes for performance
local indexes = {
"CREATE INDEX IF NOT EXISTS idx_players_steamid ON players(steamid)"
"CREATE INDEX IF NOT EXISTS idx_characters_playerid ON characters(playerid)"
"CREATE INDEX IF NOT EXISTS idx_items_charid ON items(charid)"
"CREATE INDEX IF NOT EXISTS idx_logs_timestamp ON logs(timestamp)"
}
for _, indexQuery in ipairs(indexes) do
lia.db.query(indexQuery)
end
-- Initialize database statistics
lia.data.set("dbStats", {
connected = true,
connectTime = os.time(),
tablesCreated = #tables,
indexesCreated = #indexes
})
-- Notify all players
for _, ply in ipairs(player.GetAll()) do
ply:ChatPrint("Database connected successfully")
end
print("Database initialization completed")
end)
OnDatabaseInitialized
Purpose
Called when the database is initialized
When Called
After the database connection is established and tables are created
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log database initialization
hook.Add("OnDatabaseInitialized", "MyAddon", function()
print("Database has been initialized")
end)
Medium Complexity:
-- Medium: Setup custom tables
hook.Add("OnDatabaseInitialized", "SetupCustomTables", function()
lia.db.query("CREATE TABLE IF NOT EXISTS addon_data (id INT PRIMARY KEY, data TEXT)")
print("Custom tables created")
end)
High Complexity:
-- High: Complex database initialization
hook.Add("OnDatabaseInitialized", "AdvancedDBInit", function()
-- Create custom tables
lia.db.query("CREATE TABLE IF NOT EXISTS player_stats (steamid VARCHAR(255) PRIMARY KEY, kills INT, deaths INT, playtime INT)")
lia.db.query("CREATE TABLE IF NOT EXISTS server_logs (id INT PRIMARY KEY, player VARCHAR(255), action TEXT, timestamp INT)")
-- Load initial data
lia.data.get("serverConfig", {}, function(config)
MyAddon.config = config
end)
-- Setup periodic cleanup
timer.Create("DatabaseCleanup", 3600, 0, function()
lia.db.query("DELETE FROM server_logs WHERE timestamp < ?", os.time() - 604800)
end)
print("Advanced database initialization complete")
end)
OnDatabaseLoaded
Purpose
Called when the database has finished loading all data
When Called
After all database operations and data loading is complete
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log database loaded
hook.Add("OnDatabaseLoaded", "MyAddon", function()
print("Database loading complete")
end)
Medium Complexity:
-- Medium: Initialize addon after DB load
hook.Add("OnDatabaseLoaded", "InitAfterDB", function()
MyAddon:Initialize()
print("Addon initialized after database load")
end)
High Complexity:
-- High: Complex post-database initialization
hook.Add("OnDatabaseLoaded", "AdvancedPostDBInit", function()
-- Load all cached data
lia.data.get("allData", {}, function(data)
MyAddon.cache = data
end)
-- Initialize player statistics
for _, ply in ipairs(player.GetAll()) do
local char = ply:getChar()
if char then
char:loadStats()
end
end
-- Start background processes
timer.Create("DataSync", 300, 0, function()
MyAddon:SyncData()
end)
print("All systems initialized after database load")
end)
OnDatabaseReset
Purpose
Called when the database is reset
When Called
When the database is reset to default state
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log database reset
hook.Add("OnDatabaseReset", "MyAddon", function()
print("Database has been reset")
end)
Medium Complexity:
-- Medium: Clear addon data
hook.Add("OnDatabaseReset", "ClearAddonData", function()
MyAddon.data = {}
MyAddon.cache = {}
print("Addon data cleared")
end)
High Complexity:
-- High: Complex database reset handling
hook.Add("OnDatabaseReset", "AdvancedDBReset", function()
-- Log database reset
lia.log.write("database_reset", {
timestamp = os.time(),
admin = "System"
})
-- Clear all addon data
lia.data.delete("addonData")
lia.data.delete("playerStats")
-- Reset all player data
for _, ply in ipairs(player.GetAll()) do
local char = ply:getChar()
if char then
char:setData("stats", {})
char:setData("achievements", {})
end
end
-- Notify all players
for _, ply in ipairs(player.GetAll()) do
ply:ChatPrint("Server data has been reset")
end
print("Complete database reset performed")
end)
OnDatabaseWiped
Purpose
Called when the database is completely wiped
When Called
When all database data is permanently deleted
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log database wipe
hook.Add("OnDatabaseWiped", "MyAddon", function()
print("Database has been wiped")
end)
Medium Complexity:
-- Medium: Reset addon state
hook.Add("OnDatabaseWiped", "ResetAddonState", function()
MyAddon:Reset()
print("Addon state reset after database wipe")
end)
High Complexity:
-- High: Complex database wipe handling
hook.Add("OnDatabaseWiped", "AdvancedDBWipe", function()
-- Log database wipe
lia.log.write("database_wiped", {
timestamp = os.time(),
admin = "System"
})
-- Clear all addon data
MyAddon.data = {}
MyAddon.cache = {}
MyAddon.playerStats = {}
-- Reset all player characters
for _, ply in ipairs(player.GetAll()) do
ply:Kick("Server data has been wiped")
end
-- Recreate essential tables
lia.db.query("CREATE TABLE IF NOT EXISTS lia_characters (id INTEGER PRIMARY KEY, steamid VARCHAR(255), name VARCHAR(255))")
print("Complete database wipe performed")
end)
OnEntityLoaded
Purpose
Called when an entity is loaded from the database
When Called
When an entity is restored from saved data
Parameters
createdEnt(Entity): The entity that was createddata(table): The saved entity data
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log entity loading
hook.Add("OnEntityLoaded", "MyAddon", function(createdEnt, data)
print("Entity loaded: " .. tostring(createdEnt))
end)
Medium Complexity:
-- Medium: Track loaded entities
hook.Add("OnEntityLoaded", "TrackEntities", function(createdEnt, data)
MyAddon.loadedEntities = MyAddon.loadedEntities or {}
table.insert(MyAddon.loadedEntities, {
entity = createdEnt,
class = createdEnt:GetClass(),
time = os.time()
})
end)
High Complexity:
-- High: Complex entity loading handling
hook.Add("OnEntityLoaded", "AdvancedEntityLoading", function(createdEnt, data)
-- Log entity loading
lia.log.write("entity_loaded", {
class = createdEnt:GetClass(),
position = createdEnt:GetPos(),
timestamp = os.time()
})
-- Restore custom data
if data.customData then
createdEnt:SetCustomData(data.customData)
end
-- Setup entity-specific behavior
if createdEnt:GetClass() == "lia_item" then
createdEnt:SetupItemData(data.itemData)
end
-- Notify entity of loading
if createdEnt.OnLoaded then
createdEnt:OnLoaded(data)
end
end)
OnEntityPersistUpdated
Purpose
Called when an entity's persistent data is updated
When Called
When an entity's save data is modified
Parameters
ent(Entity): The entity being updateddata(table): The updated persistent data
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log entity updates
hook.Add("OnEntityPersistUpdated", "MyAddon", function(ent, data)
print("Entity data updated: " .. tostring(ent))
end)
Medium Complexity:
-- Medium: Track entity changes
hook.Add("OnEntityPersistUpdated", "TrackEntityChanges", function(ent, data)
MyAddon.entityChanges = MyAddon.entityChanges or {}
table.insert(MyAddon.entityChanges, {
entity = ent,
data = data,
time = os.time()
})
end)
High Complexity:
-- High: Complex entity update handling
hook.Add("OnEntityPersistUpdated", "AdvancedEntityUpdate", function(ent, data)
-- Log entity update
lia.log.write("entity_persist_updated", {
class = ent:GetClass(),
position = ent:GetPos(),
data = util.TableToJSON(data),
timestamp = os.time()
})
-- Validate data integrity
if data.position and not data.position.x then
print("Warning: Invalid position data for entity " .. tostring(ent))
end
-- Update entity-specific data
if ent.OnPersistDataUpdated then
ent:OnPersistDataUpdated(data)
end
-- Sync to clients if needed
if data.syncToClients then
net.Start("liaEntityDataUpdate")
net.WriteEntity(ent)
net.WriteTable(data)
net.Broadcast()
end
end)
OnEntityPersisted
Purpose
Called when an entity is persisted to the database
When Called
When an entity's data is saved to the database
Parameters
ent(Entity): The entity being savedentData(table): The entity data being saved
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log entity persistence
hook.Add("OnEntityPersisted", "MyAddon", function(ent, entData)
print("Entity persisted: " .. tostring(ent))
end)
Medium Complexity:
-- Medium: Track entity saves
hook.Add("OnEntityPersisted", "TrackEntitySaves", function(ent, entData)
MyAddon.savedEntities = MyAddon.savedEntities or {}
table.insert(MyAddon.savedEntities, {
entity = ent,
class = ent:GetClass(),
time = os.time()
})
end)
High Complexity:
-- High: Complex entity persistence handling
hook.Add("OnEntityPersisted", "AdvancedEntityPersistence", function(ent, entData)
-- Log entity persistence
lia.log.write("entity_persisted", {
class = ent:GetClass(),
position = ent:GetPos(),
data = util.TableToJSON(entData),
timestamp = os.time()
})
-- Validate data before saving
if not entData.position or not entData.angles then
print("Warning: Incomplete entity data for " .. tostring(ent))
end
-- Add custom persistence data
if ent.GetCustomPersistenceData then
entData.customData = ent:GetCustomPersistenceData()
end
-- Update entity statistics
local stats = lia.data.get("entityStats", {})
stats[ent:GetClass()] = (stats[ent:GetClass()] or 0) + 1
lia.data.set("entityStats", stats)
end)
OnItemAdded
Purpose
Called when an item is added to an inventory
When Called
When an item is successfully added to any inventory
Parameters
owner(Player|Character): The owner of the inventoryitem(Item): The item that was added
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log item additions
hook.Add("OnItemAdded", "MyAddon", function(owner, item)
print("Item " .. item.uniqueID .. " added to inventory")
end)
Medium Complexity:
-- Medium: Handle special item effects
hook.Add("OnItemAdded", "ItemEffects", function(owner, item)
local char = owner:getChar()
if not char then return end
if item.uniqueID == "health_potion" then
char:setData("healthBonus", (char:getData("healthBonus", 0) + 10))
elseif item.uniqueID == "stamina_boost" then
char:setData("staminaBonus", (char:getData("staminaBonus", 0) + 5))
end
end)
High Complexity:
-- High: Complex item management system
hook.Add("OnItemAdded", "AdvancedItems", function(owner, item)
local char = owner:getChar()
if not char then return end
local client = char:getPlayer()
if not IsValid(client) then return end
-- Check for set bonuses
local inventory = char:getInv()
local items = inventory:getItems()
-- Check for armor set
local armorPieces = 0
for _, invItem in pairs(items) do
if string.find(invItem.uniqueID, "armor_") then
armorPieces = armorPieces + 1
end
end
if armorPieces >= 3 then
char:setData("armorSetBonus", true)
client:ChatPrint("Armor set bonus activated!")
end
-- Check for weapon upgrades
if item.uniqueID == "weapon_upgrade" then
local weapon = inventory:hasItem("weapon_pistol")
if weapon then
weapon:setData("damage", (weapon:getData("damage", 10) + 5))
client:ChatPrint("Weapon upgraded!")
end
end
-- Check for quest items
if item:getData("questItem", false) then
local questID = item:getData("questID")
if questID then
char:setData("questProgress", char:getData("questProgress", {})[questID] + 1)
client:ChatPrint("Quest progress updated!")
end
end
-- Update inventory weight
local itemWeight = item:getData("weight", 1)
local currentWeight = char:getData("currentWeight", 0)
char:setData("currentWeight", currentWeight + itemWeight)
end)
OnItemCreated
Purpose
Called when an item instance is created
When Called
When a new item instance is created from an item table
Parameters
itemTable(table): The item table definitionself(Item): The item instance being created
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log item creation
hook.Add("OnItemCreated", "MyAddon", function(itemTable, self)
print("Item created: " .. itemTable.uniqueID)
end)
Medium Complexity:
-- Medium: Set up item-specific data
hook.Add("OnItemCreated", "ItemSetup", function(itemTable, self)
if itemTable.uniqueID == "weapon_pistol" then
self:setData("ammo", 12)
self:setData("damage", 25)
elseif itemTable.uniqueID == "health_potion" then
self:setData("healAmount", 50)
self:setData("uses", 3)
end
end)
High Complexity:
-- High: Complex item creation system
hook.Add("OnItemCreated", "AdvancedItemCreation", function(itemTable, self)
local char = self:getOwner()
if not char then return end
-- Set up item quality
local quality = self:getData("quality", "common")
local qualityMultipliers = {
["common"] = 1.0,
["uncommon"] = 1.2,
["rare"] = 1.5,
["epic"] = 2.0,
["legendary"] = 3.0
}
local multiplier = qualityMultipliers[quality] or 1.0
-- Apply quality bonuses
if itemTable.uniqueID == "weapon_pistol" then
local baseDamage = 25
self:setData("damage", math.floor(baseDamage * multiplier))
self:setData("durability", math.floor(100 * multiplier))
elseif itemTable.uniqueID == "armor_vest" then
local baseProtection = 10
self:setData("protection", math.floor(baseProtection * multiplier))
self:setData("durability", math.floor(200 * multiplier))
end
-- Set up item level
local itemLevel = self:getData("level", 1)
if itemLevel > 1 then
local levelBonus = (itemLevel - 1) * 0.1
local currentValue = self:getData("value", 100)
self:setData("value", math.floor(currentValue * (1 + levelBonus)))
end
-- Set up item enchantments
local enchantments = self:getData("enchantments", {})
if #enchantments > 0 then
for _, enchant in ipairs(enchantments) do
if enchant.type == "fire" then
self:setData("fireDamage", (self:getData("fireDamage", 0) + enchant.value))
elseif enchant.type == "ice" then
self:setData("iceDamage", (self:getData("iceDamage", 0) + enchant.value))
end
end
end
-- Set up item binding
if self:getData("bindOnPickup", false) then
self:setData("boundTo", char:getID())
end
end)
OnItemSpawned
Purpose
Called when an item entity is spawned in the world
When Called
When an item is dropped or spawned as a world entity
Parameters
self(Entity): The item entity that was spawned
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log item spawning
hook.Add("OnItemSpawned", "MyAddon", function(self)
print("Item spawned: " .. self:GetItem().uniqueID)
end)
Medium Complexity:
-- Medium: Set up item physics
hook.Add("OnItemSpawned", "ItemPhysics", function(self)
local item = self:GetItem()
if item.uniqueID == "heavy_box" then
self:SetPhysicsAttacker(self:GetOwner(), 10)
self:GetPhysicsObject():SetMass(100)
elseif item.uniqueID == "fragile_item" then
self:SetPhysicsAttacker(self:GetOwner(), 5)
self:GetPhysicsObject():SetMass(1)
end
end)
High Complexity:
-- High: Complex item spawning system
hook.Add("OnItemSpawned", "AdvancedItemSpawning", function(self)
local item = self:GetItem()
if not item then return end
-- Set up item glow effects
if item:getData("glow", false) then
self:SetMaterial("models/effects/comball_tape")
self:SetColor(Color(255, 255, 0, 255))
end
-- Set up item size
local scale = item:getData("scale", 1.0)
if scale ~= 1.0 then
self:SetModelScale(scale)
end
-- Set up item physics
local physics = self:GetPhysicsObject()
if IsValid(physics) then
local weight = item:getData("weight", 1)
physics:SetMass(weight * 10)
-- Set up friction
local friction = item:getData("friction", 0.5)
physics:SetMaterial("friction_" .. friction)
end
-- Set up item lifetime
local lifetime = item:getData("lifetime", 0)
if lifetime > 0 then
timer.Simple(lifetime, function()
if IsValid(self) then
self:Remove()
end
end)
end
-- Set up item protection
if item:getData("protected", false) then
self:SetCollisionGroup(COLLISION_GROUP_WORLD)
self:SetSolid(SOLID_VPHYSICS)
end
-- Set up item sound
local sound = item:getData("dropSound")
if sound then
self:EmitSound(sound)
end
end)
OnItemsTransferred
Purpose
Called after items have been successfully transferred between characters
When Called
After items are transferred from one character to another
Parameters
fromChar(Character): The character items were transferred fromtoChar(Character): The character items were transferred toitems(table): Table of items that were transferred
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log item transfers
hook.Add("OnItemsTransferred", "MyAddon", function(fromChar, toChar, items)
print(fromChar:getName() .. " transferred items to " .. toChar:getName())
end)
Medium Complexity:
-- Medium: Track transfer history
hook.Add("OnItemsTransferred", "TrackTransfers", function(fromChar, toChar, items)
local count = table.Count(items)
local log = {
from = fromChar:getID(),
to = toChar:getID(),
count = count,
time = os.time()
}
fromChar:setData("lastTransferOut", log)
toChar:setData("lastTransferIn", log)
end)
High Complexity:
-- High: Complex transfer tracking and validation
hook.Add("OnItemsTransferred", "AdvancedTransferTracking", function(fromChar, toChar, items)
-- Log each item transferred
for _, item in pairs(items) do
lia.log.write("item_transfer", {
from = fromChar:getID(),
to = toChar:getID(),
item = item.uniqueID,
quantity = item:getQuantity(),
timestamp = os.time()
})
end
-- Update transfer statistics
local fromStats = fromChar:getData("transferStats", {sent = 0, received = 0})
fromStats.sent = fromStats.sent + table.Count(items)
fromChar:setData("transferStats", fromStats)
local toStats = toChar:getData("transferStats", {sent = 0, received = 0})
toStats.received = toStats.received + table.Count(items)
toChar:setData("transferStats", toStats)
end)
OnLoadTables
Purpose
Called when database tables are being loaded
When Called
During database initialization when tables are loaded
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log table loading
hook.Add("OnLoadTables", "MyAddon", function()
print("Database tables are being loaded")
end)
Medium Complexity:
-- Medium: Initialize custom tables
hook.Add("OnLoadTables", "InitCustomTables", function()
lia.db.query("CREATE TABLE IF NOT EXISTS custom_data (id INT PRIMARY KEY, data TEXT)")
print("Custom tables initialized")
end)
High Complexity:
-- High: Complex table initialization and migration
hook.Add("OnLoadTables", "AdvancedTableSetup", function()
-- Create custom tables
lia.db.query("CREATE TABLE IF NOT EXISTS player_stats (steamid VARCHAR(255) PRIMARY KEY, kills INT, deaths INT, playtime INT)")
-- Check for table migrations
lia.db.query("SELECT * FROM information_schema.columns WHERE table_name = 'player_stats' AND column_name = 'score'", function(data)
if not data or #data == 0 then
lia.db.query("ALTER TABLE player_stats ADD COLUMN score INT DEFAULT 0")
print("Migrated player_stats table")
end
end)
end)
OnOOCMessageSent
Purpose
Called when a player sends an OOC (Out of Character) message
When Called
When a player sends a message in OOC chat
Parameters
client(Player): The player sending the messagemessage(string): The OOC message text
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log OOC messages
hook.Add("OnOOCMessageSent", "MyAddon", function(client, message)
print(client:Name() .. " sent OOC: " .. message)
end)
Medium Complexity:
-- Medium: Filter OOC messages
hook.Add("OnOOCMessageSent", "OOCFiltering", function(client, message)
local char = client:getChar()
if not char then
client:ChatPrint("You need a character to use OOC chat")
return false
end
-- Check if player is muted
if char:getData("muted", false) then
client:ChatPrint("You are muted and cannot send OOC messages")
return false
end
end)
High Complexity:
-- High: Complex OOC system
hook.Add("OnOOCMessageSent", "AdvancedOOC", function(client, message)
local char = client:getChar()
if not char then
client:ChatPrint("You need a character to use OOC chat")
return false
end
-- Check if player is muted
if char:getData("muted", false) then
client:ChatPrint("You are muted and cannot send OOC messages")
return false
end
-- Check if player is gagged
if char:getData("gagged", false) then
client:ChatPrint("You are gagged and cannot send OOC messages")
return false
end
-- Check faction restrictions
local faction = char:getFaction()
if faction == "police" then
client:ChatPrint("Police officers cannot use OOC chat")
return false
end
-- Check for spam protection
local lastOOC = char:getData("lastOOC", 0)
local oocCooldown = 5 -- 5 second cooldown for OOC
if os.time() - lastOOC < oocCooldown then
client:ChatPrint("Please wait before sending another OOC message")
return false
end
-- Check message length
if string.len(message) > 200 then
client:ChatPrint("OOC message too long (max 200 characters)")
return false
end
-- Check for inappropriate content
local bannedWords = {"spam", "hack", "cheat", "exploit"}
for _, word in ipairs(bannedWords) do
if string.find(string.lower(message), string.lower(word)) then
client:ChatPrint("Your OOC message was blocked for inappropriate content")
return false
end
end
-- Update last OOC time
char:setData("lastOOC", os.time())
-- Check for admin commands
if string.sub(message, 1, 1) == "!" then
local command = string.sub(message, 2)
if command == "admin" then
-- Admin command
client:ChatPrint("Admin command executed")
return false
end
end
-- Log OOC message
print(string.format("[OOC] %s: %s", client:Name(), message))
-- Notify admins of OOC usage
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() and ply ~= client then
ply:ChatPrint("[OOC] " .. client:Name() .. ": " .. message)
end
end
end)
OnPAC3PartTransfered
Purpose
Called when a PAC3 part is transferred
When Called
When a PAC3 part is moved between players or inventories
Parameters
part(table): The PAC3 part data being transferred
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log PAC3 part transfer
hook.Add("OnPAC3PartTransfered", "MyAddon", function(part)
print("PAC3 part transferred: " .. (part.name or "Unknown"))
end)
Medium Complexity:
-- Medium: Track PAC3 transfers
hook.Add("OnPAC3PartTransfered", "TrackPAC3Transfers", function(part)
MyAddon.pac3Transfers = MyAddon.pac3Transfers or {}
table.insert(MyAddon.pac3Transfers, {
part = part,
time = os.time()
})
end)
High Complexity:
-- High: Complex PAC3 part transfer handling
hook.Add("OnPAC3PartTransfered", "AdvancedPAC3Transfer", function(part)
-- Log PAC3 transfer
lia.log.write("pac3_part_transferred", {
partName = part.name,
partID = part.id,
timestamp = os.time()
})
-- Validate part data
if not part.id or not part.name then
print("Warning: Invalid PAC3 part data")
return
end
-- Update part statistics
local stats = lia.data.get("pac3Stats", {transfers = 0})
stats.transfers = stats.transfers + 1
lia.data.set("pac3Stats", stats)
-- Notify relevant players
for _, ply in ipairs(player.GetAll()) do
if ply:HasPAC3Part(part.id) then
ply:ChatPrint("PAC3 part " .. part.name .. " has been transferred")
end
end
end)
OnPickupMoney
Purpose
Called when a player picks up money
When Called
When a player collects money from the ground
Parameters
client(Player): The player picking up moneymoneyEntity(Entity): The money entity being picked up
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log money pickup
hook.Add("OnPickupMoney", "MyAddon", function(client, moneyEntity)
print(client:Name() .. " picked up money")
end)
Medium Complexity:
-- Medium: Track money pickups
hook.Add("OnPickupMoney", "TrackMoneyPickups", function(client, moneyEntity)
local char = client:getChar()
if char then
local amount = moneyEntity:GetMoneyAmount()
local pickups = char:getData("moneyPickups", 0)
char:setData("moneyPickups", pickups + amount)
end
end)
High Complexity:
-- High: Complex money pickup handling
hook.Add("OnPickupMoney", "AdvancedMoneyPickup", function(client, moneyEntity)
local char = client:getChar()
if not char then return end
local amount = moneyEntity:GetMoneyAmount()
-- Log money pickup
lia.log.write("money_pickup", {
player = client:SteamID(),
amount = amount,
position = moneyEntity:GetPos(),
timestamp = os.time()
})
-- Update player statistics
local stats = char:getData("moneyStats", {pickedUp = 0, totalAmount = 0})
stats.pickedUp = stats.pickedUp + 1
stats.totalAmount = stats.totalAmount + amount
char:setData("moneyStats", stats)
-- Check for achievement
if stats.totalAmount >= 10000 then
hook.Run("PlayerEarnedAchievement", client, "money_collector")
end
-- Notify player
client:ChatPrint("You picked up " .. lia.currency.get(amount))
end)
OnPlayerDropWeapon
Purpose
Called when a player drops a weapon
When Called
When a player drops a weapon from their inventory
Parameters
client(Player): The player dropping the weaponweapon(Weapon): The weapon being droppedentity(Entity): The weapon entity created
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log weapon drops
hook.Add("OnPlayerDropWeapon", "MyAddon", function(client, weapon, entity)
print(client:Name() .. " dropped weapon: " .. weapon:GetClass())
end)
Medium Complexity:
-- Medium: Track weapon drop statistics
hook.Add("OnPlayerDropWeapon", "WeaponTracking", function(client, weapon, entity)
local char = client:getChar()
if char then
char:setData("weaponsDropped", (char:getData("weaponsDropped", 0) + 1))
char:setData("lastWeaponDrop", os.time())
end
end)
High Complexity:
-- High: Complex weapon drop system
hook.Add("OnPlayerDropWeapon", "AdvancedWeaponDrop", function(client, weapon, entity)
local char = client:getChar()
if not char then return end
-- Check if weapon is bound
if weapon:getData("bound", false) then
local boundTo = weapon:getData("boundTo")
if boundTo == char:getID() then
client:ChatPrint("This weapon is bound to you and cannot be dropped")
return false
end
end
-- Check faction restrictions
local faction = char:getFaction()
if faction == "police" and weapon:GetClass() == "weapon_pistol" then
client:ChatPrint("Police officers cannot drop their service weapon")
return false
end
-- Check if weapon is valuable
local weaponValue = weapon:getData("value", 0)
if weaponValue > 1000 then
-- Valuable weapon - require confirmation
client:ChatPrint("Warning: This is a valuable weapon. Are you sure you want to drop it?")
end
-- Update weapon drop statistics
char:setData("weaponsDropped", (char:getData("weaponsDropped", 0) + 1))
char:setData("lastWeaponDrop", os.time())
-- Set weapon entity data
entity:setNetVar("droppedBy", char:getID())
entity:setNetVar("droppedTime", os.time())
entity:setNetVar("weaponClass", weapon:GetClass())
-- Set weapon entity lifetime
local lifetime = 600 -- 10 minutes
entity:setNetVar("lifetime", lifetime)
-- Start weapon cleanup timer
timer.Simple(lifetime, function()
if IsValid(entity) then
entity:Remove()
end
end)
-- Check for achievement
local weaponsDropped = char:getData("weaponsDropped", 0)
if weaponsDropped >= 50 and not char:getData("achievement_weapon_dropper", false) then
char:setData("achievement_weapon_dropper", true)
client:ChatPrint("Achievement unlocked: Weapon Dropper!")
end
-- Notify nearby players
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(client:GetPos()) < 500 then
ply:ChatPrint(client:Name() .. " dropped a weapon")
end
end
-- Log weapon drop
print(string.format("%s dropped weapon %s (Value: $%d)",
client:Name(), weapon:GetClass(), weaponValue))
end)
OnPlayerEnterSequence
Purpose
Called when a player enters a sequence
When Called
When a player starts a sequence (animation)
Parameters
self(Player): The player entering the sequencesequenceName(string): The name of the sequencecallback(function): The callback function to call when sequence endstime(number): The duration of the sequencenoFreeze(boolean): Whether the player should be frozen during sequence
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log sequence entry
hook.Add("OnPlayerEnterSequence", "MyAddon", function(self, sequenceName, callback, time, noFreeze)
print(self:Name() .. " entered sequence: " .. sequenceName)
end)
Medium Complexity:
-- Medium: Track sequence usage
hook.Add("OnPlayerEnterSequence", "SequenceTracking", function(self, sequenceName, callback, time, noFreeze)
local char = self:getChar()
if char then
char:setData("sequencesUsed", (char:getData("sequencesUsed", 0) + 1))
char:setData("lastSequence", os.time())
end
end)
High Complexity:
-- High: Complex sequence system
hook.Add("OnPlayerEnterSequence", "AdvancedSequence", function(self, sequenceName, callback, time, noFreeze)
local char = self:getChar()
if not char then return end
-- Check if player is already in a sequence
if char:getData("inSequence", false) then
self:ChatPrint("You are already performing an action")
return false
end
-- Check faction restrictions
local faction = char:getFaction()
local restrictedSequences = {
["police"] = {"dance", "sit"},
["medic"] = {"dance"},
["citizen"] = {}
}
local restricted = restrictedSequences[faction] or {}
if table.HasValue(restricted, sequenceName) then
self:ChatPrint("Your faction cannot perform this action")
return false
end
-- Check level requirements
local sequenceRequirements = {
["dance"] = 5,
["sit"] = 1,
["wave"] = 1
}
local requiredLevel = sequenceRequirements[sequenceName]
if requiredLevel then
local charLevel = char:getData("level", 1)
if charLevel < requiredLevel then
self:ChatPrint("You need to be level " .. requiredLevel .. " to perform this action")
return false
end
end
-- Set sequence data
char:setData("inSequence", true)
char:setData("currentSequence", sequenceName)
char:setData("sequenceStartTime", os.time())
-- Update sequence statistics
char:setData("sequencesUsed", (char:getData("sequencesUsed", 0) + 1))
char:setData("lastSequence", os.time())
-- Check for achievement
local sequencesUsed = char:getData("sequencesUsed", 0)
if sequencesUsed >= 100 and not char:getData("achievement_performer", false) then
char:setData("achievement_performer", true)
self:ChatPrint("Achievement unlocked: Performer!")
end
-- Set up sequence end callback
timer.Simple(time, function()
if IsValid(self) and char:getData("inSequence", false) then
char:setData("inSequence", false)
char:setData("currentSequence", nil)
if callback then
callback()
end
end
end)
-- Notify nearby players
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(self:GetPos()) < 500 then
ply:ChatPrint(self:Name() .. " is performing: " .. sequenceName)
end
end
-- Log sequence entry
print(string.format("%s entered sequence %s (Duration: %d seconds)",
self:Name(), sequenceName, time))
end)
OnPlayerInteractItem
Purpose
Called when a player interacts with an item
When Called
When a player uses an item or performs an action on it
Parameters
client(Player): The player interacting with the itemaction(string): The action being performedself(Item): The item being interacted withresult(any): The result of the interactiondata(table): Additional data for the interaction
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log item interactions
hook.Add("OnPlayerInteractItem", "MyAddon", function(client, action, self, result, data)
print(client:Name() .. " used " .. self.uniqueID .. " with action " .. action)
end)
Medium Complexity:
-- Medium: Handle special item effects
hook.Add("OnPlayerInteractItem", "ItemEffects", function(client, action, self, result, data)
if action == "use" then
if self.uniqueID == "health_potion" then
local healAmount = self:getData("healAmount", 50)
client:SetHealth(math.min(client:Health() + healAmount, client:GetMaxHealth()))
client:ChatPrint("You healed for " .. healAmount .. " HP")
elseif self.uniqueID == "stamina_boost" then
local boostAmount = self:getData("boostAmount", 25)
local currentStamina = client:getNetVar("stamina", 100)
client:setNetVar("stamina", math.min(currentStamina + boostAmount, 100))
client:ChatPrint("You gained " .. boostAmount .. " stamina")
end
end
end)
High Complexity:
-- High: Complex item interaction system
hook.Add("OnPlayerInteractItem", "AdvancedItemInteractions", function(client, action, self, result, data)
local char = client:getChar()
if not char then return end
if action == "use" then
-- Handle consumable items
if self.uniqueID == "health_potion" then
local healAmount = self:getData("healAmount", 50)
local charLevel = char:getData("level", 1)
healAmount = healAmount * (1 + charLevel * 0.1) -- 10% bonus per level
client:SetHealth(math.min(client:Health() + healAmount, client:GetMaxHealth()))
client:ChatPrint("You healed for " .. math.floor(healAmount) .. " HP")
-- Consume the item
local uses = self:getData("uses", 1) - 1
if uses <= 0 then
char:getInv():remove(self)
else
self:setData("uses", uses)
end
elseif self.uniqueID == "weapon_upgrade" then
-- Upgrade weapon
local weapon = char:getInv():hasItem("weapon_pistol")
if weapon then
local currentDamage = weapon:getData("damage", 25)
weapon:setData("damage", currentDamage + 5)
client:ChatPrint("Weapon upgraded! Damage increased by 5")
char:getInv():remove(self)
else
client:ChatPrint("You need a weapon to upgrade")
end
elseif self.uniqueID == "teleport_scroll" then
-- Teleport to spawn
local spawns = lia.util.getSpawns()
if #spawns > 0 then
local spawn = spawns[math.random(#spawns)]
client:SetPos(spawn.pos)
client:SetAngles(spawn.ang)
client:ChatPrint("You teleported to spawn")
char:getInv():remove(self)
end
end
elseif action == "examine" then
-- Show item details
local itemData = {
name = self.name,
description = self.description,
value = self:getData("value", 0),
weight = self:getData("weight", 1),
durability = self:getData("durability", 100)
}
client:ChatPrint("Item: " .. itemData.name)
client:ChatPrint("Description: " .. itemData.description)
client:ChatPrint("Value: $" .. itemData.value)
client:ChatPrint("Weight: " .. itemData.weight .. "kg")
client:ChatPrint("Durability: " .. itemData.durability .. "%")
elseif action == "repair" then
-- Repair item
local currentDurability = self:getData("durability", 100)
if currentDurability < 100 then
local repairAmount = math.min(50, 100 - currentDurability)
self:setData("durability", currentDurability + repairAmount)
client:ChatPrint("Item repaired! Durability increased by " .. repairAmount .. "%")
else
client:ChatPrint("Item is already at full durability")
end
end
end)
OnPlayerJoinClass
Purpose
Called when a player joins a class
When Called
When a player successfully joins a new class
Parameters
client(Player): The player joining the classclass(string): The class being joinedoldClass(string): The previous class (if any)
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log class changes
hook.Add("OnPlayerJoinClass", "MyAddon", function(client, class, oldClass)
print(client:Name() .. " joined class: " .. class)
end)
Medium Complexity:
-- Medium: Give class-specific bonuses
hook.Add("OnPlayerJoinClass", "ClassBonuses", function(client, class, oldClass)
local char = client:getChar()
if not char then return end
if class == "police_officer" then
char:setData("authority", 5)
char:setData("salary", 1000)
elseif class == "medic" then
char:setData("healingBonus", 1.5)
char:setData("salary", 800)
elseif class == "citizen" then
char:setData("authority", 0)
char:setData("salary", 500)
end
client:ChatPrint("Class bonuses applied!")
end)
High Complexity:
-- High: Complex class system
hook.Add("OnPlayerJoinClass", "AdvancedClasses", function(client, class, oldClass)
local char = client:getChar()
if not char then return end
-- Remove old class bonuses
if oldClass then
local oldBonuses = {
["police_officer"] = {"authority", "salary"},
["medic"] = {"healingBonus", "medicalKnowledge"},
["engineer"] = {"repairBonus", "technicalSkill"}
}
local bonuses = oldBonuses[oldClass]
if bonuses then
for _, bonus in ipairs(bonuses) do
char:setData(bonus, 0)
end
end
end
-- Apply new class bonuses
local classBonuses = {
["police_officer"] = {
authority = 5,
salary = 1000,
items = {"police_badge", "handcuffs", "radio"}
},
["medic"] = {
healingBonus = 1.5,
medicalKnowledge = 10,
salary = 800,
items = {"medkit", "stethoscope", "bandage"}
},
["engineer"] = {
repairBonus = 2.0,
technicalSkill = 15,
salary = 900,
items = {"wrench", "screwdriver", "multitool"}
}
}
local bonuses = classBonuses[class]
if bonuses then
-- Apply stat bonuses
for stat, value in pairs(bonuses) do
if stat ~= "items" then
char:setData(stat, value)
end
end
-- Give class items
if bonuses.items then
local inventory = char:getInv()
for _, itemID in ipairs(bonuses.items) do
local item = lia.item.instance(itemID)
if item then
inventory:add(item)
end
end
end
end
-- Update character appearance
hook.Run("SetupPlayerModel", client, char)
-- Notify other players
for _, ply in ipairs(player.GetAll()) do
if ply ~= client then
ply:ChatPrint(client:Name() .. " joined the " .. class .. " class")
end
end
-- Log class change
print(string.format("%s joined class %s (was %s)",
client:Name(), class, oldClass or "none"))
end)
OnPlayerLeaveSequence
Purpose
Called when a player leaves a sequence
When Called
When a player finishes or exits a sequence
Parameters
self(Player): The player leaving the sequence
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log sequence exit
hook.Add("OnPlayerLeaveSequence", "MyAddon", function(self)
print(self:Name() .. " left sequence")
end)
Medium Complexity:
-- Medium: Track sequence completion
hook.Add("OnPlayerLeaveSequence", "SequenceTracking", function(self)
local char = self:getChar()
if char then
char:setData("sequencesCompleted", (char:getData("sequencesCompleted", 0) + 1))
char:setData("lastSequenceEnd", os.time())
end
end)
High Complexity:
-- High: Complex sequence exit system
hook.Add("OnPlayerLeaveSequence", "AdvancedSequenceExit", function(self)
local char = self:getChar()
if not char then return end
-- Get sequence data
local currentSequence = char:getData("currentSequence")
local sequenceStartTime = char:getData("sequenceStartTime", 0)
local sequenceDuration = os.time() - sequenceStartTime
-- Update sequence statistics
char:setData("sequencesCompleted", (char:getData("sequencesCompleted", 0) + 1))
char:setData("lastSequenceEnd", os.time())
char:setData("totalSequenceTime", (char:getData("totalSequenceTime", 0) + sequenceDuration))
-- Clear sequence data
char:setData("inSequence", false)
char:setData("currentSequence", nil)
char:setData("sequenceStartTime", nil)
-- Check for achievement
local sequencesCompleted = char:getData("sequencesCompleted", 0)
if sequencesCompleted >= 50 and not char:getData("achievement_sequence_master", false) then
char:setData("achievement_sequence_master", true)
self:ChatPrint("Achievement unlocked: Sequence Master!")
end
-- Check for sequence-specific achievements
if currentSequence == "dance" then
local danceCount = char:getData("danceCount", 0) + 1
char:setData("danceCount", danceCount)
if danceCount >= 20 and not char:getData("achievement_dancer", false) then
char:setData("achievement_dancer", true)
self:ChatPrint("Achievement unlocked: Dancer!")
end
elseif currentSequence == "sit" then
local sitCount = char:getData("sitCount", 0) + 1
char:setData("sitCount", sitCount)
if sitCount >= 10 and not char:getData("achievement_sitter", false) then
char:setData("achievement_sitter", true)
self:ChatPrint("Achievement unlocked: Sitter!")
end
end
-- Check for sequence duration achievements
if sequenceDuration >= 60 then -- 1 minute
local longSequences = char:getData("longSequences", 0) + 1
char:setData("longSequences", longSequences)
if longSequences >= 10 and not char:getData("achievement_patient", false) then
char:setData("achievement_patient", true)
self:ChatPrint("Achievement unlocked: Patient!")
end
end
-- Notify nearby players
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(self:GetPos()) < 500 then
ply:ChatPrint(self:Name() .. " finished performing: " .. (currentSequence or "action"))
end
end
-- Log sequence exit
print(string.format("%s left sequence %s (Duration: %d seconds)",
self:Name(), currentSequence or "unknown", sequenceDuration))
end)
OnPlayerLevelUp
Purpose
Called when a player levels up
When Called
When a player's level increases
Parameters
player(Player): The player who leveled upoldValue(number): The previous levelnewValue(number): The new level
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log level ups
hook.Add("OnPlayerLevelUp", "MyAddon", function(player, oldValue, newValue)
print(player:Name() .. " leveled up from " .. oldValue .. " to " .. newValue)
end)
Medium Complexity:
-- Medium: Give level up bonuses
hook.Add("OnPlayerLevelUp", "LevelBonuses", function(player, oldValue, newValue)
local char = player:getChar()
if not char then return end
-- Give skill points
local skillPoints = newValue - oldValue
char:setData("skillPoints", char:getData("skillPoints", 0) + skillPoints)
-- Give money bonus
local moneyBonus = newValue * 100
char:setMoney(char:getMoney() + moneyBonus)
player:ChatPrint("Level up! You gained " .. skillPoints .. " skill points and $" .. moneyBonus)
end)
High Complexity:
-- High: Complex leveling system
hook.Add("OnPlayerLevelUp", "AdvancedLeveling", function(player, oldValue, newValue)
local char = player:getChar()
if not char then return end
local levelDiff = newValue - oldValue
-- Give skill points based on level
local skillPoints = levelDiff * 2
char:setData("skillPoints", char:getData("skillPoints", 0) + skillPoints)
-- Give attribute points
local attrPoints = levelDiff
char:setData("attributePoints", char:getData("attributePoints", 0) + attrPoints)
-- Give money bonus
local moneyBonus = newValue * 150
char:setMoney(char:getMoney() + moneyBonus)
-- Check for milestone bonuses
if newValue % 10 == 0 then
-- Every 10 levels
char:setData("milestoneBonus", true)
char:setMoney(char:getMoney() + 1000)
player:ChatPrint("Milestone reached! Bonus reward: $1000")
end
-- Check for level cap
local maxLevel = 100
if newValue >= maxLevel then
char:setData("maxLevelReached", true)
player:ChatPrint("Congratulations! You have reached the maximum level!")
end
-- Update character stats
local faction = char:getFaction()
if faction == "police" then
char:setData("authority", char:getData("authority", 0) + levelDiff)
elseif faction == "medic" then
char:setData("healingBonus", char:getData("healingBonus", 1.0) + (levelDiff * 0.1))
end
-- Notify other players
for _, ply in ipairs(player.GetAll()) do
if ply ~= player then
ply:ChatPrint(player:Name() .. " reached level " .. newValue .. "!")
end
end
-- Log level up
print(string.format("%s leveled up from %d to %d",
player:Name(), oldValue, newValue))
end)
OnPlayerLostStackItem
Purpose
Called when a player loses a stack item
When Called
When a player's stack item is removed or lost
Parameters
itemTypeOrItem(string/Item): The item type or item instance that was lost
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log stack item loss
hook.Add("OnPlayerLostStackItem", "MyAddon", function(itemTypeOrItem)
print("Player lost stack item: " .. tostring(itemTypeOrItem))
end)
Medium Complexity:
-- Medium: Track stack item losses
hook.Add("OnPlayerLostStackItem", "TrackStackLosses", function(itemTypeOrItem)
MyAddon.stackLosses = MyAddon.stackLosses or {}
local itemType = type(itemTypeOrItem) == "string" and itemTypeOrItem or itemTypeOrItem.uniqueID
MyAddon.stackLosses[itemType] = (MyAddon.stackLosses[itemType] or 0) + 1
end)
High Complexity:
-- High: Complex stack item loss handling
hook.Add("OnPlayerLostStackItem", "AdvancedStackLoss", function(itemTypeOrItem)
local itemType = type(itemTypeOrItem) == "string" and itemTypeOrItem or itemTypeOrItem.uniqueID
-- Log stack item loss
lia.log.write("stack_item_lost", {
itemType = itemType,
timestamp = os.time()
})
-- Find all players who had this item
for _, ply in ipairs(player.GetAll()) do
local char = ply:getChar()
if char then
local inventory = char:getInv()
if inventory then
for _, item in pairs(inventory:getItems()) do
if item.uniqueID == itemType then
-- Notify player
ply:ChatPrint("You lost a stack item: " .. item.name)
end
end
end
end
end
-- Update global statistics
local stats = lia.data.get("stackStats", {lost = 0})
stats.lost = stats.lost + 1
lia.data.set("stackStats", stats)
end)
OnPlayerObserve
Purpose
Called when a player enters or exits observer mode
When Called
When a player starts or stops observing
Parameters
client(Player): The player entering/exiting observer modestate(boolean): True if entering observer mode, false if exiting
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log observer mode changes
hook.Add("OnPlayerObserve", "MyAddon", function(client, state)
if state then
print(client:Name() .. " entered observer mode")
else
print(client:Name() .. " exited observer mode")
end
end)
Medium Complexity:
-- Medium: Handle observer mode restrictions
hook.Add("OnPlayerObserve", "ObserverRestrictions", function(client, state)
if state then
-- Hide player when observing
client:SetNoDraw(true)
client:SetNotSolid(true)
client:SetMoveType(MOVETYPE_NOCLIP)
-- Notify other players
for _, ply in ipairs(player.GetAll()) do
if ply ~= client then
ply:ChatPrint(client:Name() .. " is now observing")
end
end
else
-- Restore player when exiting observer mode
client:SetNoDraw(false)
client:SetNotSolid(false)
client:SetMoveType(MOVETYPE_WALK)
-- Notify other players
for _, ply in ipairs(player.GetAll()) do
if ply ~= client then
ply:ChatPrint(client:Name() .. " is no longer observing")
end
end
end
end)
High Complexity:
-- High: Complex observer mode system
hook.Add("OnPlayerObserve", "AdvancedObserver", function(client, state)
local char = client:getChar()
if not char then return end
if state then
-- Check if player has permission to observe
if not client:IsAdmin() and not char:hasFlags("O") then
client:ChatPrint("You don't have permission to observe")
return
end
-- Store original position
char:setData("observePos", client:GetPos())
char:setData("observeAng", client:GetAngles())
-- Set up observer mode
client:SetNoDraw(true)
client:SetNotSolid(true)
client:SetMoveType(MOVETYPE_NOCLIP)
client:SetHealth(1)
client:SetMaxHealth(1)
-- Set observer target
local target = char:getData("observeTarget")
if target and IsValid(target) then
client:SetObserverTarget(target)
end
-- Notify admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() and ply ~= client then
ply:ChatPrint("[ADMIN] " .. client:Name() .. " entered observer mode")
end
end
-- Log observer mode
print(string.format("%s entered observer mode at %s",
client:Name(), os.date("%Y-%m-%d %H:%M:%S")))
else
-- Restore player
client:SetNoDraw(false)
client:SetNotSolid(false)
client:SetMoveType(MOVETYPE_WALK)
client:SetHealth(100)
client:SetMaxHealth(100)
-- Restore position if available
local observePos = char:getData("observePos")
local observeAng = char:getData("observeAng")
if observePos and observeAng then
client:SetPos(observePos)
client:SetAngles(observeAng)
end
-- Clear observer data
char:setData("observePos", nil)
char:setData("observeAng", nil)
char:setData("observeTarget", nil)
-- Notify admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() and ply ~= client then
ply:ChatPrint("[ADMIN] " .. client:Name() .. " exited observer mode")
end
end
-- Log observer mode exit
print(string.format("%s exited observer mode at %s",
client:Name(), os.date("%Y-%m-%d %H:%M:%S")))
end
end)
OnPlayerPurchaseDoor
Purpose
Called when a player purchases a door
When Called
When a player successfully buys a door
Parameters
client(Player): The player purchasing the doordoor(Entity): The door being purchasedprice(number): The price paid for the door
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log door purchases
hook.Add("OnPlayerPurchaseDoor", "MyAddon", function(client, door, price)
print(client:Name() .. " purchased door for $" .. price)
end)
Medium Complexity:
-- Medium: Handle door purchase bonuses
hook.Add("OnPlayerPurchaseDoor", "DoorBonuses", function(client, door, price)
local char = client:getChar()
if not char then return end
-- Give purchase bonus
local bonus = math.floor(price * 0.1) -- 10% bonus
char:setMoney(char:getMoney() + bonus)
-- Set door ownership
door:setNetVar("owner", char:getID())
door:setNetVar("purchaseTime", os.time())
client:ChatPrint("Door purchased! You received a $" .. bonus .. " bonus")
end)
High Complexity:
-- High: Complex door purchase system
hook.Add("OnPlayerPurchaseDoor", "AdvancedDoorPurchases", function(client, door, price)
local char = client:getChar()
if not char then return end
-- Set up door ownership
door:setNetVar("owner", char:getID())
door:setNetVar("purchaseTime", os.time())
door:setNetVar("purchasePrice", price)
-- Give door key
local key = lia.item.instance("door_key")
if key then
key:setData("doorID", door:EntIndex())
key:setData("doorName", door:getNetVar("doorData", {}).title or "Door")
char:getInv():add(key)
end
-- Check for bulk purchase discount
local ownedDoors = 0
for _, ent in ipairs(ents.GetAll()) do
if IsValid(ent) and ent.IsDoor and ent:getNetVar("owner") == char:getID() then
ownedDoors = ownedDoors + 1
end
end
if ownedDoors >= 5 then
local discount = math.floor(price * 0.2) -- 20% discount
char:setMoney(char:getMoney() + discount)
client:ChatPrint("Bulk purchase discount: $" .. discount)
end
-- Update character statistics
char:setData("doorsOwned", (char:getData("doorsOwned", 0) + 1))
char:setData("totalSpent", (char:getData("totalSpent", 0) + price))
-- Check for achievement
if char:getData("doorsOwned", 0) >= 10 then
char:setData("achievement_landlord", true)
client:ChatPrint("Achievement unlocked: Landlord!")
end
-- Notify nearby players
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(door:GetPos()) < 500 then
ply:ChatPrint(client:Name() .. " purchased a door for $" .. price)
end
end
-- Log purchase
print(string.format("%s purchased door %s for $%d",
client:Name(), door:EntIndex(), price))
end)
OnPlayerRagdollCreated
Purpose
Called when a player ragdoll is created
When Called
When a player's ragdoll is spawned (usually on death)
Parameters
player(Player): The player whose ragdoll was createdragdoll(Entity): The ragdoll entity that was created
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log ragdoll creation
hook.Add("OnPlayerRagdollCreated", "MyAddon", function(player, ragdoll)
print("Ragdoll created for " .. player:Name())
end)
Medium Complexity:
-- Medium: Customize ragdoll appearance
hook.Add("OnPlayerRagdollCreated", "RagdollCustomization", function(player, ragdoll)
local char = player:getChar()
if char then
-- Set ragdoll model to character model
local model = char:getModel()
if model then
ragdoll:SetModel(model)
end
-- Set ragdoll skin
local skin = char:getSkin()
ragdoll:SetSkin(skin)
end
end)
High Complexity:
-- High: Complex ragdoll system
hook.Add("OnPlayerRagdollCreated", "AdvancedRagdoll", function(player, ragdoll)
local char = player:getChar()
if not char then return end
-- Set ragdoll model to character model
local model = char:getModel()
if model then
ragdoll:SetModel(model)
end
-- Set ragdoll skin
local skin = char:getSkin()
ragdoll:SetSkin(skin)
-- Set ragdoll bodygroups
local bodygroups = char:getBodygroups()
for group, value in pairs(bodygroups) do
local index = tonumber(group)
if index then
ragdoll:SetBodygroup(index, value)
end
end
-- Set ragdoll position and angles
ragdoll:SetPos(player:GetPos())
ragdoll:SetAngles(player:GetAngles())
-- Set ragdoll velocity
ragdoll:SetVelocity(player:GetVelocity())
-- Set ragdoll health
ragdoll:SetHealth(player:Health())
-- Set ragdoll armor
ragdoll:SetArmor(player:Armor())
-- Set ragdoll data
ragdoll:setNetVar("playerID", player:UserID())
ragdoll:setNetVar("charID", char:getID())
ragdoll:setNetVar("charName", char:getName())
ragdoll:setNetVar("faction", char:getFaction())
-- Set ragdoll creation time
ragdoll:setNetVar("creationTime", os.time())
-- Set ragdoll lifetime
local lifetime = 300 -- 5 minutes
ragdoll:setNetVar("lifetime", lifetime)
-- Start ragdoll cleanup timer
timer.Simple(lifetime, function()
if IsValid(ragdoll) then
ragdoll:Remove()
end
end)
-- Log ragdoll creation
print(string.format("Ragdoll created for %s (Char: %s, Faction: %s)",
player:Name(), char:getName(), char:getFaction()))
end)
OnPlayerStatsTableCreated
Purpose
Called when the player stats table is created
When Called
When the player statistics table is initialized
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log table creation
hook.Add("OnPlayerStatsTableCreated", "MyAddon", function()
print("Player stats table created")
end)
Medium Complexity:
-- Medium: Add custom stats columns
hook.Add("OnPlayerStatsTableCreated", "CustomStats", function()
-- Add custom statistics columns
lia.db.query("ALTER TABLE player_stats ADD COLUMN IF NOT EXISTS kills INTEGER DEFAULT 0")
lia.db.query("ALTER TABLE player_stats ADD COLUMN IF NOT EXISTS deaths INTEGER DEFAULT 0")
lia.db.query("ALTER TABLE player_stats ADD COLUMN IF NOT EXISTS playtime INTEGER DEFAULT 0")
end)
High Complexity:
-- High: Complex stats system
hook.Add("OnPlayerStatsTableCreated", "AdvancedStats", function()
-- Create comprehensive stats table
local statsColumns = {
"kills INTEGER DEFAULT 0",
"deaths INTEGER DEFAULT 0",
"playtime INTEGER DEFAULT 0",
"money_earned INTEGER DEFAULT 0",
"money_spent INTEGER DEFAULT 0",
"items_crafted INTEGER DEFAULT 0",
"doors_purchased INTEGER DEFAULT 0",
"factions_joined INTEGER DEFAULT 0",
"classes_joined INTEGER DEFAULT 0",
"achievements_unlocked INTEGER DEFAULT 0",
"quests_completed INTEGER DEFAULT 0",
"pvp_wins INTEGER DEFAULT 0",
"pvp_losses INTEGER DEFAULT 0",
"admin_actions INTEGER DEFAULT 0",
"warnings_received INTEGER DEFAULT 0",
"last_activity TIMESTAMP DEFAULT CURRENT_TIMESTAMP"
}
for _, column in ipairs(statsColumns) do
lia.db.query("ALTER TABLE player_stats ADD COLUMN IF NOT EXISTS " .. column)
end
-- Create indexes for better performance
lia.db.query("CREATE INDEX IF NOT EXISTS idx_player_stats_steamid ON player_stats(steamid)")
lia.db.query("CREATE INDEX IF NOT EXISTS idx_player_stats_playtime ON player_stats(playtime)")
lia.db.query("CREATE INDEX IF NOT EXISTS idx_player_stats_kills ON player_stats(kills)")
-- Initialize default stats for existing players
lia.db.query("INSERT OR IGNORE INTO player_stats (steamid, playtime, last_activity) SELECT steamid, 0, CURRENT_TIMESTAMP FROM characters WHERE steamid NOT IN (SELECT steamid FROM player_stats)")
print("Advanced player stats system initialized")
end)
OnPlayerSwitchClass
Purpose
Called when a player switches classes
When Called
When a player successfully changes their class
Parameters
client(Player): The player switching classesclass(string): The new class being switched tooldClass(string): The previous class
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log class switches
hook.Add("OnPlayerSwitchClass", "MyAddon", function(client, class, oldClass)
print(client:Name() .. " switched from " .. oldClass .. " to " .. class)
end)
Medium Complexity:
-- Medium: Handle class switch bonuses
hook.Add("OnPlayerSwitchClass", "ClassSwitchBonuses", function(client, class, oldClass)
local char = client:getChar()
if not char then return end
-- Give switch bonus
local switchBonus = 100
char:setMoney(char:getMoney() + switchBonus)
client:ChatPrint("Class switch bonus: $" .. switchBonus)
end)
High Complexity:
-- High: Complex class switching system
hook.Add("OnPlayerSwitchClass", "AdvancedClassSwitching", function(client, class, oldClass)
local char = client:getChar()
if not char then return end
-- Remove old class bonuses
if oldClass then
local oldBonuses = {
["police_officer"] = {"authority", "salary"},
["medic"] = {"healingBonus", "medicalKnowledge"},
["engineer"] = {"repairBonus", "technicalSkill"}
}
local bonuses = oldBonuses[oldClass]
if bonuses then
for _, bonus in ipairs(bonuses) do
char:setData(bonus, 0)
end
end
end
-- Apply new class bonuses
local classBonuses = {
["police_officer"] = {
authority = 5,
salary = 1000,
items = {"police_badge", "handcuffs", "radio"}
},
["medic"] = {
healingBonus = 1.5,
medicalKnowledge = 10,
salary = 800,
items = {"medkit", "stethoscope", "bandage"}
},
["engineer"] = {
repairBonus = 2.0,
technicalSkill = 15,
salary = 900,
items = {"wrench", "screwdriver", "multitool"}
}
}
local bonuses = classBonuses[class]
if bonuses then
-- Apply stat bonuses
for stat, value in pairs(bonuses) do
if stat ~= "items" then
char:setData(stat, value)
end
end
-- Give class items
if bonuses.items then
local inventory = char:getInv()
for _, itemID in ipairs(bonuses.items) do
local item = lia.item.instance(itemID)
if item then
inventory:add(item)
end
end
end
end
-- Update character appearance
hook.Run("SetupPlayerModel", client, char)
-- Check for class switch cooldown
local lastSwitch = char:getData("lastClassSwitch", 0)
local switchCooldown = 3600 -- 1 hour
if os.time() - lastSwitch < switchCooldown then
client:ChatPrint("You must wait before switching classes again")
return false
end
-- Update switch time
char:setData("lastClassSwitch", os.time())
-- Check for achievement
local classSwitches = char:getData("classSwitches", 0) + 1
char:setData("classSwitches", classSwitches)
if classSwitches >= 10 and not char:getData("achievement_class_hopper", false) then
char:setData("achievement_class_hopper", true)
client:ChatPrint("Achievement unlocked: Class Hopper!")
end
-- Notify other players
for _, ply in ipairs(player.GetAll()) do
if ply ~= client then
ply:ChatPrint(client:Name() .. " switched to " .. class .. " class")
end
end
-- Log class switch
print(string.format("%s switched from %s to %s class",
client:Name(), oldClass or "none", class))
end)
OnPlayerXPGain
Purpose
Called when a player gains experience points
When Called
When a player earns XP from any source
Parameters
player(Player): The player gaining XPgained(number): The amount of XP gainedreason(string): The reason for gaining XP
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log XP gain
hook.Add("OnPlayerXPGain", "MyAddon", function(player, gained, reason)
print(player:Name() .. " gained " .. gained .. " XP for " .. reason)
end)
Medium Complexity:
-- Medium: Apply XP bonuses
hook.Add("OnPlayerXPGain", "XPBonuses", function(player, gained, reason)
local char = player:getChar()
if not char then return end
-- Apply faction bonus
local faction = char:getFaction()
local factionMultiplier = 1.0
if faction == "police" then
factionMultiplier = 1.2
elseif faction == "medic" then
factionMultiplier = 1.1
end
local bonusXP = math.floor(gained * factionMultiplier)
char:setData("experience", char:getData("experience", 0) + bonusXP)
player:ChatPrint("You gained " .. bonusXP .. " XP (with faction bonus)")
end)
High Complexity:
-- High: Complex XP system
hook.Add("OnPlayerXPGain", "AdvancedXP", function(player, gained, reason)
local char = player:getChar()
if not char then return end
local totalXP = char:getData("experience", 0)
local currentLevel = char:getData("level", 1)
-- Apply various bonuses
local finalXP = gained
-- Faction bonus
local faction = char:getFaction()
local factionBonuses = {
["police"] = 1.2,
["medic"] = 1.1,
["engineer"] = 1.15,
["citizen"] = 1.0
}
finalXP = finalXP * (factionBonuses[faction] or 1.0)
-- Activity bonus
local activityBonuses = {
["combat"] = 1.5,
["roleplay"] = 1.3,
["exploration"] = 1.1,
["crafting"] = 1.2
}
finalXP = finalXP * (activityBonuses[reason] or 1.0)
-- Time bonus (more XP during peak hours)
local currentHour = tonumber(os.date("%H"))
if currentHour >= 18 and currentHour <= 22 then
finalXP = finalXP * 1.2 -- 20% bonus during peak hours
end
-- Apply final XP
local newTotalXP = totalXP + math.floor(finalXP)
char:setData("experience", newTotalXP)
-- Check for level up
local requiredXP = currentLevel * 1000
if newTotalXP >= requiredXP then
local newLevel = currentLevel + 1
char:setData("level", newLevel)
hook.Run("OnPlayerLevelUp", player, currentLevel, newLevel)
end
-- Track XP sources
local xpSources = char:getData("xpSources", {})
xpSources[reason] = (xpSources[reason] or 0) + math.floor(finalXP)
char:setData("xpSources", xpSources)
-- Notify player
player:ChatPrint("You gained " .. math.floor(finalXP) .. " XP for " .. reason)
-- Log XP gain
print(string.format("%s gained %d XP for %s (Level %d)",
player:Name(), math.floor(finalXP), reason, currentLevel))
end)
OnRecordUpserted
Purpose
Called when a database record is inserted or updated
When Called
When a record is upserted in the database
Parameters
dbTable(string): The name of the database tabledata(table): The data that was upsertedaction(string): The action performed ("insert" or "update")
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log record upserts
hook.Add("OnRecordUpserted", "MyAddon", function(dbTable, data, action)
print("Record " .. action .. "ed in " .. dbTable)
end)
Medium Complexity:
-- Medium: Track database changes
hook.Add("OnRecordUpserted", "TrackDBChanges", function(dbTable, data, action)
MyAddon.dbChanges = MyAddon.dbChanges or {}
table.insert(MyAddon.dbChanges, {
table = dbTable,
action = action,
timestamp = os.time()
})
end)
High Complexity:
-- High: Complex database change tracking
hook.Add("OnRecordUpserted", "AdvancedDBTracking", function(dbTable, data, action)
-- Log database changes
lia.log.write("db_upsert", {
table = dbTable,
action = action,
data = util.TableToJSON(data),
timestamp = os.time()
})
-- Trigger table-specific hooks
if dbTable == "lia_characters" then
hook.Run("OnCharacterRecordUpserted", data, action)
elseif dbTable == "lia_inventories" then
hook.Run("OnInventoryRecordUpserted", data, action)
end
-- Notify admins of critical changes
if action == "update" and dbTable == "lia_characters" then
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("Character record updated: " .. (data.name or "Unknown"))
end
end
end
end)
OnRequestItemTransfer
Purpose
Called when an item transfer is requested
When Called
When a request is made to transfer an item to another inventory
Parameters
item(Item): The item being transferredtargetInventory(Inventory): The target inventory
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log item transfer requests
hook.Add("OnRequestItemTransfer", "MyAddon", function(item, targetInventory)
print("Item transfer requested: " .. item.name)
end)
Medium Complexity:
-- Medium: Track transfer requests
hook.Add("OnRequestItemTransfer", "TrackTransferRequests", function(item, targetInventory)
MyAddon.transferRequests = MyAddon.transferRequests or {}
table.insert(MyAddon.transferRequests, {
item = item.uniqueID,
target = targetInventory:getID(),
time = os.time()
})
end)
High Complexity:
-- High: Complex transfer request handling
hook.Add("OnRequestItemTransfer", "AdvancedTransferRequest", function(item, targetInventory)
-- Log transfer request
lia.log.write("item_transfer_request", {
item = item.uniqueID,
from = item:getInventory():getID(),
to = targetInventory:getID(),
timestamp = os.time()
})
-- Check transfer restrictions
local owner = item:getOwner()
if owner then
local char = owner:getChar()
if char then
local transferCount = char:getData("transferCount", 0)
char:setData("transferCount", transferCount + 1)
end
end
end)
OnRestoreCompleted
Purpose
Called when a restore operation completes successfully
When Called
After a successful database restore operation
Parameters
restoreLog(table): Information about the restore operation
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log restore completion
hook.Add("OnRestoreCompleted", "MyAddon", function(restoreLog)
print("Restore completed successfully")
end)
Medium Complexity:
-- Medium: Notify admins of restore
hook.Add("OnRestoreCompleted", "NotifyRestore", function(restoreLog)
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("Database restore completed")
end
end
end)
High Complexity:
-- High: Complex restore completion handling
hook.Add("OnRestoreCompleted", "AdvancedRestoreCompletion", function(restoreLog)
-- Log restore details
lia.log.write("restore_completed", {
tables = restoreLog.tables or {},
records = restoreLog.records or 0,
timestamp = os.time()
})
-- Notify all players
for _, ply in ipairs(player.GetAll()) do
ply:ChatPrint("Server data has been restored")
end
-- Reload characters
for _, ply in ipairs(player.GetAll()) do
local char = ply:getChar()
if char then
char:sync()
end
end
end)
OnRestoreFailed
Purpose
Called when a restore operation fails
When Called
After a failed database restore operation
Parameters
failedLog(table): Information about the failed restore operation
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log restore failure
hook.Add("OnRestoreFailed", "MyAddon", function(failedLog)
print("Restore failed")
end)
Medium Complexity:
-- Medium: Notify admins of failure
hook.Add("OnRestoreFailed", "NotifyRestoreFailure", function(failedLog)
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("Database restore failed: " .. (failedLog.error or "Unknown error"))
end
end
end)
High Complexity:
-- High: Complex restore failure handling
hook.Add("OnRestoreFailed", "AdvancedRestoreFailure", function(failedLog)
-- Log failure details
lia.log.write("restore_failed", {
error = failedLog.error or "Unknown",
tables = failedLog.tables or {},
timestamp = os.time()
})
-- Notify admins with detailed error
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("Restore failed: " .. (failedLog.error or "Unknown error"))
if failedLog.tables then
ply:ChatPrint("Failed tables: " .. table.concat(failedLog.tables, ", "))
end
end
end
-- Attempt rollback
if failedLog.backup then
lia.db.restore(failedLog.backup)
end
end)
OnSalaryAdjust
Purpose
Called when a player's salary is adjusted
When Called
When a player's salary amount is modified
Parameters
client(Player): The player whose salary is being adjusted
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log salary adjustments
hook.Add("OnSalaryAdjust", "MyAddon", function(client)
print(client:Name() .. "'s salary was adjusted")
end)
Medium Complexity:
-- Medium: Track salary changes
hook.Add("OnSalaryAdjust", "TrackSalaryChanges", function(client)
local char = client:getChar()
if char then
local history = char:getData("salaryHistory", {})
table.insert(history, {
time = os.time(),
action = "adjusted"
})
char:setData("salaryHistory", history)
end
end)
High Complexity:
-- High: Complex salary adjustment tracking
hook.Add("OnSalaryAdjust", "AdvancedSalaryAdjustment", function(client)
local char = client:getChar()
if not char then return end
-- Log salary adjustment
lia.log.write("salary_adjust", {
player = client:SteamID(),
character = char:getID(),
faction = char:getFaction(),
class = char:getClass(),
timestamp = os.time()
})
-- Update salary statistics
local stats = char:getData("salaryStats", {adjustments = 0})
stats.adjustments = stats.adjustments + 1
stats.lastAdjustment = os.time()
char:setData("salaryStats", stats)
end)
OnSalaryGiven
Purpose
Called when a player receives their salary
When Called
When salary is paid to a player
Parameters
client(Player): The player receiving the salarychar(Character): The character receiving the salarypay(number): The amount of salary paidfaction(number): The faction IDclass(number): The class ID
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log salary payments
hook.Add("OnSalaryGiven", "MyAddon", function(client, char, pay, faction, class)
print(client:Name() .. " received salary: " .. pay)
end)
Medium Complexity:
-- Medium: Track salary payments
hook.Add("OnSalaryGiven", "TrackSalaryPayments", function(client, char, pay, faction, class)
local history = char:getData("salaryHistory", {})
table.insert(history, {
amount = pay,
time = os.time(),
faction = faction,
class = class
})
char:setData("salaryHistory", history)
end)
High Complexity:
-- High: Complex salary payment tracking
hook.Add("OnSalaryGiven", "AdvancedSalaryTracking", function(client, char, pay, faction, class)
-- Log salary payment
lia.log.write("salary_given", {
player = client:SteamID(),
character = char:getID(),
amount = pay,
faction = faction,
class = class,
timestamp = os.time()
})
-- Update salary statistics
local stats = char:getData("salaryStats", {total = 0, count = 0})
stats.total = stats.total + pay
stats.count = stats.count + 1
stats.lastPayment = os.time()
char:setData("salaryStats", stats)
-- Notify player
client:ChatPrint("You received your salary: " .. lia.currency.get(pay))
end)
OnSavedItemLoaded
Purpose
Called when saved items are loaded
When Called
When items are loaded from the database
Parameters
loadedItems(table): Table of items that were loaded
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log loaded items
hook.Add("OnSavedItemLoaded", "MyAddon", function(loadedItems)
print("Loaded " .. table.Count(loadedItems) .. " items")
end)
Medium Complexity:
-- Medium: Track loaded items
hook.Add("OnSavedItemLoaded", "TrackLoadedItems", function(loadedItems)
MyAddon.loadedItems = MyAddon.loadedItems or {}
for _, item in pairs(loadedItems) do
table.insert(MyAddon.loadedItems, {
uniqueID = item.uniqueID,
loaded = os.time()
})
end
end)
High Complexity:
-- High: Complex item loading management
hook.Add("OnSavedItemLoaded", "AdvancedItemLoading", function(loadedItems)
-- Log item loading
lia.log.write("items_loaded", {
count = table.Count(loadedItems),
timestamp = os.time()
})
-- Validate loaded items
for _, item in pairs(loadedItems) do
if not item:isValid() then
print("Warning: Invalid item loaded: " .. (item.uniqueID or "Unknown"))
end
end
-- Update item statistics
MyAddon.itemStats = MyAddon.itemStats or {}
for _, item in pairs(loadedItems) do
MyAddon.itemStats[item.uniqueID] = (MyAddon.itemStats[item.uniqueID] or 0) + 1
end
end)
OnServerLog
Purpose
Called when a server log entry is created
When Called
When a log message is written to the server log
Parameters
client(Player): The player associated with the log (can be nil)logType(string): The type of log entrylogString(string): The log messagecategory(string): The log category
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Print server logs
hook.Add("OnServerLog", "MyAddon", function(client, logType, logString, category)
print("[" .. logType .. "] " .. logString)
end)
Medium Complexity:
-- Medium: Filter and store logs
hook.Add("OnServerLog", "FilterLogs", function(client, logType, logString, category)
if category == "admin" then
MyAddon.adminLogs = MyAddon.adminLogs or {}
table.insert(MyAddon.adminLogs, {
type = logType,
message = logString,
player = client and client:SteamID() or "Server",
time = os.time()
})
end
end)
High Complexity:
-- High: Complex log management
hook.Add("OnServerLog", "AdvancedLogManagement", function(client, logType, logString, category)
-- Store log in database
lia.db.query("INSERT INTO server_logs (player, type, message, category, timestamp) VALUES (?, ?, ?, ?, ?)",
client and client:SteamID() or "Server",
logType,
logString,
category,
os.time()
)
-- Send to external logging service
if category == "critical" then
http.Post("https://logging-service.com/api/log", {
type = logType,
message = logString,
server = game.GetIPAddress()
})
end
-- Notify admins of important logs
if category == "admin" or category == "critical" then
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("[LOG] " .. logString)
end
end
end
end)
OnSkillsChanged
Purpose
Called when a character's skills are changed
When Called
When a character's skill values are modified
Parameters
character(Character): The character whose skills changedoldValue(table): The old skill valuesvalue(table): The new skill values
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log skill changes
hook.Add("OnSkillsChanged", "MyAddon", function(character, oldValue, value)
print(character:getName() .. "'s skills changed")
end)
Medium Complexity:
-- Medium: Track skill progression
hook.Add("OnSkillsChanged", "TrackSkills", function(character, oldValue, value)
local history = character:getData("skillHistory", {})
table.insert(history, {
old = oldValue,
new = value,
time = os.time()
})
character:setData("skillHistory", history)
end)
High Complexity:
-- High: Complex skill change tracking
hook.Add("OnSkillsChanged", "AdvancedSkillTracking", function(character, oldValue, value)
-- Log skill changes
for skillName, newVal in pairs(value) do
local oldVal = oldValue[skillName] or 0
if newVal ~= oldVal then
lia.log.write("skill_change", {
character = character:getID(),
skill = skillName,
old = oldVal,
new = newVal,
timestamp = os.time()
})
end
end
-- Check for skill milestones
for skillName, newVal in pairs(value) do
if newVal >= 100 and (oldValue[skillName] or 0) < 100 then
local owner = character:getPlayer()
if IsValid(owner) then
owner:ChatPrint("You mastered " .. skillName .. "!")
end
end
end
end)
OnTableBackedUp
Purpose
Called when a database table is backed up
When Called
After a database table backup is created
Parameters
tableName(string): The name of the table that was backed upsnapshot(table): The backup snapshot data
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log table backups
hook.Add("OnTableBackedUp", "MyAddon", function(tableName, snapshot)
print("Table backed up: " .. tableName)
end)
Medium Complexity:
-- Medium: Track backups
hook.Add("OnTableBackedUp", "TrackBackups", function(tableName, snapshot)
MyAddon.backups = MyAddon.backups or {}
MyAddon.backups[tableName] = {
time = os.time(),
records = #snapshot
}
end)
High Complexity:
-- High: Complex backup management
hook.Add("OnTableBackedUp", "AdvancedBackupManagement", function(tableName, snapshot)
-- Log backup details
lia.log.write("table_backup", {
table = tableName,
records = #snapshot,
timestamp = os.time()
})
-- Store backup metadata
lia.data.get("backups", {}, function(data)
data[tableName] = data[tableName] or {}
table.insert(data[tableName], {
time = os.time(),
records = #snapshot,
size = #util.TableToJSON(snapshot)
})
lia.data.set("backups", data)
end)
-- Notify admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("Table " .. tableName .. " backed up (" .. #snapshot .. " records)")
end
end
end)
OnTableRemoved
Purpose
Called when a database table is removed
When Called
After a database table is deleted
Parameters
tableName(string): The name of the table that was removedsnapshot(table): The final snapshot of the table data
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log table removal
hook.Add("OnTableRemoved", "MyAddon", function(tableName, snapshot)
print("Table removed: " .. tableName)
end)
Medium Complexity:
-- Medium: Archive removed tables
hook.Add("OnTableRemoved", "ArchiveRemovedTables", function(tableName, snapshot)
MyAddon.archivedTables = MyAddon.archivedTables or {}
MyAddon.archivedTables[tableName] = {
data = snapshot,
removed = os.time()
}
end)
High Complexity:
-- High: Complex table removal handling
hook.Add("OnTableRemoved", "AdvancedTableRemoval", function(tableName, snapshot)
-- Log table removal
lia.log.write("table_removed", {
table = tableName,
records = #snapshot,
timestamp = os.time()
})
-- Create final backup
file.Write("lilia/backups/" .. tableName .. "_" .. os.time() .. ".json", util.TableToJSON(snapshot))
-- Notify admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("Table " .. tableName .. " was removed (" .. #snapshot .. " records archived)")
end
end
-- Clean up related data
lia.data.delete("table_" .. tableName)
end)
OnTableRestored
Purpose
Called when a database table is restored
When Called
After a database table is restored from a backup
Parameters
tableName(string): The name of the table that was restoreddata(table): The restored table data
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log table restoration
hook.Add("OnTableRestored", "MyAddon", function(tableName, data)
print("Table restored: " .. tableName)
end)
Medium Complexity:
-- Medium: Track table restorations
hook.Add("OnTableRestored", "TrackRestorations", function(tableName, data)
MyAddon.restorations = MyAddon.restorations or {}
table.insert(MyAddon.restorations, {
table = tableName,
records = #data,
time = os.time()
})
end)
High Complexity:
-- High: Complex table restoration handling
hook.Add("OnTableRestored", "AdvancedTableRestoration", function(tableName, data)
-- Log restoration details
lia.log.write("table_restored", {
table = tableName,
records = #data,
timestamp = os.time()
})
-- Notify admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("Table " .. tableName .. " restored (" .. #data .. " records)")
end
end
-- Reload affected systems
if tableName == "lia_characters" then
for _, ply in ipairs(player.GetAll()) do
local char = ply:getChar()
if char then
char:sync()
end
end
end
end)
OnTablesReady
Purpose
Called when all database tables are ready
When Called
After all database tables have been initialized and are ready for use
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log tables ready
hook.Add("OnTablesReady", "MyAddon", function()
print("Database tables are ready")
end)
Medium Complexity:
-- Medium: Initialize data after tables are ready
hook.Add("OnTablesReady", "InitData", function()
lia.data.get("addonData", {}, function(data)
MyAddon.data = data
print("Addon data loaded")
end)
end)
High Complexity:
-- High: Complex initialization after tables are ready
hook.Add("OnTablesReady", "AdvancedInit", function()
-- Load custom data
lia.db.query("SELECT * FROM custom_data", function(data)
if data then
for _, row in ipairs(data) do
MyAddon.customData[row.id] = row.data
end
end
end)
-- Initialize caching
MyAddon.cache = {}
-- Setup periodic data sync
timer.Create("MyAddonDataSync", 300, 0, function()
lia.data.get("addonData", {}, function(data)
MyAddon.data = data
end)
end)
print("Advanced addon initialization complete")
end)
OnTicketClaimed
Purpose
Called when a support ticket is claimed by an admin
When Called
When an admin claims a support ticket
Parameters
client(Player): The admin claiming the ticketrequester(Player): The player who created the ticketticketMessage(string): The ticket message
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log ticket claims
hook.Add("OnTicketClaimed", "MyAddon", function(client, requester, ticketMessage)
print(client:Name() .. " claimed ticket from " .. requester:Name())
end)
Medium Complexity:
-- Medium: Track ticket claims
hook.Add("OnTicketClaimed", "TrackTicketClaims", function(client, requester, ticketMessage)
local char = client:getChar()
if char then
local claims = char:getData("ticketsClaimed", 0)
char:setData("ticketsClaimed", claims + 1)
end
end)
High Complexity:
-- High: Complex ticket claim handling
hook.Add("OnTicketClaimed", "AdvancedTicketClaim", function(client, requester, ticketMessage)
-- Log ticket claim
lia.log.write("ticket_claimed", {
admin = client:SteamID(),
requester = requester:SteamID(),
message = ticketMessage,
timestamp = os.time()
})
-- Notify both parties
client:ChatPrint("You claimed the ticket from " .. requester:Name())
requester:ChatPrint(client:Name() .. " is handling your ticket")
-- Update ticket statistics
local char = client:getChar()
if char then
local stats = char:getData("ticketStats", {claimed = 0, resolved = 0})
stats.claimed = stats.claimed + 1
char:setData("ticketStats", stats)
end
end)
OnTicketClosed
Purpose
Called when a support ticket is closed
When Called
When a support ticket is resolved and closed
Parameters
client(Player): The admin closing the ticketrequester(Player): The player who created the ticketticketMessage(string): The ticket message
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log ticket closures
hook.Add("OnTicketClosed", "MyAddon", function(client, requester, ticketMessage)
print(client:Name() .. " closed ticket from " .. requester:Name())
end)
Medium Complexity:
-- Medium: Track ticket resolutions
hook.Add("OnTicketClosed", "TrackTicketClosures", function(client, requester, ticketMessage)
local char = client:getChar()
if char then
local resolved = char:getData("ticketsResolved", 0)
char:setData("ticketsResolved", resolved + 1)
end
end)
High Complexity:
-- High: Complex ticket closure handling
hook.Add("OnTicketClosed", "AdvancedTicketClosure", function(client, requester, ticketMessage)
-- Log ticket closure
lia.log.write("ticket_closed", {
admin = client:SteamID(),
requester = requester:SteamID(),
message = ticketMessage,
timestamp = os.time()
})
-- Notify both parties
client:ChatPrint("You closed the ticket from " .. requester:Name())
requester:ChatPrint("Your ticket has been resolved by " .. client:Name())
-- Update ticket statistics
local char = client:getChar()
if char then
local stats = char:getData("ticketStats", {claimed = 0, resolved = 0})
stats.resolved = stats.resolved + 1
char:setData("ticketStats", stats)
end
end)
OnTicketCreated
Purpose
Called when a new support ticket is created
When Called
When a player creates a support ticket
Parameters
noob(Player): The player creating the ticketmessage(string): The ticket message
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log ticket creation
hook.Add("OnTicketCreated", "MyAddon", function(noob, message)
print(noob:Name() .. " created a ticket: " .. message)
end)
Medium Complexity:
-- Medium: Notify admins of new tickets
hook.Add("OnTicketCreated", "NotifyAdmins", function(noob, message)
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("New ticket from " .. noob:Name() .. ": " .. message)
end
end
end)
High Complexity:
-- High: Complex ticket creation handling
hook.Add("OnTicketCreated", "AdvancedTicketCreation", function(noob, message)
-- Log ticket creation
lia.log.write("ticket_created", {
player = noob:SteamID(),
message = message,
timestamp = os.time()
})
-- Store ticket in database
lia.db.query("INSERT INTO tickets (player, message, status, created) VALUES (?, ?, ?, ?)",
noob:SteamID(),
message,
"open",
os.time()
)
-- Notify all admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("[TICKET] " .. noob:Name() .. ": " .. message)
surface.PlaySound("buttons/button15.wav")
end
end
-- Confirm to player
noob:ChatPrint("Your ticket has been submitted. An admin will assist you shortly.")
end)
OnTransferFailed
Purpose
Called when an item transfer fails
When Called
When an attempt to transfer items between characters fails
Parameters
fromChar(Character): The character items were being transferred fromtoChar(Character): The character items were being transferred toitems(table): Table of items that failed to transfererr(string): The error message
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log transfer failures
hook.Add("OnTransferFailed", "MyAddon", function(fromChar, toChar, items, err)
print("Transfer failed: " .. err)
end)
Medium Complexity:
-- Medium: Notify players of failure
hook.Add("OnTransferFailed", "NotifyTransferFailure", function(fromChar, toChar, items, err)
local fromPlayer = fromChar:getPlayer()
local toPlayer = toChar:getPlayer()
if IsValid(fromPlayer) then
fromPlayer:ChatPrint("Transfer failed: " .. err)
end
if IsValid(toPlayer) then
toPlayer:ChatPrint("Transfer failed: " .. err)
end
end)
High Complexity:
-- High: Complex transfer failure handling
hook.Add("OnTransferFailed", "AdvancedTransferFailure", function(fromChar, toChar, items, err)
-- Log transfer failure
lia.log.write("transfer_failed", {
from = fromChar:getID(),
to = toChar:getID(),
items = table.Count(items),
error = err,
timestamp = os.time()
})
-- Notify players
local fromPlayer = fromChar:getPlayer()
local toPlayer = toChar:getPlayer()
if IsValid(fromPlayer) then
fromPlayer:ChatPrint("Failed to transfer items: " .. err)
end
if IsValid(toPlayer) then
toPlayer:ChatPrint("Failed to receive items: " .. err)
end
-- Track failure statistics
local stats = fromChar:getData("transferStats", {failed = 0})
stats.failed = (stats.failed or 0) + 1
fromChar:setData("transferStats", stats)
end)
OnTransferred
Purpose
Called when a player is transferred
When Called
When a player is successfully transferred
Parameters
targetPlayer(Player): The player who was transferred
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log player transfers
hook.Add("OnTransferred", "MyAddon", function(targetPlayer)
print(targetPlayer:Name() .. " was transferred")
end)
Medium Complexity:
-- Medium: Track player transfers
hook.Add("OnTransferred", "TrackTransfers", function(targetPlayer)
local char = targetPlayer:getChar()
if char then
local transfers = char:getData("transfers", 0)
char:setData("transfers", transfers + 1)
end
end)
High Complexity:
-- High: Complex transfer handling
hook.Add("OnTransferred", "AdvancedTransfer", function(targetPlayer)
local char = targetPlayer:getChar()
if not char then return end
-- Log transfer
lia.log.write("player_transferred", {
player = targetPlayer:SteamID(),
character = char:getID(),
timestamp = os.time()
})
-- Update transfer statistics
local stats = char:getData("transferStats", {count = 0})
stats.count = stats.count + 1
stats.lastTransfer = os.time()
char:setData("transferStats", stats)
-- Notify player
targetPlayer:ChatPrint("You have been transferred")
-- Sync character data
char:sync()
end)
OnUsergroupCreated
Purpose
Called when a new usergroup is created
When Called
When a usergroup is added to the system
Parameters
groupName(string): The name of the usergroupgroupData(table): The usergroup configuration data
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log usergroup creation
hook.Add("OnUsergroupCreated", "MyAddon", function(groupName, groupData)
print("Usergroup created: " .. groupName)
end)
Medium Complexity:
-- Medium: Track usergroups
hook.Add("OnUsergroupCreated", "TrackUsergroups", function(groupName, groupData)
MyAddon.usergroups = MyAddon.usergroups or {}
MyAddon.usergroups[groupName] = {
data = groupData,
created = os.time()
}
end)
High Complexity:
-- High: Complex usergroup creation handling
hook.Add("OnUsergroupCreated", "AdvancedUsergroupCreation", function(groupName, groupData)
-- Log usergroup creation
lia.log.write("usergroup_created", {
name = groupName,
permissions = groupData.permissions or {},
timestamp = os.time()
})
-- Store usergroup in database
lia.db.query("INSERT INTO usergroups (name, data, created) VALUES (?, ?, ?)",
groupName,
util.TableToJSON(groupData),
os.time()
)
-- Notify admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("New usergroup created: " .. groupName)
end
end
end)
OnUsergroupPermissionsChanged
Purpose
Called when usergroup permissions are changed
When Called
When a usergroup's permissions are modified
Parameters
groupName(string): The name of the usergrouppermissions(table): The new permissions table
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log permission changes
hook.Add("OnUsergroupPermissionsChanged", "MyAddon", function(groupName, permissions)
print("Permissions changed for: " .. groupName)
end)
Medium Complexity:
-- Medium: Track permission changes
hook.Add("OnUsergroupPermissionsChanged", "TrackPermissionChanges", function(groupName, permissions)
MyAddon.permissionHistory = MyAddon.permissionHistory or {}
table.insert(MyAddon.permissionHistory, {
group = groupName,
permissions = permissions,
time = os.time()
})
end)
High Complexity:
-- High: Complex permission change handling
hook.Add("OnUsergroupPermissionsChanged", "AdvancedPermissionChange", function(groupName, permissions)
-- Log permission changes
lia.log.write("permissions_changed", {
group = groupName,
permissions = util.TableToJSON(permissions),
timestamp = os.time()
})
-- Update database
lia.db.query("UPDATE usergroups SET permissions = ? WHERE name = ?",
util.TableToJSON(permissions),
groupName
)
-- Notify affected players
for _, ply in ipairs(player.GetAll()) do
if ply:GetUserGroup() == groupName then
ply:ChatPrint("Your usergroup permissions have been updated")
end
end
-- Notify admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("Permissions updated for " .. groupName)
end
end
end)
OnUsergroupRemoved
Purpose
Called when a usergroup is removed
When Called
When a usergroup is deleted from the system
Parameters
groupName(string): The name of the usergroup being removed
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log usergroup removal
hook.Add("OnUsergroupRemoved", "MyAddon", function(groupName)
print("Usergroup removed: " .. groupName)
end)
Medium Complexity:
-- Medium: Clean up usergroup data
hook.Add("OnUsergroupRemoved", "CleanupUsergroup", function(groupName)
if MyAddon.usergroups and MyAddon.usergroups[groupName] then
MyAddon.usergroups[groupName] = nil
end
end)
High Complexity:
-- High: Complex usergroup removal handling
hook.Add("OnUsergroupRemoved", "AdvancedUsergroupRemoval", function(groupName)
-- Log usergroup removal
lia.log.write("usergroup_removed", {
name = groupName,
timestamp = os.time()
})
-- Remove from database
lia.db.query("DELETE FROM usergroups WHERE name = ?", groupName)
-- Reassign affected players
for _, ply in ipairs(player.GetAll()) do
if ply:GetUserGroup() == groupName then
ply:SetUserGroup("user")
ply:ChatPrint("Your usergroup has been removed. You have been reassigned to 'user'.")
end
end
-- Notify admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("Usergroup removed: " .. groupName)
end
end
end)
OnUsergroupRenamed
Purpose
Called when a usergroup is renamed
When Called
When a usergroup's name is changed
Parameters
oldName(string): The old name of the usergroupnewName(string): The new name of the usergroup
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log usergroup rename
hook.Add("OnUsergroupRenamed", "MyAddon", function(oldName, newName)
print("Usergroup renamed: " .. oldName .. " -> " .. newName)
end)
Medium Complexity:
-- Medium: Update usergroup tracking
hook.Add("OnUsergroupRenamed", "UpdateUsergroupTracking", function(oldName, newName)
if MyAddon.usergroups and MyAddon.usergroups[oldName] then
MyAddon.usergroups[newName] = MyAddon.usergroups[oldName]
MyAddon.usergroups[oldName] = nil
end
end)
High Complexity:
-- High: Complex usergroup rename handling
hook.Add("OnUsergroupRenamed", "AdvancedUsergroupRename", function(oldName, newName)
-- Log usergroup rename
lia.log.write("usergroup_renamed", {
oldName = oldName,
newName = newName,
timestamp = os.time()
})
-- Update database
lia.db.query("UPDATE usergroups SET name = ? WHERE name = ?", newName, oldName)
-- Update all players in this usergroup
for _, ply in ipairs(player.GetAll()) do
if ply:GetUserGroup() == oldName then
ply:SetUserGroup(newName)
ply:ChatPrint("Your usergroup has been renamed to: " .. newName)
end
end
-- Notify admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("Usergroup renamed: " .. oldName .. " -> " .. newName)
end
end
end)
OnVendorEdited
Purpose
Called when a vendor is edited
When Called
When a vendor's properties are modified
Parameters
client(Player): The player editing the vendorvendor(Entity): The vendor entity being editedkey(string): The property being modified
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log vendor edits
hook.Add("OnVendorEdited", "MyAddon", function(client, vendor, key)
print(client:Name() .. " edited vendor property: " .. key)
end)
Medium Complexity:
-- Medium: Validate vendor edits
hook.Add("OnVendorEdited", "VendorValidation", function(client, vendor, key)
if key == "price" then
local newPrice = vendor:getNetVar("price", 0)
if newPrice < 0 then
client:ChatPrint("Price cannot be negative")
return false
end
elseif key == "stock" then
local newStock = vendor:getNetVar("stock", 0)
if newStock < 0 then
client:ChatPrint("Stock cannot be negative")
return false
end
end
end)
High Complexity:
-- High: Complex vendor editing system
hook.Add("OnVendorEdited", "AdvancedVendorEditing", function(client, vendor, key)
local char = client:getChar()
if not char then return end
-- Check if player has permission to edit vendors
if not char:hasFlags("V") then
client:ChatPrint("You don't have permission to edit vendors")
return false
end
-- Validate specific properties
if key == "price" then
local newPrice = vendor:getNetVar("price", 0)
if newPrice < 0 then
client:ChatPrint("Price cannot be negative")
return false
end
-- Check for price limits based on faction
local faction = char:getFaction()
local maxPrice = {
["police"] = 10000,
["medic"] = 8000,
["citizen"] = 5000
}
local limit = maxPrice[faction] or 5000
if newPrice > limit then
client:ChatPrint("Price exceeds your faction limit of $" .. limit)
return false
end
elseif key == "stock" then
local newStock = vendor:getNetVar("stock", 0)
if newStock < 0 then
client:ChatPrint("Stock cannot be negative")
return false
end
-- Check for stock limits
local maxStock = 1000
if newStock > maxStock then
client:ChatPrint("Stock cannot exceed " .. maxStock)
return false
end
elseif key == "faction" then
local newFaction = vendor:getNetVar("faction", "citizen")
local allowedFactions = {"police", "medic", "citizen", "criminal"}
if not table.HasValue(allowedFactions, newFaction) then
client:ChatPrint("Invalid faction: " .. newFaction)
return false
end
end
-- Log the edit
print(string.format("%s edited vendor %s property %s to %s",
client:Name(), vendor:EntIndex(), key, tostring(vendor:getNetVar(key))))
-- Notify other admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() and ply ~= client then
ply:ChatPrint("[ADMIN] " .. client:Name() .. " edited vendor " .. vendor:EntIndex() .. " (" .. key .. ")")
end
end
end)
OnlineStaffDataReceived
Purpose
Called when online staff data is received
When Called
When the server receives updated staff information
Parameters
staffData(table): The staff data containing online staff information
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log staff data
hook.Add("OnlineStaffDataReceived", "MyAddon", function(staffData)
print("Received staff data for " .. table.Count(staffData) .. " staff members")
end)
Medium Complexity:
-- Medium: Track online staff
hook.Add("OnlineStaffDataReceived", "TrackStaff", function(staffData)
MyAddon.onlineStaff = MyAddon.onlineStaff or {}
for steamID, data in pairs(staffData) do
MyAddon.onlineStaff[steamID] = {
name = data.name,
rank = data.rank,
lastSeen = os.time()
}
end
end)
High Complexity:
-- High: Complex staff management
hook.Add("OnlineStaffDataReceived", "AdvancedStaffManagement", function(staffData)
-- Log staff data update
lia.log.write("staff_data_received", {
count = table.Count(staffData),
timestamp = os.time()
})
-- Update staff database
for steamID, data in pairs(staffData) do
lia.db.query("INSERT OR REPLACE INTO staff_data (steamid, name, rank, last_seen) VALUES (?, ?, ?, ?)",
steamID,
data.name,
data.rank,
os.time()
)
end
-- Notify players of staff changes
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("Staff data updated")
end
end
end)
OptionReceived
Purpose
Called when a client option is received
When Called
When the server receives an option setting from a client
Parameters
client(Player): The player who sent the optionkey(string): The option keyvalue(any): The option value
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log option changes
hook.Add("OptionReceived", "MyAddon", function(client, key, value)
print(client:Name() .. " changed option " .. key .. " to " .. tostring(value))
end)
Medium Complexity:
-- Medium: Track option changes
hook.Add("OptionReceived", "TrackOptions", function(client, key, value)
local char = client:getChar()
if char then
local options = char:getData("options", {})
options[key] = value
char:setData("options", options)
end
end)
High Complexity:
-- High: Complex option handling
hook.Add("OptionReceived", "AdvancedOptionHandling", function(client, key, value)
-- Log option change
lia.log.write("option_changed", {
player = client:SteamID(),
key = key,
value = tostring(value),
timestamp = os.time()
})
-- Validate option value
if key == "volume" and (value < 0 or value > 1) then
client:ChatPrint("Invalid volume value")
return
end
-- Store option in character data
local char = client:getChar()
if char then
local options = char:getData("options", {})
options[key] = value
char:setData("options", options)
end
end)
OverrideSpawnTime
Purpose
Called to override a player's respawn time
When Called
When a player's respawn time needs to be modified
Parameters
client(Player): The player respawningrespawnTime(number): The current respawn time in seconds
Returns
- number - The overridden respawn time (or nil to use default)
Realm
Server
Example Usage
Low Complexity:
-- Simple: Reduce respawn time
hook.Add("OverrideSpawnTime", "MyAddon", function(client, respawnTime)
return respawnTime * 0.5
end)
Medium Complexity:
-- Medium: Faction-based respawn times
hook.Add("OverrideSpawnTime", "FactionRespawnTime", function(client, respawnTime)
local char = client:getChar()
if not char then return end
local faction = char:getFaction()
if faction == FACTION_POLICE then
return 30
elseif faction == FACTION_MEDIC then
return 20
end
end)
High Complexity:
-- High: Dynamic respawn time system
hook.Add("OverrideSpawnTime", "DynamicRespawnTime", function(client, respawnTime)
local char = client:getChar()
if not char then return end
-- Check for respawn time reduction items
local inventory = char:getInv()
if inventory then
for _, item in pairs(inventory:getItems()) do
if item.reduceRespawnTime then
respawnTime = respawnTime * 0.75
end
end
end
-- Check for VIP status
if client:IsUserGroup("vip") then
respawnTime = respawnTime * 0.5
end
-- Check death count
local deaths = char:getData("deaths", 0)
if deaths > 5 then
respawnTime = respawnTime + (deaths * 2)
end
return math.max(respawnTime, 5)
end)
PlayerAccessVendor
Purpose
Called when a player accesses a vendor
When Called
When a player interacts with a vendor entity
Parameters
activator(Player): The player accessing the vendorself(Entity): The vendor entity
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log vendor access
hook.Add("PlayerAccessVendor", "MyAddon", function(activator, self)
print(activator:Name() .. " accessed a vendor")
end)
Medium Complexity:
-- Medium: Track vendor usage
hook.Add("PlayerAccessVendor", "TrackVendorUsage", function(activator, self)
local char = activator:getChar()
if char then
local vendorUses = char:getData("vendorUses", 0)
char:setData("vendorUses", vendorUses + 1)
end
end)
High Complexity:
-- High: Complex vendor access tracking
hook.Add("PlayerAccessVendor", "AdvancedVendorAccess", function(activator, self)
local char = activator:getChar()
if not char then return end
-- Track vendor usage
local vendorUses = char:getData("vendorUses", 0)
char:setData("vendorUses", vendorUses + 1)
-- Log to database
local vendorID = self:getNetVar("vendorID", "unknown")
lia.db.query("INSERT INTO vendor_logs (timestamp, charid, vendorid) VALUES (?, ?, ?)",
os.time(), char:getID(), vendorID)
-- Apply first-time bonus
if vendorUses == 0 then
activator:ChatPrint("First time using a vendor! Here's a discount.")
self:setNetVar("discount_" .. char:getID(), 10)
end
-- Check for achievements
if vendorUses + 1 >= 100 then
if not char:getData("achievement_shopaholic", false) then
char:setData("achievement_shopaholic", true)
activator:ChatPrint("Achievement unlocked: Shopaholic!")
end
end
end)
PlayerCheatDetected
Purpose
Called when a player is detected cheating
When Called
When anti-cheat systems detect suspicious behavior
Parameters
client(Player): The player who was detected cheating
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log cheat detection
hook.Add("PlayerCheatDetected", "MyAddon", function(client)
print("Cheat detected: " .. client:Name())
end)
Medium Complexity:
-- Medium: Handle cheat detection
hook.Add("PlayerCheatDetected", "HandleCheating", function(client)
client:Kick("Cheating detected")
-- Notify admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("Player " .. client:Name() .. " was kicked for cheating")
end
end
end)
High Complexity:
-- High: Complex cheat detection handling
hook.Add("PlayerCheatDetected", "AdvancedCheatDetection", function(client)
-- Log cheat detection
lia.log.write("cheat_detected", {
player = client:SteamID(),
name = client:Name(),
ip = client:IPAddress(),
timestamp = os.time()
})
-- Record cheat attempt
lia.db.query("INSERT INTO cheat_logs (steamid, name, ip, timestamp) VALUES (?, ?, ?, ?)",
client:SteamID(),
client:Name(),
client:IPAddress(),
os.time()
)
-- Apply punishment based on history
local char = client:getChar()
if char then
local cheatCount = char:getData("cheatCount", 0) + 1
char:setData("cheatCount", cheatCount)
if cheatCount >= 3 then
client:Ban(0, "Multiple cheat violations")
else
client:Kick("Cheating detected (Warning " .. cheatCount .. "/3)")
end
end
-- Notify all admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("[CHEAT] " .. client:Name() .. " detected and punished")
end
end
end)
PlayerDisconnect
Purpose
Called when a player disconnects
When Called
When a player leaves the server
Parameters
client(Player): The player disconnecting
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log disconnect
hook.Add("PlayerDisconnect", "MyAddon", function(client)
print(client:Name() .. " disconnected")
end)
Medium Complexity:
-- Medium: Save player data on disconnect
hook.Add("PlayerDisconnect", "SaveOnDisconnect", function(client)
local char = client:getChar()
if char then
char:save()
end
end)
High Complexity:
-- High: Complex disconnect handling
hook.Add("PlayerDisconnect", "AdvancedDisconnect", function(client)
local char = client:getChar()
if char then
-- Save character data
char:save()
-- Update playtime
local sessionStart = char:getData("sessionStart", os.time())
local sessionTime = os.time() - sessionStart
local totalPlaytime = char:getData("playTime", 0)
char:setData("playTime", totalPlaytime + sessionTime)
-- Log disconnect
lia.db.query("INSERT INTO disconnect_logs (timestamp, steamid, charid, playtime) VALUES (?, ?, ?, ?)",
os.time(), client:SteamID(), char:getID(), sessionTime)
end
-- Notify other players
for _, ply in ipairs(player.GetAll()) do
if ply ~= client then
ply:ChatPrint(client:Name() .. " has disconnected")
end
end
end)
PlayerGagged
Purpose
Called when a player is gagged
When Called
When a player's voice chat is disabled
Parameters
target(Player): The player being gaggedadmin(Player): The admin issuing the gag
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log gag
hook.Add("PlayerGagged", "MyAddon", function(target, admin)
print(target:Name() .. " was gagged by " .. admin:Name())
end)
Medium Complexity:
-- Medium: Track gag history
hook.Add("PlayerGagged", "TrackGagHistory", function(target, admin)
local char = target:getChar()
if char then
local gagHistory = char:getData("gagHistory", {})
table.insert(gagHistory, {admin = admin:SteamID(), time = os.time()})
char:setData("gagHistory", gagHistory)
end
end)
High Complexity:
-- High: Complex gag management
hook.Add("PlayerGagged", "AdvancedGagManagement", function(target, admin)
local char = target:getChar()
if not char then return end
-- Track gag history
local gagHistory = char:getData("gagHistory", {})
table.insert(gagHistory, {
admin = admin:SteamID(),
adminName = admin:Name(),
time = os.time()
})
char:setData("gagHistory", gagHistory)
-- Log to database
lia.db.query("INSERT INTO gag_logs (timestamp, target_steamid, admin_steamid) VALUES (?, ?, ?)",
os.time(), target:SteamID(), admin:SteamID())
-- Notify player
target:ChatPrint("You have been gagged by " .. admin:Name())
-- Notify other admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() and ply ~= admin and ply ~= target then
ply:ChatPrint("[ADMIN] " .. admin:Name() .. " gagged " .. target:Name())
end
end
end)
PlayerLiliaDataLoaded
Purpose
Called when a player's Lilia data is loaded
When Called
When a player's framework data has been loaded from the database
Parameters
client(Player): The player whose data was loaded
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log data loading
hook.Add("PlayerLiliaDataLoaded", "MyAddon", function(client)
print("Lilia data loaded for " .. client:Name())
end)
Medium Complexity:
-- Medium: Initialize player after data load
hook.Add("PlayerLiliaDataLoaded", "InitPlayer", function(client)
local char = client:getChar()
if char then
char:setData("addonInitialized", true)
end
end)
High Complexity:
-- High: Complex data loading handling
hook.Add("PlayerLiliaDataLoaded", "AdvancedDataLoading", function(client)
local char = client:getChar()
if not char then return end
-- Log data loading
lia.log.write("player_data_loaded", {
player = client:SteamID(),
character = char:getID(),
timestamp = os.time()
})
-- Load custom player data
lia.data.get("player_" .. client:SteamID(), {}, function(data)
client.customData = data
end)
-- Initialize player systems
if MyAddon.playerSystems then
MyAddon.playerSystems:InitializePlayer(client)
end
-- Sync data to client
net.Start("liaPlayerDataSync")
net.WriteTable(client.customData or {})
net.Send(client)
end)
PlayerLoadedChar
Purpose
Called when a player loads a character
When Called
When a player successfully loads a character
Parameters
client(Player): The player loading the charactercharacter(Character): The character being loadedcurrentChar(Character): The previously loaded character (if any)
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log character loading
hook.Add("PlayerLoadedChar", "MyAddon", function(client, character, currentChar)
print(client:Name() .. " loaded character: " .. character:getName())
end)
Medium Complexity:
-- Medium: Handle character switching
hook.Add("PlayerLoadedChar", "CharSwitching", function(client, character, currentChar)
if currentChar then
-- Save previous character data
currentChar:setData("lastSwitch", os.time())
currentChar:setData("switchPos", client:GetPos())
end
-- Set up new character
character:setData("lastLoad", os.time())
character:setData("loadCount", (character:getData("loadCount", 0) + 1))
client:ChatPrint("Character loaded: " .. character:getName())
end)
High Complexity:
-- High: Complex character loading system
hook.Add("PlayerLoadedChar", "AdvancedCharLoading", function(client, character, currentChar)
-- Handle previous character cleanup
if currentChar then
currentChar:setData("lastSwitch", os.time())
currentChar:setData("switchPos", client:GetPos())
currentChar:setData("switchHealth", client:Health())
currentChar:setData("switchArmor", client:Armor())
end
-- Set up new character
character:setData("lastLoad", os.time())
character:setData("loadCount", (character:getData("loadCount", 0) + 1))
-- Apply faction bonuses
local faction = character:getFaction()
local factionBonuses = {
["police"] = {
authority = 5,
salary = 1000,
items = {"police_badge", "handcuffs", "radio"}
},
["medic"] = {
healingBonus = 1.5,
medicalKnowledge = 10,
salary = 800,
items = {"medkit", "stethoscope", "bandage"}
},
["citizen"] = {
authority = 0,
salary = 500,
items = {"wallet", "phone"}
}
}
local bonuses = factionBonuses[faction]
if bonuses then
-- Apply stat bonuses
for stat, value in pairs(bonuses) do
if stat ~= "items" then
character:setData(stat, value)
end
end
-- Give faction items
if bonuses.items then
local inventory = character:getInv()
for _, itemID in ipairs(bonuses.items) do
local item = lia.item.instance(itemID)
if item then
inventory:add(item)
end
end
end
end
-- Check for returning player bonuses
local lastLoad = character:getData("lastLoad", 0)
local timeSinceLoad = os.time() - lastLoad
if timeSinceLoad > 86400 then -- 24 hours
character:setData("returningPlayerBonus", true)
client:ChatPrint("Welcome back! You have a returning player bonus.")
end
-- Update character appearance
hook.Run("SetupPlayerModel", client, character)
-- Notify other players
for _, ply in ipairs(player.GetAll()) do
if ply ~= client then
ply:ChatPrint(client:Name() .. " is now playing as " .. character:getName())
end
end
-- Log character load
print(string.format("%s loaded character %s (Faction: %s)",
client:Name(), character:getName(), faction))
end)
PlayerMessageSend
Purpose
Called when a player sends a message
When Called
When a chat message is being sent
Parameters
speaker(Player): The player sending the messagechatType(string): The type of chattext(string): The message textanonymous(boolean): Whether the message is anonymousreceivers(table): The players receiving the message
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log messages
hook.Add("PlayerMessageSend", "MyAddon", function(speaker, chatType, text, anonymous, receivers)
print(speaker:Name() .. " sent: " .. text)
end)
Medium Complexity:
-- Medium: Filter inappropriate messages
hook.Add("PlayerMessageSend", "FilterMessages", function(speaker, chatType, text, anonymous, receivers)
local bannedWords = {"spam", "hack"}
for _, word in ipairs(bannedWords) do
if string.find(string.lower(text), word) then
speaker:ChatPrint("Your message was blocked")
return false
end
end
end)
High Complexity:
-- High: Complex message handling
hook.Add("PlayerMessageSend", "AdvancedMessageHandling", function(speaker, chatType, text, anonymous, receivers)
local char = speaker:getChar()
if not char then return false end
-- Filter inappropriate content
local bannedWords = {"spam", "hack", "cheat"}
for _, word in ipairs(bannedWords) do
if string.find(string.lower(text), word) then
speaker:ChatPrint("Your message was blocked for inappropriate content")
return false
end
end
-- Check spam protection
local lastMessage = char:getData("lastMessage", 0)
if os.time() - lastMessage < 1 then
speaker:ChatPrint("Please wait before sending another message")
return false
end
char:setData("lastMessage", os.time())
-- Log to database
lia.db.query("INSERT INTO chat_logs (timestamp, steamid, chattype, message) VALUES (?, ?, ?, ?)",
os.time(), speaker:SteamID(), chatType, text)
-- Track message count
local messageCount = char:getData("messageCount", 0)
char:setData("messageCount", messageCount + 1)
end)
PlayerModelChanged
Purpose
Called when a player's model changes
When Called
When a player's character model is changed
Parameters
client(Player): The player whose model changedvalue(string): The new model path
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log model change
hook.Add("PlayerModelChanged", "MyAddon", function(client, value)
print(client:Name() .. " model changed to " .. value)
end)
Medium Complexity:
-- Medium: Track model changes
hook.Add("PlayerModelChanged", "TrackModelChanges", function(client, value)
local char = client:getChar()
if char then
local modelHistory = char:getData("modelHistory", {})
table.insert(modelHistory, {model = value, time = os.time()})
char:setData("modelHistory", modelHistory)
end
end)
High Complexity:
-- High: Complex model change tracking
hook.Add("PlayerModelChanged", "AdvancedModelTracking", function(client, value)
local char = client:getChar()
if not char then return end
-- Track model history
local modelHistory = char:getData("modelHistory", {})
table.insert(modelHistory, {model = value, time = os.time()})
char:setData("modelHistory", modelHistory)
-- Log to database
lia.db.query("INSERT INTO model_logs (timestamp, charid, model) VALUES (?, ?, ?)",
os.time(), char:getID(), value)
-- Apply model-specific effects
local gender = hook.Run("GetModelGender", value) or "male"
char:setData("gender", gender)
-- Notify nearby players
for _, ply in ipairs(player.GetAll()) do
if ply ~= client and ply:GetPos():Distance(client:GetPos()) < 500 then
ply:ChatPrint(client:Name() .. " changed their appearance")
end
end
end)
PlayerMuted
Purpose
Called when a player is muted
When Called
When a player's chat is disabled
Parameters
target(Player): The player being mutedadmin(Player): The admin issuing the mute
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log mute
hook.Add("PlayerMuted", "MyAddon", function(target, admin)
print(target:Name() .. " was muted by " .. admin:Name())
end)
Medium Complexity:
-- Medium: Track mute history
hook.Add("PlayerMuted", "TrackMuteHistory", function(target, admin)
local char = target:getChar()
if char then
local muteHistory = char:getData("muteHistory", {})
table.insert(muteHistory, {admin = admin:SteamID(), time = os.time()})
char:setData("muteHistory", muteHistory)
end
end)
High Complexity:
-- High: Complex mute management
hook.Add("PlayerMuted", "AdvancedMuteManagement", function(target, admin)
local char = target:getChar()
if not char then return end
-- Track mute history
local muteHistory = char:getData("muteHistory", {})
table.insert(muteHistory, {
admin = admin:SteamID(),
adminName = admin:Name(),
time = os.time()
})
char:setData("muteHistory", muteHistory)
-- Log to database
lia.db.query("INSERT INTO mute_logs (timestamp, target_steamid, admin_steamid) VALUES (?, ?, ?)",
os.time(), target:SteamID(), admin:SteamID())
-- Notify player
target:ChatPrint("You have been muted by " .. admin:Name())
-- Notify other admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() and ply ~= admin and ply ~= target then
ply:ChatPrint("[ADMIN] " .. admin:Name() .. " muted " .. target:Name())
end
end
end)
PlayerShouldAct
Purpose
Called to check if a player should perform an action
When Called
When validating player actions
Returns
- boolean - True to allow, false to deny
Realm
Server
Example Usage
Low Complexity:
Medium Complexity:
-- Medium: Check player state
hook.Add("PlayerShouldAct", "CheckPlayerState", function()
local client = LocalPlayer()
if not IsValid(client) then return false end
local char = client:getChar()
return char ~= nil
end)
High Complexity:
-- High: Complex action validation
hook.Add("PlayerShouldAct", "AdvancedActionValidation", function()
local client = LocalPlayer()
if not IsValid(client) then return false end
local char = client:getChar()
if not char then return false end
-- Check if player is tied
if char:getData("tied", false) then
return false
end
-- Check if player is stunned
if char:getData("stunned", false) then
return false
end
-- Check if player is in cutscene
if char:getData("inCutscene", false) then
return false
end
return true
end)
PlayerShouldPermaKill
Purpose
Called to check if a player should be permakilled
When Called
When a player dies and permakill is being considered
Parameters
client(Player): The dying playerinflictor(Entity): The entity that caused deathattacker(Entity): The attacker
Returns
- boolean - True to permakill, false otherwise
Realm
Server
Example Usage
Low Complexity:
-- Simple: Never permakill
hook.Add("PlayerShouldPermaKill", "MyAddon", function(client, inflictor, attacker)
return false
end)
Medium Complexity:
-- Medium: Permakill on admin command
hook.Add("PlayerShouldPermaKill", "AdminPermakill", function(client, inflictor, attacker)
local char = client:getChar()
if char and char:getData("markedForPK", false) then
return true
end
return false
end)
High Complexity:
-- High: Complex permakill system
hook.Add("PlayerShouldPermaKill", "AdvancedPermakill", function(client, inflictor, attacker)
local char = client:getChar()
if not char then return false end
-- Check if marked for PK
if char:getData("markedForPK", false) then
return true
end
-- Check faction-specific rules
local faction = char:getFaction()
if faction == "police" then
-- Police can only be PKed by admins
if IsValid(attacker) and attacker:IsPlayer() and attacker:IsAdmin() then
return true
end
return false
end
-- Check death count
local deathCount = char:getData("deathCount", 0)
if deathCount >= 5 then
-- Too many deaths, permakill
return true
end
return false
end)
PlayerSpawnPointSelected
Purpose
Called when a player spawn point is selected
When Called
When determining where a player should spawn
Parameters
client(Player): The player spawningpos(Vector): The spawn positionang(Angle): The spawn angle
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log spawn point
hook.Add("PlayerSpawnPointSelected", "MyAddon", function(client, pos, ang)
print(client:Name() .. " spawning at " .. tostring(pos))
end)
Medium Complexity:
-- Medium: Track spawn locations
hook.Add("PlayerSpawnPointSelected", "TrackSpawnLocations", function(client, pos, ang)
local char = client:getChar()
if char then
char:setData("lastSpawnPos", pos)
char:setData("lastSpawnAng", ang)
end
end)
High Complexity:
-- High: Complex spawn tracking
hook.Add("PlayerSpawnPointSelected", "AdvancedSpawnTracking", function(client, pos, ang)
local char = client:getChar()
if not char then return end
-- Track spawn location
char:setData("lastSpawnPos", pos)
char:setData("lastSpawnAng", ang)
char:setData("lastSpawnTime", os.time())
-- Log to database
lia.db.query("INSERT INTO spawn_logs (timestamp, charid, x, y, z) VALUES (?, ?, ?, ?, ?)",
os.time(), char:getID(), pos.x, pos.y, pos.z)
-- Track spawn count
local spawnCount = char:getData("spawnCount", 0)
char:setData("spawnCount", spawnCount + 1)
-- Apply spawn effects
client:SetHealth(100)
client:SetArmor(0)
end)
PlayerThrowPunch
Purpose
Called when a player throws a punch
When Called
When a player uses their fists to attack
Parameters
client(Player): The player throwing the punch
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log punch
hook.Add("PlayerThrowPunch", "MyAddon", function(client)
print(client:Name() .. " threw a punch")
end)
Medium Complexity:
-- Medium: Track punch count
hook.Add("PlayerThrowPunch", "TrackPunches", function(client)
local char = client:getChar()
if char then
local punchCount = char:getData("punchCount", 0)
char:setData("punchCount", punchCount + 1)
end
end)
High Complexity:
-- High: Complex punch tracking system
hook.Add("PlayerThrowPunch", "AdvancedPunchTracking", function(client)
local char = client:getChar()
if not char then return end
-- Track punch count
local punchCount = char:getData("punchCount", 0)
char:setData("punchCount", punchCount + 1)
-- Drain stamina
local stamina = client:getNetVar("stamina", 100)
client:setNetVar("stamina", math.max(0, stamina - 5))
-- Check for achievements
if punchCount + 1 >= 500 then
if not char:getData("achievement_brawler", false) then
char:setData("achievement_brawler", true)
client:ChatPrint("Achievement unlocked: Brawler!")
end
end
end)
PlayerUngagged
Purpose
Called when a player is ungagged
When Called
When a player's voice chat is re-enabled
Parameters
target(Player): The player being ungaggedadmin(Player): The admin removing the gag
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log ungag
hook.Add("PlayerUngagged", "MyAddon", function(target, admin)
print(target:Name() .. " was ungagged by " .. admin:Name())
end)
Medium Complexity:
-- Medium: Notify player
hook.Add("PlayerUngagged", "NotifyUngag", function(target, admin)
target:ChatPrint("You have been ungagged by " .. admin:Name())
end)
High Complexity:
-- High: Complex ungag management
hook.Add("PlayerUngagged", "AdvancedUngagManagement", function(target, admin)
-- Log to database
lia.db.query("INSERT INTO ungag_logs (timestamp, target_steamid, admin_steamid) VALUES (?, ?, ?)",
os.time(), target:SteamID(), admin:SteamID())
-- Notify player
target:ChatPrint("You have been ungagged by " .. admin:Name())
-- Notify other admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() and ply ~= admin and ply ~= target then
ply:ChatPrint("[ADMIN] " .. admin:Name() .. " ungagged " .. target:Name())
end
end
end)
PlayerUnmuted
Purpose
Called when a player is unmuted
When Called
When a player's chat is re-enabled
Parameters
target(Player): The player being unmutedadmin(Player): The admin removing the mute
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log unmute
hook.Add("PlayerUnmuted", "MyAddon", function(target, admin)
print(target:Name() .. " was unmuted by " .. admin:Name())
end)
Medium Complexity:
-- Medium: Notify player
hook.Add("PlayerUnmuted", "NotifyUnmute", function(target, admin)
target:ChatPrint("You have been unmuted by " .. admin:Name())
end)
High Complexity:
-- High: Complex unmute management
hook.Add("PlayerUnmuted", "AdvancedUnmuteManagement", function(target, admin)
-- Log to database
lia.db.query("INSERT INTO unmute_logs (timestamp, target_steamid, admin_steamid) VALUES (?, ?, ?)",
os.time(), target:SteamID(), admin:SteamID())
-- Notify player
target:ChatPrint("You have been unmuted by " .. admin:Name())
-- Notify other admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() and ply ~= admin and ply ~= target then
ply:ChatPrint("[ADMIN] " .. admin:Name() .. " unmuted " .. target:Name())
end
end
end)
PlayerUseDoor
Purpose
Called when a player uses a door
When Called
When a player interacts with a door entity
Parameters
client(Player): The player using the doordoor(Entity): The door entity
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log door usage
hook.Add("PlayerUseDoor", "MyAddon", function(client, door)
print(client:Name() .. " used a door")
end)
Medium Complexity:
-- Medium: Track door usage
hook.Add("PlayerUseDoor", "TrackDoorUsage", function(client, door)
local char = client:getChar()
if char then
local doorUses = char:getData("doorUses", 0)
char:setData("doorUses", doorUses + 1)
end
end)
High Complexity:
-- High: Complex door usage tracking
hook.Add("PlayerUseDoor", "AdvancedDoorUsage", function(client, door)
local char = client:getChar()
if not char then return end
-- Track door usage
local doorUses = char:getData("doorUses", 0)
char:setData("doorUses", doorUses + 1)
-- Log to database
local doorID = door:MapCreationID()
lia.db.query("INSERT INTO door_usage_logs (timestamp, charid, doorid) VALUES (?, ?, ?)",
os.time(), char:getID(), doorID)
-- Check for achievements
if doorUses + 1 >= 1000 then
if not char:getData("achievement_doorman", false) then
char:setData("achievement_doorman", true)
client:ChatPrint("Achievement unlocked: Doorman!")
end
end
end)
PostDoorDataLoad
Purpose
Called after door data is loaded
When Called
After door configuration data is loaded from the database
Parameters
ent(Entity): The door entitydoorData(table): The door data that was loaded
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log door data load
hook.Add("PostDoorDataLoad", "MyAddon", function(ent, doorData)
print("Door data loaded for entity " .. ent:EntIndex())
end)
Medium Complexity:
-- Medium: Apply custom door settings
hook.Add("PostDoorDataLoad", "CustomDoorSettings", function(ent, doorData)
if doorData.customLocked then
ent:Fire("Lock")
end
end)
High Complexity:
-- High: Complex door data processing
hook.Add("PostDoorDataLoad", "AdvancedDoorDataProcessing", function(ent, doorData)
if not IsValid(ent) or not doorData then return end
-- Apply door settings
if doorData.locked then
ent:Fire("Lock")
else
ent:Fire("Unlock")
end
-- Set door title
if doorData.title then
ent:setNetVar("title", doorData.title)
end
-- Set door price
if doorData.price then
ent:setNetVar("price", doorData.price)
end
-- Set door owner
if doorData.owner then
ent:setNetVar("owner", doorData.owner)
end
-- Apply faction restrictions
if doorData.allowedFactions then
ent:setNetVar("allowedFactions", doorData.allowedFactions)
end
-- Log door data load
print(string.format("Door data loaded for entity %d: Title=%s, Price=%s, Owner=%s",
ent:EntIndex(),
doorData.title or "None",
doorData.price or "None",
doorData.owner or "None"))
end)
PostLoadData
Purpose
Called after data is loaded
When Called
After all persistent data has been loaded
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log data load completion
hook.Add("PostLoadData", "MyAddon", function()
print("Data loaded")
end)
Medium Complexity:
-- Medium: Initialize systems after data load
hook.Add("PostLoadData", "InitializeSystems", function()
MyAddon.Initialize()
print("Systems initialized after data load")
end)
High Complexity:
-- High: Complex post-load initialization
hook.Add("PostLoadData", "AdvancedPostLoadInit", function()
-- Initialize custom systems
MyAddon.Initialize()
-- Validate loaded data
local data = lia.data.get("myAddonData", {})
if not data or table.IsEmpty(data) then
print("Warning: No data found, using defaults")
data = MyAddon.GetDefaultData()
lia.data.set("myAddonData", data)
end
-- Set up timers
timer.Create("MyAddonDataSave", 300, 0, function()
MyAddon.SaveData()
end)
print("Post-load initialization completed")
end)
PostPlayerInitialSpawn
Purpose
Called after a player's initial spawn
When Called
After a player has fully spawned for the first time
Parameters
client(Player): The player who spawned
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Welcome message
hook.Add("PostPlayerInitialSpawn", "MyAddon", function(client)
client:ChatPrint("Welcome to the server!")
end)
Medium Complexity:
-- Medium: Give starting items
hook.Add("PostPlayerInitialSpawn", "GiveStartingItems", function(client)
timer.Simple(1, function()
if IsValid(client) then
local char = client:getChar()
if char then
local inv = char:getInv()
if inv then
local item = lia.item.instance("item_bandage")
if item then
inv:add(item)
end
end
end
end
end)
end)
High Complexity:
-- High: Complex spawn initialization
hook.Add("PostPlayerInitialSpawn", "AdvancedSpawnInit", function(client)
timer.Simple(1, function()
if not IsValid(client) then return end
local char = client:getChar()
if not char then return end
-- Give starting items
local inv = char:getInv()
if inv then
local startingItems = {"item_bandage", "item_water", "item_food"}
for _, itemID in ipairs(startingItems) do
local item = lia.item.instance(itemID)
if item then
inv:add(item)
end
end
end
-- Set starting money
if char:getMoney() == 0 then
char:giveMoney(500)
client:ChatPrint("You received $500 starting money")
end
-- Apply first-time bonuses
local playTime = client:GetUTimeTotalTime()
if playTime == 0 then
char:setData("firstTimeBonus", true)
client:ChatPrint("Welcome! You received a first-time bonus!")
end
end)
end)
PostPlayerLoadedChar
Purpose
Called after a player has loaded a character
When Called
After a character has been fully loaded for a player
Parameters
client(Player): The playercharacter(Character): The character that was loadedcurrentChar(Character): The previous character (if any)
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Welcome message
hook.Add("PostPlayerLoadedChar", "MyAddon", function(client, character, currentChar)
client:ChatPrint("Welcome back, " .. character:getName())
end)
Medium Complexity:
-- Medium: Restore character state
hook.Add("PostPlayerLoadedChar", "RestoreCharState", function(client, character, currentChar)
local health = character:getData("savedHealth", 100)
client:SetHealth(health)
local armor = character:getData("savedArmor", 0)
client:SetArmor(armor)
end)
High Complexity:
-- High: Complex character load handling
hook.Add("PostPlayerLoadedChar", "AdvancedCharLoad", function(client, character, currentChar)
-- Restore character state
local health = character:getData("savedHealth", 100)
client:SetHealth(health)
local armor = character:getData("savedArmor", 0)
client:SetArmor(armor)
-- Restore position if saved
local savedPos = character:getData("savedPosition")
if savedPos then
client:SetPos(savedPos)
end
-- Update session data
character:setData("sessionStart", os.time())
character:setData("lastLogin", os.time())
-- Notify faction members
local faction = character:getFaction()
for _, ply in ipairs(player.GetAll()) do
if ply ~= client then
local plyChar = ply:getChar()
if plyChar and plyChar:getFaction() == faction then
ply:ChatPrint(character:getName() .. " has joined the server")
end
end
end
end)
PostPlayerLoadout
Purpose
Called after a player's loadout is given
When Called
After a player has received their weapons/equipment
Parameters
client(Player): The player who received loadout
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log loadout
hook.Add("PostPlayerLoadout", "MyAddon", function(client)
print(client:Name() .. " received loadout")
end)
Medium Complexity:
-- Medium: Give additional items
hook.Add("PostPlayerLoadout", "GiveAdditionalItems", function(client)
local char = client:getChar()
if char and char:getData("vip", false) then
client:Give("weapon_pistol")
end
end)
High Complexity:
-- High: Complex loadout system
hook.Add("PostPlayerLoadout", "AdvancedLoadout", function(client)
local char = client:getChar()
if not char then return end
-- Give faction-specific weapons
local faction = char:getFaction()
if faction == "police" then
client:Give("weapon_pistol")
client:Give("weapon_stunstick")
elseif faction == "medic" then
client:Give("weapon_medkit")
end
-- Give VIP bonuses
if char:getData("vip", false) then
client:SetMaxHealth(150)
client:SetHealth(150)
client:SetArmor(50)
end
-- Apply class bonuses
local class = char:getData("class")
if class == "warrior" then
client:SetMaxHealth(200)
client:SetHealth(200)
elseif class == "scout" then
client:SetRunSpeed(300)
client:SetWalkSpeed(150)
end
end)
PostPlayerSay
Purpose
Called after a player says something in chat
When Called
After a chat message has been processed and sent
Parameters
client(Player): The player who spokemessage(string): The message that was sentchatType(string): The type of chatanonymous(boolean): Whether the message was anonymous
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log chat messages
hook.Add("PostPlayerSay", "MyAddon", function(client, message, chatType, anonymous)
print(client:Name() .. " said: " .. message)
end)
Medium Complexity:
-- Medium: Track chat statistics
hook.Add("PostPlayerSay", "TrackChatStats", function(client, message, chatType, anonymous)
local char = client:getChar()
if char then
local messageCount = char:getData("messageCount", 0)
char:setData("messageCount", messageCount + 1)
end
end)
High Complexity:
-- High: Complex chat tracking system
hook.Add("PostPlayerSay", "AdvancedChatTracking", function(client, message, chatType, anonymous)
local char = client:getChar()
if not char then return end
-- Track message count
local messageCount = char:getData("messageCount", 0)
char:setData("messageCount", messageCount + 1)
-- Log to database
lia.db.query("INSERT INTO chat_logs (timestamp, charid, chattype, message, anonymous) VALUES (?, ?, ?, ?, ?)",
os.time(), char:getID(), chatType, message, anonymous and 1 or 0)
-- Check for achievements
if messageCount + 1 >= 1000 then
if not char:getData("achievement_chatty", false) then
char:setData("achievement_chatty", true)
client:ChatPrint("Achievement unlocked: Chatty!")
end
end
end)
PostScaleDamage
Purpose
Called after damage scaling is calculated
When Called
After damage has been scaled but before it's applied
Parameters
hitgroup(number): The hitgroup that was hitdmgInfo(CTakeDamageInfo): The damage infodamageScale(number): The calculated damage scale
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log damage scaling
hook.Add("PostScaleDamage", "MyAddon", function(hitgroup, dmgInfo, damageScale)
print("Damage scaled to: " .. damageScale)
end)
Medium Complexity:
-- Medium: Apply damage effects
hook.Add("PostScaleDamage", "ApplyDamageEffects", function(hitgroup, dmgInfo, damageScale)
local target = dmgInfo:GetAttacker()
if IsValid(target) and target:IsPlayer() then
local char = target:getChar()
if char then
local damage = dmgInfo:GetDamage() * damageScale
char:setData("lastDamageTaken", damage)
end
end
end)
High Complexity:
-- High: Complex damage tracking system
hook.Add("PostScaleDamage", "AdvancedDamageTracking", function(hitgroup, dmgInfo, damageScale)
local target = dmgInfo:GetAttacker()
local attacker = dmgInfo:GetAttacker()
if not IsValid(target) or not IsValid(attacker) then return end
local targetChar = target:getChar()
local attackerChar = attacker:getChar()
if not targetChar or not attackerChar then return end
local damage = dmgInfo:GetDamage() * damageScale
-- Log damage to database
lia.db.query("INSERT INTO damage_logs (timestamp, target_charid, attacker_charid, damage, hitgroup) VALUES (?, ?, ?, ?, ?)",
os.time(), targetChar:getID(), attackerChar:getID(), damage, hitgroup)
-- Track damage statistics
local damageDealt = attackerChar:getData("damageDealt", 0)
attackerChar:setData("damageDealt", damageDealt + damage)
local damageTaken = targetChar:getData("damageTaken", 0)
targetChar:setData("damageTaken", damageTaken + damage)
end)
PreCharDelete
Purpose
Called before a character is deleted
When Called
Before a character deletion is processed
Parameters
id(number): The character ID being deleted
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log character deletion
hook.Add("PreCharDelete", "MyAddon", function(id)
print("Character " .. id .. " is being deleted")
end)
Medium Complexity:
-- Medium: Backup character data
hook.Add("PreCharDelete", "BackupCharData", function(id)
local char = lia.char.loaded[id]
if char then
-- Create backup
lia.db.query("INSERT INTO char_backups SELECT * FROM characters WHERE id = ?", id)
end
end)
High Complexity:
-- High: Complex character deletion preparation
hook.Add("PreCharDelete", "AdvancedCharDeletePrep", function(id)
local char = lia.char.loaded[id]
if not char then return end
-- Create comprehensive backup
lia.db.query("INSERT INTO char_backups SELECT * FROM characters WHERE id = ?", id)
lia.db.query("INSERT INTO char_items_backup SELECT * FROM char_items WHERE charid = ?", id)
lia.db.query("INSERT INTO char_data_backup SELECT * FROM char_data WHERE charid = ?", id)
-- Notify admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("Character " .. char:getName() .. " (" .. id .. ") is being deleted")
end
end
-- Log deletion
lia.log.add("Character " .. char:getName() .. " (" .. id .. ") is being deleted", "character")
end)
PreDoorDataSave
Purpose
Called before door data is saved
When Called
Before door configuration data is saved to database
Parameters
door(Entity): The door entitydoorData(table): The door data being saved
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log door save
hook.Add("PreDoorDataSave", "MyAddon", function(door, doorData)
print("Saving door data for entity " .. door:EntIndex())
end)
Medium Complexity:
-- Medium: Validate door data
hook.Add("PreDoorDataSave", "ValidateDoorData", function(door, doorData)
if doorData.price and doorData.price < 0 then
doorData.price = 0
end
end)
High Complexity:
-- High: Complex door data validation
hook.Add("PreDoorDataSave", "AdvancedDoorDataValidation", function(door, doorData)
if not IsValid(door) then return end
-- Validate price
if doorData.price and doorData.price < 0 then
doorData.price = 0
elseif doorData.price and doorData.price > 100000 then
doorData.price = 100000
end
-- Validate title length
if doorData.title and #doorData.title > 50 then
doorData.title = string.sub(doorData.title, 1, 50)
end
-- Add metadata
doorData.lastSaved = os.time()
doorData.map = game.GetMap()
-- Log save
print(string.format("Saving door data: Entity=%d, Title=%s, Price=%s",
door:EntIndex(),
doorData.title or "None",
doorData.price or "None"))
end)
PrePlayerInteractItem
Purpose
Called before a player interacts with an item
When Called
Before an item interaction is processed
Parameters
client(Player): The player interactingaction(string): The action being performedself(Item): The item being interacted with
Returns
- boolean - True to allow, false to deny
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all interactions
hook.Add("PrePlayerInteractItem", "MyAddon", function(client, action, self)
return true
end)
Medium Complexity:
-- Medium: Check cooldown
hook.Add("PrePlayerInteractItem", "CheckCooldown", function(client, action, self)
local char = client:getChar()
if not char then return false end
local lastUse = char:getData("lastItemUse", 0)
if CurTime() - lastUse < 1 then
return false
end
char:setData("lastItemUse", CurTime())
return true
end)
High Complexity:
-- High: Complex item interaction validation
hook.Add("PrePlayerInteractItem", "AdvancedItemInteraction", function(client, action, self)
local char = client:getChar()
if not char then return false end
-- Check cooldown
local lastUse = char:getData("lastItemUse", 0)
if CurTime() - lastUse < 1 then
client:ChatPrint("Please wait before using another item")
return false
end
-- Check if item is broken
local durability = self:getData("durability", 100)
if durability <= 0 then
client:ChatPrint("This item is broken and cannot be used")
return false
end
-- Check faction restrictions
local requiredFaction = self.requiredFaction
if requiredFaction and char:getFaction() ~= requiredFaction then
client:ChatPrint("Your faction cannot use this item")
return false
end
char:setData("lastItemUse", CurTime())
return true
end)
PrePlayerLoadedChar
Purpose
Called before a player loads a character
When Called
Before a character is loaded for a player
Parameters
client(Player): The playercharacter(Character): The character being loadedcurrentChar(Character): The current character (if any)
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log character load
hook.Add("PrePlayerLoadedChar", "MyAddon", function(client, character, currentChar)
print(client:Name() .. " is loading character " .. character:getName())
end)
Medium Complexity:
-- Medium: Save current character state
hook.Add("PrePlayerLoadedChar", "SaveCurrentChar", function(client, character, currentChar)
if currentChar then
currentChar:setData("lastHealth", client:Health())
currentChar:setData("lastArmor", client:Armor())
end
end)
High Complexity:
-- High: Complex character load preparation
hook.Add("PrePlayerLoadedChar", "AdvancedCharLoadPrep", function(client, character, currentChar)
-- Save current character state
if currentChar then
currentChar:setData("lastHealth", client:Health())
currentChar:setData("lastArmor", client:Armor())
currentChar:setData("lastPosition", client:GetPos())
currentChar:setData("lastAngles", client:GetAngles())
currentChar:save()
end
-- Validate character data
if not character:getData("validated", false) then
character:setData("validated", true)
character:setData("loadCount", (character:getData("loadCount", 0) + 1))
end
-- Log character load
lia.db.query("INSERT INTO char_load_logs (timestamp, charid, steamid) VALUES (?, ?, ?)",
os.time(), character:getID(), client:SteamID())
end)
PreSalaryGive
Purpose
Called before salary is given to a player
When Called
Before salary payment is processed
Parameters
client(Player): The player receiving salarychar(Character): The character receiving salarypay(number): The salary amountfaction(string): The faction nameclass(string): The class name
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log salary
hook.Add("PreSalaryGive", "MyAddon", function(client, char, pay, faction, class)
print(client:Name() .. " is receiving $" .. pay .. " salary")
end)
Medium Complexity:
-- Medium: Modify salary amount
hook.Add("PreSalaryGive", "ModifySalary", function(client, char, pay, faction, class)
local char = client:getChar()
if char then
local level = char:getData("level", 1)
pay = pay + (level * 10)
end
end)
High Complexity:
-- High: Complex salary calculation
hook.Add("PreSalaryGive", "AdvancedSalaryCalculation", function(client, char, pay, faction, class)
local char = client:getChar()
if not char then return end
-- Base salary modifications
local level = char:getData("level", 1)
pay = pay + (level * 10)
-- Faction bonuses
if faction == "police" then
pay = pay * 1.2
elseif faction == "medic" then
pay = pay * 1.1
end
-- Class bonuses
if class == "officer" then
pay = pay + 50
elseif class == "doctor" then
pay = pay + 75
end
-- VIP bonus
if char:getData("vip", false) then
pay = pay * 1.5
end
-- Log salary calculation
lia.db.query("INSERT INTO salary_logs (timestamp, charid, amount, faction, class) VALUES (?, ?, ?, ?, ?)",
os.time(), char:getID(), pay, faction, class)
end)
PreScaleDamage
Purpose
Called before damage scaling is calculated
When Called
Before damage is scaled
Parameters
hitgroup(number): The hitgroup that was hitdmgInfo(CTakeDamageInfo): The damage infodamageScale(number): The current damage scale
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log damage scaling
hook.Add("PreScaleDamage", "MyAddon", function(hitgroup, dmgInfo, damageScale)
print("Scaling damage for hitgroup " .. hitgroup)
end)
Medium Complexity:
-- Medium: Modify damage scale
hook.Add("PreScaleDamage", "ModifyDamageScale", function(hitgroup, dmgInfo, damageScale)
if hitgroup == HITGROUP_HEAD then
damageScale = damageScale * 1.5
end
end)
High Complexity:
-- High: Complex damage scaling system
hook.Add("PreScaleDamage", "AdvancedDamageScaling", function(hitgroup, dmgInfo, damageScale)
local target = dmgInfo:GetAttacker()
local attacker = dmgInfo:GetAttacker()
if not IsValid(target) or not IsValid(attacker) then return end
local targetChar = target:getChar()
local attackerChar = attacker:getChar()
if not targetChar or not attackerChar then return end
-- Faction damage modifiers
local targetFaction = targetChar:getFaction()
local attackerFaction = attackerChar:getFaction()
if targetFaction == "police" and attackerFaction == "criminal" then
damageScale = damageScale * 1.2
elseif targetFaction == "criminal" and attackerFaction == "police" then
damageScale = damageScale * 0.8
end
-- Armor protection
local armor = target:getData("armor", 0)
if armor > 0 then
damageScale = damageScale * (1 - (armor / 200))
end
end)
RegisterPreparedStatements
Purpose
Called to register prepared SQL statements
When Called
When setting up database prepared statements
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log statement registration
hook.Add("RegisterPreparedStatements", "MyAddon", function()
print("Registering prepared statements")
end)
Medium Complexity:
-- Medium: Register custom statements
hook.Add("RegisterPreparedStatements", "RegisterCustomStatements", function()
lia.db.prepare("my_query", "SELECT * FROM my_table WHERE id = ?")
lia.db.prepare("my_insert", "INSERT INTO my_table (data) VALUES (?)")
end)
High Complexity:
-- High: Complex statement registration
hook.Add("RegisterPreparedStatements", "AdvancedStatementRegistration", function()
-- Register custom queries
lia.db.prepare("get_player_stats", "SELECT * FROM player_stats WHERE steamid = ?")
lia.db.prepare("update_player_stats", "UPDATE player_stats SET kills = ?, deaths = ? WHERE steamid = ?")
lia.db.prepare("insert_player_stats", "INSERT INTO player_stats (steamid, kills, deaths) VALUES (?, ?, ?)")
-- Register character queries
lia.db.prepare("get_char_data", "SELECT * FROM char_data WHERE charid = ?")
lia.db.prepare("update_char_data", "UPDATE char_data SET value = ? WHERE charid = ? AND key = ?")
-- Register item queries
lia.db.prepare("get_item_data", "SELECT * FROM item_data WHERE itemid = ?")
lia.db.prepare("update_item_data", "UPDATE item_data SET value = ? WHERE itemid = ? AND key = ?")
print("All prepared statements registered")
end)
RemoveWarning
Purpose
Called when a warning is removed
When Called
When a character warning is deleted
Parameters
charID(number): The character IDindex(number): The warning index
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log warning removal
hook.Add("RemoveWarning", "MyAddon", function(charID, index)
print("Warning " .. index .. " removed for character " .. charID)
end)
Medium Complexity:
-- Medium: Track warning removals
hook.Add("RemoveWarning", "TrackWarningRemovals", function(charID, index)
local char = lia.char.loaded[charID]
if char then
local warningRemovals = char:getData("warningRemovals", 0)
char:setData("warningRemovals", warningRemovals + 1)
end
end)
High Complexity:
-- High: Complex warning removal system
hook.Add("RemoveWarning", "AdvancedWarningRemoval", function(charID, index)
local char = lia.char.loaded[charID]
if not char then return end
-- Track warning removals
local warningRemovals = char:getData("warningRemovals", 0)
char:setData("warningRemovals", warningRemovals + 1)
-- Log to database
lia.db.query("INSERT INTO warning_logs (timestamp, charid, action, warning_index) VALUES (?, ?, ?, ?)",
os.time(), charID, "removed", index)
-- Notify character owner
local client = char:getPlayer()
if IsValid(client) then
client:ChatPrint("Warning " .. index .. " has been removed")
end
-- Notify admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("[ADMIN] Warning " .. index .. " removed for " .. char:getName())
end
end
end)
RunAdminSystemCommand
Purpose
Called when an admin system command is run
When Called
When an admin command is executed
Parameters
cmd(string): The command nameadmin(Player): The admin running the commandvictim(Player): The target player (if any)dur(number): The duration (if applicable)reason(string): The reason (if applicable)
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log admin commands
hook.Add("RunAdminSystemCommand", "MyAddon", function(cmd, admin, victim, dur, reason)
print(admin:Name() .. " ran command: " .. cmd)
end)
Medium Complexity:
-- Medium: Track command usage
hook.Add("RunAdminSystemCommand", "TrackCommandUsage", function(cmd, admin, victim, dur, reason)
local char = admin:getChar()
if char then
local commands = char:getData("commandsUsed", {})
commands[cmd] = (commands[cmd] or 0) + 1
char:setData("commandsUsed", commands)
end
end)
High Complexity:
-- High: Complex admin command tracking
hook.Add("RunAdminSystemCommand", "AdvancedCommandTracking", function(cmd, admin, victim, dur, reason)
local char = admin:getChar()
if not char then return end
-- Track command usage
local commands = char:getData("commandsUsed", {})
commands[cmd] = (commands[cmd] or 0) + 1
char:setData("commandsUsed", commands)
-- Log to database
lia.db.query("INSERT INTO admin_logs (timestamp, admin_steamid, command, target_steamid, duration, reason) VALUES (?, ?, ?, ?, ?, ?)",
os.time(), admin:SteamID(), cmd, victim and victim:SteamID() or "", dur or 0, reason or "")
-- Notify other admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() and ply ~= admin then
local message = admin:Name() .. " used " .. cmd
if IsValid(victim) then
message = message .. " on " .. victim:Name()
end
ply:ChatPrint("[ADMIN] " .. message)
end
end
end)
SaveData
Purpose
Called to save persistent data
When Called
When data needs to be saved to storage
Returns
- None
Realm
Server
Example Usage
Low Complexity:
Medium Complexity:
-- Medium: Save custom data
hook.Add("SaveData", "SaveCustomData", function()
lia.data.set("myAddonData", MyAddon.data)
end)
High Complexity:
-- High: Complex data saving system
hook.Add("SaveData", "AdvancedDataSaving", function()
-- Save custom data
lia.data.set("myAddonData", MyAddon.data)
-- Save player statistics
for _, ply in ipairs(player.GetAll()) do
local char = ply:getChar()
if char then
local stats = char:getData("myAddonStats", {})
lia.data.set("playerStats_" .. ply:SteamID(), stats)
end
end
-- Save to database
lia.db.query("INSERT INTO data_saves (timestamp, data) VALUES (?, ?)",
os.time(), util.TableToJSON(MyAddon.data))
print("All data saved successfully")
end)
SendPopup
Purpose
Called to send a popup message
When Called
When displaying a popup to a player
Parameters
noob(Player): The player receiving the popupmessage(string): The popup message
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log popup
hook.Add("SendPopup", "MyAddon", function(noob, message)
print("Sending popup to " .. noob:Name() .. ": " .. message)
end)
Medium Complexity:
-- Medium: Customize popup message
hook.Add("SendPopup", "CustomizePopup", function(noob, message)
local char = noob:getChar()
if char then
local customMessage = "[" .. char:getFaction() .. "] " .. message
noob:ChatPrint(customMessage)
end
end)
High Complexity:
-- High: Complex popup system
hook.Add("SendPopup", "AdvancedPopupSystem", function(noob, message)
local char = noob:getChar()
if not char then return end
-- Customize message based on faction
local faction = char:getFaction()
local factionPrefix = {
["police"] = "[POLICE]",
["medic"] = "[MEDICAL]",
["criminal"] = "[CRIMINAL]"
}
local prefix = factionPrefix[faction] or "[SYSTEM]"
local customMessage = prefix .. " " .. message
-- Send popup
noob:ChatPrint(customMessage)
-- Log popup
lia.db.query("INSERT INTO popup_logs (timestamp, steamid, message) VALUES (?, ?, ?)",
os.time(), noob:SteamID(), message)
end)
SetupBagInventoryAccessRules
Purpose
Called to set up bag inventory access rules
When Called
When configuring access rules for a bag inventory
Parameters
inventory(Inventory): The bag inventory
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log access rules setup
hook.Add("SetupBagInventoryAccessRules", "MyAddon", function(inventory)
print("Setting up bag access rules")
end)
Medium Complexity:
-- Medium: Set basic access rules
hook.Add("SetupBagInventoryAccessRules", "BasicAccessRules", function(inventory)
inventory:setData("accessLevel", "owner")
inventory:setData("allowTransfer", true)
end)
High Complexity:
-- High: Complex access rule system
hook.Add("SetupBagInventoryAccessRules", "AdvancedAccessRules", function(inventory)
-- Set access level
inventory:setData("accessLevel", "owner")
inventory:setData("allowTransfer", true)
inventory:setData("allowView", true)
-- Set faction restrictions
local owner = inventory:getOwner()
if IsValid(owner) then
local char = owner:getChar()
if char then
local faction = char:getFaction()
inventory:setData("allowedFactions", {faction})
end
end
-- Set time restrictions
inventory:setData("accessTime", os.time())
inventory:setData("accessDuration", 3600) -- 1 hour
end)
SetupBotPlayer
Purpose
Called to set up a bot player
When Called
When initializing a bot player
Parameters
client(Player): The bot player
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log bot setup
hook.Add("SetupBotPlayer", "MyAddon", function(client)
print("Setting up bot: " .. client:Name())
end)
Medium Complexity:
-- Medium: Configure bot behavior
hook.Add("SetupBotPlayer", "ConfigureBot", function(client)
client:SetNetVar("isBot", true)
client:SetNetVar("botType", "guard")
end)
High Complexity:
-- High: Complex bot setup system
hook.Add("SetupBotPlayer", "AdvancedBotSetup", function(client)
-- Mark as bot
client:SetNetVar("isBot", true)
client:SetNetVar("botType", "guard")
-- Set up bot AI
client:SetNetVar("botState", "patrol")
client:SetNetVar("botTarget", nil)
-- Give bot equipment
client:Give("weapon_pistol")
client:SetArmor(100)
-- Set up bot behavior
timer.Create("BotAI_" .. client:EntIndex(), 1, 0, function()
if IsValid(client) then
hook.Run("BotAIUpdate", client)
end
end)
end)
SetupDatabase
Purpose
Called to set up the database
When Called
When initializing database connections and tables
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log database setup
hook.Add("SetupDatabase", "MyAddon", function()
print("Setting up database")
end)
Medium Complexity:
-- Medium: Create custom tables
hook.Add("SetupDatabase", "CreateCustomTables", function()
lia.db.query("CREATE TABLE IF NOT EXISTS my_table (id INTEGER PRIMARY KEY, data TEXT)")
end)
High Complexity:
-- High: Complex database setup
hook.Add("SetupDatabase", "AdvancedDatabaseSetup", function()
-- Create custom tables
local tables = {
"CREATE TABLE IF NOT EXISTS my_table (id INTEGER PRIMARY KEY, data TEXT)",
"CREATE TABLE IF NOT EXISTS player_stats (steamid TEXT PRIMARY KEY, kills INTEGER, deaths INTEGER)",
"CREATE TABLE IF NOT EXISTS achievements (id INTEGER PRIMARY KEY, name TEXT, description TEXT)"
}
for _, query in ipairs(tables) do
lia.db.query(query)
end
-- Create indexes
lia.db.query("CREATE INDEX IF NOT EXISTS idx_player_stats_steamid ON player_stats(steamid)")
-- Set up prepared statements
lia.db.prepare("get_player_stats", "SELECT * FROM player_stats WHERE steamid = ?")
lia.db.prepare("update_player_stats", "UPDATE player_stats SET kills = ?, deaths = ? WHERE steamid = ?")
end)
SetupPlayerModel
Purpose
Called to set up a player's model
When Called
When configuring a player's character model
Parameters
client(Player): The playercharacter(Character): The character
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log model setup
hook.Add("SetupPlayerModel", "MyAddon", function(client, character)
print("Setting up model for " .. character:getName())
end)
Medium Complexity:
-- Medium: Set faction-based model
hook.Add("SetupPlayerModel", "FactionModel", function(client, character)
local faction = character:getFaction()
local factionModels = {
["police"] = "models/player/police.mdl",
["medic"] = "models/player/medic.mdl"
}
local model = factionModels[faction]
if model then
client:SetModel(model)
end
end)
High Complexity:
-- High: Complex model setup system
hook.Add("SetupPlayerModel", "AdvancedModelSetup", function(client, character)
local faction = character:getFaction()
local class = character:getData("class")
-- Get model based on faction and class
local model = character:getModel()
-- Apply faction-specific model overrides
local factionModels = lia.faction.indices[faction] and lia.faction.indices[faction].models
if factionModels and factionModels[class] then
model = factionModels[class]
end
-- Apply outfit model override
local outfit = character:getData("outfit")
if outfit then
local outfitItem = lia.item.instances[outfit]
if outfitItem and outfitItem.model then
model = outfitItem.model
end
end
-- Set model
client:SetModel(model)
-- Apply skin and bodygroups
local skin = character:getData("skin", 0)
client:SetSkin(skin)
local bodygroups = character:getData("bodygroups", {})
for i, group in ipairs(bodygroups) do
client:SetBodygroup(i, group)
end
end)
ShouldDataBeSaved
Purpose
Called to check if data should be saved
When Called
When determining if current data should be persisted
Returns
- boolean - True to save, false to skip
Realm
Server
Example Usage
Low Complexity:
Medium Complexity:
-- Medium: Check save conditions
hook.Add("ShouldDataBeSaved", "CheckSaveConditions", function()
local players = player.GetAll()
return #players > 0
end)
High Complexity:
-- High: Complex save validation
hook.Add("ShouldDataBeSaved", "AdvancedSaveValidation", function()
-- Don't save if no players
local players = player.GetAll()
if #players == 0 then
return false
end
-- Don't save if server is shutting down
if game.IsDedicated() and GetConVar("sv_shutdown"):GetBool() then
return false
end
-- Don't save if too frequent
local lastSave = lia.data.get("lastSave", 0)
if os.time() - lastSave < 60 then
return false
end
return true
end)
ShouldDeleteSavedItems
Purpose
Called to check if saved items should be deleted
When Called
When determining if old saved items should be cleaned up
Returns
- boolean - True to delete, false to keep
Realm
Server
Example Usage
Low Complexity:
-- Simple: Never delete saved items
hook.Add("ShouldDeleteSavedItems", "MyAddon", function()
return false
end)
Medium Complexity:
-- Medium: Delete old items
hook.Add("ShouldDeleteSavedItems", "DeleteOldItems", function()
local lastCleanup = lia.data.get("lastItemCleanup", 0)
return os.time() - lastCleanup > 86400 -- 24 hours
end)
High Complexity:
-- High: Complex item cleanup system
hook.Add("ShouldDeleteSavedItems", "AdvancedItemCleanup", function()
local lastCleanup = lia.data.get("lastItemCleanup", 0)
local cleanupInterval = 86400 -- 24 hours
-- Don't cleanup too frequently
if os.time() - lastCleanup < cleanupInterval then
return false
end
-- Check server load
local serverLoad = GetConVar("sv_stats"):GetFloat()
if serverLoad > 0.8 then
return false
end
-- Check player count
local players = player.GetAll()
if #players > 20 then
return false
end
return true
end)
StorageCanTransferItem
Purpose
Called to check if an item can be transferred to storage
When Called
When attempting to transfer an item to storage
Parameters
client(Player): The player transferring the itemstorage(Entity): The storage entityitem(Item): The item being transferred
Returns
- boolean - True to allow, false to deny
Realm
Server
Example Usage
Low Complexity:
-- Simple: Allow all transfers
hook.Add("StorageCanTransferItem", "MyAddon", function(client, storage, item)
return true
end)
Medium Complexity:
-- Medium: Check item restrictions
hook.Add("StorageCanTransferItem", "ItemRestrictions", function(client, storage, item)
local restrictedItems = {"weapon_crowbar", "weapon_stunstick"}
return not table.HasValue(restrictedItems, item.uniqueID)
end)
High Complexity:
-- High: Complex storage transfer system
hook.Add("StorageCanTransferItem", "AdvancedStorageTransfer", function(client, storage, item)
if not IsValid(client) or not IsValid(storage) or not item then
return false
end
local char = client:getChar()
if not char then return false end
-- Check storage capacity
local storageInv = storage:getInv()
if not storageInv then return false end
local maxWeight = storageInv:getMaxWeight()
local currentWeight = storageInv:getWeight()
local itemWeight = item:getWeight()
if currentWeight + itemWeight > maxWeight then
client:ChatPrint("Storage is full")
return false
end
-- Check item restrictions
local restrictedItems = {
["weapon_crowbar"] = "Weapons not allowed in storage",
["weapon_stunstick"] = "Weapons not allowed in storage"
}
if restrictedItems[item.uniqueID] then
client:ChatPrint(restrictedItems[item.uniqueID])
return false
end
-- Check faction restrictions
local faction = char:getFaction()
local storageFaction = storage:getNetVar("faction")
if storageFaction and storageFaction ~= faction then
client:ChatPrint("You cannot access this storage")
return false
end
-- Check distance
local distance = client:GetPos():Distance(storage:GetPos())
if distance > 200 then
client:ChatPrint("You are too far away from the storage")
return false
end
-- Check if storage is locked
if storage:getNetVar("locked", false) then
client:ChatPrint("Storage is locked")
return false
end
return true
end)
StorageEntityRemoved
Purpose
Called when a storage entity is removed
When Called
When a storage entity is deleted or removed
Parameters
self(Entity): The storage entity being removedinventory(Inventory): The inventory associated with the storage
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log storage removal
hook.Add("StorageEntityRemoved", "MyAddon", function(self, inventory)
print("Storage entity removed: " .. tostring(self))
end)
Medium Complexity:
-- Medium: Clean up storage data
hook.Add("StorageEntityRemoved", "CleanupStorage", function(self, inventory)
if inventory then
inventory:save()
end
-- Remove from storage list
lia.storage.list[self] = nil
end)
High Complexity:
-- High: Complex storage cleanup system
hook.Add("StorageEntityRemoved", "AdvancedStorageCleanup", function(self, inventory)
if not IsValid(self) then return end
-- Save inventory data
if inventory then
inventory:save()
-- Log inventory contents
local items = inventory:getItems()
local itemCount = 0
for _, item in pairs(items) do
itemCount = itemCount + 1
end
print(string.format("Storage %s removed with %d items", self:EntIndex(), itemCount))
end
-- Remove from storage list
lia.storage.list[self] = nil
-- Notify nearby players
local pos = self:GetPos()
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(pos) < 500 then
ply:ChatPrint("Storage has been removed")
end
end
-- Log to database
lia.db.query("INSERT INTO storage_logs (timestamp, entityid, action) VALUES (?, ?, ?)",
os.time(), self:EntIndex(), "removed")
-- Clean up any associated data
local storageData = self:getNetVar("storageData", {})
if storageData.owner then
local ownerChar = lia.char.loaded[storageData.owner]
if ownerChar then
ownerChar:setData("storageCount", (ownerChar:getData("storageCount", 0) - 1))
end
end
end)
StorageInventorySet
Purpose
Called when a storage inventory is set
When Called
When a storage entity gets its inventory assigned
Parameters
entity(Entity): The storage entityinventory(Inventory): The inventory being setisCar(boolean): Whether this is a car storage
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log storage inventory set
hook.Add("StorageInventorySet", "MyAddon", function(entity, inventory, isCar)
print("Storage inventory set for " .. tostring(entity))
end)
Medium Complexity:
-- Medium: Set storage properties
hook.Add("StorageInventorySet", "SetStorageProperties", function(entity, inventory, isCar)
if inventory then
inventory:setMaxWeight(isCar and 1000 or 500)
inventory:setMaxItems(isCar and 50 or 25)
end
end)
High Complexity:
-- High: Complex storage inventory system
hook.Add("StorageInventorySet", "AdvancedStorageInventory", function(entity, inventory, isCar)
if not IsValid(entity) or not inventory then return end
-- Set storage properties based on type
if isCar then
inventory:setMaxWeight(1000)
inventory:setMaxItems(50)
inventory:setData("storageType", "car")
else
inventory:setMaxWeight(500)
inventory:setMaxItems(25)
inventory:setData("storageType", "storage")
end
-- Set storage data
entity:setNetVar("storageData", {
inventory = inventory:getID(),
isCar = isCar,
maxWeight = inventory:getMaxWeight(),
maxItems = inventory:getMaxItems()
})
-- Add to storage list
lia.storage.list[entity] = {
inventory = inventory,
isCar = isCar,
created = os.time()
}
-- Log to database
lia.db.query("INSERT INTO storage_logs (timestamp, entityid, action, isCar) VALUES (?, ?, ?, ?)",
os.time(), entity:EntIndex(), "inventory_set", isCar and 1 or 0)
-- Notify nearby players
local pos = entity:GetPos()
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(pos) < 300 then
ply:ChatPrint("Storage is now available")
end
end
end)
StorageItemRemoved
Purpose
Called when an item is removed from storage
When Called
When an item is removed from a storage inventory
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log item removal
hook.Add("StorageItemRemoved", "MyAddon", function()
print("Item removed from storage")
end)
Medium Complexity:
-- Medium: Update storage statistics
hook.Add("StorageItemRemoved", "UpdateStats", function()
local storageCount = 0
for _, storage in pairs(lia.storage.list) do
if storage.inventory then
storageCount = storageCount + 1
end
end
print("Active storages: " .. storageCount)
end)
High Complexity:
-- High: Complex storage item removal system
hook.Add("StorageItemRemoved", "AdvancedStorageItemRemoval", function()
-- Update storage statistics
local totalItems = 0
local totalWeight = 0
for _, storage in pairs(lia.storage.list) do
if storage.inventory then
local items = storage.inventory:getItems()
for _, item in pairs(items) do
totalItems = totalItems + 1
totalWeight = totalWeight + item:getWeight()
end
end
end
-- Log statistics
print(string.format("Storage statistics: %d items, %.2f weight", totalItems, totalWeight))
-- Update storage data
for entity, storage in pairs(lia.storage.list) do
if IsValid(entity) and storage.inventory then
local items = storage.inventory:getItems()
local itemCount = 0
for _, item in pairs(items) do
itemCount = itemCount + 1
end
entity:setNetVar("itemCount", itemCount)
end
end
-- Notify nearby players
for _, ply in ipairs(player.GetAll()) do
if IsValid(ply) then
local char = ply:getChar()
if char then
local pos = ply:GetPos()
for entity, storage in pairs(lia.storage.list) do
if IsValid(entity) and entity:GetPos():Distance(pos) < 300 then
ply:ChatPrint("Storage contents updated")
end
end
end
end
end
end)
StorageOpen
Purpose
Called when storage is opened
When Called
When a player opens a storage entity
Parameters
storage(Entity): The storage entity being openedisCar(boolean): Whether this is a car storage
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log storage opening
hook.Add("StorageOpen", "MyAddon", function(storage, isCar)
print("Storage opened: " .. tostring(storage))
end)
Medium Complexity:
-- Medium: Track storage usage
hook.Add("StorageOpen", "TrackUsage", function(storage, isCar)
local storageData = storage:getNetVar("storageData", {})
storageData.openCount = (storageData.openCount or 0) + 1
storageData.lastOpened = os.time()
storage:setNetVar("storageData", storageData)
end)
High Complexity:
-- High: Complex storage opening system
hook.Add("StorageOpen", "AdvancedStorageOpening", function(storage, isCar)
if not IsValid(storage) then return end
-- Update storage statistics
local storageData = storage:getNetVar("storageData", {})
storageData.openCount = (storageData.openCount or 0) + 1
storageData.lastOpened = os.time()
storage:setNetVar("storageData", storageData)
-- Check storage capacity
local inventory = storage:getInv()
if inventory then
local items = inventory:getItems()
local itemCount = 0
for _, item in pairs(items) do
itemCount = itemCount + 1
end
storage:setNetVar("itemCount", itemCount)
end
-- Log to database
lia.db.query("INSERT INTO storage_logs (timestamp, entityid, action, isCar) VALUES (?, ?, ?, ?)",
os.time(), storage:EntIndex(), "opened", isCar and 1 or 0)
-- Notify nearby players
local pos = storage:GetPos()
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(pos) < 500 then
ply:ChatPrint("Storage has been opened")
end
end
-- Check for storage upgrades
local openCount = storageData.openCount
if openCount >= 100 and not storageData.upgraded then
storageData.upgraded = true
storage:setNetVar("storageData", storageData)
-- Increase storage capacity
if inventory then
inventory:setMaxWeight(inventory:getMaxWeight() * 1.5)
inventory:setMaxItems(inventory:getMaxItems() * 1.5)
end
end
end)
StorageRestored
Purpose
Called when storage is restored
When Called
When a storage entity is restored from save data
Parameters
ent(Entity): The storage entity being restoredinventory(Inventory): The inventory being restored
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log storage restoration
hook.Add("StorageRestored", "MyAddon", function(ent, inventory)
print("Storage restored: " .. tostring(ent))
end)
Medium Complexity:
-- Medium: Validate storage data
hook.Add("StorageRestored", "ValidateStorage", function(ent, inventory)
if inventory then
inventory:setMaxWeight(500)
inventory:setMaxItems(25)
end
end)
High Complexity:
-- High: Complex storage restoration system
hook.Add("StorageRestored", "AdvancedStorageRestoration", function(ent, inventory)
if not IsValid(ent) or not inventory then return end
-- Validate inventory data
if inventory:getMaxWeight() <= 0 then
inventory:setMaxWeight(500)
end
if inventory:getMaxItems() <= 0 then
inventory:setMaxItems(25)
end
-- Set storage data
ent:setNetVar("storageData", {
inventory = inventory:getID(),
restored = true,
restoredAt = os.time()
})
-- Add to storage list
lia.storage.list[ent] = {
inventory = inventory,
restored = true,
restoredAt = os.time()
}
-- Log to database
lia.db.query("INSERT INTO storage_logs (timestamp, entityid, action) VALUES (?, ?, ?)",
os.time(), ent:EntIndex(), "restored")
-- Notify nearby players
local pos = ent:GetPos()
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(pos) < 300 then
ply:ChatPrint("Storage has been restored")
end
end
-- Check for corrupted items
local items = inventory:getItems()
local corruptedItems = 0
for _, item in pairs(items) do
if not item.uniqueID or not lia.item.list[item.uniqueID] then
corruptedItems = corruptedItems + 1
end
end
if corruptedItems > 0 then
print(string.format("Storage %s restored with %d corrupted items", ent:EntIndex(), corruptedItems))
end
end)
StoreSpawns
Purpose
Called to store spawn points
When Called
When spawn points are being stored
Parameters
spawns(table): The spawn points to store
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log spawn storage
hook.Add("StoreSpawns", "MyAddon", function(spawns)
print("Storing " .. #spawns .. " spawn points")
end)
Medium Complexity:
-- Medium: Validate spawn points
hook.Add("StoreSpawns", "ValidateSpawns", function(spawns)
for i, spawn in ipairs(spawns) do
if not spawn.pos or not spawn.ang then
print("Invalid spawn point at index " .. i)
end
end
end)
High Complexity:
-- High: Complex spawn storage system
hook.Add("StoreSpawns", "AdvancedSpawnStorage", function(spawns)
if not spawns or #spawns == 0 then
print("No spawn points to store")
return
end
-- Validate spawn points
local validSpawns = {}
for i, spawn in ipairs(spawns) do
if spawn.pos and spawn.ang then
-- Check if spawn is valid
local trace = util.TraceLine({
start = spawn.pos,
endpos = spawn.pos + Vector(0, 0, -100),
mask = MASK_SOLID
})
if trace.Hit then
table.insert(validSpawns, spawn)
else
print("Spawn point " .. i .. " is not on solid ground")
end
else
print("Invalid spawn point at index " .. i)
end
end
-- Store valid spawns
lia.spawns = validSpawns
-- Log to database
lia.db.query("DELETE FROM spawns")
for _, spawn in ipairs(validSpawns) do
lia.db.query("INSERT INTO spawns (pos_x, pos_y, pos_z, ang_p, ang_y, ang_r) VALUES (?, ?, ?, ?, ?, ?)",
spawn.pos.x, spawn.pos.y, spawn.pos.z,
spawn.ang.p, spawn.ang.y, spawn.ang.r)
end
print(string.format("Stored %d valid spawn points", #validSpawns))
end)
SyncCharList
Purpose
Called to sync character list with client
When Called
When character list needs to be synchronized
Parameters
client(Player): The client to sync with
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log character list sync
hook.Add("SyncCharList", "MyAddon", function(client)
print("Syncing character list with " .. client:Name())
end)
Medium Complexity:
-- Medium: Validate character data
hook.Add("SyncCharList", "ValidateChars", function(client)
local charList = client:getCharList()
for _, char in ipairs(charList) do
if not char.name or not char.faction then
print("Invalid character data for " .. client:Name())
end
end
end)
High Complexity:
-- High: Complex character list sync system
hook.Add("SyncCharList", "AdvancedCharSync", function(client)
if not IsValid(client) then return end
local charList = client:getCharList()
if not charList then
print("No character list for " .. client:Name())
return
end
-- Validate character data
local validChars = {}
for _, char in ipairs(charList) do
if char.name and char.faction then
-- Check if character is valid
local faction = lia.faction.list[char.faction]
if faction then
table.insert(validChars, char)
else
print("Invalid faction for character " .. char.name)
end
else
print("Invalid character data for " .. client:Name())
end
end
-- Update client character list
client:setCharList(validChars)
-- Log to database
lia.db.query("UPDATE players SET char_list = ? WHERE steamid = ?",
util.TableToJSON(validChars), client:SteamID())
-- Notify client
net.Start("liaCharListUpdated")
net.WriteTable(validChars)
net.Send(client)
print(string.format("Synced %d characters for %s", #validChars, client:Name()))
end)
TicketSystemClaim
Purpose
Called when a ticket is claimed
When Called
When a support ticket is claimed by an admin
Parameters
client(Player): The admin claiming the ticketrequester(Player): The player who requested the ticketticketMessage(string): The ticket message
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log ticket claim
hook.Add("TicketSystemClaim", "MyAddon", function(client, requester, ticketMessage)
print(client:Name() .. " claimed ticket from " .. requester:Name())
end)
Medium Complexity:
-- Medium: Notify players
hook.Add("TicketSystemClaim", "NotifyClaim", function(client, requester, ticketMessage)
requester:ChatPrint("Your ticket has been claimed by " .. client:Name())
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("[ADMIN] " .. client:Name() .. " claimed ticket from " .. requester:Name())
end
end
end)
High Complexity:
-- High: Complex ticket claim system
hook.Add("TicketSystemClaim", "AdvancedTicketClaim", function(client, requester, ticketMessage)
if not IsValid(client) or not IsValid(requester) then return end
-- Check if client is admin
if not client:IsAdmin() then
client:ChatPrint("You do not have permission to claim tickets")
return
end
-- Update ticket status
local ticketData = {
claimed = true,
claimedBy = client:SteamID(),
claimedAt = os.time(),
message = ticketMessage
}
requester:setData("ticketData", ticketData)
-- Notify requester
requester:ChatPrint("Your ticket has been claimed by " .. client:Name())
-- Notify admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("[ADMIN] " .. client:Name() .. " claimed ticket from " .. requester:Name())
end
end
-- Log to database
lia.db.query("INSERT INTO ticket_logs (timestamp, requester_steamid, claimer_steamid, message) VALUES (?, ?, ?, ?)",
os.time(), requester:SteamID(), client:SteamID(), ticketMessage)
-- Update client data
local clientData = client:getData("ticketStats", {})
clientData.claimed = (clientData.claimed or 0) + 1
client:setData("ticketStats", clientData)
end)
TicketSystemClose
Purpose
Called when a ticket is closed
When Called
When a support ticket is closed
Parameters
client(Player): The admin closing the ticketrequester(Player): The player who requested the ticketticketMessage(string): The ticket message
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log ticket close
hook.Add("TicketSystemClose", "MyAddon", function(client, requester, ticketMessage)
print(client:Name() .. " closed ticket from " .. requester:Name())
end)
Medium Complexity:
-- Medium: Notify players
hook.Add("TicketSystemClose", "NotifyClose", function(client, requester, ticketMessage)
requester:ChatPrint("Your ticket has been closed by " .. client:Name())
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("[ADMIN] " .. client:Name() .. " closed ticket from " .. requester:Name())
end
end
end)
High Complexity:
-- High: Complex ticket close system
hook.Add("TicketSystemClose", "AdvancedTicketClose", function(client, requester, ticketMessage)
if not IsValid(client) or not IsValid(requester) then return end
-- Check if client is admin
if not client:IsAdmin() then
client:ChatPrint("You do not have permission to close tickets")
return
end
-- Update ticket status
local ticketData = requester:getData("ticketData", {})
ticketData.closed = true
ticketData.closedBy = client:SteamID()
ticketData.closedAt = os.time()
ticketData.closeMessage = ticketMessage
requester:setData("ticketData", ticketData)
-- Notify requester
requester:ChatPrint("Your ticket has been closed by " .. client:Name())
if ticketMessage and ticketMessage ~= "" then
requester:ChatPrint("Reason: " .. ticketMessage)
end
-- Notify admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("[ADMIN] " .. client:Name() .. " closed ticket from " .. requester:Name())
end
end
-- Log to database
lia.db.query("INSERT INTO ticket_logs (timestamp, requester_steamid, closer_steamid, message, action) VALUES (?, ?, ?, ?, ?)",
os.time(), requester:SteamID(), client:SteamID(), ticketMessage, "closed")
-- Update client data
local clientData = client:getData("ticketStats", {})
clientData.closed = (clientData.closed or 0) + 1
client:setData("ticketStats", clientData)
-- Clear ticket data after delay
timer.Simple(60, function()
if IsValid(requester) then
requester:setData("ticketData", nil)
end
end)
end)
TicketSystemCreated
Purpose
Called when a ticket is created
When Called
When a player creates a support ticket
Parameters
noob(Player): The player creating the ticketmessage(string): The ticket message
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log ticket creation
hook.Add("TicketSystemCreated", "MyAddon", function(noob, message)
print(noob:Name() .. " created a ticket: " .. message)
end)
Medium Complexity:
-- Medium: Notify admins
hook.Add("TicketSystemCreated", "NotifyAdmins", function(noob, message)
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("[TICKET] " .. noob:Name() .. ": " .. message)
end
end
end)
High Complexity:
-- High: Complex ticket creation system
hook.Add("TicketSystemCreated", "AdvancedTicketCreation", function(noob, message)
if not IsValid(noob) then return end
-- Check if player already has an open ticket
local ticketData = noob:getData("ticketData", {})
if ticketData.open and not ticketData.closed then
noob:ChatPrint("You already have an open ticket. Please wait for it to be resolved.")
return
end
-- Validate message
if not message or #message < 10 then
noob:ChatPrint("Please provide a more detailed description of your issue.")
return
end
-- Create ticket data
local newTicketData = {
open = true,
closed = false,
message = message,
createdAt = os.time(),
requester = noob:SteamID()
}
noob:setData("ticketData", newTicketData)
-- Notify admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("[TICKET] " .. noob:Name() .. " created a new ticket")
ply:ChatPrint("[TICKET] Message: " .. message)
end
end
-- Log to database
lia.db.query("INSERT INTO ticket_logs (timestamp, requester_steamid, message, action) VALUES (?, ?, ?, ?)",
os.time(), noob:SteamID(), message, "created")
-- Update player data
local playerData = noob:getData("ticketStats", {})
playerData.created = (playerData.created or 0) + 1
noob:setData("ticketStats", playerData)
-- Notify player
noob:ChatPrint("Your ticket has been created. An admin will respond soon.")
end)
ToggleLock
Purpose
Called when a door lock is toggled
When Called
When a door is locked or unlocked
Parameters
client(Player): The player toggling the lockdoor(Entity): The door entitystate(boolean): The new lock state
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log door lock toggle
hook.Add("ToggleLock", "MyAddon", function(client, door, state)
print(client:Name() .. " " .. (state and "locked" or "unlocked") .. " door")
end)
Medium Complexity:
-- Medium: Notify nearby players
hook.Add("ToggleLock", "NotifyToggle", function(client, door, state)
local pos = door:GetPos()
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(pos) < 500 then
ply:ChatPrint("A door has been " .. (state and "locked" or "unlocked"))
end
end
end)
High Complexity:
-- High: Complex door lock system
hook.Add("ToggleLock", "AdvancedDoorLock", function(client, door, state)
if not IsValid(client) or not IsValid(door) then return end
local char = client:getChar()
if not char then return end
-- Check permissions
if not client:IsAdmin() then
local doorOwner = door:getNetVar("owner")
if doorOwner and doorOwner ~= char:getID() then
client:ChatPrint("You do not have permission to lock this door")
return
end
end
-- Update door data
door:setNetVar("locked", state)
door:setNetVar("lastLocked", os.time())
door:setNetVar("lastLockedBy", client:SteamID())
-- Log to database
lia.db.query("INSERT INTO door_logs (timestamp, steamid, doorid, action) VALUES (?, ?, ?, ?)",
os.time(), client:SteamID(), door:EntIndex(), state and "locked" or "unlocked")
-- Notify nearby players
local pos = door:GetPos()
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(pos) < 500 and ply ~= client then
ply:ChatPrint("A door has been " .. (state and "locked" or "unlocked"))
end
end
-- Update character stats
local locks = char:getData("doorsLocked", 0)
char:setData("doorsLocked", locks + 1)
-- Check for door upgrades
local lockCount = char:getData("doorsLocked", 0)
if lockCount >= 10 and not char:getData("doorMaster", false) then
char:setData("doorMaster", true)
client:ChatPrint("You have mastered door locking!")
end
end)
TransferItem
Purpose
Called to transfer an item
When Called
When an item is being transferred
Parameters
itemID(string): The ID of the item being transferred
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log item transfer
hook.Add("TransferItem", "MyAddon", function(itemID)
print("Item transferred: " .. itemID)
end)
Medium Complexity:
-- Medium: Track item transfers
hook.Add("TransferItem", "TrackTransfers", function(itemID)
local item = lia.item.instances[itemID]
if item then
local transferCount = item:getData("transferCount", 0)
item:setData("transferCount", transferCount + 1)
end
end)
High Complexity:
-- High: Complex item transfer system
hook.Add("TransferItem", "AdvancedItemTransfer", function(itemID)
if not itemID then return end
local item = lia.item.instances[itemID]
if not item then return end
-- Get item data
local itemData = item:getData()
local fromInventory = item:getInventory()
local toInventory = item:getData("targetInventory")
if not fromInventory or not toInventory then return end
-- Check transfer permissions
local fromOwner = fromInventory:getOwner()
local toOwner = toInventory:getOwner()
if fromOwner and toOwner and fromOwner ~= toOwner then
-- Check if transfer is allowed between different owners
local transferAllowed = item:getData("transferable", true)
if not transferAllowed then
print("Item " .. itemID .. " is not transferable")
return
end
end
-- Update item data
local transferCount = item:getData("transferCount", 0)
item:setData("transferCount", transferCount + 1)
item:setData("lastTransfer", os.time())
-- Log to database
lia.db.query("INSERT INTO item_transfer_logs (timestamp, itemid, from_inventory, to_inventory) VALUES (?, ?, ?, ?)",
os.time(), itemID, fromInventory:getID(), toInventory:getID())
-- Notify players
local fromChar = lia.char.loaded[fromOwner]
local toChar = lia.char.loaded[toOwner]
if fromChar and fromChar:getPlayer() then
fromChar:getPlayer():ChatPrint("Item transferred: " .. item:getName())
end
if toChar and toChar:getPlayer() and toChar:getPlayer() ~= fromChar:getPlayer() then
toChar:getPlayer():ChatPrint("Item received: " .. item:getName())
end
-- Check for item degradation
local durability = item:getData("durability", 100)
if durability > 0 then
local newDurability = math.max(0, durability - 1)
item:setData("durability", newDurability)
if newDurability <= 0 then
item:setData("broken", true)
end
end
end)
UpdateEntityPersistence
Purpose
Called to update entity persistence
When Called
When an entity's persistence data needs to be updated
Parameters
ent(Entity): The entity to update
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log entity persistence update
hook.Add("UpdateEntityPersistence", "MyAddon", function(ent)
print("Updating persistence for " .. tostring(ent))
end)
Medium Complexity:
-- Medium: Update entity data
hook.Add("UpdateEntityPersistence", "UpdateData", function(ent)
if IsValid(ent) then
ent:setData("lastUpdate", os.time())
ent:setData("persistent", true)
end
end)
High Complexity:
-- High: Complex entity persistence system
hook.Add("UpdateEntityPersistence", "AdvancedPersistence", function(ent)
if not IsValid(ent) then return end
-- Check if entity should be persistent
local shouldPersist = hook.Run("CanPersistEntity", ent)
if not shouldPersist then
ent:setData("persistent", false)
return
end
-- Update entity data
local entityData = {
class = ent:GetClass(),
model = ent:GetModel(),
pos = ent:GetPos(),
ang = ent:GetAngles(),
lastUpdate = os.time(),
persistent = true
}
-- Save custom data
local customData = ent:getData("customData", {})
if customData and next(customData) then
entityData.customData = customData
end
-- Save to database
local entityID = ent:EntIndex()
lia.db.query("INSERT OR REPLACE INTO persistent_entities (entityid, data, lastupdate) VALUES (?, ?, ?)",
entityID, util.TableToJSON(entityData), os.time())
-- Update entity
ent:setData("persistent", true)
ent:setData("lastUpdate", os.time())
-- Notify nearby players
local pos = ent:GetPos()
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(pos) < 500 then
ply:ChatPrint("Entity persistence updated")
end
end
-- Log to file
lia.log.write("entity_persistence", {
entityID = entityID,
class = ent:GetClass(),
timestamp = os.time()
})
end)
VendorClassUpdated
Purpose
Called when a vendor class is updated
When Called
When a vendor's allowed classes are modified
Parameters
vendor(Entity): The vendor entityid(string): The class ID being updatedallowed(boolean): Whether the class is allowed
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log vendor class update
hook.Add("VendorClassUpdated", "MyAddon", function(vendor, id, allowed)
print("Vendor class " .. id .. " " .. (allowed and "allowed" or "denied"))
end)
Medium Complexity:
-- Medium: Notify players
hook.Add("VendorClassUpdated", "NotifyPlayers", function(vendor, id, allowed)
local pos = vendor:GetPos()
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(pos) < 500 then
ply:ChatPrint("Vendor class " .. id .. " " .. (allowed and "allowed" or "denied"))
end
end
end)
High Complexity:
-- High: Complex vendor class system
hook.Add("VendorClassUpdated", "AdvancedVendorClass", function(vendor, id, allowed)
if not IsValid(vendor) then return end
-- Update vendor data
local vendorData = vendor:getNetVar("vendorData", {})
vendorData.allowedClasses = vendorData.allowedClasses or {}
vendorData.allowedClasses[id] = allowed
vendor:setNetVar("vendorData", vendorData)
-- Update vendor inventory
local inventory = vendor:getInv()
if inventory then
local items = inventory:getItems()
for _, item in pairs(items) do
if item.uniqueID == id then
item:setData("allowed", allowed)
end
end
end
-- Log to database
lia.db.query("INSERT INTO vendor_class_logs (timestamp, vendorid, classid, allowed) VALUES (?, ?, ?, ?)",
os.time(), vendor:EntIndex(), id, allowed and 1 or 0)
-- Notify nearby players
local pos = vendor:GetPos()
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(pos) < 500 then
local char = ply:getChar()
if char and char:getFaction() == id then
ply:ChatPrint("Vendor access " .. (allowed and "granted" or "revoked") .. " for your class")
end
end
end
-- Update vendor UI if open
if IsValid(lia.gui.vendor) and lia.gui.vendor.vendor == vendor then
lia.gui.vendor:Populate()
end
end)
VendorEdited
Purpose
Called when a vendor is edited
When Called
When a vendor's properties are modified
Parameters
liaVendorEnt(Entity): The vendor entity being editedkey(string): The property key being edited
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log vendor edit
hook.Add("VendorEdited", "MyAddon", function(liaVendorEnt, key)
print("Vendor edited: " .. key)
end)
Medium Complexity:
-- Medium: Validate vendor edits
hook.Add("VendorEdited", "ValidateEdits", function(liaVendorEnt, key)
if key == "name" and liaVendorEnt:getNetVar("name") == "" then
liaVendorEnt:setNetVar("name", "Unnamed Vendor")
end
end)
High Complexity:
-- High: Complex vendor editing system
hook.Add("VendorEdited", "AdvancedVendorEdit", function(liaVendorEnt, key)
if not IsValid(liaVendorEnt) then return end
-- Update vendor data
local vendorData = liaVendorEnt:getNetVar("vendorData", {})
vendorData.lastEdit = os.time()
vendorData.editedBy = key
liaVendorEnt:setNetVar("vendorData", vendorData)
-- Validate specific properties
if key == "name" then
local name = liaVendorEnt:getNetVar("name", "")
if name == "" then
liaVendorEnt:setNetVar("name", "Unnamed Vendor")
elseif #name > 50 then
liaVendorEnt:setNetVar("name", string.sub(name, 1, 50))
end
elseif key == "money" then
local money = liaVendorEnt:getNetVar("money", 0)
if money < 0 then
liaVendorEnt:setNetVar("money", 0)
elseif money > 1000000 then
liaVendorEnt:setNetVar("money", 1000000)
end
end
-- Log to database
lia.db.query("INSERT INTO vendor_edit_logs (timestamp, vendorid, property, value) VALUES (?, ?, ?, ?)",
os.time(), liaVendorEnt:EntIndex(), key, tostring(liaVendorEnt:getNetVar(key, "")))
-- Notify nearby players
local pos = liaVendorEnt:GetPos()
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(pos) < 500 then
ply:ChatPrint("Vendor " .. key .. " has been updated")
end
end
-- Update vendor UI if open
if IsValid(lia.gui.vendor) and lia.gui.vendor.vendor == liaVendorEnt then
lia.gui.vendor:Populate()
end
end)
VendorFactionUpdated
Purpose
Called when a vendor faction is updated
When Called
When a vendor's allowed factions are modified
Parameters
vendor(Entity): The vendor entityid(string): The faction ID being updatedallowed(boolean): Whether the faction is allowed
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log vendor faction update
hook.Add("VendorFactionUpdated", "MyAddon", function(vendor, id, allowed)
print("Vendor faction " .. id .. " " .. (allowed and "allowed" or "denied"))
end)
Medium Complexity:
-- Medium: Notify players
hook.Add("VendorFactionUpdated", "NotifyPlayers", function(vendor, id, allowed)
local pos = vendor:GetPos()
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(pos) < 500 then
local char = ply:getChar()
if char and char:getFaction() == id then
ply:ChatPrint("Vendor access " .. (allowed and "granted" or "revoked") .. " for your faction")
end
end
end
end)
High Complexity:
-- High: Complex vendor faction system
hook.Add("VendorFactionUpdated", "AdvancedVendorFaction", function(vendor, id, allowed)
if not IsValid(vendor) then return end
-- Update vendor data
local vendorData = vendor:getNetVar("vendorData", {})
vendorData.allowedFactions = vendorData.allowedFactions or {}
vendorData.allowedFactions[id] = allowed
vendor:setNetVar("vendorData", vendorData)
-- Update vendor inventory
local inventory = vendor:getInv()
if inventory then
local items = inventory:getItems()
for _, item in pairs(items) do
if item.faction == id then
item:setData("allowed", allowed)
end
end
end
-- Log to database
lia.db.query("INSERT INTO vendor_faction_logs (timestamp, vendorid, factionid, allowed) VALUES (?, ?, ?, ?)",
os.time(), vendor:EntIndex(), id, allowed and 1 or 0)
-- Notify affected players
local pos = vendor:GetPos()
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(pos) < 500 then
local char = ply:getChar()
if char and char:getFaction() == id then
ply:ChatPrint("Vendor access " .. (allowed and "granted" or "revoked") .. " for your faction")
end
end
end
-- Update vendor UI if open
if IsValid(lia.gui.vendor) and lia.gui.vendor.vendor == vendor then
lia.gui.vendor:Populate()
end
-- Check for faction-specific items
local factionItems = lia.item.getByFaction(id)
for _, item in ipairs(factionItems) do
if allowed then
vendor:addItem(item.uniqueID, 1)
else
vendor:removeItem(item.uniqueID, 1)
end
end
end)
VendorItemMaxStockUpdated
Purpose
Called when a vendor item max stock is updated
When Called
When a vendor item's maximum stock is modified
Parameters
vendor(Entity): The vendor entityitemType(string): The item type being updatedvalue(number): The new maximum stock value
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log max stock update
hook.Add("VendorItemMaxStockUpdated", "MyAddon", function(vendor, itemType, value)
print("Vendor item " .. itemType .. " max stock set to " .. value)
end)
Medium Complexity:
-- Medium: Validate max stock value
hook.Add("VendorItemMaxStockUpdated", "ValidateMaxStock", function(vendor, itemType, value)
if value < 0 then
value = 0
elseif value > 1000 then
value = 1000
end
vendor:setNetVar("itemMaxStock_" .. itemType, value)
end)
High Complexity:
-- High: Complex vendor max stock system
hook.Add("VendorItemMaxStockUpdated", "AdvancedVendorMaxStock", function(vendor, itemType, value)
if not IsValid(vendor) then return end
-- Validate value
if value < 0 then
value = 0
elseif value > 10000 then
value = 10000
end
-- Update vendor data
local vendorData = vendor:getNetVar("vendorData", {})
vendorData.itemMaxStock = vendorData.itemMaxStock or {}
vendorData.itemMaxStock[itemType] = value
vendor:setNetVar("vendorData", vendorData)
-- Update item in inventory
local inventory = vendor:getInv()
if inventory then
local items = inventory:getItems()
for _, item in pairs(items) do
if item.uniqueID == itemType then
item:setData("maxStock", value)
-- Adjust current stock if it exceeds max
local currentStock = item:getData("stock", 0)
if currentStock > value then
item:setData("stock", value)
end
end
end
end
-- Log to database
lia.db.query("INSERT INTO vendor_item_logs (timestamp, vendorid, itemtype, property, value) VALUES (?, ?, ?, ?, ?)",
os.time(), vendor:EntIndex(), itemType, "maxStock", value)
-- Notify nearby players
local pos = vendor:GetPos()
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(pos) < 500 then
ply:ChatPrint("Vendor item " .. itemType .. " max stock updated to " .. value)
end
end
-- Update vendor UI if open
if IsValid(lia.gui.vendor) and lia.gui.vendor.vendor == vendor then
lia.gui.vendor:Populate()
end
end)
VendorItemModeUpdated
Purpose
Called when a vendor item mode is updated
When Called
When a vendor item's mode is modified
Parameters
vendor(Entity): The vendor entityitemType(string): The item type being updatedvalue(string): The new mode value
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log item mode update
hook.Add("VendorItemModeUpdated", "MyAddon", function(vendor, itemType, value)
print("Vendor item " .. itemType .. " mode set to " .. value)
end)
Medium Complexity:
-- Medium: Validate mode value
hook.Add("VendorItemModeUpdated", "ValidateMode", function(vendor, itemType, value)
local validModes = {"buy", "sell", "both"}
if not table.HasValue(validModes, value) then
value = "both"
end
vendor:setNetVar("itemMode_" .. itemType, value)
end)
High Complexity:
-- High: Complex vendor item mode system
hook.Add("VendorItemModeUpdated", "AdvancedVendorItemMode", function(vendor, itemType, value)
if not IsValid(vendor) then return end
-- Validate mode
local validModes = {"buy", "sell", "both"}
if not table.HasValue(validModes, value) then
value = "both"
end
-- Update vendor data
local vendorData = vendor:getNetVar("vendorData", {})
vendorData.itemModes = vendorData.itemModes or {}
vendorData.itemModes[itemType] = value
vendor:setNetVar("vendorData", vendorData)
-- Update item in inventory
local inventory = vendor:getInv()
if inventory then
local items = inventory:getItems()
for _, item in pairs(items) do
if item.uniqueID == itemType then
item:setData("mode", value)
-- Update item display based on mode
if value == "buy" then
item:setData("sellable", false)
item:setData("buyable", true)
elseif value == "sell" then
item:setData("sellable", true)
item:setData("buyable", false)
else
item:setData("sellable", true)
item:setData("buyable", true)
end
end
end
end
-- Log to database
lia.db.query("INSERT INTO vendor_item_logs (timestamp, vendorid, itemtype, property, value) VALUES (?, ?, ?, ?, ?)",
os.time(), vendor:EntIndex(), itemType, "mode", value)
-- Notify nearby players
local pos = vendor:GetPos()
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(pos) < 500 then
ply:ChatPrint("Vendor item " .. itemType .. " mode updated to " .. value)
end
end
-- Update vendor UI if open
if IsValid(lia.gui.vendor) and lia.gui.vendor.vendor == vendor then
lia.gui.vendor:Populate()
end
end)
VendorItemPriceUpdated
Purpose
Called when a vendor item price is updated
When Called
When a vendor item's price is modified
Parameters
vendor(Entity): The vendor entityitemType(string): The item type being updatedvalue(number): The new price value
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log price update
hook.Add("VendorItemPriceUpdated", "MyAddon", function(vendor, itemType, value)
print("Vendor item " .. itemType .. " price set to " .. value)
end)
Medium Complexity:
-- Medium: Validate price value
hook.Add("VendorItemPriceUpdated", "ValidatePrice", function(vendor, itemType, value)
if value < 0 then
value = 0
elseif value > 1000000 then
value = 1000000
end
vendor:setNetVar("itemPrice_" .. itemType, value)
end)
High Complexity:
-- High: Complex vendor price system
hook.Add("VendorItemPriceUpdated", "AdvancedVendorPrice", function(vendor, itemType, value)
if not IsValid(vendor) then return end
-- Validate price
if value < 0 then
value = 0
elseif value > 10000000 then
value = 10000000
end
-- Update vendor data
local vendorData = vendor:getNetVar("vendorData", {})
vendorData.itemPrices = vendorData.itemPrices or {}
vendorData.itemPrices[itemType] = value
vendor:setNetVar("vendorData", vendorData)
-- Update item in inventory
local inventory = vendor:getInv()
if inventory then
local items = inventory:getItems()
for _, item in pairs(items) do
if item.uniqueID == itemType then
item:setData("price", value)
-- Calculate profit margin
local basePrice = item:getData("basePrice", value)
local profitMargin = ((value - basePrice) / basePrice) * 100
item:setData("profitMargin", profitMargin)
end
end
end
-- Log to database
lia.db.query("INSERT INTO vendor_item_logs (timestamp, vendorid, itemtype, property, value) VALUES (?, ?, ?, ?, ?)",
os.time(), vendor:EntIndex(), itemType, "price", value)
-- Notify nearby players
local pos = vendor:GetPos()
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(pos) < 500 then
ply:ChatPrint("Vendor item " .. itemType .. " price updated to $" .. value)
end
end
-- Update vendor UI if open
if IsValid(lia.gui.vendor) and lia.gui.vendor.vendor == vendor then
lia.gui.vendor:Populate()
end
-- Check for price alerts
local priceAlerts = lia.config.get("priceAlerts", {})
for _, alert in ipairs(priceAlerts) do
if alert.itemType == itemType and alert.priceThreshold and value >= alert.priceThreshold then
for _, ply in ipairs(player.GetAll()) do
ply:ChatPrint("Price alert: " .. itemType .. " is now $" .. value)
end
end
end
end)
VendorItemStockUpdated
Purpose
Called when a vendor item stock is updated
When Called
When a vendor item's stock is modified
Parameters
vendor(Entity): The vendor entityitemType(string): The item type being updatedvalue(number): The new stock value
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log stock update
hook.Add("VendorItemStockUpdated", "MyAddon", function(vendor, itemType, value)
print("Vendor item " .. itemType .. " stock set to " .. value)
end)
Medium Complexity:
-- Medium: Validate stock value
hook.Add("VendorItemStockUpdated", "ValidateStock", function(vendor, itemType, value)
if value < 0 then
value = 0
end
vendor:setNetVar("itemStock_" .. itemType, value)
end)
High Complexity:
-- High: Complex vendor stock system
hook.Add("VendorItemStockUpdated", "AdvancedVendorStock", function(vendor, itemType, value)
if not IsValid(vendor) then return end
-- Validate stock
if value < 0 then
value = 0
end
-- Get max stock
local maxStock = vendor:getNetVar("itemMaxStock_" .. itemType, 100)
if value > maxStock then
value = maxStock
end
-- Update vendor data
local vendorData = vendor:getNetVar("vendorData", {})
vendorData.itemStocks = vendorData.itemStocks or {}
vendorData.itemStocks[itemType] = value
vendor:setNetVar("vendorData", vendorData)
-- Update item in inventory
local inventory = vendor:getInv()
if inventory then
local items = inventory:getItems()
for _, item in pairs(items) do
if item.uniqueID == itemType then
item:setData("stock", value)
-- Check if item is out of stock
if value <= 0 then
item:setData("outOfStock", true)
else
item:setData("outOfStock", false)
end
end
end
end
-- Log to database
lia.db.query("INSERT INTO vendor_item_logs (timestamp, vendorid, itemtype, property, value) VALUES (?, ?, ?, ?, ?)",
os.time(), vendor:EntIndex(), itemType, "stock", value)
-- Notify nearby players
local pos = vendor:GetPos()
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(pos) < 500 then
ply:ChatPrint("Vendor item " .. itemType .. " stock updated to " .. value)
end
end
-- Update vendor UI if open
if IsValid(lia.gui.vendor) and lia.gui.vendor.vendor == vendor then
lia.gui.vendor:Populate()
end
-- Check for low stock alerts
local lowStockThreshold = lia.config.get("lowStockThreshold", 10)
if value <= lowStockThreshold then
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("Low stock alert: " .. itemType .. " has " .. value .. " left")
end
end
end
end)
VendorOpened
Purpose
Called when a vendor is opened by a player
When Called
When a player successfully opens a vendor
Parameters
vendor(Entity): The vendor entity being opened
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log vendor opening
hook.Add("VendorOpened", "MyAddon", function(vendor)
print("Vendor opened: " .. vendor:EntIndex())
end)
Medium Complexity:
-- Medium: Track vendor usage
hook.Add("VendorOpened", "VendorTracking", function(vendor)
local vendorData = vendor:getNetVar("vendorData", {})
vendorData.openCount = (vendorData.openCount or 0) + 1
vendorData.lastOpened = os.time()
vendor:setNetVar("vendorData", vendorData)
end)
High Complexity:
-- High: Complex vendor opening system
hook.Add("VendorOpened", "AdvancedVendorOpening", function(vendor)
local char = vendor:getChar()
if not char then return end
-- Update vendor statistics
local vendorData = vendor:getNetVar("vendorData", {})
vendorData.openCount = (vendorData.openCount or 0) + 1
vendorData.lastOpened = os.time()
vendorData.totalRevenue = vendorData.totalRevenue or 0
vendor:setNetVar("vendorData", vendorData)
-- Check for vendor upgrades
local openCount = vendorData.openCount
if openCount >= 100 and not vendorData.upgraded then
vendorData.upgraded = true
vendor:setNetVar("vendorData", vendorData)
char:getPlayer():ChatPrint("Vendor upgraded! Increased stock capacity.")
end
-- Apply faction bonuses
local faction = char:getFaction()
local bonuses = {
["police"] = {discount = 0.1, bonusStock = 50},
["medic"] = {discount = 0.05, bonusStock = 25},
["citizen"] = {discount = 0.0, bonusStock = 0}
}
local bonus = bonuses[faction] or {discount = 0.0, bonusStock = 0}
vendor:setNetVar("factionDiscount", bonus.discount)
vendor:setNetVar("bonusStock", bonus.bonusStock)
-- Check for time-based events
local currentHour = tonumber(os.date("%H"))
if currentHour >= 18 and currentHour <= 22 then
-- Peak hours bonus
vendor:setNetVar("peakHoursBonus", 0.2)
else
vendor:setNetVar("peakHoursBonus", 0.0)
end
-- Log vendor opening
print(string.format("Vendor %s opened by %s (Faction: %s, Opens: %d)",
vendor:EntIndex(), char:getName(), faction, openCount))
end)
VendorTradeEvent
Purpose
Called when a vendor trade event occurs
When Called
When a player trades with a vendor
Parameters
client(Player): The player tradingvendor(Entity): The vendor entityitemType(string): The type of item being tradedisSellingToVendor(boolean): Whether the player is selling to the vendor
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log vendor trade
hook.Add("VendorTradeEvent", "MyAddon", function(client, vendor, itemType, isSellingToVendor)
print(client:Name() .. " traded " .. itemType)
end)
Medium Complexity:
-- Medium: Track trade statistics
hook.Add("VendorTradeEvent", "TrackTrades", function(client, vendor, itemType, isSellingToVendor)
local char = client:getChar()
if not char then return end
local trades = char:getData("vendorTrades", 0)
char:setData("vendorTrades", trades + 1)
end)
High Complexity:
-- High: Complex vendor trade system
hook.Add("VendorTradeEvent", "AdvancedVendorTrade", function(client, vendor, itemType, isSellingToVendor)
local char = client:getChar()
if not char then return end
-- Update trade statistics
local trades = char:getData("vendorTrades", 0)
char:setData("vendorTrades", trades + 1)
-- Track trade value
local tradeValue = char:getData("tradeValue", 0)
local itemPrice = lia.item.list[itemType] and lia.item.list[itemType].price or 0
char:setData("tradeValue", tradeValue + itemPrice)
-- Log to database
lia.db.query("INSERT INTO trade_logs (timestamp, steamid, vendorid, itemtype, selling) VALUES (?, ?, ?, ?, ?)",
os.time(), client:SteamID(), vendor:EntIndex(), itemType, isSellingToVendor and 1 or 0)
-- Update vendor reputation
local vendorID = vendor:EntIndex()
local reputation = char:getData("vendorRep_" .. vendorID, 0)
char:setData("vendorRep_" .. vendorID, reputation + 1)
-- Notify nearby players
local pos = vendor:GetPos()
for _, ply in ipairs(player.GetAll()) do
if ply:GetPos():Distance(pos) < 500 and ply ~= client then
ply:ChatPrint(client:Name() .. " traded with the vendor")
end
end
end)
WarningIssued
Purpose
Called when a warning is issued
When Called
When a player receives a warning
Parameters
client(Player): The player who issued the warningtarget(Player): The player who received the warningreason(string): The reason for the warningcount(number): The total warning countwarnerSteamID(string): The SteamID of the warnerwarnerName(string): The name of the warner
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log warning
hook.Add("WarningIssued", "MyAddon", function(client, target, reason, count, warnerSteamID, warnerName)
print(target:Name() .. " was warned by " .. client:Name())
end)
Medium Complexity:
-- Medium: Notify admins
hook.Add("WarningIssued", "NotifyAdmins", function(client, target, reason, count, warnerSteamID, warnerName)
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint(target:Name() .. " was warned for: " .. reason)
end
end
end)
High Complexity:
-- High: Complex warning system
hook.Add("WarningIssued", "AdvancedWarningSystem", function(client, target, reason, count, warnerSteamID, warnerName)
-- Log to database
lia.db.query("INSERT INTO warning_logs (timestamp, warner_steamid, target_steamid, reason, count) VALUES (?, ?, ?, ?, ?)",
os.time(), warnerSteamID, target:SteamID(), reason, count)
-- Notify target
target:ChatPrint("You have been warned by " .. warnerName .. " for: " .. reason)
target:ChatPrint("Total warnings: " .. count)
-- Notify admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("[ADMIN] " .. target:Name() .. " was warned by " .. warnerName .. " for: " .. reason)
end
end
-- Auto-kick if too many warnings
if count >= 3 then
target:Kick("Too many warnings (" .. count .. ")")
end
-- Update character data
local char = target:getChar()
if char then
char:setData("totalWarnings", count)
char:setData("lastWarning", os.time())
end
end)
WarningRemoved
Purpose
Called when a warning is removed
When Called
When a warning is removed from a player
Parameters
client(Player): The player who removed the warningtargetClient(Player): The player whose warning was removedreason(string): The reason for the warning removalcount(number): The remaining warning countwarnerSteamID(string): The SteamID of the original warnerwarnerName(string): The name of the original warner
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log warning removal
hook.Add("WarningRemoved", "MyAddon", function(client, targetClient, reason, count, warnerSteamID, warnerName)
print(targetClient:Name() .. "'s warning was removed by " .. client:Name())
end)
Medium Complexity:
-- Medium: Notify admins
hook.Add("WarningRemoved", "NotifyWarningRemoval", function(client, targetClient, reason, count, warnerSteamID, warnerName)
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint(targetClient:Name() .. "'s warning was removed by " .. client:Name())
end
end
end)
High Complexity:
-- High: Complex warning removal system
hook.Add("WarningRemoved", "AdvancedWarningRemoval", function(client, targetClient, reason, count, warnerSteamID, warnerName)
-- Log to database
lia.db.query("INSERT INTO warning_removal_logs (timestamp, remover_steamid, target_steamid, reason, remaining_count) VALUES (?, ?, ?, ?, ?)",
os.time(), client:SteamID(), targetClient:SteamID(), reason, count)
-- Notify target
targetClient:ChatPrint("One of your warnings has been removed by " .. client:Name())
targetClient:ChatPrint("Remaining warnings: " .. count)
-- Notify admins
for _, ply in ipairs(player.GetAll()) do
if ply:IsAdmin() then
ply:ChatPrint("[ADMIN] " .. client:Name() .. " removed a warning from " .. targetClient:Name())
ply:ChatPrint("[ADMIN] Reason: " .. reason .. " | Remaining: " .. count)
end
end
-- Update character data
local char = targetClient:getChar()
if char then
char:setData("totalWarnings", count)
char:setData("lastWarningRemoval", os.time())
end
end)
setData
Purpose
Called to set persistent data
When Called
When setting global or character-specific data
Parameters
value(any): The value to setglobal(boolean): Whether this is global dataignoreMap(boolean): Whether to ignore map-specific data
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Log data setting
hook.Add("setData", "MyAddon", function(value, global, ignoreMap)
print("Data set: " .. tostring(value))
end)
Medium Complexity:
-- Medium: Validate data before setting
hook.Add("setData", "ValidateData", function(value, global, ignoreMap)
if type(value) == "string" and #value > 1000 then
print("Warning: Data value too long")
return false
end
return true
end)
High Complexity:
-- High: Complex data validation system
hook.Add("setData", "AdvancedDataValidation", function(value, global, ignoreMap)
-- Validate data type and size
if type(value) == "string" and #value > 1000 then
print("Warning: Data value too long, truncating")
value = string.sub(value, 1, 1000)
end
-- Validate global data
if global and type(value) == "table" then
-- Check for circular references
local function hasCircularRef(obj, seen)
seen = seen or {}
if type(obj) ~= "table" then return false end
if seen[obj] then return true end
seen[obj] = true
for k, v in pairs(obj) do
if hasCircularRef(v, seen) then return true end
end
return false
end
if hasCircularRef(value) then
print("Error: Circular reference detected in global data")
return false
end
end
-- Log data changes
lia.db.query("INSERT INTO data_logs (timestamp, global, value_type) VALUES (?, ?, ?)",
os.time(), global and 1 or 0, type(value))
return true
end)