17,105
edits
(getMatchCriteriaFromIDs: Fix processing of scopes from modifier IDs) |
(Support modifier matching by properties such as skill ID, item ID, etc.) |
||
Line 33: | Line 33: | ||
['mod'] = modDefn, | ['mod'] = modDefn, | ||
['alias'] = modAlias, | ['alias'] = modAlias, | ||
[' | ['props'] = { ['valueType'] = keyDefn.type } | ||
} | } | ||
end | end | ||
Line 52: | Line 52: | ||
['key'] = 'damageType', | ['key'] = 'damageType', | ||
['templateKey'] = 'damageType', | ['templateKey'] = 'damageType', | ||
['templateKey2'] = 'resistanceName' | ['templateKey2'] = 'resistanceName', | ||
['gameDataKey'] = 'damageTypes' | |||
}, | }, | ||
['realmID'] = { | ['realmID'] = { | ||
['key'] = 'realm', | ['key'] = 'realm', | ||
['templateKey'] = 'realmName' | ['templateKey'] = 'realmName', | ||
['gameDataKey'] = 'realms' | |||
}, | }, | ||
['currencyID'] = { | ['currencyID'] = { | ||
['key'] = 'currency', | ['key'] = 'currency', | ||
['templateKey'] = 'currencyName' | ['templateKey'] = 'currencyName', | ||
['gameDataKey'] = 'currencies' | |||
}, | }, | ||
['categoryID'] = { | ['categoryID'] = { | ||
Line 76: | Line 79: | ||
['itemID'] = { | ['itemID'] = { | ||
['key'] = 'item', | ['key'] = 'item', | ||
['templateKey'] = 'itemName' | ['templateKey'] = 'itemName', | ||
['gameDataKey'] = 'items' | |||
}, | }, | ||
['effectGroupID'] = { | ['effectGroupID'] = { | ||
['key'] = 'effectGroup', | ['key'] = 'effectGroup', | ||
['templateKey'] = 'effectGroupName' | ['templateKey'] = 'effectGroupName', | ||
['gameDataKey'] = 'combatEffectGroups' | |||
}, | }, | ||
} | } | ||
local ScopeKeyToIDMap = {} | |||
for idKey, defn in pairs(ScopeKeyMap) do | |||
ScopeKeyToIDMap[defn.key] = idKey | |||
end | |||
-- Retrieves a modifier definition by ID | -- Retrieves a modifier definition by ID | ||
Line 127: | Line 137: | ||
-- At this point, both definitions have the same elements | -- At this point, both definitions have the same elements | ||
return true | return true | ||
end | |||
-- Given a table containing one or more sets of data criteria, combines those criteria into a | |||
-- single set of criteria. Should the same criteria key be specified more than once, the value from | |||
-- the last set containing that key will be retained | |||
function p.combineDataCriteria(dataCriteriaList) | |||
local rv = {} | |||
for _, dataCriteria in ipairs(dataCriteriaList) do | |||
for dataKey, dataValue in pairs(dataCriteria) do | |||
rv[dataKey] = dataValue | |||
end | |||
end | |||
return rv | |||
end | |||
-- Given data criteria where the values are entity names, converts those names to IDs. | |||
function p.convertCriteriaNamesToIDs(dataCriteriaByName) | |||
local dataCriteria = {} | |||
for criteriaKey, criteriaName in pairs(dataCriteriaByName) do | |||
if criteriaName == nil or criteriaName == '' then | |||
error('Value for criteria ' .. criteriaKey .. ' cannot be nil', 2) | |||
end | |||
if criteriaKey == 'valueType' then | |||
-- Special case | |||
dataCriteria[criteriaKey] = string.lower(criteriaName) | |||
elseif ScopeKeyMap[criteriaKey] ~= nil then | |||
-- ID specified directly | |||
dataCriteria[criteriaKey] = criteriaName | |||
else | |||
local criteriaIDKey = ScopeKeyToIDMap[criteriaKey] | |||
if criteriaIDKey == nil then | |||
error('Invalid criteria specified: ' .. criteriaKey, 2) | |||
end | |||
local keyMap = ScopeKeyMap[criteriaIDKey] | |||
local criteriaID = nil | |||
if keyMap.gameDataKey ~= nil then | |||
local criteriaData = GameData.getEntityByName(keyMap.gameDataKey, criteriaName) | |||
if criteriaData ~= nil then | |||
criteriaID = criteriaData.id | |||
end | |||
elseif criteriaKey == 'skill' then | |||
criteriaID = Common.getSkillID(criteriaName) | |||
else | |||
error('Criteria ' .. criteriaKey .. ' is currently unsupported', 2) | |||
end | |||
if criteriaID == nil then | |||
error('Unknown ' .. criteriaKey .. ': ' .. criteriaName, 2) | |||
end | |||
dataCriteria[criteriaIDKey] = criteriaID | |||
end | |||
end | |||
return dataCriteria | |||
end | end | ||
Line 174: | Line 239: | ||
-- Given a list of modifier IDs and aliases, returns all match criteria for these. | -- Given a list of modifier IDs and aliases, returns all match criteria for these. | ||
-- This matching criteria can then be pased to p.getMatchingModifiers() | -- This matching criteria can then be pased to p.getMatchingModifiers() | ||
function p.getMatchCriteriaFromIDs(modifierIDs | function p.getMatchCriteriaFromIDs(modifierIDs) | ||
local matchCriteria = {} | local matchCriteria = {} | ||
-- For modifier IDs, find the relevant mod definition and add all allowed scopes | -- For modifier IDs, find the relevant mod definition and add all allowed scopes | ||
if modifierIDs ~= nil then | if modifierIDs ~= nil then | ||
for _, | for _, idObject in ipairs(modifierIDs) do | ||
local modDefn = p.getModifierByID(modifierID) | local modifierID = idObject.id | ||
local modType = idObject.type | |||
local modProps = idObject.props or {} | |||
if modType == 'id' then | |||
local modDefn = p.getModifierByID(modifierID) | |||
if modDefn == nil then | |||
error('No such modifier ID: ' .. modifierID, 2) | |||
end | |||
-- Add all scopes | |||
for _, allowedScope in ipairs(modDefn.allowedScopes) do | |||
table.insert(matchCriteria, { | |||
["mod"] = modDefn, | |||
["scope"] = allowedScope.scopes or {}, | |||
["props"] = modProps | |||
}) | |||
end | |||
elseif modType == 'alias' then | |||
-- For alias IDs, simply add these one at a time to the table | |||
table.insert(matchCriteria, { | table.insert(matchCriteria, { | ||
[" | ["alias"] = modifierID, | ||
[" | ["props"] = modProps | ||
}) | }) | ||
else | |||
error('Unknown modifier ID type: ' .. (modType or 'nil'), 2) | |||
end | end | ||
end | end | ||
end | end | ||
Line 209: | Line 281: | ||
-- when they relate to that given skill ID | -- when they relate to that given skill ID | ||
-- matchCriteria is a table of elements structured as follows: | -- matchCriteria is a table of elements structured as follows: | ||
-- { ["mod"] = modDefn, ["scope"] = scopeDefn, ["alias"] = modAlias } | -- { | ||
-- ["mod"] = modDefn, | |||
-- ["scope"] = scopeDefn, | |||
-- ["alias"] = modAlias, | |||
-- ["props"] = modProps | |||
-- } | |||
-- Examples of valid mod and scope definitions can be obtained from | -- Examples of valid mod and scope definitions can be obtained from | ||
-- p.getModifierByID() and p.getScope() | -- p.getModifierByID() and p.getScope() | ||
-- alias is an optional property, if specified mod and scope are derived | -- alias is an optional property, if specified mod and scope are derived | ||
-- from the modAlias. | -- from the modAlias. | ||
function p.getMatchingModifiers(modifiers, matchCriteria | -- props is an optional property, if specified then a modifier is only matched | ||
-- if the properties (skillID, itemID, etc.) also match. | |||
function p.getMatchingModifiers(modifiers, matchCriteria) | |||
local resultMods = { | local resultMods = { | ||
["matched"] = {}, | ["matched"] = {}, | ||
Line 223: | Line 302: | ||
local matchCriteriaMap = {} | local matchCriteriaMap = {} | ||
for _, matchDefn in ipairs(matchCriteria) do | for _, matchDefn in ipairs(matchCriteria) do | ||
local modDefn, scopeDefn, modAlias, | local modDefn, scopeDefn, modAlias, propCriteria = matchDefn.mod, matchDefn.scope, {}, (matchDefn.props or {}) | ||
if matchDefn.alias ~= nil then | if matchDefn.alias ~= nil then | ||
local aliasData = p.getModifierByAlias(matchDefn.alias) | local aliasData = p.getModifierByAlias(matchDefn.alias) | ||
Line 229: | Line 308: | ||
error('No such modifier alias: ' .. matchDefn.alias, 2) | error('No such modifier alias: ' .. matchDefn.alias, 2) | ||
else | else | ||
modDefn, scopeDefn, modAlias, | local aliasProps = p.combineDataCriteria({propCriteria, aliasData.props}) | ||
modDefn, scopeDefn, modAlias, propCriteria = aliasData.mod, aliasData.scope.scopes, aliasData.alias, aliasProps | |||
end | end | ||
Line 237: | Line 317: | ||
matchCriteriaMap[modLocalID] = {} | matchCriteriaMap[modLocalID] = {} | ||
end | end | ||
table.insert(matchCriteriaMap[modLocalID], { ["scope"] = scopeDefn, ["alias"] = modAlias, [" | table.insert(matchCriteriaMap[modLocalID], { ["scope"] = scopeDefn, ["alias"] = modAlias, ["props"] = propCriteria }) | ||
end | end | ||
Line 259: | Line 339: | ||
local modScopeDefn = p.convertScopeDataToDefinition(scopeData) | local modScopeDefn = p.convertScopeDataToDefinition(scopeData) | ||
for _, matchDefn in ipairs(modMatchCriteria) do | for _, matchDefn in ipairs(modMatchCriteria) do | ||
local scopeDefn, modAlias = matchDefn.scope, matchDefn.alias | local scopeDefn, modAlias, propCriteria = matchDefn.scope, matchDefn.alias, matchDefn.props | ||
local matchKey = 'unmatched' | local matchKey = 'unmatched' | ||
-- Check that: | -- Check that: | ||
Line 272: | Line 348: | ||
p.doScopeDefinitionsMatch(modScopeDefn, scopeDefn) | p.doScopeDefinitionsMatch(modScopeDefn, scopeDefn) | ||
and p.checkScopeDataMeetsCriteria(scopeData, scopeDefn, modAlias) | and p.checkScopeDataMeetsCriteria(scopeData, scopeDefn, modAlias) | ||
and p.checkScopeDataMeetsCriteria(scopeData, scopeDefn, | and p.checkScopeDataMeetsCriteria(scopeData, scopeDefn, propCriteria) | ||
) then | ) then | ||
-- Add to matched table | -- Add to matched table | ||
Line 646: | Line 722: | ||
function p.test3() | function p.test3() | ||
local item = GameData.getEntityByID('items', ' | local item = GameData.getEntityByID('items', 'melvorItA:Corrupted_Light_Consumable_I') | ||
local matchCriteria = { | local matchCriteria = { | ||
{ | { | ||
Line 674: | Line 750: | ||
["damageType"] = true | ["damageType"] = true | ||
} | } | ||
}, | |||
{ | |||
["mod"] = p.getModifierByID('flatBaseRandomProductQuantity'), | |||
["scope"] = { | |||
["item"] = true, | |||
["skill"] = true | |||
}, | |||
["props"] = p.convertCriteriaNamesToIDs({ ["item"] = 'Abyssal Stardust' }) | |||
} | } | ||
} | } | ||
return p.getMatchingModifiers(item.modifiers, matchCriteria | return p.getMatchingModifiers(item.modifiers, matchCriteria) | ||
end | end | ||
Line 702: | Line 786: | ||
local modIDs = {} | local modIDs = {} | ||
for modID, modDet in pairs(entMods) do | for modID, modDet in pairs(entMods) do | ||
table.insert(modIDs, modID) | table.insert(modIDs, { | ||
["id"] = modID, | |||
["type"] = 'id', | |||
["props"] = {} | |||
}) | |||
end | end | ||
local matchCriteria = p.getMatchCriteriaFromIDs(modIDs | local matchCriteria = p.getMatchCriteriaFromIDs(modIDs) | ||
mw.logObject(matchCriteria) | mw.logObject(matchCriteria) | ||
mw.log('=======================================================') | mw.log('=======================================================') |