Index: binaries/data/mods/public/globalscripts/AttackEffects.js =================================================================== --- binaries/data/mods/public/globalscripts/AttackEffects.js +++ binaries/data/mods/public/globalscripts/AttackEffects.js @@ -1,17 +1,74 @@ -// 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", - "sound": "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 = {}; + this.effectSounds = {}; + + for (let filename of Engine.ListDirectoryFiles("simulation/data/attack_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 + }; + this.effectSounds[data.code] = data.sound || ""; + } + + 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); + deepfreeze(this.effectSounds); } -}; + + /** + * @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]; + } + + /** + * @param {string} type - The type of effect to get the receiving sound for. + * @return {string} - The name of the soundgroup to play. + */ + GetSound(type) + { + return "attacked" + (this.effectSounds[type] ? "_" + this.effectSounds[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/AttackDetection.js =================================================================== --- binaries/data/mods/public/simulation/components/AttackDetection.js +++ binaries/data/mods/public/simulation/components/AttackDetection.js @@ -128,10 +128,7 @@ "targetIsDomesticAnimal": targetIsDomesticAnimal }); - let soundGroup = "attacked"; - if (g_EffectReceiver[type] && g_EffectReceiver[type].sound) - soundGroup += '_' + g_EffectReceiver[type].sound; - + let soundGroup = AttackEffects.GetSound(type); if (attackerOwner === 0) soundGroup += "_gaia"; 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("Attacking.js"); Engine.LoadHelperScript("Player.js"); Engine.LoadHelperScript("ValueModification.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("Attacking.js"); Engine.LoadHelperScript("Player.js"); Engine.LoadHelperScript("ValueModification.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("Attacking.js"); Engine.LoadHelperScript("ValueModification.js"); Engine.LoadComponentScript("interfaces/DeathDamage.js"); Index: binaries/data/mods/public/simulation/components/tests/test_Resistance.js =================================================================== --- binaries/data/mods/public/simulation/components/tests/test_Resistance.js +++ binaries/data/mods/public/simulation/components/tests/test_Resistance.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("Attacking.js"); Engine.LoadHelperScript("Player.js"); Engine.LoadHelperScript("ValueModification.js"); Index: binaries/data/mods/public/simulation/data/attack_effects/capture.json =================================================================== --- /dev/null +++ binaries/data/mods/public/simulation/data/attack_effects/capture.json @@ -0,0 +1,9 @@ +{ + "code": "Capture", + "name": "Capture", + "description": "Reduces capture points of a target.", + "IID": "IID_Capturable", + "method": "Capture", + "sound": "capture", + "order": 2 +} Index: binaries/data/mods/public/simulation/data/attack_effects/damage.json =================================================================== --- /dev/null +++ binaries/data/mods/public/simulation/data/attack_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/attack_effects/statuseffects.json =================================================================== --- /dev/null +++ binaries/data/mods/public/simulation/data/attack_effects/statuseffects.json @@ -0,0 +1,8 @@ +{ + "code": "ApplyStatus", + "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 @@ -358,12 +358,12 @@ bonusMultiplier *= !attackData.Bonuses ? 1 : this.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; @@ -447,3 +447,5 @@ var AttackingInstance = new Attacking(); Engine.RegisterGlobal("Attacking", AttackingInstance); + +AttackEffects = new AttackEffects(); 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,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("Attacking.js"); Engine.LoadComponentScript("interfaces/Capturable.js"); Engine.LoadComponentScript("interfaces/Health.js");