Index: binaries/data/mods/public/globalscripts/AttackEffects.js =================================================================== --- binaries/data/mods/public/globalscripts/AttackEffects.js +++ binaries/data/mods/public/globalscripts/AttackEffects.js @@ -1,16 +1,62 @@ -// TODO: could be worth putting this in json files someday -const g_EffectTypes = ["Damage", "Capture", "ApplyStatus"]; -const g_EffectReceiver = { - "Damage": { - "IID": "IID_Health", - "method": "TakeDamage" - }, - "Capture": { - "IID": "IID_Capturable", - "method": "Capture" - }, - "ApplyStatus": { - "IID": "IID_StatusEffectsReceiver", - "method": "ApplyStatus" +/** + * This class provides a cache for accessing attack effects stored in JSON files. + */ +class AttackEffects +{ + constructor() + { + let effectsData = []; + let effectsDataObj = {}; + this.effectTypes = []; + this.effectReceivers = {}; + + for (let filename of Engine.ListDirectoryFiles("simulation/data/effects", "*.json", false)) + { + let data = Engine.ReadJSONFile(filename); + if (!data) + continue; + + if (data.code in effectsDataObj) + { + error("Encountered two effect types with the code " + data.name); + continue; + } + + effectsData.push(data); + effectsDataObj[data.code] = data; + + this.effectTypes.push(data.code); + this.effectReceivers[data.code] = { + "IID": data.IID, + "method": data.method + }; + } + + let effDataSort = (a, b) => a.order < b.order ? -1 : a.order > b.order ? +1 : 0; + let effSort = (a, b) => effDataSort( + effectsData.find(effect => effect.code == a), + effectsData.find(effect => effect.code == b) + ); + this.effectTypes.sort(effSort); + + deepfreeze(this.effectTypes); + deepfreeze(this.effectReceivers); } -}; + + /** + * @return {string[]} - The effects possible. + */ + GetTypes() + { + return this.effectTypes; + } + + /** + * @param {string} type - The type of effect to get the receiving IID and function for. + * @return {Object} - Object of the form { "IID": {String}, "method": {String} }. + */ + GetReceiver(type) + { + return this.effectReceivers[type]; + } +} Index: binaries/data/mods/public/globalscripts/tests/test_attackeffects.js =================================================================== --- /dev/null +++ binaries/data/mods/public/globalscripts/tests/test_attackeffects.js @@ -0,0 +1,29 @@ +let effects = { + "eff_A": { + "code": "a", + "name": "A", + "order": 2, + "IID": "IID_A", + "method": "doA" + }, + "eff_B": { + "code": "b", + "name": "B", + "order": 1, + "IID": "IID_B", + "method": "doB" + } +}; + +Engine.ListDirectoryFiles = () => Object.keys(effects); +Engine.ReadJSONFile = (file) => effects[file]; + +let attackEffects = new AttackEffects(); + +TS_ASSERT_EQUALS(attackEffects.GetTypes().length, 2); +TS_ASSERT_EQUALS(attackEffects.GetTypes()[0], "b"); + +TS_ASSERT_UNEVAL_EQUALS(attackEffects.GetReceiver("b"), { + "IID": "IID_B", + "method": "doB" +}); Index: binaries/data/mods/public/simulation/components/tests/test_Attack.js =================================================================== --- binaries/data/mods/public/simulation/components/tests/test_Attack.js +++ binaries/data/mods/public/simulation/components/tests/test_Attack.js @@ -1,3 +1,27 @@ +AttackEffects = class AttackEffects +{ + constructor() {} + GetTypes() { return ["Damage", "Capture", "ApplyStatus"]; } + GetReceiver(effect) + { + if (effect == "Damage") + return { + "IID": "IID_Health", + "method": "TakeDamage" + }; + if (effect == "Capture") + return { + "IID": "IID_Capturable", + "method": "Capture" + }; + if (effect == "ApplyStatus") + return { + "IID": "IID_StatusEffectsReceiver", + "method": "ApplyStatus" + }; + } +}; + Engine.LoadHelperScript("DamageBonus.js"); Engine.LoadHelperScript("Attacking.js"); Engine.LoadHelperScript("Player.js"); Index: binaries/data/mods/public/simulation/components/tests/test_Damage.js =================================================================== --- binaries/data/mods/public/simulation/components/tests/test_Damage.js +++ binaries/data/mods/public/simulation/components/tests/test_Damage.js @@ -1,3 +1,17 @@ +AttackEffects = class AttackEffects +{ + constructor() {} + GetTypes() { return ["Damage"]; } + GetReceiver(effect) + { + if (effect == "Damage") + return { + "IID": "IID_Health", + "method": "TakeDamage" + }; + } +}; + Engine.LoadHelperScript("DamageBonus.js"); Engine.LoadHelperScript("Attacking.js"); Engine.LoadHelperScript("Player.js"); Index: binaries/data/mods/public/simulation/components/tests/test_DeathDamage.js =================================================================== --- binaries/data/mods/public/simulation/components/tests/test_DeathDamage.js +++ binaries/data/mods/public/simulation/components/tests/test_DeathDamage.js @@ -1,3 +1,17 @@ +AttackEffects = class AttackEffects +{ + constructor() {} + GetTypes() { return ["Damage"]; } + GetReceiver(effect) + { + if (effect == "Damage") + return { + "IID": "IID_Health", + "method": "TakeDamage" + }; + } +}; + Engine.LoadHelperScript("DamageBonus.js"); Engine.LoadHelperScript("Attacking.js"); Engine.LoadHelperScript("ValueModification.js"); Index: binaries/data/mods/public/simulation/data/effects/capture.json =================================================================== --- /dev/null +++ binaries/data/mods/public/simulation/data/effects/capture.json @@ -0,0 +1,8 @@ +{ + "code": "Capture", + "name": "Capture", + "description": "Reduces capture points of a target.", + "IID": "IID_Capturable", + "method": "Capture", + "order": 2 +} Index: binaries/data/mods/public/simulation/data/effects/damage.json =================================================================== --- /dev/null +++ binaries/data/mods/public/simulation/data/effects/damage.json @@ -0,0 +1,8 @@ +{ + "code": "Damage", + "name": "Damage", + "description": "Reduces the health of a target.", + "IID": "IID_Health", + "method": "TakeDamage", + "order": 1 +} Index: binaries/data/mods/public/simulation/data/effects/statuseffects.json =================================================================== --- /dev/null +++ binaries/data/mods/public/simulation/data/effects/statuseffects.json @@ -0,0 +1,8 @@ +{ + "code": "StatusEffects", + "name": "Status Effects", + "description": "Various (timed) effects, including ???.", + "IID": "IID_StatusEffectsReceiver", + "method": "ApplyStatus", + "order": 3 +} Index: binaries/data/mods/public/simulation/helpers/Attacking.js =================================================================== --- binaries/data/mods/public/simulation/helpers/Attacking.js +++ binaries/data/mods/public/simulation/helpers/Attacking.js @@ -1,3 +1,5 @@ +AttackEffects = new AttackEffects(); + /** * Provides attack and damage-related helpers under the Attacking umbrella (to avoid name ambiguity with the component). */ @@ -257,12 +259,12 @@ bonusMultiplier *= !attackData.Bonuses ? 1 : GetAttackBonus(attacker, target, attackType, attackData.Bonuses); let targetState = {}; - for (let effectType of g_EffectTypes) + for (let effectType of AttackEffects.GetTypes()) { if (!attackData[effectType]) continue; - let receiver = g_EffectReceiver[effectType]; + let receiver = AttackEffects.GetReceiver(effectType); let cmpReceiver = Engine.QueryInterface(target, global[receiver.IID]); if (!cmpReceiver) continue; Index: binaries/data/mods/public/simulation/helpers/tests/test_Attacking.js =================================================================== --- binaries/data/mods/public/simulation/helpers/tests/test_Attacking.js +++ binaries/data/mods/public/simulation/helpers/tests/test_Attacking.js @@ -1,3 +1,22 @@ +AttackEffects = class AttackEffects +{ + constructor() {} + GetTypes() { return ["Damage", "Capture"]; } + GetReceiver(effect) + { + if (effect == "Damage") + return { + "IID": "IID_Health", + "method": "TakeDamage" + }; + if (effect == "Capture") + return { + "IID": "IID_Capturable", + "method": "Capture" + }; + } +}; + Engine.LoadHelperScript("Attacking.js"); Engine.LoadComponentScript("interfaces/Attack.js"); Engine.LoadComponentScript("interfaces/Capturable.js");