KarmaSystem
welcome this will discuss the contents of the globals\helpers\conflict.lua this documentation is correct as of version 6.0 PRECB1 Release
Contents
- 1 Karma Functions
- 1.1 AdjustKarma
- 1.2 AlterKarmaAction
- 1.3 CheckKarmaBeneficialAction
- 1.4 CheckKarmaLoot
- 1.5 ColorizeMobileName
- 1.6 ColorizePlayerName
- 1.7 DailyLogin
- 1.8 ExectueKarmaAction
- 1.9 GetKarma
- 1.10 GetKarmaLevel
- 1.11 GetKarmaStringAmount
- 1.12 KarmaPunishAllAggressorsForMurder
- 1.13 SetKarma
- 1.14 WithinKarmaArea
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