Changeset View
Standalone View
binaries/data/mods/public/simulation/components/ProximityDamage.js
- This file was added.
function ProximityDamage() {} | |||||
ProximityDamage.prototype.bonusesSchema = | |||||
"<optional>" + | |||||
"<element name='Bonuses'>" + | |||||
"<zeroOrMore>" + | |||||
"<element>" + | |||||
"<anyName/>" + | |||||
"<interleave>" + | |||||
"<optional>" + | |||||
"<element name='Civ' a:help='If an entity has this civ then the bonus is applied'><text/></element>" + | |||||
"</optional>" + | |||||
"<element name='Classes' a:help='If an entity has all these classes then the bonus is applied'><text/></element>" + | |||||
"<element name='Multiplier' a:help='The attackers attack strength is multiplied by this'><ref name='nonNegativeDecimal'/></element>" + | |||||
"</interleave>" + | |||||
"</element>" + | |||||
"</zeroOrMore>" + | |||||
"</element>" + | |||||
"</optional>"; | |||||
ProximityDamage.prototype.restrictedClassesSchema = | |||||
"<optional>" + | |||||
"<element name='RestrictedClasses' a:help='Space delimited list of classes that cannot be damaged by this entity. If target entity has any of these classes, it cannot be damaged'>" + | |||||
"<attribute name='datatype'>" + | |||||
"<value>tokens</value>" + | |||||
"</attribute>" + | |||||
"<text/>" + | |||||
"</element>" + | |||||
"</optional>"; | |||||
ProximityDamage.prototype.Schema = | |||||
"<a:help>Whether a unit or building inflicts damage to nearby units.</a:help>" + | |||||
"<a:example>" + | |||||
"<Shape>Circular</Shape>" + | |||||
"<Range>10</Range>" + | |||||
"<FriendlyFire>true</FriendlyFire>" + | |||||
"<Hack>0.0</Hack>" + | |||||
"<Pierce>10.0</Pierce>" + | |||||
"<Crush>50.0</Crush>" + | |||||
"</a:example>" + | |||||
"<element name='Shape' a:help='Shape of the proximity damage, can be circular'><text/></element>" + | |||||
"<element name='Range' a:help='Size of the area affected by the proximity damage'><ref name='nonNegativeDecimal'/></element>" + | |||||
"<element name='FriendlyFire' a:help='Whether the proximity damage can hurt non enemy units'><data type='boolean'/></element>" + | |||||
"<element name='OnlyWhenMoving' a:help='Whether the proximity damage is only applied when moving'><data type='boolean'/></element>" + | |||||
DamageTypes.BuildSchema("damage strength") + | |||||
ProximityDamage.prototype.restrictedClassesSchema + | |||||
ProximityDamage.prototype.bonusesSchema; | |||||
ProximityDamage.prototype.Init = function() | |||||
bb: comparing to the attack schema (not necessarily splash) one could consider adding a Delay… | |||||
Done Inline ActionsNot sure whether a MinRange would make sense? Freagarach: Not sure whether a `MinRange` would make sense? | |||||
Done Inline ActionsNevermind, it does (viz. a magic unit with a ring of fire). Freagarach: Nevermind, it does (viz. a magic unit with a ring of fire). | |||||
{ | |||||
this.CheckTimer(); | |||||
}; | |||||
/** | |||||
* Find the entities not to be damaged by this proximity damage | |||||
* @return {Array} classes not to be damaged by this proximity damage | |||||
*/ | |||||
ProximityDamage.prototype.GetRestrictedClasses = function() | |||||
{ | |||||
if (this.template.RestrictedClasses && | |||||
this.template.RestrictedClasses._string) | |||||
Done Inline Actionsperiods bb: periods | |||||
return this.template.RestrictedClasses._string.split(/\s+/); | |||||
return []; | |||||
Done Inline ActionsCould make it an empty function instead. Did you try to save ? Also, what about the deserialize function Stan: Could make it an empty function instead. Did you try to save ? Also, what about the deserialize… | |||||
Done Inline ActionsUhm, I have no clue what this does and why it should or should not be here. I used the DeathDamage component as a template and build this component upon that. And this line was in the DeathDamage component. Freagarach: Uhm, I have no clue what this does and why it should or should not be here. I used the… | |||||
Done Inline ActionsOh I see. Well while saving the game components are serialized and deserialized. The more things you serialize the bigger the savegame becomes, and the longer it takes to do it. Some stuff, especially stuff being inherited from the template does not need to be serialized because it can be recomputed without going out of sync. However stuff like counters and other variables that get changed during the game randomly need to be. In your case I'm not sure but I think the timer id could be serialized. Stan: Oh I see. Well while saving the game components are serialized and deserialized. The more… | |||||
Done Inline ActionsBut the timers of other components are not serialised either. So I'll let this be. Freagarach: But the timers of other components are not serialised either. So I'll let this be. | |||||
Done Inline ActionsBy default everything is serialized :) Stan: By default everything is serialized :) | |||||
Done Inline ActionsAh, okay. My grep returned mostly null ;) Freagarach: Ah, okay. My grep returned mostly null ;) | |||||
Done Inline Actions
I tried, it works fine. What is your suggestion now? Freagarach: > Did you try to save ?
I tried, it works fine. What is your suggestion now? | |||||
}; | |||||
ProximityDamage.prototype.Serialize = null; // We have no dynamic state to save | |||||
/** | |||||
* Work out the damage values with technology effects | |||||
Done Inline ActionsOut of Scope, but at some point we might want to merge this with its duplicates in an attack helper or so bb: Out of Scope, but at some point we might want to merge this with its duplicates in an attack… | |||||
* @return {Array} modifications to the damage types | |||||
*/ | |||||
ProximityDamage.prototype.GetProximityDamageStrengths = function() | |||||
{ | |||||
let applyMods = damageType => | |||||
ApplyValueModificationsToEntity("ProximityDamage/" + damageType, +(this.template[damageType] || 0), this.entity); | |||||
let ret = {}; | |||||
for (let damageType of DamageTypes.GetTypes()) | |||||
ret[damageType] = applyMods(damageType); | |||||
return ret; | |||||
}; | |||||
/** | |||||
* Handle any bonuses with this damage type | |||||
Done Inline Actionsperiods bb: periods | |||||
* @return {Array} bonusses to apply | |||||
*/ | |||||
Done Inline ActionsOne 's' for bonusses. Stan: One 's' for bonusses. | |||||
ProximityDamage.prototype.GetBonusTemplate = function() | |||||
{ | |||||
return this.template.Bonuses || null; | |||||
}; | |||||
ProximityDamage.prototype.CauseProximityDamage = function() | |||||
{ | |||||
// Return when this entity is otherworldly | |||||
let cmpPosition = Engine.QueryInterface(this.entity, IID_Position); | |||||
if (!cmpPosition || !cmpPosition.IsInWorld()) | |||||
return; | |||||
let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); | |||||
let owner = cmpOwnership.GetOwner(); | |||||
Done Inline Actionsperiods bb: periods | |||||
if (owner == INVALID_PLAYER) | |||||
Done Inline ActionsRemove temporary variable, and use it in the object directly. Stan: Remove temporary variable, and use it in the object directly. | |||||
warn("Unit causing proximity damage does not have any owner."); | |||||
Done Inline ActionsMight want to check if the unit has an ownership component before using it. Stan: Might want to check if the unit has an ownership component before using it. | |||||
// Get an array of the players which ought to be damaged | |||||
let cmpDamage = Engine.QueryInterface(SYSTEM_ENTITY, IID_Damage); | |||||
let playersToDamage = cmpDamage.GetPlayersToDamage(owner, this.template.FriendlyFire); | |||||
let radius = ApplyValueModificationsToEntity("ProximityDamage/Range", +this.template.Range, this.entity); | |||||
// Call the Damage-component to find out which entities to damage and damage them | |||||
cmpDamage.CauseProximityDamage({ | |||||
"attacker": this.entity, | |||||
"origin": cmpPosition.GetPosition2D(), | |||||
Done Inline ActionsJSDoc Stan: JSDoc | |||||
"radius": radius, | |||||
"shape": this.template.Shape, | |||||
"strengths": this.GetProximityDamageStrengths(), | |||||
"proximityBonus": this.GetBonusTemplate(), | |||||
"playersToDamage": playersToDamage, | |||||
"type": "Proximity", | |||||
"attackerOwner": owner | |||||
}); | |||||
}; | |||||
Done Inline ActionsComments start with caps :) Stan: Comments start with caps :) | |||||
// Start the damage timer when no timer exists. | |||||
ProximityDamage.prototype.CheckTimer = function() | |||||
Done Inline ActionsOne could also use the delete keyword. Stan: One could also use the delete keyword. | |||||
{ | |||||
// If the unit only causes proximity damage whilst moving, disable timer when not moving | |||||
if (this.template.OnlyWhenMoving == "true") | |||||
{ | |||||
Done Inline ActionsDamage component (no hyphen) bb: `Damage component` (no hyphen) | |||||
let cmpUnitAI = Engine.QueryInterface(this.entity, IID_UnitAI); | |||||
if (cmpUnitAI && !cmpUnitAI.IsInMovingState()) | |||||
{ | |||||
// We don't need a timer, disable if one exists | |||||
Done Inline ActionsComments start with caps :) Stan: Comments start with caps :) | |||||
if (this.proximityDamageTimer) | |||||
{ | |||||
let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); | |||||
cmpTimer.CancelTimer(this.proximityDamageTimer); | |||||
delete this.proximityDamageTimer; | |||||
} | |||||
return; | |||||
} | |||||
Done Inline ActionsJSDoc. Also, are there messages one might want to ignore ? Stan: JSDoc. Also, are there messages one might want to ignore ? | |||||
Done Inline ActionsI'm sorry, what exactly do you mean with JSDoc? Freagarach: I'm sorry, what exactly do you mean with JSDoc?
Regarding the messages to be ignored, I have no… | |||||
Done Inline ActionsJSDoc is the documentation on top of functions So for instance /** * This function does stuff * @param {string} charstring the entry charstring * @param {{ "valuekey": valuetype, "valuekey2": valuetype2}} * @return {boolean} Whether the method worked successfully. */ ProximityDamage.prototype.DoInterestingStuff = function(charstring, obj) { // Do stuff return true; } To figure out the messages one could just add warn(uneval(msg)) and see what's in it, then early return if it's not useful. Stan: JSDoc is the documentation on top of functions So for instance
```lang=js
/**
* This… | |||||
Done Inline ActionsI can't seem to get the proper ignoring of messages working, I'll look into that when I've got more time on my hands. Freagarach: I can't seem to get the proper ignoring of messages working, I'll look into that when I've got… | |||||
Done Inline ActionsSure. It's just to make sure we don't do unnecessary processing too often. Stan: Sure. It's just to make sure we don't do unnecessary processing too often. | |||||
Done Inline ActionsI think there are little messages to be ignored whith this (OnMotionChanged) check ;) Freagarach: I think there are little messages to be ignored whith this (OnMotionChanged) check ;) | |||||
} | |||||
// We need a timer, enable if one doesn't exist | |||||
if (this.proximityDamageTimer) | |||||
return; | |||||
let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); | |||||
this.proximityDamageTimer = cmpTimer.SetInterval(this.entity, IID_ProximityDamage, "CauseProximityDamage", 100, 100, undefined); | |||||
}; | |||||
// If the entity starts or stops moving check the timer | |||||
ProximityDamage.prototype.OnUnitAIStateChanged = function(msg) | |||||
Done Inline ActionsI'm not sure but I think it should be undefined instead of null. Stan: I'm not sure but I think it should be undefined instead of null. | |||||
Done Inline ActionsIt's undefined at ResourceTrickle.js and null at Health.js ;) Freagarach: It's undefined at ResourceTrickle.js and null at Health.js ;) | |||||
Done Inline Actions@elexis would know Stan: @elexis would know | |||||
{ | |||||
this.CheckTimer(); | |||||
}; | |||||
Engine.RegisterComponentType(IID_ProximityDamage, "ProximityDamage", ProximityDamage); | |||||
Done Inline ActionsThe interval should be in the template too bb: The interval should be in the template too | |||||
Done Inline ActionsPass that to the GUI as well? Freagarach: Pass that to the GUI as well? | |||||
Done Inline Actionsobject spaces bb: object spaces | |||||
Done Inline Actionssame bb: same | |||||
Done Inline Actionsperiod bb: period | |||||
Done Inline Actionsperiod bb: period | |||||
Done Inline ActionsTheoretically correct, since the timer component guesses that the timer needs to be removed, however we shouldn't be guessing, just clean the timer here bb: Theoretically correct, since the timer component guesses that the timer needs to be removed… |
comparing to the attack schema (not necessarily splash) one could consider adding a Delay, minRange and/or statusEffect tag