KarmaSystem

From Legends of Aria Admin and Modding Wiki
Revision as of 09:24, 27 January 2018 by Gizmo (talk | contribs) (KarmaPunishAllAggressorsForMurder)
Jump to: navigation, search

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

Karma Functions

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

ColorizePlayerName

DailyLogin

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

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