mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-06-20 23:33:59 -07: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:
parent
2847eb2a20
commit
7f7a3edfae
13 changed files with 223 additions and 24 deletions
76
binaries/data/mods/public/globalscripts/AttackEffects.js
Executable file → Normal file
76
binaries/data/mods/public/globalscripts/AttackEffects.js
Executable file → Normal file
|
|
@ -1,17 +1,61 @@
|
|||
// 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 effectsDataObj = {};
|
||||
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 (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"
|
||||
}
|
||||
},
|
||||
{
|
||||
"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
|
||||
});
|
||||
|
||||
let soundGroup = "attacked";
|
||||
if (g_EffectReceiver[type] && g_EffectReceiver[type].sound)
|
||||
soundGroup += '_' + g_EffectReceiver[type].sound;
|
||||
|
||||
let soundGroup = g_AttackEffects.GetSound(type);
|
||||
if (attackerOwner === 0)
|
||||
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("Player.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("Player.js");
|
||||
Engine.LoadHelperScript("Position.js");
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
AttackEffects = class AttackEffects
|
||||
{
|
||||
};
|
||||
|
||||
Engine.LoadHelperScript("Attacking.js");
|
||||
Engine.LoadHelperScript("ValueModification.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("Player.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);
|
||||
|
||||
let targetState = {};
|
||||
for (let effectType of g_EffectTypes)
|
||||
for (let receiver of g_AttackEffects.Receivers())
|
||||
{
|
||||
if (!attackData[effectType])
|
||||
if (!attackData[receiver.type])
|
||||
continue;
|
||||
|
||||
let receiver = g_EffectReceiver[effectType];
|
||||
let cmpReceiver = Engine.QueryInterface(target, global[receiver.IID]);
|
||||
if (!cmpReceiver)
|
||||
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)
|
||||
|
|
@ -378,3 +377,5 @@ Attacking.prototype.GetAttackBonus = function(source, target, type, template)
|
|||
|
||||
var AttackingInstance = new Attacking();
|
||||
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.LoadComponentScript("interfaces/Capturable.js");
|
||||
Engine.LoadComponentScript("interfaces/Health.js");
|
||||
|
|
|
|||
Loading…
Reference in a new issue