Difference between revisions of "KarmaSystem"

From Legends of Aria Admin and Modding Wiki
Jump to: navigation, search
(AlterKarmaAction)
 
(24 intermediate revisions by the same user not shown)
Line 1: Line 1:
 +
''This page documentation was added by Gizmo''
 +
== Karma Actions ==
 
''
 
''
   welcome this will discuss the contents of the globals\helpers\conflict.lua
+
   welcome this will discuss the contents of the globals\static_data\karma\main.lua
 
   this documentation is correct as of version 6.0 PRECB1 Release  
 
   this documentation is correct as of version 6.0 PRECB1 Release  
 +
''
 +
''
 +
  --[[ 
 +
    KarmaActionName = {
 +
        -- the amount to adjust
 +
        Adjust = -10,
 +
        -- the max amount this karma action can affect
 +
        UpTo = -500,
 +
        -- These only apply to NEGATIVE mods. (Adjust < 0)
 +
        -- if the action is being performed on a NPC (not a player character), it's multiplied by this amount
 +
        NpcModifier = 0.1
 +
    },
 +
  ]]
 +
  KarmaActions = {}
 +
  require 'globals.static_data.karma.negative_actions'
 +
  require 'globals.static_data.karma.positive_actions'
 +
''
 +
=== NegativeActions ===
 +
''
 +
  welcome this will discuss the contents of the globals\static_data\karma\negative_actions.lua
 +
  this documentation is correct as of version 6.0 PRECB1 Release
 +
''
 +
