diff --git a/Classic/scripts/LakRabbitGame.cs b/Classic/scripts/LakRabbitGame.cs index 815cd78..5d9d1a4 100644 --- a/Classic/scripts/LakRabbitGame.cs +++ b/Classic/scripts/LakRabbitGame.cs @@ -700,13 +700,17 @@ function Armor::damageObject(%data, %targetObject, %sourceObject, %position, %am %special !$= "" ? %special : "", %distance, %vel, - %accuracy ); + %accuracy); if(%sourceObject.holdingFlag && %points >= 75) { missileEveryone(%sourceObject); %sound = '~wfx/Bonuses/horz_straipass2_heist.wav'; } + else if(%points >= 100) + { + %sound = '~wfx/Misc/MA1.wav'; + } Game.recalcScore(%sourceObject.client); } diff --git a/Classic/scripts/autoexec/AntiLouExploitFixes.cs b/Classic/scripts/autoexec/AntiLouExploitFixes.cs index 17960f1..9191ba0 100644 --- a/Classic/scripts/autoexec/AntiLouExploitFixes.cs +++ b/Classic/scripts/autoexec/AntiLouExploitFixes.cs @@ -367,6 +367,13 @@ function DeactivatePackage(%this) parent::DeactivatePackage(%this); } +// Prevents clients from being vulnerable to crashing via NULL voice exploit +function alxGetWaveLen(%wavFile) { + if ( strstr( %wavFile , ".wav" ) == -1 ) return $MaxMessageWavLength + 1; + echo("Length check: " @ %wavFile); + parent::alxGetWaveLen(%wavFile); +} + }; diff --git a/Classic/scripts/autoexec/AntiPack.cs b/Classic/scripts/autoexec/AntiPack.cs index a8bd290..1994616 100644 --- a/Classic/scripts/autoexec/AntiPack.cs +++ b/Classic/scripts/autoexec/AntiPack.cs @@ -18,7 +18,7 @@ $AntiPackIncludeShield = 0; function CheckAntiPack( %game ) { //CTF only - if( $Host::AntiPackEnable && $CurrentMissionType $= "CTF" && !$Host::TournamentMode ) + if( $Host::AntiPackEnable ) { //echo("TotalTeamPlayerCount " @ $TotalTeamPlayerCount); //echo("AntiPackPlayerCount " @ $AntiPackPlayerCount); diff --git a/Classic/scripts/autoexec/Autobalance.cs b/Classic/scripts/autoexec/Autobalance.cs index fb82209..0a57f12 100644 --- a/Classic/scripts/autoexec/Autobalance.cs +++ b/Classic/scripts/autoexec/Autobalance.cs @@ -9,7 +9,7 @@ // How far behind littleTeam must be to use All Mode. // Meaning picking from a pool of all players on the bigTeam instead of just the lowest scoring player. // 400 equals 400 points. 4 caps behind. -$AllModeThreshold = 400; +$AllModeThreshold = 300; // Run from TeamBalanceNotify.cs via UnbalancedSound( %game ) @@ -28,18 +28,13 @@ function Autobalance( %game, %AutobalanceSafetynetTrys ) %team1difference = $TeamRank[1, count] - $TeamRank[2, count]; %team2difference = $TeamRank[2, count] - $TeamRank[1, count]; - //If even, stop. - if( %team1difference == 1 || %team2difference == 1 || $TeamRank[1, count] == $TeamRank[2, count] ) - { - //Reset TBN - ResetTBNStatus(); - return; - } //Determine bigTeam - else if( %team1difference >= 2 ) + if( %team1difference >= 2 ) %bigTeam = 1; else if( %team2difference >= 2 ) %bigTeam = 2; + else + return; %littleTeam = ( %bigTeam == 1 ) ? 2 : 1; diff --git a/Classic/scripts/autoexec/GetTeamCounts.cs b/Classic/scripts/autoexec/GetTeamCounts.cs index 36c2d3e..d0aca39 100644 --- a/Classic/scripts/autoexec/GetTeamCounts.cs +++ b/Classic/scripts/autoexec/GetTeamCounts.cs @@ -20,7 +20,7 @@ function CreateServer( %mission, %missionType ) { parent::CreateServer( %mission, %missionType ); //Call for a GetTeamCount update - GetTeamCounts( %game, %client, %respawn ); + GetTeamCounts(%game); // Set when server starts // Used to reset timelimit (if voted) when map changes @@ -37,46 +37,31 @@ function CreateServer( %mission, %missionType ) if (!isActivePackage(StartTeamCounts)) activatePackage(StartTeamCounts); -function GetTeamCounts( %game, %client, %respawn ) +function GetTeamCounts(%game) { switch$($GetCountsStatus) { case UPDATE: - //Get teamcounts if($countdownStarted && $MatchStarted ) { - //Team Count code by Keen - $PlayerCount[0] = 0; - $PlayerCount[1] = 0; - $PlayerCount[2] = 0; - - for(%i = 0; %i < ClientGroup.getCount(); %i++) + //Variables + $TotalTeamPlayerCount = $TeamRank[1, count] + $TeamRank[2, count]; + $AllPlayerCount = $HostGamePlayerCount; + + //echo("$PlayerCount[0] " @ $HostGamePlayerCount - ($TeamRank[1, count] + $TeamRank[2, count])); + //echo("$PlayerCount[1] " @ $TeamRank[1, count]); + //echo("$PlayerCount[2] " @ $TeamRank[2, count]); + + if( !$Host::TournamentMode ) { - %client = ClientGroup.getObject(%i); - - //if(!%client.isAIControlled()) - $PlayerCount[%client.team]++; + if( $CurrentMissionType $= "CTF" ) + { + NBRStatusNotify(%game); + CheckAntiPack(%game); + } + TeamBalanceNotify(%game); } - //echo ("$PlayerCount[0] " @ $PlayerCount[0]); - //echo ("$PlayerCount[1] " @ $PlayerCount[1]); - //echo ("$PlayerCount[2] " @ $PlayerCount[2]); - - //Amount of players on teams - $TotalTeamPlayerCount = $PlayerCount[1] + $PlayerCount[2]; - //Amount of all players including observers - $AllPlayerCount = $PlayerCount[1] + $PlayerCount[2] + $PlayerCount[0]; - //Difference Variables - %team1difference = $PlayerCount[1] - $PlayerCount[2]; - %team2difference = $PlayerCount[2] - $PlayerCount[1]; - - //Start Base Rape Notify - schedule(500, 0, "NBRStatusNotify", %game); - //Start Team Balance Notify - schedule(1000, 0, "TeamBalanceNotify", %game, %team1difference, %team2difference); - //Start AntiCloak - schedule(1500, 0, "CheckAntiPack", %game); - //Set so counter wont run when it doesnt need to. $GetCountsStatus = "IDLE"; } diff --git a/Classic/scripts/autoexec/MemPatches.cs b/Classic/scripts/autoexec/MemPatches.cs index 9c20772..db77650 100644 --- a/Classic/scripts/autoexec/MemPatches.cs +++ b/Classic/scripts/autoexec/MemPatches.cs @@ -24,18 +24,4 @@ function suppressTraversalRootPatch() memPatch("56AD8A", "90909090909090909090909090909090909090909090"); memPatch("56D114", "90909090909090909090909090909090909090909090"); $tvpatched = 1; -} - -// Netrate patch by bahke -// 32 packets per second - -$pref::Net::PacketSize = $Host::ClassicPacketSize; - -memPatch("A3A100","5052BA00000000B8000000005150526800000000E8C7D6B4FF5A585981C20100000039C27CE65A58E95F8CB8FF"); -memPatch("A3A200","5052BA00000000B8000000005150526800000000E8C7D5B4FF5A585981C20100000039C27CE65A58E9FC8AB8FF"); -memPatch("5C2D22","E9D97447009090"); -memPatch("5C2D85","E9767347009090"); -memPatch("0058665C","9090909090909090"); -memPatch("00586682","90909090909090909090"); -memPatch("005866AB","90909090909090909090"); -memPatch("58781A","EB0C"); \ No newline at end of file +} \ No newline at end of file diff --git a/Classic/scripts/autoexec/NoBaseRape.cs b/Classic/scripts/autoexec/NoBaseRape.cs index e93b61a..a0d8460 100644 --- a/Classic/scripts/autoexec/NoBaseRape.cs +++ b/Classic/scripts/autoexec/NoBaseRape.cs @@ -1,27 +1,26 @@ package NoBaseRape { -//From Evolution MOD -//Modified for our needs +// From Evolution MOD +// Modified for our needs function StaticShapeData::damageObject(%data, %targetObject, %sourceObject, %position, %amount, %damageType) { //echo( %targetObject.getDataBlock().getClassName() ); //echo( %targetObject.getDataBlock().getName() ); - + %targetname = %targetObject.getDataBlock().getName(); - + //Used on some maps to make invs invincible if( %targetObject.invincible && %targetname $= "StationInventory" ) return; - + if(!$Host::TournamentMode && $Host::NoBaseRapeEnabled && $Host::NoBaseRapePlayerCount > $TotalTeamPlayerCount) - { + { if( %targetname $= "GeneratorLarge" || %targetname $= "StationInventory" || %targetname $= "SolarPanel" ) { //Notify only if asset is on other team if( %targetObject.team !$= %sourceObject.team ) - NBRAssetSound( %game, %sourceObject ); - + NBRAssetMessage(%sourceObject); return; } } @@ -33,4 +32,19 @@ function StaticShapeData::damageObject(%data, %targetObject, %sourceObject, %pos // Prevent package from being activated if it is already if (!isActivePackage(NoBaseRape)) - activatePackage(NoBaseRape); \ No newline at end of file + activatePackage(NoBaseRape); + + +// Message when a player hits a protected enemy asset +function NBRAssetMessage(%sourceObject) +{ + if($CurrentMissionType $= "CTF" && $Host::EnableNoBaseRapeNotify ) + { + %timeDif = getSimTime() - %sourceObject.NBRTime; + if(%timeDif > 10000 || !%sourceObject.NBRTime) + { + messageClient(%sourceObject.client, 'MsgNoBaseRapeNotify', '\c2No Base Rape is enabled until %1 players.', $Host::NoBaseRapePlayerCount ); + %sourceObject.NBRTime = getSimTime(); + } + } +} diff --git a/Classic/scripts/autoexec/NoBaseRapeNotify.cs b/Classic/scripts/autoexec/NoBaseRapeNotify.cs index fc7542c..82dfaf5 100644 --- a/Classic/scripts/autoexec/NoBaseRapeNotify.cs +++ b/Classic/scripts/autoexec/NoBaseRapeNotify.cs @@ -9,7 +9,7 @@ // Called in GetTeamCounts.cs function NBRStatusNotify( %game ) { - if( $CurrentMissionType $= "CTF" && $Host::EnableNoBaseRapeNotify && !$Host::TournamentMode && $Host::NoBaseRapeEnabled ) + if( $Host::EnableNoBaseRapeNotify && $Host::NoBaseRapeEnabled ) { //On if( $Host::NoBaseRapePlayerCount > $TotalTeamPlayerCount ) @@ -59,22 +59,3 @@ if (!isActivePackage(ResetNBRNotify)) activatePackage(ResetNBRNotify); -// This function is at StaticShapeData::damageObject(%data, %targetObject, %sourceObject, %position, %amount, %damageType) in the staticshape.ovl in evoClassic.vl2 -// Plays a sound when a player hits a protected enemy asset -function NBRAssetSound( %game, %sourceObject ) -{ - //Wont play again until the schedule is done - if(!isEventPending(%sourceObject.NBRAssetSoundSchedule) && $CurrentMissionType $= "CTF" && $Host::EnableNoBaseRapeNotify && !$Host::TournamentMode && $Host::NoBaseRapeEnabled ) - { - messageClient(%sourceObject.client, 'MsgNoBaseRapeNotify', '\c2No Base Rape is enabled until %1 players.', $Host::NoBaseRapePlayerCount ); - %sourceObject.NBRAssetSoundSchedule = schedule(10000, 0, "ResetNBRAssetSound", %sourceObject ); - } -} -// Reset -function ResetNBRAssetSound( %sourceObject ) -{ - if(isEventPending(%sourceObject.NBRAssetSoundSchedule)) - cancel(%sourceObject.NBRAssetSoundSchedule); -} - - diff --git a/Classic/scripts/autoexec/TeamBalanceNotify.cs b/Classic/scripts/autoexec/TeamBalanceNotify.cs index 01200f9..f84005f 100644 --- a/Classic/scripts/autoexec/TeamBalanceNotify.cs +++ b/Classic/scripts/autoexec/TeamBalanceNotify.cs @@ -12,27 +12,30 @@ // Called in GetTeamCounts.cs -function TeamBalanceNotify( %game, %team1difference, %team2difference ) +function TeamBalanceNotify(%game) { - if( Game.numTeams > 1 && $TotalTeamPlayerCount !$= 0 && !$Host::TournamentMode ) + if( Game.numTeams > 1 && $TotalTeamPlayerCount !$= 0 ) { - //echo ("%Team1Difference " @ %Team1Difference); - //echo ("%Team2Difference " @ %Team2Difference); - //Uneven - if( $PlayerCount[1] !$= $PlayerCount[2] ) + if($TeamRank[1, count] !$= $TeamRank[2, count]) { + %team1difference = $TeamRank[1, count] - $TeamRank[2, count]; + %team2difference = $TeamRank[2, count] - $TeamRank[1, count]; + + //echo("%Team1Difference " @ %team1difference); + //echo("%Team2Difference " @ %team2difference); + if( %team1difference >= 2 || %team2difference >= 2 ) //Teams are unbalanced { if( $TBNStatus !$= "NOTIFY" ) //Stops any new schedules $TBNStatus = "UNBALANCED"; } else - //Means teams arnt even, but arnt so uneven to do anything about. Meaning a team is a man down. 6vs7, 4vs3 etc + //Man down. 6vs7, 4vs3 etc $TBNStatus = "UNEVEN"; } //Teams are even - else if( $PlayerCount[1] == $PlayerCount[2] && $TBNStatus !$= "PLAYEDEVEN" ) + else if($TeamRank[1, count] == $TeamRank[2, count] && $TBNStatus !$= "PLAYEDEVEN" ) $TBNStatus = "EVEN"; switch$($TBNStatus) @@ -63,49 +66,33 @@ function NotifyUnbalanced( %game ) { if(isEventPending($NotifySchedule)) cancel($NotifySchedule); + + if( $TBNStatus !$= "NOTIFY" ) //If Status has changed to EVEN or anything else (GameOver reset). + return; + + //Difference Variables + %team1difference = $TeamRank[1, count] - $TeamRank[2, count]; + %team2difference = $TeamRank[2, count] - $TeamRank[1, count]; - if( $TBNStatus $= "NOTIFY" ) //If Status has changed to EVEN or anything else. - { - //Team Count code by Keen - $PlayerCount[0] = 0; - $PlayerCount[1] = 0; - $PlayerCount[2] = 0; - - for(%i = 0; %i < ClientGroup.getCount(); %i++) + if( %team1difference >= 2 || %team2difference >= 2 ) + { + //Autobalance Warning + if( $Host::EnableAutobalance ) { - %client = ClientGroup.getObject(%i); - - //if(!%client.isAIControlled()) - $PlayerCount[%client.team]++; + messageAll('MsgTeamBalanceNotify', '\c1Teams are unbalanced: \c0Autobalance Initializing.~wgui/vote_nopass.wav'); + $AutoBalanceSchedule = schedule(30000, 0, "Autobalance", %game ); } - - //Difference Variables - %team1difference = $PlayerCount[1] - $PlayerCount[2]; - %team2difference = $PlayerCount[2] - $PlayerCount[1]; - - if( %team1difference == 1 || %team2difference == 1 || $PlayerCount[1] == $PlayerCount[2] ) - { - ResetTBNStatus(); - return; - } - //Continue - else if( %team1difference >= 2 || %team2difference >= 2 ) - { - //Autobalance Warning - if( $Host::EnableAutobalance ) - { - messageAll('MsgTeamBalanceNotify', '\c1Teams are unbalanced: \c0Autobalance Initializing.~wgui/vote_nopass.wav'); - $AutoBalanceSchedule = schedule(30000, 0, "Autobalance", %game ); - } - //If Autobalance is disabled, message only. - else if( $Host::EnableTeamBalanceNotify ) - { - messageAll('MsgTeamBalanceNotify', '\c1Teams are unbalanced: \c0%1 vs %2 with %3 observers.~wgui/vote_nopass.wav', $PlayerCount[1], $PlayerCount[2], $PlayerCount[0] ); - schedule(13000, 0, "ResetTBNStatus"); - schedule(15000, 0, "ResetGetCountsStatus"); - } + //If Autobalance is disabled, message only. + else if( $Host::EnableTeamBalanceNotify ) + { + %observers = $HostGamePlayerCount - ($TeamRank[1, count] + $TeamRank[2, count]); + messageAll('MsgTeamBalanceNotify', '\c1Teams are unbalanced: \c0%1 vs %2 with %3 observers.~wgui/vote_nopass.wav', $TeamRank[1, count], $TeamRank[2, count], %observers ); + schedule(13000, 0, "ResetTBNStatus"); + schedule(15000, 0, "ResetGetCountsStatus"); } } + else + ResetTBNStatus(); } // Reset TBNStatus diff --git a/Classic/scripts/defaultGame.cs b/Classic/scripts/defaultGame.cs index 8faef77..6321a9f 100644 --- a/Classic/scripts/defaultGame.cs +++ b/Classic/scripts/defaultGame.cs @@ -1210,7 +1210,7 @@ function cmdAutoKickObserver(%client, %key) // Edit GG if ( isObject( %client ) ) { - messageAll('MsgAdminForce', '\c2%1 has left the game. (Observer Timeout)', %client.nameBase); + messageAll('MsgAdminForce', '\c2%1 has left the game. (Observer Timeout)', %client.name); %client.setDisconnectReason( "Observer Timeout" ); %client.schedule(700, "delete"); diff --git a/Classic/scripts/packs/satchelCharge.cs b/Classic/scripts/packs/satchelCharge.cs new file mode 100644 index 0000000..62b3d79 --- /dev/null +++ b/Classic/scripts/packs/satchelCharge.cs @@ -0,0 +1,853 @@ +//-------------------------------------------------------------------------- +// Satchel Charge pack +// can be used by any armor type +// when activated, throws the pack -- when activated again (before +// picking up another pack), detonates with a BIG explosion. + +//-------------------------------------------------------------------------- +// Sounds + +datablock EffectProfile(SatchelChargeActivateEffect) +{ + effectname = "packs/satchel_pack_activate"; + minDistance = 2.5; + maxDistance = 2.5; +}; + +datablock EffectProfile(SatchelChargeExplosionEffect) +{ + effectname = "packs/satchel_pack_detonate"; + minDistance = 2.5; + maxDistance = 5.0; +}; + +datablock EffectProfile(SatchelChargePreExplosionEffect) +{ + effectname = "explosions/explosion.xpl03"; + minDistance = 10.0; + maxDistance = 30.0; +}; + +datablock AudioProfile(SatchelChargeActivateSound) +{ + filename = "fx/packs/satchel_pack_activate.wav"; + description = AudioClose3d; + preload = true; + effect = SatchelChargeActivateEffect; +}; + +datablock AudioProfile(SatchelChargeExplosionSound) +{ + filename = "fx/packs/satchel_pack_detonate.wav"; + description = AudioBIGExplosion3d; + preload = true; + effect = SatchelChargeExplosionEffect; +}; + +datablock AudioProfile(SatchelChargePreExplosionSound) +{ + filename = "fx/explosions/explosion.xpl03.wav"; + description = AudioBIGExplosion3d; + preload = true; + effect = SatchelChargePreExplosionEffect; +}; + +datablock AudioProfile(UnderwaterSatchelChargeExplosionSound) +{ + filename = "fx/weapons/mortar_explode_UW.wav"; + description = AudioBIGExplosion3d; + preload = true; + effect = SatchelChargeExplosionEffect; +}; + +//---------------------------------------------------------------------------- +// Satchel Debris +//---------------------------------------------------------------------------- +datablock ParticleData( SDebrisSmokeParticle ) +{ + dragCoeffiecient = 1.0; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.2; + + lifetimeMS = 1000; + lifetimeVarianceMS = 100; + + textureName = "particleTest"; + + useInvAlpha = true; + + spinRandomMin = -60.0; + spinRandomMax = 60.0; + + colors[0] = "0.4 0.4 0.4 1.0"; + colors[1] = "0.3 0.3 0.3 0.5"; + colors[2] = "0.0 0.0 0.0 0.0"; + sizes[0] = 0.0; + sizes[1] = 2.0; + sizes[2] = 3.0; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ParticleEmitterData( SDebrisSmokeEmitter ) +{ + ejectionPeriodMS = 7; + periodVarianceMS = 1; + + ejectionVelocity = 1.0; // A little oomph at the back end + velocityVariance = 0.2; + + thetaMin = 0.0; + thetaMax = 40.0; + + particles = "SDebrisSmokeParticle"; +}; + + +datablock DebrisData( SatchelDebris ) +{ + emitters[0] = SDebrisSmokeEmitter; + + explodeOnMaxBounce = true; + + elasticity = 0.4; + friction = 0.2; + + lifetime = 0.3; + lifetimeVariance = 0.02; +}; + +//---------------------------------------------------------------------------- +// Bubbles +//---------------------------------------------------------------------------- +datablock ParticleData(SatchelBubbleParticle) +{ + dragCoefficient = 0.0; + gravityCoefficient = -0.25; + inheritedVelFactor = 0.0; + constantAcceleration = 0.0; + lifetimeMS = 1500; + lifetimeVarianceMS = 600; + useInvAlpha = false; + textureName = "special/bubbles"; + + spinRandomMin = -100.0; + spinRandomMax = 100.0; + + colors[0] = "0.7 0.8 1.0 0.0"; + colors[1] = "0.7 0.8 1.0 0.4"; + colors[2] = "0.7 0.8 1.0 0.0"; + sizes[0] = 2.0; + sizes[1] = 2.0; + sizes[2] = 2.0; + times[0] = 0.0; + times[1] = 0.8; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(SatchelBubbleEmitter) +{ + ejectionPeriodMS = 10; + periodVarianceMS = 0; + ejectionVelocity = 1.0; + ejectionOffset = 7.0; + velocityVariance = 0.5; + thetaMin = 0; + thetaMax = 80; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + particles = "MortarExplosionBubbleParticle"; +}; + +//-------------------------------------------------------------------------- +// Satchel Explosion Particle effects +//-------------------------------------- +datablock ParticleData(SatchelExplosionSmoke) +{ + dragCoeffiecient = 0.4; + gravityCoefficient = -0.0; // rises slowly + inheritedVelFactor = 0.025; + + lifetimeMS = 2000; + lifetimeVarianceMS = 0; + + textureName = "particleTest"; + + useInvAlpha = true; + spinRandomMin = -200.0; + spinRandomMax = 200.0; + + textureName = "special/Smoke/smoke_001"; + + colors[0] = "1.0 0.7 0.0 1.0"; + colors[1] = "0.2 0.2 0.2 0.5"; + colors[2] = "0.0 0.0 0.0 0.0"; + sizes[0] = 7.0; + sizes[1] = 17.0; + sizes[2] = 2.0; + times[0] = 0.0; + times[1] = 0.4; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(SatchelExplosionSmokeEmitter) +{ + ejectionPeriodMS = 10; + periodVarianceMS = 0; + + ejectionVelocity = 14.25; + velocityVariance = 2.25; + + thetaMin = 0.0; + thetaMax = 180.0; + + lifetimeMS = 200; + + particles = "SatchelExplosionSmoke"; +}; + +datablock ParticleData(UnderwaterSatchelExplosionSmoke) +{ + dragCoeffiecient = 105.0; + gravityCoefficient = -0.0; + inheritedVelFactor = 0.025; + + constantAcceleration = -1.0; + + lifetimeMS = 1500; + lifetimeVarianceMS = 0; + + textureName = "particleTest"; + + useInvAlpha = false; + spinRandomMin = -200.0; + spinRandomMax = 200.0; + + textureName = "special/Smoke/smoke_001"; + + colors[0] = "0.4 0.4 1.0 1.0"; + colors[1] = "0.4 0.4 1.0 0.5"; + colors[2] = "0.0 0.0 0.0 0.0"; + sizes[0] = 7.0; + sizes[1] = 17.0; + sizes[2] = 2.0; + times[0] = 0.0; + times[1] = 0.2; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(UnderwaterSatchelExplosionSmokeEmitter) +{ + ejectionPeriodMS = 10; + periodVarianceMS = 0; + + ejectionVelocity = 14.25; + velocityVariance = 2.25; + + thetaMin = 0.0; + thetaMax = 180.0; + + lifetimeMS = 200; + + particles = "UnderwaterSatchelExplosionSmoke"; +}; + + +datablock ParticleData(SatchelSparks) +{ + dragCoefficient = 1; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.2; + constantAcceleration = 0.0; + lifetimeMS = 500; + lifetimeVarianceMS = 150; + textureName = "special/bigSpark"; + colors[0] = "0.56 0.36 0.26 1.0"; + colors[1] = "0.56 0.36 0.26 1.0"; + colors[2] = "1.0 0.36 0.26 0.0"; + sizes[0] = 0.5; + sizes[1] = 0.5; + sizes[2] = 0.75; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; + +}; + +datablock ParticleEmitterData(SatchelSparksEmitter) +{ + ejectionPeriodMS = 1; + periodVarianceMS = 0; + ejectionVelocity = 40; + velocityVariance = 20.0; + ejectionOffset = 0.0; + thetaMin = 0; + thetaMax = 180; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + orientParticles = true; + lifetimeMS = 200; + particles = "SatchelSparks"; +}; + +datablock ParticleData(UnderwaterSatchelSparks) +{ + dragCoefficient = 1; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.2; + constantAcceleration = 0.0; + lifetimeMS = 500; + lifetimeVarianceMS = 350; + textureName = "special/underwaterSpark"; + colors[0] = "0.6 0.6 1.0 1.0"; + colors[1] = "0.6 0.6 1.0 1.0"; + colors[2] = "0.6 0.6 1.0 0.0"; + sizes[0] = 0.5; + sizes[1] = 0.5; + sizes[2] = 0.75; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; + +}; + +datablock ParticleEmitterData(UnderwaterSatchelSparksEmitter) +{ + ejectionPeriodMS = 2; + periodVarianceMS = 0; + ejectionVelocity = 30; + velocityVariance = 5.0; + ejectionOffset = 0.0; + thetaMin = 0; + thetaMax = 70; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + orientParticles = true; + lifetimeMS = 100; + particles = "UnderwaterSatchelSparks"; +}; + + +//--------------------------------------------------------------------------- +// Explosion +//--------------------------------------------------------------------------- + +datablock ExplosionData(SatchelSubExplosion) +{ + explosionShape = "disc_explosion.dts"; + faceViewer = true; + explosionScale = "0.5 0.5 0.5"; + + debris = SatchelDebris; + debrisThetaMin = 10; + debrisThetaMax = 80; + debrisNum = 8; + debrisVelocity = 60.0; + debrisVelocityVariance = 15.0; + + lifetimeMS = 1000; + delayMS = 0; + + emitter[0] = SatchelExplosionSmokeEmitter; + emitter[1] = SatchelSparksEmitter; + + offset = 0.0; + + playSpeed = 1.5; + + sizes[0] = "1.5 1.5 1.5"; + sizes[1] = "3.0 3.0 3.0"; + times[0] = 0.0; + times[1] = 1.0; +}; + +datablock ExplosionData(SatchelSubExplosion2) +{ + explosionShape = "disc_explosion.dts"; + faceViewer = true; + explosionScale = "0.7 0.7 0.7"; + + debris = SatchelDebris; + debrisThetaMin = 10; + debrisThetaMax = 170; + debrisNum = 8; + debrisVelocity = 60.0; + debrisVelocityVariance = 15.0; + + lifetimeMS = 1000; + delayMS = 50; + + emitter[0] = SatchelExplosionSmokeEmitter; + emitter[1] = SatchelSparksEmitter; + + offset = 9.0; + + playSpeed = 1.5; + + sizes[0] = "1.5 1.5 1.5"; + sizes[1] = "1.5 1.5 1.5"; + times[0] = 0.0; + times[1] = 1.0; +}; + +datablock ExplosionData(SatchelSubExplosion3) +{ + explosionShape = "disc_explosion.dts"; + faceViewer = true; + explosionScale = "1.0 1.0 1.0"; + + debris = SatchelDebris; + debrisThetaMin = 10; + debrisThetaMax = 170; + debrisNum = 8; + debrisVelocity = 60.0; + debrisVelocityVariance = 15.0; + + lifetimeMS = 2000; + delayMS = 100; + + emitter[0] = SatchelExplosionSmokeEmitter; + emitter[1] = SatchelSparksEmitter; + + offset = 9.0; + + playSpeed = 2.5; + + sizes[0] = "1.0 1.0 1.0"; + sizes[1] = "1.0 1.0 1.0"; + times[0] = 0.0; + times[1] = 1.0; +}; + +datablock ExplosionData(SatchelMainExplosion) +{ + soundProfile = SatchelChargePreExplosionSound; + + subExplosion[0] = SatchelSubExplosion; + subExplosion[1] = SatchelSubExplosion2; + subExplosion[2] = SatchelSubExplosion3; +}; + +//--------------------------------------------------------------------------- +// Underwater Explosion +//--------------------------------------------------------------------------- + +datablock ExplosionData(UnderwaterSatchelSubExplosion) +{ + explosionShape = "disc_explosion.dts"; + faceViewer = true; + explosionScale = "0.5 0.5 0.5"; + + + lifetimeMS = 1000; + delayMS = 0; + + emitter[0] = UnderwaterSatchelExplosionSmokeEmitter; + emitter[1] = UnderwaterSatchelSparksEmitter; + emitter[2] = SatchelBubbleEmitter; + + offset = 0.0; + + playSpeed = 0.75; + + sizes[0] = "1.5 1.5 1.5"; + sizes[1] = "2.5 2.5 2.5"; + sizes[2] = "2.0 2.0 2.0"; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ExplosionData(UnderwaterSatchelSubExplosion2) +{ + explosionShape = "disc_explosion.dts"; + faceViewer = true; + explosionScale = "0.7 0.7 0.7"; + + + lifetimeMS = 1000; + delayMS = 50; + + emitter[0] = UnderwaterSatchelExplosionSmokeEmitter; + emitter[1] = UnderwaterSatchelSparksEmitter; + emitter[2] = SatchelBubbleEmitter; + + offset = 9.0; + + playSpeed = 0.75; + + sizes[0] = "1.5 1.5 1.5"; + sizes[1] = "1.0 1.0 1.0"; + sizes[2] = "0.75 0.75 0.75"; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ExplosionData(UnderwaterSatchelSubExplosion3) +{ + explosionShape = "disc_explosion.dts"; + faceViewer = true; + explosionScale = "1.0 1.0 1.0"; + + + lifetimeMS = 2000; + delayMS = 100; + + emitter[0] = UnderwaterSatchelExplosionSmokeEmitter; + emitter[1] = UnderwaterSatchelSparksEmitter; + emitter[2] = SatchelBubbleEmitter; + + offset = 9.0; + + playSpeed = 1.25; + + sizes[0] = "1.0 1.0 1.0"; + sizes[1] = "1.0 1.0 1.0"; + sizes[2] = "0.5 0.5 0.5"; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ExplosionData(UnderwaterSatchelMainExplosion) +{ + soundProfile = UnderwaterSatchelChargeExplosionSound; + + subExplosion[0] = UnderwaterSatchelSubExplosion; + subExplosion[1] = UnderwaterSatchelSubExplosion2; + subExplosion[2] = UnderwaterSatchelSubExplosion3; +}; + + +//-------------------------------------------------------------------------- +// Projectile + +//------------------------------------------------------------------------- +// shapebase datablocks +datablock ShapeBaseImageData(SatchelChargeImage) +{ + shapeFile = "pack_upgrade_satchel.dts"; + item = SatchelCharge; + mountPoint = 1; + offset = "0 0 0"; + emap = true; +}; + +datablock ItemData(SatchelCharge) +{ + className = Pack; + catagory = "Packs"; + image = SatchelChargeImage; + shapeFile = "pack_upgrade_satchel.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 2; + rotate = true; + pickUpName = "a satchel charge pack"; + + computeCRC = true; +}; + +datablock ItemData(SatchelChargeTossed) +{ + shapeFile = "pack_upgrade_satchel.dts"; + mass = 1.2; + elasticity = 0.1; + friction = 0.9; + rotate = false; + pickupRadius = 0; + noTimeout = true; + sticky = true; +}; + +datablock StaticShapeData(SatchelChargeThrown) : StaticShapeDamageProfile +{ + shapeFile = "pack_upgrade_satchel.dts"; + explosion = SatchelMainExplosion; + underwaterExplosion = UnderwaterSatchelMainExplosion; + armDelay = 2500; + maxDamage = 0.6; + + disabledLevel = 0.5; + destroyedLevel = 0.6; + dynamicType = $TypeMasks::StaticShapeObjectType; + renderWhenDestroyed = false; + + kickBackStrength = 4000; +}; + +//-------------------------------------------------------------------------- + +function SatchelCharge::onUse(%this, %obj) +{ + %item = new Item() { + dataBlock = SatchelChargeTossed; + rotation = "0 0 1 " @ (getRandom() * 360); + }; + MissionCleanup.add(%item); + // take pack out of inventory and unmount image + %obj.decInventory(SatchelCharge, 1); + %obj.throwObject(%item); + %item.sourceObject = %obj; + + // z0dd - ZOD, 5/16/02. Schedule a check to see if the satchel is at rest but not stuck to anything + %item.checkCount = 0; + %item.velocCheck = %item.getDataBlock().schedule(1000, "checkVelocity", %item); +} + +function initArmSatchelCharge(%satchel) +{ + // "deet deet deet" sound + %satchel.playAudio(1, SatchelChargeActivateSound); + // also need to play "antenna extending" animation + %satchel.playThread(0, "deploy"); + %satchel.playThread(1, "activate"); + + // delay the actual arming until after sound is done playing + schedule( 2200, 0, "armSatchelCharge", %satchel ); +} + +function armSatchelCharge(%satchel) +{ + %satchel.armed = true; + commandToClient( %satchel.sourceObject.client, 'setSatchelArmed' ); +} + +function detonateSatchelCharge(%player) +{ + %satchelCharge = %player.thrownChargeId; + // can't detonate the satchel charge if it isn't armed + if(!%satchelCharge.armed) + return; + + //error("Detonating satchel charge #" @ %satchelCharge @ " for player #" @ %player); + + if(%satchelCharge.getDamageState() !$= Destroyed) + { + %satchelCharge.setDamageState(Destroyed); + %satchelCharge.blowup(); + } + + // Clear the player's HUD: + %player.client.clearBackpackIcon(); +} + +function SatchelChargeThrown::onEnterLiquid(%data, %obj, %coverage, %type) +{ + // lava types + if(%type >=4 && %type <= 6) + { + if(%obj.getDamageState() !$= "Destroyed") + { + %obj.armed = true; + detonateSatchelCharge(%obj.sourceObject); + return; + } + } + + // quickSand + if(%type == 7) + if(isObject(%obj.sourceObject)) + %obj.sourceObject.thrownChargeId = 0; + + Parent::onEnterLiquid(%data, %obj, %coverage, %type); +} + +function SatchelChargeImage::onMount(%data, %obj, %node) +{ + %obj.thrownChargeId = 0; +} + +function SatchelChargeImage::onUnmount(%data, %obj, %node) +{ +} + +function SatchelChargeThrown::onDestroyed(%this, %object, %lastState) +{ + if(%object.kaboom) + return; + else + { + %object.kaboom = true; + + // the "thwart" flag is set if the charge is destroyed with weapons rather + // than detonated. A less damaging explosion, but visually the same scale. + if(%object.thwart) + { + messageClient(%object.sourceObject.client, 'msgSatchelChargeDetonate', "\c2Satchel charge destroyed."); + %dmgRadius = 15; // z0dd - ZOD, 9/27/02. Was 10 + %dmgMod = 0.35; // z0dd - ZOD, 9/27/02. Was 0.3 + %expImpulse = 2000; // z0dd - ZOD, 9/27/02. Was 1000 + %dmgType = $DamageType::Explosion; + } + else + { + messageClient(%object.sourceObject.client, 'msgSatchelChargeDetonate', "\c2Satchel charge detonated!"); + %dmgRadius = 25; // z0dd - ZOD, 9/27/02. Was 20 + %dmgMod = 1.15; // z0dd - ZOD, 9/27/02. Was 1.0 + %expImpulse = 5000; // z0dd - ZOD, 9/27/02. Was 2500 + %dmgType = $DamageType::SatchelCharge; + } + + %object.blowingUp = true; + + //Slope fix by DarkTiger + ///RadiusExplosion(%object, %object.getPosition(), %dmgRadius, %dmgMod, %expImpulse, %object.sourceObject, %dmgType); + %rot = getWords(%object.getTransform(), 3, 6); + %tmat = VectorOrthoBasis(%rot); + %upVec = getWords(%tmat, 6, 8); + %offset = vectorAdd(%object.getPosition(),vectorScale(%upVec,0.5)); + RadiusExplosion(%object, %offset, %dmgRadius, %dmgMod, %expImpulse, %object.sourceObject, %dmgType); + + %object.schedule(1000, "delete"); + } + + // -------------------------------------------------------------------------------- + // z0dd - ZOD, 4/25/02. Satchel bug fix. Prior to fix, clients couldn't pick up + // packs when satchel was destroyed from dmg + if(isObject(%object.sourceObject)) + %object.sourceObject.thrownChargeId = 0; + // -------------------------------------------------------------------------------- +} + +function SatchelChargeThrown::onCollision(%data,%obj,%col) +{ + // Do nothing... +} + +function SatchelChargeThrown::damageObject(%data, %targetObject, %sourceObject, %position, %amount, %damageType) +{ + if (!%object.blowingUp) + { + %targetObject.damaged += %amount; + + if(%targetObject.damaged >= %targetObject.getDataBlock().maxDamage && + %targetObject.getDamageState() !$= Destroyed) + { + %targetObject.thwart = true; + %targetObject.setDamageState(Destroyed); + %targetObject.blowup(); + + // clear the player's HUD: + %targetObject.sourceObject.client.clearBackPackIcon(); + } + } +} +// z0dd - ZOD, 5/18/03. Removed functions, created parent. Streamline. +//function SatchelCharge::onPickup(%this, %obj, %shape, %amount) +//{ + // created to prevent console errors +//} + +//************************************************************** +// STICKY SATCHEL FUNCTIONS: z0dd - ZOD, 5/16/02 +//************************************************************** + +function SatchelChargeTossed::onEnterLiquid(%data, %obj, %coverage, %type) +{ + // If it lands in lava or quicksand, delete it + if(%type >=4 && %type <= 7) + { + cancel(%obj.velocCheck); + if(isObject(%obj.sourceObject)) + %obj.sourceObject.thrownChargeId = 0; + + %obj.sourceObject.client.clearBackPackIcon(); + %obj.schedule(100, "delete"); + } + else + cancel(%obj.velocCheck); +} + +function SatchelChargeTossed::onLeaveLiquid(%data, %obj, %type) +{ + // On the off chance it passes through to air, reschedule the velocity check + %obj.checkCount = 0; + %obj.velocCheck = %obj.getDataBlock().schedule(1000, "checkVelocity", %obj); +} + +function SatchelChargeTossed::onCollision(%data, %obj, %col) +{ + // Lets keep thing from floating mid air, the check velocity should handle it afterwards + if(%col.getType() & ($TypeMasks::PlayerObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::TurretObjectType)) + { + %vec = (-1.0 + getRandom() * 2.0) SPC (-1.0 + getRandom() * 2.0) SPC getRandom(); + %vec = vectorScale(%vec, 15); + %pos = %col.getWorldBoxCenter(); + %obj.applyImpulse(%pos, %vec); + } +} + +function SatchelChargeTossed::checkVelocity(%data, %item) +{ + %item.checkCount++; + if(VectorLen(%item.getVelocity()) < 0.1) + { + // Satchel has come to rest but not activated, probably on a + // staticshape (station, gen, etc) lets force activation + cancel(%item.velocCheck); + activateSatchel(posFromTransform(%item.getTransform()), rotFromTransform(%item.getTransform()), %item.sourceObject); + %item.schedule(100, "delete"); + } + else if(%item.checkCount >= 6) + { + // satchel's still moving but it's been checked several times, + // probably thrown off face of earth, delete it + cancel(%item.velocCheck); + if(isObject(%item.sourceObject)) + %item.sourceObject.thrownChargeId = 0; + + %item.sourceObject.client.clearBackPackIcon(); + %item.schedule(100, "delete"); + } + else + { + // check back in a little while + %item.velocCheck = %data.schedule(1000, "checkVelocity", %item); + } +} + +function SatchelChargeTossed::onStickyCollision(%data, %obj) +{ + // We have sticky! Lets setup for the actual charge + cancel(%obj.velocCheck); + %pos = %obj.getLastStickyPos(); + %norm = %obj.getLastStickyNormal(); + %intAngle = getTerrainAngle(%norm); + %rotAxis = vectorNormalize(vectorCross(%norm, "0 0 1")); + if (getWord(%norm, 2) == 1 || getWord(%norm, 2) == -1) + %rotAxis = vectorNormalize(vectorCross(%norm, "0 1 0")); + + %rot = %rotAxis @ " " @ %intAngle; + activateSatchel(%pos, %rot, %obj.sourceObject); + %obj.schedule(50, "delete"); +} + +function activateSatchel(%pos, %rot, %source) +{ + // Create the charge and schedule arming + %satchel = new StaticShape() { + dataBlock = SatchelChargeThrown; + sourceObject = %source; + position = %pos; + rotation = %rot; + }; + MissionCleanup.add(%satchel); + %source.thrownChargeId = %satchel; + %satchel.armed = false; + %satchel.damaged = 0.0; + %satchel.thwart = false; + messageClient(%source.client, 'MsgSatchelChargePlaced', "\c2Satchel charge deployed."); + + // arm itself 2.5 seconds after creation + if(%source.thrownChargeId != %satchel) // z0dd - ZOD, 5/19/03. Address multiple charges exploit. + %satchel.schedule(100, "delete"); + else + schedule(%satchel.getDatablock().armDelay, %satchel, "initArmSatchelCharge", %satchel); +} diff --git a/Classic/scripts/server.cs b/Classic/scripts/server.cs index 63d2704..5d5e95c 100644 --- a/Classic/scripts/server.cs +++ b/Classic/scripts/server.cs @@ -963,18 +963,18 @@ function GameConnection::onConnect( %client, %name, %raceGender, %skin, %voice, if($Host::GuidCheck) { // If we don't have a GUID try to find one somewhere. - if(! %client.guid || %client.guid $= "") + if(!%client.guid || %client.guid $= "") { %client.guid = getField(%client.getAuthInfo(),3); } // If we don't have a name, try to get one. - if(!%name || %name $= "") + if(%name $= "") { - %name = getField(%client.getAuthInfo(),0); - %client.nameBase = %name; + %name = getField(%client.getAuthInfo(),0); + %client.nameBase = %name; } // If we still don't have a GUID or name, time to boot the player (unless a local game). - if(getIPAddress(%client) !$= "Local" && (!%client.guid $= "" || %name $= "")) + if(getIPAddress(%client) !$= "Local" && (%client.guid $= "" || %name $= "")) { echo("No name/GUID kick for CID (" @ %client @ ") with IP (" @ getIPAddress(%client) @ ")"); KickByCID(%client, "You joined the server with a blank name and/or GUID. Try rejoining.",2);