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 +