iw6-scripts-dev/maps/mp/mp_swamp.gsc
2024-12-11 11:28:08 +01:00

486 lines
13 KiB
Plaintext

#include maps\mp\_utility;
#include common_scripts\utility;
SWAMP_SLASHER_HEAL_AMOUNT = 2;
SWAMP_SLASHER_WEAPON = "iw6_axe_mp";
main()
{
maps\mp\mp_swamp_precache::main();
maps\createart\mp_swamp_art::main();
maps\mp\mp_swamp_fx::main();
// TODO: get fx for these
level._effect[ "swamp_slasher_victim" ] = LoadFX( "vfx/moments/mp_swamp/vfx_spirit_victim" );
level._effect[ "swamp_slasher_death" ] = LoadFX( "vfx/moments/mp_swamp/vfx_spirit_victim_killstreak" );
level._effect[ "vfx_flesh_hit_body_fatal_hatchet" ] = loadfx( "vfx/gameplay/impacts/flesh/vfx_flesh_hit_body_fatal_hatchet" );
maps\mp\_load::main();
level.mapCustomCrateFunc = ::swampCustomCrateFunc;
level.mapCustomKillstreakFunc = ::swampCustomKillstreakFunc;
level.mapCustomBotKillstreakFunc = ::swampCustomBotKillstreakFunc;
maps\mp\killstreaks\_juggernaut::initLevelCustomJuggernaut( ::swampSlasherCreateFunc, ::setJuggSwampSlasherClass, ::setJuggSwampSlasher, "callout_killed_swamp_slasher" );
setdvar_cg_ng( "r_specularColorScale", 2.5 , 7 );
// AmbientPlay( "ambient_mp_setup_template" );
maps\mp\_compass::setupMiniMap( "compass_map_mp_swamp" );
setdvar( "r_lightGridEnableTweaks", 1 );
setdvar( "r_lightGridIntensity", 1.33 );
SetDvar( "r_tessellationCutoffFalloffBase", 600 );
SetDvar( "r_tessellationCutoffDistanceBase", 1600 );
SetDvar( "r_tessellationCutoffFalloff", 600 );
SetDvar( "r_tessellationCutoffDistance", 1600 );
SetDvar( "r_reactiveMotionWindFrequencyScale", 0.1);
SetDvar( "r_reactiveMotionWindAmplitudeScale", 0.5);
setdvar_cg_ng( "sm_sunShadowScale", 0.25, 1 );
setdvar_cg_ng( "fx_alphaThreshold", 5, 0);
game["attackers"] = "allies";
game["defenders"] = "axis";
game[ "allies_outfit" ] = "urban";
game[ "axis_outfit" ] = "woodland";
level thread maps\mp\_breach::main();
vfxSetupFrogFx();
thread vfxBatCaveWaitInit( "triggerBatCave" );
thread maps\mp\_dlcalienegg::setupEggForMap( "alienEasterEgg" );
// don't allow bots to use the vanguard on this map because we don't have enough heli nodes, which leads to stationary vanguards
maps\mp\bots\_bots_ks::blockKillstreakForBots( "vanguard" );
}
swampSlasherCreateFunc( juggType )
{
AssertEx( juggType == "juggernaut_swamp_slasher" );
self.isJuggernautLevelCustom = true;
self.juggMoveSpeedScaler = 1.05; // for unset perk juiced
self maps\mp\gametypes\_class::giveLoadout( self.pers["team"], juggType, false );
self givePerk( "specialty_blindeye", false );
self givePerk( "specialty_coldblooded", false );
self givePerk( "specialty_noscopeoutline", false);
self givePerk( "specialty_detectexplosive", false );
self givePerk( "specialty_marathon", false );
self givePerk( "specialty_falldamage", false );
// TODO! LOOK WHY THERE ARE TWO VALUES
self.moveSpeedScaler = 1.15; // this needs to happen last because some perks change speed
self swampSlasherBeginMusic();
self thread onJuggSwampSlasherEnemyKilled();
self thread onJuggSwampSlasherDeath();
self thread teamPlayerCardSplash( "used_juggernaut_swamp_slasher", self );
self thread swampSlasherSounds();
self.canUseKillstreakCallback = ::juggSwampSlasherCanUseKillstreak;
self.killstreakErrorMsg = ::juggSwampSlasherKillsteakErrorMsg;
return false;
}
juggSwampSlasherCanUseKillstreak( streakName )
{
if ( streakName == "heli_sniper" || self isRideKillstreak( streakname ) )
return false;
return true;
}
juggSwampSlasherKillsteakErrorMsg()
{
self IPrintLnBold( &"MP_SWAMP_NO_KILLSTREAKS" );
}
setJuggSwampSlasherClass( class )
{
// rely on "none" defaults
loadout = [];
loadout[ "loadoutPrimary" ] = "iw6_axe";
loadout[ "loadoutPrimaryBuff" ] = "specialty_null";
loadout[ "loadoutSecondaryBuff" ] = "specialty_null";
loadout[ "loadoutEquipment" ] = "specialty_null";
return loadout;
}
setJuggSwampSlasher()
{
if( IsDefined( self.headModel ) )
{
self Detach( self.headModel, "" );
self.headModel = undefined;
}
self SetModel( "mp_fullbody_mp_mmyers_a" );
self SetViewModel( "viewhands_mp_mmyers" );
self SetClothType( "nylon" );
}
tryUseJuggernautSwampSlasher( lifeId, streakName )
{
maps\mp\killstreaks\_juggernaut::giveJuggernaut( streakName );
game[ "player_holding_level_killstrek" ] = false;
return true;
}
SWAMP_SLASHER_WEIGHT = 85;
enable_level_killstreak()
{
maps\mp\killstreaks\_airdrop::changeCrateWeight("airdrop_assault", "juggernaut_swamp_slasher", SWAMP_SLASHER_WEIGHT);
}
disable_level_killstreak()
{
maps\mp\killstreaks\_airdrop::changeCrateWeight("airdrop_assault", "juggernaut_swamp_slasher", 0);
}
swampCustomCrateFunc()
{
if(!IsDefined(game["player_holding_level_killstrek"]))
game["player_holding_level_killstrek"] = false;
if(!allowLevelKillstreaks() || game["player_holding_level_killstrek"])
return;
//"Press and hold [{+activate}] for Swamp Slasher."
maps\mp\killstreaks\_airdrop::addCrateType(
"airdrop_assault",
"juggernaut_swamp_slasher",
SWAMP_SLASHER_WEIGHT,
maps\mp\killstreaks\_airdrop::juggernautCrateThink,
maps\mp\killstreaks\_airdrop::get_friendly_juggernaut_crate_model(),
maps\mp\killstreaks\_airdrop::get_enemy_juggernaut_crate_model(),
&"MP_SWAMP_JUGGERNAUT_SWAMP_SLASHER_PICKUP"
);
level thread watch_for_swamp_slasher_crate();
}
watch_for_swamp_slasher_crate()
{
while( true )
{
level waittill( "createAirDropCrate", dropCrate );
if( IsDefined( dropCrate ) && IsDefined( dropCrate.crateType ) && dropCrate.crateType == "juggernaut_swamp_slasher" )
{
disable_level_killstreak();
captured = wait_for_capture( dropCrate );
if(!captured)
{
enable_level_killstreak();
}
else
{
//Once its picked up it needs to remain off.
game[ "player_holding_level_killstrek" ] = true;
break;
}
}
}
}
//death and capture are sent on the same frame but death is processed first :(
wait_for_capture( dropCrate )
{
result = watch_for_air_drop_death( dropCrate );
return !IsDefined( result ); //If !isdefined the captured notify was also sent.
}
watch_for_air_drop_death(dropCrate)
{
dropCrate endon( "captured" );
dropCrate waittill( "death" );
waittillframeend;
return true;
}
swampCustomKillstreakFunc()
{
AddDebugCommand( "devgui_cmd \"MP/Killstreak/Level Event:5/Care Package/Swamp Slasher\" \"set scr_devgivecarepackage juggernaut_swamp_slasher; set scr_devgivecarepackagetype airdrop_assault\"\n");
AddDebugCommand( "devgui_cmd \"MP/Killstreak/Level Event:5/Swamp Slasher\" \"set scr_givekillstreak juggernaut_swamp_slasher\"\n" );
level.killStreakFuncs[ "juggernaut_swamp_slasher" ] = ::tryUseJuggernautSwampSlasher;
}
swampCustomBotKillstreakFunc()
{
AddDebugCommand( "devgui_cmd \"MP/Bots(Killstreak)/Level Events:5/Swamp Slasher\" \"set scr_testclients_givekillstreak juggernaut_swamp_slasher\"\n" );
maps\mp\bots\_bots_ks::bot_register_killstreak_func( "juggernaut_swamp_slasher", maps\mp\bots\_bots_ks::bot_killstreak_simple_use );
}
swampSlasherSounds()
{
level endon ( "game_ended" );
self endon( "death" );
self endon( "disconnect" );
self endon( "jugg_removed" );
while( true )
{
wait ( 3.0 );
playPlayerAndNpcSounds( self, "axeman_breathing_player", "axeman_breathing_sound" );
}
}
onJuggSwampSlasherEnemyKilled() // self == player
{
self endon( "death" );
while( true )
{
self waittill( "killed_enemy", victim, sWeapon );
if ( sWeapon == SWAMP_SLASHER_WEAPON )
{
// give health back on each kill, since we don't regen
self.health = int( min( self.health + SWAMP_SLASHER_HEAL_AMOUNT, 100 ) );
self thread swampSlasherKillEffect( victim );
}
}
}
swampSlasherKillEffect( victim ) // self == player
{
pos = victim.origin + (0, 0, 50);
attackDir = self.origin - victim.origin;
hitPos = victim GetTagOrigin( "j_neck");
PlayFx( level._effect[ "vfx_flesh_hit_body_fatal_hatchet" ], hitPos, VectorNormalize( attackDir ), AnglesToUp( victim GetTagAngles( "j_neck" ) ) );
victim PlaySound( "scn_axe_kill_npc" );
wait(0.05);
PlayFX( level._effect[ "swamp_slasher_victim" ], pos );
}
onJuggSwampSlasherDeath() // self == player
{
level endon( "game_ended" );
self thread swampSlasherMusicEndOfLevel();
self waittill_any( "death", "disconnect" );
if ( IsDefined( self ) )
{
PlayFX( level._effect[ "swamp_slasher_death" ], self.origin + ( 0, 0, 50 ) );
self PlaySound( "scn_axe_kill_plr" );
}
thread swampSlasherEndMusic();
self.canUseKillstreakCallback = undefined;
self.killstreakErrorMsg = undefined;
}
// don't let the music keep playing after the game ends
swampSlasherMusicEndOfLevel()
{
self endon( "death" );
self endon( "disconnect" );
level waittill( "game_ended" );
thread swampSlasherEndMusic();
}
CONST_SWAMP_SLASHER_MUSIC_START = "mus_mp_swamp_killstreak_start";
CONST_SWAMP_SLASHER_MUSIC_END = "mus_mp_swamp_killstreak_end";
swampSlasherBeginMusic()
{
// this won't stop currently playing music
maps\mp\gametypes\_music_and_dialog::disableMusic();
level.SlasherMusicEnt = Spawn( "script_origin", (0,0,0) );
level.SlasherMusicEnt playLoopSound( CONST_SWAMP_SLASHER_MUSIC_START );
}
swampSlasherEndMusic()
{
// foreach ( player in level.players )
// {
// player StopLocalSound( CONST_SWAMP_SLASHER_MUSIC_START );
// }
level.SlasherMusicEnt StopLoopSound();
playSoundOnPlayers( CONST_SWAMP_SLASHER_MUSIC_END );
thread maps\mp\gametypes\_music_and_dialog::enableMusic();
waitframe();
level.SlasherMusicEnt Delete();
level.SlasherMusicEnt = undefined;
}
// VFX
VFX_FROG_LEAP = "vfx_frog_jump_inwater_r";
VFX_FROG_TRIGGER_RADIUS = 400;
VFX_FROG_TRIGGER_HEIGHT = 128;
VFX_FROG_COOLDOWN = 30;
vfxCreateFrogTrigger( fxpos, angle, trigPos, trigRadius )
{
fxEnt = SpawnFx( getfx( VFX_FROG_LEAP ), fxpos, AnglesToForward( angle ), AnglesToUp( angle ) );
fxEnt.trigger = Spawn( "trigger_radius", trigPos, 0, trigRadius, VFX_FROG_TRIGGER_HEIGHT );
fxEnt.radius = trigRadius;
fxEnt thread vfxRunFrogTrigger();
}
vfxRunFrogTrigger()
{
level endon( "game_ended" );
while ( true )
{
/#
self thread vfxDebugFrog( VFX_FROG_TRIGGER_HEIGHT, self.radius, (0, 1, 0) );
#/
self.trigger waittill( "trigger", player );
/#
self thread vfxDebugFrog( VFX_FROG_TRIGGER_HEIGHT, self.radius, (1, 0, 0) );
#/
TriggerFX( self );
// play sound?
wait( VFX_FROG_COOLDOWN );
}
}
vfxSetupFrogFx()
{
/#
SetDvarIfUninitialized( "swamp_draw_frog_trigger", 0 );
#/
vfxCreateFrogTrigger( (543.607, -1866.1, 16.9588), (273, 270.011, 33.961), (543.607, -1866.1, 16.9588), VFX_FROG_TRIGGER_RADIUS );
vfxCreateFrogTrigger( (-137.91, -1403.79, 17.1477), (273, 270, 163.983), (-137.91, -1403.79, 17.1477), VFX_FROG_TRIGGER_RADIUS );
vfxCreateFrogTrigger( (-753.322, 385.262, 2.15145), (273, 270.009, 95.9661), (-753.322, 385.262, 2.15145), VFX_FROG_TRIGGER_RADIUS );
vfxCreateFrogTrigger( (-928.21, 619.578, 1.96266), (273, 270.002, 116.968), (-928.21, 619.578, 1.96266), VFX_FROG_TRIGGER_RADIUS );
vfxCreateFrogTrigger( (-1138.44, 365.926, 1.51848), (274, 269.744, -90.7688), (-1138.44, 365.926, 1.51848), VFX_FROG_TRIGGER_RADIUS );
vfxCreateFrogTrigger( (-941.947, -27.4375, 7.81633), (273, 270.004, 43.9734), (-941.947, -27.4375, 7.81633), VFX_FROG_TRIGGER_RADIUS );
vfxCreateFrogTrigger( (-1092.89, -419.291, 6.29806), (273, 270.003, 82.9732), (-1092.89, -419.291, 6.29806), VFX_FROG_TRIGGER_RADIUS );
vfxCreateFrogTrigger( (-758.194, -1355.44, 61.8263), (273, 270, 176.977), (-758.194, -1355.44, 61.8263), VFX_FROG_TRIGGER_RADIUS );
vfxCreateFrogTrigger( (-198.275, -1725.05, 19.3899), (273, 270, 100.969), (-198.275, -1725.05, 19.3899), VFX_FROG_TRIGGER_RADIUS );
vfxCreateFrogTrigger( (721.78, -1614.7, 18.9652), (273.486, 235.078, 120.847), (721.78, -1614.7, 18.9652), VFX_FROG_TRIGGER_RADIUS );
vfxCreateFrogTrigger( (494.378, -1182.59, 2.01686), (273, 270.003, 0.0), (494.378, -1182.59, 2.01686), VFX_FROG_TRIGGER_RADIUS );
}
VFX_BAT_EXPLODER_ID = 55;
VFX_BAT_COOLDOWN = 60;
// "triggerBatCave"
vfxBatCaveWaitInit( triggername )
{
level endon( "game_ended" );
// get the trigger
trigger = GetEnt( triggername, "targetname" );
if ( IsDefined( trigger ) )
{
trigger childthread vfxBatCaveTrigger();
while ( true )
{
trigger waittill( "trigger", player );
trigger thread vfxBatCaveWatchPlayerState( player );
}
}
}
vfxBatCaveWatchPlayerState( player ) // self == bat trigger
{
// if any other player starts the bats, stop checking
self endon( "batCaveTrigger" );
player endon( "death" );
player endon( "disconnect" );
// make sure we aren't already runnning one
player notify( "batCaveExit" );
player endon( "batCaveExit" );
self childthread vfxBatCaveWatchPlayerWeapons( player );
// this detects if the player has exited the trigger
while ( player IsTouching( self ) )
{
waitframe();
}
player notify( "batCaveExit" );
}
vfxBatCaveWatchPlayerWeapons( player )
{
player endon( "batCaveExit" );
player waittill( "weapon_fired" );
self notify ( "batCaveTrigger" );
}
vfxBatCaveTrigger()
{
/#
SetDvarIfUninitialized( "scr_dbg_batcave_cooldown", VFX_BAT_COOLDOWN );
#/
while ( true )
{
self waittill( "batCaveTrigger" );
// play the effect
exploder( VFX_BAT_EXPLODER_ID );
waitTime = VFX_BAT_COOLDOWN;
/#
waitTime = GetDvarInt( "scr_dbg_batcave_cooldown" );
#/
wait ( waitTime );
}
}
/#
vfxDebugFrog( height, radius, color ) // self == trigger
{
self notify ( "update_debug_draw_trigger" );
self endon( "update_debug_draw_trigger" );
while ( true )
{
if ( GetDvarInt( "swamp_draw_frog_trigger" ) != 0 )
{
Cylinder( self.trigger.origin, self.trigger.origin + ( 0, 0, height ), radius, color, false );
Sphere( self.origin, 10, color, true );
}
wait ( 0.05 );
}
}
#/