''
 +
  --[[
 +
    Negative actions, obviously, are only applicable to 'bad' player choices.
 +
    (ie LootContainer should never apply when looting something from your bank or a mob you killed for example, but should apply if the thing you're looting has positive Karma)
 +
  ]]
 +
 +
  KarmaActions.Negative = {
 +
    Attack = {
 +
        Adjust = -50,
 +
        NpcModifier = 0.5,
 +
    },
 +
    -- This applies to looting players bodies as well as anything with ObjVar Karma
 +
    LootContainer = {
 +
        Adjust = -10,
 +
        NpcModifier = 0.25,
 +
    },
 +
    LootUnownedKill = {
 +
        Adjust = -25,
 +
        NpcModifier = 1, -- set to 1 to negate the effects of this modifer for this action since this only applies to npcs (corpses n such)
 +
    },
 +
    Murder = {
 +
        Adjust = -500,
 +
        NpcModifier = 0.1,
 +
    },
 +
    -- applies when a player performs a benefical act on a karma level set to punish beneficial acts
 +
    PunishForBeneficial = {
 +
        Adjust = -50,
 +
        NpcModifier = 0.1,
 +
    },
 +
  }
 +
''
 +
 +
=== PositiveActions ===
 +
''
 +
  welcome this will discuss the contents of the globals\static_data\karma\positive_actions.lua
 +
  this documentation is correct as of version 6.0 PRECB1 Release
 +
''
 +
''
 +
  KarmaActions.Positive = {
 +
    DailyLogin = {
 +
        Adjust = 50,
 +
        UpTo = 5000,
 +
    },
 +
    SlayMonster = {
 +
        Adjust = 1,
 +
        UpTo = 7500
 +
    }
 +
  }
 
''
 
''
  
== Conflict Functions ==
+
== Karma Functions ==
 +
''
 +
  welcome this will discuss the contents of the globals\helpers\karma.lua
 +
  this documentation is correct as of version 6.0 PRECB1 Release
 +
''
 
=== AdjustKarma ===
 
=== AdjustKarma ===
 
''
 
''
Line 46: Line 122:
 
=== CheckKarmaBeneficialAction ===
 
=== CheckKarmaBeneficialAction ===
 
''
 
''
 +
  -- Check when a player performs a beneficial action on a mobile(player/npc/etc)
 +
  -- @param player(playerObj) DOES NOT ENFORCE IsPlayerCharacter()
 +
  -- @param mobile(mobileObj) Anything with a karma level
 +
  -- @return none
  
 +
  function CheckKarmaBeneficialAction(player, mobileB)
 +
    -- beneficial actions are only bad against some
 +
    local karmaLevelB = GetKarmaLevel(GetKarma(mobileB))
 +
    local isPlayerB = IsPlayerCharacter(mobileB)
 +
    if (
 +
        (isPlayerB and karmaLevelB.PunishBeneficialToPlayer)
 +
        or
 +
        (not isPlayerB and karmaLevelB.PunishBeneficialToNPC)
 +
    ) then
 +
        ExecuteKarmaAction(player, KarmaActions.Negative.PunishForBeneficial, mobileB)
 +
    end
 +
    if ( isPlayerB ) then
 +
        -- when players benefit players, they inherit their aggressive conflict relations.
 +
        InheritAggressivePlayerConflicts(mobileB, player)
 +
    end
 +
  end
 
''
 
''
 +
 
=== CheckKarmaLoot ===
 
=== CheckKarmaLoot ===
 
''
 
''
 +
  -- Check player against a container on a loot (item removed from a container)
 +
  -- @param player(playerObj) Player doing the looting
 +
  -- @param container(Container) Container being looted from (mobileB:TopmostContainer())
 +
  -- @return none (executes karma actions internally)
  
 +
  function CheckKarmaLoot(player, container)
 +
    if ( container == nil ) then return end
 +
    -- can't get in trouble doing stuff to yourself..
 +
    if ( player == container ) then return end
 +
    -- only mobiles supported right now
 +
    if not( container:IsMobile() ) then return end
 +
    local containerOwner = nil
 +
    -- re-assign the container to the owner if applicable.
 +
    if ( container:GetCreationTemplateId() == "player_corpse" ) then
 +
        containerOwner = container:GetObjVar("BackpackOwner")
 +
    else
 +
        if ( IsPet(container) ) then containerOwner = container:GetObjectOwner() or container end
 +
    end
 +
    -- can't get in trouble doing stuff to yourself..
 +
    if ( containerOwner ~= nil and player == containerOwner ) then return end
 +
    local isPlayer = false
 +
    if ( containerOwner ~= nil ) then
 +
        isPlayer = IsPlayerCharacter(containerOwner)
 +
    else
 +
        isPlayer = IsPlayerCharacter(container)
 +
    end
 +
    if ( isPlayer ) then
 +
        -- TODO: It's ok to loot players in your group?
 +
        -- if looting a player owned container that's not theirs, advance the conflict relation with no warning, no karma action
 +
        AdvanceConflictRelation(player, containerOwner, true, KarmaActions.Negative.LootContainer)
 +
    else
 +
        -- explicitly check for false, since nil is returned in the event the container doesn't have conflicts
 +
        -- and we don't care to punish anyone for looting something without conflict (like a chest)
 +
        if ( IsMobTaggedBy(container, player) == false ) then
 +
            -- the container is not tagged by the player, therefor the player doesn't have the right to loot.
 +
            ExecuteKarmaAction(player, KarmaActions.Negative.LootUnownedKill)
 +
            return
 +
        end
 +
    end
 +
    -- at this point we just execute a LootContainer action. Karma system should take care of the rest
 +
    ExecuteKarmaAction(player, KarmaActions.Negative.LootContainer, container)
 +
  end
 
''
 
''
 +
 
=== ColorizeMobileName ===
 
=== ColorizeMobileName ===
 
''
 
''
 +
  -- Colorize a mobile name dependant on their karma
 +
  -- @param mobile(mobileObj) the mobile used to decide the name color
 +
  -- @param newName(string) The name to be colorized
 +
  -- @return colorized newName(string)
  
 +
  function ColorizeMobileName(mobile, newName)
 +
    if ( mobile == nil ) then
 +
        LuaDebugCallStack("[Karma] Nil mobile supplied to ColorizeMobileName")
 +
        return newName
 +
    end
 +
    local color = nil
 +
    if ( mobile:GetObjVar("ImportantNPC") ~= nil ) then
 +
        color = "F2F5A9"
 +
    else
 +
        color = GetKarmaLevel(GetKarma(mobile)).NameColor
 +
    end
 +
    return "[" .. color .. "]" .. newName .. "[-]"
 +
  end
 
''
 
''
 +
 
=== ColorizePlayerName ===
 
=== ColorizePlayerName ===
 
''
 
''
 +
  -- Colorize a player's name dependant on their karma
 +
  -- @param player(mobileObj) the playerObj used to decide the name color
 +
  -- @param newName(string) The name to be colorized
 +
  -- @return colorized newName(string)
  
 +
  function ColorizePlayerName(player, newName)
 +
    if ( player == nil ) then
 +
        LuaDebugCallStack("[Karma] Nil player supplied to ColorizePlayerName")
 +
        return newName
 +
    end
 +
    local color = player:GetObjVar("NameColorOverride")
 +
    if ( color == nil ) then
 +
        if ( IsImmortal(player) and not player:GetObjVar("TestMortal") ) then color = "FFBF00" end
 +
    end
 +
    if ( color == nil ) then
 +
        color = GetKarmaLevel(GetKarma(player)).NameColor
 +
    end
 +
    return "[" .. color .. "]" .. newName .. "[-]"
 +
  end
 
''
 
''
 +
 
=== DailyLogin ===
 
=== DailyLogin ===
 
''
 
''
 +
  -- Perform the positive karma action Daily Login with checks
 +
  -- @param player(playerObj)
 +
  -- @return none
  
 +
  function DailyLogin(player)
 +
    local lastDailyLoginReward = player:GetObjVar("KarmaDaily")
 +
    local now = DateTime.UtcNow
 +
    if ( lastDailyLoginReward == nil or lastDailyLoginReward + ServerSettings.Karma.DailyLoginInterval < now ) then
 +
        player:SetObjVar("KarmaDaily", now)
 +
        ExecuteKarmaAction(player, KarmaActions.Positive.DailyLogin)
 +
    end
 +
  end
 
''
 
''
 +
 
=== ExectueKarmaAction ===
 
=== ExectueKarmaAction ===
 
''
 
''
 +
  -- Perform the actual karma handling for a karma action, will adjust mobileA's karma appropriately(if at all) for the given action.
 +
  -- @param mobileA the mobile that is performing the karma action
 +
  -- @param karmaAction(table) The KarmaActions.Positive/KarmaActions.Negative for the action.
 +
  -- @param mobileB(mobileObj)(optional) The mobile that the karma action is being performed on(if any)
 +
  -- @return none
  
 +
  function ExecuteKarmaAction(mobileA, action, mobileB)
 +
    if ( mobileA == nil ) then
 +
        LuaDebugCallStack("[Karma] Nil mobileA provided, need at least one mobile for a karma action.")
 +
        return
 +
    end
 +
    if ( action == nil ) then
 +
        LuaDebugCallStack("[Karma] Nil action supplied.")
 +
        return
 +
    end
 +
    if ( action.Adjust == nil ) then
 +
        LuaDebugCallStack("[Karma] Supplied action without 'Adjust', this karma action is invalid until resolved.")
 +
        return
 +
    end
 +
    -- if mobileB is passed, ensure it's in the same region.
 +
    if ( mobileB ~= nil and not mobileB:IsValid() ) then return end
 +
    -- karma adjustments can only be applied to players
 +
    if not( IsPlayerCharacter(mobileA) ) then return end
 +
    local karmaA = GetKarma(mobileA)
 +
    -- if they cannot be affected by this karma action any further, stop here.
 +
    if ( action.Adjust < 0 ) then
 +
        if ( action.UpTo and karmaA < action.UpTo ) then return end
 +
    else
 +
        if ( action.UpTo and karmaA > action.UpTo ) then return end
 +
    end
 +
    -- ensure they are both within the karma area.
 +
    if ( not WithinKarmaArea(mobileA) and (mobileB ~= nil and not WithinKarmaArea(mobileB)) ) then
 +
        return
 +
    end
 +
    local isPlayerB = false
 +
    local karmaB =
 +
    -- handle special karma cases
 +
    if ( mobileB ~= nil ) then
 +
        isPlayerB = IsPlayerCharacter(mobileB)
 +
        -- important npcs are off the charts.
 +
        if ( not isPlayerB and mobileB:HasObjVar("ImportantNPC") ) then karmaB = 1000000 else
 +
            karmaB = GetKarma(mobileB)
 +
        end
 +
    end
 +
    local conflictMod = 1
 +
    local pvpMod = 1
 +
    local negativeAdjustMod = 1
 +
    local npcMod = 1
 +
    -- players in same guilds/opposing factions never effect each other's karma
 +
    if ( isPlayerB ) then
 +
        local guildA = mobileA:GetObjVar("Guild")
 +
        if ( guildA ~= nil ) then
 +
            local guildB = mobileB:GetObjVar("Guild")
 +
            -- they share the same guild, end here
 +
            if ( guildA == guildB ) then return end
 +
            if ( guildB ~= nil and guildA ~= guildB ) then
 +
                -- determined the two involved are both definitely in guilds, and they are not the same guild,
 +
                -- let's compare their factions.
 +
                local guildRecordA = Guild.GetGuildRecord(guildA)
 +
                if ( guildRecordA ~= nil and guildRecordA.PatronGod ~= nil ) then
 +
                    local guildRecordB = Guild.GetGuildRecord(guildB)
 +
                    if ( guildRecordB ~= nil and guildRecordB.PatronGod ~= nil and guildRecordA.PatronGod ~= guildRecordB.PatronGod ) then
 +
                        -- officially determined that playerA and playerB are both in factions, and their factions are not the same.
 +
                        return
 +
                    end
 +
                end
 +
            end
 +
        end
 +
    end
 +
    -- handle negative karma actions
 +
    if ( action.Adjust < 0 ) then
 +
        local karmaALevel = nil
 +
        if ( mobileB ~= nil ) then
 +
            local karmaBLevel = GetKarmaLevel(karmaB)
 +
            -- if guards don't protect them, they are free to perform negative actions on.
 +
            -- the guards are the metaphorical judge/jury/(literal)executioner
 +
            if ( (not isPlayerB and karmaBLevel.GuardProtectNPC ~= true) or (isPlayerB and karmaBLevel.GuardProtectPlayer ~= true) ) then return end
 +
            if ( isPlayerB ) then
 +
                --determine their player vs player modifiers
 +
                karmaALevel = GetKarmaLevel(karmaA)
 +
                karmaBLevel = karmaBLevel or GetKarmaLevel(karmaB)
 +
                pvpMod = karmaALevel.PvPMods[karmaBLevel.Name]
 +
            else
 +
                if ( action.NpcModifier ~= nil ) then
 +
                    -- if mobileB is not a player, modify as such
 +
                    npcMod = action.NpcModifier
 +
                end
 +
            end
 +
            -- get conflict mod
 +
            if ( pvpMod > 0 ) then
 +
                if ( ConflictEquals(GetConflictRelation(mobileB, mobileA), ConflictRelations.Aggressor) ) then
 +
                    local aToBRelation = GetConflictRelation(mobileA, mobileB)
 +
                    if (
 +
                        ConflictEquals(aToBRelation, ConflictRelations.Defender)
 +
                        or
 +
                        ConflictEquals(aToBRelation, ConflictRelations.Victim)
 +
                    ) then
 +
                        --victim/defender karma action against aggressor, this is free.
 +
                        conflictMod = 0
 +
                    end
 +
                end
 +
            end
 +
        end     
 +
        if ( pvpMod > 0 and conflictMod > 0 ) then
 +
            -- determine the negative karma adjust mod
 +
            karmaALevel = karmaALevel or GetKarmaLevel(karmaA)
 +
            negativeAdjustMod = karmaALevel.NegativeKarmaAdjustMod
 +
        end
 +
    else
 +
        -- handle positive karma actions
 +
    end
 +
    --[[
 +
    DebugMessage("--Execute Karma Action--")
 +
    DebugMessage("Adjust: "..action.Adjust)
 +
    DebugMessage("conMod: "..conflictMod)
 +
    DebugMessage("pvpMod: "..pvpMod)
 +
    DebugMessage("negMod: "..negativeAdjustMod)
 +
    DebugMessage("npcMod: "..npcMod)
 +
    ]]
 +
    local adjust = action.Adjust * conflictMod * pvpMod * negativeAdjustMod * npcMod
 +
    -- prevent positive actions from going negative
 +
    if ( action.Adjust > 0 and adjust < 0 ) then return end
 +
    -- prevent negative actions from going positive
 +
    if ( action.Adjust < 0 and adjust > 0 ) then return end
 +
    -- finally apply all the calculated karma
 +
    AdjustKarma(mobileA, adjust)
 +
  end
 
''
 
''
 +
 
=== GetKarma ===
 
=== GetKarma ===
 
''
 
''
 +
  -- Get the Karma for a mobile
 +
  -- @param mobile(mobileObj)
 +
  -- @return Amount of Karma the mobile has(number), 0 if Karma is not set
  
 +
  function GetKarma(mobile)
 +
    if ( mobile == nil ) then
 +
        LuaDebugCallStack("[Karma] Nil mobile provided to GetKarma()")
 +
        return
 +
    end
 +
    return mobile:GetObjVar("Karma") or 0
 +
  end
 
''
 
''
 +
 
=== GetKarmaLevel ===
 
=== GetKarmaLevel ===
 +
''
 +
  -- Get the karma level data table for the given amount of karma.
 +
  -- @param karma(number) return value of GetKarma()
 +
  -- @return KarmaLevelData(luaTable) from ServerSettings.Karma.Levels
 +
  function GetKarmaLevel(karma)
 +
    karma = karma or 0
 +
    if ( karma >= 0 ) then
 +
        for i,data in pairs(ServerSettings.Karma.Levels) do
 +
            if ( karma >= data.Amount ) then return data end
 +
        end
 +
    elseif ( karma < 0 ) then
 +
        --negative karma we check the list backwards
 +
        local ii = #ServerSettings.Karma.Levels
 +
        for i,data in pairs(ServerSettings.Karma.Levels) do
 +
            if ( ServerSettings.Karma.Levels[ii].Amount >= karma ) then
 +
                return ServerSettings.Karma.Levels[ii]
 +
            end
 +
            ii = ii - 1
 +
        end
 +
    end
 +
  end
 
''
 
''
  
''
 
 
=== GetKarmaStringAmount ===
 
=== GetKarmaStringAmount ===
 
''
 
''
 +
  -- Convert an amount of karma gained/lost to a string representation
 +
  -- @param amount(number)
 +
  -- @return string amount
  
 +
  function GetKarmaStringAmount(amount)
 +
    if ( amount < 10 ) then
 +
        return " a little "
 +
    elseif ( amount < 50 ) then
 +
        return " some "
 +
    elseif ( amount < 100 ) then
 +
        return " "
 +
    elseif ( amount < 1000 ) then
 +
        return " a lot of "
 +
    else
 +
        return " a substantial amount of "
 +
    end
 +
  end
 
''
 
''
 +
 
=== KarmaPunishAllAggressorsForMurder ===
 
=== KarmaPunishAllAggressorsForMurder ===
 
''
 
''
 +
  -- Anyone that is an aggressor to the victim will have a Murder Karma action executed on them.
 +
  -- @param victim(mobileObj)
 +
  -- @return none
  
 +
  function KarmaPunishAllAggressorsForMurder(victim)
 +
    ForeachAggressor(victim,
 +
        function(aggressor)
 +
            if ( aggressor:IsValid() ) then
 +
                ExecuteKarmaAction(aggressor, KarmaActions.Negative.Murder, victim)
 +
            end
 +
        end)
 +
  end
 
''
 
''
 +
 
=== SetKarma ===
 
=== SetKarma ===
 
''
 
''
 +
  -- Set a mobiles karma to an exact amount, does not adjust.
 +
  -- @param mobile(mobileObj)
 +
  -- @param amount(number) The exact number to set their Karma too
 +
  -- @return none
  
 +
  function SetKarma(mobile, amount)
 +
    if ( mobile == nil ) then
 +
        LuaDebugCallStack("[Karma] Nil mobile provided to SetKarma()")
 +
        return
 +
    end
 +
    mobile:SetObjVar("Karma", amount)
 +
  end
 
''
 
''
 +
 
=== WithinKarmaArea ===
 
=== WithinKarmaArea ===
 
''
 
''
 +
  -- Determine if a mobile is in a location that karma matters
 +
  -- @param mobileObj
 +
  -- @return true/false
  
 +
  function WithinKarmaArea(mobileObj)
 +
    for i,j in pairs(ServerSettings.Karma.DisableKarmaZones) do
 +
        if ( mobileObj:IsInRegion(j) ) then return false end
 +
    end
 +
    local regionAddress = GetRegionAddress()
 +
    for i,disabledRegionAddress in pairs(ServerSettings.Karma.DisableKarmaRegionAddresses) do
 +
        if ( regionAddress == disabledRegionAddress ) then return false end
 +
    end
 +
    return true
 +
  end
 +
''
 +
== Server Settings ==
 +
''
 +
  welcome this will discuss the contents of the globals\server_settings\karma.lua
 +
  this documentation is correct as of version 6.0 PRECB1 Release
 +
''
 +
''
 +
  ServerSettings.Karma = {
 +
    -- zones in-game will be disabled from karma.
 +
    DisableKarmaZones = { "Arena" },
 +
    -- Regions with this address will be disabled
 +
    DisableKarmaRegionAddresses = { "TwoTowers" },
 +
    -- the minimum time between daily login bonus
 +
    DailyLoginInterval = TimeSpan.FromHours(20),
 +
    -- always keep these ordered from highest to lowest
 +
    Levels = {
 +
        {
 +
            Amount = 10000,
 +
            Name = "Trustworthy",
 +
            NameColor = "ffff99",
 +
            Title = "%s the Trustworthy", -- %s will be replaced with the mobile's name.
 +
            --Negative Karma Adjustment modifiers are used to compound negative acts by players of positive karma and to reduce players of negative karma from falling off a cliff.
 +
            NegativeKarmaAdjustMod = 5,
 +
            -- do guards protect this karma level for players?
 +
            GuardProtectPlayer = true,
 +
            -- do guards protect this karma level for NPCs?
 +
            GuardProtectNPC = true,
 +
            --PvPMods: Player Vs Player Modifiers; Karma rewards are not given at low levels of positive karma as people may use this to game high karma through killing red accomplices.
 +
              Accomplishing
 +
            high karma must be a grind to those not generating it organically.
 +
            PvPMods = {
 +
                Trustworthy = 2,
 +
                Honest = 1.5,
 +
                Good = 1.25,
 +
                Neutral = 1,
 +
                Rude = 0,
 +
                Scoundrel = -1,
 +
                Outcast = -1.25,
 +
            }
 +
        },
 +
        {
 +
            Amount = 5000,
 +
            Name = "Honest",
 +
            NameColor = "355fb2",
 +
            Title = "%s the Honest",
 +
            NegativeKarmaAdjustMod = 3,
 +
            GuardProtectPlayer = true,
 +
            GuardProtectNPC = true,
 +
            PvPMods = {
 +
                Trustworthy = 2,
 +
                Honest = 1.5,
 +
                Good = 1.25,
 +
                Neutral = 1,
 +
                Rude = 0,
 +
                Scoundrel = -1,
 +
                Outcast = 1.25,
 +
            }
 +
        },
 +
        {
 +
            Amount = 2500,
 +
            Name = "Good",
 +
            NameColor = "82abff",
 +
            Title = "%s the Good",
 +
            NegativeKarmaAdjustMod = 1.5,
 +
            GuardProtectPlayer = true,
 +
            GuardProtectNPC = true,
 +
            PvPMods = {
 +
                Trustworthy = 2,
 +
                Honest = 1.5,
 +
                Good = 1.25,
 +
                Neutral = 1,
 +
                Rude = 0,
 +
                Scoundrel = 0,
 +
                Outcast = 0,
 +
            }
 +
        },
 +
        {
 +
            Amount = 0,
 +
            Name = "Neutral",
 +
            NameColor = "FFFFFF",
 +
            Title = "%s",
 +
            NegativeKarmaAdjustMod = 1,
 +
            GuardProtectPlayer = true,
 +
            PunishBeneficialToNPC = true,
 +
            PvPMods = {
 +
                Trustworthy = 2,
 +
                Honest = 1.5,
 +
                Good = 1.25,
 +
                Neutral = 1,
 +
                Rude = 0,
 +
                Scoundrel = 0,
 +
                Outcast = 0,
 +
            }
 +
        },
 +
        {
 +
            Amount = -2500,
 +
            Name = "Rude",
 +
            NameColor = "A7A7A7",
 +
            Title = "%s the Rude",
 +
            NegativeKarmaAdjustMod = 1,
 +
            GuardProtectPlayer = true,
 +
            GuardHostileNPC = true,
 +
            PunishBeneficialToNPC = true,
 +
            PvPMods = {
 +
                Trustworthy = 2,
 +
                Honest = 1.5,
 +
                Good = 1.25,
 +
                Neutral = 1,
 +
                Rude = 0,
 +
                Scoundrel = 0,
 +
                Outcast = 0,
 +
            },
 +
            -- Apply and modify the Positive Karma action SlayMonster ONLY when slaying an NPC of this Karma Level.
 +
            SlayMonsterModifier = 1,
 +
        },
 +
        {
 +
            Amount = -5000,
 +
            Name = "Scoundrel",
 +
            NameColor = "ff5959",
 +
            Title = "%s the Scoundrel",
 +
            NegativeKarmaAdjustMod = 0.5,
 +
            GuardProtectPlayer = true,
 +
            GuardHostileNPC = true,
 +
            PunishBeneficialToNPC = true,
 +
            PvPMods = {
 +
                Trustworthy = 1,
 +
                Honest = 1,
 +
                Good = 1,
 +
                Neutral = 1,
 +
                Rude = 0,
 +
                Scoundrel = 0,
 +
                Outcast = 0,
 +
            },
 +
            SlayMonsterModifier = 2,
 +
        },
 +
        {
 +
            Amount = -10000,
 +
            Name = "Outcast",
 +
            NameColor = "FF0000",
 +
            Title = "%s the Outcast",
 +
            NegativeKarmaAdjustMod = 0.25,
 +
            -- guards will attack this player, don't set guard protect to true when this is true, things might get weird?
 +
            GuardHostilePlayer = true,
 +
            -- guards will attack this NPC, don't set guard protect to true when this is true, things might get weird?
 +
            GuardHostileNPC = true,
 +
            -- If any beneficial actions are performed on this karma level (as a player), the one performing will have a negative karma action executed on them
 +
            PunishBeneficialToPlayer = true,
 +
            -- If any beneficial actions are performed on this karma level (as an NPC), the one performing will have a negative karma action executed on them
 +
            PunishBeneficialToNPC = true,
 +
            --
 +
            DisallowBlueResurrectShrines = true,
 +
            PvPMods = {
 +
                Trustworthy = 1,
 +
                Honest = 1,
 +
                Good = 1,
 +
                Neutral = 1,
 +
                Rude = 0,
 +
                Scoundrel = 0,
 +
                Outcast = 0,
 +
            },
 +
            SlayMonsterModifier = 3,
 +
        }
 +
    }
 +
  }
 
''
 
''

Latest revision as of 01:19, 28 January 2018

This page documentation was added by Gizmo

Karma Actions

 welcome this will discuss the contents of the globals\static_data\karma\main.lua
 this documentation is correct as of version 6.0 PRECB1 Release 

 --[[  
   KarmaActionName = {
       -- the amount to adjust
       Adjust = -10,
       -- the max amount this karma action can affect
       UpTo = -500,
       -- These only apply to NEGATIVE mods. (Adjust < 0)
       -- if the action is being performed on a NPC (not a player character), it's multiplied by this amount
       NpcModifier = 0.1
   },
 ]]
 KarmaActions = {}
 require 'globals.static_data.karma.negative_actions'
 require 'globals.static_data.karma.positive_actions'

NegativeActions

 welcome this will discuss the contents of the globals\static_data\karma\negative_actions.lua
 this documentation is correct as of version 6.0 PRECB1 Release 

 --[[
   Negative actions, obviously, are only applicable to 'bad' player choices.
   (ie LootContainer should never apply when looting something from your bank or a mob you killed for example, but should apply if the thing you're looting has positive Karma)
 ]]
 KarmaActions.Negative = {
   Attack = {
       Adjust = -50,
       NpcModifier = 0.5,
   },
   -- This applies to looting players bodies as well as anything with ObjVar Karma
   LootContainer = {
       Adjust = -10,
       NpcModifier = 0.25,
   },
   LootUnownedKill = {
       Adjust = -25,
       NpcModifier = 1, -- set to 1 to negate the effects of this modifer for this action since this only applies to npcs (corpses n such)
   },
   Murder = {
       Adjust = -500,
       NpcModifier = 0.1,
   },
   -- applies when a player performs a benefical act on a karma level set to punish beneficial acts
   PunishForBeneficial = {
       Adjust = -50,
       NpcModifier = 0.1,
   },
 }

PositiveActions

 welcome this will discuss the contents of the globals\static_data\karma\positive_actions.lua
 this documentation is correct as of version 6.0 PRECB1 Release 

 KarmaActions.Positive = {
   DailyLogin = {
       Adjust = 50,
       UpTo = 5000,
   },
   SlayMonster = {
       Adjust = 1,
       UpTo = 7500
   }
 }

Karma Functions

 welcome this will discuss the contents of the globals\helpers\karma.lua
 this documentation is correct as of version 6.0 PRECB1 Release 

AdjustKarma

 -- Adjust the karma for a mobile, a system message pertaining to the change is sent.
 -- @param mobile(mobileObj)
 -- @param amount(number) The amount to adjust by.
 -- @return none
 function AdjustKarma(mobile, amount)
   if ( amount == 0 or amount == nil ) then return end
   local karma = GetKarma(mobile)
   -- cache the karma level so we can check if it changed.
   local karmaLevel = GetKarmaLevel(karma)
   karma = math.floor(karma + amount + 0.5)
   SetKarma(mobile, karma)
   if ( amount > 0 ) then
       mobile:SystemMessage("You have gained"..GetKarmaStringAmount(amount).."karma.", "info")
   else
       mobile:SystemMessage("You have lost"..GetKarmaStringAmount(math.abs(amount)).."karma.", "info")
   end
   if ( karmaLevel.Name ~= GetKarmaLevel(karma).Name ) then
       -- Karma was changed, update the name and whatever else, maybe a message?
       mobile:SendMessage("UpdateName")
   end
 end

AlterKarmaAction

 -- convenience function to alter a karma action's amount before applying it
 -- @param karmaAction Lua table karma action
 -- @param newAmount(number)
 -- @return the altered karma action
 function AlterKarmaAction(karmaAction, newAmount)
   karmaAction = deepcopy(karmaAction)
   karmaAction.Adjust = newAmount
   return karmaAction
 end

CheckKarmaBeneficialAction

 -- Check when a player performs a beneficial action on a mobile(player/npc/etc)
 -- @param player(playerObj) DOES NOT ENFORCE IsPlayerCharacter()
 -- @param mobile(mobileObj) Anything with a karma level
 -- @return none
 function CheckKarmaBeneficialAction(player, mobileB)
   -- beneficial actions are only bad against some
   local karmaLevelB = GetKarmaLevel(GetKarma(mobileB))
   local isPlayerB = IsPlayerCharacter(mobileB)
   if (
       (isPlayerB and karmaLevelB.PunishBeneficialToPlayer)
       or
       (not isPlayerB and karmaLevelB.PunishBeneficialToNPC)
   ) then
       ExecuteKarmaAction(player, KarmaActions.Negative.PunishForBeneficial, mobileB)
   end
   if ( isPlayerB ) then
       -- when players benefit players, they inherit their aggressive conflict relations.
       InheritAggressivePlayerConflicts(mobileB, player)
   end
 end

CheckKarmaLoot

 -- Check player against a container on a loot (item removed from a container)
 -- @param player(playerObj) Player doing the looting
 -- @param container(Container) Container being looted from (mobileB:TopmostContainer())
 -- @return none (executes karma actions internally)
 function CheckKarmaLoot(player, container)
   if ( container == nil ) then return end
   -- can't get in trouble doing stuff to yourself..
   if ( player == container ) then return end
   -- only mobiles supported right now
   if not( container:IsMobile() ) then return end
   local containerOwner = nil
   -- re-assign the container to the owner if applicable.
   if ( container:GetCreationTemplateId() == "player_corpse" ) then
       containerOwner = container:GetObjVar("BackpackOwner")
   else
       if ( IsPet(container) ) then containerOwner = container:GetObjectOwner() or container end
   end
   -- can't get in trouble doing stuff to yourself..
   if ( containerOwner ~= nil and player == containerOwner ) then return end
   local isPlayer = false
   if ( containerOwner ~= nil ) then
       isPlayer = IsPlayerCharacter(containerOwner)
   else
       isPlayer = IsPlayerCharacter(container)
   end
   if ( isPlayer ) then
       -- TODO: It's ok to loot players in your group?
       -- if looting a player owned container that's not theirs, advance the conflict relation with no warning, no karma action
       AdvanceConflictRelation(player, containerOwner, true, KarmaActions.Negative.LootContainer)
   else
       -- explicitly check for false, since nil is returned in the event the container doesn't have conflicts
       -- and we don't care to punish anyone for looting something without conflict (like a chest)
       if ( IsMobTaggedBy(container, player) == false ) then
           -- the container is not tagged by the player, therefor the player doesn't have the right to loot.
           ExecuteKarmaAction(player, KarmaActions.Negative.LootUnownedKill)
           return
       end
   end
   -- at this point we just execute a LootContainer action. Karma system should take care of the rest
   ExecuteKarmaAction(player, KarmaActions.Negative.LootContainer, container)
 end

ColorizeMobileName

 -- Colorize a mobile name dependant on their karma
 -- @param mobile(mobileObj) the mobile used to decide the name color
 -- @param newName(string) The name to be colorized
 -- @return colorized newName(string)
 function ColorizeMobileName(mobile, newName)
   if ( mobile == nil ) then
       LuaDebugCallStack("[Karma] Nil mobile supplied to ColorizeMobileName")
       return newName
   end
   local color = nil
   if ( mobile:GetObjVar("ImportantNPC") ~= nil ) then
       color = "F2F5A9"
   else
       color = GetKarmaLevel(GetKarma(mobile)).NameColor
   end
   return "[" .. color .. "]" .. newName .. "[-]"
 end

ColorizePlayerName

 -- Colorize a player's name dependant on their karma
 -- @param player(mobileObj) the playerObj used to decide the name color
 -- @param newName(string) The name to be colorized
 -- @return colorized newName(string)
 function ColorizePlayerName(player, newName)
   if ( player == nil ) then
       LuaDebugCallStack("[Karma] Nil player supplied to ColorizePlayerName")
       return newName
   end
   local color = player:GetObjVar("NameColorOverride")
   if ( color == nil ) then
       if ( IsImmortal(player) and not player:GetObjVar("TestMortal") ) then color = "FFBF00" end
   end
   if ( color == nil ) then
       color = GetKarmaLevel(GetKarma(player)).NameColor
   end
   return "[" .. color .. "]" .. newName .. "[-]"
 end

DailyLogin

 -- Perform the positive karma action Daily Login with checks
 -- @param player(playerObj)
 -- @return none
 function DailyLogin(player)
   local lastDailyLoginReward = player:GetObjVar("KarmaDaily")
   local now = DateTime.UtcNow
   if ( lastDailyLoginReward == nil or lastDailyLoginReward + ServerSettings.Karma.DailyLoginInterval < now ) then
       player:SetObjVar("KarmaDaily", now)
       ExecuteKarmaAction(player, KarmaActions.Positive.DailyLogin)
   end
 end

ExectueKarmaAction

 -- Perform the actual karma handling for a karma action, will adjust mobileA's karma appropriately(if at all) for the given action.
 -- @param mobileA the mobile that is performing the karma action
 -- @param karmaAction(table) The KarmaActions.Positive/KarmaActions.Negative for the action.
 -- @param mobileB(mobileObj)(optional) The mobile that the karma action is being performed on(if any)
 -- @return none
 function ExecuteKarmaAction(mobileA, action, mobileB)
   if ( mobileA == nil ) then
       LuaDebugCallStack("[Karma] Nil mobileA provided, need at least one mobile for a karma action.")
       return
   end
   if ( action == nil ) then
       LuaDebugCallStack("[Karma] Nil action supplied.")
       return
   end
   if ( action.Adjust == nil ) then
       LuaDebugCallStack("[Karma] Supplied action without 'Adjust', this karma action is invalid until resolved.")
       return
   end
   -- if mobileB is passed, ensure it's in the same region.
   if ( mobileB ~= nil and not mobileB:IsValid() ) then return end
   -- karma adjustments can only be applied to players
   if not( IsPlayerCharacter(mobileA) ) then return end
   local karmaA = GetKarma(mobileA)
   -- if they cannot be affected by this karma action any further, stop here.
   if ( action.Adjust < 0 ) then
       if ( action.UpTo and karmaA < action.UpTo ) then return end
   else
       if ( action.UpTo and karmaA > action.UpTo ) then return end
   end
   -- ensure they are both within the karma area.
   if ( not WithinKarmaArea(mobileA) and (mobileB ~= nil and not WithinKarmaArea(mobileB)) ) then
       return
   end
   local isPlayerB = false
   local karmaB = 
   -- handle special karma cases
   if ( mobileB ~= nil ) then
       isPlayerB = IsPlayerCharacter(mobileB)
        -- important npcs are off the charts.
       if ( not isPlayerB and mobileB:HasObjVar("ImportantNPC") ) then karmaB = 1000000 else
           karmaB = GetKarma(mobileB)
       end
   end
   local conflictMod = 1
   local pvpMod = 1
   local negativeAdjustMod = 1
   local npcMod = 1
   -- players in same guilds/opposing factions never effect each other's karma
   if ( isPlayerB ) then
       local guildA = mobileA:GetObjVar("Guild")
       if ( guildA ~= nil ) then
           local guildB = mobileB:GetObjVar("Guild")
           -- they share the same guild, end here
           if ( guildA == guildB ) then return end
           if ( guildB ~= nil and guildA ~= guildB ) then
               -- determined the two involved are both definitely in guilds, and they are not the same guild,
               -- let's compare their factions.
               local guildRecordA = Guild.GetGuildRecord(guildA)
               if ( guildRecordA ~= nil and guildRecordA.PatronGod ~= nil ) then
                   local guildRecordB = Guild.GetGuildRecord(guildB)
                   if ( guildRecordB ~= nil and guildRecordB.PatronGod ~= nil and guildRecordA.PatronGod ~= guildRecordB.PatronGod ) then
                       -- officially determined that playerA and playerB are both in factions, and their factions are not the same.
                       return
                   end
               end
           end
       end
   end
   -- handle negative karma actions
   if ( action.Adjust < 0 ) then
       local karmaALevel = nil
       if ( mobileB ~= nil ) then
           local karmaBLevel = GetKarmaLevel(karmaB)
           -- if guards don't protect them, they are free to perform negative actions on.
           -- the guards are the metaphorical judge/jury/(literal)executioner
           if ( (not isPlayerB and karmaBLevel.GuardProtectNPC ~= true) or (isPlayerB and karmaBLevel.GuardProtectPlayer ~= true) ) then return end
           if ( isPlayerB ) then
               --determine their player vs player modifiers
               karmaALevel = GetKarmaLevel(karmaA)
               karmaBLevel = karmaBLevel or GetKarmaLevel(karmaB)
               pvpMod = karmaALevel.PvPMods[karmaBLevel.Name]
           else
               if ( action.NpcModifier ~= nil ) then
                   -- if mobileB is not a player, modify as such
                   npcMod = action.NpcModifier
               end
           end
           -- get conflict mod
           if ( pvpMod > 0 ) then
               if ( ConflictEquals(GetConflictRelation(mobileB, mobileA), ConflictRelations.Aggressor) ) then
                   local aToBRelation = GetConflictRelation(mobileA, mobileB)
                   if (
                       ConflictEquals(aToBRelation, ConflictRelations.Defender) 
                       or
                       ConflictEquals(aToBRelation, ConflictRelations.Victim)
                   ) then
                       --victim/defender karma action against aggressor, this is free.
                       conflictMod = 0
                   end
               end
           end
       end      
       if ( pvpMod > 0 and conflictMod > 0 ) then
           -- determine the negative karma adjust mod
           karmaALevel = karmaALevel or GetKarmaLevel(karmaA)
           negativeAdjustMod = karmaALevel.NegativeKarmaAdjustMod
       end
   else
       -- handle positive karma actions
   end
   --[[
   DebugMessage("--Execute Karma Action--")
   DebugMessage("Adjust: "..action.Adjust)
   DebugMessage("conMod: "..conflictMod)
   DebugMessage("pvpMod: "..pvpMod)
   DebugMessage("negMod: "..negativeAdjustMod)
   DebugMessage("npcMod: "..npcMod)
   ]]
   local adjust = action.Adjust * conflictMod * pvpMod * negativeAdjustMod * npcMod
   -- prevent positive actions from going negative
   if ( action.Adjust > 0 and adjust < 0 ) then return end
   -- prevent negative actions from going positive
   if ( action.Adjust < 0 and adjust > 0 ) then return end
   -- finally apply all the calculated karma
   AdjustKarma(mobileA, adjust)
 end

GetKarma

 -- Get the Karma for a mobile
 -- @param mobile(mobileObj)
 -- @return Amount of Karma the mobile has(number), 0 if Karma is not set
 function GetKarma(mobile)
   if ( mobile == nil ) then
       LuaDebugCallStack("[Karma] Nil mobile provided to GetKarma()")
       return
   end
   return mobile:GetObjVar("Karma") or 0
 end

GetKarmaLevel

 -- Get the karma level data table for the given amount of karma.
 -- @param karma(number) return value of GetKarma()
 -- @return KarmaLevelData(luaTable) from ServerSettings.Karma.Levels
 function GetKarmaLevel(karma)
   karma = karma or 0
   if ( karma >= 0 ) then
       for i,data in pairs(ServerSettings.Karma.Levels) do
           if ( karma >= data.Amount ) then return data end
       end
   elseif ( karma < 0 ) then
       --negative karma we check the list backwards
       local ii = #ServerSettings.Karma.Levels
       for i,data in pairs(ServerSettings.Karma.Levels) do
           if ( ServerSettings.Karma.Levels[ii].Amount >= karma ) then
               return ServerSettings.Karma.Levels[ii]
           end
           ii = ii - 1
       end
   end
 end

GetKarmaStringAmount

 -- Convert an amount of karma gained/lost to a string representation
 -- @param amount(number)
 -- @return string amount
 function GetKarmaStringAmount(amount)
   if ( amount < 10 ) then
       return " a little "
   elseif ( amount < 50 ) then
       return " some "
   elseif ( amount < 100 ) then
       return " "
   elseif ( amount < 1000 ) then
       return " a lot of "
   else
       return " a substantial amount of "
   end
 end

KarmaPunishAllAggressorsForMurder

 -- Anyone that is an aggressor to the victim will have a Murder Karma action executed on them.
 -- @param victim(mobileObj)
 -- @return none
 function KarmaPunishAllAggressorsForMurder(victim)
   ForeachAggressor(victim, 
       function(aggressor)
           if ( aggressor:IsValid() ) then
               ExecuteKarmaAction(aggressor, KarmaActions.Negative.Murder, victim)
           end
       end)
 end

SetKarma

 -- Set a mobiles karma to an exact amount, does not adjust.
 -- @param mobile(mobileObj)
 -- @param amount(number) The exact number to set their Karma too
 -- @return none
 function SetKarma(mobile, amount)
   if ( mobile == nil ) then
       LuaDebugCallStack("[Karma] Nil mobile provided to SetKarma()")
       return
   end
   mobile:SetObjVar("Karma", amount)
 end

WithinKarmaArea

 -- Determine if a mobile is in a location that karma matters
 -- @param mobileObj
 -- @return true/false
 function WithinKarmaArea(mobileObj)
   for i,j in pairs(ServerSettings.Karma.DisableKarmaZones) do
       if ( mobileObj:IsInRegion(j) ) then return false end
   end
   local regionAddress = GetRegionAddress()
   for i,disabledRegionAddress in pairs(ServerSettings.Karma.DisableKarmaRegionAddresses) do
       if ( regionAddress == disabledRegionAddress ) then return false end
   end
   return true
 end

Server Settings

 welcome this will discuss the contents of the globals\server_settings\karma.lua
 this documentation is correct as of version 6.0 PRECB1 Release 

 ServerSettings.Karma = {
   -- zones in-game will be disabled from karma.
   DisableKarmaZones = { "Arena" },
   -- Regions with this address will be disabled
   DisableKarmaRegionAddresses = { "TwoTowers" },
   -- the minimum time between daily login bonus
   DailyLoginInterval = TimeSpan.FromHours(20),
   -- always keep these ordered from highest to lowest
   Levels = {
       {
           Amount = 10000,
           Name = "Trustworthy",
           NameColor = "ffff99",
           Title = "%s the Trustworthy", -- %s will be replaced with the mobile's name.
           --Negative Karma Adjustment modifiers are used to compound negative acts by players of positive karma and to reduce players of negative karma from falling off a cliff.
           NegativeKarmaAdjustMod = 5,
           -- do guards protect this karma level for players?
           GuardProtectPlayer = true,
           -- do guards protect this karma level for NPCs?
           GuardProtectNPC = true,
           --PvPMods: Player Vs Player Modifiers; Karma rewards are not given at low levels of positive karma as people may use this to game high karma through killing red accomplices. 
             Accomplishing 
           high karma must be a grind to those not generating it organically.
           PvPMods = {
               Trustworthy = 2,
               Honest = 1.5,
               Good = 1.25,
               Neutral = 1,
               Rude = 0,
               Scoundrel = -1,
               Outcast = -1.25,
           }
       },
       {
           Amount = 5000,
           Name = "Honest",
           NameColor = "355fb2",
           Title = "%s the Honest",
           NegativeKarmaAdjustMod = 3,
           GuardProtectPlayer = true,
           GuardProtectNPC = true,
           PvPMods = {
               Trustworthy = 2,
               Honest = 1.5,
               Good = 1.25,
               Neutral = 1,
               Rude = 0,
               Scoundrel = -1,
               Outcast = 1.25,
           }
       },
       {
           Amount = 2500,
           Name = "Good",
           NameColor = "82abff",
           Title = "%s the Good",
           NegativeKarmaAdjustMod = 1.5,
           GuardProtectPlayer = true,
           GuardProtectNPC = true,
           PvPMods = {
               Trustworthy = 2,
               Honest = 1.5,
               Good = 1.25,
               Neutral = 1,
               Rude = 0,
               Scoundrel = 0,
               Outcast = 0,
           }
       },
       {
           Amount = 0,
           Name = "Neutral",
           NameColor = "FFFFFF",
           Title = "%s",
           NegativeKarmaAdjustMod = 1,
           GuardProtectPlayer = true,
           PunishBeneficialToNPC = true,
           PvPMods = {
               Trustworthy = 2,
               Honest = 1.5,
               Good = 1.25,
               Neutral = 1,
               Rude = 0,
               Scoundrel = 0,
               Outcast = 0,
           }
       },
       {
           Amount = -2500,
           Name = "Rude",
           NameColor = "A7A7A7",
           Title = "%s the Rude",
           NegativeKarmaAdjustMod = 1,
           GuardProtectPlayer = true,
           GuardHostileNPC = true,
           PunishBeneficialToNPC = true,
           PvPMods = {
               Trustworthy = 2,
               Honest = 1.5,
               Good = 1.25,
               Neutral = 1,
               Rude = 0,
               Scoundrel = 0,
               Outcast = 0,
           },
           -- Apply and modify the Positive Karma action SlayMonster ONLY when slaying an NPC of this Karma Level.
           SlayMonsterModifier = 1,
       },
       {
           Amount = -5000,
           Name = "Scoundrel",
           NameColor = "ff5959",
           Title = "%s the Scoundrel",
           NegativeKarmaAdjustMod = 0.5,
           GuardProtectPlayer = true,
           GuardHostileNPC = true,
           PunishBeneficialToNPC = true,
           PvPMods = {
               Trustworthy = 1,
               Honest = 1,
               Good = 1,
               Neutral = 1,
               Rude = 0,
               Scoundrel = 0,
               Outcast = 0,
           },
           SlayMonsterModifier = 2,
       },
       {
           Amount = -10000,
           Name = "Outcast",
           NameColor = "FF0000",
           Title = "%s the Outcast",
           NegativeKarmaAdjustMod = 0.25,
           -- guards will attack this player, don't set guard protect to true when this is true, things might get weird?
           GuardHostilePlayer = true,
           -- guards will attack this NPC, don't set guard protect to true when this is true, things might get weird?
           GuardHostileNPC = true,
           -- If any beneficial actions are performed on this karma level (as a player), the one performing will have a negative karma action executed on them
           PunishBeneficialToPlayer = true,
           -- If any beneficial actions are performed on this karma level (as an NPC), the one performing will have a negative karma action executed on them
           PunishBeneficialToNPC = true,
           --
           DisallowBlueResurrectShrines = true,
           PvPMods = {
               Trustworthy = 1,
               Honest = 1,
               Good = 1,
               Neutral = 1,
               Rude = 0,
               Scoundrel = 0,
               Outcast = 0,
           },
           SlayMonsterModifier = 3,
       }
   }
 }