Ticket #1912: ProofOfConcept.patch

File ProofOfConcept.patch, 10.3 KB (added by Leander Hemelhof, 8 years ago)

Proof of concept of the continuous damage system.

  • data/mods/public/gui/credits/texts/programming.json

     
    108108            {"nick": "kingadami", "name": "Adam Winsor"},
    109109            {"nick": "kingbasil", "name": "Giannis Fafalios"},
    110110            {"nick": "lafferjm", "name": "Justin Lafferty"},
     111            {"nick": "LeanderH", "name": "Leander Hemelhof"},
    111112            {"nick": "leper", "name": "Georg Kilzer"},
    112113            {"nick": "LittleDev"},
    113114            {"nick": "livingaftermidnight", "name": "Will Dull"},
  • data/mods/public/simulation/components/Attack.js

     
    8888                "<Crush>0.0</Crush>" +
    8989            "</Splash>" +
    9090        "</Ranged>" +
     91        "<Continuous>" +
     92            "<Hack>0.0</Hack>" +
     93            "<Pierce>0.0</Pierce>" +
     94            "<Crush>10.0</Crush>" +
     95            "<Cycles>12</Cycles>" +
     96            "<CycleDuration>250</CycleDuration>" +
     97        "</Continuous>" +
    9198        "<Charge>" +
    9299            "<Hack>10.0</Hack>" +
    93100            "<Pierce>0.0</Pierce>" +
     
    159166        "</element>" +
    160167    "</optional>" +
    161168    "<optional>" +
     169        "<element name='Continuous'>" +
     170            "<interleave>" +
     171                "<element name='Hack' a:help='Hack damage strength'><ref name='nonNegativeDecimal'/></element>" +
     172                "<element name='Pierce' a:help='Pierce damage strength'><ref name='nonNegativeDecimal'/></element>" +
     173                "<element name='Crush' a:help='Crush damage strength'><ref name='nonNegativeDecimal'/></element>" +
     174                "<element name='Cycles' a:help='Amount of damage cycles'><data type='positiveInteger'/></element>" +
     175                "<element name='CycleDuration' a:help='Time between cycles (in milliseconds)'><data type='nonNegativeInteger'/></element>" +
     176                Attack.prototype.bonusesSchema +
     177            "</interleave>" +
     178        "</element>" +
     179    "</optional>" +
     180    "<optional>" +
    162181        "<element name='Capture'>" +
    163182            "<interleave>" +
    164183                "<element name='Value' a:help='Capture points value'><ref name='nonNegativeDecimal'/></element>" +
     
    588607            "target": target,
    589608            "attacker": this.entity,
    590609            "multiplier": this.GetAttackBonus(type, target),
    591             "type":type
     610            "type": type
    592611        });
     612        if (this.template.Continuous)
     613        {
     614            let strengths = {
     615                "hack": this.template.Continuous.Hack,
     616                "pierce": this.template.Continuous.Pierce,
     617                "crush": this.template.Continuous.Crush
     618            };
     619            this.CauseContinuousDamage({
     620                "strengths": strengths,
     621                "target": ents[i],
     622                "attacker": this.entity,
     623                "multiplier": multiplier,
     624                "type": data.type,
     625                "cycles": this.template.Continuous.Cycles,
     626                "cycleDuration": this.template.Continuous.CycleDuration,
     627            });
     628        }
    593629    }
    594630    // TODO: charge attacks (need to design how they work)
    595631};
     
    677713        data.strengths = this.GetAttackStrengths(data.type);
    678714        // Hit the primary target
    679715        Damage.CauseDamage(data);
     716        if (this.template.Continuous){
     717            let strengths = {
     718                "hack": this.template.Continuous.Hack,
     719                "pierce": this.template.Continuous.Pierce,
     720                "crush": this.template.Continuous.Crush
     721            };
     722            this.CauseContinuousDamage({
     723                "strengths": strengths,
     724                "target": data.target,
     725                "attacker": data.attacker,
     726                "multiplier": data.multiplier,
     727                "type": data.type,
     728                "cycles": this.template.Continuous.Cycles,
     729                "cycleDuration": this.template.Continuous.CycleDuration,
     730            });
     731        }
    680732
    681733        // Remove the projectile
    682734        let cmpProjectileManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_ProjectileManager);
     
    692744        {
    693745            if (this.testCollision(ents[i], data.position, lateness))
    694746            {
     747                let multiplier = this.GetAttackBonus(data.type, ents[i]);
    695748                Damage.CauseDamage({
    696749                        "strengths": this.GetAttackStrengths(data.type),
    697750                        "target": ents[i],
    698751                        "attacker": this.entity,
    699                         "multiplier": this.GetAttackBonus(data.type, ents[i]),
     752                        "multiplier": multiplier,
    700753                        "type": data.type
    701754                });
     755                if (this.template.Continuous)
     756                {
     757                    let strengths = {
     758                        "hack": this.template.Continuous.Hack,
     759                        "pierce": this.template.Continuous.Pierce,
     760                        "crush": this.template.Continuous.Crush
     761                    };
     762                    this.CauseContinuousDamage({
     763                        "strengths": strengths,
     764                        "target": ents[i],
     765                        "attacker": this.entity,
     766                        "multiplier": multiplier,
     767                        "type": data.type,
     768                        "cycles": this.template.Continuous.Cycles,
     769                        "cycleDuration": this.template.Continuous.CycleDuration,
     770                    });
     771                }
    702772                // Remove the projectile
    703773                let cmpProjectileManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_ProjectileManager);
    704774                cmpProjectileManager.RemoveProjectile(data.projectileId);
     
    721791        cmpUnitAI.UpdateRangeQueries();
    722792};
    723793
     794/**
     795 * Causes damage on a given unit every cycle, for a specific number of cycles.
     796 * data.strengths = {'hack':<float>, 'pierce':<float>, 'crush':<float>}
     797 * data.target = <entity id>
     798 * data.attacker = <entity id>
     799 * data.multiplier = <float between 1 and 0>
     800 * data.type = <string>
     801 * data.cycles = <int>
     802 * data.cycleDuration = <int>
     803 */
     804Attack.prototype.CauseContinuousDamage = function(data)
     805{
     806    var cyclesLeft = data.cycles;
     807    var cmpHealth = Engine.QueryInterface(data.target, IID_Health);
     808    if (cyclesLeft <= 0 || (cmpHealth && cmpHealth.GetHitpoints() == 0)) //Check if mistakes have been made or if the target is already dead
     809        return;
     810    Damage.CauseDamage(data);
     811    // Check if all damage cycles have happened, or if the damage already killed the target
     812    if (--cyclesLeft > 0 && cmpHealth && cmpHealth.GetHitpoints() != 0)
     813    {
     814        data.cycles = cyclesLeft;
     815        var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
     816        var tmp = cmpTimer.SetTimeout(this.entity, IID_Attack, "CauseContinuousDamage", +data.cycleDuration, data);
     817    }
     818}
     819
    724820Engine.RegisterComponentType(IID_Attack, "Attack", Attack);
  • data/mods/public/simulation/components/AttackDetection.js

     
    6363    if (cmpTargetOwnership.GetOwner() != cmpPlayer.GetPlayerID())
    6464        return;
    6565    var cmpAttackerOwnership = Engine.QueryInterface(attacker, IID_Ownership);
    66     // Don't register attacks dealt by myself
    67     if (cmpAttackerOwnership.GetOwner() == cmpPlayer.GetPlayerID())
     66    // Don't register attacks dealt by myself and ignore if attacker is already dead
     67    if (!cmpAttackerOwnership || cmpAttackerOwnership.GetOwner() == cmpPlayer.GetPlayerID())
    6868        return;
    6969       
    7070    // Since livestock can be attacked/gathered by other players
  • data/mods/public/simulation/helpers/Damage.js

     
    5252        }
    5353        // Call CauseDamage which reduces the hitpoints, posts network command, plays sounds....
    5454        Damage.CauseDamage({"strengths":data.strengths, "target":entity, "attacker":data.attacker, "multiplier":damageMultiplier, "type":data.type + ".Splash"});
     55        var cmpAttack = Engine.QueryInterface(data.attacker, IID_Attack);
     56        if (cmpAttack && cmpAttack.template.Continuous)
     57        {
     58            var strengths = {
     59                "hack": cmpAttack.template.Continuous.Hack,
     60                "pierce": cmpAttack.template.Continuous.Pierce,
     61                "crush": cmpAttack.template.Continuous.Crush
     62            };
     63            cmpAttack.CauseContinuousDamage({
     64                "strengths": strengths,
     65                "target": entity,
     66                "attacker": data.attacker,
     67                "multiplier": damageMultiplier,
     68                "type": data.type,
     69                "cycles": cmpAttack.template.Continuous.Cycles,
     70                "cycleDuration": cmpAttack.template.Continuous.CycleDuration,
     71            });
     72        }
    5573    }
    5674};
    5775
     
    7492    // Damage the target
    7593    var targetState = cmpDamageReceiver.TakeDamage(data.strengths.hack * data.multiplier, data.strengths.pierce * data.multiplier, data.strengths.crush * data.multiplier);
    7694
    77     var cmpPromotion = Engine.QueryInterface(data.attacker, IID_Promotion);
    78     var cmpLoot = Engine.QueryInterface(data.target, IID_Loot);
    79     if (cmpPromotion && cmpLoot && cmpLoot.GetXp() > 0)
    80         cmpPromotion.IncreaseXp(cmpLoot.GetXp() * -targetState.change / cmpHealth.GetMaxHitpoints());
     95    if (cmpHealth.GetHitpoints() != 0) // No loot needed if attacker is already dead
     96    {
     97        var cmpPromotion = Engine.QueryInterface(data.attacker, IID_Promotion);
     98        var cmpLoot = Engine.QueryInterface(data.target, IID_Loot);
     99        if (cmpPromotion && cmpLoot && cmpLoot.GetXp() > 0)
     100            cmpPromotion.IncreaseXp(cmpLoot.GetXp() * -targetState.change / cmpHealth.GetMaxHitpoints());
     101    }
    81102
    82103    // If the target was killed run some cleanup
    83104    if (targetState.killed)
     
    135156        cmpTargetPlayerStatisticsTracker.LostEntity(targetEntity);
    136157
    137158    // If killer can collect loot, let's try to collect it.
    138     var cmpLooter = Engine.QueryInterface(killerEntity, IID_Looter);
    139     if (cmpLooter)
    140         cmpLooter.Collect(targetEntity);
     159    var cmpHealth = Engine.QueryInterface(killerEntity, IID_Health)
     160    if (cmpHealth && cmpHealth.GetHitpoints() != 0) // Check if killer is still alive, else no loot is needed.
     161    {
     162        var cmpLooter = Engine.QueryInterface(killerEntity, IID_Looter);
     163        if (cmpLooter)
     164            cmpLooter.Collect(targetEntity);
     165    }
    141166};
    142167
    143168Engine.RegisterGlobal("Damage", Damage);
  • data/mods/public/simulation/templates/template_structure_civic_civil_centre.xml

     
    2020      <PrepareTime>1200</PrepareTime>
    2121      <RepeatTime>2000</RepeatTime>
    2222      <Spread>1.5</Spread>
     23      <Splash>
     24        <Shape>Circular</Shape>
     25        <Range>20</Range>
     26        <FriendlyFire>false</FriendlyFire>
     27        <Hack>0.0</Hack>
     28        <Pierce>0.1</Pierce>
     29        <Crush>0.0</Crush>
     30      </Splash>
    2331    </Ranged>
     32    <Continuous>
     33      <Hack>0.0</Hack>
     34      <Pierce>0.0</Pierce>
     35      <Crush>10.0</Crush>
     36      <Cycles>12</Cycles>
     37      <CycleDuration>250</CycleDuration>
     38    </Continuous> 
    2439  </Attack>
    2540  <BuildingAI>
    2641    <DefaultArrowCount>3</DefaultArrowCount>