Difference between revisions of "ConflictSystem"
(→AdvanceConflictRelation) |
(→ForeachAggressor) |
||
Line 326: | Line 326: | ||
=== ForeachAggressor === | === ForeachAggressor === | ||
+ | '' | ||
+ | -- Perform a function on each aggressor of a mobile | ||
+ | -- @param mobile(mobileObj) | ||
+ | -- @param callback(function(id)) | ||
+ | -- @return none | ||
+ | |||
+ | function ForeachAggressor(mobile, callback) | ||
+ | local conflictTable = GetConflictTable(mobile) | ||
+ | for mobileB,relation in pairs(conflictTable) do | ||
+ | if ( mobileB:IsValid() ) then | ||
+ | if (( ConflictEquals(relation[1], ConflictRelations.Victim) or ConflictEquals(relation[1], ConflictRelations.Defender )) and ValidConflictRelationTable(relation)) then | ||
+ | if ( ConflictEquals(GetConflictRelation(mobileB, mobile), ConflictRelations.Aggressor) ) then | ||
+ | callback(mobileB) | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | '' | ||
+ | |||
=== IsAggressor === | === IsAggressor === | ||
=== IsMobTaggedBy === | === IsMobTaggedBy === |
Revision as of 08:22, 27 January 2018
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 ConflictRelations Table
- 2 Conflict Functions
- 2.1 GetConflictTable
- 2.2 ClearConflictTable
- 2.3 SetConflictTable
- 2.4 FreezeConflictTable
- 2.5 GetConflictRelation
- 2.6 ValidConflictRelationTable
- 2.7 UpdateConflictRelation
- 2.8 ConflictEquals
- 2.9 AdvanceConflictRelation
- 2.10 ForeachAggressor
- 2.11 IsAggressor
- 2.12 IsMobTaggedBy
- 2.13 TagMob
- 2.14 InheritAggressivePlayerConflicts
- 2.15 GetNearbyTaggedMobiles
- 2.16 InitializeClientConflicts
ConflictRelations Table
ConflictRelations = { Warning = { Name = "Warning", Warning = true, }, BeenWarned = { Name = "BeenWarned", Warning = true, }, Aggressor = { Name = "Aggressor", }, Victim = { Name = "Victim" }, Defender = { Name = "Defender" } }
Conflict Functions
GetConflictTable
-- Get the conflict table for a mobile -- @param mobile(mobileObj) -- @return luaTable containing all conflicts for this mobile
function GetConflictTable(mobile) if ( mobile == nil or not mobile ) then LuaDebugCallStack("[Conflict] Invalid mobile provided.") return {} end return mobile:GetObjVar("Conflicts") or {} end
ClearConflictTable
-- Clear the conflict table of a mobile -- @param mobile(mobileObj) -- @return none
function ClearConflictTable(mobile, isPlayer) if ( mobile == nil or not mobile ) then LuaDebugCallStack("[Conflict] Invalid mobile provided.") return end if ( mobile:HasObjVar("Conflicts") ) then mobile:DelObjVar("Conflicts") end if ( isPlayer == true ) then InitializeClientConflicts(mobile) end end
SetConflictTable
-- Set the conflict table for a mobile -- @param mobile(mobileObj) -- @param data(luaTable) -- @return none
function SetConflictTable(mobile, data) mobile:SetObjVar("Conflicts", data) end
FreezeConflictTable
--- Freeze the conflict table on a mobile, optionally saving the frozen table on a different object. Will clear all conflicts for the mobile if target does not equal mobile. -- @param mobile(mobileObj) -- @param target(gameObj)(optional) the gameObj the conflict table will be saved to -- @return none
function FreezeConflictTable(mobile, target) target = target or mobile local conflictTable = GetConflictTable(mobile) for mobileId,conflict in pairs(conflictTable) do -- set all the expires to true, meaning they never expire conflictTable[mobileId][2] = true end -- save the frozen table on the target SetConflictTable(target, conflictTable) end
GetConflictRelation
-- Get the relation of conflict mobileA is to mobileB. -- @param mobileA(mobileObj) -- @param mobileB(mobileObj) -- @param mobileAConflictTable(optional) return value from GetConflictTable() -- @return One of ConflictRelations, nil if not-found/expired.
function GetConflictRelation(mobileA, mobileB, mobileAConflictTable) mobileAConflictTable = mobileAConflictTable or GetConflictTable(mobileA) or {} -- only valid, frozen/non-expired, will make the cut. if ( ValidConflictRelationTable(mobileAConflictTable[mobileB]) ) then return mobileAConflictTable[mobileB][1] end return nil end
ValidConflictRelationTable
--- Validate a conflict relation table (make sure it's not expired) -- @param conflictRelationTable(luaTable) A single entry from return value GetConflictTable() -- @return true if valid, false if not
function ValidConflictRelationTable(conflictRelationTable) return ( conflictRelationTable ~= nil and ( -- frozen conflictRelationTable[2] == true or -- or non-expired DateTime.UtcNow < conflictRelationTable[2] ) ) end
UpdateConflictRelation
-- Update the conflict relation between two mobiles, also cleans mobileA's conflict table of any expired. -- @param mobileA(mobileObj) -- @param mobileB(mobileObj) -- @param newRelation(luaTable) the entry from ConflictRelations -- @param guardCheck(boolean) If true, this update will check for guard protection, this way you can refresh a conflict on both sides but only one will cares about guards. -- @return none
function UpdateConflictRelation(mobileA, mobileB, newRelation, guardCheck) if ( newRelation == nil ) then LuaDebugCallStack("[Conflict] Nil conflict relation table provided") return end if ( newRelation.Name == nil ) then LuaDebugCallStack("[Conflict] Invalid conflict relation table, missing Name") return end if ( mobileA == nil ) then LuaDebugCallStack("[Conflict] Nil mobileA provided.") return end if ( mobileB == nil ) then LuaDebugCallStack("[Conflict] Nil mobileB provided.") return end local tableA = GetConflictTable(mobileA) local wasGuardIgnored = false if ( not guardCheck and tableA[mobileB] ~= nil and tableA[mobileB][3] ) then wasGuardIgnored = true end -- set/update the conflict local now = DateTime.UtcNow tableA[mobileB] = {newRelation.Name} -- when the conflict should end if ( newRelation.Warning == true ) then tableA[mobileB][2] = now + ServerSettings.Conflict.WarningDuration else tableA[mobileB][2] = now + ServerSettings.Conflict.RelationDuration end -- cleanse table of any expired. for k,v in pairs(tableA) do if ( now >= v[2] ) then -- it's expired tableA[k] = nil end end if ( ConflictEquals(newRelation.Name, ConflictRelations.Aggressor) and IsPlayerCharacter(mobileA) and IsPlayerCharacter(mobileB)) then -- mobileB has zero karma concequences against mobileA -- Turn mobileA AGGRESSIVE on mobileB's client (so B is looking at an aggressive A) mobileA:SendClientMessage("UpdateMobileConflictStatus", {mobileB,"Aggressor",ServerSettings.Conflict.RelationDuration.TotalSeconds}) mobileB:SendClientMessage("UpdateMobileConflictStatus", {mobileA,"Aggressed",ServerSettings.Conflict.RelationDuration.TotalSeconds}) -- 100 elseif ( ConflictEquals(newRelation.Name, ConflictRelations.Warning) and IsPlayerCharacter(mobileA) and IsPlayerCharacter(mobileB) ) then -- mobileA is nearly an aggressor to mobileB -- Turn mobileB YELLOW on mobileA's client (so A is looking at a mobile they know if they hit again they are an aggressor) mobileA:SendClientMessage("UpdateMobileConflictStatus", {mobileB,"Warning",ServerSettings.Conflict.WarningDuration.TotalSeconds}) end --[[ Handle Guard protection triggers for aggressive actions. ]] -- if mobileA's relation is aggressor if ( guardCheck and ConflictEquals(newRelation.Name, ConflictRelations.Aggressor) ) then local karmaBLevel = GetKarmaLevel(GetKarma(mobileB)) local guardIgnore = true -- if mobileB's karma level is guard protected if ( karmaBLevel.GuardProtectPlayer or karmaBLevel.GuardProtectNPC ) then local isPlayerB = IsPlayerCharacter(mobileB) if ( (isPlayerB and karmaBLevel.GuardProtectPlayer) or (not isPlayerB and karmaBLevel.GuardProtectNPC) ) then -- make the guards protect B from A GuardProtect(mobileB, mobileA) guardIgnore = false end end -- if guards don't protect mobileB's karma level, add an ignore guard entry -- (This is so, for example, players can be aggressors against an outcast, but guards won't attack them for being aggressors against outcasts) if ( guardIgnore == true ) then tableA[mobileB][3] = true end end -- when skipping guard protect this value would be ignored and overwritten if not cached from previous data. if ( wasGuardIgnored ) then tableA[mobileB][3] = true end -- save the updated conflict table for the mobile SetConflictTable(mobileA, tableA) end
ConflictEquals
-- Convenience function to make checking conflicts more readable -- @param strRelation(string) The string Name of the relation to check for -- @param tableRelation(luaTable) The ConflictRelations entry to check against -- @return true or false
function ConflictEquals(strRelation, tableRelation) return ( strRelation == tableRelation.Name ) end
AdvanceConflictRelation
-- Advance mobileA against mobileB in conflict, will also refresh any current conflicts between the two. -- @param mobileA(mobileObj) -- @param mobileB(mobileObj) -- @param noWarning(boolean)(optional) if true, warning will be skipped and they will go directly to aggressor -- @param karmaAction(luaTable)(optional) KarmaAction that will be executed on mobileA when they become an aggressor. (default: KarmaActions.Negative.Attack) Setting this to false will not execute any karma actions. -- @return none
function AdvanceConflictRelation(mobileA, mobileB, noWarning, karmaAction) if not( karmaAction == false ) then karmaAction = karmaAction or KarmaActions.Negative.Attack end -- when Warnings are not enabled, we force noWarning to true. if ( ServerSettings.Conflict.WarningEnabled ~= true ) then noWarning = true end -- reassign mobileA and mobileB to pet owners, if applicable if ( IsPet(mobileA) ) then mobileA = mobileA:GetObjectOwner() or mobileA end if ( mobileB ~= nil and IsPet(mobileB) ) then mobileB = mobileB:GetObjectOwner() or mobileB end -- conflict don't care what you do to yourself or your pets if ( mobileA == mobileB ) then return end local aToBRelation = GetConflictRelation(mobileA, mobileB) local bToARelation = GetConflictRelation(mobileB, mobileA) local refreshA = true local refreshB = true -- when one side has a relation but the other side does not, we count neither side as having a relation. -- this is so we can clear a conflict relation on either side and not need to clear both involved parties (the other involved could be in a different region at time of clearing!) if ( noWarning ~= true and (aToBRelation == nil or bToARelation == nil) ) then UpdateConflictRelation(mobileA, mobileB, ConflictRelations.Warning) UpdateConflictRelation(mobileB, mobileA, ConflictRelations.BeenWarned) refreshA = false elseif ( (noWarning == true and (aToBRelation == nil or bToARelation == nil)) or ConflictEquals(aToBRelation, ConflictRelations.Warning) ) then -- A becomes aggressor, B becomes victim. UpdateConflictRelation(mobileA, mobileB, ConflictRelations.Aggressor, true) UpdateConflictRelation(mobileB, mobileA, ConflictRelations.Victim) refreshA = false refreshB = false -- Karma action for becoming the aggressor if ( karmaAction ) then ExecuteKarmaAction(mobileA, karmaAction, mobileB) end if ( IsInitiate(mobileB) and IsPlayerCharacter(mobileA) ) then EndInitiate(mobileB) end elseif ( ConflictEquals(aToBRelation, ConflictRelations.Victim) ) then -- A was a victim, now A is a defender. UpdateConflictRelation(mobileA, mobileB, ConflictRelations.Defender) refreshA = false end --refresh the conflict expiration. -- Possible optimization, only refresh every other one/every third one? if ( aToBRelation ~= nil and refreshA ) then if ( karmaAction and ConflictEquals(aToBRelation, ConflictRelations.Aggressor) ) then ExecuteKarmaAction(mobileA, karmaAction, mobileB) end UpdateConflictRelation(mobileA, mobileB, ConflictRelations[aToBRelation], true) end if ( bToARelation ~= nil and refreshB ) then UpdateConflictRelation(mobileB, mobileA, ConflictRelations[bToARelation]) end end
ForeachAggressor
-- Perform a function on each aggressor of a mobile -- @param mobile(mobileObj) -- @param callback(function(id)) -- @return none
function ForeachAggressor(mobile, callback) local conflictTable = GetConflictTable(mobile) for mobileB,relation in pairs(conflictTable) do if ( mobileB:IsValid() ) then if (( ConflictEquals(relation[1], ConflictRelations.Victim) or ConflictEquals(relation[1], ConflictRelations.Defender )) and ValidConflictRelationTable(relation)) then if ( ConflictEquals(GetConflictRelation(mobileB, mobile), ConflictRelations.Aggressor) ) then callback(mobileB) end end end end end