zombiesurvival-evolved/gamemodes/zombiesurvival/gamemode/skillweb/sh_skillweb.lua

282 lines
7.2 KiB
Lua
Raw Permalink Normal View History

include("registry.lua")
-- These are inverse functions of eachother!
function GM:LevelForXP(xp)
--return math.floor(1 + 1 * math.sqrt(xp))
return math.floor(1 + 0.25 * math.sqrt(xp))
end
function GM:XPForLevel(level)
--return level * level - 2 * level + 1
return 16 * level * level - 32 * level + 16
end
function GM:ProgressForXP(xp)
local current_level = self:LevelForXP(xp)
if current_level >= self.MaxLevel then return 1 end
local current_level_xp = self:XPForLevel(current_level)
local next_level_xp = self:XPForLevel(current_level + 1)
return (xp - current_level_xp) / (next_level_xp - current_level_xp)
end
GM.MaxLevel = 50
GM.MaxXP = GM:XPForLevel(GM.MaxLevel)
-- Makes sure all skill connections are double linked
function GM:FixSkillConnections()
for skillid, skill in pairs(self.Skills) do
for connectid, _ in pairs(skill.Connections) do
local otherskill = self.Skills[connectid]
if otherskill and not otherskill.Connections[skillid] then
otherskill.Connections[skillid] = true
end
end
end
end
function GM:SkillIsNeighbor(skillid, otherskillid)
local myskill = self.Skills[skillid]
return myskill ~= nil and self.Skills[otherskillid] ~= nil and myskill.Connections[otherskillid]
end
function GM:SkillCanUnlock(pl, skillid, skilllist)
local skill = self.Skills[skillid]
if skill then
if skill.RemortLevel and pl:GetZSRemortLevel() < skill.RemortLevel then
return false
end
local connections = skill.Connections
if connections[SKILL_NONE] then
return true
end
for _, myskillid in pairs(skilllist) do
if connections[myskillid] then
return true
end
end
end
return false
end
local meta = FindMetaTable("Player")
if not meta then return end
function meta:IsSkillUnlocked(skillid)
return table.HasValue(self:GetUnlockedSkills(), skillid)
end
function meta:SkillCanUnlock(skillid)
return GAMEMODE:SkillCanUnlock(self, skillid, self:GetUnlockedSkills())
end
function meta:IsSkillDesired(skillid)
return table.HasValue(self:GetDesiredActiveSkills(), skillid)
end
function meta:IsSkillActive(skillid)
return self:GetActiveSkills()[skillid]-- == true
end
function meta:HasTrinket(trinket)
return self:HasInventoryItem("trinket_" .. trinket)
end
function meta:CreateTrinketStatus(status)
for _, ent in pairs(ents.FindByClass("status_" .. status)) do
if ent:GetOwner() == self then return end
end
local ent = ents.Create("status_" .. status)
if ent:IsValid() then
ent:SetPos(self:EyePos())
ent:SetParent(self)
ent:SetOwner(self)
ent:Spawn()
end
end
function meta:ApplyAssocModifiers(assoc)
local skillmodifiers = {}
local gm_modifiers = GAMEMODE.SkillModifiers
for skillid in pairs(assoc) do
local modifiers = gm_modifiers[skillid]
if modifiers then
for modid, amount in pairs(modifiers) do
skillmodifiers[modid] = (skillmodifiers[modid] or 0) + amount
end
end
end
for modid, func in pairs(GAMEMODE.SkillModifierFunctions) do
func(self, skillmodifiers[modid] or 0)
end
end
-- These are done on human spawn.
function meta:ApplySkills(override)
if GAMEMODE.ZombieEscape or GAMEMODE.ClassicMode then return end -- Skills not used on these modes
local allskills = GAMEMODE.Skills
local desired = override or self:Alive() and self:Team() == TEAM_HUMAN and self:GetDesiredActiveSkills() or {}
local current_active = self:GetActiveSkills()
local desired_assoc = table.ToAssoc(desired)
-- Do we even have these skills unlocked?
if not override then
for skillid in pairs(desired_assoc) do
if not self:IsSkillUnlocked(skillid) or allskills[skillid] and allskills[skillid].Disabled then
desired_assoc[skillid] = nil
end
end
end
self:ApplyAssocModifiers(desired_assoc)
-- All skill function states can easily be kept track of.
local funcs
local gm_functions = GAMEMODE.SkillFunctions
for skillid in pairs(allskills) do
funcs = gm_functions[skillid]
if funcs then
if current_active[skillid] and not desired_assoc[skillid] then -- On but we want it off.
for _, func in pairs(funcs) do
func(self, false)
end
elseif desired_assoc[skillid] and not current_active[skillid] then -- Off but we want it on.
for _, func in pairs(funcs) do
func(self, true)
end
end -- Otherwise it's already in the state we want.
end
end
-- Store and sync with client.
self:SetActiveSkills(desired_assoc, not self.PlayerReady)
if SERVER and self.ExtraStartingWorth ~= self.LastSentESW then
self.LastSentESW = self.ExtraStartingWorth
net.Start("zs_extrastartingworth")
net.WriteUInt(self.ExtraStartingWorth, 16)
net.Send(self)
end
end
-- For trinkets, these apply after your skills, and they need to work differently so they can't be used to "update" your skills midgame.
function meta:ApplyTrinkets(override)
if GAMEMODE.ZombieEscape or GAMEMODE.ClassicMode then return end -- Skills not used on these modes
local allskills = GAMEMODE.Skills
local current_active = self:GetActiveSkills()
local real_assoc = table.ToAssoc(current_active)
if not override then
for skillid, skilltbl in pairs(allskills) do
if skilltbl.Trinket then
local hastrinket = self:HasTrinket(skilltbl.Trinket)
real_assoc[skillid] = hastrinket and true or nil
if SERVER then
if skilltbl.PairedWeapon then
local pairedwep = "weapon_zs_t_"..skilltbl.Trinket
if hastrinket and not self:HasWeapon(pairedwep) then
self:Give(pairedwep)
elseif not hastrinket and self:HasWeapon(pairedwep) then
self:StripWeapon(pairedwep)
end
end
if hastrinket and skilltbl.Status then
self:CreateTrinketStatus(skilltbl.Status)
end
end
end
end
end
self:ApplyAssocModifiers(real_assoc)
local funcs
local gm_functions = GAMEMODE.SkillFunctions
for skillid in pairs(allskills) do
funcs = gm_functions[skillid]
if funcs then
if not real_assoc[skillid] then -- On but we want it off.
for _, func in pairs(funcs) do
func(self, false)
end
elseif real_assoc[skillid] then -- Off but we want it on.
for _, func in pairs(funcs) do
func(self, true)
end
end
end
end
end
function meta:CanSkillsRemort()
return self:GetZSLevel() >= GAMEMODE.MaxLevel
end
meta.CanSkillRemort = meta.CanSkillsRemort
function meta:SetSkillActive(skillid, active, nosend)
local skills = table.ToAssoc(self:GetActiveSkills())
skills[active] = active
self:SetActiveSkills(skills, nosend)
end
function meta:GetZSLevel()
return math.floor(GAMEMODE:LevelForXP(self:GetZSXP()))
end
function meta:GetZSRemortLevel()
return self:GetDTInt(DT_PLAYER_INT_REMORTLEVEL)
end
function meta:GetZSRemortLevelGraded()
return math.floor(self:GetZSRemortLevel() / 4)
end
function meta:GetZSXP()
return self:GetDTInt(DT_PLAYER_INT_XP)
end
function meta:GetZSSPUsed()
return #self:GetUnlockedSkills()
end
function meta:GetZSSPRemaining()
return self:GetZSSPTotal() - self:GetZSSPUsed()
end
function meta:GetZSSPTotal()
return self:GetZSLevel() + self:GetZSRemortLevel()
end
function meta:GetDesiredActiveSkills()
return self.DesiredActiveSkills or {}
end
function meta:GetActiveSkills()
return self.ActiveSkills or {}
end
function meta:GetUnlockedSkills()
return self.UnlockedSkills or {}
end
function meta:GetTotalAdditiveModifier(...)
local totalmod = 1
for i, modifier in ipairs({...}) do
totalmod = totalmod + (self[modifier] or 1) - 1
end
return totalmod
end