An analysis of the game lua code

HarimauHarimau Join Date: 2007-12-24 Member: 63250Members
edited January 2011 in NS2 General Discussion
<div class="IPBDescription">in relation to *Marine vs Skulk balance*</div>I'll add anything else to this as I figure it out. It's a work in progress, and I'll probably make changes as the game itself changes.
Some relevant info out of the code (skip to the bottom of it for the actual analysis):
<!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1-->//Rifle.lua:
Rifle.kClipSize = kRifleClipSize
Rifle.kRange = 250
Rifle.kFireDelay = kRifleFireDelay
Rifle.kSpread = ClipWeapon.kCone4Degrees    // From NS1
Rifle.kDamage = kRifleDamage
Rifle.kButtDelay = kRifleMeleeFireDelay
Rifle.kButtDamage = kRifleMeleeDamage
Rifle.kButtRange = 1.5

//Pistol.lua:
Pistol.kClipSize = 10
Pistol.kDamage = kPistolDamage
Pistol.kAltDamage = kPistolAltDamage
Pistol.kRange = 200
Pistol.kFireDelay = kPistolFireDelay
Pistol.kAltFireDelay = kPistolAltFireDelay
Pistol.kSpread = ClipWeapon.kCone1Degrees
Pistol.kAltSpread = ClipWeapon.kCone0Degrees    // From NS1
Biteleap.lua:
BiteLeap.kDamage = kBiteDamage
BiteLeap.kBiteDelay = kBiteFireDelay
BiteLeap.kRange = 1.5       // From NS1

//Shotgun.lua:
Shotgun.kClipSize = kShotgunClipSize
// Do max damage when within max damage range
Shotgun.kMaxDamage = kShotgunMaxDamage
Shotgun.kMinDamage = kShotgunMinDamage
Shotgun.kPrimaryRange = kShotgunMinDamageRange
Shotgun.kPrimaryMaxDamageRange = kShotgunMaxDamageRange
Shotgun.kSecondaryRange = 10
Shotgun.kFireDelay = kShotgunFireDelay
Shotgun.kSecondaryFireDelay = 0.5
function Shotgun:GetSpread()
    // NS1 was 20 degrees for half the shots and 20 degrees plus 7 degrees for half the shots
    if NetworkRandom(string.format("%s:GetSpread():", self:GetClassName())) < .5 then
        return ClipWeapon.kCone20Degrees    
    else
        return ClipWeapon.kCone20Degrees + ClipWeapon.kCone7Degrees
    end
    
end

//Balance.lua:
kShotgunMaxDamage = 20    
kShotgunMinDamage = 14    
kShotgunDamageType = kDamageType.Normal    
kShotgunFireDelay = 0.9    
kShotgunClipSize = 8    
kShotgunBulletsPerShot = 10    
kShotgunMinDamageRange = 20    
kShotgunMaxDamageRange = 2    
kShotgunSpreadDegrees = 20    
kRifleDamage = 10    
kRifleDamageType = kDamageType.Normal    
kRifleFireDelay = 0.0555    
kRifleClipSize = 50    
kRifleMeleeDamage = 35    
kRifleMeleeDamageType = kDamageType.Normal    
kRifleMeleeFireDelay = 0.7    
kPistolDamage = 20    
kPistolDamageType = kDamageType.Heavy    
kPistolFireDelay = 0.1    
kPistolClipSize = 10    
kPistolAltDamage = 30    
kPistolAltFireDelay = 0.2
kBiteDamage = 75    
kBiteDamageType = kDamageType.Normal    
kBiteFireDelay = 0.45    
kBiteEnergyCost = 3    
kParasiteDamage = 10    
kParasiteDamageType = kDamageType.Normal    
kParasiteFireDelay = 0.5    
kParasiteEnergyCost = 30    
kWeapons1DamageScalar = 1.1    
kWeapons2DamageScalar = 1.2    
kWeapons3DamageScalar = 1.3    
kPiercingDamageScalar = 1.4
kMelee1DamageScalar = 1.1    
kMelee2DamageScalar = 1.2    
kMelee3DamageScalar = 1.3

//LiveScriptActor_Server.lua:
function LiveScriptActor:GetHealthPerArmor(damageType)
    local healthPerArmor = kHealthPointsPerArmor
    if damageType == kDamageType.Light then
        healthPerArmor = kHealthPointsPerArmorLight
    elseif damageType == kDamageType.Heavy then
        healthPerArmor = kHealthPointsPerArmorHeavy
    end
    return healthPerArmor
end
// Calculate damage absorbed by armor according to damage type
local absorbPercentage = self:GetArmorAbsorbPercentage(damageType)
// Each point of armor blocks a point of health but is only destroyed at half that rate (like NS1)
healthPointsBlocked = math.min(self.armor, absorbPercentage * damage )
armorPointsUsed = healthPointsBlocked / self:GetHealthPerArmor(damageType)
// Anything left over comes off of health
healthPointsUsed = damage - healthPointsBlocked  

//NS2Gamerules.lua:
return damage * damageScalar

//Balancehealth.lua
kMarineHealth = 100    kMarineArmor = 30    kMarinePointValue = 5
kSkulkHealth = 70    kSkulkArmor = 10    kSkulkPointValue = 5
kArmorPerUpgradeLevel = 20
kBaseArmorAbsorption = 0.7    
kHealthPointsPerArmor = 2
kHealthPointsPerArmorLight = 4        
kHealthPointsPerArmorHeavy = 1        
kPuncturePlayerDamageScalar = 1.3<!--c2--></div><!--ec2-->
<u>Notes</u>
-For determining circles of spread, I've used r = s*tan(angle of spread) (or y = x*tan(theta), or opposite = adjacent*tangent).
-Neglected any innate healing for simplicity's sake.
-Assumed that attack-rates are as they're advertised (wherever I've bothered to make a time-based analysis).
-Haven't discussed the alien side much, because although alien gameplay is more interesting than marine's, marine game mechanics are more interesting than alien's.

