Line data Source code
1 : function DelayedDamage() {} 2 : 3 1 : DelayedDamage.prototype.Schema = 4 : "<a:component type='system'/><empty/>"; 5 : 6 1 : DelayedDamage.prototype.Init = function() 7 : { 8 : }; 9 : 10 : /** 11 : * When missiles miss their target, other units in MISSILE_HIT_RADIUS range are considered. 12 : * Large missiles should probably implement splash damage anyways, 13 : * so keep this value low for performance. 14 : */ 15 1 : DelayedDamage.prototype.MISSILE_HIT_RADIUS = 2; 16 : 17 : /** 18 : * Handles hit logic (after a delay has passed). 19 : * @param {Object} data - The data sent by the caller. 20 : * @param {string} data.type - The type of damage. 21 : * @param {Object} data.attackData - Data of the form { 'effectType': { ...opaque effect data... }, 'Bonuses': {...} }. 22 : * @param {number} data.target - The entity id of the target. 23 : * @param {number} data.attacker - The entity id of the attacker. 24 : * @param {number} data.attackerOwner - The player id of the owner of the attacker. 25 : * @param {Vector3D} data.position - The expected position of the target. 26 : * @param {number} data.projectileId - The id of the projectile. 27 : * @param {Vector3D} data.direction - The unit vector defining the direction. 28 : * @param {string} data.attackImpactSound - The name of the sound emited on impact. 29 : * @param {boolean} data.friendlyFire - A flag indicating whether allied entities can also be damaged. 30 : * ***When splash damage*** 31 : * @param {boolean} data.splash.friendlyFire - A flag indicating if allied entities are also damaged. 32 : * @param {number} data.splash.radius - The radius of the splash damage. 33 : * @param {string} data.splash.shape - The shape of the splash range. 34 : * @param {Object} data.splash.attackData - same as attackData, for splash. 35 : */ 36 1 : DelayedDamage.prototype.Hit = function(data, lateness) 37 : { 38 11 : if (!data.position) 39 0 : return; 40 : 41 11 : if (data.attackImpactSound) 42 0 : Engine.QueryInterface(SYSTEM_ENTITY, IID_SoundManager).PlaySoundGroupAtPosition(data.attackImpactSound, data.position); 43 : 44 11 : if (data.splash) 45 7 : AttackHelper.CauseDamageOverArea({ 46 : "type": data.type, 47 : "attackData": data.splash.attackData, 48 : "attacker": data.attacker, 49 : "attackerOwner": data.attackerOwner, 50 : "origin": Vector2D.from3D(data.position), 51 : "radius": data.splash.radius, 52 : "shape": data.splash.shape, 53 : "direction": data.direction, 54 : "friendlyFire": data.splash.friendlyFire 55 : }); 56 : 57 : // Since we can't damage mirages, replace a miraged target by the real target. 58 11 : let target = data.target; 59 11 : let cmpMirage = Engine.QueryInterface(data.target, IID_Mirage); 60 11 : if (cmpMirage) 61 1 : target = cmpMirage.GetParent(); 62 : 63 11 : if (!data.projectileId) 64 : { 65 0 : AttackHelper.HandleAttackEffects(target, data); 66 0 : return; 67 : } 68 : 69 11 : let cmpProjectileManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_ProjectileManager); 70 : 71 : // Deal direct damage if we hit the main target 72 : // and we could handle the attack. 73 11 : if (PositionHelper.TestCollision(target, data.position, lateness) && 74 : AttackHelper.HandleAttackEffects(target, data)) 75 : { 76 3 : cmpProjectileManager.RemoveProjectile(data.projectileId); 77 3 : return; 78 : } 79 : 80 : // If we didn't hit the main target look for nearby units. 81 8 : let ents = PositionHelper.EntitiesNearPoint(Vector2D.from3D(data.position), this.MISSILE_HIT_RADIUS, 82 : AttackHelper.GetPlayersToDamage(data.attackerOwner, data.friendlyFire)); 83 : 84 8 : for (let ent of ents) 85 : { 86 8 : if (!PositionHelper.TestCollision(ent, data.position, lateness) || 87 : !AttackHelper.HandleAttackEffects(ent, data)) 88 0 : continue; 89 : 90 8 : cmpProjectileManager.RemoveProjectile(data.projectileId); 91 8 : break; 92 : } 93 : }; 94 : 95 1 : Engine.RegisterSystemComponentType(IID_DelayedDamage, "DelayedDamage", DelayedDamage);