mirror of
https://gitea.wildfiregames.com/0ad/0ad.git
synced 2026-07-28 12:51:34 +00:00
Get attack effects from JSON.
Reads attack effects from JSON files to allow easier introduction (one still needs to modify other components). Differential revision: D2661 Comments by: @Angen, @bb, @Stan, @wraitii This was SVN commit r24500.
This commit is contained in:
Executable → Regular
+60
-16
@@ -1,17 +1,61 @@
|
|||||||
// TODO: could be worth putting this in json files someday
|
/**
|
||||||
const g_EffectTypes = ["Damage", "Capture", "ApplyStatus"];
|
* This class provides a cache for accessing attack effects stored in JSON files.
|
||||||
const g_EffectReceiver = {
|
*/
|
||||||
"Damage": {
|
class AttackEffects
|
||||||
"IID": "IID_Health",
|
{
|
||||||
"method": "TakeDamage"
|
constructor()
|
||||||
},
|
{
|
||||||
"Capture": {
|
let effectsDataObj = {};
|
||||||
"IID": "IID_Capturable",
|
this.effectReceivers = [];
|
||||||
"method": "Capture",
|
this.effectSounds = {};
|
||||||
"sound": "capture"
|
|
||||||
},
|
for (let filename of Engine.ListDirectoryFiles("simulation/data/attack_effects", "*.json", false))
|
||||||
"ApplyStatus": {
|
{
|
||||||
"IID": "IID_StatusEffectsReceiver",
|
let data = Engine.ReadJSONFile(filename);
|
||||||
"method": "ApplyStatus"
|
if (!data)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (effectsDataObj[data.code])
|
||||||
|
{
|
||||||
|
error("Encountered two effect types with the code " + data.name + ".");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
effectsDataObj[data.code] = data;
|
||||||
|
|
||||||
|
this.effectReceivers.push({
|
||||||
|
"type": 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(
|
||||||
|
effectsDataObj[a.type],
|
||||||
|
effectsDataObj[b.type]
|
||||||
|
);
|
||||||
|
this.effectReceivers.sort(effSort);
|
||||||
|
|
||||||
|
deepfreeze(this.effectReceivers);
|
||||||
|
deepfreeze(this.effectSounds);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
/**
|
||||||
|
* @return {Object[]} - The effects possible with their data.
|
||||||
|
*/
|
||||||
|
Receivers()
|
||||||
|
{
|
||||||
|
return this.effectReceivers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 this.effectSounds[type] || "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
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_UNEVAL_EQUALS(attackEffects.Receivers(), [{
|
||||||
|
"type": "b",
|
||||||
|
"IID": "IID_B",
|
||||||
|
"method": "doB"
|
||||||
|
}, {
|
||||||
|
"type": "a",
|
||||||
|
"IID": "IID_A",
|
||||||
|
"method": "doA"
|
||||||
|
}]);
|
||||||
@@ -540,6 +540,19 @@
|
|||||||
],
|
],
|
||||||
"context": "status effect"
|
"context": "status effect"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"extractor": "json",
|
||||||
|
"filemasks": [
|
||||||
|
"simulation/data/attack_effects/*.json"
|
||||||
|
],
|
||||||
|
"options": {
|
||||||
|
"keywords": [
|
||||||
|
"name",
|
||||||
|
"description"
|
||||||
|
],
|
||||||
|
"context": "effect caused by an attack"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -128,10 +128,7 @@ AttackDetection.prototype.AttackAlert = function(target, attacker, type, attacke
|
|||||||
"targetIsDomesticAnimal": targetIsDomesticAnimal
|
"targetIsDomesticAnimal": targetIsDomesticAnimal
|
||||||
});
|
});
|
||||||
|
|
||||||
let soundGroup = "attacked";
|
let soundGroup = g_AttackEffects.GetSound(type);
|
||||||
if (g_EffectReceiver[type] && g_EffectReceiver[type].sound)
|
|
||||||
soundGroup += '_' + g_EffectReceiver[type].sound;
|
|
||||||
|
|
||||||
if (attackerOwner === 0)
|
if (attackerOwner === 0)
|
||||||
soundGroup += "_gaia";
|
soundGroup += "_gaia";
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,26 @@
|
|||||||
|
AttackEffects = class AttackEffects
|
||||||
|
{
|
||||||
|
constructor() {}
|
||||||
|
Receivers()
|
||||||
|
{
|
||||||
|
return [{
|
||||||
|
"type": "Damage",
|
||||||
|
"IID": "IID_Health",
|
||||||
|
"method": "TakeDamage"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Capture",
|
||||||
|
"IID": "IID_Capturable",
|
||||||
|
"method": "Capture"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ApplyStatus",
|
||||||
|
"IID": "IID_StatusEffectsReceiver",
|
||||||
|
"method": "ApplyStatus"
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Engine.LoadHelperScript("Attacking.js");
|
Engine.LoadHelperScript("Attacking.js");
|
||||||
Engine.LoadHelperScript("Player.js");
|
Engine.LoadHelperScript("Player.js");
|
||||||
Engine.LoadHelperScript("ValueModification.js");
|
Engine.LoadHelperScript("ValueModification.js");
|
||||||
|
|||||||
@@ -1,3 +1,16 @@
|
|||||||
|
AttackEffects = class AttackEffects
|
||||||
|
{
|
||||||
|
constructor() {}
|
||||||
|
Receivers()
|
||||||
|
{
|
||||||
|
return [{
|
||||||
|
"type": "Damage",
|
||||||
|
"IID": "IID_Health",
|
||||||
|
"method": "TakeDamage"
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Engine.LoadHelperScript("Attacking.js");
|
Engine.LoadHelperScript("Attacking.js");
|
||||||
Engine.LoadHelperScript("Player.js");
|
Engine.LoadHelperScript("Player.js");
|
||||||
Engine.LoadHelperScript("Position.js");
|
Engine.LoadHelperScript("Position.js");
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
AttackEffects = class AttackEffects
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
Engine.LoadHelperScript("Attacking.js");
|
Engine.LoadHelperScript("Attacking.js");
|
||||||
Engine.LoadHelperScript("ValueModification.js");
|
Engine.LoadHelperScript("ValueModification.js");
|
||||||
Engine.LoadComponentScript("interfaces/DeathDamage.js");
|
Engine.LoadComponentScript("interfaces/DeathDamage.js");
|
||||||
|
|||||||
@@ -1,3 +1,26 @@
|
|||||||
|
AttackEffects = class AttackEffects
|
||||||
|
{
|
||||||
|
constructor() {}
|
||||||
|
Receivers()
|
||||||
|
{
|
||||||
|
return [{
|
||||||
|
"type": "Damage",
|
||||||
|
"IID": "IID_Health",
|
||||||
|
"method": "TakeDamage"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Capture",
|
||||||
|
"IID": "IID_Capturable",
|
||||||
|
"method": "Capture"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ApplyStatus",
|
||||||
|
"IID": "IID_StatusEffectsReceiver",
|
||||||
|
"method": "ApplyStatus"
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Engine.LoadHelperScript("Attacking.js");
|
Engine.LoadHelperScript("Attacking.js");
|
||||||
Engine.LoadHelperScript("Player.js");
|
Engine.LoadHelperScript("Player.js");
|
||||||
Engine.LoadHelperScript("ValueModification.js");
|
Engine.LoadHelperScript("ValueModification.js");
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"code": "ApplyStatus",
|
||||||
|
"description": "Various (timed) effects.",
|
||||||
|
"IID": "IID_StatusEffectsReceiver",
|
||||||
|
"method": "ApplyStatus",
|
||||||
|
"name": "Apply Status",
|
||||||
|
"order": 3,
|
||||||
|
"sound": "attacked"
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"code": "Capture",
|
||||||
|
"description": "Reduces capture points of a target.",
|
||||||
|
"IID": "IID_Capturable",
|
||||||
|
"method": "Capture",
|
||||||
|
"name": "Capture",
|
||||||
|
"order": 2,
|
||||||
|
"sound": "attacked_capture"
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"code": "Damage",
|
||||||
|
"description": "Reduces the health of a target.",
|
||||||
|
"IID": "IID_Health",
|
||||||
|
"method": "TakeDamage",
|
||||||
|
"name": "Damage",
|
||||||
|
"order": 1,
|
||||||
|
"sound": "attacked"
|
||||||
|
}
|
||||||
@@ -307,17 +307,16 @@ Attacking.prototype.HandleAttackEffects = function(target, attackType, attackDat
|
|||||||
bonusMultiplier *= !attackData.Bonuses ? 1 : this.GetAttackBonus(attacker, target, attackType, attackData.Bonuses);
|
bonusMultiplier *= !attackData.Bonuses ? 1 : this.GetAttackBonus(attacker, target, attackType, attackData.Bonuses);
|
||||||
|
|
||||||
let targetState = {};
|
let targetState = {};
|
||||||
for (let effectType of g_EffectTypes)
|
for (let receiver of g_AttackEffects.Receivers())
|
||||||
{
|
{
|
||||||
if (!attackData[effectType])
|
if (!attackData[receiver.type])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
let receiver = g_EffectReceiver[effectType];
|
|
||||||
let cmpReceiver = Engine.QueryInterface(target, global[receiver.IID]);
|
let cmpReceiver = Engine.QueryInterface(target, global[receiver.IID]);
|
||||||
if (!cmpReceiver)
|
if (!cmpReceiver)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Object.assign(targetState, cmpReceiver[receiver.method](this.GetTotalAttackEffects(target, attackData, effectType, bonusMultiplier, cmpResistance), attacker, attackerOwner));
|
Object.assign(targetState, cmpReceiver[receiver.method](this.GetTotalAttackEffects(target, attackData, receiver.type, bonusMultiplier, cmpResistance), attacker, attackerOwner));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Object.keys(targetState).length)
|
if (!Object.keys(targetState).length)
|
||||||
@@ -378,3 +377,5 @@ Attacking.prototype.GetAttackBonus = function(source, target, type, template)
|
|||||||
|
|
||||||
var AttackingInstance = new Attacking();
|
var AttackingInstance = new Attacking();
|
||||||
Engine.RegisterGlobal("Attacking", AttackingInstance);
|
Engine.RegisterGlobal("Attacking", AttackingInstance);
|
||||||
|
|
||||||
|
Engine.RegisterGlobal("g_AttackEffects", new AttackEffects());
|
||||||
|
|||||||
@@ -1,3 +1,26 @@
|
|||||||
|
AttackEffects = class AttackEffects
|
||||||
|
{
|
||||||
|
constructor() {}
|
||||||
|
Receivers()
|
||||||
|
{
|
||||||
|
return [{
|
||||||
|
"type": "Damage",
|
||||||
|
"IID": "IID_Health",
|
||||||
|
"method": "TakeDamage"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Capture",
|
||||||
|
"IID": "IID_Capturable",
|
||||||
|
"method": "Capture"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ApplyStatus",
|
||||||
|
"IID": "IID_StatusEffectsReceiver",
|
||||||
|
"method": "ApplyStatus"
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Engine.LoadHelperScript("Attacking.js");
|
Engine.LoadHelperScript("Attacking.js");
|
||||||
Engine.LoadComponentScript("interfaces/Capturable.js");
|
Engine.LoadComponentScript("interfaces/Capturable.js");
|
||||||
Engine.LoadComponentScript("interfaces/Health.js");
|
Engine.LoadComponentScript("interfaces/Health.js");
|
||||||
|
|||||||
Reference in New Issue
Block a user