<u>The Rifle</u>
It *should* take 2.775 seconds to empty 50 rounds with the rifle.
The firing cone is 4 degrees from the centre. This means that at a distance of 7 game units (2.52m) (the distance a skulk can "walk" in 1 second), there is a circle of radius 0.49 game units (17.6cm) (7% of distance), or diameter 0.98 game units (35.2cm) (14% of distance), for the firing cone.

<u>The Pistol</u>
At the fastest rate of fire (if you can click that fast), it should take 1 second to fire 10 pistol rounds, for a total damage of 200.
The firing cone is 1 degree from the centre.
For alt-fire pistol, as above, it should take two seconds to fire 10 pistol rounds, for a total damage of 300.
The firing cone is 0 degrees from the centre (perfectly precise).

<u>Reload Times</u>
I can't find the reload times in number form, it's probably directly as a result of the length of the animation.

<u>Damage Upgrades</u>
Weapon1/2/3 or Melee1/2/3 upgrades just add 10% each: damage multiplied by a scalar of 1.1, 1.2, 1.3 respectively. (Actual damage done depends on the armour system and the damage types.)
There is also a Piercing upgrade for the lerk which adds 40% (damagescalar of 1.4).

<u>Bite vs Marine</u>
<b>Currently, a perfect vanilla skulk can bite a vanilla marine to death in 0.45-0.9 seconds</b> (depending on whether damage is applied before or after the delay, and assuming the animation length isn't counted):
Bite one: time=0 or 0.45; damage = 75 -> healthpointsblocked = 30 (min(30, 52.5)) -> armorpointsused = 15 (<b>15</b> remaining) -> healthpointsused = 45 (<b>55</b> remaining)
Bite two: time=0.45 or 0.9; damage = 75 -> healthpointsblocked = 15 (min(15,52.5)) -> armorpointsused = 7.5 (<b>7.5</b> remaining) -> healthpointsused = 60 (<b>0</b> remaining)

<b>I don't think armour is working as it should be.</b>
As it is: for one thing, armour never reaches zero; for another, this leads to bite damage being too high and skulks able to kill marines in only two bites.
I think the <b>self.armor</b> element should be multiplied by <b>HealthPerArmor</b>.

For example, that line could read:
<!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1-->healthPointsBlocked = math.min(self:GetHealthPerArmor(damageType) * self.armor, absorbPercentage * damage )<!--c2--></div><!--ec2-->
or if you first specified,
<!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1-->local HealthPerArmor = self:GetHealthPerArmor(damageType)<!--c2--></div><!--ec2-->
then,
<!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1-->healthPointsBlocked = math.min(HealthPerArmor * self.armor, absorbPercentage * damage )
armorPointsUsed = healthPointsBlocked / HealthPerArmor<!--c2--></div><!--ec2-->

Then:
Bite one: damage = 75 -> healthpointsblocked = 52.5 (min(60,52.5)) -> armorpointsused = 26.25 (<b>3.75</b> remaining) -> healthpointsused = 22.5 (<b>77.5</b> remaining)
Bite two: damage = 75 -> healthpointsblocked = 7 (min(7,52.5) -> armorpointsused = 3.75 (<b>0</b> remaining) -> healthpointsused = 68 (<b>9.5</b> remaining)
Bite three: damage = 75 -> healthpointsblocked = 0 (min(0,52.5) -> armorpointsused = 0 (<b>0</b> remaining) -> healthpointsused = 75 (<b>0</b> remaining)

Or, with parasite first:
Parasite: damage = 10 -> healthpointsblocked = 7 (min(60,7)) -> armorpointsused = 3.75 (<b>26.25</b> remaining) -> healthpointsused = 3 (<b>97</b> remaining)
Bite one: damage = 75 -> healthpointsblocked = 52.5 (min(52.5.52.5)) -> armorpointsused = 26.25 (<b>0</b> remaining) -> healthpointsused = 22.5 (<b>74.5</b> remaining)
Bite two: damage = 75 -> healthpointsblocked = 0 (min(0,52.5)) -> armorpointsused = 0 (<b>0</b> remaining) -> healthpointsused = 75 (<b>0</b> remaining)

This option seems much better, and more in line with what I remember from NS1. Parasite(3dmg)-bite-bite? Armour consumed first?

<u>Edit1</u>:
<u>Actual Fire-rate</u><!--quoteo(post=1822826:date=Jan 9 2011, 01:37 PM:name=Harimau)--><div class='quotetop'>QUOTE (Harimau @ Jan 9 2011, 01:37 PM) <a href="index.php?act=findpost&pid=1822826"><{POST_SNAPBACK}></a></div><div class='quotemain'><!--quotec-->Also, this: <!--quoteo(post=1822787:date=Jan 9 2011, 08:45 AM:name=FocusedWolf)--><div class='quotetop'>QUOTE (FocusedWolf @ Jan 9 2011, 08:45 AM) <a href="index.php?act=findpost&pid=1822787"><{POST_SNAPBACK}></a></div><div class='quotemain'><!--quotec-->Hmm i found a small discrepancy between ns1 and ns2. Guess the "numbers" aren't always the same huh :P

NS2:

1. 3.8 seconds to fire 50 rounds.

NS1 (not watching the weapon animation, but instead watching when the ammo count changes):

1. 3.3 seconds to fire 50 rounds.<!--QuoteEnd--></div><!--QuoteEEnd-->
doesn't match the game code (0.0555 second delay per shot - 2.775 seconds for 50 shots). Or each shot itself has an 'animation time' unrelated to the delay. Judging from your measurement, each shot must have an extra 0.02 second 'animation'. If you want to get this to match up with NS (3.3 seconds), then make it a 0.01 second 'animation'.
<!--QuoteEnd--></div><!--QuoteEEnd-->
<u>Edit5</u>:
<u>Actual Fire-rate, continued</u><!--quoteo(post=1822830:date=Jan 9 2011, 02:08 PM:name=FocusedWolf)--><div class='quotetop'>QUOTE (FocusedWolf @ Jan 9 2011, 02:08 PM) <a href="index.php?act=findpost&pid=1822830"><{POST_SNAPBACK}></a></div><div class='quotemain'><!--quotec-->Ok the times changed in a lan (still over the expected time of 2.775 seconds, Harimau):

NS2 (lan):

1. 3.5 seconds to fire 50 rounds. (little faster then my previous time on a public server of 3.8 seconds)
2. 3.1 seconds to reload. (essentially what i got in my first recording, 3.2, on a public server, so no surprise there... its just one animation playing)

NS2 (laggiest server i could find)

1. <b>4.3 - 5.1</b> seconds to fire 50 rounds... <b>mad fluctuations!!!</b>)
2. 3.2 seconds to reload (just like before, so this value isn't affected by lag so much)

Conclusion: The rate of fire (and therefore hit/fire detection) is not consistent, and is heavily influenced by the servers capabilities/lag. Therefore the dev's attempts to enforce a fixed rate of fire, to balance the game, is not possible currently. It's safe to assume this affects every weapon/offensive-capability in the game.<!--QuoteEnd--></div><!--QuoteEEnd-->
<u>Edit2</u>:
<u>Pistol vs skulk</u>:
Taking into account that HealthPerArmor for pistol is 1 (Heavy damage-type), ironically pistol damage on skulks actually works properly:

Default fire mode:
shot 1: damage = 20 -> healthpointsblocked = 10 (min(10,14)) -> armorpointsused = 10 (<b>0</b> remaining) -> healthpointsused = 10 (<b>60</b> remaining)
shot 2: damage = 20 -> healthpointsblocked = 0 (min(0,14)) -> armorpointused = 0 (<b>0</b> remaining) -> healthpointsused = 20 (<b>40</b> remaining)
shot 3: damage = 20 -> healthpointsblocked = 0 (min(0,14)) -> armorpointused = 0 (<b>0</b> remaining) -> healthpointsused = 20 (<b>20</b> remaining)
shot 4: damage = 20 -> healthpointsblocked = 0 (min(0,14)) -> armorpointused = 0 (<b>0</b> remaining) -> healthpointsused = 20 (<b>0</b> remaining)
Ostensibly can be done in 0.4 seconds: faster than a skulk can bite (0.45 seconds).

Alternate fire mode:
shot 1: damage = 30 -> healthpointsblocked = 10 (min(10,21)) -> armorpointsused = 10 (<b>0</b> remaining) -> healthpointsused = 20 (<b>50</b> remaining)
shot 2: damage = 30 -> healthpointsblocked = 0 (min(0,21)) -> armorpointsused = 0 (<b>0</b> remaining) -> healthpointsused = 30 (<b>20</b> remaining)
shot 3: damage = 30 -> healthpointsblocked = 0 (min(0,21)) -> armorpointsused = 0 (<b>0</b> remaining) -> healthpointsused = 30 (<b>0</b> remaining)
Ostensibly can be done in 0.6 seconds.

I think that the best option for a marine currently, considering the uselessness of the rifle, is to just take skulks out with the pistol: 3 well-placed shots with alt-fire mode. Hell, don't marines run out of rifle ammunition then have to kill skulks with the pistol anyway?

<u>Edit3</u>:
<u>Rifle vs Skulk</u> (did it with excel as it's 10x as fast):
<img src="http://img233.imageshack.us/img233/6711/ns2riflevsskulk.png" border="0" class="linked-image" />

Interestingly, it takes 9 shots to kill a skulk either way. Too bad 45 of your shots miss... :P

<u>Edit4</u>:
<u>Rifle vs Fade</u> (not going to embed, too large). I used the same spreadsheet, just changed armour to 100 and hp to 300, and pulled the attack no. down to 50.
Takes an <b>entire magazine</b> (I wonder if this was intentional) - 50 shots, to kill a fade - <i>every</i> shot hitting the fade - this is assuming no upgrades to either fade or marine. This is the case with both the current armour system, and the corrected armour system.
With Weapon3 (13 damage per shot) and no upgrades to fade, it takes 39 shots regardless of the armour system.
Long story short, don't fight a fade with a rifle by yourself.

<u>Edit6</u>:
<u>The Shotgun</u>
The shotgun is strange in that it seems like it was almost designed to miss, but it was also clearly designed for very, very close combat situations.

Shotgun works by firing 10 "bullets" per shot.
Each "bullet" has damage drop-off based on its distance. '20' between 0 and 2 game units (0.72 metres), and '14' above 20 game units (7.2 metres); scaling (I assume) in between.
This explains why you can one-shot a skulk at a close enough distance. Ostensibly only 5 (half) of your "bullets" have to hit within the max damage range; 7 of your "bullets" have to hit above the minimum damage range. See:
<u>Shotgun vs Skulk</u>
<img src="http://img155.imageshack.us/img155/4138/ns2shotgunvsskulk.png" border="0" class="linked-image" />

Again, too much to embed, so,
<u>Shotgun vs Fade</u>:
It takes 25 pellets (~3 shots) to kill a fade at maximum damage range, and 36 pellets (~4 shots) to kill a fade at minimum damage range, but at that range most of your pellets will miss anyway. (Funnily enough, that's 5^2 and 6^2. I wonder if that was intentional.)

<u>Shotgun spread</u>
Spread is 20 degrees for half the bullets, and 27 degrees for the other half.

For the first half, that's a 36%-of-distance radial spread, or a 72%-of-distance diametric spread.
That means that at the upper threshold of max damage range (2 game units, or 0.72 metres), spread is a circle of diameter 1.46 game units, or 0.52 metres.
And, at the lower threshold of minimum damage range (20 game units, or 7.2 metres), spread is a circle of diameter 14.6 game units, or 5.2 metres.

For the second half, that's a 51%-of-distance radial spread, or a 102%-of-distance diametric spread.
That means that at the upper threshold of max damage range, spread is a circle of diameter 2.04 game units, or 0.73 metres.
And, at the lower threshold of minimum damage range, spread is a circle of diameter 20.4 game units, or 7.3 metres.

Trying to hit anything at that minimum damage range with that kind of spread is completely up to luck. Never mind trying to kill it, when combined with the lower damage.

So with the shotgun, you really want to be getting up close and personal, because it's pretty useless otherwise. Having said that, within that maximum damage range, the spread is small enough and the damage is high enough to make the shotgun a very powerful weapon indeed. Ideally you can kill a skulk with one shot, before it bites you for a second time (before you're dead), or a fade with three.

<u>Musings about shotgun pellet hit chance</u>
If I had access to the skulk's (or other alien's) model size I'd be able to estimate the % likelihood that a single shotgun "bullet" will hit a skulk
- if your aim was perfect (centred on the skulk exposed face), or if your aim was a "bit" off (centred on a corner of the skulk exposed face),
- at various distances (although just minimum damage distance and maximum damage distance and maybe a point in between would be satisfactory and more relevant)
- and various orientations of the skulk (although just minimum and maximum exposure would be satisfactory and more relevant).
It'd simply be the area of the exposed face(s) that overlaps with the circle(s) of spread, divided by the total area of the circle(s) of spread. The 20 and 27 degree circles have to be treated separately, then take the average.
Essentially the problem is analagous to: if you roll either a 4-sided die or a 6-sided die, what's the chance you'll roll a 1? Average of 1/4 and 1/6 is 5/24. Assuming there's an even chance of rolling either die (which is the case above as it's half-half).
For multiple bullets, it's just a binomial distribution. So for example, you could do scenarios like, of 10 bullets you fire, what's the chance that 7 will hit? (10choose7) * hitchance^7 * misschance^(10-7)

...

If there's anything wrong with my interpretations, or how I'm doing my analysis, please speak up so I can correct it.
Also, feel free to discuss anything I've highlighted.

...

This thing's become a bit of a beast, I might have to break it up, or add proper headings and formatting or something. Hopefully people put this information to good use - players or devs. Relevant info could go on the wiki, too.
«13

Comments

  • weezlweezl Join Date: 2008-07-04 Member: 64557Members, Reinforced - Shadow
    when will americans start using SI units like everybody else? :P
  • AsranielAsraniel Join Date: 2002-06-03 Member: 724Members, Playtest Lead, Forum Moderators, NS2 Playtester, Squad Five Blue, Reinforced - Shadow, WC 2013 - Shadow, Subnautica Playtester, Retired Community Developer
    one thing you might add is that the firing rate is lag/server performance related.
  • WheeeeWheeee Join Date: 2003-02-18 Member: 13713Members, Reinforced - Shadow
    yeah pistol is a lot better at killing skulks atm.
  • CrispyCrispy Jaded GD Join Date: 2004-08-22 Member: 30793Members, Constellation
    <!--quoteo(post=1822862:date=Jan 9 2011, 12:15 PM:name=weezl)--><div class='quotetop'>QUOTE (weezl @ Jan 9 2011, 12:15 PM) <a href="index.php?act=findpost&pid=1822862"><{POST_SNAPBACK}></a></div><div class='quotemain'><!--quotec-->when will americans start using SI units like everybody else? :P<!--QuoteEnd--></div><!--QuoteEEnd-->I hope you're not French, because French people often say things like this yet they still have an alarming number of prices in Francs as well as Euros. <i>It's been 9 years!</i> [/tangent]
  • BoBiNoUBoBiNoU Join Date: 2007-12-27 Member: 63274Members
    <!--quoteo(post=1822885:date=Jan 9 2011, 03:28 PM:name=Crispy)--><div class='quotetop'>QUOTE (Crispy @ Jan 9 2011, 03:28 PM) <a href="index.php?act=findpost&pid=1822885"><{POST_SNAPBACK}></a></div><div class='quotemain'><!--quotec-->I hope you're not French, because French people often say things like this yet they still have an alarming number of prices in Francs as well as Euros. <i>It's been 9 years!</i> [/tangent]<!--QuoteEnd--></div><!--QuoteEEnd-->

    you've been trippin man
  • HarimauHarimau Join Date: 2007-12-24 Member: 63250Members
    edited January 2011
    <!--quoteo(post=1822862:date=Jan 9 2011, 08:15 PM:name=weezl)--><div class='quotetop'>QUOTE (weezl @ Jan 9 2011, 08:15 PM) <a href="index.php?act=findpost&pid=1822862"><{POST_SNAPBACK}></a></div><div class='quotemain'><!--quotec-->when will americans start using SI units like everybody else? :P<!--QuoteEnd--></div><!--QuoteEEnd-->
    SI/Metric FTW.

    <!--quoteo(post=1822866:date=Jan 9 2011, 08:48 PM:name=Asraniel)--><div class='quotetop'>QUOTE (Asraniel @ Jan 9 2011, 08:48 PM) <a href="index.php?act=findpost&pid=1822866"><{POST_SNAPBACK}></a></div><div class='quotemain'><!--quotec-->one thing you might add is that the firing rate is lag/server performance related.<!--QuoteEnd--></div><!--QuoteEEnd-->
    Added FocusedWolf's experimental results.

    <b>The biggest thing IMO is fixing that one line that specifies how armour works.</b>
  • countbasiecountbasie Join Date: 2008-12-27 Member: 65884Members
    Thank you harimau, great work.
  • HarimauHarimau Join Date: 2007-12-24 Member: 63250Members
    edited January 2011
    ^np. Too much time on my hands, a strong curiousity and a meticulous, analytical nature led to this wall of text and numbers.

    Added shotguns (including shotgun spread), did a bit of formatting. Next up grenades?

    Having looked through some the code, and I don't really have a programming background, but I really feel like modding this thing. I don't know if it's just me, but most things are pretty transparent. More comments would be even better though.
    Also, does anyone know where to find the "line-ruler" in Decoda? (I don't know what else to call it - numbered bar on the side, just shows what line you're on, seen it in a number of other editors.) IS there one?
  • LazerLazer Join Date: 2003-03-11 Member: 14406Members, Contributor, Constellation, NS2 Playtester
    Glad to see people trying to figure out the root of some of these issues. Haven't had a chance to do it myself but could you check how often hydras scan for local targets? If they all scan on the same frame (or every frame) there is going to be serious lag on those frames. If they all scan at the same rate (1/2 second in between?) but different time offsets (dependent on when they were dropped) then all the scans will act more asynchronous and not cause the same kind of stuttering. Again haven't had a chance to check myself and would like verification that it's done this way or if it needs fixing. (I can fix it fine just haven't had a chance to look)
  • HarimauHarimau Join Date: 2007-12-24 Member: 63250Members
    edited January 2011
    <!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1-->//Hydra.lua:
    Hydra.kAlertCheckInterval = 2

    //Hydra_server.lua:
    Hydra.kThinkInterval = .5

    function Hydra:OnThink()
        Structure.OnThink(self)
        if(self:GetIsBuilt()) then    
            self:AcquireTarget()
            if self.target then
                if(self.timeOfNextFire == nil or (Shared.GetTime() > self.timeOfNextFire)) then
                    self:AttackTarget()
                end
            else
                // Play alert animation if marines nearby and we're not targeting (ARCs?)
                if self.timeLastAlertCheck == nil or Shared.GetTime() > self.timeLastAlertCheck + Hydra.kAlertCheckInterval then
                    if self:GetIsEnemyNearby() then
                        self:SetAnimationWithBlending(Hydra.kAnimAlert, nil, nil, 1/self:AdjustFuryFireDelay(1))
                        self.timeLastAlertCheck = Shared.GetTime()
                    end
                end
            end
        end
        self:SetNextThink(Hydra.kThinkInterval)
    end

    function Hydra:OnConstructionComplete()
        Structure.OnConstructionComplete(self)
        // Start scanning for targets once built
        self:SetNextThink(Hydra.kThinkInterval)
    end<!--c2--></div><!--ec2-->
    Not entirely sure, but it seems to "think"/scan every half a second, depending on when they were dropped; but "alerts", whatever that means, every? for? two seconds. So yeah it's fine. Unless something is broken somewhere and it isn't working that way.
  • KoruyoKoruyo AUT Join Date: 2009-06-06 Member: 67724Members, Reinforced - Shadow
    edited January 2011
    <!--quoteo(post=1823130:date=Jan 10 2011, 04:11 PM:name=Harimau)--><div class='quotetop'>QUOTE (Harimau @ Jan 10 2011, 04:11 PM) <a href="index.php?act=findpost&pid=1823130"><{POST_SNAPBACK}></a></div><div class='quotemain'><!--quotec-->Also, does anyone know where to find the "line-ruler" in Decoda? (I don't know what else to call it - numbered bar on the side, just shows what line you're on, seen it in a number of other editors.) IS there one?<!--QuoteEnd--></div><!--QuoteEEnd-->

    Tools -> Settings -> Editor -> Show line numbers in the margin


    Great work btw Harimau!
  • IronHorseIronHorse Developer, QA Manager, Technical Support & contributor Join Date: 2010-05-08 Member: 71669Members, Super Administrators, Forum Admins, Forum Moderators, NS2 Developer, NS2 Playtester, Squad Five Blue, Subnautica Playtester, Subnautica PT Lead, Pistachionauts
    <!--quoteo(post=1823150:date=Jan 10 2011, 10:14 AM:name=Koruyo)--><div class='quotetop'>QUOTE (Koruyo @ Jan 10 2011, 10:14 AM) <a href="index.php?act=findpost&pid=1823150"><{POST_SNAPBACK}></a></div><div class='quotemain'><!--quotec-->Tools -> Settings -> Editor -> Show line numbers in the margin


    Great work btw Harimau!<!--QuoteEnd--></div><!--QuoteEEnd-->

    great work.. but how a bout the simple answer of stuttering frames + lag + lack of smooth ingame animation = difficult to hit skulks. even in the beta video from top down perspective you can clearly see the "skipping" animation of the skulks movement.
    idk. just my opinion i guess.
  • FlayraFlayra Game Director, Unknown Worlds Entertainment San Francisco Join Date: 2002-01-22 Member: 3Super Administrators, NS2 Developer, Subnautica Developer
    Thanks for the detailed info! I'll check through this and make sure everything is working as it should be.
  • weezlweezl Join Date: 2008-07-04 Member: 64557Members, Reinforced - Shadow
    the hydra alert i think is their indication that a marine is nearby
    it's a feature they have to become all riled up and alert when they "sense" a marine in close proximity, to signal team...
  • MaxMax Technical Director, Unknown Worlds Entertainment Join Date: 2002-03-15 Member: 318Super Administrators, Retired Developer, NS1 Playtester, Forum Moderators, NS2 Developer, Constellation, Subnautica Developer, Pistachionauts, Future Perfect Developer
    <!--quoteo(post=1822862:date=Jan 9 2011, 04:15 AM:name=weezl)--><div class='quotetop'>QUOTE (weezl @ Jan 9 2011, 04:15 AM) <a href="index.php?act=findpost&pid=1822862"><{POST_SNAPBACK}></a></div><div class='quotemain'><!--quotec-->when will americans start using SI units like everybody else? :P<!--QuoteEnd--></div><!--QuoteEEnd-->
    Our code is all based around SI units (and you can switch how they're displayed in the Editor as well!)
  • FlayraFlayra Game Director, Unknown Worlds Entertainment San Francisco Join Date: 2002-01-22 Member: 3Super Administrators, NS2 Developer, Subnautica Developer
    Nice work - this <b>was</b> a big problem.

    Now marines take 3 bites to kill instead of 2, which should help the marine/skulk balance significantly! I love the fact that this fix came from the community too - advantages of releasing all our game code with the game!

    Thanks Harimaru!
  • QuovatisQuovatis Team Inversion Join Date: 2010-01-26 Member: 70321Members, NS2 Playtester, Squad Five Blue
  • JerunkJerunk Join Date: 2002-11-22 Member: 9659Members
  • XuXuXuXu Join Date: 2011-01-01 Member: 76096Members, Reinforced - Silver
  • LazerLazer Join Date: 2003-03-11 Member: 14406Members, Contributor, Constellation, NS2 Playtester
    edited January 2011
    Memory is a little fuzzy but I thought marines were 2 bite kills until armor 1? (encouraging upgrading armor 1 quick) And the Hydra code looks good guess the Hydras themselves aren't the issue.
  • _Thresh__Thresh_ Join Date: 2008-01-11 Member: 63385Members
    you could 2 bite with a parasite in ns1

    site bite bite
  • exoityexoity Join Date: 2003-03-17 Member: 14620Members, NS1 Playtester, Constellation
    <!--quoteo(post=1823241:date=Jan 10 2011, 09:33 PM:name=Lazer)--><div class='quotetop'>QUOTE (Lazer @ Jan 10 2011, 09:33 PM) <a href="index.php?act=findpost&pid=1823241"><{POST_SNAPBACK}></a></div><div class='quotemain'><!--quotec-->Memory is a little fuzzy but I thought marines were 2 bite kills until armor 1? (encouraging upgrading armor 1 quick) And the Hydra code looks good guess the Hydras themselves aren't the issue.<!--QuoteEnd--></div><!--QuoteEEnd-->

    Before armor one it was three bites.

    After two bites the light armor (with armor 0) marine would be done to 10 hp. As a result, you can have two bites and a parasite. That is why it is common to be parasited on approach, then have two bites done to you.
  • PseudoKnightPseudoKnight Join Date: 2002-06-18 Member: 791Members
    edited January 2011
    <!--quoteo(post=1823241:date=Jan 10 2011, 06:33 PM:name=Lazer)--><div class='quotetop'>QUOTE (Lazer @ Jan 10 2011, 06:33 PM) <a href="index.php?act=findpost&pid=1823241"><{POST_SNAPBACK}></a></div><div class='quotemain'><!--quotec-->Memory is a little fuzzy but I thought marines were 2 bite kills until armor 1? (encouraging upgrading armor 1 quick)<!--QuoteEnd--></div><!--QuoteEEnd-->That's what I remember, too, in NS1.
  • juicejuice Join Date: 2003-01-28 Member: 12886Members, Constellation
    bite bite site >> site bite bite
  • zexzex Join Date: 2009-10-07 Member: 68978Members
    edited January 2011
    <!--quoteo(post=1823247:date=Jan 11 2011, 03:05 AM:name=juice)--><div class='quotetop'>QUOTE (juice @ Jan 11 2011, 03:05 AM) <a href="index.php?act=findpost&pid=1823247"><{POST_SNAPBACK}></a></div><div class='quotemain'><!--quotec-->bite bite site >> site bite bite<!--QuoteEnd--></div><!--QuoteEEnd-->

    this
  • Slickk-Slickk- Join Date: 2007-11-26 Member: 63019Members
    edited January 2011
    Really nice work.
    Agree with Charlie though, great this came from a community member.

    On the Hydra front, the code looks fairly ok to understand.

    Could the problem be that if each Hydra (and presumably sentries) are all checking individually for the "self:GetIsEnemyNearby()", would that not mean that each entity would be spamming the server with their own request every half a second?

    Also would that return the locations of all actors on the map or actors nearby (within a distance but through a wall) or actors within distance and visible?
  • ZekZek Join Date: 2002-11-10 Member: 7962Members, NS1 Playtester, Constellation, Reinforced - Shadow
    Marines were two bites at Armor 0 for a long time before they slightly increased armor so it took a parasite as well.
  • LazerLazer Join Date: 2003-03-11 Member: 14406Members, Contributor, Constellation, NS2 Playtester
    <!--quoteo(post=1823262:date=Jan 10 2011, 11:18 PM:name=Zek)--><div class='quotetop'>QUOTE (Zek @ Jan 10 2011, 11:18 PM) <a href="index.php?act=findpost&pid=1823262"><{POST_SNAPBACK}></a></div><div class='quotemain'><!--quotec-->Marines were two bites at Armor 0 for a long time before they slightly increased armor so it took a parasite as well.<!--QuoteEnd--></div><!--QuoteEEnd-->
    Ok that makes sense probably why I remembered it that way plus always para'd on approach out of habit anyway :p
  • HarimauHarimau Join Date: 2007-12-24 Member: 63250Members
    edited January 2011
    <!--quoteo(post=1823150:date=Jan 11 2011, 02:14 AM:name=Koruyo)--><div class='quotetop'>QUOTE (Koruyo @ Jan 11 2011, 02:14 AM) <a href="index.php?act=findpost&pid=1823150"><{POST_SNAPBACK}></a></div><div class='quotemain'><!--quotec-->Tools -> Settings -> Editor -> Show line numbers in the margin

    Great work btw Harimau!<!--QuoteEnd--></div><!--QuoteEEnd-->
    Thanks, on both counts.

    <!--quoteo(post=1823151:date=Jan 11 2011, 02:28 AM:name=ironhorse)--><div class='quotetop'>QUOTE (ironhorse @ Jan 11 2011, 02:28 AM) <a href="index.php?act=findpost&pid=1823151"><{POST_SNAPBACK}></a></div><div class='quotemain'><!--quotec-->great work.. but how a bout the simple answer of stuttering frames + lag + lack of smooth ingame animation = difficult to hit skulks. even in the beta video from top down perspective you can clearly see the "skipping" animation of the skulks movement.
    idk. just my opinion i guess.<!--QuoteEnd--></div><!--QuoteEEnd-->
    As true as this is, it's not so relevant to my interests. That's an engine/networking issue, rather than a game issue--at least not directly. I was more interested in looking at game mechanics, and marine vs alien balance on an "ideal playing field"; through analysis of the code (mechanics and values). So assuming that, further down the track, those issues are eliminated, then how will the game balance or work then from a theoretical perspective? And how can we apply that knowledge?

    Has anyone yet seen how LAN games perform (where you've at least eliminated the network latency)? It'd be interesting to know.

    <!--quoteo(post=1823172:date=Jan 11 2011, 04:38 AM:name=weezl)--><div class='quotetop'>QUOTE (weezl @ Jan 11 2011, 04:38 AM) <a href="index.php?act=findpost&pid=1823172"><{POST_SNAPBACK}></a></div><div class='quotemain'><!--quotec-->the hydra alert i think is their indication that a marine is nearby
    it's a feature they have to become all riled up and alert when they "sense" a marine in close proximity, to signal team...<!--QuoteEnd--></div><!--QuoteEEnd-->
    So basically unrelated to the scan (for targets) then? That makes a lot of sense, actually.

    <!--quoteo(post=1823210:date=Jan 11 2011, 07:07 AM:name=Max)--><div class='quotetop'>QUOTE (Max @ Jan 11 2011, 07:07 AM) <a href="index.php?act=findpost&pid=1823210"><{POST_SNAPBACK}></a></div><div class='quotemain'><!--quotec-->Our code is all based around SI units (and you can switch how they're displayed in the Editor as well!)<!--QuoteEnd--></div><!--QuoteEEnd-->
    Yeah, Metric/SI is a great standard, since it's all pretty self-consistent, whereas Imperial/American Engineering is pretty much all over the place. I'm an engineering student and SI makes things a tonne easier (pun fully intended).

    <!--quoteo(post=1823225:date=Jan 11 2011, 08:37 AM:name=Flayra)--><div class='quotetop'>QUOTE (Flayra @ Jan 11 2011, 08:37 AM) <a href="index.php?act=findpost&pid=1823225"><{POST_SNAPBACK}></a></div><div class='quotemain'><!--quotec-->Nice work - this <b>was</b> a big problem.

    Now marines take 3 bites to kill instead of 2, which should help the marine/skulk balance significantly! I love the fact that this fix came from the community too - advantages of releasing all our game code with the game!

    Thanks Harimaru!<!--QuoteEnd--></div><!--QuoteEEnd-->
    You're welcome. Glad to be of assistance.

    <!--quoteo(post=1823247:date=Jan 11 2011, 10:05 AM:name=juice)--><div class='quotetop'>QUOTE (juice @ Jan 11 2011, 10:05 AM) <a href="index.php?act=findpost&pid=1823247"><{POST_SNAPBACK}></a></div><div class='quotemain'><!--quotec-->bite bite site >> site bite bite<!--QuoteEnd--></div><!--QuoteEEnd-->
    It doesn't actually matter what order, since both attacks are the same damage type: "Normal" (2 health per armour). So a marine effectively has: 100 health + (30 armour * 2 health per armour) = 160 health. You could go Bite-Bite-Para, Para-Bite-Bite, or even Bite-Para-Bite, it would all be the same: 75 + 75 + 10 = 160 damage.
    But yes, it was three bites, or para-bite-bite, from NS1. That's what I remember.
    Fun fact: considering that marines mainly attack with the Normal damage type (rifle, shotgun), Fades effectively have 300 + 100*2 = 500 health.

    <!--quoteo(post=1823252:date=Jan 11 2011, 10:27 AM:name=Slickk-)--><div class='quotetop'>QUOTE (Slickk- @ Jan 11 2011, 10:27 AM) <a href="index.php?act=findpost&pid=1823252"><{POST_SNAPBACK}></a></div><div class='quotemain'><!--quotec-->Really nice work.
    Agree with Charlie though, great this came from a community member.

    On the Hydra front, the code looks fairly ok to understand.

    Could the problem be that if each Hydra (and presumably sentries) are all checking individually for the "self:GetIsEnemyNearby()", would that not mean that each entity would be spamming the server with their own request every half a second?

    Also would that return the locations of all actors on the map or actors nearby (within a distance but through a wall) or actors within distance and visible?<!--QuoteEnd--></div><!--QuoteEEnd-->
    Well, each hydra does do the following actions each think.
    <!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1-->OnThink
    -> AcquireTarget
      -> GetSortedTargetList
      -> GetTargetValid
    -> AttackTarget
      -> CreateSpikeProjectile
        -> [...]
    -> OR Alert
      -> GetIsEnemyNearby
    -> SetNextThink<!--c2--></div><!--ec2-->
    GetSortedTargetList seems the most intensive, but the origin and the range are put into the function from the beginning, so it shouldn't be scanning everything on the map.
    There are a few instances (33, so relatively few) in the code of "GetGamerules():GetEntities(arguments)", but I can't figure out how they work as I can't find the function "GetEntities(arguments)". The closest is "GetEntitiesIsA(arguments)", and I wonder why the hydra doesn't use the function "GetEntitiesIsAInRadius(arguments)", as the arguments match:
    <!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1-->//Entity.lua
    function GetEntitiesIsaInRadius(className, teamNumber, origin, radius, checkXZOnly, visibleOnly, log)

    //Hydra_Server.lua
    function Hydra:GetSortedTargetList()
        local targets = GetGamerules():GetEntities("LiveScriptActor", GetEnemyTeamNumber(self:GetTeamNumber()), hydraAttackOrigin, Hydra.kRange)<!--c2--></div><!--ec2-->
    It's the same case for sentries, as well.
    Could this be the source of the problem, or are my searching skills not enough? I figure if it weren't working, hydras and sentries wouldn't work at all though, so I don't know... :/ Unless it's managing to scan every target on the map regardless...

    Just noticed <b>Bot_Player.lua</b> and had as skim-through; so it looks like bots are being supported from the start (I didn't know this), which is great news, especially for a potential SP campaign and training servers.
  • HarimauHarimau Join Date: 2007-12-24 Member: 63250Members
    I won't bother editing the OP and adding the info there, so I'll just keep posting anything new with new replies. Maybe I'll compile it later.

    Quotes from other threads:
    <u>Weapons vs Structures</u>
    <!--quoteo(post=1823301:date=Jan 11 2011, 09:37 PM:name=Harimau)--><div class='quotetop'>QUOTE (Harimau @ Jan 11 2011, 09:37 PM) <a href="index.php?act=findpost&pid=1823301"><{POST_SNAPBACK}></a></div><div class='quotemain'><!--quotec-->I see the biggest problem with flamethrower simply being the blinding effect.

    Just for interest:

    Axe has a base damage of 30, with a cooldown of 0.6. That's (under ideal conditions) 50 dps. But it does double damage against structures. So 100 dps. "Normal" HealthPerArmor. Harvester has 2000 health and 250 armour, effectively 2500 hitpoints. It takes 25 seconds for a lone marine to cut down a Harvester.

    A grenade has a base damage of 150. Double damage against structures. So 300 damage. "Normal" HealthPerArmor. Takes 9 (8.33r) grenades to take down a harvester. This is assuming point-blank explosion, as damage drops off with blast radius, scaling linearly from r = 0 (maxdamage) to r = damageradius (0 damage).

    Shotgun does 20 damage per pellet (assuming point-blank), and 10 pellets total. That's 200 damage. "Normal" HealthPerArmor. Takes 13 (12.5) shells to take down a harvester.

    Flamethrower does 35 damage 'per shot' and 'fires' every 0.5 seconds. That's 70 dps. It can fire for a length of 10 seconds. Add 10 dps from burning effects for a total of 80 dps. "Normal" HealthPerArmor. It takes 31.25 seconds for a lone flamethrower to take down, assuming continous burning and continuous flame (not going to happen).

    Skulk has 70 health and 10 armour. Effectively 90 hitpoints. Takes a flamethrower (just the flame, no burning effects) 1.3 seconds to kill a skulk. On the other hand, it takes 9 rifle bullets to kill a skulk, and if it were working right and you had a 100% hit-rate, it would only take 0.4995 seconds to kill a skulk. You can also one-shot a skulk with a shotgun, so it effectively takes 0 seconds to kill a skulk with a shotgun.

    By comparison, skulk bite has a base damage of 75, cooldown of 0.45 seconds. That's 166.6r7 dps. "Normal" HealthPerArmor. Extractor has 4800 health and 600 armour, effectively 6000 hitpoints. It takes a lone skulk 36 seconds to bite down an extractor.

    Fade swipe does 80 damage, cooldown of 0.5 seconds. That's 160 dps. "Normal" HealthPerArmor. Takes 37.5 seconds to take out an extractor.<!--QuoteEnd--></div><!--QuoteEEnd-->

    <u>Flamethrower Burning</u>
    <!--quoteo(post=1823317:date=Jan 12 2011, 01:05 AM:name=Harimau)--><div class='quotetop'>QUOTE (Harimau @ Jan 12 2011, 01:05 AM) <a href="index.php?act=findpost&pid=1823317"><{POST_SNAPBACK}></a></div><div class='quotemain'><!--quotec-->Burning is a "game effect". Game effects update every 0.3 seconds. Each update, it does the following:
    <!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1-->//PlayingTeam.lua:
    PlayingTeam.kUpdateGameEffectsInterval = .3
                // See if we put ourselves out
                local stopFireChance = PlayingTeam.kUpdateGameEffectsInterval * kStopFireProbability
                
                if NetworkRandom() < stopFireChance then
                
                    entity:SetGameEffectMask(kGameEffect.OnFire, false)

                end

    //BalanceMisc.lua:
                kStopFireProbability = .15       // 15% chance per second<!--c2--></div><!--ec2-->
    Basically, stopFireChance = 0.3*0.15 = 0.045
    NetworkRandom() finds a random value between 0 and 1; if it's less than 0.045, the player gets put out.
    <b>Every trial there's only a 4.5% chance that a player will get put out.</b>
    This seems incredibly wrong to me.

    Because in fact, over say, 0.9 seconds (3 trials), the chance that the player gets put out is:
    1 - [(3Choose0)*0.045^0*(1-0.045)^3] = 1 - [1*1*0.955^23] = 0.129 chance ===> actual chance
    Compare to:
    0.15 chance per second * 0.9 seconds = 0.135 chance ===> the projected chance, based on the idea of "15% chance <b>per second</b>"
    The discrepancy doesn't seem too large, but actual chance is certainly less.

    But to illustrate that point better, let's consider 23 trials (6.9 seconds):
    actual chance = 1 - [(23Choose0)*0.045^0*(1-0.045)^23] = 1 - [1*1*0.955^23] = 0.653 chance
    projected chance = 0.15*6.9 = 1.035 ===> supposedly over 100% chance. impossible.
    The difference is obvious.

    <i>What we're interested in is "the chance of at least 1 success", given a number of trials. This can be re-expressed as the chance of there <b>not</b> being 'zero successes'. (1 - chance of zero successes) which is what I've used above.</i>

    Needless to say, there is a <b>far</b> greater likelihood that you'll die before you get put out.

    There is also another problem with the method used, because for example, you could set kStopFireProbability to 1.5 (150%, a pretty much impossible value in terms of probability), but that would still make the chance per trial 0.45, or 45%.

    What I (personally) think should happen, is that stopFireChance should simply be kStopFireProbability, independent of the update time; and you can have kStopFireProbability whatever is best for balance.<!--QuoteEnd--></div><!--QuoteEEnd-->
    Also:
    <u>Put Out Burning Chance</u>
    <img src="http://img832.imageshack.us/img832/2083/ns2burningputoutchance.png" border="0" class="linked-image" />

    <u>Potential Flamethrower vs Onos</u>
    <!--quoteo(post=1823298:date=Jan 11 2011, 09:08 PM:name=Harimau)--><div class='quotetop'>QUOTE (Harimau @ Jan 11 2011, 09:08 PM) <a href="index.php?act=findpost&pid=1823298"><{POST_SNAPBACK}></a></div><div class='quotemain'><!--quotec-->Price: As I understand it, if it's not heavy, and it's not light, then it's considered 'normal'. They haven't specified armour effects for any other damage types. All that means is HealthPerArmor = 2. So flame vs onos: onos effectively has 700 + 600*2 = 1900 hp. Fun fact: It takes 3 full rifle clips with Weapon3 to take down an un-upgraded onos.
    Looking at the flamer damage: 35 every 0.5 seconds for 10 seconds. 700 damage, plus any lingering burn effects. Whether someone burns or goes out is 100% to do with chance. Assuming they get set fire to after first taking damage, and go out straight after the flamer runs out of ammo, that's only an extra 10 seconds of burn damage: 100 damage. 800 damage total. Add Weapon3: 800 => 1040 hp (haven't checked this, just guessing). An Onos should be able to tank two "clips" of flamethrowers dealing their full damage.

    Also, I'd love to see a late-game "heavy damage" upgrade + larger mag, for the rifle. It would convert the rifle's current 'normal' damage-type to a 'heavy' damage-type (HealthPerArmor from 2 to 1). It wouldn't affect damage too drastically, it'd just halve the effectiveness of armour to block hp. It'd make the rifle more useful in the late-game.<!--QuoteEnd--></div><!--QuoteEEnd-->
Sign In or Register to comment.