diff --git a/ns2/lua/AlienWeaponEffects.lua b/ns2/lua/AlienWeaponEffects.lua
index e7cebf5..1f44980 100644
--- a/ns2/lua/AlienWeaponEffects.lua
+++ b/ns2/lua/AlienWeaponEffects.lua
@@ -23,8 +23,9 @@ kAlienWeaponEffects =
// Brian TODO: Change to something cooler
{player_cinematic = "cinematics/alien/gorge/bilebomb_impact.cinematic", doer = "Bomb", done = true},
- //{player_cinematic = "cinematics/alien/lerk/spike_impact.cinematic", doer = "Spike", done = true},
+ {cinematic = "cinematics/alien/lerk/spike_impact.cinematic", doer = "Spikes", done = true},
//{player_cinematic = "cinematics/alien/hydra/spike_impact.cinematic", doer = "HydraSpike", done = true},
+
{player_cinematic = "cinematics/materials/%s/scrape.cinematic", doer = "SwipeBlink", done = true},
{player_cinematic = "cinematics/materials/%s/scrape.cinematic", doer = "StabBlink", done = true},
@@ -313,15 +314,17 @@ kAlienWeaponEffects =
{sound = "sound/ns2.fev/alien/lerk/spikes", upgraded = false, done = true},
{sound = "sound/ns2.fev/alien/lerk/spikes_pierce", upgraded = true, done = true},
},
+
},
spikes_alt_attack =
{
-
- spikeZoomEffect =
+ spikeSpray =
{
- {sound = "sound/ns2.fev/alien/lerk/spikes_zoom", upgraded = false, done = true},
- {sound = "sound/ns2.fev/alien/lerk/spikes_zoomed_pierce", upgraded = true, done = true},
+ {overlay_animation = "spike"},
+ {viewmodel_animation = "spikes_snipe"},
+ {sound = "sound/ns2.fev/alien/lerk/spikes_zoom"},
+ /*{sound = "sound/ns2.fev/alien/lerk/spikes_zoomed_pierce", upgraded = true, done = true},*/
},
},
@@ -351,8 +354,7 @@ kAlienWeaponEffects =
{
sporesAttackEffects =
{
- {sound = "sound/ns2.fev/alien/lerk/spores_shoot"},
- {viewmodel_animation = "spores_attack"},
+ {looping_sound = "sound/ns2.fev/alien/lerk/spore_spray"},
{overlay_animation = "spore"},
//{viewmodel_cinematic = "cinematics/alien/lerk/spore_view_fire.cinematic", attach_point = "?"},
@@ -360,12 +362,24 @@ kAlienWeaponEffects =
},
},
- spores =
+ spores_attack_end =
+ {
+ sporesAttackEndEffects =
+ {
+ {stop_sound = "sound/ns2.fev/alien/lerk/spore_spray"},
+ },
+ },
+
+ spores_alt_attack =
{
- sporesCreateEffects =
+ sporesAttackEffects =
{
- {sound = "sound/ns2.fev/alien/lerk/spores_hit"},
- {cinematic = "cinematics/alien/lerk/spore_impact.cinematic"},
+ {sound = "sound/ns2.fev/alien/lerk/spores_shoot"},
+ {viewmodel_animation = "spores_attack"},
+ {overlay_animation = "spore"},
+
+ //{viewmodel_cinematic = "cinematics/alien/lerk/spore_view_fire.cinematic", attach_point = "?"},
+ //{weapon_cinematic = "cinematics/alien/lerk/spores.cinematic", attach_point = "?"},
},
},
diff --git a/ns2/lua/Balance.lua b/ns2/lua/Balance.lua
index 7adfbb4..ef2b815 100644
--- a/ns2/lua/Balance.lua
+++ b/ns2/lua/Balance.lua
@@ -316,22 +316,27 @@ kBileBombDamageType = kDamageType.StructuresOnly
kBileBombFireDelay = 1
kBileBombEnergyCost = 15
-kSpikeMaxDamage = 30
-kSpikeMinDamage = 8
+kSpikeMaxDamage = 24
+kSpikeMinDamage = 20
kSpikeDamageType = kDamageType.Light
-kSpikeFireDelay = 0.1
+kSpikeFireDelay = 0.08
kSpikeEnergyCost = 1.5
+kSpikeMinDamageRange = 16
+kSpikeMaxDamageRange = 2
kPiercingDamageScalar = 1.4
kSpikesAltDamage = 90
-kSpikesAltDamageType = kDamageType.Normal
-kSpikesAltFireDelay = 1
-kSpikesAltEnergyCost = 30
+kSpikesAltDamageType = kDamageType.Heavy
+kSpikesAltFireDelay = 0.5
+kSpikesAltEnergyCost = 25
kSporesDamagePerSecond = 7
kSporesDamageType = kDamageType.Gas
-kSporesFireDelay = 0.8
-kSporesEnergyCost = 20
+kSporesDustDamagePerSecond = 18
+kSporesDustFireDelay = 0.18
+kSporesCloudFireDelay = 0.8
+kSporesDustEnergyCost = 7
+kSporesCloudEnergyCost = 20
kSwipeDamage = 70
kSwipeDamageType = kDamageType.Puncture
@@ -372,9 +377,6 @@ kMelee3DamageScalar = 1.3
-
-
-
// SPAWN TIMES
kMarineRespawnTime = 10
kAlienRespawnTime = 13
@@ -537,7 +539,7 @@ kMetabolizeCost = 25
kObservatoryInitialEnergy = 25 kObservatoryMaxEnergy = 100
kObservatoryScanCost = 20
-kObservatoryDistressBeaconCost = 50
+kObservatoryDistressBeaconCost = 50
kDrifterCost = 30
diff --git a/ns2/lua/BalanceHealth.lua b/ns2/lua/BalanceHealth.lua
index 48982e8..aab65f6 100644
--- a/ns2/lua/BalanceHealth.lua
+++ b/ns2/lua/BalanceHealth.lua
@@ -1,124 +1,124 @@
-// ======= Copyright © 2003-2011, Unknown Worlds Entertainment, Inc. All rights reserved. =======
-//
-// lua\BalanceHealth.lua
-//
-// Created by: Charlie Cleveland (charlie@unknownworlds.com)
-//
-// Auto-generated. Copy and paste from balance spreadsheet.
-//
-// ========= For more information, visit us at http://www.unknownworlds.com =====================
-
-// HEALTH AND ARMOR
-kMarineHealth = 100 kMarineArmor = 30 kMarinePointValue = 5
-kExosuitHealth = 100 kExosuitArmor = 200 kExosuitPointValue = 10
-
-kSkulkHealth = 70 kSkulkArmor = 5 kSkulkPointValue = 5
-kGorgeHealth = 150 kGorgeArmor = 50 kGorgePointValue = 7
-kLerkHealth = 125 kLerkArmor = 30 kLerkPointValue = 15
-kFadeHealth = 200 kFadeArmor = 50 kFadePointValue = 20
-kOnosHealth = 700 kOnosArmor = 600 kOnosPointValue = 30
-
-kEggHealth = 250 kEggArmor = 0 kEggPointValue = 2
-
-kArmorPerUpgradeLevel = 20
-kExosuitArmorPerUpgradeLevel = 30
-kBaseArmorAbsorption = 0.7
-kHealthPointsPerArmor = 2
-kBuildPointValue = 5
-kRecyclePaybackScalar = 0.75
-kRepairMarineArmorPointValue = 1
-
-kSkulkArmorFullyUpgradedAmount = 20
-kGorgeArmorFullyUpgradedAmount = 50
-kLerkArmorFullyUpgradedAmount = 30
-kFadeArmorFullyUpgradedAmount = 100
-kOnosArmorFullyUpgradedAmount = 350
-
-kAlienArmorAbsorption1 = 1
-kAlienArmorAbsorption2 = 1.1
-kAlienArmorAbsorption3 = 1.2
-
-// Damage types
-kHealthPointsPerArmorLight = 4
-kHealthPointsPerArmorHeavy = 1
-kPuncturePlayerDamageScalar = 1.5
-kStructuralDamageScalar = 2
-
-kExosuitAbsorption = 0.95
-kBalanceAutoHealMaxPercentPerSecond = 0.5
-kBalanceInfestationHurtPercentPerSecond = 2
-
-kStartHealthScalar = 0.3
-kCarapaceHealthPerArmor = 3
-
-
-kArmoryHealth = 1800 kArmoryArmor = 300 kArmoryPointValue = 10
-kAdvancedArmoryHealth = 3000 kAdvancedArmoryArmor = 500 kAdvancedArmoryPointValue = 40
-
-kCommandStationHealth = 5000 kCommandStationArmor = 2500 kCommandStationPointValue = 25
-
-kObservatoryHealth = 1700 kObservatoryArmor = 0 kObservatoryPointValue = 15
-kPhaseGateHealth = 2700 kPhaseGateArmor = 150 kPhaseGatePointValue = 15
-kRoboticsFactoryHealth = 2400 kRoboticsFactoryArmor = 800 kRoboticsFactoryPointValue = 20
-kPrototypeLabHealth = 3200 kPrototypeLabArmor = 400 kPrototypeLabPointValue = 20
-kInfantryPortalHealth = 2250 kInfantryPortalArmor = 125 kInfantryPortalPointValue = 15
-kInfantryPortalTransponderHealth = 3000 kInfantryPortalTransponderArmor = 0 kInfantryPortalTransponderPointValue = 20
-kPowerPackHealth = 1200 kPowerPackArmor = 400 kPowerPackPointValue = 15
-kArmsLabHealth = 1870 kArmsLabArmor = 165 kArmsLabPointValue = 20
-
-kHiveHealth = 6300 kHiveArmor = 350 kHivePointValue = 30
-
-kDrifterHealth = 150 kDrifterArmor = 0 kDrifterPointValue = 2
-kMACHealth = 300 kMACArmor = 50 kMACPointValue = 5
-
-kExtractorHealth = 4200 kExtractorArmor = 900 kExtractorPointValue = 15
-kHarvesterHealth = 1750 kHarvesterArmor = 375 kHarvesterPointValue = 15
-
-kSentryHealth = 1440 kSentryArmor = 180 kSentryPointValue = 10
-kARCHealth = 1600 kARCArmor = 200 kARCPointValue = 20
-
-kCragHealth = 600 kCragArmor = 200 kCragPointValue = 10
-kMatureCragHealth = 600 kMatureCragArmor = 300 kMatureCragPointValue = 15
-
-kWhipHealth = 640 kWhipArmor = 80 kWhipPointValue = 10
-kMatureWhipHealth = 750 kMatureWhipArmor = 125 kMatureWhipPointValue = 15
-
-kShiftHealth = 560 kShiftArmor = 70 kShiftPointValue = 10
-kMatureShiftHealth = 720 kMatureShiftArmor = 90 kMatureShiftPointValue = 15
-
-kShadeHealth = 700 kShadeArmor = 0 kShadePointValue = 10
-kMatureShadeHealth = 900 kMatureShadeArmor = 0 kMatureShadePointValue = 15
-
-kHydraHealth = 500 kHydraArmor = 0 kHydraPointValue = 5
-kCystHealth = 600 kCystArmor = 0 kCystPointValue = 5
-kMiniCystHealth = 400 kMiniCystArmor = 0 kMiniCystPointValue = 3
-
-kPowerPointHealth = 2500 kPowerPointArmor = 1250 kPowerPointPointValue = 15
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+// ======= Copyright © 2003-2011, Unknown Worlds Entertainment, Inc. All rights reserved. =======
+//
+// lua\BalanceHealth.lua
+//
+// Created by: Charlie Cleveland (charlie@unknownworlds.com)
+//
+// Auto-generated. Copy and paste from balance spreadsheet.
+//
+// ========= For more information, visit us at http://www.unknownworlds.com =====================
+
+// HEALTH AND ARMOR
+kMarineHealth = 100 kMarineArmor = 30 kMarinePointValue = 5
+kExosuitHealth = 100 kExosuitArmor = 200 kExosuitPointValue = 10
+
+kSkulkHealth = 70 kSkulkArmor = 5 kSkulkPointValue = 5
+kGorgeHealth = 150 kGorgeArmor = 50 kGorgePointValue = 7
+kLerkHealth = 200 kLerkArmor = 25 kLerkPointValue = 15
+kFadeHealth = 200 kFadeArmor = 50 kFadePointValue = 20
+kOnosHealth = 700 kOnosArmor = 600 kOnosPointValue = 30
+
+kEggHealth = 250 kEggArmor = 0 kEggPointValue = 2
+
+kArmorPerUpgradeLevel = 20
+kExosuitArmorPerUpgradeLevel = 30
+kBaseArmorAbsorption = 0.7
+kHealthPointsPerArmor = 2
+kBuildPointValue = 5
+kRecyclePaybackScalar = 0.75
+kRepairMarineArmorPointValue = 1
+
+kSkulkArmorFullyUpgradedAmount = 20
+kGorgeArmorFullyUpgradedAmount = 50
+kLerkArmorFullyUpgradedAmount = 30
+kFadeArmorFullyUpgradedAmount = 100
+kOnosArmorFullyUpgradedAmount = 350
+
+kAlienArmorAbsorption1 = 1
+kAlienArmorAbsorption2 = 1.1
+kAlienArmorAbsorption3 = 1.2
+
+// Damage types
+kHealthPointsPerArmorLight = 4
+kHealthPointsPerArmorHeavy = 1
+kPuncturePlayerDamageScalar = 1.5
+kStructuralDamageScalar = 2
+
+kExosuitAbsorption = 0.95
+kBalanceAutoHealMaxPercentPerSecond = 0.5
+kBalanceInfestationHurtPercentPerSecond = 2
+
+kStartHealthScalar = 0.3
+kCarapaceHealthPerArmor = 3
+
+
+kArmoryHealth = 1800 kArmoryArmor = 300 kArmoryPointValue = 10
+kAdvancedArmoryHealth = 3000 kAdvancedArmoryArmor = 500 kAdvancedArmoryPointValue = 40
+
+kCommandStationHealth = 5000 kCommandStationArmor = 2500 kCommandStationPointValue = 25
+
+kObservatoryHealth = 1700 kObservatoryArmor = 0 kObservatoryPointValue = 15
+kPhaseGateHealth = 2700 kPhaseGateArmor = 150 kPhaseGatePointValue = 15
+kRoboticsFactoryHealth = 2400 kRoboticsFactoryArmor = 800 kRoboticsFactoryPointValue = 20
+kPrototypeLabHealth = 3200 kPrototypeLabArmor = 400 kPrototypeLabPointValue = 20
+kInfantryPortalHealth = 2250 kInfantryPortalArmor = 125 kInfantryPortalPointValue = 15
+kInfantryPortalTransponderHealth = 3000 kInfantryPortalTransponderArmor = 0 kInfantryPortalTransponderPointValue = 20
+kPowerPackHealth = 1200 kPowerPackArmor = 400 kPowerPackPointValue = 15
+kArmsLabHealth = 1870 kArmsLabArmor = 165 kArmsLabPointValue = 20
+
+kHiveHealth = 6300 kHiveArmor = 350 kHivePointValue = 30
+
+kDrifterHealth = 150 kDrifterArmor = 0 kDrifterPointValue = 2
+kMACHealth = 300 kMACArmor = 50 kMACPointValue = 5
+
+kExtractorHealth = 4200 kExtractorArmor = 900 kExtractorPointValue = 15
+kHarvesterHealth = 1750 kHarvesterArmor = 375 kHarvesterPointValue = 15
+
+kSentryHealth = 1440 kSentryArmor = 180 kSentryPointValue = 10
+kARCHealth = 1600 kARCArmor = 200 kARCPointValue = 20
+
+kCragHealth = 600 kCragArmor = 200 kCragPointValue = 10
+kMatureCragHealth = 600 kMatureCragArmor = 300 kMatureCragPointValue = 15
+
+kWhipHealth = 640 kWhipArmor = 80 kWhipPointValue = 10
+kMatureWhipHealth = 750 kMatureWhipArmor = 125 kMatureWhipPointValue = 15
+
+kShiftHealth = 560 kShiftArmor = 70 kShiftPointValue = 10
+kMatureShiftHealth = 720 kMatureShiftArmor = 90 kMatureShiftPointValue = 15
+
+kShadeHealth = 700 kShadeArmor = 0 kShadePointValue = 10
+kMatureShadeHealth = 900 kMatureShadeArmor = 0 kMatureShadePointValue = 15
+
+kHydraHealth = 500 kHydraArmor = 0 kHydraPointValue = 5
+kCystHealth = 600 kCystArmor = 0 kCystPointValue = 5
+kMiniCystHealth = 400 kMiniCystArmor = 0 kMiniCystPointValue = 3
+
+kPowerPointHealth = 2500 kPowerPointArmor = 1250 kPowerPointPointValue = 15
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ns2/lua/ClientEffects.lua b/ns2/lua/ClientEffects.lua
index 6f2c1e0..4253895 100644
--- a/ns2/lua/ClientEffects.lua
+++ b/ns2/lua/ClientEffects.lua
@@ -21,8 +21,28 @@ kClientEffectData =
// Destroy it if not spinning
{stop_cinematic = "cinematics/marine/infantryportal/spin.cinematic", classname = "InfantryPortal", active = false, done = true},
+
+ // Create dust trail (alt-mode true for alt-fire spore cloud, false for trail)
+ {cinematic = "cinematics/alien/lerk/spore_trail.cinematic", classname = "SporeCloud", alt_mode = false, done = true},
+
+ // Fire spore cloud
+ {sound = "sound/ns2.fev/alien/lerk/spores_hit", classname = "SporeCloud", alt_mode = true},
+ {cinematic = "cinematics/alien/lerk/spore_impact.cinematic", classname = "SporeCloud", alt_mode = true, done = true},
},
},
+
+ on_destroy =
+ {
+ destroyEffects =
+ {
+ // Dust trail
+ {stop_cinematic = "cinematics/alien/lerk/spore_trail.cinematic", classname = "SporeCloud", alt_mode = false, done = true},
+
+ // Spore cloud
+ {stop_cinematic = "cinematics/alien/lerk/spore_impact.cinematic", classname = "SporeCloud", alt_mode = true, done = true},
+
+ },
+ },
// Called on client only, whenever the "active" state of a structure is changed (currently only the IP)
client_active_changed =
@@ -52,6 +72,23 @@ kClientEffectData =
{stop_cinematic = "cinematics/alien/metabolize_small.cinematic", cloaked = false, done = true},
},
},
+
+ /*
+ client_spore_trail_create =
+ {
+ sporeCloudEffects =
+ {
+ {cinematic = "cinematics/alien/lerk/spore_trail.cinematic"},
+ }
+ },
+
+ client_spore_trail_destroy =
+ {
+ sporeCloudEffects =
+ {
+ {stop_cinematic = "cinematics/alien/lerk/spore_trail.cinematic"},
+ }
+ },*/
}
diff --git a/ns2/lua/GeneralEffects.lua b/ns2/lua/GeneralEffects.lua
index 8524fd9..faab8fe 100644
--- a/ns2/lua/GeneralEffects.lua
+++ b/ns2/lua/GeneralEffects.lua
@@ -373,6 +373,19 @@ kGeneralEffectData =
{stop_sound = "sound/ns2.fev/alien/infestation/build", classname = "Infestation", done = true},
},
},
+
+ res_received =
+ {
+ resReceivedEffects =
+ {
+ {private_sound = "sound/ns2.fev/alien/common/res_received", classname = "Alien", done = true},
+ {private_sound = "sound/ns2.fev/alien/commander/res_received", classname = "Commander", isalien = true, done = true},
+ {private_sound = "sound/ns2.fev/marine/commander/res_received", classname = "Commander", isalien = false, done = true},
+ // Marine/Heavy
+ {private_sound = "sound/ns2.fev/marine/common/res_received", done = true},
+
+ },
+ },
}
diff --git a/ns2/lua/Lerk.lua b/ns2/lua/Lerk.lua
index 66eb5ec..0bbc88f 100644
--- a/ns2/lua/Lerk.lua
+++ b/ns2/lua/Lerk.lua
@@ -5,6 +5,8 @@
// Created by: Charlie Cleveland (charlie@unknownworlds.com) and
// Max McGuire (max@unknownworlds.com)
//
+// Modified by: James Gu (twiliteblue) on 5 Aug 2011
+//
// ========= For more information, visit us at http://www.unknownworlds.com =====================
Script.Load("lua/Utility.lua")
@@ -37,10 +39,10 @@ Lerk.networkVars =
Lerk.kViewOffsetHeight = .5
Lerk.XZExtents = .4
Lerk.YExtents = .4
-Lerk.kJumpImpulse = 5
-Lerk.kFlapUpImpulse = 4 // NS1 made this 2/3 of kFlapStraightUpImpulse
+Lerk.kJumpImpulse = 4
+Lerk.kFlapUpImpulse = 4
Lerk.kFlapStraightUpImpulse = 6
-Lerk.kFlapThrustMoveScalar = .85 // From NS1
+Lerk.kFlapThrustMoveScalar = 1 //.85
Lerk.kFov = 100
Lerk.kZoomedFov = 35
Lerk.kMass = 54 // ~120 pounds
@@ -103,11 +105,16 @@ function Lerk:GetMaxSpeed()
speed = Lerk.kMaxWalkSpeed
if not self:GetIsOnGround() then
- local kBaseAirScalar = .5
- local kAirTimeToMaxSpeed = 10
+ local kBaseAirScalar = 1.2 // originally 0.5
+ local kAirTimeToMaxSpeed = 5 // originally 10
local airTimeScalar = Clamp((Shared.GetTime() - self.timeLastOnGround) / kAirTimeToMaxSpeed, 0, 1)
local speedScalar = kBaseAirScalar + airTimeScalar * (1 - kBaseAirScalar)
speed = Lerk.kMaxWalkSpeed + speedScalar * (Lerk.kMaxSpeed - Lerk.kMaxWalkSpeed)
+
+ // half max speed while the walk key is pressed
+ if self.movementModiferState then
+ speed = speed * 0.5
+ end
//Print("timeLastOnGround: %.2f, airTimeScalar: %.2f, speed scalar: %.2f, speed: %.2f", self.timeLastOnGround, airTimeScalar, speedScalar, speed)
end
@@ -128,6 +135,29 @@ function Lerk:GetJumpHeight()
return Lerk.kJumpHeight
end
+function Lerk:GetFrictionForce(input, velocity)
+
+ local frictionScalar = 2
+
+ if self.gliding then
+ return Vector(0, 0, 0)
+ end
+
+ // When in the air, but not gliding (spinning out of control)
+ // Allow holding the jump key to reduce velocity, and slow the fall
+ if (not self:GetIsOnGround()) and (bit.band(input.commands, Move.Jump) ~= 0) and (not self.gliding) then
+ if velocity.y < 0 then
+ return Vector(-velocity.x, -velocity.y, -velocity.z) * frictionScalar
+ else
+ return Vector(-velocity.x, 0, -velocity.z) * frictionScalar
+ end
+ end
+
+ return Alien.GetFrictionForce(self, input, velocity)
+
+end
+
+
// Lerk flight
//
// Lift = New vertical movement
@@ -191,24 +221,25 @@ function Lerk:ComputeForwardVelocity(input)
if self.gliding then
+ // Gliding: ignore air control
// Add or remove velocity depending if we're looking up or down
- local dot = Clamp(Vector(0, -1, 0):DotProduct(viewCoords.zAxis), 0, 1)
-
- local glideAmount = dot // math.sin( dot * math.pi / 2 )
-
- local glideVelocity = viewCoords.zAxis * math.abs(glideAmount) * self:GetAcceleration() * 5
-
+ local zAxis = viewCoords.zAxis
+
+ local dot = Clamp(Vector(0, -1, 0):DotProduct(zAxis), 0, 1)
+
+ local glideAmount = dot// math.sin( dot * math.pi / 2 )
+
+ local glideVelocity = viewCoords.zAxis * math.abs(glideAmount) * self:GetAcceleration()
+
return glideVelocity
else
- // Don't allow a lot of lateral movement while flying
- move.x = Sign(move.x) * .1
-
+ // Not gliding: use normal ground movement, or air control if we're in the air
local transformedVertical = viewCoords:TransformVector( Vector(0, 0, move.z) )
-
+
local moveVelocity = viewCoords:TransformVector( move ) * self:GetAcceleration()
-
+
return moveVelocity
end
@@ -222,20 +253,12 @@ end
function Lerk:RedirectVelocity(redirectDir)
- local velocity = self:GetVelocity()
- if velocity.y <= 0 then
-
- local newVelocity = redirectDir * self:GetVelocity():GetLength()
- self:SetVelocity(newVelocity)
-
- else
-
- local zAxis = redirectDir//self:GetViewAngles():GetCoords().zAxis
- local xzLook = GetNormalizedVector(Vector(zAxis.x, 0, zAxis.z))
- local newVelocity = xzLook * velocity:GetLengthXZ() + Vector(0, velocity.y, 0)
- self:SetVelocity(newVelocity)
-
- end
+ local velocity = self:GetVelocity()
+ local xzSpeed = GetNormalizedVector(Vector(redirectDir.x, 0, redirectDir.z))
+ local ySpeed = 0
+
+ local newVelocity = redirectDir * velocity:GetLength() //+ Vector(0, ySpeed, 0)
+ self:SetVelocity(newVelocity)
end
@@ -245,16 +268,44 @@ function Lerk:PreUpdateMove(input, runningPrediction)
// If we're gliding, redirect velocity to whichever way we're looking
// so we get that cool soaring feeling from NS1
+ // Now with strafing and air brake
if not self:GetIsOnGround() then
-
- if self.gliding then
+
+ local move = GetNormalizedVector(input.move)
+ local viewCoords = self:GetViewAngles():GetCoords()
+ local redirectDir = self:GetViewAngles():GetCoords().zAxis
+ local velocity = GetNormalizedVector(self:GetVelocity())
- // If we're strafing, redirect velocity towards direction we're pressing
- // otherwise re-direct direction we're facing
- local redirectDir = self:GetViewAngles():GetCoords().zAxis
- self:RedirectVelocity(redirectDir)
+ if self.gliding then
+
+ // Glide forward, strafe left/right, or brake slowly
+ if (move.z ~= 0) then
- end
+ // Forward/Back key pressed - Glide in the facing direction
+ // Allow some backward acceleration and some strafing
+ move.z = Clamp(move.z, -0.05, 0)
+ move.x = Clamp(move.x, -0.5, 0.5)
+ redirectDir = redirectDir + viewCoords:TransformVector( move )
+
+ else
+
+ // Non forward/back-key gliding, zero download velocity
+ // Useful for maintaining height when attacking targets below
+ move.x = Clamp(move.x, -0.5, 0.5)
+ redirectDir = Vector(redirectDir.x, math.max(redirectDir.y, velocity.y, -0.01), redirectDir.z)
+ redirectDir = redirectDir + viewCoords:TransformVector( move )
+ redirectDir:Normalize()
+
+ end
+
+ // Limit max speed so strafing does not increase total velocity
+ if (redirectDir:GetLength() > 1) then
+ redirectDir:Normalize()
+ end
+
+ self:RedirectVelocity(redirectDir)
+
+ end
end
@@ -272,7 +323,7 @@ function Lerk:HandleAttacks(input)
dot = GetNormalizedVector(velocity):DotProduct(zAxis)
end
- self.gliding = (not self:GetIsOnGround() and self.flappedSinceLeftGround and (bit.band(input.commands, Move.Jump) ~= 0) and dot >= .8)
+ self.gliding = (not self:GetIsOnGround() and self.flappedSinceLeftGround and (bit.band(input.commands, Move.Jump) ~= 0) and dot >= .7)
end
@@ -296,25 +347,36 @@ end
function Lerk:Flap(input, velocity)
+ local lift = 0
local flapVelocity = Vector(0, 0, 0)
+
+ // Thrust forward or backward, or laterally
+ if (input.move:GetLength() > 0 )then
- // Thrust forward or backward
- if(input.move:GetLength() > 0) then
-
+ // Flapping backward and sideways generate very small amounts of thrust
+ // Allow full forward thrust, half lateral thrust, and minimal backward thrust
+ input.move.z = Clamp(input.move.z, -0.3, 1)
+ input.move.x = input.move.x * 0.5
+ if (input.move.x ~= 0) then
+ lift = Lerk.kFlapStraightUpImpulse * 0.5
+ end
flapVelocity = GetNormalizedVector(self:GetViewCoords():TransformVector( input.move )) * self:GetAcceleration() * Lerk.kFlapThrustMoveScalar
else
-
- // Get more lift when that's all we're doing
- flapVelocity.y = flapVelocity.y + Lerk.kFlapStraightUpImpulse
-
+ // Get more lift and slow down in the XZ directions when trying to flap straight up
+ lift = Lerk.kFlapStraightUpImpulse
+ flapVelocity = Vector(velocity.x, 0, velocity.z) * -0.1
end
- VectorCopy(velocity + flapVelocity, velocity)
+ flapVelocity.y = flapVelocity.y + lift
+
+ // Each flap reduces some of the previous velocity
+ // So we can change direction quickly by flapping
+ VectorCopy(velocity * 0.7 + flapVelocity, velocity)
// Play wing flap sound
Shared.PlaySound(self, Lerk.kFlapSound)
-
+
self.flappedSinceLeftGround = true
end
diff --git a/ns2/lua/LiveScriptActor_Server.lua b/ns2/lua/LiveScriptActor_Server.lua
index b46dc09..755ccc2 100644
--- a/ns2/lua/LiveScriptActor_Server.lua
+++ b/ns2/lua/LiveScriptActor_Server.lua
@@ -101,7 +101,14 @@ function LiveScriptActor:OnTakeDamage(damage, attacker, doer, point)
flinchParams[kEffectFilterDoerName] = doer:GetClassName()
end
- self:TriggerEffects("flinch", flinchParams)
+ // Don't flinch too often
+ local time = Shared.GetTime()
+ if self.lastFlinchEffectTime == nil or (time > (self.lastFlinchEffectTime + 1)) then
+
+ self:TriggerEffects("flinch", flinchParams)
+ self.lastFlinchEffectTime = time
+
+ end
// Apply directed impulse to physically simulated objects, according to amount of damage
if (self.physicsModel ~= nil and self.physicsType == Actor.PhysicsType.Dynamic) then
diff --git a/ns2/lua/LoopingSoundMixin.lua b/ns2/lua/LoopingSoundMixin.lua
new file mode 100644
index 0000000..426d00d
--- /dev/null
+++ b/ns2/lua/LoopingSoundMixin.lua
@@ -0,0 +1,154 @@
+// ======= Copyright © 2003-2011, Unknown Worlds Entertainment, Inc. All rights reserved. =======
+//
+// lua\LoopingSoundMixin.lua
+//
+// Created by: Charlie Cleveland (charlie@unknownworlds.com)
+//
+// Allows a looping sound to be tracked by a parent entity. Makes it it stops looping
+// when the parent dies or changes. Users of the mixin call PlayLoopingSound() and optionally
+// StopLoopingSound(), and GetLoopingEntityId(). Must provide OnStopLoopingSound().
+//
+// ========= For more information, visit us at http://www.unknownworlds.com =====================
+
+Script.Load("lua/FunctionContracts.lua")
+
+LoopingSoundMixin = { }
+LoopingSoundMixin.type = "LoopingSound"
+
+LoopingSoundMixin.expectedCallbacks =
+{
+ // Only called if sound was playing when StopLoopingSound() called
+ OnStopLoopingSound = "Called with parent when looping sound is stopped manually, or because entity was destroyed or changed.",
+}
+
+function LoopingSoundMixin.__prepareclass(toClass)
+
+ ASSERT(toClass.networkVars ~= nil, "LoopingSoundMixin expects the class to have network fields")
+
+ local addNetworkFields =
+ {
+ playingLoopingOnEntityId = "entityid",
+ }
+
+ for k, v in pairs(addNetworkFields) do
+ toClass.networkVars[k] = v
+ end
+
+end
+
+function LoopingSoundMixin:__initmixin()
+ self.playingLoopingOnEntityId = Entity.invalidId
+end
+
+function LoopingSoundMixin:OnInit()
+ self.playingLoopingOnEntityId = Entity.invalidId
+end
+
+function LoopingSoundMixin:StopLoopingSound()
+
+ if self.soundName ~= nil then
+
+ ASSERT(type(self.soundName) == "string")
+
+ local parent = Shared.GetEntity(self.playingLoopingOnEntityId)
+ if parent then
+
+ Shared.StopSound(parent, self.soundName)
+
+ end
+
+ // This case happens when the sound effect has been stopped by StopLoopingSound on
+ // the server, but was not predicted on the client (when a player dies for example).
+ if Client then
+
+ // In the case where the parent no longer exists, the engine will have automatically
+ // stopped the looping sound effect.
+ local clientParent = Shared.GetEntity(self.clientParentId)
+ if clientParent then
+ Shared.StopSound(clientParent, self.soundName)
+ end
+
+ self.clientParentId = nil
+
+ end
+
+ self:OnStopLoopingSound(parent)
+
+ // This indicates if sound is playing or not
+ self.soundName = nil
+
+ //self.playingLoopingOnEntityId = Entity.invalidId
+
+ end
+
+end
+
+// Returns boolean if sound was played. Don't play sound on same player if already playing.
+// If on new player, stop old sound and start new sound.
+function LoopingSoundMixin:PlayLoopingSound(parent, soundName)
+
+ ASSERT(parent ~= nil)
+ ASSERT(parent.isa)
+ ASSERT(parent:isa("Player"))
+ ASSERT(type(soundName) == "string")
+
+ if self.soundName ~= nil then
+
+ // Don't replay sound on existing
+ if parent:GetId() == self.playingLoopingOnEntityId then
+ return false
+ else
+ // Stop first if already playing
+ self:StopLoopingSound()
+ end
+
+ end
+
+ Shared.PlaySound(parent, soundName)
+
+ self.playingLoopingOnEntityId = parent:GetId()
+ self.soundName = soundName
+
+ // Store enough information for us to stop the sound in the case where
+ // the player dies.
+ if Client then
+ self.clientParentId = parent:GetId()
+ end
+
+ return true
+
+end
+
+function LoopingSoundMixin:GetLoopingEntityId()
+ return self.playingLoopingOnEntityId
+end
+
+function LoopingSoundMixin:OnEntityChange(oldId, newId)
+
+ // In case the parent is destroyed.
+ if oldId == self.playingLoopingOnEntityId then
+
+ self:StopLoopingSound()
+
+ end
+
+end
+
+function LoopingSoundMixin:OnDestroy()
+ self:StopLoopingSound()
+end
+
+function LoopingSoundMixin:GetIsLoopingSoundPlaying()
+ return (self.soundName ~= nil)
+end
+
+function LoopingSoundMixin:OnUpdate()
+
+ // If our parent goes away while we're playing, stop the sound
+ if self:GetIsLoopingSoundPlaying() and ((self.playingLoopingOnEntityId == Entity.invalidId) or (Shared.GetEntity(self.playingLoopingOnEntityId) == nil)) then
+
+ self:StopLoopingSound()
+
+ end
+
+end
diff --git a/ns2/lua/OptionsDialog.lua b/ns2/lua/OptionsDialog.lua
index c5f6b83..8825ac6 100644
--- a/ns2/lua/OptionsDialog.lua
+++ b/ns2/lua/OptionsDialog.lua
@@ -168,7 +168,7 @@ end
* windowed - true/false run in windowed mode
* invMouse - true/false (true == mouse is inverted)
*/
-function OptionsDialogUI_SetValues(nickname, mouseSens, screenResIdx, visualDetailIdx, soundVol, musicVol, windowed, invMouse)
+function OptionsDialogUI_SetValues(nickname, mouseSens, screenResIdx, visualDetailIdx, soundVol, musicVol, windowed, invMouse, voiceVol)
Client.SetOptionString( kNicknameOptionsKey, nickname )
@@ -182,6 +182,7 @@ function OptionsDialogUI_SetValues(nickname, mouseSens, screenResIdx, visualDeta
// Save sound and music options
OptionsDialogUI_SetSoundVolume( soundVol )
OptionsDialogUI_SetMusicVolume( musicVol )
+ OptionsDialogUI_SetVoiceVolume( voiceVol )
Client.SetOptionBoolean ( kFullscreenOptionsKey, not windowed )
diff --git a/ns2/lua/Player.lua b/ns2/lua/Player.lua
index 1321d56..f104cca 100644
--- a/ns2/lua/Player.lua
+++ b/ns2/lua/Player.lua
@@ -29,9 +29,6 @@ class 'Player' (LiveScriptActor)
Player.kTooltipSound = PrecacheAsset("sound/ns2.fev/common/tooltip")
Player.kToolTipInterval = 18
-Player.kMarineResReceivedSound = PrecacheAsset("sound/ns2.fev/marine/common/res_received")
-Player.kAlienResReceivedSound = PrecacheAsset("sound/ns2.fev/alien/common/res_received")
-
if (Server) then
Script.Load("lua/Player_Server.lua")
else
@@ -2115,7 +2112,7 @@ function Player:HandleButtons(input)
PROFILE("Player:HandleButtons")
- if (bit.band(input.commands, Move.Use) ~= 0) then
+ if (bit.band(input.commands, Move.Use) ~= 0) and not self.primaryAttackLastFrame and not self.secondaryAttackLastFrame then
self:Use(input.time)
end
diff --git a/ns2/lua/Player_Server.lua b/ns2/lua/Player_Server.lua
index 40165fc..00e47f2 100644
--- a/ns2/lua/Player_Server.lua
+++ b/ns2/lua/Player_Server.lua
@@ -184,10 +184,7 @@ function Player:AwardResForKill(target)
//self:GetTeam():SetTeamResources(self:GetTeam():GetTeamResources() + kKillTeamReward)
// Play sound for player and also our commanders
- local resReceivedSoundName = ConditionalValue(self:GetTeamType() == kAlienTeamType, Player.kAlienResReceivedSound, Player.kMarineResReceivedSound)
-
- Server.PlayPrivateSound(self, resReceivedSoundName, self, 1.0, Vector(0, 0, 0))
- self:GetTeam():PlayPrivateTeamSound(resReceivedSoundName, nil, true, self)
+ self:GetTeam():TriggerEffects("res_received")
end
diff --git a/ns2/lua/TargetCache.lua b/ns2/lua/TargetCache.lua
index b3c38ef..2832c9b 100644
--- a/ns2/lua/TargetCache.lua
+++ b/ns2/lua/TargetCache.lua
@@ -581,7 +581,7 @@ end
// Check if the target is possible.
//
function TargetSelector:_PossibleTarget(target)
- if target and self.attacker ~= target and target:GetIsAlive() and target:GetCanTakeDamage() then
+ if target and self.attacker ~= target and (target.GetIsAlive and target:GetIsAlive()) and target:GetCanTakeDamage() then
local origin = self.attacker:GetEyePos()
local possible = false
diff --git a/ns2/lua/Team.lua b/ns2/lua/Team.lua
index 522cad1..c4176a1 100644
--- a/ns2/lua/Team.lua
+++ b/ns2/lua/Team.lua
@@ -232,6 +232,15 @@ function Team:PlayPrivateTeamSound(soundName, origin, commandersOnly, excludePla
end
+function Team:TriggerEffects(eventName)
+
+ local function TriggerEffects(player)
+ player:TriggerEffects(eventName)
+ end
+
+ self:ForEachPlayer(TriggerEffects)
+end
+
function Team:SetFrozenState(state)
local function SetFrozen(player)
diff --git a/ns2/lua/Weapons/Alien/Bomb.lua b/ns2/lua/Weapons/Alien/Bomb.lua
index 488a481..5fd17cd 100644
--- a/ns2/lua/Weapons/Alien/Bomb.lua
+++ b/ns2/lua/Weapons/Alien/Bomb.lua
@@ -55,6 +55,7 @@ if (Server) then
// Do splash damage to structures and ARCs
local hitEntities = GetEntitiesForTeamWithinRange("Structure", GetEnemyTeamNumber(self:GetTeamNumber()), self:GetOrigin(), Bomb.kSplashRadius)
table.copy(GetEntitiesForTeamWithinRange("ARC", GetEnemyTeamNumber(self:GetTeamNumber()), self:GetOrigin(), Bomb.kSplashRadius), hitEntities, true)
+ table.copy(GetEntitiesForTeamWithinRange("MAC", GetEnemyTeamNumber(self:GetTeamNumber()), self:GetOrigin(), Bomb.kSplashRadius), hitEntities, true)
// Do damage to every target in range
RadiusDamage(hitEntities, self:GetOrigin(), Bomb.kSplashRadius, kBileBombDamage, self, false)
diff --git a/ns2/lua/Weapons/Alien/Spike.lua b/ns2/lua/Weapons/Alien/Spike.lua
index 1bfc77c..6a5af92 100644
--- a/ns2/lua/Weapons/Alien/Spike.lua
+++ b/ns2/lua/Weapons/Alien/Spike.lua
@@ -13,10 +13,6 @@ class 'Spike' (Projectile)
Spike.kMapName = "spike"
Spike.kModelName = PrecacheAsset("models/alien/lerk/lerk_view_spike.model")
-// Does full damage up close then falls off over time
-Spike.kMaxDamage = kSpikeMaxDamage
-Spike.kMinDamage = kSpikeMinDamage
-
// Seconds
Spike.kDamageFalloffInterval = 1
diff --git a/ns2/lua/Weapons/Alien/Spikes.lua b/ns2/lua/Weapons/Alien/Spikes.lua
index af07bed..3dc7c43 100644
--- a/ns2/lua/Weapons/Alien/Spikes.lua
+++ b/ns2/lua/Weapons/Alien/Spikes.lua
@@ -26,7 +26,15 @@ Spikes.kZoomedSensScalar = 0.25
Spikes.kSpikeEnergy = kSpikeEnergyCost
Spikes.kSnipeEnergy = kSpikesAltEnergyCost
Spikes.kSnipeDamage = kSpikesAltDamage
-Spikes.kSpread2Degrees = Vector( 0.01745, 0.01745, 0.01745 )
+Spikes.kRange = kSpikeMinDamageRange
+Spikes.kMinDamageRange = kSpikeMaxDamageRange
+Spikes.kMaxDamageRange = kSpikeMinDamageRange
+Spikes.kSpread = Math.Radians(6)
+Spikes.kNumSpikesOnSecondary = 5
+
+// Does full damage up close then falls off over the max distance
+Spikes.kMaxDamage = kSpikeMaxDamage
+Spikes.kMinDamage = kSpikeMinDamage
local networkVars =
{
@@ -95,77 +103,85 @@ function Spikes:PerformPrimaryAttack(player)
// Alternate view model animation to fire left then right
self.fireLeftNext = not self.fireLeftNext
+ /*
if not self.zoomedIn then
+ */
- self:FireSpikeProjectile(player)
-
+ self:FireSpike(player)
+
+ /*
else
// Snipe them!
self:PerformZoomedAttack(player)
end
+ */
player:SetActivityEnd(player:AdjustFuryFireDelay(self:GetPrimaryAttackDelay()))
return true
end
-function Spikes:FireSpikeProjectile(player)
+function Spikes:FireSpike(player)
- // On server, create projectile
- if(Server) then
+ local viewAngles = player:GetViewAngles()
+ local viewCoords = viewAngles:GetCoords()
- // trace using view coords, but back off the given distance to make sure we don't miss any walls
- local backOffDist = 0.5
- // fire from one meter in front of the lerk, to avoid the lerk flying into his own projectils (the projectile
- // will only start moving on the NEXT tick, and the lerk might be updated before the projectile. considering that
- // a lerk has a topspeed of 5-10m/sec, and a slow server update might be 100ms, you are looking at a lerk movement
- // per tick of 0.5-1m ... 1m should be good enough.
- local firePointOffs = 1.0
- // seems to be a bug in trace; make sure any entity indicate as hit are inside this range.
- local maxTraceLen = backOffDist + firePointOffs
+ local startPoint = player:GetEyePos()
- local viewCoords = player:GetViewAngles():GetCoords()
- local alternate = (self.fireLeftNext and -.1) or .1
- local firePoint = player:GetEyePos() + viewCoords.zAxis * firePointOffs - viewCoords.yAxis * .1 + viewCoords.xAxis * alternate
+ // Filter ourself out of the trace so that we don't hit ourselves.
+ local filter = EntityFilterTwo(player, self)
+
+ if Client then
+ DbgTracer.MarkClientFire(player, startPoint)
+ end
+
+ // Calculate spread for each shot, in case they differ
+ local randomAngle = NetworkRandom() * math.pi * 2
+ local randomRadius = NetworkRandom() * NetworkRandom() * math.tan(Spikes.kSpread)
+ local fireDirection = viewCoords.zAxis + (viewCoords.xAxis * math.cos(randomAngle) + viewCoords.yAxis * math.sin(randomAngle)) * randomRadius
+ fireDirection:Normalize()
+
+ local endPoint = startPoint + fireDirection * Spikes.kRange
+ local trace = Shared.TraceRay(startPoint, endPoint, PhysicsMask.Bullets, filter)
+
+ if Server then
+ Server.dbgTracer:TraceBullet(player, startPoint, trace)
+ end
+
+ if trace.fraction < 1 and trace.entity then
+
+ if trace.entity:isa("LiveScriptActor") and Server and GetGamerules():CanEntityDoDamageTo(self, trace.entity) then
- // To avoid the lerk butting his face against a wall and shooting blindly, trace and move back the firepoint
- // if hitting a wall
- local startTracePoint = player:GetEyePos() - viewCoords.zAxis * backOffDist + viewCoords.xAxis * alternate
- local trace = Shared.TraceRay(startTracePoint, firePoint, PhysicsMask.Bullets, EntityFilterOne(player))
- if trace.fraction ~= 1 and (trace.entity == nil or (trace.entity:GetOrigin() - startTracePoint):GetLength() < maxTraceLen) then
- local offset = math.max(backOffDist, trace.fraction * maxTraceLen)
- firePoint = startTracePoint + (viewCoords.zAxis * offset)
+ // Do max damage for short time and then fall off over time to encourage close quarters combat instead of
+ // hanging back and sniping
+ local damageScalar = ConditionalValue(player:GetHasUpgrade(kTechId.Piercing), kPiercingDamageScalar, 1)
+ local distToTarget = (trace.endPoint - startPoint):GetLength()
+
+ // Have damage increase to reward close combat
+ local damageDistScalar = Clamp(1 - (distToTarget / Spikes.kRange), 0, 1)
+ local damage = Spikes.kMinDamage + damageDistScalar * (Spikes.kMaxDamage - Spikes.kMinDamage)
+ local direction = (trace.endPoint - startPoint):GetUnit()
+ trace.entity:TakeDamage(damage * damageScalar, player, self, self:GetOrigin(), direction)
+
end
-
- local spike = CreateEntity(Spike.kMapName, firePoint, player:GetTeamNumber())
-
- // Add slight randomness to start direction. Gaussian distribution.
- local x = (NetworkRandom() - .5) + (NetworkRandom() - .5)
- local y = (NetworkRandom() - .5) + (NetworkRandom() - .5)
-
- local spread = Spikes.kSpread2Degrees
- local direction = viewCoords.zAxis + x * spread.x * viewCoords.xAxis + y * spread.y * viewCoords.yAxis
- spike:SetVelocity(direction * 20)
-
- spike:SetOrientationFromVelocity()
-
- spike:SetGravityEnabled(true)
-
- // Set spike parent to player so we don't collide with ourselves and so we
- // can attribute a kill to us
- spike:SetOwner(player)
-
- spike:SetIsVisible(true)
-
- spike:SetUpdates(true)
-
- spike:SetDeathIconIndex(self:GetDeathIconIndex())
-
- end
+ // If we are far away from our target, trigger a private sound so we can hear we hit something
+ if (trace.endPoint - player:GetOrigin()):GetLength() > 5 then
+
+ player:TriggerEffects("hit_effect_local", {surface = trace.surface})
+
+ end
+
+ end
+
+ // Play hit effects on ground, on target or in the air if it missed
+ local impactPoint = trace.endPoint
+ local surfaceName = trace.surface
+ TriggerHitEffects(self, trace.entity, impactPoint, surfaceName)
+
end
function Spikes:PerformZoomedAttack(player)
@@ -199,8 +215,6 @@ function Spikes:PerformZoomedAttack(player)
player:SetActivityEnd(player:AdjustFuryFireDelay(Spikes.kSnipeDelay))
-
-
end
function Spikes:SetZoomState(player, zoomedIn)
@@ -227,8 +241,13 @@ function Spikes:PerformSecondaryAttack(player)
if(player:GetCanNewActivityStart()) then
- self:SetZoomState(player, not self.zoomedIn)
-
+ //self:SetZoomState(player, not self.zoomedIn)
+
+ // Fire a burst of bullets
+ for index = 1, Spikes.kNumSpikesOnSecondary do
+ self:FireSpike(player)
+ end
+
player:SetActivityEnd(player:AdjustFuryFireDelay(Spikes.kZoomDelay))
return true
@@ -276,7 +295,7 @@ function Spikes:GetSecondaryAttackRequiresPress()
end
function Spikes:GetSecondaryEnergyCost(player)
- return 0
+ return kSpikesAltEnergyCost
end
function Spikes:GetEffectParams(tableParams)
diff --git a/ns2/lua/Weapons/Alien/SporeCloud.lua b/ns2/lua/Weapons/Alien/SporeCloud.lua
index 870dd9c..86057e8 100644
--- a/ns2/lua/Weapons/Alien/SporeCloud.lua
+++ b/ns2/lua/Weapons/Alien/SporeCloud.lua
@@ -13,15 +13,18 @@ class 'SporeCloud' (ScriptActor)
SporeCloud.kMapName = "sporecloud"
// Damage per think interval (from NS1)
-SporeCloud.kThinkInterval = .5 // From NS1
-SporeCloud.kDamage = kSporesDamagePerSecond * SporeCloud.kThinkInterval
-SporeCloud.kDamageRadius = 3 // 5.7 in NS1
-SporeCloud.kLifetime = 6.0 // From NS1
+SporeCloud.kThinkInterval = .25 // .5 in NS1, reducing to make sure sprinting machines take damage
// Keep table of entities that have been hurt by spores to make
// spores non-stackable. List of {entityId, time} pairs.
gHurtBySpores = {}
+SporeCloud.networkVars =
+{
+ radius = "float",
+ altMode = "boolean",
+}
+
function GetEntityRecentlyHurt(entityId, time)
for index, pair in ipairs(gHurtBySpores) do
@@ -57,8 +60,8 @@ end
// Have damage radius grow to maximum non-instantly
function SporeCloud:GetDamageRadius()
- local scalar = Clamp(((Shared.GetTime() - self.createTime) / SporeCloud.kLifetime) * 12, 0, 1)
- return scalar * SporeCloud.kDamageRadius
+ local scalar = Clamp((Shared.GetTime() - self.createTime) * 3, 0, 1)
+ return scalar * self.radius
end
@@ -84,7 +87,7 @@ function SporeCloud:OnThink()
local trace = Shared.TraceRay(self:GetOrigin(), targetPosition, PhysicsMask.Bullets, filterNonDoors)
if trace.fraction == 1.0 or trace.entity == entity then
- entity:TakeDamage(SporeCloud.kDamage, self:GetOwner(), self)
+ entity:TakeDamage(self.damage * SporeCloud.kThinkInterval, self:GetOwner(), self)
// Spores can't hurt this entity for SporeCloud.kThinkInterval
SetEntityRecentlyHurt(entity:GetId())
@@ -97,7 +100,7 @@ function SporeCloud:OnThink()
end
- if Shared.GetTime() > (self.createTime + SporeCloud.kLifetime) then
+ if Shared.GetTime() > (self.createTime + self.lifetime) then
DestroyEntity(self)
else
self:SetNextThink(SporeCloud.kThinkInterval)
@@ -109,21 +112,34 @@ function SporeCloud:OnInit()
ScriptActor.OnInit(self)
- self:SetUpdates(true)
-
if Server then
self:SetNextThink(SporeCloud.kThinkInterval)
end
/* For debugging damage radius */
- /*if Client then
+ /*
+ if Client then
self:SetUpdates(true)
- end*/
+ end
+ */
self.createTime = Shared.GetTime()
+ self.altMode = false
end
+function SporeCloud:SetLifetime(lifetime)
+ self.lifetime = lifetime
+end
+
+function SporeCloud:SetDamage(damage)
+ self.damage = damage
+end
+
+function SporeCloud:SetRadius(radius)
+ self.radius = radius
+end
+
/* For debugging damage radius */
/*
function SporeCloud:OnUpdate(deltaTime)
@@ -131,7 +147,19 @@ function SporeCloud:OnUpdate(deltaTime)
local damageRadius = self:GetDamageRadius()
DebugCapsule(self:GetOrigin(), self:GetOrigin(), damageRadius, 0, deltaTime)
end
+end*/
+
+function SporeCloud:GetEffectParams(tableParams)
+
+ ScriptActor.GetEffectParams(self, tableParams)
+
+ tableParams[kEffectFilterInAltMode] = self.altMode
+
+end
+
+// Used on client to play effects for either dust cloud or regular cloud
+function SporeCloud:SetAltMode(altMode)
+ self.altMode = altMode
end
-*/
-Shared.LinkClassToMap("SporeCloud", SporeCloud.kMapName, {} )
+Shared.LinkClassToMap("SporeCloud", SporeCloud.kMapName, SporeCloud.networkVars )
diff --git a/ns2/lua/Weapons/Alien/Spores.lua b/ns2/lua/Weapons/Alien/Spores.lua
index e1a258c..9d53967 100644
--- a/ns2/lua/Weapons/Alien/Spores.lua
+++ b/ns2/lua/Weapons/Alien/Spores.lua
@@ -8,40 +8,110 @@
// ========= For more information, visit us at http://www.unknownworlds.com =====================
Script.Load("lua/Weapons/Alien/Ability.lua")
Script.Load("lua/Weapons/Alien/SporeCloud.lua")
+Script.Load("lua/LoopingSoundMixin.lua")
class 'Spores' (Ability)
Spores.kMapName = "spores"
-Spores.kDelay = kSporesFireDelay
Spores.kSwitchTime = .5
+Spores.kSporeDustCloudLifetime = 12.0
+Spores.kSporeCloudLifetime = 6.0 // From NS1
+Spores.kSporeDustCloudDPS = kSporesDustDamagePerSecond
+Spores.kSporeCloudDPS = kSporesDamagePerSecond
+Spores.kSporeDustCloudRadius = 1.5
+Spores.kSporeCloudRadius = 3 // 5.7 in NS1
+Spores.kLoopingDustSound = PrecacheAsset("sound/ns2.fev/alien/lerk/spore_spray")
// Points per second
Spores.kDamage = kSporesDamagePerSecond
local networkVars = {
- sporePoseParam = "compensated float"
+ sporePoseParam = "compensated float",
}
+PrepareClassForMixin(Spores, LoopingSoundMixin)
+
function Spores:OnCreate()
Ability.OnCreate(self)
self.sporePoseParam = 0
end
+function Spores:OnInit()
+ Ability.OnInit(self)
+ InitMixin(self, LoopingSoundMixin)
+end
+
function Spores:GetEnergyCost(player)
- return kSporesEnergyCost
+ return kSporesDustEnergyCost
+end
+
+/*
+function Spores:GetSecondaryEnergyCost(player)
+ return kSporesCloudEnergyCost
end
+*/
function Spores:GetPrimaryAttackDelay()
- return Spores.kDelay
+ return kSporesDustFireDelay
end
+/*
+function Spores:GetSecondaryAttackDelay()
+ return kSporesCloudFireDelay
+end
+*/
+
function Spores:GetIconOffsetY(secondary)
return kAbilityOffset.Spores
end
-function Spores:PerformPrimaryAttack(player)
+local function CreateSporeCloud(origin, player, lifetime, damage, radius)
+
+ local spores = CreateEntity(SporeCloud.kMapName, origin, player:GetTeamNumber())
+ spores:SetOwner(player)
+ spores:SetLifetime(lifetime)
+ spores:SetDamage(damage)
+ spores:SetRadius(radius)
+
+ return spores
+
+end
+
+function Spores:PerformPrimaryAttack(player)
+
+ // Create long-lasting spore cloud near player that can be used to prevent marines from passing through an area
player:SetActivityEnd(player:AdjustFuryFireDelay(self:GetPrimaryAttackDelay()))
+
+ if Server then
+
+ local origin = player:GetModelOrigin()
+ local sporecloud = CreateSporeCloud(origin, player, Spores.kSporeDustCloudLifetime, Spores.kSporeDustCloudDPS, Spores.kSporeDustCloudRadius)
+ if not self:GetIsLoopingSoundPlaying() then
+ self:PlayLoopingSound(player, Spores.kLoopingDustSound)
+ end
+
+ end
+
+ return true
+
+end
+
+function Spores:OnStopLoopingSound(parent)
+end
+
+function Spores:OnPrimaryAttackEnd(player)
+
+ Ability.OnPrimaryAttackEnd(self, player)
+ self:StopLoopingSound(player)
+
+end
+
+// Removed for now to keep spore dust trails distinct
+/*
+function Spores:PerformSecondaryAttack(player)
+
+ player:SetActivityEnd(player:AdjustFuryFireDelay(self:GetSecondaryAttackDelay()))
// Trace instant line to where it should hit
local viewAngles = player:GetViewAngles()
@@ -54,16 +124,15 @@ function Spores:PerformPrimaryAttack(player)
if Server then
local spawnPoint = trace.endPoint + (trace.normal * 0.5)
- local spores = CreateEntity(SporeCloud.kMapName, spawnPoint, player:GetTeamNumber())
- spores:SetOwner(player)
-
- self:TriggerEffects("spores", {effecthostcoords = Coords.GetTranslation(spawnPoint) })
+ local sporecloud = CreateSporeCloud(spawnPoint, player, Spores.kSporeCloudLifetime, Spores.kSporeCloudDPS, Spores.kSporeCloudRadius)
+ sporecloud:SetAltMode(true)
end
return true
end
+*/
function Spores:GetHUDSlot()
return 2
diff --git a/ns2/lua/Weapons/Weapon.lua b/ns2/lua/Weapons/Weapon.lua
index 3a1a0ce..2441cba 100644
--- a/ns2/lua/Weapons/Weapon.lua
+++ b/ns2/lua/Weapons/Weapon.lua
@@ -341,6 +341,11 @@ function Weapon:OnUpdate(deltaTime)
end
end
+
+ // Handle dropping on the client
+ if Client then
+ self:UpdateDropped()
+ end
end
diff --git a/ns2/lua/Weapons/Weapon_Client.lua b/ns2/lua/Weapons/Weapon_Client.lua
index 294a8b2..fad4775 100644
--- a/ns2/lua/Weapons/Weapon_Client.lua
+++ b/ns2/lua/Weapons/Weapon_Client.lua
@@ -9,6 +9,19 @@
function Weapon:Dropped(prevOwner)
end
+function Weapon:UpdateDropped()
+
+ if self:GetPhysicsType() == Actor.PhysicsType.DynamicServer and not self.dropped then
+
+ self:Dropped(nil)
+ self.dropped = true
+
+ elseif self:GetPhysicsType() == Actor.PhysicsType.None then
+ self.dropped = false
+ end
+
+end
+
function Weapon:CreateWeaponEffect(player, playerAttachPointName, entityAttachPointName, cinematicName)
if not player:GetIsThirdPerson() then
diff --git a/ns2/lua/ns2.deproj b/ns2/lua/ns2.deproj
index 218647e..8aee190 100644
--- a/ns2/lua/ns2.deproj
+++ b/ns2/lua/ns2.deproj
@@ -42,9 +42,6 @@
Armory_Server.lua
-
- balance.lua
-
Structure.lua
@@ -486,9 +483,6 @@
AlienSpectator.lua
-
- mac.lua
-
AlienBuy_Client.lua
@@ -993,4 +987,10 @@
..\..\core\lua\MapEntityLoader.lua
+
+ Balance.lua
+
+
+ MAC.lua
+