diff --git a/userraw/maps/mp/gametypes/_damage.gsc b/userraw/maps/mp/gametypes/_damage.gsc deleted file mode 100644 index 3f23a29..0000000 --- a/userraw/maps/mp/gametypes/_damage.gsc +++ /dev/null @@ -1,2564 +0,0 @@ -#include maps\mp\_utility; -#include maps\mp\gametypes\_hud_util; -#include common_scripts\utility; - - -isSwitchingTeams() -{ - if ( isDefined( self.switching_teams ) ) - return true; - - return false; -} - - -isTeamSwitchBalanced() -{ - playerCounts = self maps\mp\gametypes\_teams::CountPlayers(); - playerCounts[ self.leaving_team ] -- ; - playerCounts[ self.joining_team ]++ ; - - return( ( playerCounts[ self.joining_team ] - playerCounts[ self.leaving_team ] ) < 2 ); -} - - -isFriendlyFire( victim, attacker ) -{ - if ( !level.teamBased ) - return false; - - if ( !isDefined( attacker ) ) - return false; - - if ( !isPlayer( attacker ) && !isDefined( attacker.team ) ) - return false; - - if ( victim.team != attacker.team ) - return false; - - if ( victim == attacker ) - return false; - - return true; -} - - -killedSelf( attacker ) -{ - if ( !isPlayer( attacker ) ) - return false; - - if ( attacker != self ) - return false; - - return true; -} - - -isHeadShot( sWeapon, sHitLoc, sMeansOfDeath, attacker ) -{ - if ( isDefined( attacker ) ) - { - if ( attacker.code_classname == "script_vehicle" && isDefined( attacker.owner ) ) - return false; - if ( attacker.code_classname == "misc_turret" && isDefined( attacker.owner ) ) - return false; - if ( attacker.code_classname == "script_model" && isDefined( attacker.owner ) ) - return false; - } - - return( sHitLoc == "head" || sHitLoc == "helmet" ) && sMeansOfDeath != "MOD_MELEE" && sMeansOfDeath != "MOD_IMPACT" && !isMG( sWeapon ); -} - - -handleTeamChangeDeath() -{ - if ( !level.teamBased ) - return; - - // this might be able to happen now, but we should remove instances where it can - assert( self.leaving_team != self.joining_team ); - - if ( self.joining_team == "spectator" || !isTeamSwitchBalanced() ) - { - self thread [[ level.onXPEvent ]]( "suicide" ); - self incPersStat( "suicides", 1 ); - self.suicides = self getPersStat( "suicides" ); - } -} - - -handleWorldDeath( attacker, lifeId, sMeansOfDeath, sHitLoc ) -{ - if ( !isDefined( attacker ) ) - return; - - if ( !isDefined( attacker.team ) ) - { - handleSuicideDeath( sMeansOfDeath, sHitLoc ); - return; - } - - assert( attacker.team == "axis" || attacker.team == "allies" ); - - if ( level.teamBased && attacker.team != self.team ) - { - if ( isDefined( level.onNormalDeath ) && isPlayer( attacker ) && attacker.team != "spectator" ) - [[ level.onNormalDeath ]]( self, attacker, lifeId ); - } -} - - -handleSuicideDeath( sMeansOfDeath, sHitLoc ) -{ - self SetCardDisplaySlot( self, 7 ); - self openMenu( "killedby_card_display" ); - - self thread [[ level.onXPEvent ]]( "suicide" ); - self incPersStat( "suicides", 1 ); - self.suicides = self getPersStat( "suicides" ); - - if ( !matchMakingGame() ) - self incPlayerStat( "suicides", 1 ); - - scoreSub = maps\mp\gametypes\_tweakables::getTweakableValue( "game", "suicidepointloss" ); - maps\mp\gametypes\_gamescore::_setPlayerScore( self, maps\mp\gametypes\_gamescore::_getPlayerScore( self ) - scoreSub ); - - if ( sMeansOfDeath == "MOD_SUICIDE" && sHitLoc == "none" && isDefined( self.throwingGrenade ) ) - self.lastGrenadeSuicideTime = gettime(); - - // suicide was caused by too many team kills - if ( isDefined( self.friendlydamage ) ) - self iPrintLnBold( &"MP_FRIENDLY_FIRE_WILL_NOT" ); -} - - -handleFriendlyFireDeath( attacker ) -{ - attacker SetCardDisplaySlot( self, 8 ); - attacker openMenu( "youkilled_card_display" ); - - self SetCardDisplaySlot( attacker, 7 ); - self openMenu( "killedby_card_display" ); - - attacker thread [[ level.onXPEvent ]]( "teamkill" ); - attacker.pers[ "teamkills" ] += 1.0; - - attacker.teamkillsThisRound++ ; - - if ( maps\mp\gametypes\_tweakables::getTweakableValue( "team", "teamkillpointloss" ) ) - { - scoreSub = maps\mp\gametypes\_rank::getScoreInfoValue( "kill" ); - maps\mp\gametypes\_gamescore::_setPlayerScore( attacker, maps\mp\gametypes\_gamescore::_getPlayerScore( attacker ) - scoreSub ); - } - - if ( level.maxAllowedTeamkills < 0 ) - return; - - if ( level.inGracePeriod ) - { - teamKillDelay = 1; - attacker.pers["teamkills"] += level.maxAllowedTeamkills; - } - else if ( attacker.pers[ "teamkills" ] > 1 && getTimePassed() < ( (level.gracePeriod * 1000) + 8000 + ( attacker.pers[ "teamkills" ] * 1000 ) ) ) - { - teamKillDelay = 1; - attacker.pers["teamkills"] += level.maxAllowedTeamkills; - } - else - { - teamKillDelay = attacker maps\mp\gametypes\_playerlogic::TeamKillDelay(); - } - - if ( teamKillDelay > 0 ) - { - attacker.pers["teamKillPunish"] = true; - attacker _suicide(); - } -} - - -handleNormalDeath( lifeId, attacker, eInflictor, sWeapon, sMeansOfDeath ) -{ - attacker thread maps\mp\_events::killedPlayer( lifeId, self, sWeapon, sMeansOfDeath ); - - //if ( attacker.pers["teamkills"] <= level.maxAllowedTeamkills ) - // attacker.pers["teamkills"] = max( attacker.pers["teamkills"] - 1, 0 ); - - attacker SetCardDisplaySlot( self, 8 ); - attacker openMenu( "youkilled_card_display" ); - - self SetCardDisplaySlot( attacker, 7 ); - self openMenu( "killedby_card_display" ); - - if ( sMeansOfDeath == "MOD_HEAD_SHOT" ) - { - attacker incPersStat( "headshots", 1 ); - attacker.headshots = attacker getPersStat( "headshots" ); - attacker incPlayerStat( "headshots", 1 ); - - if ( isDefined( attacker.lastStand ) ) - value = maps\mp\gametypes\_rank::getScoreInfoValue( "kill" ) * 2; - else - value = undefined; - - if( !level.extraDamageFeedback ) - attacker playLocalSound( "bullet_impact_headshot_2" ); - } - else - { - if ( isDefined( attacker.lastStand ) ) - value = maps\mp\gametypes\_rank::getScoreInfoValue( "kill" ) * 2; - else - value = undefined; - } - - attacker thread maps\mp\gametypes\_rank::giveRankXP( "kill", value ); - - attacker incPersStat( "kills", 1 ); - attacker.kills = attacker getPersStat( "kills" ); - attacker updatePersRatio( "kdRatio", "kills", "deaths" ); - attacker maps\mp\gametypes\_persistence::statSetChild( "round", "kills", attacker.kills ); - attacker incPlayerStat( "kills", 1 ); - - if ( isFlankKill( self, attacker ) ) - { - attacker incPlayerStat( "flankkills", 1 ); - - self incPlayerStat( "flankdeaths", 1 ); - } - - lastKillStreak = attacker.pers["cur_kill_streak"]; - - self.pers["copyCatLoadout"] = undefined; - - if ( self _hasPerk( "specialty_copycat" ) ) - self.pers["copyCatLoadout"] = attacker maps\mp\gametypes\_class::cloneLoadout(); - - if ( isAlive( attacker ) ) - { - // killstreaks only advance from kills earned this life - if ( isDefined( level.killStreakSpecialCaseWeapons[sWeapon] ) || sWeapon == "nuke_mp" ) // this is an optimization - { - switch ( sWeapon ) - { - case "ac130_105mm_mp": - case "ac130_40mm_mp": - case "ac130_25mm_mp": - if ( attacker.ac130LifeId == attacker.pers["deaths"] && !level.scriptIncKillstreak ) - attacker.pers["cur_kill_streak"]++; - break; - case "cobra_player_minigun_mp": - case "weapon_cobra_mk19_mp": - if ( attacker.heliRideLifeId == attacker.pers["deaths"] && !level.scriptIncKillstreak ) - attacker.pers["cur_kill_streak"]++; - break; - case "cobra_20mm_mp": - case "artillery_mp": - case "stealth_bomb_mp": - case "remotemissile_projectile_mp": - case "sentry_minigun_mp": - case "harrier_20mm_mp": - case "pavelow_minigun_mp": - case "nuke_mp": - if ( isDefined( eInflictor ) && isDefined( eInflictor.lifeId ) ) - killstreakLifeId = eInflictor.lifeId; - else - killstreakLifeId = attacker.lifeId; - - if ( killstreakLifeId == attacker.pers["deaths"] && !level.scriptIncKillstreak && (level.nukeIncreasesStreak || sWeapon != "nuke_mp") ) - attacker.pers["cur_kill_streak"]++; - break; - default: - if( !level.scriptIncKillstreak ) - attacker.pers["cur_kill_streak"]++; - break; - } - } - else - { - if( !level.scriptIncKillstreak ) - attacker.pers["cur_kill_streak"]++; - } - - attacker setPlayerStatIfGreater( "killstreak", attacker.pers["cur_kill_streak"] ); - - if ( attacker.pers["cur_kill_streak"] > attacker getPersStat( "longestStreak" ) ) - attacker setPersStat( "longestStreak", attacker.pers["cur_kill_streak"] ); - } - - attacker.pers["cur_death_streak"] = 0; - - if ( attacker.pers["cur_kill_streak"] > attacker maps\mp\gametypes\_persistence::statGetChild( "round", "killStreak" ) ) - { - attacker maps\mp\gametypes\_persistence::statSetChild( "round", "killStreak", attacker.pers["cur_kill_streak"] ); - } - - if ( attacker.pers["cur_kill_streak"] > attacker.kill_streak ) - { - attacker maps\mp\gametypes\_persistence::statSet( "killStreak", attacker.pers["cur_kill_streak"] ); - attacker.kill_streak = attacker.pers["cur_kill_streak"]; - } - - maps\mp\gametypes\_gamescore::givePlayerScore( "kill", attacker, self ); - maps\mp\_skill::processKill( attacker, self ); - - scoreSub = maps\mp\gametypes\_tweakables::getTweakableValue( "game", "deathpointloss" ); - maps\mp\gametypes\_gamescore::_setPlayerScore( self, maps\mp\gametypes\_gamescore::_getPlayerScore( self ) - scoreSub ); - - if ( isDefined( level.ac130player ) && level.ac130player == attacker ) - level notify( "ai_killed", self ); - - //if ( lastKillStreak != attacker.pers["cur_kill_streak"] ) - level notify ( "player_got_killstreak_" + attacker.pers["cur_kill_streak"], attacker ); - - if ( isAlive( attacker ) ) - attacker thread maps\mp\killstreaks\_killstreaks::checkKillstreakReward( attacker.pers["cur_kill_streak"] ); - - attacker notify ( "killed_enemy" ); - - if ( !level.teamBased ) - { - self.attackers = []; - return; - } - - if ( isDefined( level.onNormalDeath ) && attacker.pers[ "team" ] != "spectator" ) - [[ level.onNormalDeath ]]( self, attacker, lifeId ); - - if ( isDefined( level.onNormalDeath2 ) && attacker.pers[ "team" ] != "spectator" ) - [[ level.onNormalDeath2 ]]( self, attacker, sMeansOfDeath ); - - level thread maps\mp\gametypes\_battlechatter_mp::sayLocalSoundDelayed( attacker, "kill", 0.75 ); - - if ( isDefined( self.lastAttackedShieldPlayer ) && isDefined( self.lastAttackedShieldTime ) && self.lastAttackedShieldPlayer != attacker ) - { - if ( getTime() - self.lastAttackedShieldTime < 2500 ) - { - self.lastAttackedShieldPlayer thread maps\mp\gametypes\_gamescore::processShieldAssist( self ); - } - else if ( isAlive( self.lastAttackedShieldPlayer ) && getTime() - self.lastAttackedShieldTime < 5000 ) - { - forwardVec = vectorNormalize( anglesToForward( self.angles ) ); - shieldVec = vectorNormalize( self.lastAttackedShieldPlayer.origin - self.origin ); - - if ( vectorDot( shieldVec, forwardVec ) > 0.925 ) - self.lastAttackedShieldPlayer thread maps\mp\gametypes\_gamescore::processShieldAssist( self ); - } - } - - if ( isDefined( self.attackers ) ) - { - foreach ( player in self.attackers ) - { - if ( !isDefined( player ) ) - continue; - - if ( player == attacker ) - continue; - - player thread maps\mp\gametypes\_gamescore::processAssist( self ); - } - self.attackers = []; - } -} - -isPlayerWeapon( weaponName ) -{ - if ( weaponClass( weaponName ) == "non-player" ) - return false; - - if ( weaponClass( weaponName ) == "turret" ) - return false; - - if ( weaponInventoryType( weaponName ) == "primary" || weaponInventoryType( weaponName ) == "altmode" ) - return true; - - return false; -} - -Callback_PlayerKilled( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration ) -{ - PlayerKilled_internal( eInflictor, attacker, self, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration, false ); -} - - -QueueShieldForRemoval( shield ) -{ - MY_MAX_SHIELDS_AT_A_TIME = 5; - - if ( !isDefined( level.shieldTrashArray ) ) - level.shieldTrashArray = []; - - if ( level.shieldTrashArray.size >= MY_MAX_SHIELDS_AT_A_TIME ) - { - idxMax = (level.shieldTrashArray.size - 1); - level.shieldTrashArray[0] delete(); - for ( idx = 0; idx < idxMax; idx++ ) - level.shieldTrashArray[idx] = level.shieldTrashArray[idx + 1]; - level.shieldTrashArray[idxMax] = undefined; - } - - level.shieldTrashArray[level.shieldTrashArray.size] = shield; -} - - -LaunchShield( damage, meansOfDeath ) -{ - shieldModel = "weapon_riot_shield_mp"; - - self DetachShieldModel( shieldModel, "tag_weapon_left" ); - self.hasRiotShield = false; - self.hasRiotShieldEquipped = false; -} - - -PlayerKilled_internal( eInflictor, attacker, victim, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration, isFauxDeath ) -{ - prof_begin( "PlayerKilled" ); - //prof_begin( " PlayerKilled_1" ); - - victim endon( "spawned" ); - victim notify( "killed_player" ); - - assert( victim.sessionteam != "spectator" ); - - if ( isDefined( attacker ) ) - attacker.assistedSuicide = undefined; - - if ( !isDefined( victim.idFlags ) ) - { - if ( sMeansOfDeath == "MOD_SUICIDE" ) - victim.idFlags = 0; - else if ( sMeansOfDeath == "MOD_GRENADE" && isSubstr( sWeapon, "frag_grenade" ) && iDamage == 100000 ) - victim.idFlags = 0; - else if ( sWeapon == "nuke_mp" && !level.forceFinalKillcam ) - victim.idFlags = 0; - else if ( level.friendlyfire >= 2) - victim.idFlags = 0; - else - assertEx( 0, "Victims ID flags not set, but means of death was gr or nuke: " + sMeansOfDeath ); - } - - if ( victim.hasRiotShieldEquipped ) - victim LaunchShield( iDamage, sMeansofDeath ); - - //victim thread checkForceBleedOut(); - - if ( !isFauxDeath ) - { - if ( isDefined( victim.endGame ) ) - { - victim VisionSetNakedForPlayer( getDvar( "mapname" ), 2 ); - } - else if ( !isDefined( victim.nuked ) ) - { - victim VisionSetNakedForPlayer( getDvar( "mapname" ), 0 ); - victim ThermalVisionOff(); - } - } - else - { - victim.fauxDead = true; - self notify ( "death" ); - } - - if ( game[ "state" ] == "postgame" ) - { - //prof_end( " PlayerKilled_1" ); - prof_end( "PlayerKilled" ); - return; - } - - // replace params with last stand info - deathTimeOffset = 0; - - if ( !isPlayer( eInflictor ) && isDefined( eInflictor.primaryWeapon ) ) - sPrimaryWeapon = eInflictor.primaryWeapon; - else if ( isDefined( attacker ) && isPlayer( attacker ) && attacker getCurrentPrimaryWeapon() != "none" ) - sPrimaryWeapon = attacker getCurrentPrimaryWeapon(); - else - sPrimaryWeapon = undefined; - - if ( isdefined( victim.useLastStandParams ) ) - { - victim ensureLastStandParamsValidity(); - victim.useLastStandParams = undefined; - - assert( isdefined( victim.lastStandParams ) ); - - eInflictor = victim.lastStandParams.eInflictor; - attacker = victim.lastStandParams.attacker; - iDamage = victim.lastStandParams.iDamage; - sMeansOfDeath = victim.lastStandParams.sMeansOfDeath; - sWeapon = victim.lastStandParams.sWeapon; - sPrimaryWeapon = victim.lastStandParams.sPrimaryWeapon; - vDir = victim.lastStandParams.vDir; - sHitLoc = victim.lastStandParams.sHitLoc; - - deathTimeOffset = ( gettime() - victim.lastStandParams.lastStandStartTime ) / 1000; - victim.lastStandParams = undefined; - } - - //prof_end( " PlayerKilled_1" ); - //prof_begin( " PlayerKilled_2" ); - - //used for endgame perk and assisted suicide. - if ( (!isDefined( attacker ) || attacker.classname == "trigger_hurt" || attacker.classname == "worldspawn" || attacker == victim ) && isDefined( self.attackers ) ) - { - bestPlayer = undefined; - - foreach ( player in self.attackers ) - { - if ( !isDefined( player ) ) - continue; - - if (! isDefined( victim.attackerData[ player.guid ].damage ) ) - continue; - - if ( player == victim || (level.teamBased && player.team == victim.team ) ) - continue; - - if ( victim.attackerData[ player.guid ].lasttimedamaged + 2500 < getTime() ) - continue; - - if ( victim.attackerData[ player.guid ].damage > 1 && ! isDefined( bestPlayer ) ) - bestPlayer = player; - else if ( isDefined( bestPlayer ) && victim.attackerData[ player.guid ].damage > victim.attackerData[ bestPlayer.guid ].damage ) - bestPlayer = player; - } - - if ( isDefined( bestPlayer ) ) - { - attacker = bestPlayer; - attacker.assistedSuicide = true; - sWeapon = victim.attackerData[ bestPlayer.guid ].weapon; - vDir = victim.attackerData[ bestPlayer.guid ].vDir; - sHitLoc = victim.attackerData[ bestPlayer.guid ].sHitLoc; - psOffsetTime = victim.attackerData[ bestPlayer.guid ].psOffsetTime; - sMeansOfDeath = victim.attackerData[ bestPlayer.guid ].sMeansOfDeath; - iDamage = victim.attackerData[ bestPlayer.guid ].damage; - sPrimaryWeapon = victim.attackerData[ bestPlayer.guid ].sPrimaryWeapon; - eInflictor = attacker; - } - } - else - { - if ( isDefined( attacker ) ) - attacker.assistedSuicide = undefined; - } - - // override MOD - if ( isHeadShot( sWeapon, sHitLoc, sMeansOfDeath, attacker ) ) - { - sMeansOfDeath = "MOD_HEAD_SHOT"; - if( level.headShotDetachHead ) - victim detach(victim.headmodel); - } - else if ( sMeansOfDeath != "MOD_MELEE" && !isDefined( victim.nuked ) ) - victim playDeathSound(); - - friendlyFire = isFriendlyFire( victim, attacker ); - - if ( isDefined( attacker ) ) - { - // override attacker if it's a vehicle - if ( attacker.code_classname == "script_vehicle" && isDefined( attacker.owner ) ) - attacker = attacker.owner; - - // override attacker if it's a sentry - if ( attacker.code_classname == "misc_turret" && isDefined( attacker.owner ) ) - attacker = attacker.owner; - - // override attacker if it's a crate - if ( attacker.code_classname == "script_model" && isDefined( attacker.owner ) ) - { - attacker = attacker.owner; - - if ( !isFriendlyFire( victim, attacker ) && attacker != victim ) - attacker notify( "crushed_enemy" ); - } - } - - //prof_end( " PlayerKilled_2" ); - //prof_begin( " PlayerKilled_3" ); - - //prof_begin( " PlayerKilled_3_drop" ); - // drop weapons from killed player - victim maps\mp\gametypes\_weapons::dropScavengerForDeath( attacker ); // must be done before dropWeaponForDeath, since we use some weapon information - victim maps\mp\gametypes\_weapons::dropWeaponForDeath( attacker ); - //prof_end( " PlayerKilled_3_drop" ); - - if ( !isFauxDeath ) - { - victim.sessionstate = "dead"; - victim.statusicon = "hud_status_dead"; - } - - // UTS update aliveCount - victim maps\mp\gametypes\_playerlogic::removeFromAliveCount(); - - if ( !isDefined( victim.switching_teams ) ) - { - // update our various stats - victim incPersStat( "deaths", 1 ); - victim.deaths = victim getPersStat( "deaths" ); - victim updatePersRatio( "kdRatio", "kills", "deaths" ); - victim maps\mp\gametypes\_persistence::statSetChild( "round", "deaths", victim.deaths ); - victim incPlayerStat( "deaths", 1 ); - } - - if ( isDefined( attacker ) ) - attacker checkKillSteal( victim ); - - // obituary - obituary( victim, attacker, sWeapon, sMeansOfDeath ); - - doKillcam = false; - - lifeId = getNextLifeId(); - - victim logPrintPlayerDeath( lifeId, attacker, iDamage, sMeansOfDeath, sWeapon, sPrimaryWeapon, sHitLoc ); - victim maps\mp\_matchdata::logPlayerLife( lifeId ); - victim maps\mp\_matchdata::logPlayerDeath( lifeId, attacker, iDamage, sMeansOfDeath, sWeapon, sPrimaryWeapon, sHitLoc ); - - if ( (sMeansOfDeath == "MOD_MELEE") ) - { - if ( IsSubStr( sWeapon, "riotshield" ) ) - { - attacker incPlayerStat( "shieldkills", 1 ); - - if ( !matchMakingGame() ) - victim incPlayerStat( "shielddeaths", 1 ); - } - else - attacker incPlayerStat( "knifekills", 1 ); - } - - //prof_end( " PlayerKilled_3" ); - //prof_begin( " PlayerKilled_4" ); - - if ( victim isSwitchingTeams() ) - { - handleTeamChangeDeath(); - } - else if ( !isPlayer( attacker ) || (isPlayer( attacker ) && sMeansOfDeath == "MOD_FALLING") ) - { - handleWorldDeath( attacker, lifeId, sMeansOfDeath, sHitLoc ); - if ( level.failCam ) - doKillcam = true; - } - else if ( attacker == victim ) - { - handleSuicideDeath( sMeansOfDeath, sHitLoc ); - if ( level.failCam ) - doKillcam = true; - } - else if ( friendlyFire ) - { - if ( !isDefined( victim.nuked ) ) - { - handleFriendlyFireDeath( attacker ); - } - if ( level.failCam ) - doKillcam = true; - } - else - { - if ( sMeansOfDeath == "MOD_GRENADE" && eInflictor == attacker ) - addAttacker( victim, attacker, eInflictor, sWeapon, iDamage, (0,0,0), vDir, sHitLoc, psOffsetTime, sMeansOfDeath ); - - doKillcam = true; - handleNormalDeath( lifeId, attacker, eInflictor, sWeapon, sMeansOfDeath ); - victim thread maps\mp\gametypes\_missions::playerKilled( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, sPrimaryWeapon, sHitLoc, attacker.modifiers ); - - victim.pers["cur_death_streak"]++; - - if ( !getGametypeNumLives() && !matchMakingGame() ) - victim setPlayerStatIfGreater( "deathstreak", victim.pers["cur_death_streak"] ); - } - - //prof_end( " PlayerKilled_4" ); - //prof_begin( " PlayerKilled_5" ); - - // clear any per life variables - victim resetPlayerVariables(); - victim.lastAttacker = attacker; - victim.lastDeathPos = victim.origin; - victim.deathTime = getTime(); - victim.wantSafeSpawn = false; - victim.revived = false; - victim.sameShotDamage = 0; - - if ( isFauxDeath ) - { - doKillcam = false; - deathAnimDuration = (victim PlayerForceDeathAnim( eInflictor, sMeansOfDeath, sWeapon, sHitLoc, vDir )); - } - - victim.body = victim clonePlayer( deathAnimDuration ); - - if ( isFauxDeath ) - victim PlayerHide(); - - if ( victim isOnLadder() || victim isMantling() || !victim isOnGround() || isDefined( victim.nuked ) ) - victim.body startRagDoll(); - - if ( !isDefined( victim.switching_teams ) ) - thread maps\mp\gametypes\_deathicons::addDeathicon( victim.body, victim, victim.team, 5.0 ); - - thread delayStartRagdoll( victim.body, sHitLoc, vDir, sWeapon, eInflictor, sMeansOfDeath ); - - // allow per gametype death handling - victim thread [[ level.onPlayerKilled ]]( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration, lifeId ); - - if ( isPlayer( attacker ) ) - attackerNum = attacker getEntityNumber(); - else if ( (sMeansOfDeath == "MOD_FALLING" || eInflictor.classname == "trigger_hurt") && level.failCam )//banz - attackerNum = victim getEntityNumber(); - else - attackerNum = -1; - killcamentity = victim getKillcamEntity( attacker, eInflictor, sWeapon, sMeansOfDeath ); - killcamentityindex = -1; - killcamentitystarttime = 0; - - if ( isDefined( killcamentity ) ) - { - killcamentityindex = killcamentity getEntityNumber();// must do this before any waiting lest the entity be deleted - killcamentitystarttime = killcamentity.birthtime; - if ( !isdefined( killcamentitystarttime ) ) - killcamentitystarttime = 0; - } - - /# - if ( getDvarInt( "scr_forcekillcam" ) != 0 ) - doKillcam = true; - #/ - - // record the kill cam values for the final kill cam - if ( level.forceFinalKillcam && doKillcam ) - maps\mp\gametypes\_gamelogic::recordFinalKillCam( 5.0, victim, attacker, attackerNum, killcamentityindex, killcamentitystarttime, sWeapon, deathTimeOffset, psOffsetTime ); - - if ( !level.forceFinalKillcam && level.allowFinalKillcam ) - { - if ( isDefined( attacker.finalKill ) ) - maps\mp\_awards::addAwardWinner( "finalkill", attacker.clientid ); - - //prof_end( " PlayerKilled_5" ); - //prof_begin( " PlayerKilled_6" ); - - if ( isDefined( attacker.finalKill ) && doKillcam && !isDefined( level.nukeDetonated ) ) - { - level thread doFinalKillcam( 5.0, victim, attacker, attackerNum, killcamentityindex, killcamentitystarttime, sWeapon, deathTimeOffset, psOffsetTime ); - - if ( !isFauxDeath ) - wait ( 1.0 ); - } - } - - if ( !isFauxDeath ) - { - if ( !level.showingFinalKillcam && !level.killcam && doKillcam ) - { - if ( victim _hasPerk( "specialty_copycat" ) && isDefined( victim.pers["copyCatLoadout"] ) ) - { - victim thread maps\mp\gametypes\_killcam::waitDeathCopyCatButton( attacker ); - wait ( 1.0 ); - } - } - - // let the player watch themselves die - wait( 0.25 ); - victim thread maps\mp\gametypes\_killcam::cancelKillCamOnUse(); - wait( 0.25 ); - - self.respawnTimerStartTime = gettime() + 1000; - timeUntilSpawn = maps\mp\gametypes\_playerlogic::TimeUntilSpawn( true ); - if ( timeUntilSpawn < 1 ) - timeUntilSpawn = 1; - victim thread maps\mp\gametypes\_playerlogic::predictAboutToSpawnPlayerOverTime( timeUntilSpawn ); - - wait( 1.0 ); - victim notify( "death_delay_finished" ); - } - - postDeathDelay = ( getTime() - victim.deathTime ) / 1000; - self.respawnTimerStartTime = gettime(); - - if ( !(isDefined( victim.cancelKillcam) && victim.cancelKillcam) && doKillcam && level.killcam && game[ "state" ] == "playing" && !victim isUsingRemote() && !level.showingFinalKillcam ) - { - livesLeft = !( getGametypeNumLives() && !victim.pers[ "lives" ] ); - timeUntilSpawn = maps\mp\gametypes\_playerlogic::TimeUntilSpawn( true ); - willRespawnImmediately = livesLeft && ( timeUntilSpawn <= 0 ); - - if ( !livesLeft ) - timeUntilSpawn = -1; - - victim maps\mp\gametypes\_killcam::killcam( attackerNum, killcamentityindex, killcamentitystarttime, sWeapon, postDeathDelay + deathTimeOffset, psOffsetTime, timeUntilSpawn, maps\mp\gametypes\_gamelogic::timeUntilRoundEnd(), attacker, victim ); - } - - //prof_end( " PlayerKilled_6" ); - //prof_begin( " PlayerKilled_7" ); - - //self openMenu( "killedby_card_hide" ); - - if ( game[ "state" ] != "playing" ) - { - if ( !level.showingFinalKillcam ) - { - victim.sessionstate = "dead"; - victim ClearKillcamState(); - } - - //prof_end( " PlayerKilled_7" ); - prof_end( "PlayerKilled" ); - return; - } - - // class may be undefined if we have changed teams - if ( isValidClass( victim.class ) ) - { - victim thread maps\mp\gametypes\_playerlogic::spawnClient(); - } - - //prof_end( " PlayerKilled_7" ); - prof_end( "PlayerKilled" ); -} - -checkForceBleedout() -{ - if ( level.dieHardMode != 1 ) - return false; - - if ( !getGametypeNumLives() ) - return false; - - if ( level.livesCount[self.team] > 0 ) - return false; - - foreach ( player in level.players ) - { - if ( !isAlive( player ) ) - continue; - - if ( player.team != self.team ) - continue; - - if ( player == self ) - continue; - - if ( !player.inLastStand ) - return false; - } - - foreach ( player in level.players ) - { - if ( !isAlive( player ) ) - continue; - - if ( player.team != self.team ) - continue; - - if ( player.inLastStand && player != self ) - player lastStandBleedOut(false); - } - - return true; -} - -checkKillSteal( vic ) -{ - if ( matchMakingGame() ) - return; - - greatestDamage = 0; - greatestAttacker = undefined; - - if ( isDefined( vic.attackerdata ) && vic.attackerdata.size > 1 ) - { - foreach ( attacker in vic.attackerdata ) - { - if ( attacker.damage > greatestDamage ) - { - greatestDamage = attacker.damage; - greatestAttacker = attacker.attackerEnt; - } - } - - if ( isDefined( greatestAttacker ) && greatestAttacker != self ) - self incPlayerStat( "killsteals", 1 ); - } -} - -doFinalKillcam( delay, victim, attacker, attackerNum, killcamentityindex, killcamentitystarttime, sWeapon, deathTimeOffset, psOffsetTime ) -{ - level.showingFinalKillcam = true; - - level waittill ( "round_end_finished" ); - - if ( !isDefined( victim ) || !isDefined( attacker ) ) - { - level.showingFinalKillcam = false; - return; - } - - postDeathDelay = (( getTime() - victim.deathTime ) / 1000); - - foreach ( player in level.players ) - { - player closePopupMenu(); - player closeInGameMenu(); - player VisionSetNakedForPlayer( getDvar( "mapname" ), 0 ); - player.killcamentitylookat = victim getEntityNumber(); - - if ( (player != victim || (!isRoundBased() || isLastRound())) && player _hasPerk( "specialty_copycat" ) ) - player _unsetPerk( "specialty_copycat" ); - - player thread maps\mp\gametypes\_killcam::killcam( attackerNum, killcamentityindex, killcamentitystarttime, sWeapon, postDeathDelay + deathTimeOffset, psOffsetTime, 0, 10000, attacker, victim ); - } - - wait( 0.1 ); - - while ( anyPlayersInKillcam() ) - wait( 0.05 ); - - level.showingFinalKillcam = false; -} - - -anyPlayersInKillcam() -{ - foreach ( player in level.players ) - { - if ( isDefined( player.killcam ) ) - return true; - } - - return false; -} - - -resetPlayerVariables() -{ - self.killedPlayersCurrent = []; - self.switching_teams = undefined; - self.joining_team = undefined; - self.leaving_team = undefined; - - self.pers["cur_kill_streak"] = 0; - - self maps\mp\gametypes\_gameobjects::detachUseModels();// want them detached before we create our corpse -} - - -getKillcamEntity( attacker, eInflictor, sWeapon, sMeansOfDeath ) -{ - if ( !isDefined( eInflictor ) ) - return undefined; - - if( (sMeansOfDeath == "MOD_FALLING" || eInflictor.classname == "trigger_hurt") && level.failCam ) - return attacker; - - if ( eInflictor == attacker ) - return undefined; - - if ( isSubStr( sWeapon, "ac130_" ) ) - return undefined; - - if ( sWeapon == "cobra_player_minigun_mp" ) - return undefined; - - if ( sWeapon == "artillery_mp" || sWeapon == "stealth_bomb_mp" || sWeapon == "pavelow_minigun_mp" ) - return eInflictor.killCamEnt; - - if ( isDefined( eInflictor.script_gameobjectname ) && eInflictor.script_gameobjectname == "bombzone" ) - return eInflictor.killCamEnt; - - if ( eInflictor.classname == "script_origin" || eInflictor.classname == "script_model" || eInflictor.classname == "script_brushmodel" ) - return undefined; // probably a barrel or a car... code does airstrike cam for these things which looks bad - - if ( issubstr( sWeapon, "remotemissile_" ) ) - return undefined; - if ( issubstr( sWeapon, "ac130_" ) ) - return undefined; - - return eInflictor; -} - - -HitlocDebug( attacker, victim, damage, hitloc, dflags ) -{ - colors = []; - colors[ 0 ] = 2; - colors[ 1 ] = 3; - colors[ 2 ] = 5; - colors[ 3 ] = 7; - - if ( !getdvarint( "scr_hitloc_debug" ) ) - return; - - if ( !isdefined( attacker.hitlocInited ) ) - { - for ( i = 0; i < 6; i++ ) - { - attacker setClientDvar( "ui_hitloc_" + i, "" ); - } - attacker.hitlocInited = true; - } - - if ( level.splitscreen || !isPLayer( attacker ) ) - return; - - elemcount = 6; - if ( !isdefined( attacker.damageInfo ) ) - { - attacker.damageInfo = []; - for ( i = 0; i < elemcount; i++ ) - { - attacker.damageInfo[ i ] = spawnstruct(); - attacker.damageInfo[ i ].damage = 0; - attacker.damageInfo[ i ].hitloc = ""; - attacker.damageInfo[ i ].bp = false; - attacker.damageInfo[ i ].jugg = false; - attacker.damageInfo[ i ].colorIndex = 0; - } - attacker.damageInfoColorIndex = 0; - attacker.damageInfoVictim = undefined; - } - - for ( i = elemcount - 1; i > 0; i -- ) - { - attacker.damageInfo[ i ].damage = attacker.damageInfo[ i - 1 ].damage; - attacker.damageInfo[ i ].hitloc = attacker.damageInfo[ i - 1 ].hitloc; - attacker.damageInfo[ i ].bp = attacker.damageInfo[ i - 1 ].bp; - attacker.damageInfo[ i ].jugg = attacker.damageInfo[ i - 1 ].jugg; - attacker.damageInfo[ i ].colorIndex = attacker.damageInfo[ i - 1 ].colorIndex; - } - attacker.damageInfo[ 0 ].damage = damage; - attacker.damageInfo[ 0 ].hitloc = hitloc; - attacker.damageInfo[ 0 ].bp = ( dflags & level.iDFLAGS_PENETRATION ); - attacker.damageInfo[ 0 ].jugg = victim hasPerk( "specialty_armorvest", true ); - if ( isdefined( attacker.damageInfoVictim ) && ( attacker.damageInfoVictim != victim ) ) - { - attacker.damageInfoColorIndex++ ; - if ( attacker.damageInfoColorIndex == colors.size ) - attacker.damageInfoColorIndex = 0; - } - attacker.damageInfoVictim = victim; - attacker.damageInfo[ 0 ].colorIndex = attacker.damageInfoColorIndex; - - for ( i = 0; i < elemcount; i++ ) - { - color = "^" + colors[ attacker.damageInfo[ i ].colorIndex ]; - if ( attacker.damageInfo[ i ].hitloc != "" ) - { - val = color + attacker.damageInfo[ i ].hitloc; - if ( attacker.damageInfo[ i ].bp ) - val += " (BP)"; - if ( attacker.damageInfo[ i ].jugg ) - val += " (Jugg)"; - attacker setClientDvar( "ui_hitloc_" + i, val ); - } - attacker setClientDvar( "ui_hitloc_damage_" + i, color + attacker.damageInfo[ i ].damage ); - } -} - -giveRecentShieldXP() -{ - self endon ( "death" ); - self endon ( "disconnect" ); - - self notify ( "giveRecentShieldXP" ); - self endon ( "giveRecentShieldXP" ); - - self.recentShieldXP++; - - wait ( 20.0 ); - - self.recentShieldXP = 0; -} - - -Callback_PlayerDamage_internal( eInflictor, eAttacker, victim, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime ) -{ - if( level.disableKnife && sMeansOfDeath == "MOD_MELEE" && sWeapon != "riotshield_mp" ) - return; - - if( level.disableTurret && sWeapon == "turret_minigun_mp" ) - return; - - if ( !isReallyAlive( victim ) ) - return; - - if ( isDefined( eAttacker ) && eAttacker.classname == "script_origin" && isDefined( eAttacker.type ) && eAttacker.type == "soft_landing" ) - return; - - if ( isDefined( level.hostMigrationTimer ) ) - return; - - if ( sMeansOfDeath == "MOD_FALLING" ) - victim thread emitFallDamage( iDamage ); - - if ( sMeansOfDeath == "MOD_EXPLOSIVE_BULLET" && iDamage != 1 ) - { - iDamage *= getDvarFloat( "scr_explBulletMod" ); - iDamage = int( iDamage ); - } - - if ( isDefined( eAttacker ) && eAttacker.classname == "worldspawn" ) - eAttacker = undefined; - - if ( isDefined( eAttacker ) && isDefined( eAttacker.gunner ) ) - eAttacker = eAttacker.gunner; - - attackerIsNPC = isDefined( eAttacker ) && !isDefined( eAttacker.gunner ) && (eAttacker.classname == "script_vehicle" || eAttacker.classname == "misc_turret" || eAttacker.classname == "script_model"); - attackerIsHittingTeammate = level.teamBased && isDefined( eAttacker ) && ( victim != eAttacker ) && isDefined( eAttacker.team ) && ( victim.pers[ "team" ] == eAttacker.team ); - - stunFraction = 0.0; - - if ( iDFlags & level.iDFLAGS_STUN ) - { - stunFraction = 0.0; - //victim StunPlayer( 1.0 ); - iDamage = 0.0; - } - else if ( sHitLoc == "shield" ) - { - if ( attackerIsHittingTeammate && level.friendlyfire == 0 ) - return; - - if ( sMeansOfDeath == "MOD_PISTOL_BULLET" || sMeansOfDeath == "MOD_RIFLE_BULLET" || sMeansOfDeath == "MOD_EXPLOSIVE_BULLET" && !attackerIsHittingTeammate ) - { - if ( isPlayer( eAttacker ) ) - { - eAttacker.lastAttackedShieldPlayer = victim; - eAttacker.lastAttackedShieldTime = getTime(); - } - victim notify ( "shield_blocked" ); - - // fix turret + shield challenge exploits - if ( sWeapon == "turret_minigun_mp" ) - shieldDamage = 25; - else - shieldDamage = maps\mp\perks\_perks::cac_modified_damage( victim, eAttacker, iDamage, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc ); - - victim.shieldDamage += shieldDamage; - - // fix turret + shield challenge exploits - if ( sWeapon != "turret_minigun_mp" || cointoss() ) - victim.shieldBulletHits++; - - if ( victim.shieldBulletHits >= level.riotShieldXPBullets ) - { - if ( self.recentShieldXP > 4 ) - xpVal = int( 50 / self.recentShieldXP ); - else - xpVal = 50; - - printLn( xpVal ); - - victim thread maps\mp\gametypes\_rank::giveRankXP( "shield_damage", xpVal ); - victim thread giveRecentShieldXP(); - - victim thread maps\mp\gametypes\_missions::genericChallenge( "shield_damage", victim.shieldDamage ); - - victim thread maps\mp\gametypes\_missions::genericChallenge( "shield_bullet_hits", victim.shieldBulletHits ); - - victim.shieldDamage = 0; - victim.shieldBulletHits = 0; - } - } - - if ( iDFlags & level.iDFLAGS_SHIELD_EXPLOSIVE_IMPACT ) - { - if ( !attackerIsHittingTeammate ) - victim thread maps\mp\gametypes\_missions::genericChallenge( "shield_explosive_hits", 1 ); - - sHitLoc = "none"; // code ignores any damage to a "shield" bodypart. - if ( !(iDFlags & level.iDFLAGS_SHIELD_EXPLOSIVE_IMPACT_HUGE) ) - iDamage *= 0.0; - } - else if ( iDFlags & level.iDFLAGS_SHIELD_EXPLOSIVE_SPLASH ) - { - if ( isDefined( eInflictor ) && isDefined( eInflictor.stuckEnemyEntity ) && eInflictor.stuckEnemyEntity == victim ) //does enough damage to shield carrier to ensure death - iDamage = 101; - - victim thread maps\mp\gametypes\_missions::genericChallenge( "shield_explosive_hits", 1 ); - sHitLoc = "none"; // code ignores any damage to a "shield" bodypart. - } - else - { - return; - } - } - else if ( (smeansofdeath == "MOD_MELEE") && IsSubStr( sweapon, "riotshield" ) ) - { - if ( !(attackerIsHittingTeammate && (level.friendlyfire == 0)) ) - { - stunFraction = 0.0; - victim StunPlayer( 0.0 ); - } - } - - if ( !attackerIsHittingTeammate ) - iDamage = maps\mp\perks\_perks::cac_modified_damage( victim, eAttacker, iDamage, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc ); - - if ( !iDamage ) - return false; - - victim.iDFlags = iDFlags; - victim.iDFlagsTime = getTime(); - - if ( game[ "state" ] == "postgame" ) - return; - if ( victim.sessionteam == "spectator" ) - return; - if ( isDefined( victim.canDoCombat ) && !victim.canDoCombat ) - return; - if ( isDefined( eAttacker ) && isPlayer( eAttacker ) && isDefined( eAttacker.canDoCombat ) && !eAttacker.canDoCombat ) - return; - - // handle vehicles/turrets and friendly fire - if ( attackerIsNPC && attackerIsHittingTeammate ) - { - if ( sMeansOfDeath == "MOD_CRUSH" ) - { - victim _suicide(); - return; - } - - if ( !level.friendlyfire ) - return; - } - - prof_begin( "PlayerDamage flags/tweaks" ); - - // Don't do knockback if the damage direction was not specified - if ( !isDefined( vDir ) ) - iDFlags |= level.iDFLAGS_NO_KNOCKBACK; - - friendly = false; - - if ( ( victim.health == victim.maxhealth && ( !isDefined( victim.lastStand ) || !victim.lastStand ) ) || !isDefined( victim.attackers ) && !isDefined( victim.lastStand ) ) - { - victim.attackers = []; - victim.attackerData = []; - } - - if ( isHeadShot( sWeapon, sHitLoc, sMeansOfDeath, eAttacker ) ) - sMeansOfDeath = "MOD_HEAD_SHOT"; - - if ( maps\mp\gametypes\_tweakables::getTweakableValue( "game", "onlyheadshots" ) ) - { - if ( sMeansOfDeath == "MOD_PISTOL_BULLET" || sMeansOfDeath == "MOD_RIFLE_BULLET" || sMeansOfDeath == "MOD_EXPLOSIVE_BULLET" ) - return; - else if ( sMeansOfDeath == "MOD_HEAD_SHOT" ) - iDamage = 150; - } - - // explosive barrel/car detection - if ( sWeapon == "none" && isDefined( eInflictor ) ) - { - if ( isDefined( eInflictor.destructible_type ) && isSubStr( eInflictor.destructible_type, "vehicle_" ) ) - sWeapon = "destructible_car"; - } - - prof_end( "PlayerDamage flags/tweaks" ); - - // check for completely getting out of the damage - if ( !(iDFlags & level.iDFLAGS_NO_PROTECTION) ) - { - // items you own don't damage you in FFA - if ( !level.teamBased && attackerIsNPC && isDefined( eAttacker.owner ) && eAttacker.owner == victim ) - { - prof_end( "PlayerDamage player" ); - - if ( sMeansOfDeath == "MOD_CRUSH" ) - victim _suicide(); - - return; - } - - if ( ( isSubStr( sMeansOfDeath, "MOD_GRENADE" ) || isSubStr( sMeansOfDeath, "MOD_EXPLOSIVE" ) || isSubStr( sMeansOfDeath, "MOD_PROJECTILE" ) ) && isDefined( eInflictor ) && isDefined( eAttacker ) ) - { - // protect players from spawnkill grenades - if ( eInflictor.classname == "grenade" && ( victim.lastSpawnTime + 3500 ) > getTime() && isDefined( victim.lastSpawnPoint ) && distance( eInflictor.origin, victim.lastSpawnPoint.origin ) < 250 ) - { - prof_end( "PlayerDamage player" ); - return; - } - - victim.explosiveInfo = []; - victim.explosiveInfo[ "damageTime" ] = getTime(); - victim.explosiveInfo[ "damageId" ] = eInflictor getEntityNumber(); - victim.explosiveInfo[ "returnToSender" ] = false; - victim.explosiveInfo[ "counterKill" ] = false; - victim.explosiveInfo[ "chainKill" ] = false; - victim.explosiveInfo[ "cookedKill" ] = false; - victim.explosiveInfo[ "throwbackKill" ] = false; - victim.explosiveInfo[ "suicideGrenadeKill" ] = false; - victim.explosiveInfo[ "weapon" ] = sWeapon; - - isFrag = isSubStr( sWeapon, "frag_" ); - - if ( eAttacker != victim ) - { - if ( ( isSubStr( sWeapon, "c4_" ) || isSubStr( sWeapon, "claymore_" ) ) && isDefined( eAttacker ) && isDefined( eInflictor.owner ) ) - { - victim.explosiveInfo[ "returnToSender" ] = ( eInflictor.owner == victim ); - victim.explosiveInfo[ "counterKill" ] = isDefined( eInflictor.wasDamaged ); - victim.explosiveInfo[ "chainKill" ] = isDefined( eInflictor.wasChained ); - victim.explosiveInfo[ "bulletPenetrationKill" ] = isDefined( eInflictor.wasDamagedFromBulletPenetration ); - victim.explosiveInfo[ "cookedKill" ] = false; - } - - if ( isDefined( eAttacker.lastGrenadeSuicideTime ) && eAttacker.lastGrenadeSuicideTime >= gettime() - 50 && isFrag ) - victim.explosiveInfo[ "suicideGrenadeKill" ] = true; - } - - if ( isFrag ) - { - victim.explosiveInfo[ "cookedKill" ] = isDefined( eInflictor.isCooked ); - victim.explosiveInfo[ "throwbackKill" ] = isDefined( eInflictor.threwBack ); - } - - victim.explosiveInfo[ "stickKill" ] = isDefined( eInflictor.isStuck ) && eInflictor.isStuck == "enemy"; - victim.explosiveInfo[ "stickFriendlyKill" ] = isDefined( eInflictor.isStuck ) && eInflictor.isStuck == "friendly"; - } - - if ( isPlayer( eAttacker ) ) - eAttacker.pers[ "participation" ]++ ; - - prevHealthRatio = victim.health / victim.maxhealth; - - if ( attackerIsHittingTeammate ) - { - if ( !matchMakingGame() && isPlayer(eAttacker) ) - eAttacker incPlayerStat( "mostff", 1 ); - - prof_begin( "PlayerDamage player" );// profs automatically end when the function returns - if ( level.friendlyfire == 0 || ( !isPlayer(eAttacker) && level.friendlyfire != 1 ) )// no one takes damage - { - if ( sWeapon == "artillery_mp" || sWeapon == "stealth_bomb_mp" ) - victim damageShellshockAndRumble( eInflictor, sWeapon, sMeansOfDeath, iDamage, iDFlags, eAttacker ); - return; - } - else if ( level.friendlyfire == 1 )// the friendly takes damage - { - if ( iDamage < 1 ) - iDamage = 1; - - victim.lastDamageWasFromEnemy = false; - - victim finishPlayerDamageWrapper( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, stunFraction ); - } - else if ( ( level.friendlyfire == 2 ) && isReallyAlive( eAttacker ) )// only the attacker takes damage - { - iDamage = int( iDamage * .5 ); - if ( iDamage < 1 ) - iDamage = 1; - - eAttacker.lastDamageWasFromEnemy = false; - - eAttacker.friendlydamage = true; - eAttacker finishPlayerDamageWrapper( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, stunFraction ); - eAttacker.friendlydamage = undefined; - } - else if ( level.friendlyfire == 3 && isReallyAlive( eAttacker ) )// both friendly and attacker take damage - { - iDamage = int( iDamage * .5 ); - if ( iDamage < 1 ) - iDamage = 1; - - victim.lastDamageWasFromEnemy = false; - eAttacker.lastDamageWasFromEnemy = false; - - victim finishPlayerDamageWrapper( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, stunFraction ); - if ( isReallyAlive( eAttacker ) )// may have died due to friendly fire punishment - { - eAttacker.friendlydamage = true; - eAttacker finishPlayerDamageWrapper( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, stunFraction ); - eAttacker.friendlydamage = undefined; - } - } - - friendly = true; - - } - else// not hitting teammate - { - prof_begin( "PlayerDamage world" ); - - if ( iDamage < 1 ) - iDamage = 1; - - if ( isDefined( eAttacker ) && isPlayer( eAttacker ) ) - addAttacker( victim, eAttacker, eInflictor, sWeapon, iDamage, vPoint, vDir, sHitLoc, psOffsetTime, sMeansOfDeath ); - - if ( sMeansOfDeath == "MOD_EXPLOSIVE" || sMeansOfDeath == "MOD_GRENADE_SPLASH" && iDamage < victim.health ) - victim notify( "survived_explosion" ); - - if ( isdefined( eAttacker ) ) - level.lastLegitimateAttacker = eAttacker; - - if ( isdefined( eAttacker ) && isPlayer( eAttacker ) && isDefined( sWeapon ) ) - eAttacker thread maps\mp\gametypes\_weapons::checkHit( sWeapon, victim ); - - if ( isdefined( eAttacker ) && isPlayer( eAttacker ) && isDefined( sWeapon ) && eAttacker != victim ) - { - eAttacker thread maps\mp\_events::damagedPlayer( self, iDamage, sWeapon ); - victim.attackerPosition = eAttacker.origin; - } - else - { - victim.attackerPosition = undefined; - } - - if ( issubstr( sMeansOfDeath, "MOD_GRENADE" ) && isDefined( eInflictor.isCooked ) ) - victim.wasCooked = getTime(); - else - victim.wasCooked = undefined; - - victim.lastDamageWasFromEnemy = ( isDefined( eAttacker ) && ( eAttacker != victim ) ); - - if ( victim.lastDamageWasFromEnemy ) - eAttacker.damagedPlayers[ victim.guid ] = getTime(); - - victim finishPlayerDamageWrapper( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, stunFraction ); - - if ( isDefined( level.ac130player ) && isDefined( eAttacker ) && ( level.ac130player == eAttacker ) ) - level notify( "ai_pain", victim ); - - victim thread maps\mp\gametypes\_missions::playerDamaged( eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, sHitLoc ); - - prof_end( "PlayerDamage world" ); - - } - - if ( attackerIsNPC && isDefined( eAttacker.gunner ) ) - damager = eAttacker.gunner; - else if( level.extraDamageFeedback && isDefined( eAttacker.owner ) ) - damager = eAttacker.owner; - else - damager = eAttacker; - - if ( isDefined( damager) && damager != victim && iDamage > 0 ) - { - if ( iDFlags & level.iDFLAGS_STUN ) - typeHit = "stun"; - else if ( victim _hasPerk( "specialty_armorvest" ) || (isExplosiveDamage( sMeansOfDeath ) && victim _hasPerk( "_specialty_blastshield" )) ) - typeHit = "hitBodyArmor"; - else if ( victim _hasPerk( "specialty_combathigh") ) - typeHit = "hitEndGame"; - else - typeHit = "standard"; - - damager thread maps\mp\gametypes\_damagefeedback::updateDamageFeedback( typeHit ); - } - - victim.hasDoneCombat = true; - } - - if ( isdefined( eAttacker ) && ( eAttacker != victim ) && !friendly ) - level.useStartSpawns = false; - - - //================= - // Damage Logging - //================= - - prof_begin( "PlayerDamage log" ); - - // why getEntityNumber() for victim and .clientid for attacker? - if ( getDvarInt( "g_debugDamage" ) ) - println( "client:" + victim getEntityNumber() + " health:" + victim.health + " attacker:" + eAttacker.clientid + " inflictor is player:" + isPlayer( eInflictor ) + " damage:" + iDamage + " hitLoc:" + sHitLoc ); - - if ( victim.sessionstate != "dead" ) - { - lpselfnum = victim getEntityNumber(); - lpselfname = victim.name; - lpselfteam = victim.pers[ "team" ]; - lpselfGuid = victim.guid; - lpattackerteam = ""; - - if ( isPlayer( eAttacker ) ) - { - lpattacknum = eAttacker getEntityNumber(); - lpattackGuid = eAttacker.guid; - lpattackname = eAttacker.name; - lpattackerteam = eAttacker.pers[ "team" ]; - } - else - { - lpattacknum = -1; - lpattackGuid = ""; - lpattackname = ""; - lpattackerteam = "world"; - } - - logPrint( "D;" + lpselfGuid + ";" + lpselfnum + ";" + lpselfteam + ";" + lpselfname + ";" + lpattackGuid + ";" + lpattacknum + ";" + lpattackerteam + ";" + lpattackname + ";" + sWeapon + ";" + iDamage + ";" + sMeansOfDeath + ";" + sHitLoc + "\n" ); - } - - HitlocDebug( eAttacker, victim, iDamage, sHitLoc, iDFlags ); - - /*if( isDefined( eAttacker ) && eAttacker != victim ) - { - if ( isPlayer( eAttacker ) ) - eAttacker incPlayerStat( "damagedone", iDamage ); - - victim incPlayerStat( "damagetaken", iDamage ); - }*/ - - prof_end( "PlayerDamage log" ); -} - - -addAttacker( victim, eAttacker, eInflictor, sWeapon, iDamage, vPoint, vDir, sHitLoc, psOffsetTime, sMeansOfDeath ) -{ - if ( !isDefined( victim.attackerData ) ) - victim.attackerData = []; - - if ( !isDefined( victim.attackerData[ eAttacker.guid ] ) ) - { - victim.attackers[ eAttacker.guid ] = eAttacker; - // we keep an array of attackers by their client ID so we can easily tell - // if they're already one of the existing attackers in the above if(). - // we store in this array data that is useful for other things, like challenges - victim.attackerData[ eAttacker.guid ] = SpawnStruct(); - victim.attackerData[ eAttacker.guid ].damage = 0; - victim.attackerData[ eAttacker.guid ].attackerEnt = eAttacker; - victim.attackerData[ eAttacker.guid ].firstTimeDamaged = getTime(); - } - if ( maps\mp\gametypes\_weapons::isPrimaryWeapon( sWeapon ) && ! maps\mp\gametypes\_weapons::isSideArm( sWeapon ) ) - victim.attackerData[ eAttacker.guid ].isPrimary = true; - - victim.attackerData[ eAttacker.guid ].damage += iDamage; - victim.attackerData[ eAttacker.guid ].weapon = sWeapon; - victim.attackerData[ eAttacker.guid ].vPoint = vPoint; - victim.attackerData[ eAttacker.guid ].vDir = vDir; - victim.attackerData[ eAttacker.guid ].sHitLoc = sHitLoc; - victim.attackerData[ eAttacker.guid ].psOffsetTime = psOffsetTime; - victim.attackerData[ eAttacker.guid ].sMeansOfDeath = sMeansOfDeath; - victim.attackerData[ eAttacker.guid ].attackerEnt = eAttacker; - victim.attackerData[ eAttacker.guid ].lasttimeDamaged = getTime(); - - if ( isDefined( eInflictor ) && !isPlayer( eInflictor ) && isDefined( eInflictor.primaryWeapon ) ) - victim.attackerData[ eAttacker.guid ].sPrimaryWeapon = eInflictor.primaryWeapon; - else if ( isDefined( eAttacker ) && isPlayer( eAttacker ) && eAttacker getCurrentPrimaryWeapon() != "none" ) - victim.attackerData[ eAttacker.guid ].sPrimaryWeapon = eAttacker getCurrentPrimaryWeapon(); - else - victim.attackerData[ eAttacker.guid ].sPrimaryWeapon = undefined; -} - -resetAttackerList() -{ - self endon( "disconnect" ); - self endon( "death" ); - level endon( "game_ended" ); - - //wait is to offset premature calling in _healthOverlay - wait( 1.75 ); - self.attackers = []; - self.attackerData = []; -} - - -Callback_PlayerDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime ) -{ - Callback_PlayerDamage_internal( eInflictor, eAttacker, self, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime ); -} - - -finishPlayerDamageWrapper( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, stunFraction ) -{ - if( level.allowPrintDamage ) - { - if ( isDefined( eAttacker ) && isPlayer( eAttacker ) && eAttacker.printDamage ) - eAttacker iPrintLnBold( iDamage ); - else if( isDefined( eAttacker.owner ) && isPlayer( eAttacker.owner ) && eAttacker.owner.printDamage ) - eAttacker.owner iPrintLnBold( iDamage ); - } - - if( level.extraDamageFeedback ) - { - if( sWeapon == "nuke_mp" ) - { - if ( self _hasPerk( "specialty_armorvest" ) || self _hasPerk( "_specialty_blastshield") ) - typeHit = "hitBodyArmor"; - else if ( self _hasPerk( "specialty_combathigh") ) - typeHit = "hitEndGame"; - else - typeHit = "standard"; - - eAttacker thread maps\mp\gametypes\_damagefeedback::updateDamageFeedback( typeHit ); - } - - if( sHitLoc == "head" || sHitLoc == "helmet" ) - { - if ( isDefined( eAttacker ) && isPlayer( eAttacker ) ) - eAttacker playLocalSound( "bullet_impact_headshot_2" ); - else if( isDefined( eAttacker.owner ) && isPlayer( eAttacker.owner ) ) - eAttacker.owner playLocalSound( "bullet_impact_headshot_2" ); - } - } - - if ( (self isUsingRemote() ) && (iDamage >= self.health) && !(iDFlags & level.iDFLAGS_STUN) ) - { - if ( !isDefined( vDir ) ) - vDir = ( 0,0,0 ); - - if ( !isDefined( eAttacker ) && !isDefined( eInflictor ) ) - { - eAttacker = self; - eInflictor = eAttacker; - } - - assert( isDefined( eAttacker ) ); - assert( isDefined( eInflictor ) ); - - PlayerKilled_internal( eInflictor, eAttacker, self, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, 0, true ); - } - else - { - if ( !self Callback_KillingBlow( eInflictor, eAttacker, iDamage - (iDamage * stunFraction), iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime ) ) - return; - - self finishPlayerDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, stunFraction ); - } - - if ( sMeansOfDeath == "MOD_EXPLOSIVE_BULLET" ) - self shellShock( "damage_mp", getDvarFloat( "scr_csmode" ) ); - - self damageShellshockAndRumble( eInflictor, sWeapon, sMeansOfDeath, iDamage, iDFlags, eAttacker ); -} - - -Callback_PlayerLastStand( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration ) -{ - - lastStandParams = spawnStruct(); - lastStandParams.eInflictor = eInflictor; - lastStandParams.attacker = attacker; - lastStandParams.iDamage = iDamage; - lastStandParams.attackerPosition = attacker.origin; - if ( attacker == self ) - lastStandParams.sMeansOfDeath = "MOD_SUICIDE"; - else - lastStandParams.sMeansOfDeath = sMeansOfDeath; - - lastStandParams.sWeapon = sWeapon; - if ( isDefined( attacker ) && isPlayer( attacker ) && attacker getCurrentPrimaryWeapon() != "none" ) - lastStandParams.sPrimaryWeapon = attacker getCurrentPrimaryWeapon(); - else - lastStandParams.sPrimaryWeapon = undefined; - lastStandParams.vDir = vDir; - lastStandParams.sHitLoc = sHitLoc; - lastStandParams.lastStandStartTime = getTime(); - - mayDoLastStand = mayDoLastStand( sWeapon, sMeansOfDeath, sHitLoc ); - - //if ( mayDoLastStand ) - // mayDoLastStand = !self checkForceBleedOut(); - - if ( isDefined( self.endGame ) ) - mayDoLastStand = false; - - if ( level.teamBased && isDefined( attacker.team ) && attacker.team == self.team ) - mayDoLastStand = false; - - /# - if ( getdvar( "scr_forcelaststand" ) == "1" ) - mayDoLastStand = true; - #/ - - if ( !mayDoLastStand ) - { - self.lastStandParams = lastStandParams; - self.useLastStandParams = true; - self _suicide(); - return; - } - - self.inLastStand = true; - - notifyData = spawnStruct(); - if ( self _hasPerk( "specialty_finalstand" ) ) - { - notifyData.titleText = game[ "strings" ][ "final_stand" ]; - notifyData.iconName = "specialty_finalstand"; - } - else - { - notifyData.titleText = game[ "strings" ][ "last_stand" ]; - notifyData.iconName = "specialty_pistoldeath"; - } - notifyData.glowColor = ( 1, 0, 0 ); - notifyData.sound = "mp_last_stand"; - notifyData.duration = 2.0; - - self.health = 1; - - self thread maps\mp\gametypes\_hud_message::notifyMessage( notifyData ); - - grenadeTypePrimary = "frag_grenade_mp"; - - if ( isDefined( level.ac130player ) && isDefined( attacker ) && level.ac130player == attacker ) - level notify( "ai_crawling", self ); - - if ( self _hasPerk( "specialty_finalstand" ) ) - { - self.lastStandParams = lastStandParams; - self.inFinalStand = true; - - weaponList = self GetWeaponsListExclusives(); - foreach ( weapon in weaponList ) - self takeWeapon( weapon ); - - self _disableUsability(); - - self thread enableLastStandWeapons(); - self thread lastStandTimer( 20, true ); - } - /* - else if ( self _hasPerk( "specialty_c4death" ) ) - { - self.lastStandParams = lastStandParams; - - self takeAllWeapons(); - self giveWeapon( "c4Death_mp", 0, false ); - self switchToWeapon( "c4Death_mp" ); - self _disableUsability(); - self.inC4Death = true; - - //self thread dieAfterTime( 7 ); - self thread lastStandTimer( 10, false ); - self thread detonateOnUse(); - //self thread detonateOnDeath(); - } - */ - else if ( level.dieHardMode ) - { - self.lastStandParams = lastStandParams; - self thread enableLastStandWeapons(); - self thread lastStandTimer( 20, false ); - self _disableUsability(); - } - else // normal last stand - { - self.lastStandParams = lastStandParams; - - pistolWeapon = undefined; - - weaponsList = self GetWeaponsListPrimaries(); - foreach ( weapon in weaponsList ) - { - if ( maps\mp\gametypes\_weapons::isSideArm( weapon ) ) - pistolWeapon = weapon; - } - - if ( !isDefined( pistolWeapon ) ) - { - pistolWeapon = "beretta_mp"; - self _giveWeapon( pistolWeapon ); - } - - self giveMaxAmmo( pistolWeapon ); - self DisableWeaponSwitch(); - self _disableUsability(); - - if ( !self _hasPerk("specialty_laststandoffhand") ) - self DisableOffhandWeapons(); - - self switchToWeapon( pistolWeapon ); - - self thread lastStandTimer( 10, false ); - } -} - -dieAfterTime( time ) -{ - self endon( "death" ); - self endon( "disconnect" ); - self endon( "joined_team" ); - level endon( "game_ended" ); - - wait ( time ); - self.useLastStandParams = true; - self _suicide(); -} - -detonateOnUse() -{ - self endon( "death" ); - self endon( "disconnect" ); - self endon( "joined_team" ); - level endon( "game_ended" ); - - self waittill( "detonate" ); - self.useLastStandParams = true; - self c4DeathDetonate(); -} - -detonateOnDeath() -{ - self endon( "detonate" ); - self endon( "disconnect" ); - self endon( "joined_team" ); - level endon( "game_ended" ); - - self waittill( "death" ); - self c4DeathDetonate(); -} - -c4DeathDetonate() -{ - self playSound( "detpack_explo_default" ); - self.c4DeathEffect = playFX( level.c4Death, self.origin ); - RadiusDamage( self.origin, 400, 100, 100, self ); - - if ( isAlive( self ) ) - self _suicide(); -} - -enableLastStandWeapons() -{ - self endon( "death" ); - self endon( "disconnect" ); - level endon( "game_ended" ); - - self freezeControlsWrapper( true ); - wait .30; - - self freezeControlsWrapper( false ); -} - -lastStandTimer( delay, isFinalStand ) -{ - self endon( "death" ); - self endon( "disconnect" ); - self endon( "revive"); - level endon( "game_ended" ); - - level notify ( "player_last_stand" ); - - self thread lastStandWaittillDeath(); - - self.lastStand = true; - - if ( !isFinalStand && !level.dieHardMode && ( !isDefined( self.inC4Death ) || !self.inC4Death ) ) - { - self thread lastStandAllowSuicide(); - self setLowerMessage( "last_stand", &"PLATFORM_COWARDS_WAY_OUT" ); - self thread lastStandKeepOverlay(); - } - - if ( level.dieHardMode == 1 && level.dieHardMode != 2 ) - { - reviveEnt = spawn( "script_model", self.origin ); - reviveEnt setModel( "tag_origin" ); - reviveEnt setCursorHint( "HINT_NOICON" ); - reviveEnt setHintString( &"PLATFORM_REVIVE" ); - - reviveEnt reviveSetup( self ); - reviveEnt endon ( "death" ); - - reviveIcon = newTeamHudElem( self.team ); - reviveIcon setShader( "waypoint_revive", 8, 8 ); - reviveIcon setWaypoint( true, true ); - reviveIcon SetTargetEnt( self ); - reviveIcon thread destroyOnReviveEntDeath( reviveEnt ); - - reviveIcon.color = (0.33, 0.75, 0.24); - self playDeathSound(); - - if ( isFinalStand ) - { - wait( delay ); - - if ( self.inFinalStand ) - self thread lastStandBleedOut( isFinalStand, reviveEnt ); - } - - return; - } - else if( level.dieHardMode == 2 ) - { - self thread lastStandKeepOverlay(); - reviveEnt = spawn( "script_model", self.origin ); - reviveEnt setModel( "tag_origin" ); - reviveEnt setCursorHint( "HINT_NOICON" ); - reviveEnt setHintString( &"PLATFORM_REVIVE" ); - - reviveEnt reviveSetup( self ); - reviveEnt endon ( "death" ); - - reviveIcon = newTeamHudElem( self.team ); - reviveIcon setShader( "waypoint_revive", 8, 8 ); - reviveIcon setWaypoint( true, true ); - reviveIcon SetTargetEnt( self ); - reviveIcon thread destroyOnReviveEntDeath( reviveEnt ); - - reviveIcon.color = (0.33, 0.75, 0.24); - self playDeathSound(); - - if ( isFinalStand ) - { - wait( delay ); - - if ( self.inFinalStand ) - self thread lastStandBleedOut( isFinalStand, reviveEnt ); - } - - wait delay / 3; - reviveIcon.color = (1.0, 0.64, 0.0); - - while ( reviveEnt.inUse ) - wait ( 0.05 ); - - self playDeathSound(); - wait delay / 3; - reviveIcon.color = (1.0, 0.0, 0.0); - - while ( reviveEnt.inUse ) - wait ( 0.05 ); - - self playDeathSound(); - wait delay / 3; - - while ( reviveEnt.inUse ) - wait ( 0.05 ); - - wait( 0.05 ); - self thread lastStandBleedOut( isFinalStand ); - return; - } - - wait( delay ); - self thread lastStandBleedout( isFinalStand ); - -} - -maxHealthOverlay( maxHealth, refresh ) -{ - self endon( "stop_maxHealthOverlay" ); - self endon( "revive" ); - self endon( "death" ); - - for( ;; ) - { - self.health -= 1; - self.maxHealth = maxHealth; - wait( .05 ); - self.maxHealth = 50; - self.health += 1; - - wait ( .50 ); - } -} - -lastStandBleedOut( reviveOnBleedOut, reviveEnt ) -{ - if ( reviveOnBleedOut ) - { - self.lastStand = undefined; - self.inFinalStand = false; - self clearLowerMessage( "last_stand" ); - maps\mp\gametypes\_playerlogic::lastStandRespawnPlayer(); - - if( isDefined( reviveEnt ) ) - reviveEnt Delete(); - } - else - { - self.useLastStandParams = true; - self.beingRevived = false; - self _suicide(); - } -} - - -lastStandAllowSuicide() -{ - self endon( "death" ); - self endon( "disconnect" ); - self endon( "game_ended" ); - self endon( "revive"); - - while ( 1 ) - { - if ( self useButtonPressed() ) - { - pressStartTime = gettime(); - while ( self useButtonPressed() ) - { - wait .05; - if ( gettime() - pressStartTime > 700 ) - break; - } - if ( gettime() - pressStartTime > 700 ) - break; - } - wait .05; - } - - self thread lastStandBleedOut( false ); -} - -lastStandKeepOverlay() -{ - level endon( "game_ended" ); - self endon( "death" ); - self endon( "disconnect" ); - self endon( "revive" ); - - // keep the health overlay going by making code think the player is getting damaged - while ( !level.gameEnded ) - { - self.health = 2; - wait .05; - self.health = 1; - wait .5; - } - - self.health = self.maxhealth; -} - - -lastStandWaittillDeath() -{ - self endon( "disconnect" ); - self endon( "revive" ); - level endon( "game_ended" ); - self waittill( "death" ); - - self clearLowerMessage( "last_stand" ); - self.lastStand = undefined; -} - - -mayDoLastStand( sWeapon, sMeansOfDeath, sHitLoc ) -{ - if ( sMeansOfDeath == "MOD_TRIGGER_HURT" ) - return false; - - if ( sMeansOfDeath != "MOD_PISTOL_BULLET" && sMeansOfDeath != "MOD_RIFLE_BULLET" && sMeansOfDeath != "MOD_FALLING" && sMeansOfDeath != "MOD_EXPLOSIVE_BULLET" ) - return false; - - if ( sMeansOfDeath == "MOD_IMPACT" && sWeapon == "throwingknife_mp" ) - return false; - - if ( sMeansOfDeath == "MOD_IMPACT" && ( sWeapon == "m79_mp" || isSubStr(sWeapon, "gl_") ) ) - return false; - - if ( isHeadShot( sWeapon, sHitLoc, sMeansOfDeath ) ) - return false; - - if ( self isUsingRemote() ) - return false; - - return true; -} - - -ensureLastStandParamsValidity() -{ - // attacker may have become undefined if the player that killed me has disconnected - if ( !isDefined( self.lastStandParams.attacker ) ) - self.lastStandParams.attacker = self; -} - -getHitLocHeight( sHitLoc ) -{ - switch( sHitLoc ) - { - case "helmet": - case "head": - case "neck": - return 60; - case "torso_upper": - case "right_arm_upper": - case "left_arm_upper": - case "right_arm_lower": - case "left_arm_lower": - case "right_hand": - case "left_hand": - case "gun": - return 48; - case "torso_lower": - return 40; - case "right_leg_upper": - case "left_leg_upper": - return 32; - case "right_leg_lower": - case "left_leg_lower": - return 10; - case "right_foot": - case "left_foot": - return 5; - } - return 48; -} - -delayStartRagdoll( ent, sHitLoc, vDir, sWeapon, eInflictor, sMeansOfDeath ) -{ - if ( isDefined( ent ) ) - { - deathAnim = ent getCorpseAnim(); - if ( animhasnotetrack( deathAnim, "ignore_ragdoll" ) ) - return; - } - - wait( 0.2 ); - - if ( !isDefined( ent ) ) - return; - - if ( ent isRagDoll() ) - return; - - deathAnim = ent getcorpseanim(); - - startFrac = 0.35; - - if ( animhasnotetrack( deathAnim, "start_ragdoll" ) ) - { - times = getnotetracktimes( deathAnim, "start_ragdoll" ); - if ( isDefined( times ) ) - startFrac = times[ 0 ]; - } - - waitTime = startFrac * getanimlength( deathAnim ); - wait( waitTime ); - - if ( isDefined( ent ) ) - { - ent startragdoll( 1 ); - } -} - - -getMostKilledBy() -{ - mostKilledBy = ""; - killCount = 0; - - killedByNames = getArrayKeys( self.killedBy ); - - for ( index = 0; index < killedByNames.size; index++ ) - { - killedByName = killedByNames[ index ]; - if ( self.killedBy[ killedByName ] <= killCount ) - continue; - - killCount = self.killedBy[ killedByName ]; - mostKilleBy = killedByName; - } - - return mostKilledBy; -} - - -getMostKilled() -{ - mostKilled = ""; - killCount = 0; - - killedNames = getArrayKeys( self.killedPlayers ); - - for ( index = 0; index < killedNames.size; index++ ) - { - killedName = killedNames[ index ]; - if ( self.killedPlayers[ killedName ] <= killCount ) - continue; - - killCount = self.killedPlayers[ killedName ]; - mostKilled = killedName; - } - - return mostKilled; -} - - -damageShellshockAndRumble( eInflictor, sWeapon, sMeansOfDeath, iDamage, iDFlags, eAttacker ) -{ - self thread maps\mp\gametypes\_weapons::onWeaponDamage( eInflictor, sWeapon, sMeansOfDeath, iDamage, eAttacker ); - self PlayRumbleOnEntity( "damage_heavy" ); -} - - -reviveSetup( owner ) -{ - team = owner.team; - - self linkTo( owner, "tag_origin" ); - - self.owner = owner; - self.inUse = false; - self makeUsable(); - self updateUsableByTeam( team ); - self thread trackTeamChanges( team ); - - self thread reviveTriggerThink( team ); - - self thread deleteOnReviveOrDeathOrDisconnect(); -} - - -deleteOnReviveOrDeathOrDisconnect() -{ - self endon ( "death" ); - - self.owner waittill_any ( "death", "disconnect" ); - - self delete(); -} - - -updateUsableByTeam( team ) -{ - foreach (player in level.players) - { - if ( team == player.team && player != self.owner ) - self enablePlayerUse( player ); - else - self disablePlayerUse( player ); - } -} - - -trackTeamChanges( team ) -{ - self endon ( "death" ); - - while ( true ) - { - level waittill ( "joined_team" ); - - self updateUsableByTeam( team ); - } -} - - -trackLastStandChanges( team ) -{ - self endon ( "death" ); - - while ( true ) - { - level waittill ( "player_last_stand" ); - - self updateUsableByTeam( team ); - } -} - - -reviveTriggerThink( team ) -{ - self endon ( "death" ); - level endon ( "game_ended" ); - - for ( ;; ) - { - self waittill ( "trigger", player ); - self.owner.beingRevived = true; - - if ( isDefined(player.beingRevived) && player.beingRevived ) - { - self.owner.beingRevived = false; - continue; - } - - self makeUnUsable(); - self.owner freezeControlsWrapper( true ); - - revived = self useHoldThink( player ); - self.owner.beingRevived = false; - - if ( !isAlive( self.owner ) ) - { - self delete(); - return; - } - - self.owner freezeControlsWrapper( false ); - - if ( revived ) - { - player thread maps\mp\gametypes\_hud_message::SplashNotifyDelayed( "reviver", 200 ); - player thread maps\mp\gametypes\_rank::giveRankXP( "reviver", 200 ); - - self.owner.lastStand = undefined; - self.owner clearLowerMessage( "last_stand" ); - - if ( self.owner _hasPerk( "specialty_lightweight" ) ) - self.owner.moveSpeedScaler = 1.07; - else - self.owner.moveSpeedScaler = 1; - - self.owner.maxHealth = 100; - - self.owner maps\mp\gametypes\_weapons::updateMoveSpeedScale( "primary" ); - self.owner maps\mp\gametypes\_playerlogic::lastStandRespawnPlayer(); - - self.owner setPerk( "specialty_pistoldeath", true ); - self.owner.beingRevived = false; - - self delete(); - return; - } - - self makeUsable(); - self updateUsableByTeam( team ); - } -} - - - -/* -============= -useHoldThink - -Claims the use trigger for player and displays a use bar -Returns true if the player sucessfully fills the use bar -============= -*/ -useHoldThink( player ) -{ - reviveSpot = spawn( "script_origin", self.origin ); - reviveSpot hide(); - player playerLinkTo( reviveSpot ); - player PlayerLinkedOffsetEnable(); - - player _disableWeapon(); - - self.curProgress = 0; - self.inUse = true; - self.useRate = 0; - self.useTime = 3000; - - player thread personalUseBar( self ); - - result = useHoldThinkLoop( player ); - - if ( isDefined( player ) && isReallyAlive( player ) ) - { - player Unlink(); - player _enableWeapon(); - } - - if ( isDefined( result ) && result ) - { - self.owner thread maps\mp\gametypes\_hud_message::playerCardSplashNotify( "revived", player ); - self.owner.inlaststand = false; - return true; - } - - self.inUse = false; - reviveSpot Delete(); - return false; -} - - -personalUseBar( object ) -{ - useBar = self createPrimaryProgressBar(); - useBarText = self createPrimaryProgressBarText(); - useBarText setText( &"MPUI_REVIVING" ); - - objUseBar = object.owner createPrimaryProgressBar(); - objUseBarText = object.owner createPrimaryProgressBarText(); - objUseBarText setText( &"MPUI_BEING_REVIVED" ); - - lastRate = -1; - while ( isReallyAlive( self ) && isDefined( object ) && object.inUse && !level.gameEnded && isDefined( self ) ) - { - if ( lastRate != object.useRate ) - { - if( object.curProgress > object.useTime) - object.curProgress = object.useTime; - - useBar updateBar( object.curProgress / object.useTime, (1000 / object.useTime) * object.useRate ); - objUseBar updateBar( object.curProgress / object.useTime, (1000 / object.useTime) * object.useRate ); - - if ( !object.useRate ) - { - useBar hideElem(); - useBarText hideElem(); - - objUseBar hideElem(); - objUseBarText hideElem(); - } - else - { - useBar showElem(); - useBarText showElem(); - - objUseBar showElem(); - objUseBarText showElem(); - } - } - lastRate = object.useRate; - wait ( 0.05 ); - } - - // when the players disconnect the hudElems are destroyed automatically - if ( isDefined( useBar ) ) - useBar destroyElem(); - if ( isDefined( useBarText ) ) - useBarText destroyElem(); - - if ( isDefined( objUseBar ) ) - objUseBar destroyElem(); - if ( isDefined( objUseBarText ) ) - objUseBarText destroyElem(); -} - - -useHoldThinkLoop( player ) -{ - level endon ( "game_ended" ); - self.owner endon( "death" ); - self.owner endon( "disconnect" ); - - while( isReallyAlive( player ) && player useButtonPressed() && self.curProgress < self.useTime ) - { - self.curProgress += (50 * self.useRate); - self.useRate = 1; /* * player.objectiveScaler;*/ - - if ( self.curProgress >= self.useTime ) - { - self.inUse = false; - - return isReallyAlive( player ); - } - - wait 0.05; - } - - return false; -} - - -Callback_KillingBlow( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime ) -{ - if ( isDefined(self.lastDamageWasFromEnemy) && self.lastDamageWasFromEnemy && iDamage >= self.health && isDefined( self.combatHigh ) && self.combatHigh == "specialty_endgame" ) - { - self setAdrenaline( 0 ); - self _setPerk( "specialty_endgame" ); - return false; - } - - return true; -} - - -emitFallDamage( iDamage ) -{ - PhysicsExplosionSphere( self.origin, 64, 64, 1 ); - - // get the entities we landed on - damageEnts = []; - for ( testAngle = 0; testAngle < 360; testAngle += 30 ) - { - xOffset = cos( testAngle ) * 16; - yOffset = sin( testAngle ) * 16; - - traceData = bulletTrace( self.origin + (xOffset, yOffset, 4), self.origin + (xOffset,yOffset,-6), true, self ); - //thread drawLine( self.origin + (xOffset, yOffset, 4), self.origin + (xOffset,yOffset,-6), 10.0 ); - - if ( isDefined( traceData["entity"] ) && isDefined( traceData["entity"].targetname ) && (traceData["entity"].targetname == "destructible_vehicle" || traceData["entity"].targetname == "destructible_toy") ) - damageEnts[damageEnts.size] = traceData["entity"]; - } - - if ( damageEnts.size ) - { - damageOwner = spawn( "script_origin", self.origin ); - damageOwner hide(); - damageOwner.type = "soft_landing"; - damageOwner.destructibles = damageEnts; - radiusDamage( self.origin, 64, 100, 100, damageOwner ); - - wait ( 0.1 ); - damageOwner delete(); - } -} - -drawLine( start, end, timeSlice ) -{ - drawTime = int(timeSlice * 20); - for( time = 0; time < drawTime; time++ ) - { - line( start, end, (1,0,0),false, 1 ); - wait ( 0.05 ); - } -} - -isFlankKill( victim, attacker ) -{ - victimForward = anglestoforward( victim.angles ); - victimForward = ( victimForward[0], victimForward[1], 0 ); - victimForward = VectorNormalize( victimForward ); - - attackDirection = victim.origin - attacker.origin; - attackDirection = ( attackDirection[0], attackDirection[1], 0 ); - attackDirection = VectorNormalize( attackDirection ); - - dotProduct = VectorDot( victimForward, attackDirection ); - if ( dotProduct > 0 ) // 0 = cos( 90 ), 180 degree arc total - return true; - else - return false; -} - -_obituary( victim, attacker, sWeapon, sMeansOfDeath ) -{ - victimTeam = victim.team; - - foreach ( player in level.players ) - { - playerTeam = player.team; - if ( playerTeam == "spectator" ) - player iPrintLn( &"MP_OBITUARY_NEUTRAL", attacker.name, victim.name ); - else if ( playerTeam == victimTeam ) - player iPrintLn( &"MP_OBITUARY_ENEMY", attacker.name, victim.name ); - else - player iPrintLn( &"MP_OBITUARY_FRIENDLY", attacker.name, victim.name ); - } -} - - -logPrintPlayerDeath( lifeId, attacker, iDamage, sMeansOfDeath, sWeapon, sPrimaryWeapon, sHitLoc ) -{ - // create a lot of redundant data for the log print - lpselfnum = self getEntityNumber(); - lpselfname = self.name; - lpselfteam = self.team; - lpselfguid = self.guid; - - if ( isPlayer( attacker ) ) - { - lpattackGuid = attacker.guid; - lpattackname = attacker.name; - lpattackerteam = attacker.team; - lpattacknum = attacker getEntityNumber(); - attackerString = attacker getXuid() + "(" + lpattackname + ")"; - } - else - { - lpattackGuid = ""; - lpattackname = ""; - lpattackerteam = "world"; - lpattacknum = -1; - attackerString = "none"; - } - - logPrint( "K;" + lpselfguid + ";" + lpselfnum + ";" + lpselfteam + ";" + lpselfname + ";" + lpattackguid + ";" + lpattacknum + ";" + lpattackerteam + ";" + lpattackname + ";" + sWeapon + ";" + iDamage + ";" + sMeansOfDeath + ";" + sHitLoc + "\n" ); -} - - -destroyOnReviveEntDeath( reviveEnt ) -{ - reviveEnt waittill ( "death" ); - - self destroy(); -} diff --git a/userraw/maps/mp/gametypes/_gamelogic.gsc b/userraw/maps/mp/gametypes/_gamelogic.gsc deleted file mode 100644 index 77ee8c2..0000000 --- a/userraw/maps/mp/gametypes/_gamelogic.gsc +++ /dev/null @@ -1,3083 +0,0 @@ -#include maps\mp\_utility; -#include maps\mp\gametypes\_hud_util; -#include common_scripts\utility; - -FACTION_REF_COL = 0; -FACTION_NAME_COL = 1; -FACTION_SHORT_NAME_COL = 1; -FACTION_WIN_GAME_COL = 3; -FACTION_WIN_ROUND_COL = 4; -FACTION_MISSION_ACCOMPLISHED_COL = 5; -FACTION_ELIMINATED_COL = 6; -FACTION_FORFEITED_COL = 7; -FACTION_ICON_COL = 8; -FACTION_HUD_ICON_COL = 9; -FACTION_VOICE_PREFIX_COL = 10; -FACTION_SPAWN_MUSIC_COL = 11; -FACTION_WIN_MUSIC_COL = 12; -FACTION_COLOR_R_COL = 13; -FACTION_COLOR_G_COL = 14; -FACTION_COLOR_B_COL = 15; - -// when a team leaves completely, that team forfeited, team left wins round, ends game -onForfeit( team ) -{ - if ( isDefined( level.forfeitInProgress ) ) - return; - - level endon( "abort_forfeit" ); //end if the team is no longer in forfeit status - - level.forfeitInProgress = true; - - // in 1v1 DM, give players time to change teams - if ( !level.teambased && level.players.size > 1 ) - wait 10; - - forfeit_delay = 20.0; //forfeit wait, for switching teams and such - - foreach ( player in level.players ) - { - player setLowerMessage( "forfeit_warning", game["strings"]["opponent_forfeiting_in"], forfeit_delay, 100 ); - player thread forfeitWaitforAbort(); - } - - wait ( forfeit_delay ); - - endReason = &""; - if ( !isDefined( team ) ) - { - endReason = game["strings"]["players_forfeited"]; - winner = level.players[0]; - } - else if ( team == "allies" ) - { - endReason = game["strings"]["allies_forfeited"]; - winner = "axis"; - } - else if ( team == "axis" ) - { - endReason = game["strings"]["axis_forfeited"]; - winner = "allies"; - } - else - { - //shouldn't get here - assertEx( isdefined( team ), "Forfeited team is not defined" ); - assertEx( 0, "Forfeited team " + team + " is not allies or axis" ); - winner = "tie"; - } - //exit game, last round, no matter if round limit reached or not - level.forcedEnd = true; - - if ( isPlayer( winner ) ) - logString( "forfeit, win: " + winner getXuid() + "(" + winner.name + ")" ); - else - logString( "forfeit, win: " + winner + ", allies: " + game["teamScores"]["allies"] + ", opfor: " + game["teamScores"]["axis"] ); - thread endGame( winner, endReason ); -} - - -forfeitWaitforAbort() -{ - self endon ( "disconnect" ); - level endon ( "game_ended" ); - - level waittill ( "abort_forfeit" ); - - self clearLowerMessage( "forfeit_warning" ); -} - - -default_onDeadEvent( team ) -{ - if ( team == "allies" ) - { - iPrintLn( game["strings"]["allies_eliminated"] ); - - logString( "team eliminated, win: opfor, allies: " + game["teamScores"]["allies"] + ", opfor: " + game["teamScores"]["axis"] ); - - thread endGame( "axis", game["strings"]["allies_eliminated"] ); - } - else if ( team == "axis" ) - { - iPrintLn( game["strings"]["axis_eliminated"] ); - - logString( "team eliminated, win: allies, allies: " + game["teamScores"]["allies"] + ", opfor: " + game["teamScores"]["axis"] ); - - thread endGame( "allies", game["strings"]["axis_eliminated"] ); - } - else - { - logString( "tie, allies: " + game["teamScores"]["allies"] + ", opfor: " + game["teamScores"]["axis"] ); - - if ( level.teamBased ) - thread endGame( "tie", game["strings"]["tie"] ); - else - thread endGame( undefined, game["strings"]["tie"] ); - } -} - - -default_onOneLeftEvent( team ) -{ - if ( level.teamBased ) - { - assert( team == "allies" || team == "axis" ); - - lastPlayer = getLastLivingPlayer( team ); - lastPlayer thread giveLastOnTeamWarning(); - } - else - { - lastPlayer = getLastLivingPlayer(); - - logString( "last one alive, win: " + lastPlayer.name ); - thread endGame( lastPlayer, &"MP_ENEMIES_ELIMINATED" ); - } - - return true; -} - - -default_onTimeLimit() -{ - winner = undefined; - - if ( level.teamBased ) - { - if ( game["teamScores"]["allies"] == game["teamScores"]["axis"] ) - winner = "tie"; - else if ( game["teamScores"]["axis"] > game["teamScores"]["allies"] ) - winner = "axis"; - else - winner = "allies"; - - logString( "time limit, win: " + winner + ", allies: " + game["teamScores"]["allies"] + ", opfor: " + game["teamScores"]["axis"] ); - } - else - { - winner = maps\mp\gametypes\_gamescore::getHighestScoringPlayer(); - - if ( isDefined( winner ) ) - logString( "time limit, win: " + winner.name ); - else - logString( "time limit, tie" ); - } - - thread endGame( winner, game["strings"]["time_limit_reached"] ); -} - - -default_onHalfTime() -{ - winner = undefined; - - thread endGame( "halftime", game["strings"]["time_limit_reached"] ); -} - - -forceEnd() -{ - if ( level.hostForcedEnd || level.forcedEnd ) - return; - - winner = undefined; - - if ( level.teamBased ) - { - if ( game["teamScores"]["allies"] == game["teamScores"]["axis"] ) - winner = "tie"; - else if ( game["teamScores"]["axis"] > game["teamScores"]["allies"] ) - winner = "axis"; - else - winner = "allies"; - logString( "host ended game, win: " + winner + ", allies: " + game["teamScores"]["allies"] + ", opfor: " + game["teamScores"]["axis"] ); - } - else - { - winner = maps\mp\gametypes\_gamescore::getHighestScoringPlayer(); - if ( isDefined( winner ) ) - logString( "host ended game, win: " + winner.name ); - else - logString( "host ended game, tie" ); - } - - level.forcedEnd = true; - level.hostForcedEnd = true; - - if ( level.splitscreen ) - endString = &"MP_ENDED_GAME"; - else - endString = &"MP_HOST_ENDED_GAME"; - - thread endGame( winner, endString ); -} - - -onScoreLimit() -{ - scoreText = game["strings"]["score_limit_reached"]; - winner = undefined; - - if ( level.teamBased ) - { - if ( game["teamScores"]["allies"] == game["teamScores"]["axis"] ) - winner = "tie"; - else if ( game["teamScores"]["axis"] > game["teamScores"]["allies"] ) - winner = "axis"; - else - winner = "allies"; - logString( "scorelimit, win: " + winner + ", allies: " + game["teamScores"]["allies"] + ", opfor: " + game["teamScores"]["axis"] ); - } - else - { - winner = maps\mp\gametypes\_gamescore::getHighestScoringPlayer(); - if ( isDefined( winner ) ) - logString( "scorelimit, win: " + winner.name ); - else - logString( "scorelimit, tie" ); - } - - thread endGame( winner, scoreText ); - return true; -} - - -updateGameEvents() -{ - if ( matchMakingGame() && !level.inGracePeriod ) - { - if ( level.teamBased ) - { - // if allies disconnected, and axis still connected, axis wins round and game ends to lobby - if ( level.teamCount["allies"] < 1 && level.teamCount["axis"] > 0 && game["state"] == "playing" ) - { - //allies forfeited - thread onForfeit( "allies" ); - return; - } - - // if axis disconnected, and allies still connected, allies wins round and game ends to lobby - if ( level.teamCount["axis"] < 1 && level.teamCount["allies"] > 0 && game["state"] == "playing" ) - { - //axis forfeited - thread onForfeit( "axis" ); - return; - } - - if ( level.teamCount["axis"] > 0 && level.teamCount["allies"] > 0 ) - { - level.forfeitInProgress = undefined; - level notify( "abort_forfeit" ); - } - } - else - { - if ( level.teamCount["allies"] + level.teamCount["axis"] == 1 && level.maxPlayerCount > 1 ) - { - thread onForfeit(); - return; - } - - if ( level.teamCount["axis"] + level.teamCount["allies"] > 1 ) - { - level.forfeitInProgress = undefined; - level notify( "abort_forfeit" ); - } - } - } - - if ( !getGametypeNumLives() && (!isDefined( level.disableSpawning ) || !level.disableSpawning) ) - return; - - if ( !gameHasStarted() ) - return; - - if ( level.inGracePeriod ) - return; - - if ( level.teamBased ) - { - livesCount["allies"] = level.livesCount["allies"]; - livesCount["axis"] = level.livesCount["axis"]; - - if ( isDefined( level.disableSpawning ) && level.disableSpawning ) - { - livesCount["allies"] = 0; - livesCount["axis"] = 0; - } - - // if both allies and axis were alive and now they are both dead in the same instance - if ( !level.aliveCount["allies"] && !level.aliveCount["axis"] && !livesCount["allies"] && !livesCount["axis"] ) - { - return [[level.onDeadEvent]]( "all" ); - } - - // if allies were alive and now they are not - if ( !level.aliveCount["allies"] && !livesCount["allies"] ) - { - return [[level.onDeadEvent]]( "allies" ); - } - - // if axis were alive and now they are not - if ( !level.aliveCount["axis"] && !livesCount["axis"] ) - { - return [[level.onDeadEvent]]( "axis" ); - } - - // one ally left - if ( level.aliveCount["allies"] == 1 && !livesCount["allies"] ) - { - if ( !isDefined( level.oneLeftTime["allies"] ) ) - { - level.oneLeftTime["allies"] = getTime(); - return [[level.onOneLeftEvent]]( "allies" ); - } - } - - // one axis left - if ( level.aliveCount["axis"] == 1 && !livesCount["axis"] ) - { - if ( !isDefined( level.oneLeftTime["axis"] ) ) - { - level.oneLeftTime["axis"] = getTime(); - return [[level.onOneLeftEvent]]( "axis" ); - } - } - } - else - { - // everyone is dead - if ( (!level.aliveCount["allies"] && !level.aliveCount["axis"]) && (!level.livesCount["allies"] && !level.livesCount["axis"]) ) - { - return [[level.onDeadEvent]]( "all" ); - } - - livePlayers = getPotentialLivingPlayers(); - - if ( livePlayers.size == 1 ) - { - return [[level.onOneLeftEvent]]( "all" ); - } - } -} - - -waittillFinalKillcamDone() -{ - if ( level.forceFinalKillcam ) - { - waittillframeend; // give "round_end_finished" notifies time to process - - if( level.showingFinalKillcam ) - { - foreach ( player in level.players ) - player notify( "reset_outcome" ); - - level notify( "game_cleanup" ); - - while ( level.showingFinalKillcam ) - wait ( 0.05 ); - } - } - else - { - if ( !level.showingFinalKillcam ) - return false; - - while ( level.showingFinalKillcam ) - wait ( 0.05 ); - - return true; - } -} - -timeLimitClock_Intermission( waitTime, clockColor ) -{ - if( !isDefined( clockColor ) ) - clockColor = (0, 0, 0); - - NewWaitTime = waitTime*1000; - - setGameEndTime( getTime() + int(NewWaitTime) ); - clockObject = spawn( "script_origin", (0,0,0) ); - clockObject hide(); - - matchStartTimer = createServerTimer("objective", 1.4); - matchStartTimer setPoint( "TOPRIGHT", "TOPRIGHT", -5, 0 ); //("CENTER", "CENTER", 0, -45); - matchStartTimer setTimer( waitTime - 1 ); - matchStartTimer.sort = 1001; - matchStartTimer.foreground = false; - matchStartTimer.hideWhenInMenu = false; - matchStartTimer.color = clockColor; - - currentTime = getTime(); - timeRunning = ( getTime() - currentTime ); - while ( timeRunning <= NewWaitTime ) - { - wait 0.05; - if ( (timeRunning - NewWaitTime) >= -10000 && timeRunning%1000 == 0 ) - clockObject playSound( "ui_mp_timer_countdown" ); - - timeRunning = ( getTime() - currentTime ); - } - - clockObject delete(); - matchStartTimer destroyElem(); -} - - -waitForPlayers( maxTime ) -{ - endTime = gettime() + maxTime * 1000 - 200; - - if ( level.teamBased ) - while( (!level.hasSpawned[ "axis" ] || !level.hasSpawned[ "allies" ]) && gettime() < endTime ) - wait ( 0.05 ); - else - while ( level.maxPlayerCount < 2 && gettime() < endTime ) - wait ( 0.05 ); -} - - -prematchPeriod() -{ - level endon( "game_ended" ); - - if ( level.prematchPeriod > 0 ) - { - if ( level.console ) - { - thread matchStartTimer( "match_starting_in", level.prematchPeriod ); - wait ( level.prematchPeriod ); - } - else - { - matchStartTimerPC(); - } - } - else - { - matchStartTimerSkip(); - } - - for ( index = 0; index < level.players.size; index++ ) - { - level.players[index] freezeControlsWrapper( false ); - level.players[index] enableWeapons(); - - hintMessage = getObjectiveHintText( level.players[index].pers["team"] ); - if ( !isDefined( hintMessage ) || !level.players[index].hasSpawned ) - continue; - - level.players[index] setClientDvar( "scr_objectiveText", hintMessage ); - level.players[index] thread maps\mp\gametypes\_hud_message::hintMessage( hintMessage ); - } - - if ( game["state"] != "playing" ) - return; -} - - -gracePeriod() -{ - level endon("game_ended"); - - while ( level.inGracePeriod ) - { - wait ( 1.0 ); - level.inGracePeriod--; - } - - //wait ( level.gracePeriod ); - - level notify ( "grace_period_ending" ); - wait ( 0.05 ); - - gameFlagSet( "graceperiod_done" ); - level.inGracePeriod = false; - - if ( game["state"] != "playing" ) - return; - - if ( getGametypeNumLives() ) - { - // Players on a team but without a weapon show as dead since they can not get in this round - players = level.players; - - for ( i = 0; i < players.size; i++ ) - { - player = players[i]; - - if ( !player.hasSpawned && player.sessionteam != "spectator" && !isAlive( player ) ) - player.statusicon = "hud_status_dead"; - } - } - - level thread updateGameEvents(); -} - - -updateWinStats( winner ) -{ - if ( !winner rankingEnabled() ) - return; - - winner maps\mp\gametypes\_persistence::statAdd( "losses", -1 ); - - println( "setting winner: " + winner maps\mp\gametypes\_persistence::statGet( "wins" ) ); - winner maps\mp\gametypes\_persistence::statAdd( "wins", 1 ); - winner updatePersRatio( "winLossRatio", "wins", "losses" ); - winner maps\mp\gametypes\_persistence::statAdd( "currentWinStreak", 1 ); - - cur_win_streak = winner maps\mp\gametypes\_persistence::statGet( "currentWinStreak" ); - if ( cur_win_streak > winner maps\mp\gametypes\_persistence::statGet( "winStreak" ) ) - winner maps\mp\gametypes\_persistence::statSet( "winStreak", cur_win_streak ); - - winner maps\mp\gametypes\_persistence::statSetChild( "round", "win", true ); - winner maps\mp\gametypes\_persistence::statSetChild( "round", "loss", false ); -} - - -updateLossStats( loser ) -{ - if ( !loser rankingEnabled() ) - return; - - loser maps\mp\gametypes\_persistence::statAdd( "losses", 1 ); - loser updatePersRatio( "winLossRatio", "wins", "losses" ); - loser maps\mp\gametypes\_persistence::statSetChild( "round", "loss", true ); -} - - -updateTieStats( loser ) -{ - if ( !loser rankingEnabled() ) - return; - - loser maps\mp\gametypes\_persistence::statAdd( "losses", -1 ); - - loser maps\mp\gametypes\_persistence::statAdd( "ties", 1 ); - loser updatePersRatio( "winLossRatio", "wins", "losses" ); - loser maps\mp\gametypes\_persistence::statSet( "currentWinStreak", 0 ); -} - - -updateWinLossStats( winner ) -{ - //if ( privateMatch() ) - // return; - - if ( !wasLastRound() ) - return; - - players = level.players; - - if ( !isDefined( winner ) || ( isDefined( winner ) && isString( winner ) && winner == "tie" ) ) - { - foreach ( player in level.players ) - { - if ( isDefined( player.connectedPostGame ) ) - continue; - - if ( level.hostForcedEnd && player isHost() ) - { - player maps\mp\gametypes\_persistence::statSet( "currentWinStreak", 0 ); - continue; - } - - updateTieStats( player ); - } - } - else if ( isPlayer( winner ) ) - { - if ( level.hostForcedEnd && winner isHost() ) - { - winner maps\mp\gametypes\_persistence::statSet( "currentWinStreak", 0 ); - return; - } - - updateWinStats( winner ); - } - else if ( isString( winner ) ) - { - foreach ( player in level.players ) - { - if ( isDefined( player.connectedPostGame ) ) - continue; - - if ( level.hostForcedEnd && player isHost() ) - { - player maps\mp\gametypes\_persistence::statSet( "currentWinStreak", 0 ); - continue; - } - - if ( winner == "tie" ) - updateTieStats( player ); - else if ( player.pers["team"] == winner ) - updateWinStats( player ); - else - player maps\mp\gametypes\_persistence::statSet( "currentWinStreak", 0 ); - } - } -} - - -freezePlayerForRoundEnd( delay ) -{ - self endon ( "disconnect" ); - self clearLowerMessages(); - - if ( !isDefined( delay ) ) - delay = 0.05; - - self closepopupMenu(); - self closeInGameMenu(); - - wait ( delay ); - self freezeControlsWrapper( true ); -// self disableWeapons(); -} - - -updateMatchBonusScores( winner ) -{ - if ( !game["timePassed"] ) - return; - - //if ( !matchMakingGame() ) - // return; - - if ( !getTimeLimit() || level.forcedEnd ) - { - gameLength = getTimePassed() / 1000; - // cap it at 20 minutes to avoid exploiting - gameLength = min( gameLength, 1200 ); - } - else - { - gameLength = getTimeLimit() * 60; - } - - if ( level.teamBased ) - { - if ( winner == "allies" ) - { - winningTeam = "allies"; - losingTeam = "axis"; - } - else if ( winner == "axis" ) - { - winningTeam = "axis"; - losingTeam = "allies"; - } - else - { - winningTeam = "tie"; - losingTeam = "tie"; - } - - if ( winningTeam != "tie" ) - { - winnerScale = maps\mp\gametypes\_rank::getScoreInfoValue( "win" ); - loserScale = maps\mp\gametypes\_rank::getScoreInfoValue( "loss" ); - setWinningTeam( winningTeam ); - } - else - { - winnerScale = maps\mp\gametypes\_rank::getScoreInfoValue( "tie" ); - loserScale = maps\mp\gametypes\_rank::getScoreInfoValue( "tie" ); - } - - foreach ( player in level.players ) - { - if ( isDefined( player.connectedPostGame ) ) - continue; - - if ( !player rankingEnabled() ) - continue; - - if ( player.timePlayed["total"] < 1 || player.pers["participation"] < 1 ) - { - player thread maps\mp\gametypes\_rank::endGameUpdate(); - continue; - } - - // no bonus for hosts who force ends - if ( level.hostForcedEnd && player isHost() ) - continue; - - spm = player maps\mp\gametypes\_rank::getSPM(); - if ( winningTeam == "tie" ) - { - playerScore = int( (winnerScale * ((gameLength/60) * spm)) * (player.timePlayed["total"] / gameLength) ); - player thread giveMatchBonus( "tie", playerScore ); - player.matchBonus = playerScore; - } - else if ( isDefined( player.pers["team"] ) && player.pers["team"] == winningTeam ) - { - playerScore = int( (winnerScale * ((gameLength/60) * spm)) * (player.timePlayed["total"] / gameLength) ); - player thread giveMatchBonus( "win", playerScore ); - player.matchBonus = playerScore; - } - else if ( isDefined(player.pers["team"] ) && player.pers["team"] == losingTeam ) - { - playerScore = int( (loserScale * ((gameLength/60) * spm)) * (player.timePlayed["total"] / gameLength) ); - player thread giveMatchBonus( "loss", playerScore ); - player.matchBonus = playerScore; - } - } - } - else - { - if ( isDefined( winner ) ) - { - winnerScale = maps\mp\gametypes\_rank::getScoreInfoValue( "win" ); - loserScale = maps\mp\gametypes\_rank::getScoreInfoValue( "loss" ); - } - else - { - winnerScale = maps\mp\gametypes\_rank::getScoreInfoValue( "tie" ); - loserScale = maps\mp\gametypes\_rank::getScoreInfoValue( "tie" ); - } - - foreach ( player in level.players ) - { - if ( isDefined( player.connectedPostGame ) ) - continue; - - if ( player.timePlayed["total"] < 1 || player.pers["participation"] < 1 ) - { - player thread maps\mp\gametypes\_rank::endGameUpdate(); - continue; - } - - spm = player maps\mp\gametypes\_rank::getSPM(); - - isWinner = false; - for ( pIdx = 0; pIdx < min( level.placement["all"].size, 3 ); pIdx++ ) - { - if ( level.placement["all"][pIdx] != player ) - continue; - isWinner = true; - } - - if ( isWinner ) - { - playerScore = int( (winnerScale * ((gameLength/60) * spm)) * (player.timePlayed["total"] / gameLength) ); - player thread giveMatchBonus( "win", playerScore ); - player.matchBonus = playerScore; - } - else - { - playerScore = int( (loserScale * ((gameLength/60) * spm)) * (player.timePlayed["total"] / gameLength) ); - player thread giveMatchBonus( "loss", playerScore ); - player.matchBonus = playerScore; - } - } - } -} - - -giveMatchBonus( scoreType, score ) -{ - self endon ( "disconnect" ); - - level waittill ( "give_match_bonus" ); - - self maps\mp\gametypes\_rank::giveRankXP( scoreType, score ); - //logXPGains(); - - self maps\mp\gametypes\_rank::endGameUpdate(); -} - - -setXenonRanks( winner ) -{ - players = level.players; - - for ( i = 0; i < players.size; i++ ) - { - player = players[i]; - - if( !isdefined(player.score) || !isdefined(player.pers["team"]) ) - continue; - - } - - for ( i = 0; i < players.size; i++ ) - { - player = players[i]; - - if( !isdefined(player.score) || !isdefined(player.pers["team"]) ) - continue; - - setPlayerTeamRank( player, player.clientid, player.score - 5 * player.deaths ); - } - sendranks(); -} - - -checkTimeLimit( prevTimePassed ) -{ - if ( isDefined( level.timeLimitOverride ) && level.timeLimitOverride ) - return; - - if ( game["state"] != "playing" ) - { - setGameEndTime( 0 ); - return; - } - - if ( getTimeLimit() <= 0 ) - { - if ( isDefined( level.startTime ) ) - setGameEndTime( level.startTime ); - else - setGameEndTime( 0 ); - return; - } - - if ( !gameFlag( "prematch_done" ) ) - { - setGameEndTime( 0 ); - return; - } - - if ( !isdefined( level.startTime ) ) - return; - - timeLeft = getTimeRemaining(); - - // want this accurate to the millisecond -// if ( getHalfTime() && game["status"] != "halftime" ) -// setGameEndTime( getTime() + (int(timeLeft) - int(getTimeLimit()*60*1000*0.5)) ); -// else - setGameEndTime( getTime() + int(timeLeft) ); - - if ( timeLeft > 0 ) - { - if ( getHalfTime() && checkHalfTime( prevTimePassed ) ) - [[level.onHalfTime]](); - - return; - } - - [[level.onTimeLimit]](); -} - - -checkHalfTime( prevTimePassed ) -{ - if ( !level.teamBased ) - return false; - - if ( getTimeLimit() ) - { - halfTime = (getTimeLimit() * 60 * 1000) * 0.5; - - if ( getTimePassed() >= halfTime && prevTimePassed < halfTime && prevTimePassed > 0 ) - { - game["roundMillisecondsAlreadyPassed"] = getTimePassed(); - return true; - } - } - - return false; -} - - - -getTimeRemaining() -{ - return getTimeLimit() * 60 * 1000 - getTimePassed(); -} - - -checkTeamScoreLimitSoon( team ) -{ - assert( isDefined( team ) ); - - if ( getWatchedDvar( "scorelimit" ) <= 0 || isObjectiveBased() ) - return; - - if ( isDefined( level.scoreLimitOverride ) && level.scoreLimitOverride ) - return; - - if ( !level.teamBased ) - return; - - // No checks until a minute has passed to let wild data settle - if ( getTimePassed() < (60 * 1000) ) // 1 min - return; - - timeLeft = estimatedTimeTillScoreLimit( team ); - - if ( timeLeft < 2 ) - level notify( "match_ending_soon", "score" ); -} - - -checkPlayerScoreLimitSoon() -{ - if ( getWatchedDvar( "scorelimit" ) <= 0 || isObjectiveBased() ) - return; - - if ( level.teamBased ) - return; - - // No checks until a minute has passed to let wild data settle - if ( getTimePassed() < (60 * 1000) ) // 1 min - return; - - timeLeft = self estimatedTimeTillScoreLimit(); - - if ( timeLeft < 2 ) - level notify( "match_ending_soon", "score" ); -} - - -checkScoreLimit() -{ - if ( isObjectiveBased() ) - return false; - - if ( isDefined( level.scoreLimitOverride ) && level.scoreLimitOverride ) - return false; - - if ( game["state"] != "playing" ) - return false; - - if ( getWatchedDvar( "scorelimit" ) <= 0 ) - return false; - - if ( level.teamBased ) - { - if( game["teamScores"]["allies"] < getWatchedDvar( "scorelimit" ) && game["teamScores"]["axis"] < getWatchedDvar( "scorelimit" ) ) - return false; - } - else - { - if ( !isPlayer( self ) ) - return false; - - if ( self.score < getWatchedDvar( "scorelimit" ) ) - return false; - } - - return onScoreLimit(); -} - - -updateGameTypeDvars() -{ - level endon ( "game_ended" ); - - while ( game["state"] == "playing" ) - { - // make sure we check time limit right when game ends - if ( isdefined( level.startTime ) ) - { - if ( getTimeRemaining() < 3000 ) - { - wait .1; - continue; - } - } - wait 1; - } -} - - -matchStartTimerPC() -{ - thread matchStartTimer( "waiting_for_teams", level.prematchPeriod + level.prematchPeriodEnd ); - - waitForPlayers( level.prematchPeriod ); - - if ( level.prematchPeriodEnd > 0 ) - matchStartTimer( "match_starting_in", level.prematchPeriodEnd ); -} - -matchStartTimer_Internal( countTime, matchStartTimer ) -{ - waittillframeend; // wait till cleanup of previous start timer if multiple happen at once - visionSetNaked( "mpIntro", 0 ); - - level endon( "match_start_timer_beginning" ); - while ( countTime > 0 && !level.gameEnded ) - { - matchStartTimer thread maps\mp\gametypes\_hud::fontPulse( level ); - wait ( matchStartTimer.inFrames * 0.05 ); - matchStartTimer setValue( countTime ); - if ( countTime == 2 ) - visionSetNaked( getDvar( "mapname" ), 3.0 ); - countTime--; - wait ( 1 - (matchStartTimer.inFrames * 0.05) ); - } -} - -matchStartTimer( type, duration ) -{ - level notify( "match_start_timer_beginning" ); - - matchStartText = createServerFontString( "objective", 1.5 ); - matchStartText setPoint( "CENTER", "CENTER", 0, -40 ); - matchStartText.sort = 1001; - matchStartText setText( game["strings"]["waiting_for_teams"] ); - matchStartText.foreground = false; - matchStartText.hidewheninmenu = true; - - matchStartText setText( game["strings"][type] ); // "match begins in:" - - matchStartTimer = createServerFontString( "hudbig", 1 ); - matchStartTimer setPoint( "CENTER", "CENTER", 0, 0 ); - matchStartTimer.sort = 1001; - matchStartTimer.color = (1,1,0); - matchStartTimer.foreground = false; - matchStartTimer.hidewheninmenu = true; - - matchStartTimer maps\mp\gametypes\_hud::fontPulseInit(); - - countTime = int( duration ); - - if ( countTime >= 2 ) - { - matchStartTimer_Internal( countTime, matchStartTimer ); - visionSetNaked( getDvar( "mapname" ), 3.0 ); - } - else - { - visionSetNaked( "mpIntro", 0 ); - visionSetNaked( getDvar( "mapname" ), 1.0 ); - } - - matchStartTimer destroyElem(); - matchStartText destroyElem(); -} - -matchStartTimerSkip() -{ - visionSetNaked( getDvar( "mapname" ), 0 ); -} - - -onRoundSwitch() -{ - if ( !isDefined( game["switchedsides"] ) ) - game["switchedsides"] = false; - - // overtime - if ( game["roundsWon"]["allies"] == getWatchedDvar( "winlimit" ) - 1 && game["roundsWon"]["axis"] == getWatchedDvar( "winlimit" ) - 1 ) - { - aheadTeam = getBetterTeam(); - if ( aheadTeam != game["defenders"] ) - { - game["switchedsides"] = !game["switchedsides"]; - } - else - { - level.halftimeSubCaption = ""; - } - level.halftimeType = "overtime"; - } - else - { - level.halftimeType = "halftime"; - game["switchedsides"] = !game["switchedsides"]; - } -} - - -checkRoundSwitch() -{ - if ( !level.teamBased ) - return false; - - if ( !isDefined( level.roundSwitch ) || !level.roundSwitch ) - return false; - - assert( game["roundsPlayed"] > 0 ); - if ( game["roundsPlayed"] % level.roundSwitch == 0 ) - { - onRoundSwitch(); - return true; - } - - return false; -} - - -// returns the best guess of the exact time until the scoreboard will be displayed and player control will be lost. -// returns undefined if time is not known -timeUntilRoundEnd() -{ - if ( level.gameEnded ) - { - timePassed = (getTime() - level.gameEndTime) / 1000; - timeRemaining = level.postRoundTime - timePassed; - - if ( timeRemaining < 0 ) - return 0; - - return timeRemaining; - } - - if ( getTimeLimit() <= 0 ) - return undefined; - - if ( !isDefined( level.startTime ) ) - return undefined; - - tl = getTimeLimit(); - - timePassed = (getTime() - level.startTime)/1000; - timeRemaining = (getTimeLimit() * 60) - timePassed; - - if ( isDefined( level.timePaused ) ) - timeRemaining += level.timePaused; - - return timeRemaining + level.postRoundTime; -} - - - -freeGameplayHudElems() -{ - // free up some hud elems so we have enough for other things. - - // perk icons - if ( isdefined( self.perkicon ) ) - { - if ( isdefined( self.perkicon[0] ) ) - { - self.perkicon[0] destroyElem(); - self.perkname[0] destroyElem(); - } - if ( isdefined( self.perkicon[1] ) ) - { - self.perkicon[1] destroyElem(); - self.perkname[1] destroyElem(); - } - if ( isdefined( self.perkicon[2] ) ) - { - self.perkicon[2] destroyElem(); - self.perkname[2] destroyElem(); - } - } - self notify("perks_hidden"); // stop any threads that are waiting to hide the perk icons - - // lower message - self.lowerMessage destroyElem(); - self.lowerTimer destroyElem(); - - // progress bar - if ( isDefined( self.proxBar ) ) - self.proxBar destroyElem(); - if ( isDefined( self.proxBarText ) ) - self.proxBarText destroyElem(); -} - - -getHostPlayer() -{ - players = getEntArray( "player", "classname" ); - - for ( index = 0; index < players.size; index++ ) - { - if ( players[index] isHost() ) - return players[index]; - } -} - - -hostIdledOut() -{ - hostPlayer = getHostPlayer(); - - // host never spawned - if ( isDefined( hostPlayer ) && !hostPlayer.hasSpawned && !isDefined( hostPlayer.selectedClass ) ) - return true; - - return false; -} - - - -roundEndWait( defaultDelay, matchBonus ) -{ - //setSlowMotion( 1.0, 0.15, defaultDelay / 2 ); - - notifiesDone = false; - while ( !notifiesDone ) - { - players = level.players; - notifiesDone = true; - - foreach ( player in players ) - { - if ( !isDefined( player.doingSplash ) ) - continue; - - if ( !player maps\mp\gametypes\_hud_message::isDoingSplash() ) - continue; - - notifiesDone = false; - } - wait ( 0.5 ); - } - - if ( !matchBonus ) - { - wait ( defaultDelay ); - level notify ( "round_end_finished" ); - //setSlowMotion( 1.0, 1.0, 0.05 ); - return; - } - - wait ( defaultDelay / 2 ); - level notify ( "give_match_bonus" ); - wait ( defaultDelay / 2 ); - - notifiesDone = false; - while ( !notifiesDone ) - { - players = level.players; - notifiesDone = true; - foreach ( player in players ) - { - if ( !isDefined( player.doingSplash ) ) - continue; - - if ( !player maps\mp\gametypes\_hud_message::isDoingSplash() ) - continue; - - notifiesDone = false; - } - wait ( 0.5 ); - } - //setSlowMotion( 1.0, 1.0, 0.05); - - level notify ( "round_end_finished" ); -} - - -roundEndDOF( time ) -{ - self setDepthOfField( 0, 128, 512, 4000, 6, 1.8 ); -} - -randomizeMaps() -{ - tok = strTok( level.votingMaps, "," ); - - randomArray = []; - for( i = 0; i < 9; i++ ) - { - selectedRand = randomint( tok.size ); - randomArray[ i ] = tok[ selectedRand ]; - tok = restructMapArray( tok, selectedRand ); - } - - return randomArray; -} - -restructMapArray(oldArray, index) -{ - restructArray = []; - - for( i=0; i < oldArray.size; i++ ) - { - if( i < index ) - restructArray[ i ] = oldArray[ i ]; - else if( i > index ) - restructArray[ i - 1 ] = oldArray[ i ]; - } - - return restructArray; -} - - -Callback_StartGameType() -{ - maps\mp\_load::main(); - - levelFlagInit( "round_over", false ); - levelFlagInit( "game_over", false ); - levelFlagInit( "block_notifies", false ); - - level.prematchPeriod = 0; - level.prematchPeriodEnd = 0; - level.postGameNotifies = 0; - - level.intermission = false; - - - setDvarIfUninitialized( "scr_extraDamageFeedback", false ); - setDvarIfUninitialized( "scr_printDamage", false ); - setDvarIfUninitialized( "scr_disableKnife", false ); - setDvarIfUninitialized( "scr_intermission_time", 30.0 ); - setDvarIfUninitialized( "scr_forceKillcam", false ); - setDvarIfUninitialized( "scr_forceKillcam_winnersKill", true ); - setDvarIfUninitialized( "scr_game_allowFinalKillcam", true ); - setDvarIfUninitialized( "scr_disableTurret", false ); - setDvarIfUninitialized( "scr_failCam", false ); - setDvarIfUninitialized( "scr_voting", false ); - setDvarIfUninitialized( "scr_voting_maps", "mp_rust,mp_terminal" ); - setDvarIfUninitialized( "scr_voting_time", 26.0 ); - setDvarIfUninitialized( "scr_voting_winTime", 4.0 ); - setDvarIfUninitialized( "scr_allow_intermission", false );//vanilla as possible - setDvarIfUninitialized( "scr_voting_bots", false ); - setDvarIfUninitialized( "scr_nuke_increases_streak", true ); - setDvarIfUninitialized( "headshot_detach_head", false ); - - level.extraDamageFeedback = getDvarInt("scr_extraDamageFeedback"); - level.allowPrintDamage = getDvarInt("scr_printDamage"); - level.disableKnife = getDvarInt("scr_disableKnife"); - level.intermissionTime = getDvarFloat("scr_intermission_time"); - level.forceFinalKillcam = getDvarInt("scr_forceKillcam"); - level.forceFinalKillcamWinnersKill = getDvarInt("scr_forceKillcam_winnersKill"); - level.allowFinalKillcam = getDvarInt("scr_game_allowFinalKillcam"); - level.disableTurret = getDvarInt( "scr_disableTurret" ); - level.failCam = getDvarInt( "scr_failCam" ); - level.voting = getDvarInt( "scr_voting" ); - level.votingMaps = getDvar( "scr_voting_maps" ); - level.voteWinTime = getDvarInt( "scr_voting_winTime" ); - level.voteTime = getDvarInt( "scr_voting_time" ); - level.allowIntermission = getDvarInt( "scr_allow_intermission" ); - level.hardpointsRollover = getDvarInt( "scr_hardpoints_rollover" ); - level.botsVote = getDvarInt( "scr_voting_bots" ); - level.headShotDetachHead = getDvarInt("headshot_detach_head"); - level.nukeIncreasesStreak = getDvarInt( "scr_nuke_increases_streak" ); - - if ( level.voting ) - level.votingMapsTok = randomizeMaps(); - else - level.votingMapsTok = strTok( level.votingMaps, "," ); - - level.scriptIncKillstreak = false; - - level.mapVotes = []; - for( i=0; i < level.votingMapsTok.size; i++ ) - level.mapVotes[ i ] = 0; - - level.inVoting = false; - level.inShowingWinner = false; - level.inIntermission = false; - level.highestVotedMap = -1; - - - makeDvarServerInfo( "cg_thirdPersonAngle", 356 ); - - makeDvarServerInfo( "scr_gameended", 0 ); - - if ( !isDefined( game["gamestarted"] ) ) - { - game["clientid"] = 0; - - alliesCharSet = getMapCustom( "allieschar" ); - if ( (!isDefined( alliesCharSet ) || alliesCharSet == "") ) - { - if ( !isDefined( game["allies"] ) ) - alliesCharSet = "us_army"; - else - alliesCharSet = game["allies"]; - } - - axisCharSet = getMapCustom( "axischar" ); - if ( (!isDefined( axisCharSet ) || axisCharSet == "") ) - { - if ( !isDefined( game["axis"] ) ) - axisCharSet = "opforce_composite"; - else - axisCharSet = game["axis"]; - } - - game["allies"] = alliesCharSet; - game["axis"] = axisCharSet; - - if ( !isDefined( game["attackers"] ) || !isDefined( game["defenders"] ) ) - thread error( "No attackers or defenders team defined in level .gsc." ); - - if ( !isDefined( game["attackers"] ) ) - game["attackers"] = "allies"; - if ( !isDefined( game["defenders"] ) ) - game["defenders"] = "axis"; - - if ( !isDefined( game["state"] ) ) - game["state"] = "playing"; - - precacheStatusIcon( "hud_status_dead" ); - precacheStatusIcon( "hud_status_connecting" ); - precacheString( &"MPUI_REVIVING" ); - precacheString( &"MPUI_BEING_REVIVED" ); - - precacheRumble( "damage_heavy" ); - - precacheShader( "white" ); - precacheShader( "black" ); - - game["menu_vote"] = "vote"; - - if ( level.voting && level.voteTime > 0.0 && level.votingMapsTok.size ) - precacheMenu( game["menu_vote"] ); - - game["menu_popup_summary"] = "popup_summary"; - - if ( level.allowIntermission && level.intermissionTime > 0.0 ) - precacheMenu( game["menu_popup_summary"] ); - - game["strings"]["press_to_spawn"] = &"PLATFORM_PRESS_TO_SPAWN"; - if ( level.teamBased ) - { - game["strings"]["waiting_for_teams"] = &"MP_WAITING_FOR_TEAMS"; - game["strings"]["opponent_forfeiting_in"] = &"MP_OPPONENT_FORFEITING_IN"; - } - else - { - game["strings"]["waiting_for_teams"] = &"MP_WAITING_FOR_MORE_PLAYERS"; - game["strings"]["opponent_forfeiting_in"] = &"MP_OPPONENT_FORFEITING_IN"; - } - game["strings"]["match_starting_in"] = &"MP_MATCH_STARTING_IN"; - game["strings"]["match_resuming_in"] = &"MP_MATCH_RESUMING_IN"; - game["strings"]["waiting_for_players"] = &"MP_WAITING_FOR_PLAYERS"; - game["strings"]["spawn_next_round"] = &"MP_SPAWN_NEXT_ROUND"; - game["strings"]["waiting_to_spawn"] = &"MP_WAITING_TO_SPAWN"; - game["strings"]["waiting_to_safespawn"] = &"MP_WAITING_TO_SAFESPAWN"; - game["strings"]["match_starting"] = &"MP_MATCH_STARTING"; - game["strings"]["change_class"] = &"MP_CHANGE_CLASS_NEXT_SPAWN"; - game["strings"]["last_stand"] = &"MPUI_LAST_STAND"; - game["strings"]["final_stand"] = &"MPUI_FINAL_STAND"; - game["strings"]["c4_death"] = &"MPUI_C4_DEATH"; - - game["strings"]["cowards_way"] = &"PLATFORM_COWARDS_WAY_OUT"; - - game["strings"]["tie"] = &"MP_MATCH_TIE"; - game["strings"]["round_draw"] = &"MP_ROUND_DRAW"; - - game["strings"]["grabbed_flag"] = &"MP_GRABBED_FLAG_FIRST"; - game["strings"]["enemies_eliminated"] = &"MP_ENEMIES_ELIMINATED"; - game["strings"]["score_limit_reached"] = &"MP_SCORE_LIMIT_REACHED"; - game["strings"]["round_limit_reached"] = &"MP_ROUND_LIMIT_REACHED"; - game["strings"]["time_limit_reached"] = &"MP_TIME_LIMIT_REACHED"; - game["strings"]["players_forfeited"] = &"MP_PLAYERS_FORFEITED"; - game["strings"]["S.A.S Win"] = &"SAS_WIN"; - game["strings"]["Spetsnaz Win"] = &"SPETSNAZ_WIN"; - - game["colors"]["blue"] = (0.25,0.25,0.75); - game["colors"]["red"] = (0.75,0.25,0.25); - game["colors"]["white"] = (1.0,1.0,1.0); - game["colors"]["black"] = (0.0,0.0,0.0); - game["colors"]["green"] = (0.25,0.75,0.25); - game["colors"]["yellow"] = (0.65,0.65,0.0); - game["colors"]["orange"] = (1.0,0.45,0.0); - - game["strings"]["allies_eliminated"] = maps\mp\gametypes\_teams::getTeamEliminatedString( "allies" ); - game["strings"]["allies_forfeited"] = maps\mp\gametypes\_teams::getTeamForfeitedString( "allies" ); - game["strings"]["allies_name"] = maps\mp\gametypes\_teams::getTeamName( "allies" ); - game["icons"]["allies"] = maps\mp\gametypes\_teams::getTeamIcon( "allies" ); - game["colors"]["allies"] = maps\mp\gametypes\_teams::getTeamColor( "allies" ); - - game["strings"]["axis_eliminated"] = maps\mp\gametypes\_teams::getTeamEliminatedString( "axis" ); - game["strings"]["axis_forfeited"] = maps\mp\gametypes\_teams::getTeamForfeitedString( "axis" ); - game["strings"]["axis_name"] = maps\mp\gametypes\_teams::getTeamName( "axis" ); - game["icons"]["axis"] = maps\mp\gametypes\_teams::getTeamIcon( "axis" ); - game["colors"]["axis"] = maps\mp\gametypes\_teams::getTeamColor( "axis" ); - - if ( game["colors"]["allies"] == (0,0,0) ) - game["colors"]["allies"] = (0.5,0.5,0.5); - - if ( game["colors"]["axis"] == (0,0,0) ) - game["colors"]["axis"] = (0.5,0.5,0.5); - - [[level.onPrecacheGameType]](); - - if ( level.console ) - { - if ( !level.splitscreen ) - level.prematchPeriod = maps\mp\gametypes\_tweakables::getTweakableValue( "game", "graceperiod" ); - } - else - { - // first round, so set up prematch - level.prematchPeriod = maps\mp\gametypes\_tweakables::getTweakableValue( "game", "playerwaittime" ); - level.prematchPeriodEnd = maps\mp\gametypes\_tweakables::getTweakableValue( "game", "matchstarttime" ); - } - } - - if ( !isDefined( game["status"] ) ) - game["status"] = "normal"; - - makeDvarServerInfo( "ui_overtime", (game["status"] == "overtime") ); - - if ( game["status"] != "overtime" && game["status"] != "halftime" ) - { - game["teamScores"]["allies"] = 0; - game["teamScores"]["axis"] = 0; - } - - if( !isDefined( game["timePassed"] ) ) - game["timePassed"] = 0; - - if( !isDefined( game["roundsPlayed"] ) ) - game["roundsPlayed"] = 0; - - if ( !isDefined( game["roundsWon"] ) ) - game["roundsWon"] = []; - - if ( level.teamBased ) - { - if ( !isDefined( game["roundsWon"]["axis"] ) ) - game["roundsWon"]["axis"] = 0; - if ( !isDefined( game["roundsWon"]["allies"] ) ) - game["roundsWon"]["allies"] = 0; - } - - level.gameEnded = false; - level.forcedEnd = false; - level.hostForcedEnd = false; - - level.hardcoreMode = getDvarInt( "g_hardcore" ); - if ( level.hardcoreMode ) - logString( "game mode: hardcore" ); - - level.dieHardMode = getDvarInt( "scr_diehard" ); - - if ( !level.teamBased ) - level.dieHardMode = 0; - - if ( level.dieHardMode ) - logString( "game mode: diehard" ); - - level.killstreakRewards = getDvarInt( "scr_game_hardpoints" ); - - /# - printLn( "SESSION INFO" ); - printLn( "=====================================" ); - printLn( " Map: " + level.script ); - printLn( " Script: " + level.gametype ); - printLn( " HardCore: " + level.hardcoreMode ); - printLn( " Diehard: " + level.dieHardMode ); - printLn( " 3rd Person: " + getDvarInt( "camera_thirdperson" ) ); - printLn( " Round: " + game[ "roundsPlayed" ] ); - printLn( " scr_" + level.gametype + "_scorelimit " + getDvar( "scr_" + level.gametype + "_scorelimit" ) ); - printLn( " scr_" + level.gametype + "_roundlimit " +getDvar( "scr_" + level.gametype + "_roundlimit" ) ); - printLn( " scr_" + level.gametype + "_winlimit " + getDvar( "scr_" + level.gametype + "_winlimit" ) ); - printLn( " scr_" + level.gametype + "_timelimit " + getDvar( "scr_" + level.gametype + "_timelimit" ) ); - printLn( " scr_" + level.gametype + "_numlives " + getDvar( "scr_" + level.gametype + "_numlives" ) ); - printLn( " scr_" + level.gametype + "_halftime " + getDvar( "scr_" + level.gametype + "_halftime" ) ); - printLn( " scr_" + level.gametype + "_roundswitch " + getDvar( "scr_" + level.gametype + "_roundswitch" ) ); - printLn( "=====================================" ); - #/ - - // this gets set to false when someone takes damage or a gametype-specific event happens. - level.useStartSpawns = true; - - // multiplier for score from objectives - level.objectivePointsMod = 1; - - if ( matchMakingGame() ) - level.maxAllowedTeamKills = 2; - else - level.maxAllowedTeamKills = -1; - - thread maps\mp\gametypes\_persistence::init(); - thread maps\mp\gametypes\_menus::init(); - thread maps\mp\gametypes\_hud::init(); - thread maps\mp\gametypes\_serversettings::init(); - thread maps\mp\gametypes\_teams::init(); - thread maps\mp\gametypes\_weapons::init(); - thread maps\mp\gametypes\_killcam::init(); - thread maps\mp\gametypes\_shellshock::init(); - thread maps\mp\gametypes\_deathicons::init(); - thread maps\mp\gametypes\_damagefeedback::init(); - thread maps\mp\gametypes\_healthoverlay::init(); - thread maps\mp\gametypes\_spectating::init(); - thread maps\mp\gametypes\_objpoints::init(); - thread maps\mp\gametypes\_gameobjects::init(); - thread maps\mp\gametypes\_spawnlogic::init(); - thread maps\mp\gametypes\_battlechatter_mp::init(); - thread maps\mp\gametypes\_music_and_dialog::init(); - thread maps\mp\_matchdata::init(); - thread maps\mp\_awards::init(); - thread maps\mp\_skill::init(); - thread maps\mp\_areas::init(); - thread maps\mp\killstreaks\_killstreaks::init(); - //thread maps\mp\_perks::init(); // No longer in use, removed from common scripts. (smart arrow) - thread maps\mp\perks\_perks::init(); - thread maps\mp\_events::init(); - thread maps\mp\_defcon::init(); - - level thread onPlayerConnect(); - - if ( level.teamBased ) - thread maps\mp\gametypes\_friendicons::init(); - - thread maps\mp\gametypes\_hud_message::init(); - - if ( !level.console ) - thread maps\mp\gametypes\_quickmessages::init(); - - foreach ( locString in game["strings"] ) - precacheString( locString ); - - foreach ( icon in game["icons"] ) - precacheShader( icon ); - - game["gamestarted"] = true; - - level.maxPlayerCount = 0; - level.waveDelay["allies"] = 0; - level.waveDelay["axis"] = 0; - level.lastWave["allies"] = 0; - level.lastWave["axis"] = 0; - level.wavePlayerSpawnIndex["allies"] = 0; - level.wavePlayerSpawnIndex["axis"] = 0; - level.alivePlayers["allies"] = []; - level.alivePlayers["axis"] = []; - level.activePlayers = []; - - makeDvarServerInfo( "ui_scorelimit", 0 ); - makeDvarServerInfo( "ui_allow_classchange", getDvar( "ui_allow_classchange" ) ); - makeDvarServerInfo( "ui_allow_teamchange", 1 ); - setDvar( "ui_allow_teamchange", 1 ); - - if ( getGametypeNumLives() ) - setdvar( "g_deadChat", 0 ); - else - setdvar( "g_deadChat", 1 ); - - waveDelay = getDvarInt( "scr_" + level.gameType + "_waverespawndelay" ); - if ( waveDelay ) - { - level.waveDelay["allies"] = waveDelay; - level.waveDelay["axis"] = waveDelay; - level.lastWave["allies"] = 0; - level.lastWave["axis"] = 0; - - level thread maps\mp\gametypes\_gamelogic::waveSpawnTimer(); - } - - gameFlagInit( "prematch_done", false ); - - level.gracePeriod = 15; - - level.inGracePeriod = level.gracePeriod; - gameFlagInit( "graceperiod_done", false ); - - level.roundEndDelay = 4; - level.halftimeRoundEndDelay = 4; - - - if ( level.teamBased ) - { - maps\mp\gametypes\_gamescore::updateTeamScore( "axis" ); - maps\mp\gametypes\_gamescore::updateTeamScore( "allies" ); - } - else - { - thread maps\mp\gametypes\_gamescore::initialDMScoreUpdate(); - } - - thread updateUIScoreLimit(); - level notify ( "update_scorelimit" ); - - - [[level.onStartGameType]](); - - // this must be after onstartgametype for scr_showspawns to work when set at start of game - /# - thread maps\mp\gametypes\_dev::init(); - #/ - - thread startGame(); - - level thread updateWatchedDvars(); - level thread timeLimitThread(); - - level thread doFinalKillcam(); -} - -onPlayerConnect() -{ - for(;;) - { - level waittill( "connected", player ); - - player thread onPlayerSpawned(); - - player thread watchIntermissionAfterConnect(); - } -} - -watchIntermissionAfterConnect() -{ - self endon("disconnect"); - - wait 0.05; - - self notify("kill_menus_on_connect"); - if(level.inVoting || level.inShowingWinner) - { - self.sessionstate = "spectator";//allow player to leave while in intermission and make voting options - self thread watchVoting(); - - if(level.inVoting) - { - self setClientDvars( "hud_ShowWinner", "0", - "hud_voteText", "^3Vote for new map:", - "vote_map", "" ); - } - else if(level.inShowingWinner) - { - self setClientDvars( "hud_WinningName", "preview_" + level.votingMapsTok[ level.highestVotedMap ], - "hud_WinningMap", consoleMapNameToMapName( level.votingMapsTok[ level.highestVotedMap ] ), - "hud_voteText", "^3Next Map:", - "hud_ShowWinner", "1" ); - } - - self openPopupMenu( game["menu_vote"] ); - } - else if(level.inIntermission) - { - self.sessionstate = "spectator";//allow player to leave while in intermission - self thread openSummaryOnMenuClose(); - self openPopupMenu( game["menu_popup_summary"] ); - } -} - -onPlayerSpawned() -{ - self endon("disconnect"); - self.printDamage = false; - firstTime = false; - for(;;) - { - self waittill("spawned_player"); - if( !firstTime && level.allowPrintDamage ) - { - firstTime = true; - self iPrintlnBold( "^7Press ^3[{+actionslot 2}] ^7to toggle ^3Print Damage" ); - } - self thread printDamage(); - } -} - -printDamage() -{ - if( !level.allowPrintDamage ) - return; - - self endon("disconnect"); - self endon("death"); - - self notifyOnPlayerCommand("printDamage", "+actionslot 2"); - for(;;) - { - self waittill("printDamage"); - self playSound( "semtex_warning" ); - if(self.printDamage) - { - self iPrintlnBold("^7Print Damage ^1Disabled"); - self.printDamage = false; - } - else - { - self iPrintlnBold("^7Print Damage ^1Enabled"); - self.printDamage = true; - } - } -} - - -Callback_CodeEndGame() -{ - endparty(); - - if ( !level.gameEnded ) - level thread maps\mp\gametypes\_gamelogic::forceEnd(); -} - - -timeLimitThread() -{ - level endon ( "game_ended" ); - - prevTimePassed = getTimePassed(); - - while ( game["state"] == "playing" ) - { - thread checkTimeLimit( prevTimePassed ); - prevTimePassed = getTimePassed(); - - // make sure we check time limit right when game ends - if ( isdefined( level.startTime ) ) - { - if ( getTimeRemaining() < 3000 ) - { - wait .1; - continue; - } - } - wait 1; - } -} - - -updateUIScoreLimit() -{ - for ( ;; ) - { - level waittill_either ( "update_scorelimit", "update_winlimit" ); - - if ( !isRoundBased() || !isObjectiveBased() ) - { - setDvar( "ui_scorelimit", getWatchedDvar( "scorelimit" ) ); - thread checkScoreLimit(); - } - else - { - setDvar( "ui_scorelimit", getWatchedDvar( "winlimit" ) ); - } - } -} - - -playTickingSound() -{ - self endon("death"); - self endon("stop_ticking"); - level endon("game_ended"); - - time = level.bombTimer; - - while(1) - { - self playSound( "ui_mp_suitcasebomb_timer" ); - - if ( time > 10 ) - { - time -= 1; - wait 1; - } - else if ( time > 4 ) - { - time -= .5; - wait .5; - } - else if ( time > 1 ) - { - time -= .4; - wait .4; - } - else - { - time -= .3; - wait .3; - } - maps\mp\gametypes\_hostmigration::waitTillHostMigrationDone(); - } -} - -stopTickingSound() -{ - self notify("stop_ticking"); -} - -timeLimitClock() -{ - level endon ( "game_ended" ); - - wait .05; - - clockObject = spawn( "script_origin", (0,0,0) ); - clockObject hide(); - - while ( game["state"] == "playing" ) - { - if ( !level.timerStopped && getTimeLimit() ) - { - timeLeft = getTimeRemaining() / 1000; - timeLeftInt = int(timeLeft + 0.5); // adding .5 and flooring rounds it. - - if ( getHalfTime() && timeLeftInt > (getTimeLimit()*60) * 0.5 ) - timeLeftInt -= int((getTimeLimit()*60) * 0.5); - - if ( (timeLeftInt >= 30 && timeLeftInt <= 60) ) - level notify ( "match_ending_soon", "time" ); - - if ( timeLeftInt <= 10 || (timeLeftInt <= 30 && timeLeftInt % 2 == 0) ) - { - level notify ( "match_ending_very_soon" ); - // don't play a tick at exactly 0 seconds, that's when something should be happening! - if ( timeLeftInt == 0 ) - break; - - clockObject playSound( "ui_mp_timer_countdown" ); - } - - // synchronize to be exactly on the second - if ( timeLeft - floor(timeLeft) >= .05 ) - wait timeLeft - floor(timeLeft); - } - - wait ( 1.0 ); - } -} - - -gameTimer() -{ - level endon ( "game_ended" ); - - level waittill("prematch_over"); - - level.startTime = getTime(); - level.discardTime = 0; - - if ( isDefined( game["roundMillisecondsAlreadyPassed"] ) ) - { - level.startTime -= game["roundMillisecondsAlreadyPassed"]; - game["roundMillisecondsAlreadyPassed"] = undefined; - } - - prevtime = gettime(); - - while ( game["state"] == "playing" ) - { - if ( !level.timerStopped ) - { - // the wait isn't always exactly 1 second. dunno why. - game["timePassed"] += gettime() - prevtime; - } - prevtime = gettime(); - wait ( 1.0 ); - } -} - -UpdateTimerPausedness() -{ - shouldBeStopped = level.timerStoppedForGameMode || isDefined( level.hostMigrationTimer ); - if ( !gameFlag( "prematch_done" ) ) - shouldBeStopped = false; - - if ( !level.timerStopped && shouldBeStopped ) - { - level.timerStopped = true; - level.timerPauseTime = gettime(); - } - else if ( level.timerStopped && !shouldBeStopped ) - { - level.timerStopped = false; - level.discardTime += gettime() - level.timerPauseTime; - } -} - -pauseTimer() -{ - level.timerStoppedForGameMode = true; - UpdateTimerPausedness(); -} - -resumeTimer() -{ - level.timerStoppedForGameMode = false; - UpdateTimerPausedness(); -} - - -startGame() -{ - thread gameTimer(); - level.timerStopped = false; - level.timerStoppedForGameMode = false; - thread maps\mp\gametypes\_spawnlogic::spawnPerFrameUpdate(); - - prematchPeriod(); - gameFlagSet( "prematch_done" ); - level notify("prematch_over"); - - UpdateTimerPausedness(); - - thread timeLimitClock(); - thread gracePeriod(); - - thread maps\mp\gametypes\_missions::roundBegin(); -} - - -waveSpawnTimer() -{ - level endon( "game_ended" ); - - while ( game["state"] == "playing" ) - { - time = getTime(); - - if ( time - level.lastWave["allies"] > (level.waveDelay["allies"] * 1000) ) - { - level notify ( "wave_respawn_allies" ); - level.lastWave["allies"] = time; - level.wavePlayerSpawnIndex["allies"] = 0; - } - - if ( time - level.lastWave["axis"] > (level.waveDelay["axis"] * 1000) ) - { - level notify ( "wave_respawn_axis" ); - level.lastWave["axis"] = time; - level.wavePlayerSpawnIndex["axis"] = 0; - } - - wait ( 0.05 ); - } -} - - -getBetterTeam() -{ - kills["allies"] = 0; - kills["axis"] = 0; - deaths["allies"] = 0; - deaths["axis"] = 0; - - foreach ( player in level.players ) - { - team = player.pers["team"]; - if ( isDefined( team ) && (team == "allies" || team == "axis") ) - { - kills[ team ] += player.kills; - deaths[ team ] += player.deaths; - } - } - - if ( kills["allies"] > kills["axis"] ) - return "allies"; - else if ( kills["axis"] > kills["allies"] ) - return "axis"; - - // same number of kills - - if ( deaths["allies"] < deaths["axis"] ) - return "allies"; - else if ( deaths["axis"] < deaths["allies"] ) - return "axis"; - - // same number of deaths - - if ( randomint(2) == 0 ) - return "allies"; - return "axis"; -} - - -rankedMatchUpdates( winner ) -{ - //if ( matchMakingGame() ) - //{ - setXenonRanks(); - - //if ( hostIdledOut() ) - //{ - // level.hostForcedEnd = true; - // logString( "host idled out" ); - // endLobby(); - //} - - updateMatchBonusScores( winner ); - //} - - updateWinLossStats( winner ); -} - - -displayRoundEnd( winner, endReasonText ) -{ - foreach ( player in level.players ) - { - if ( isDefined( player.connectedPostGame ) || player.pers["team"] == "spectator" ) - continue; - - if ( level.teamBased ) - player thread maps\mp\gametypes\_hud_message::teamOutcomeNotify( winner, true, endReasonText ); - else - player thread maps\mp\gametypes\_hud_message::outcomeNotify( winner, endReasonText ); - } - - if ( !wasLastRound() ) - level notify ( "round_win", winner ); - - if ( wasLastRound() ) - roundEndWait( level.roundEndDelay, false ); - else - roundEndWait( level.roundEndDelay, true ); -} - - -displayGameEnd( winner, endReasonText ) -{ - // catching gametype, since DM forceEnd sends winner as player entity, instead of string - foreach ( player in level.players ) - { - if ( isDefined( player.connectedPostGame ) || player.pers["team"] == "spectator" ) - continue; - - if ( level.teamBased ) - player thread maps\mp\gametypes\_hud_message::teamOutcomeNotify( winner, false, endReasonText ); - else - player thread maps\mp\gametypes\_hud_message::outcomeNotify( winner, endReasonText ); - } - - level notify ( "game_win", winner ); - - roundEndWait( level.postRoundTime, true ); -} - - -displayRoundSwitch() -{ - switchType = level.halftimeType; - if ( switchType == "halftime" ) - { - if ( getWatchedDvar( "roundlimit" ) ) - { - if ( (game["roundsPlayed"] * 2) == getWatchedDvar( "roundlimit" ) ) - switchType = "halftime"; - else - switchType = "intermission"; - } - else if ( getWatchedDvar( "winlimit" ) ) - { - if ( game["roundsPlayed"] == (getWatchedDvar( "winlimit" ) - 1) ) - switchType = "halftime"; - else - switchType = "intermission"; - } - else - { - switchType = "intermission"; - } - } - - level notify ( "round_switch", switchType ); - - foreach ( player in level.players ) - { - if ( isDefined( player.connectedPostGame ) || player.pers["team"] == "spectator" ) - continue; - - player thread maps\mp\gametypes\_hud_message::teamOutcomeNotify( switchType, true, level.halftimeSubCaption ); - } - - roundEndWait( level.halftimeRoundEndDelay, false ); -} - - -endGameOvertime( winner, endReasonText ) -{ - visionSetNaked( "mpOutro", 0.5 ); - setDvar( "scr_gameended", 2 ); - // freeze players - foreach ( player in level.players ) - { - player thread freezePlayerForRoundEnd( 0 ); - player thread roundEndDoF( 4.0 ); - - player freeGameplayHudElems(); - - player setClientDvars( "cg_everyoneHearsEveryone", 1 ); - player setClientDvars( "cg_drawSpectatorMessages", 0, - "g_compassShowEnemies", 0 ); - - if ( player.pers["team"] == "spectator" ) - player thread maps\mp\gametypes\_playerlogic::spawnIntermission(); - } - - level notify ( "round_switch", "overtime" ); - - // catching gametype, since DM forceEnd sends winner as player entity, instead of string - foreach ( player in level.players ) - { - if ( isDefined( player.connectedPostGame ) || player.pers["team"] == "spectator" ) - continue; - - if ( level.teamBased ) - player thread maps\mp\gametypes\_hud_message::teamOutcomeNotify( winner, false, endReasonText ); - else - player thread maps\mp\gametypes\_hud_message::outcomeNotify( winner, endReasonText ); - } - - roundEndWait( level.roundEndDelay, false ); - - if ( level.forceFinalKillcam ) - waittillFinalKillcamDone(); - - game["status"] = "overtime"; - level notify ( "restarting" ); - game["state"] = "playing"; - map_restart( true ); -} - - - -endGameHalfTime() -{ - visionSetNaked( "mpOutro", 0.5 ); - setDvar( "scr_gameended", 2 ); - - game["switchedsides"] = !game["switchedsides"]; - - // freeze players - foreach ( player in level.players ) - { - player thread freezePlayerForRoundEnd( 0 ); - player thread roundEndDoF( 4.0 ); - - player freeGameplayHudElems(); - - player setClientDvars( "cg_everyoneHearsEveryone", 1 ); - player setClientDvars( "cg_drawSpectatorMessages", 0, - "g_compassShowEnemies", 0 ); - - if ( player.pers["team"] == "spectator" ) - player thread maps\mp\gametypes\_playerlogic::spawnIntermission(); - } - - foreach ( player in level.players ) - player.pers["stats"] = player.stats; - - level notify ( "round_switch", "halftime" ); - - foreach ( player in level.players ) - { - if ( isDefined( player.connectedPostGame ) || player.pers["team"] == "spectator" ) - continue; - - player thread maps\mp\gametypes\_hud_message::teamOutcomeNotify( "halftime", true, level.halftimeSubCaption ); - } - - roundEndWait( level.roundEndDelay, false ); - - if ( level.forceFinalKillcam ) - waittillFinalKillcamDone(); - - game["status"] = "halftime"; - level notify ( "restarting" ); - game["state"] = "playing"; - map_restart( true ); -} - - -endGame( winner, endReasonText, nukeDetonated ) -{ - if( !level.forceFinalKillcamWinnersKill || !isDefined( winner ) || !isString( winner ) || ( winner != "axis" && winner != "allies" ) ) - level.finalKillCam_winner = "none"; - else - level.finalKillCam_winner = winner; - - if ( !isDefined(nukeDetonated) ) - nukeDetonated = false; - - // return if already ending via host quit or victory, or nuke incoming - if ( game["state"] == "postgame" || level.gameEnded || (isDefined(level.nukeIncoming) && !nukeDetonated) && ( !isDefined( level.gtnw ) || !level.gtnw ) ) - return; - - game["state"] = "postgame"; - - level.gameEndTime = getTime(); - level.gameEnded = true; - level.inGracePeriod = false; - level notify ( "game_ended", winner ); - levelFlagSet( "game_over" ); - levelFlagSet( "block_notifies" ); - waitframe(); // give "game_ended" notifies time to process - - setGameEndTime( 0 ); // stop/hide the timers - - maps\mp\gametypes\_playerlogic::printPredictedSpawnpointCorrectness(); - - if ( isDefined( winner ) && isString( winner ) && winner == "overtime" ) - { - endGameOvertime( winner, endReasonText ); - return; - } - - if ( isDefined( winner ) && isString( winner ) && winner == "halftime" ) - { - endGameHalftime(); - return; - } - - game["roundsPlayed"]++; - - if ( level.teamBased ) - { - if ( winner == "axis" || winner == "allies" ) - game["roundsWon"][winner]++; - - maps\mp\gametypes\_gamescore::updateTeamScore( "axis" ); - maps\mp\gametypes\_gamescore::updateTeamScore( "allies" ); - } - else - { - if ( isDefined( winner ) && isPlayer( winner ) ) - game["roundsWon"][winner.guid]++; - } - - maps\mp\gametypes\_gamescore::updatePlacement(); - - rankedMatchUpdates( winner ); - - foreach ( player in level.players ) - { - player setClientDvar( "ui_opensummary", 1 ); - } - - setDvar( "g_deadChat", 1 ); - setDvar( "ui_allow_teamchange", 0 ); - - // freeze players - foreach ( player in level.players ) - { - player thread freezePlayerForRoundEnd( 1.0 ); - player thread roundEndDoF( 4.0 ); - - player freeGameplayHudElems(); - - player setClientDvars( "cg_everyoneHearsEveryone", 1 ); - player setClientDvars( "cg_drawSpectatorMessages", 0, - "g_compassShowEnemies", 0, - "cg_fovScale", 1 ); - - if ( player.pers["team"] == "spectator" ) - player thread maps\mp\gametypes\_playerlogic::spawnIntermission(); - } - - if( !nukeDetonated ) - visionSetNaked( "mpOutro", 0.5 ); - - // End of Round - if ( !wasOnlyRound() && !nukeDetonated ) - { - setDvar( "scr_gameended", 2 ); - - displayRoundEnd( winner, endReasonText ); - - if ( level.forceFinalKillcam ) - { - waittillFinalKillcamDone(); - } - else - { - if ( level.showingFinalKillcam ) - { - foreach ( player in level.players ) - player notify ( "reset_outcome" ); - - level notify ( "game_cleanup" ); - - waittillFinalKillcamDone(); - } - } - - if ( !wasLastRound() ) - { - levelFlagClear( "block_notifies" ); - if ( checkRoundSwitch() ) - displayRoundSwitch(); - - foreach ( player in level.players ) - player.pers["stats"] = player.stats; - - level notify ( "restarting" ); - game["state"] = "playing"; - map_restart( true ); - return; - } - - if ( !level.forcedEnd ) - endReasonText = updateEndReasonText( winner ); - } - - setDvar( "scr_gameended", 1 ); - - if ( !isDefined( game["clientMatchDataDef"] ) ) - { - game["clientMatchDataDef"] = "mp/clientmatchdata.def"; - setClientMatchDataDef( game["clientMatchDataDef"] ); - } - - maps\mp\gametypes\_missions::roundEnd( winner ); - - if( isRoundBased() ) - winner = getWinningTeam(); - - displayGameEnd( winner, endReasonText ); - - if( wasOnlyRound() ) - { - if ( level.forceFinalKillcam ) - { - waittillFinalKillcamDone(); - } - else - { - if ( level.showingFinalKillcam ) - { - foreach ( player in level.players ) - player notify ( "reset_outcome" ); - - level notify ( "game_cleanup" ); - - waittillFinalKillcamDone(); - } - } - } - - levelFlagClear( "block_notifies" ); - - level.intermission = true; - - level notify ( "spawning_intermission" ); - - foreach ( player in level.players ) - { - player closepopupMenu(); - player closeInGameMenu(); - player notify ( "reset_outcome" ); - player thread maps\mp\gametypes\_playerlogic::spawnIntermission(); - } - - processLobbyData(); - - wait ( 1.0 ); - - if ( matchMakingGame() ) - sendMatchData(); - - foreach ( player in level.players ) - player.pers["stats"] = player.stats; - - //logString( "game ended" ); - if( !nukeDetonated && !level.postGameNotifies ) - { - if ( !wasOnlyRound() ) - wait 6.0; - else - wait 3.0; - } - else - { - wait ( min( 10.0, 4.0 + level.postGameNotifies ) ); - } - - if ( level.voting && level.voteTime > 0.0 && level.votingMapsTok.size ) - { - level.inVoting = true; - foreach (player in level.players) - { - player.sessionstate = "spectator";//allow player to leave while in intermission and make voting options - player thread watchVoting(); - - player setClientDvars( "hud_ShowWinner", "0", - "hud_voteText", "^3Vote for new map:", - "vote_map", "" ); - - player openPopupMenu( game["menu_vote"] ); - } - - level thread doBotVoting(); - thread timeLimitClock_Intermission( level.voteTime, (84.7, 100, 0) ); - wait level.voteTime; - level.inVoting = false; - - level.highestVotedMap = getHighestVotedMap(); - - if ( level.voteWinTime > 0.0 ) - { - level.inShowingWinner = true; - foreach (player in level.players) - { - player setClientDvars( "hud_WinningName", "preview_" + level.votingMapsTok[ level.highestVotedMap ], - "hud_WinningMap", consoleMapNameToMapName( level.votingMapsTok[ level.highestVotedMap ] ), - "hud_voteText", "^3Next Map:", - "hud_ShowWinner", "1" ); - } - - thread timeLimitClock_Intermission( level.voteWinTime, (84.7, 100, 0) ); - wait level.voteWinTime; - level.inShowingWinner = false; - } - - foreach (player in level.players) - player closeMenu( game["menu_vote"] ); - - level notify( "voting_finished" ); - - level setVoteVars( level.highestVotedMap ); - } - - if ( level.allowIntermission && level.intermissionTime > 0.0 ) - { - level.inIntermission = true; - foreach (player in level.players) - { - player.sessionstate = "spectator";//allow player to leave while in intermission - player thread openSummaryOnMenuClose(); - player openPopupMenu( game["menu_popup_summary"] ); - } - - thread timeLimitClock_Intermission( level.intermissionTime ); - wait level.intermissionTime; - level.inIntermission = false; - - level notify( "intermission_finished" ); - } - - level notify( "exitLevel_called" ); - exitLevel( false ); -} - -setVoteVars( highestVotedMap ) -{ - setDvar( "sv_maprotation", "map " + level.votingMapsTok[ highestVotedMap ] ); - setDvar( "sv_maprotationCurrent", "map " + level.votingMapsTok[ highestVotedMap ] ); -} - -getHighestVotedMap() -{ - highest = 0; - for( i = 0; i < level.mapVotes.size; i++ ) - if( level.mapVotes[ i ] > highest && i < 9 ) - highest = level.mapVotes[ i ]; - - votes = []; - for( i = 0; i < level.mapVotes.size; i++ ) - if( level.mapVotes[ i ] == highest && i < 9 ) - votes[votes.size] = i; - - if ( votes.size ) - return votes[ randomInt( votes.size ) ]; - else if ( level.mapVotes.size > 9 ) - return randomIntRange( 0, 8 ); - else - return randomInt( level.mapVotes.size ); -} - -doBotVoting() -{ - if(!level.botsVote) - return; - - level endon("voting_finished"); - - bots = []; - - foreach(player in level.players) - { - if(!isDefined(player.pers["isBot"]) || !player.pers["isBot"]) - continue; - - player.botWillVoteFor = bots.size; - bots[bots.size] = player; - } - - while(bots.size) - { - wait 0.05; - bot = bots[randomInt(bots.size)]; - if(!bot.hasVoted) - { - bot castMap(bot.botWillVoteFor); - wait randomInt(3); - } - } -} - -ridVoteOnDisconnect() -{ - level endon("voting_finished"); - - self waittill_either( "disconnect", "kill_menus_on_connect" ); - - if ( self.votedNum > -1 ) - level.mapVotes[ self.votedNum ]--; -} - -updateVoteMenu() -{ - self endon("disconnect"); - self endon("kill_menus_on_connect"); - level endon("voting_finished"); - - for(i = 0; i < 9; i++) - { - if( i >= level.votingMapsTok.size ) - { - self setClientDvar( "hud_picName" + i, "white" ); - } - else - { - self setClientDvars( "hud_mapName" + i, consoleMapNameToMapName( level.votingMapsTok[ i ] ), - "hud_mapVotes" + i, level.mapVotes[ i ], - "hud_picName" + i, "preview_" + level.votingMapsTok[ i ] ); - } - } - - for(;;) - { - wait 0.5; - - for( i = 0; i < level.votingMapsTok.size; i++ ) - self setClientDvar( "hud_mapVotes" + i, level.mapVotes[ i ] ); - - highestVotedMap = getHighestVotedMap(); - self setClientDvars( "hud_gamesize", level.players.size, - "hud_mapVotes" + highestVotedMap, "^3" + level.mapVotes[ highestVotedMap ] ); - } -} - -watchVoting() -{ - self endon("disconnect"); - self endon("kill_menus_on_connect"); - level endon("voting_finished"); - - self thread ridVoteOnDisconnect(); - self thread updateVoteMenu(); - - self.hasVoted = false; - self.votedNum = -1; - - for(;;) - { - self waittill("menuresponse", menu, response); - - if( menu == game["menu_vote"] ) - { - switch(response) - { - case "map1": - self castMap(0); - break; - case "map2": - self castMap(1); - break; - case "map3": - self castMap(2); - break; - case "map4": - self castMap(3); - break; - case "map5": - self castMap(4); - break; - case "map6": - self castMap(5); - break; - case "map7": - self castMap(6); - break; - case "map8": - self castMap(7); - break; - case "map9": - self castMap(8); - break; - default: - break; - } - } - else if ( response == "back" ) - { - self closepopupMenu(); - self closeInGameMenu(); - wait 0.25; - self openPopupMenu( game["menu_vote"] ); - continue; - } - } -} - -castMap( number ) -{ - if ( !isDefined( level.votingMapsTok[ number ] ) || level.votingMapsTok[ number ] == "" ) - { - if ( self.hasVoted ) - { - self.hasVoted = false; - level.mapVotes[ self.votedNum ]--; - self.votedNum = -1; - } - self iprintln( "Invalid map selection" ); - return; - } - - if( !self.hasVoted ) - { - self.hasVoted = true; - level.mapVotes[ number ]++; - self.votedNum = number; - self iprintln( "You voted for ^3" + consoleMapNameToMapName( level.votingMapsTok[ number ] ) ); - } - else if( self.votedNum != number ) - { - level.mapVotes[ self.votedNum ]--; - level.mapVotes[ number ]++; - self.votedNum = number; - self iprintln( "You ^3re-voted ^7for ^3" + consoleMapNameToMapName( level.votingMapsTok[ number ] ) ); - } -} - -consoleMapNameToMapName(mapname) -{ - switch(mapname) - { - case "mp_abandon": - return "Carnival"; - case "mp_rundown": - return "Rundown"; - case "mp_afghan": - return "Afghan"; - case "mp_boneyard": - return "Scrapyard"; - case "mp_brecourt": - return "Wasteland"; - case "mp_cargoship": - return "Wetwork"; - case "mp_checkpoint": - return "Karachi"; - case "mp_compact": - return "Salvage"; - case "mp_complex": - return "Bailout"; - case "mp_crash": - return "Crash"; - case "mp_cross_fire": - return "Crossfire"; - case "mp_derail": - return "Derail"; - case "mp_estate": - return "Estate"; - case "mp_favela": - return "Favela"; - case "mp_fuel2": - return "Fuel"; - case "mp_highrise": - return "Highrise"; - case "mp_invasion": - return "Invasion"; - case "mp_killhouse": - return "Killhouse"; - case "mp_nightshift": - return "Skidrow"; - case "mp_nuked": - return "Nuketown"; - case "oilrig": - return "Oilrig"; - case "mp_quarry": - return "Quarry"; - case "mp_rust": - return "Rust"; - case "mp_storm": - return "Storm"; - case "mp_strike": - return "Strike"; - case "mp_subbase": - return "Subbase"; - case "mp_terminal": - return "Terminal"; - case "mp_trailerpark": - return "Trailer Park"; - case "mp_overgrown": - return "Overgrown"; - case "mp_underpass": - return "Underpass"; - case "mp_vacant": - return "Vacant"; - case "iw4_credits": - return "IW4 Test Map"; - case "airport": - return "Airport"; - case "co_hunted": - return "Hunted"; - case "invasion": - return "Burgertown"; - case "mp_bloc": - return "Bloc"; - case "mp_bog_sh": - return "Bog"; - case "contingency": - return "Contingency"; - case "gulag": - return "Gulag"; - case "so_ghillies": - return "Pripyat"; - case "ending": - return "Museum"; - case "af_chase": - return "Afghan Chase"; - case "af_caves": - return "Afghan Caves"; - case "arcadia": - return "Arcadia"; - case "boneyard": - return "Boneyard"; - case "cliffhanger": - return "Cliffhanger"; - case "dcburning": - return "DCBurning"; - case "dcemp": - return "DCEMP"; - case "downtown": - return "Downtown"; - case "estate": - return "EstateSP"; - case "favela": - return "FavelaSP"; - case "favela_escape": - return "Favela Escape"; - case "roadkill": - return "Roadkill"; - case "trainer": - return "TH3 PIT"; - case "so_bridge": - return "Bridge"; - case "dc_whitehouse": - return "Whitehouse"; - default: - return mapname; - } -} - -openSummaryOnMenuClose() -{ - self endon("disconnect"); - self endon("kill_menus_on_connect"); - level endon("intermission_finished"); - - for(;;) - { - self waittill("menuresponse", menu, response); - - if ( response == "back" && menu != game["menu_popup_summary"] ) - { - self closepopupMenu(); - self closeInGameMenu(); - wait 0.25; - self openPopupMenu( game["menu_popup_summary"] ); - continue; - } - } -} - -updateEndReasonText( winner ) -{ - if ( !level.teamBased ) - return true; - - if ( hitRoundLimit() ) - return &"MP_ROUND_LIMIT_REACHED"; - - if ( hitWinLimit() ) - return &"MP_SCORE_LIMIT_REACHED"; - - if ( winner == "axis" ) - return &"SPETSNAZ_WIN"; - else - return &"SAS_WIN"; -} - -estimatedTimeTillScoreLimit( team ) -{ - assert( isPlayer( self ) || isDefined( team ) ); - - scorePerMinute = getScorePerMinute( team ); - scoreRemaining = getScoreRemaining( team ); - - estimatedTimeLeft = 999999; - if ( scorePerMinute ) - estimatedTimeLeft = scoreRemaining / scorePerMinute; - - //println( "estimatedTimeLeft: " + estimatedTimeLeft ); - return estimatedTimeLeft; -} - -getScorePerMinute( team ) -{ - assert( isPlayer( self ) || isDefined( team ) ); - - scoreLimit = getWatchedDvar( "scorelimit" ); - timeLimit = getTimeLimit(); - minutesPassed = (getTimePassed() / (60*1000)) + 0.0001; - - if ( isPlayer( self ) ) - scorePerMinute = self.score / minutesPassed; - else - scorePerMinute = getTeamScore( team ) / minutesPassed; - - return scorePerMinute; -} - -getScoreRemaining( team ) -{ - assert( isPlayer( self ) || isDefined( team ) ); - - scoreLimit = getWatchedDvar( "scorelimit" ); - - if ( isPlayer( self ) ) - scoreRemaining = scoreLimit - self.score; - else - scoreRemaining = scoreLimit - getTeamScore( team ); - - return scoreRemaining; -} - -giveLastOnTeamWarning() -{ - self endon("death"); - self endon("disconnect"); - level endon( "game_ended" ); - - self waitTillRecoveredHealth( 3 ); - - otherTeam = getOtherTeam( self.pers["team"] ); - thread teamPlayerCardSplash( "callout_lastteammemberalive", self, self.pers["team"] ); - thread teamPlayerCardSplash( "callout_lastenemyalive", self, otherTeam ); - level notify ( "last_alive", self ); -} - -processLobbyData() -{ - curPlayer = 0; - foreach ( player in level.players ) - { - if ( !isDefined( player ) ) - continue; - - player.clientMatchDataId = curPlayer; - curPlayer++; - - // on PS3 cap long names - if ( level.ps3 && (player.name.size > level.MaxNameLength) ) - { - playerName = ""; - for ( i = 0; i < level.MaxNameLength-3; i++ ) - playerName += player.name[i]; - - playerName += "..."; - } - else - { - playerName = player.name; - } - - setClientMatchData( "players", player.clientMatchDataId, "xuid", playerName ); - } - - maps\mp\_awards::assignAwards(); - maps\mp\_scoreboard::processLobbyScoreboards(); - - sendClientMatchData(); -} - -getWinningTeam() -{ - if ( game["roundsWon"]["allies"] == game["roundsWon"]["axis"] ) - winner = "tie"; - else if ( game["roundsWon"]["axis"] > game["roundsWon"]["allies"] ) - winner = "axis"; - else - winner = "allies"; - - return winner; -} - -doFinalKillCam() -{ - level waittill ( "round_end_finished" ); - - winner = level.finalKillCam_winner; // we want to show the winner's final kill cam - delay = level.finalKillCam_delay[ winner ]; - victim = level.finalKillCam_victim[ winner ]; - attacker = level.finalKillCam_attacker[ winner ]; - attackerNum = level.finalKillCam_attackerNum[ winner ]; - killCamEntityIndex = level.finalKillCam_killCamEntityIndex[ winner ]; - killCamEntityStartTime = level.finalKillCam_killCamEntityStartTime[ winner ]; - sWeapon = level.finalKillCam_sWeapon[ winner ]; - deathTimeOffset = level.finalKillCam_deathTimeOffset[ winner ]; - psOffsetTime = level.finalKillCam_psOffsetTime[ winner ]; - timeRecorded = level.finalKillCam_timeRecorded[ winner ]/1000; - timeGameEnded = level.gameEndTime/1000; - - if( !isDefined( victim ) || !isDefined( attacker ) ) - return; - - if( !level.forceFinalKillcam || !level.allowFinalKillcam ) - return; - - // if the killcam happened longer than 15 seconds ago, don't show it - killCamBufferTime = 15; - killCamOffsetTime = timeGameEnded - timeRecorded; - - if( killCamOffsetTime > killCamBufferTime ) - return; - - level.showingFinalKillcam = true; - - if ( isDefined( attacker ) ) - { - maps\mp\_awards::addAwardWinner( "finalkill", attacker.clientid ); - attacker.finalKill = true; - } - - postDeathDelay = (( getTime() - victim.deathTime ) / 1000); - - foreach ( player in level.players ) - { - player closePopupMenu(); - player closeInGameMenu(); - - if( isDefined( level.nukeDetonated ) ) - player VisionSetNakedForPlayer( "mpnuke_aftermath", 0 ); - else - player VisionSetNakedForPlayer( getDvar( "mapname" ), 0 ); - - player.killcamentitylookat = victim getEntityNumber(); - - if ( (player != victim || (!isRoundBased() || isLastRound())) && player _hasPerk( "specialty_copycat" ) ) - player _unsetPerk( "specialty_copycat" ); - - player thread maps\mp\gametypes\_killcam::killcam( attackerNum, killcamentityindex, killcamentitystarttime, sWeapon, postDeathDelay + deathTimeOffset, psOffsetTime, 0, 10000, attacker, victim ); - } - - wait( 0.1 ); - - while ( maps\mp\gametypes\_damage::anyPlayersInKillcam() ) - wait( 0.05 ); - - level.showingFinalKillcam = false; -} - -recordFinalKillCam( delay, victim, attacker, attackerNum, killCamEntityIndex, killCamEntityStartTime, sWeapon, deathTimeOffset, psOffsetTime ) -{ - teams[0] = "none"; // none gets filled just in case we need something without a team or this is ffa - - if( level.teambased && IsDefined( attacker.team ) ) - teams[1] = attacker.team; // we want to save each team seperately so we can show the winning team's kill when applicable - - for( i = 0; i < teams.size; i++ ) - { - team = teams[i]; - - level.finalKillCam_delay[ team ] = delay; - level.finalKillCam_victim[ team ] = victim; - level.finalKillCam_attacker[ team ] = attacker; - level.finalKillCam_attackerNum[ team ] = attackerNum; - level.finalKillCam_killCamEntityIndex[ team ] = killCamEntityIndex; - level.finalKillCam_killCamEntityStartTime[ team ] = killCamEntityStartTime; - level.finalKillCam_sWeapon[ team ] = sWeapon; - level.finalKillCam_deathTimeOffset[ team ] = deathTimeOffset; - level.finalKillCam_psOffsetTime[ team ] = psOffsetTime; - level.finalKillCam_timeRecorded[ team ] = getTime(); - } -} diff --git a/userraw/maps/mp/gametypes/_rank.gsc b/userraw/maps/mp/gametypes/_rank.gsc deleted file mode 100644 index 8c38cbe..0000000 --- a/userraw/maps/mp/gametypes/_rank.gsc +++ /dev/null @@ -1,686 +0,0 @@ -#include common_scripts\utility; -#include maps\mp\_utility; -#include maps\mp\gametypes\_hud_util; - - -init() -{ - level.scoreInfo = []; - level.xpScale = getDvarInt( "scr_xpscale" ); - - // if ( level.xpScale > 4 || level.xpScale < 0) - // exitLevel( false ); - - // level.xpScale = min( level.xpScale, 4 ); - // level.xpScale = max( level.xpScale, 0 ); - - level.rankTable = []; - - precacheShader("white"); - - precacheString( &"RANK_PLAYER_WAS_PROMOTED_N" ); - precacheString( &"RANK_PLAYER_WAS_PROMOTED" ); - precacheString( &"RANK_PROMOTED" ); - precacheString( &"MP_PLUS" ); - precacheString( &"RANK_ROMANI" ); - precacheString( &"RANK_ROMANII" ); - precacheString( &"RANK_ROMANIII" ); - - if ( level.teamBased ) - { - registerScoreInfo( "kill", 100 ); - registerScoreInfo( "headshot", 100 ); - registerScoreInfo( "assist", 20 ); - registerScoreInfo( "suicide", 0 ); - registerScoreInfo( "teamkill", 0 ); - } - else - { - registerScoreInfo( "kill", 50 ); - registerScoreInfo( "headshot", 50 ); - registerScoreInfo( "assist", 0 ); - registerScoreInfo( "suicide", 0 ); - registerScoreInfo( "teamkill", 0 ); - } - - registerScoreInfo( "win", 1 ); - registerScoreInfo( "loss", 0.5 ); - registerScoreInfo( "tie", 0.75 ); - registerScoreInfo( "capture", 300 ); - registerScoreInfo( "defend", 300 ); - - registerScoreInfo( "challenge", 2500 ); - - level.maxRank = int(tableLookup( "mp/rankTable.csv", 0, "maxrank", 1 )); - level.maxPrestige = int(tableLookup( "mp/rankIconTable.csv", 0, "maxprestige", 1 )); - - pId = 0; - rId = 0; - for ( pId = 0; pId <= level.maxPrestige; pId++ ) - { - for ( rId = 0; rId <= level.maxRank; rId++ ) - precacheShader( tableLookup( "mp/rankIconTable.csv", 0, rId, pId+1 ) ); - } - - rankId = 0; - rankName = tableLookup( "mp/ranktable.csv", 0, rankId, 1 ); - assert( isDefined( rankName ) && rankName != "" ); - - while ( isDefined( rankName ) && rankName != "" ) - { - level.rankTable[rankId][1] = tableLookup( "mp/ranktable.csv", 0, rankId, 1 ); - level.rankTable[rankId][2] = tableLookup( "mp/ranktable.csv", 0, rankId, 2 ); - level.rankTable[rankId][3] = tableLookup( "mp/ranktable.csv", 0, rankId, 3 ); - level.rankTable[rankId][7] = tableLookup( "mp/ranktable.csv", 0, rankId, 7 ); - - precacheString( tableLookupIString( "mp/ranktable.csv", 0, rankId, 16 ) ); - - rankId++; - rankName = tableLookup( "mp/ranktable.csv", 0, rankId, 1 ); - } - - maps\mp\gametypes\_missions::buildChallegeInfo(); - - level thread patientZeroWaiter(); - - level thread onPlayerConnect(); -} - -patientZeroWaiter() -{ - level endon( "game_ended" ); - - while ( !isDefined( level.players ) || !level.players.size ) - wait ( 0.05 ); - - if ( !matchMakingGame() ) - { - if ( (getDvar( "mapname" ) == "mp_rust" && randomInt( 1000 ) == 999) ) - level.patientZeroName = level.players[0].name; - } - else - { - if ( getDvar( "scr_patientZero" ) != "" ) - level.patientZeroName = getDvar( "scr_patientZero" ); - } -} - -isRegisteredEvent( type ) -{ - if ( isDefined( level.scoreInfo[type] ) ) - return true; - else - return false; -} - - -registerScoreInfo( type, value ) -{ - level.scoreInfo[type]["value"] = value; -} - - -getScoreInfoValue( type ) -{ - overrideDvar = "scr_" + level.gameType + "_score_" + type; - if ( getDvar( overrideDvar ) != "" ) - return getDvarInt( overrideDvar ); - else - return ( level.scoreInfo[type]["value"] ); -} - - -getScoreInfoLabel( type ) -{ - return ( level.scoreInfo[type]["label"] ); -} - - -getRankInfoMinXP( rankId ) -{ - return int(level.rankTable[rankId][2]); -} - - -getRankInfoXPAmt( rankId ) -{ - return int(level.rankTable[rankId][3]); -} - - -getRankInfoMaxXp( rankId ) -{ - return int(level.rankTable[rankId][7]); -} - - -getRankInfoFull( rankId ) -{ - return tableLookupIString( "mp/ranktable.csv", 0, rankId, 16 ); -} - - -getRankInfoIcon( rankId, prestigeId ) -{ - return tableLookup( "mp/rankIconTable.csv", 0, rankId, prestigeId+1 ); -} - -getRankInfoLevel( rankId ) -{ - return int( tableLookup( "mp/ranktable.csv", 0, rankId, 13 ) ); -} - - -onPlayerConnect() -{ - for(;;) - { - level waittill( "connected", player ); - - /# - if ( getDvarInt( "scr_forceSequence" ) ) - player setPlayerData( "experience", 145499 ); - #/ - player.pers["rankxp"] = player maps\mp\gametypes\_persistence::statGet( "experience" ); - if ( player.pers["rankxp"] < 0 ) // paranoid defensive - player.pers["rankxp"] = 0; - - rankId = player getRankForXp( player getRankXP() ); - player.pers[ "rank" ] = rankId; - player.pers[ "participation" ] = 0; - - player.xpUpdateTotal = 0; - player.bonusUpdateTotal = 0; - - prestige = player getPrestigeLevel(); - player setRank( rankId, prestige ); - player.pers["prestige"] = prestige; - - player.postGamePromotion = false; - if ( !isDefined( player.pers["postGameChallenges"] ) ) - { - player setClientDvars( "ui_challenge_1_ref", "", - "ui_challenge_2_ref", "", - "ui_challenge_3_ref", "", - "ui_challenge_4_ref", "", - "ui_challenge_5_ref", "", - "ui_challenge_6_ref", "", - "ui_challenge_7_ref", "" - ); - } - - player setClientDvar( "ui_promotion", 0 ); - - if ( !isDefined( player.pers["summary"] ) ) - { - player.pers["summary"] = []; - player.pers["summary"]["xp"] = 0; - player.pers["summary"]["score"] = 0; - player.pers["summary"]["challenge"] = 0; - player.pers["summary"]["match"] = 0; - player.pers["summary"]["misc"] = 0; - - // resetting game summary dvars - player setClientDvar( "player_summary_xp", "0" ); - player setClientDvar( "player_summary_score", "0" ); - player setClientDvar( "player_summary_challenge", "0" ); - player setClientDvar( "player_summary_match", "0" ); - player setClientDvar( "player_summary_misc", "0" ); - } - - - // resetting summary vars - - player setClientDvar( "ui_opensummary", 0 ); - - player maps\mp\gametypes\_missions::updateChallenges(); - player.explosiveKills[0] = 0; - player.xpGains = []; - - player.hud_scorePopup = newClientHudElem( player ); - player.hud_scorePopup.horzAlign = "center"; - player.hud_scorePopup.vertAlign = "middle"; - player.hud_scorePopup.alignX = "center"; - player.hud_scorePopup.alignY = "middle"; - player.hud_scorePopup.x = 0; - if ( level.splitScreen ) - player.hud_scorePopup.y = -40; - else - player.hud_scorePopup.y = -60; - player.hud_scorePopup.font = "hudbig"; - player.hud_scorePopup.fontscale = 0.75; - player.hud_scorePopup.archived = false; - player.hud_scorePopup.color = (0.5,0.5,0.5); - player.hud_scorePopup.sort = 10000; - player.hud_scorePopup maps\mp\gametypes\_hud::fontPulseInit( 3.0 ); - - player thread onPlayerSpawned(); - player thread onJoinedTeam(); - player thread onJoinedSpectators(); - } -} - - -onJoinedTeam() -{ - self endon("disconnect"); - - for(;;) - { - self waittill( "joined_team" ); - self thread removeRankHUD(); - } -} - - -onJoinedSpectators() -{ - self endon("disconnect"); - - for(;;) - { - self waittill( "joined_spectators" ); - self thread removeRankHUD(); - } -} - - -onPlayerSpawned() -{ - self endon("disconnect"); - - for(;;) - { - self waittill("spawned_player"); - } -} - - -roundUp( floatVal ) -{ - if ( int( floatVal ) != floatVal ) - return int( floatVal+1 ); - else - return int( floatVal ); -} - - -giveRankXP( type, value ) -{ - self endon("disconnect"); - - lootType = "none"; - - if ( !self rankingEnabled() ) - return; - - if ( level.teamBased && (!level.teamCount["allies"] || !level.teamCount["axis"]) ) - return; - else if ( !level.teamBased && (level.teamCount["allies"] + level.teamCount["axis"] < 2) ) - return; - - if ( !isDefined( value ) ) - value = getScoreInfoValue( type ); - - if ( !isDefined( self.xpGains[type] ) ) - self.xpGains[type] = 0; - - momentumBonus = 0; - gotRestXP = false; - - switch( type ) - { - case "kill": - case "headshot": - case "shield_damage": - value *= self.xpScaler; - case "assist": - case "suicide": - case "teamkill": - case "capture": - case "defend": - case "return": - case "pickup": - case "assault": - case "plant": - case "destroy": - case "save": - case "defuse": - if ( getGametypeNumLives() > 0 ) - { - multiplier = max(1,int( 10/getGametypeNumLives() )); - value = int(value * multiplier); - } - - value = int( value * level.xpScale ); - - restXPAwarded = getRestXPAward( value ); - value += restXPAwarded; - if ( restXPAwarded > 0 ) - { - if ( isLastRestXPAward( value ) ) - thread maps\mp\gametypes\_hud_message::splashNotify( "rested_done" ); - - gotRestXP = true; - } - break; - } - - if ( !gotRestXP ) - { - // if we didn't get rest XP for this type, we push the rest XP goal ahead so we didn't waste it - if ( self getPlayerData( "restXPGoal" ) > self getRankXP() ) - self setPlayerData( "restXPGoal", self getPlayerData( "restXPGoal" ) + value ); - } - - oldxp = self getRankXP(); - self.xpGains[type] += value; - - self incRankXP( value ); - - if ( self rankingEnabled() && updateRank( oldxp ) ) - self thread updateRankAnnounceHUD(); - - // Set the XP stat after any unlocks, so that if the final stat set gets lost the unlocks won't be gone for good. - self syncXPStat(); - - if ( !level.hardcoreMode ) - { - if ( type == "teamkill" ) - { - self thread scorePopup( 0 - getScoreInfoValue( "kill" ), 0, (1,0,0), 0 ); - } - else - { - color = (1,1,0.5); - if ( gotRestXP ) - color = (1,.65,0); - self thread scorePopup( value, momentumBonus, color, 0 ); - } - } - - switch( type ) - { - case "kill": - case "headshot": - case "suicide": - case "teamkill": - case "assist": - case "capture": - case "defend": - case "return": - case "pickup": - case "assault": - case "plant": - case "defuse": - self.pers["summary"]["score"] += value; - self.pers["summary"]["xp"] += value; - break; - - case "win": - case "loss": - case "tie": - self.pers["summary"]["match"] += value; - self.pers["summary"]["xp"] += value; - break; - - case "challenge": - self.pers["summary"]["challenge"] += value; - self.pers["summary"]["xp"] += value; - break; - - default: - self.pers["summary"]["misc"] += value; //keeps track of ungrouped match xp reward - self.pers["summary"]["match"] += value; - self.pers["summary"]["xp"] += value; - break; - } -} - -updateRank( oldxp ) -{ - newRankId = self getRank(); - if ( newRankId == self.pers["rank"] ) - return false; - - oldRank = self.pers["rank"]; - rankId = self.pers["rank"]; - self.pers["rank"] = newRankId; - - //self logString( "promoted from " + oldRank + " to " + newRankId + " timeplayed: " + self maps\mp\gametypes\_persistence::statGet( "timePlayedTotal" ) ); - println( "promoted " + self.name + " from rank " + oldRank + " to " + newRankId + ". Experience went from " + oldxp + " to " + self getRankXP() + "." ); - - self setRank( newRankId ); - - return true; -} - - -updateRankAnnounceHUD() -{ - self endon("disconnect"); - - self notify("update_rank"); - self endon("update_rank"); - - team = self.pers["team"]; - if ( !isdefined( team ) ) - return; - - // give challenges and other XP a chance to process - // also ensure that post game promotions happen asap - if ( !levelFlag( "game_over" ) ) - level waittill_notify_or_timeout( "game_over", 0.25 ); - - - newRankName = self getRankInfoFull( self.pers["rank"] ); - rank_char = level.rankTable[self.pers["rank"]][1]; - subRank = int(rank_char[rank_char.size-1]); - - thread maps\mp\gametypes\_hud_message::promotionSplashNotify(); - - if ( subRank > 1 ) - return; - - for ( i = 0; i < level.players.size; i++ ) - { - player = level.players[i]; - playerteam = player.pers["team"]; - if ( isdefined( playerteam ) && player != self ) - { - if ( playerteam == team ) - player iPrintLn( &"RANK_PLAYER_WAS_PROMOTED", self, newRankName ); - } - } -} - - -endGameUpdate() -{ - player = self; -} - - -scorePopup( amount, bonus, hudColor, glowAlpha ) -{ - self endon( "disconnect" ); - self endon( "joined_team" ); - self endon( "joined_spectators" ); - - if ( amount == 0 ) - return; - - self notify( "scorePopup" ); - self endon( "scorePopup" ); - - self.xpUpdateTotal += amount; - self.bonusUpdateTotal += bonus; - - wait ( 0.05 ); - - if ( self.xpUpdateTotal < 0 ) - self.hud_scorePopup.label = &""; - else - self.hud_scorePopup.label = &"MP_PLUS"; - - self.hud_scorePopup.color = hudColor; - self.hud_scorePopup.glowColor = hudColor; - self.hud_scorePopup.glowAlpha = glowAlpha; - - self.hud_scorePopup setValue(self.xpUpdateTotal); - self.hud_scorePopup.alpha = 0.85; - self.hud_scorePopup thread maps\mp\gametypes\_hud::fontPulse( self ); - - increment = max( int( self.bonusUpdateTotal / 20 ), 1 ); - - if ( self.bonusUpdateTotal ) - { - while ( self.bonusUpdateTotal > 0 ) - { - self.xpUpdateTotal += min( self.bonusUpdateTotal, increment ); - self.bonusUpdateTotal -= min( self.bonusUpdateTotal, increment ); - - self.hud_scorePopup setValue( self.xpUpdateTotal ); - - wait ( 0.05 ); - } - } - else - { - wait ( 1.0 ); - } - - self.hud_scorePopup fadeOverTime( 0.75 ); - self.hud_scorePopup.alpha = 0; - - self.xpUpdateTotal = 0; -} - -removeRankHUD() -{ - self.hud_scorePopup.alpha = 0; -} - -getRank() -{ - rankXp = self.pers["rankxp"]; - rankId = self.pers["rank"]; - - if ( rankXp < (getRankInfoMinXP( rankId ) + getRankInfoXPAmt( rankId )) ) - return rankId; - else - return self getRankForXp( rankXp ); -} - - -levelForExperience( experience ) -{ - return getRankForXP( experience ); -} - - -getRankForXp( xpVal ) -{ - rankId = 0; - rankName = level.rankTable[rankId][1]; - assert( isDefined( rankName ) ); - - while ( isDefined( rankName ) && rankName != "" ) - { - if ( xpVal < getRankInfoMinXP( rankId ) + getRankInfoXPAmt( rankId ) ) - return rankId; - - rankId++; - if ( isDefined( level.rankTable[rankId] ) ) - rankName = level.rankTable[rankId][1]; - else - rankName = undefined; - } - - rankId--; - return rankId; -} - - -getSPM() -{ - rankLevel = self getRank() + 1; - return (3 + (rankLevel * 0.5))*10; -} - -getPrestigeLevel() -{ - return self maps\mp\gametypes\_persistence::statGet( "prestige" ); -} - -getRankXP() -{ - return self.pers["rankxp"]; -} - -incRankXP( amount ) -{ - if ( !self rankingEnabled() ) - return; - - if ( isDefined( self.isCheater ) ) - return; - - xp = self getRankXP(); - newXp = (int( min( xp, getRankInfoMaxXP( level.maxRank ) ) ) + amount); - - if ( self.pers["rank"] == level.maxRank && newXp >= getRankInfoMaxXP( level.maxRank ) ) - newXp = getRankInfoMaxXP( level.maxRank ); - - self.pers["rankxp"] = newXp; -} - -getRestXPAward( baseXP ) -{ - if ( !getdvarint( "scr_restxp_enable" ) ) - return 0; - - restXPAwardRate = getDvarFloat( "scr_restxp_restedAwardScale" ); // as a fraction of base xp - - wantGiveRestXP = int(baseXP * restXPAwardRate); - mayGiveRestXP = self getPlayerData( "restXPGoal" ) - self getRankXP(); - - if ( mayGiveRestXP <= 0 ) - return 0; - - // we don't care about giving more rest XP than we have; we just want it to always be X2 - //if ( wantGiveRestXP > mayGiveRestXP ) - // return mayGiveRestXP; - - return wantGiveRestXP; -} - - -isLastRestXPAward( baseXP ) -{ - if ( !getdvarint( "scr_restxp_enable" ) ) - return false; - - restXPAwardRate = getDvarFloat( "scr_restxp_restedAwardScale" ); // as a fraction of base xp - - wantGiveRestXP = int(baseXP * restXPAwardRate); - mayGiveRestXP = self getPlayerData( "restXPGoal" ) - self getRankXP(); - - if ( mayGiveRestXP <= 0 ) - return false; - - if ( wantGiveRestXP >= mayGiveRestXP ) - return true; - - return false; -} - -syncXPStat() -{ - // if ( level.xpScale > 4 || level.xpScale <= 0) - // exitLevel( false ); - - xp = self getRankXP(); - - self maps\mp\gametypes\_persistence::statSet( "experience", xp ); -} diff --git a/userraw/maps/mp/gametypes/_weapons.gsc b/userraw/maps/mp/gametypes/_weapons.gsc deleted file mode 100644 index 90befa0..0000000 --- a/userraw/maps/mp/gametypes/_weapons.gsc +++ /dev/null @@ -1,3031 +0,0 @@ -#include common_scripts\utility; -#include maps\mp\_utility; - - -attachmentGroup( attachmentName ) -{ - return tableLookup( "mp/attachmentTable.csv", 4, attachmentName, 2 ); -} - -getAttachmentList() -{ - attachmentList = []; - - index = 0; - attachmentName = tableLookup( "mp/attachmentTable.csv", 9, index, 4 ); - - while ( attachmentName != "" ) - { - attachmentList[attachmentList.size] = attachmentName; - - index++; - attachmentName = tableLookup( "mp/attachmentTable.csv", 9, index, 4 ); - } - - return alphabetize( attachmentList ); -} - -init() -{ - level.scavenger_altmode = true; - level.scavenger_secondary = true; - - // 0 is not valid - level.maxPerPlayerExplosives = max( getIntProperty( "scr_maxPerPlayerExplosives", 2 ), 1 ); - level.riotShieldXPBullets = getIntProperty( "scr_riotShieldXPBullets", 15 ); - - switch ( getIntProperty( "perk_scavengerMode", 0 ) ) - { - case 1: // disable altmode - level.scavenger_altmode = false; - break; - - case 2: // disable secondary - level.scavenger_secondary = false; - break; - - case 3: // disable altmode and secondary - level.scavenger_altmode = false; - level.scavenger_secondary = false; - break; - } - - setDvarIfUninitialized("scr_allowDropWeaponOnCommand", false); - setDvarIfUninitialized("scr_allowPickUpEquipment", false); - setDvarIfUninitialized("scr_allowDropWeaponOnDeath", true); - setDvarIfUninitialized("scr_allowClaymoreBounces", true); - setDvarIfUninitialized("scr_extraTeamIcons", false); - setDvarIfUninitialized("scr_deleteNadeOnTeamChange", false); - - level.allowDropWeaponOnCommand = getDvarInt("scr_allowDropWeaponOnCommand"); - level.allowDropWeaponOnDeath = getDvarInt("scr_allowDropWeaponOnDeath"); - level.allowPickUpEquipment = getDvarInt("scr_allowPickUpEquipment"); - level.allowExtendedClaymoreTrace = getDvarInt("scr_allowClaymoreBounces"); - level.extraTeamIcons = getDvarInt("scr_extraTeamIcons"); - level.deleteNadeOnTeamChange = getDvarInt("scr_deleteNadeOnTeamChange"); - - attachmentList = getAttachmentList(); - - // assigns weapons with stat numbers from 0-149 - // attachments are now shown here, they are per weapon settings instead - - max_weapon_num = 149; - - level.weaponList = []; - for( weaponId = 0; weaponId <= max_weapon_num; weaponId++ ) - { - weapon_name = tablelookup( "mp/statstable.csv", 0, weaponId, 4 ); - if( weapon_name == "" ) - continue; - - if ( !isSubStr( tableLookup( "mp/statsTable.csv", 0, weaponId, 2 ), "weapon_" ) ) - continue; - - level.weaponList[level.weaponList.size] = weapon_name + "_mp"; - /# - if ( getDvar( "scr_dump_weapon_assets" ) != "" ) - { - printLn( "" ); - printLn( "// " + weapon_name + " real assets" ); - printLn( "weapon,mp/" + weapon_name + "_mp" ); - } - #/ - - // the alphabetize function is slow so we try not to do it for every weapon/attachment combo; a code solution would be better. - attachmentNames = []; - for ( innerLoopCount = 0; innerLoopCount < 10; innerLoopCount++ ) - { - // generating attachment combinations - attachmentName = tablelookup( "mp/statStable.csv", 0, weaponId, innerLoopCount + 11 ); - - if( attachmentName == "" ) - break; - - attachmentNames[attachmentName] = true; - } - - // generate an alphabetized attachment list - attachments = []; - foreach ( attachmentName in attachmentList ) - { - if ( !isDefined( attachmentNames[attachmentName] ) ) - continue; - - level.weaponList[level.weaponList.size] = weapon_name + "_" + attachmentName + "_mp"; - attachments[attachments.size] = attachmentName; - /# - if ( getDvar( "scr_dump_weapon_assets" ) != "" ) - println( "weapon,mp/" + weapon_name + "_" + attachmentName + "_mp" ); - #/ - } - - attachmentCombos = []; - for ( i = 0; i < (attachments.size - 1); i++ ) - { - colIndex = tableLookupRowNum( "mp/attachmentCombos.csv", 0, attachments[i] ); - for ( j = i + 1; j < attachments.size; j++ ) - { - if ( tableLookup( "mp/attachmentCombos.csv", 0, attachments[j], colIndex ) == "no" ) - continue; - - attachmentCombos[attachmentCombos.size] = attachments[i] + "_" + attachments[j]; - } - } - - /# - if ( getDvar( "scr_dump_weapon_assets" ) != "" && attachmentCombos.size ) - println( "// " + weapon_name + " virtual assets" ); - #/ - - foreach ( combo in attachmentCombos ) - { - /# - if ( getDvar( "scr_dump_weapon_assets" ) != "" ) - println( "weapon,mp/" + weapon_name + "_" + combo + "_mp" ); - #/ - - level.weaponList[level.weaponList.size] = weapon_name + "_" + combo + "_mp"; - } - } - - foreach ( weaponName in level.weaponList ) - { - precacheItem( weaponName ); - - /# - if ( getDvar( "scr_dump_weapon_assets" ) != "" ) - { - altWeapon = weaponAltWeaponName( weaponName ); - if ( altWeapon != "none" ) - println( "weapon,mp/" + altWeapon ); - } - #/ - } - - precacheItem( "flare_mp" ); - precacheItem( "scavenger_bag_mp" ); - precacheItem( "frag_grenade_short_mp" ); - precacheItem( "destructible_car" ); - - precacheShellShock( "default" ); - precacheShellShock( "concussion_grenade_mp" ); - thread maps\mp\_flashgrenades::main(); - thread maps\mp\_entityheadicons::init(); - - claymoreDetectionConeAngle = 70; - level.claymoreDetectionDot = cos( claymoreDetectionConeAngle ); - level.claymoreDetectionMinDist = 20; - level.claymoreDetectionGracePeriod = .75; - level.claymoreDetonateRadius = 192; - - // this should move to _stinger.gsc - level.stingerFXid = loadfx ("explosions/aerial_explosion_large"); - - // generating weapon type arrays which classifies the weapon as primary (back stow), pistol, or inventory (side pack stow) - // using mp/statstable.csv's weapon grouping data ( numbering 0 - 149 ) - level.primary_weapon_array = []; - level.side_arm_array = []; - level.grenade_array = []; - level.inventory_array = []; - level.stow_priority_model_array = []; - level.stow_offset_array = []; - - max_weapon_num = 149; - for( i = 0; i < max_weapon_num; i++ ) - { - weapon = tableLookup( "mp/statsTable.csv", 0, i, 4 ); - stow_model = tableLookup( "mp/statsTable.csv", 0, i, 9 ); - - if ( stow_model == "" ) - continue; - - precacheModel( stow_model ); - - if ( isSubStr( stow_model, "weapon_stow_" ) ) - level.stow_offset_array[ weapon ] = stow_model; - else - level.stow_priority_model_array[ weapon + "_mp" ] = stow_model; - } - - precacheModel( "weapon_claymore_bombsquad" ); - precacheModel( "weapon_c4_bombsquad" ); - precacheModel( "projectile_m67fraggrenade_bombsquad" ); - precacheModel( "projectile_semtex_grenade_bombsquad" ); - precacheModel( "weapon_light_stick_tactical_bombsquad" ); - - level.killStreakSpecialCaseWeapons = []; - level.killStreakSpecialCaseWeapons["cobra_player_minigun_mp"] = true; - level.killStreakSpecialCaseWeapons["artillery_mp"] = true; - level.killStreakSpecialCaseWeapons["stealth_bomb_mp"] = true; - level.killStreakSpecialCaseWeapons["pavelow_minigun_mp"] = true; - level.killStreakSpecialCaseWeapons["sentry_minigun_mp"] = true; - level.killStreakSpecialCaseWeapons["harrier_20mm_mp"] = true; - level.killStreakSpecialCaseWeapons["ac130_105mm_mp"] = true; - level.killStreakSpecialCaseWeapons["ac130_40mm_mp"] = true; - level.killStreakSpecialCaseWeapons["ac130_25mm_mp"] = true; - level.killStreakSpecialCaseWeapons["remotemissile_projectile_mp"] = true; - level.killStreakSpecialCaseWeapons["cobra_20mm_mp"] = true; - level.killStreakSpecialCaseWeapons["sentry_minigun_mp"] = true; - - - level thread onPlayerConnect(); - - level thread watchSentryLimit(); - - level.c4explodethisframe = false; - - array_thread( getEntArray( "misc_turret", "classname" ), ::turret_monitorUse ); - -// thread dumpIt(); -} - - -watchSentryLimit() -{ - for(;;) - { - sentries = getentarray( "misc_turret", "classname" ); - if(sentries.size > 30) - sentries[0] delete(); - - wait 0.05; - } -} - - -dumpIt() -{ - - wait ( 5.0 ); - /# - max_weapon_num = 149; - - for( weaponId = 0; weaponId <= max_weapon_num; weaponId++ ) - { - weapon_name = tablelookup( "mp/statstable.csv", 0, weaponId, 4 ); - if( weapon_name == "" ) - continue; - - if ( !isSubStr( tableLookup( "mp/statsTable.csv", 0, weaponId, 2 ), "weapon_" ) ) - continue; - - if ( getDvar( "scr_dump_weapon_challenges" ) != "" ) - { - /* - sharpshooter - marksman - veteran - expert - master - */ - - weaponLStringName = tableLookup( "mp/statsTable.csv", 0, weaponId, 3 ); - weaponRealName = tableLookupIString( "mp/statsTable.csv", 0, weaponId, 3 ); - - prefix = "WEAPON_"; - weaponCapsName = getSubStr( weaponLStringName, prefix.size, weaponLStringName.size ); - - weaponGroup = tableLookup( "mp/statsTable.csv", 0, weaponId, 2 ); - - weaponGroupSuffix = getSubStr( weaponGroup, prefix.size, weaponGroup.size ); - - /* - iprintln( "REFERENCE TITLE_" + weaponCapsName + "_SHARPSHOOTER" ); - iprintln( "LANG_ENGLISH ", weaponRealName, ": Sharpshooter" ); - iprintln( "" ); - iprintln( "REFERENCE TITLE_" + weaponCapsName + "_MARKSMAN" ); - iprintln( "LANG_ENGLISH ", weaponRealName, ": Marksman" ); - iprintln( "" ); - iprintln( "REFERENCE TITLE_" + weaponCapsName + "_VETERAN" ); - iprintln( "LANG_ENGLISH ", weaponRealName, ": Veteran" ); - iprintln( "" ); - iprintln( "REFERENCE TITLE_" + weaponCapsName + "_EXPERT" ); - iprintln( "LANG_ENGLISH ", weaponRealName, ": Expert" ); - iprintln( "" ); - iprintln( "REFERENCE TITLE_" + weaponCapsName + "_Master" ); - iprintln( "LANG_ENGLISH ", weaponRealName, ": Master" ); - */ - - iprintln( "cardtitle_" + weapon_name + "_sharpshooter,PLAYERCARDS_TITLE_" + weaponCapsName + "_SHARPSHOOTER,cardtitle_" + weaponGroupSuffix + "_sharpshooter,1,1,1" ); - iprintln( "cardtitle_" + weapon_name + "_marksman,PLAYERCARDS_TITLE_" + weaponCapsName + "_MARKSMAN,cardtitle_" + weaponGroupSuffix + "_marksman,1,1,1" ); - iprintln( "cardtitle_" + weapon_name + "_veteran,PLAYERCARDS_TITLE_" + weaponCapsName + "_VETERAN,cardtitle_" + weaponGroupSuffix + "_veteran,1,1,1" ); - iprintln( "cardtitle_" + weapon_name + "_expert,PLAYERCARDS_TITLE_" + weaponCapsName + "_EXPERT,cardtitle_" + weaponGroupSuffix + "_expert,1,1,1" ); - iprintln( "cardtitle_" + weapon_name + "_master,PLAYERCARDS_TITLE_" + weaponCapsName + "_MASTER,cardtitle_" + weaponGroupSuffix + "_master,1,1,1" ); - - wait ( 0.05 ); - } - } - #/ -} - -bombSquadWaiter() -{ - self endon ( "disconnect" ); - - for ( ;; ) - { - self waittill ( "grenade_fire", weaponEnt, weaponName ); - - team = level.otherTeam[self.team]; - - if ( weaponName == "c4_mp" ) - weaponEnt thread createBombSquadModel( "weapon_c4_bombsquad", "tag_origin", team, self ); - else if ( weaponName == "claymore_mp" ) - weaponEnt thread createBombSquadModel( "weapon_claymore_bombsquad", "tag_origin", team, self ); - else if ( weaponName == "frag_grenade_mp" ) - weaponEnt thread createBombSquadModel( "projectile_m67fraggrenade_bombsquad", "tag_weapon", team, self ); - else if ( weaponName == "frag_grenade_short_mp" ) - weaponEnt thread createBombSquadModel( "projectile_m67fraggrenade_bombsquad", "tag_weapon", team, self ); - else if ( weaponName == "semtex_mp" ) - weaponEnt thread createBombSquadModel( "projectile_semtex_grenade_bombsquad", "tag_weapon", team, self ); - } -} - - -createBombSquadModel( modelName, tagName, teamName, owner ) -{ - bombSquadModel = spawn( "script_model", (0,0,0) ); - bombSquadModel hide(); - wait ( 0.05 ); - - if (!isDefined( self ) ) //grenade model may not be around if picked up - return; - - bombSquadModel thread bombSquadVisibilityUpdater( teamName, owner ); - bombSquadModel setModel( modelName ); - bombSquadModel linkTo( self, tagName, (0,0,0), (0,0,0) ); - bombSquadModel SetContents( 0 ); - - self waittill ( "death" ); - - bombSquadModel delete(); -} - - -bombSquadVisibilityUpdater( teamName, owner ) -{ - self endon ( "death" ); - - foreach ( player in level.players ) - { - if ( level.teamBased ) - { - if ( player.team == teamName && player _hasPerk( "specialty_detectexplosive" ) ) - self showToPlayer( player ); - } - else - { - if ( isDefined( owner ) && player == owner ) - continue; - - if ( !player _hasPerk( "specialty_detectexplosive" ) ) - continue; - - self showToPlayer( player ); - } - } - - for ( ;; ) - { - level waittill_any( "joined_team", "player_spawned", "changed_kit" ); - - self hide(); - - foreach ( player in level.players ) - { - if ( level.teamBased ) - { - if ( player.team == teamName && player _hasPerk( "specialty_detectexplosive" ) ) - self showToPlayer( player ); - } - else - { - if ( isDefined( owner ) && player == owner ) - continue; - - if ( !player _hasPerk( "specialty_detectexplosive" ) ) - continue; - - self showToPlayer( player ); - } - } - } -} - - -onPlayerConnect() -{ - for(;;) - { - level waittill("connected", player); - - player.hits = 0; - player.hasDoneCombat = false; - - player KC_RegWeaponForFXRemoval( "remotemissile_projectile_mp" ); - - player thread onPlayerSpawned(); - player thread bombSquadWaiter(); - player thread monitorSemtex(); - } -} - - -onPlayerSpawned() -{ - self endon("disconnect"); - - for(;;) - { - self waittill("spawned_player"); - - self.currentWeaponAtSpawn = self getCurrentWeapon(); // optimization so these threads we start don't have to call it. - - self.empEndTime = 0; - self.concussionEndTime = 0; - self.hasDoneCombat = false; - self thread watchWeaponUsage(); - self thread watchGrenadeUsage(); - self thread watchWeaponChange(); - self thread watchStingerUsage(); - self thread watchJavelinUsage(); - self thread watchMissileUsage(); - self thread watchSentryUsage(); - self thread watchWeaponReload(); - self thread maps\mp\gametypes\_class::trackRiotShield(); - self thread watchDropWeaponOnCommand(); - - self.lastHitTime = []; - - self.droppedDeathWeapon = undefined; - self.tookWeaponFrom = []; - - self thread updateStowedWeapon(); - - self thread updateSavedLastWeapon(); - - self.currentWeaponAtSpawn = undefined; - } -} - -watchDropWeaponOnCommand() -{ - if( !level.allowDropWeaponOnCommand ) - return; - - self endon( "disconnect" ); - self endon( "death" ); - - self notifyOnPlayerCommand( "drop_weapon_on_cmd", "+actionslot 2" ); - for(;;) - { - self waittill( "drop_weapon_on_cmd" ); - weapon = self GetCurrentWeapon(); - - if ( !gameFlag( "prematch_done" ) || !isDefined( weapon ) ) - continue; - - if( level.gameEnded ) - continue; - - if( !mayDropWeapon( weapon ) ) - continue; - - if ( !self hasWeapon( weapon ) ) - continue; - - if ( weapon != "riotshield_mp" ) - { - if ( !(self AnyAmmoForWeaponModes( weapon )) ) - { - continue; - } - - clipAmmoR = self GetWeaponAmmoClip( weapon, "right" ); - clipAmmoL = self GetWeaponAmmoClip( weapon, "left" ); - if ( !clipAmmoR && !clipAmmoL ) - { - continue; - } - - stockAmmo = self GetWeaponAmmoStock( weapon ); - stockMax = WeaponMaxAmmo( weapon ); - if ( stockAmmo > stockMax ) - stockAmmo = stockMax; - - item = self dropItem( weapon ); - item ItemWeaponSetAmmo( clipAmmoR, stockAmmo, clipAmmoL ); - } - else - { - item = self dropItem( weapon ); - if ( !isDefined( item ) ) - continue; - item ItemWeaponSetAmmo( 1, 1, 0 ); - } - item.owner = self; - - item thread maps\mp\gametypes\_weapons::watchPickup(); - - //deletes dropped weapon after 30 sec. - item thread maps\mp\gametypes\_weapons::deletePickupAfterAWhile(); - - detach_model = getWeaponModel( weapon ); - - if ( !isDefined( detach_model ) ) - continue; - - if( isDefined( self.tag_stowed_back ) && detach_model == self.tag_stowed_back ) - self maps\mp\gametypes\_weapons::detach_back_weapon(); - - if ( !isDefined( self.tag_stowed_hip ) ) - continue; - - if( detach_model == self.tag_stowed_hip ) - self maps\mp\gametypes\_weapons::detach_hip_weapon(); - } -} - -WatchStingerUsage() -{ - self maps\mp\_stinger::StingerUsageLoop(); -} - - -WatchJavelinUsage() -{ - self maps\mp\_javelin::JavelinUsageLoop(); -} - -watchWeaponChange() -{ - self endon("death"); - self endon("disconnect"); - - self thread watchStartWeaponChange(); - self.lastDroppableWeapon = self.currentWeaponAtSpawn; - self.hitsThisMag = []; - - weapon = self getCurrentWeapon(); - - if ( isCACPrimaryWeapon( weapon ) && !isDefined( self.hitsThisMag[ weapon ] ) ) - self.hitsThisMag[ weapon ] = weaponClipSize( weapon ); - - self.bothBarrels = undefined; - - if ( isSubStr( weapon, "ranger" ) ) - self thread watchRangerUsage( weapon ); - - while(1) - { - self waittill( "weapon_change", newWeapon ); - - tokedNewWeapon = StrTok( newWeapon, "_" ); - - self.bothBarrels = undefined; - - if ( isSubStr( newWeapon, "ranger" ) ) - self thread watchRangerUsage( newWeapon ); - - if ( tokedNewWeapon[0] == "gl" || ( tokedNewWeapon.size > 2 && tokedNewWeapon[2] == "attach" ) ) - newWeapon = self getCurrentPrimaryWeapon(); - - if ( newWeapon != "none" ) - { - if ( isCACPrimaryWeapon( newWeapon ) && !isDefined( self.hitsThisMag[ newWeapon ] ) ) - self.hitsThisMag[ newWeapon ] = weaponClipSize( newWeapon ); - } - self.changingWeapon = undefined; - if ( mayDropWeapon( newWeapon ) ) - self.lastDroppableWeapon = newWeapon; - } -} - - -watchStartWeaponChange() -{ - self endon("death"); - self endon("disconnect"); - self.changingWeapon = undefined; - - while(1) - { - self waittill( "weapon_switch_started", newWeapon ); - self.changingWeapon = newWeapon; - } -} - -watchWeaponReload() -{ - self endon("death"); - self endon("disconnect"); - - for ( ;; ) - { - self waittill( "reload" ); - - weaponName = self getCurrentWeapon(); - - self.bothBarrels = undefined; - - if ( !isSubStr( weaponName, "ranger" ) ) - continue; - - self thread watchRangerUsage( weaponName ); - } -} - - -watchRangerUsage( rangerName ) -{ - rightAmmo = self getWeaponAmmoClip( rangerName, "right" ); - leftAmmo = self getWeaponAmmoClip( rangerName, "left" ); - - self endon ( "reload" ); - self endon ( "weapon_change" ); - - for ( ;; ) - { - self waittill ( "weapon_fired", weaponName ); - - if ( weaponName != rangerName ) - continue; - - self.bothBarrels = undefined; - - if ( isSubStr( rangerName, "akimbo" ) ) - { - newLeftAmmo = self getWeaponAmmoClip( rangerName, "left" ); - newRightAmmo = self getWeaponAmmoClip( rangerName, "right" ); - - if ( leftAmmo != newLeftAmmo && rightAmmo != newRightAmmo ) - self.bothBarrels = true; - - if ( !newLeftAmmo || !newRightAmmo ) - return; - - - leftAmmo = newLeftAmmo; - rightAmmo = newRightAmmo; - } - else if ( rightAmmo == 2 && !self getWeaponAmmoClip( rangerName, "right" ) ) - { - self.bothBarrels = true; - return; - } - } -} - - -isHackWeapon( weapon ) -{ - if ( weapon == "radar_mp" || weapon == "airstrike_mp" || weapon == "helicopter_mp" ) - return true; - if ( weapon == "briefcase_bomb_mp" ) - return true; - return false; -} - - -mayDropWeapon( weapon ) -{ - if ( weapon == "none" ) - return false; - - if ( isSubStr( weapon, "ac130" ) ) - return false; - - invType = WeaponInventoryType( weapon ); - if ( invType != "primary" ) - return false; - - return true; -} - -dropWeaponForDeath( attacker ) -{ - if( !level.allowDropWeaponOnDeath ) - return; - - weapon = self.lastDroppableWeapon; - - if ( isdefined( self.droppedDeathWeapon ) ) - return; - - if ( level.inGracePeriod ) - return; - - if ( !isdefined( weapon ) ) - { - /# - if ( getdvar("scr_dropdebug") == "1" ) - println( "didn't drop weapon: not defined" ); - #/ - return; - } - - if ( weapon == "none" ) - { - /# - if ( getdvar("scr_dropdebug") == "1" ) - println( "didn't drop weapon: weapon == none" ); - #/ - return; - } - - if ( !self hasWeapon( weapon ) ) - { - /# - if ( getdvar("scr_dropdebug") == "1" ) - println( "didn't drop weapon: don't have it anymore (" + weapon + ")" ); - #/ - return; - } - - if ( weapon != "riotshield_mp" ) - { - if ( !(self AnyAmmoForWeaponModes( weapon )) ) - { - /# - if ( getdvar("scr_dropdebug") == "1" ) - println( "didn't drop weapon: no ammo for weapon modes" ); - #/ - return; - } - - clipAmmoR = self GetWeaponAmmoClip( weapon, "right" ); - clipAmmoL = self GetWeaponAmmoClip( weapon, "left" ); - if ( !clipAmmoR && !clipAmmoL ) - { - /# - if ( getdvar("scr_dropdebug") == "1" ) - println( "didn't drop weapon: no ammo in clip" ); - #/ - return; - } - - stockAmmo = self GetWeaponAmmoStock( weapon ); - stockMax = WeaponMaxAmmo( weapon ); - if ( stockAmmo > stockMax ) - stockAmmo = stockMax; - - item = self dropItem( weapon ); - item ItemWeaponSetAmmo( clipAmmoR, stockAmmo, clipAmmoL ); - } - else - { - item = self dropItem( weapon ); - if ( !isDefined( item ) ) - return; - item ItemWeaponSetAmmo( 1, 1, 0 ); - } - - /# - if ( getdvar("scr_dropdebug") == "1" ) - println( "dropped weapon: " + weapon ); - #/ - - self.droppedDeathWeapon = true; - - item.owner = self; - item.ownersattacker = attacker; - - item thread watchPickup(); - - item thread deletePickupAfterAWhile(); - - detach_model = getWeaponModel( weapon ); - - if ( !isDefined( detach_model ) ) - return; - - if( isDefined( self.tag_stowed_back ) && detach_model == self.tag_stowed_back ) - self detach_back_weapon(); - - if ( !isDefined( self.tag_stowed_hip ) ) - return; - - if( detach_model == self.tag_stowed_hip ) - self detach_hip_weapon(); -} - - -detachIfAttached( model, baseTag ) -{ - attachSize = self getAttachSize(); - - for ( i = 0; i < attachSize; i++ ) - { - attach = self getAttachModelName( i ); - - if ( attach != model ) - continue; - - tag = self getAttachTagName( i ); - self detach( model, tag ); - - if ( tag != baseTag ) - { - attachSize = self getAttachSize(); - - for ( i = 0; i < attachSize; i++ ) - { - tag = self getAttachTagName( i ); - - if ( tag != baseTag ) - continue; - - model = self getAttachModelName( i ); - self detach( model, tag ); - - break; - } - } - return true; - } - return false; -} - - -deletePickupAfterAWhile() -{ - self endon("death"); - - wait 60; - - if ( !isDefined( self ) ) - return; - - self delete(); -} - -getItemWeaponName() -{ - classname = self.classname; - assert( getsubstr( classname, 0, 7 ) == "weapon_" ); - weapname = getsubstr( classname, 7 ); - return weapname; -} - -watchPickup() -{ - self endon("death"); - - weapname = self getItemWeaponName(); - - while(1) - { - self waittill( "trigger", player, droppedItem ); - - if ( isdefined( droppedItem ) ) - break; - // otherwise, player merely acquired ammo and didn't pick this up - } - - /# - if ( getdvar("scr_dropdebug") == "1" ) - println( "picked up weapon: " + weapname + ", " + isdefined( self.ownersattacker ) ); - #/ - - assert( isdefined( player.tookWeaponFrom ) ); - - // make sure the owner information on the dropped item is preserved - droppedWeaponName = droppedItem getItemWeaponName(); - if ( isdefined( player.tookWeaponFrom[ droppedWeaponName ] ) ) - { - droppedItem.owner = player.tookWeaponFrom[ droppedWeaponName ]; - droppedItem.ownersattacker = player; - player.tookWeaponFrom[ droppedWeaponName ] = undefined; - } - droppedItem thread watchPickup(); - - // take owner information from self and put it onto player - if ( isdefined( self.ownersattacker ) && self.ownersattacker == player ) - { - player.tookWeaponFrom[ weapname ] = self.owner; - } - else - { - player.tookWeaponFrom[ weapname ] = undefined; - } -} - -itemRemoveAmmoFromAltModes() -{ - origweapname = self getItemWeaponName(); - - curweapname = weaponAltWeaponName( origweapname ); - - altindex = 1; - while ( curweapname != "none" && curweapname != origweapname ) - { - self itemWeaponSetAmmo( 0, 0, 0, altindex ); - curweapname = weaponAltWeaponName( curweapname ); - altindex++; - } -} - - -handleScavengerBagPickup( scrPlayer ) -{ - self endon( "death" ); - level endon ( "game_ended" ); - - assert( isDefined( scrPlayer ) ); - - // Wait for the pickup to happen - self waittill( "scavenger", destPlayer ); - assert( isDefined ( destPlayer ) ); - - destPlayer notify( "scavenger_pickup" ); - destPlayer playLocalSound( "scavenger_pack_pickup" ); - - offhandWeapons = destPlayer getWeaponsListOffhands(); - - if ( destPlayer _hasPerk( "specialty_tacticalinsertion" ) && destPlayer getAmmoCount( "flare_mp" ) < 1 ) - destPlayer _setPerk( "specialty_tacticalinsertion"); - - foreach ( offhand in offhandWeapons ) - { - currentClipAmmo = destPlayer GetWeaponAmmoClip( offhand ); - destPlayer SetWeaponAmmoClip( offhand, currentClipAmmo + 1); - } - - primaryWeapons = destPlayer getWeaponsListPrimaries(); - foreach ( primary in primaryWeapons ) - { - if ( !isCACPrimaryWeapon( primary ) && !level.scavenger_secondary ) - continue; - - currentStockAmmo = destPlayer GetWeaponAmmoStock( primary ); - addStockAmmo = weaponClipSize( primary ); - - destPlayer setWeaponAmmoStock( primary, currentStockAmmo + addStockAmmo ); - - altWeapon = weaponAltWeaponName( primary ); - - if ( !isDefined( altWeapon ) || (altWeapon == "none") || !level.scavenger_altmode ) - continue; - - currentStockAmmo = destPlayer GetWeaponAmmoStock( altWeapon ); - addStockAmmo = weaponClipSize( altWeapon ); - - destPlayer setWeaponAmmoStock( altWeapon, currentStockAmmo + addStockAmmo ); - } - - destPlayer maps\mp\gametypes\_damagefeedback::updateDamageFeedback( "scavenger" ); -} - - -dropScavengerForDeath( attacker ) -{ - if ( level.inGracePeriod ) - return; - - if( !isDefined( attacker ) ) - return; - - if( attacker == self ) - return; - - dropBag = self dropScavengerBag( "scavenger_bag_mp" ); - dropBag thread handleScavengerBagPickup( self ); - -} - -getWeaponBasedGrenadeCount(weapon) -{ - return 2; -} - -getWeaponBasedSmokeGrenadeCount(weapon) -{ - return 1; -} - -getFragGrenadeCount() -{ - grenadetype = "frag_grenade_mp"; - - count = self getammocount(grenadetype); - return count; -} - -getSmokeGrenadeCount() -{ - grenadetype = "smoke_grenade_mp"; - - count = self getammocount(grenadetype); - return count; -} - - -watchWeaponUsage( weaponHand ) -{ - self endon( "death" ); - self endon( "disconnect" ); - level endon ( "game_ended" ); - - for ( ;; ) - { - self waittill ( "weapon_fired", weaponName ); - - self.hasDoneCombat = true; - - if ( !maps\mp\gametypes\_weapons::isPrimaryWeapon( weaponName ) && !maps\mp\gametypes\_weapons::isSideArm( weaponName ) ) - continue; - - if ( isDefined( self.hitsThisMag[ weaponName ] ) ) - self thread updateMagShots( weaponName ); - - totalShots = self maps\mp\gametypes\_persistence::statGetBuffered( "totalShots" ) + 1; - hits = self maps\mp\gametypes\_persistence::statGetBuffered( "hits" ); - self maps\mp\gametypes\_persistence::statSetBuffered( "totalShots", totalShots ); - self maps\mp\gametypes\_persistence::statSetBuffered( "accuracy", int(hits * 10000 / totalShots) ); - self maps\mp\gametypes\_persistence::statSetBuffered( "misses", int(totalShots - hits) ); - } -} - - -updateMagShots( weaponName ) -{ - self endon ( "death" ); - self endon ( "disconnect" ); - self endon ( "updateMagShots_" + weaponName ); - - self.hitsThisMag[ weaponName ]--; - - wait ( 0.05 ); - - self.hitsThisMag[ weaponName ] = weaponClipSize( weaponName ); -} - - -checkHitsThisMag( weaponName ) -{ - self endon ( "death" ); - self endon ( "disconnect" ); - - self notify ( "updateMagShots_" + weaponName ); - waittillframeend; - - if ( self.hitsThisMag[ weaponName ] == 0 ) - { - weaponClass = getWeaponClass( weaponName ); - - maps\mp\gametypes\_missions::genericChallenge( weaponClass ); - - self.hitsThisMag[ weaponName ] = weaponClipSize( weaponName ); - } -} - - -checkHit( weaponName, victim ) -{ - if ( !maps\mp\gametypes\_weapons::isPrimaryWeapon( weaponName ) && !maps\mp\gametypes\_weapons::isSideArm( weaponName ) ) - return; - - // sometimes the "weapon_fired" notify happens after we hit the guy... - waittillframeend; - - if ( isDefined( self.hitsThisMag[ weaponName ] ) ) - self thread checkHitsThisMag( weaponName ); - - if ( !isDefined( self.lastHitTime[ weaponName ] ) ) - self.lastHitTime[ weaponName ] = 0; - - // already hit with this weapon on this frame - if ( self.lastHitTime[ weaponName ] == getTime() ) - return; - - self.lastHitTime[ weaponName ] = getTime(); - - totalShots = self maps\mp\gametypes\_persistence::statGetBuffered( "totalShots" ); - hits = self maps\mp\gametypes\_persistence::statGetBuffered( "hits" ) + 1; - - if ( hits <= totalShots ) - { - self maps\mp\gametypes\_persistence::statSetBuffered( "hits", hits ); - self maps\mp\gametypes\_persistence::statSetBuffered( "misses", int(totalShots - hits) ); - self maps\mp\gametypes\_persistence::statSetBuffered( "accuracy", int(hits * 10000 / totalShots) ); - } -} - - -attackerCanDamageItem( attacker, itemOwner ) -{ - return friendlyFireCheck( itemOwner, attacker ); -} - -// returns true if damage should be done to the item given its owner and the attacker -friendlyFireCheck( owner, attacker, forcedFriendlyFireRule ) -{ - if ( !isdefined( owner ) )// owner has disconnected? allow it - return true; - - if ( !level.teamBased )// not a team based mode? allow it - return true; - - attackerTeam = attacker.team; - - friendlyFireRule = level.friendlyfire; - if ( isdefined( forcedFriendlyFireRule ) ) - friendlyFireRule = forcedFriendlyFireRule; - - if ( friendlyFireRule != 0 )// friendly fire is on? allow it - return true; - - if ( attacker == owner )// owner may attack his own items - return true; - - if ( !isdefined( attackerTeam ) )// attacker not on a team? allow it - return true; - - if ( attackerTeam != owner.team )// attacker not on the same team as the owner? allow it - return true; - - return false;// disallow it -} - -watchGrenadeUsage() -{ - self endon( "death" ); - self endon( "disconnect" ); - - self.throwingGrenade = undefined; - self.gotPullbackNotify = false; - - if ( getIntProperty( "scr_deleteexplosivesonspawn", 1 ) == 1 ) - { - // delete c4 from previous spawn - if ( isdefined( self.c4array ) ) - { - for ( i = 0; i < self.c4array.size; i++ ) - { - if ( isdefined( self.c4array[ i ] ) ) - self.c4array[ i ] delete(); - } - } - self.c4array = []; - // delete claymores from previous spawn - if ( isdefined( self.claymorearray ) ) - { - for ( i = 0; i < self.claymorearray.size; i++ ) - { - if ( isdefined( self.claymorearray[ i ] ) ) - self.claymorearray[ i ] delete(); - } - } - self.claymorearray = []; - } - else - { - if ( !isdefined( self.c4array ) ) - self.c4array = []; - if ( !isdefined( self.claymorearray ) ) - self.claymorearray = []; - } - - thread watchC4(); - thread watchC4Detonation(); - thread watchC4AltDetonation(); - thread watchClaymores(); - thread deleteC4AndClaymoresOnDisconnect(); - - self thread watchForThrowbacks(); - - for ( ;; ) - { - self waittill( "grenade_pullback", weaponName ); - - self.hasDoneCombat = true; - - if ( weaponName == "claymore_mp" ) - continue; - - self.throwingGrenade = weaponName; - self.gotPullbackNotify = true; - - if ( weaponName == "c4_mp" ) - self beginC4Tracking(); - else - self beginGrenadeTracking(); - - self.throwingGrenade = undefined; - } -} - -deleteOnOwnerTeamChange( owner ) -{ - self endon( "delete_on_team_overlap" ); - - self endon( "death" ); - - owner waittill_any( "disconnect", "joined_team", "joined_spectators" ); - - self delete(); -} - -beginGrenadeTracking() -{ - self endon( "death" ); - self endon( "disconnect" ); - self endon( "offhand_end" ); - self endon( "weapon_change" ); - - startTime = getTime(); - - self waittill( "grenade_fire", grenade, weaponName ); - - if ( ( getTime() - startTime > 1000 ) && weaponName == "frag_grenade_mp" ) - grenade.isCooked = true; - - self.changingWeapon = undefined; - - grenade.owner = self; - - switch( weaponName ) - { - case "frag_grenade_mp": - case "semtex_mp": - grenade thread maps\mp\gametypes\_shellshock::grenade_earthQuake(); - grenade.originalOwner = self; - - if ( level.deleteNadeOnTeamChange ) - grenade thread deleteOnOwnerTeamChange( self ); - - if( level.extraTeamIcons ) - grenade thread setClaymoreTeamHeadIcon( self.pers[ "team" ] ); - break; - case "flash_grenade_mp": - case "concussion_grenade_mp": - grenade thread empExplodeWaiter(); - - if ( level.deleteNadeOnTeamChange ) - grenade thread deleteOnOwnerTeamChange( self ); - - if( level.extraTeamIcons ) - grenade thread setClaymoreTeamHeadIcon( self.pers[ "team" ] ); - break; - case "smoke_grenade_mp": - if( level.extraTeamIcons ) - grenade thread setClaymoreTeamHeadIcon( self.pers[ "team" ] ); - break; - case "throwingknife_mp": - if ( level.deleteNadeOnTeamChange ) - grenade thread deleteOnOwnerTeamChange( self ); - - if( level.extraTeamIcons ) - grenade thread setClaymoreTeamHeadIcon( self.pers[ "team" ] ); - break; - } -} - -AddMissileToSightTraces( team ) -{ - self.team = team; - level.missilesForSightTraces[ level.missilesForSightTraces.size ] = self; - - self waittill( "death" ); - - newArray = []; - foreach( missile in level.missilesForSightTraces ) - { - if ( missile != self ) - newArray[ newArray.size ] = missile; - } - level.missilesForSightTraces = newArray; -} - -watchMissileUsage() -{ - self endon( "death" ); - self endon( "disconnect" ); - - for ( ;; ) - { - self waittill( "missile_fire", missile, weaponName ); - - if ( isSubStr( weaponName, "gl_" ) ) - { - missile.primaryWeapon = self getCurrentPrimaryWeapon(); - missile thread maps\mp\gametypes\_shellshock::grenade_earthQuake(); - } - - switch ( weaponName ) - { - case "at4_mp": - case "stinger_mp": - level notify ( "stinger_fired", self, missile, self.stingerTarget ); - self thread setAltSceneObj( missile, "tag_origin", 65 ); - break; - case "javelin_mp": - level notify ( "stinger_fired", self, missile, self.javelinTarget ); - self thread setAltSceneObj( missile, "tag_origin", 65 ); - break; - default: - break; - } - - switch ( weaponName ) - { - case "at4_mp": - case "javelin_mp": - case "rpg_mp": - case "ac130_105mm_mp": - case "ac130_40mm_mp": - case "remotemissile_projectile_mp": - missile thread maps\mp\gametypes\_shellshock::grenade_earthQuake(); - default: - break; - } - if( level.extraTeamIcons /*&& weaponName != "remotemissile_projectile_mp"*/ ) - missile thread setClaymoreTeamHeadIcon( self.pers[ "team" ] ); - if ( level.deleteNadeOnTeamChange ) - missile thread deleteOnOwnerTeamChange( self ); - } -} - - -watchSentryUsage() -{ - self endon( "death" ); - self endon( "disconnect" ); - - for ( ;; ) - { - self waittill( "sentry_placement_finished", sentry ); - - self thread setAltSceneObj( sentry, "tag_flash", 65 ); - } -} - - -empExplodeWaiter() -{ - self thread maps\mp\gametypes\_shellshock::endOnDeath(); - self endon( "end_explode" ); - - self waittill( "explode", position ); - - ents = getEMPDamageEnts( position, 512, false ); - - foreach ( ent in ents ) - { - if ( isDefined( ent.owner ) && !friendlyFireCheck( self.owner, ent.owner ) ) - continue; - - ent notify( "emp_damage", self.owner, 8.0 ); - } -} - - -beginC4Tracking() -{ - self endon( "death" ); - self endon( "disconnect" ); - - self waittill_any( "grenade_fire", "weapon_change", "offhand_end" ); -} - - -watchForThrowbacks() -{ - self endon( "death" ); - self endon( "disconnect" ); - - for ( ;; ) - { - self waittill( "grenade_fire", grenade, weapname ); - - if ( self.gotPullbackNotify ) - { - self.gotPullbackNotify = false; - continue; - } - if ( !isSubStr( weapname, "frag_" ) && !isSubStr( weapname, "semtex_" ) ) - continue; - - // no grenade_pullback notify! we must have picked it up off the ground. - grenade.threwBack = true; - self thread incPlayerStat( "throwbacks", 1 ); - - grenade thread maps\mp\gametypes\_shellshock::grenade_earthQuake(); - grenade.originalOwner = self; - - if( level.extraTeamIcons ) - grenade thread setClaymoreTeamHeadIcon( self.pers[ "team" ] ); - if ( level.deleteNadeOnTeamChange ) - { - grenade notify( "delete_on_team_overlap" ); - grenade thread deleteOnOwnerTeamChange( self ); - } - } -} - - -watchC4() -{ - self endon( "spawned_player" ); - self endon( "disconnect" ); - - //maxc4 = 2; - - while ( 1 ) - { - self waittill( "grenade_fire", c4, weapname ); - if ( weapname == "c4" || weapname == "c4_mp" ) - { - if ( !self.c4array.size ) - self thread watchC4AltDetonate(); - - if ( self.c4array.size ) - { - self.c4array = array_removeUndefined( self.c4array ); - - if( self.c4array.size >= level.maxPerPlayerExplosives ) - { - self.c4array[0] detonate(); - } - } - - self.c4array[ self.c4array.size ] = c4; - c4.owner = self; - c4.team = self.team; - c4.activated = false; - c4.weaponName = weapname; - - c4 thread maps\mp\gametypes\_shellshock::c4_earthQuake(); - c4 thread c4Activate(); - c4 thread c4Damage(); - c4 thread c4EMPDamage(); - c4 thread c4EMPKillstreakWait(); - if( level.extraTeamIcons ) - c4 thread setClaymoreTeamHeadIcon( self.pers[ "team" ] ); - //c4 thread c4DetectionTrigger( self.pers[ "team" ] ); - c4 thread c4WatchPickup(); - if ( level.deleteNadeOnTeamChange ) - c4 thread deleteOnOwnerTeamChange( self ); - } - } -} - - -c4EMPDamage() -{ - self endon( "death" ); - - for ( ;; ) - { - self waittill( "emp_damage", attacker, duration ); - - if ( isPlayer(attacker) && !friendlyFireCheck( self.owner, attacker ) ) - continue; - - playfxOnTag( getfx( "sentry_explode_mp" ), self, "tag_origin" ); - - self.disabled = true; - self notify( "disabled" ); - - wait( duration ); - - self.disabled = undefined; - self notify( "enabled" ); - } -} - - -c4EMPKillstreakWait() -{ - self endon( "death" ); - - for ( ;; ) - { - level waittill( "emp_update" ); - - if ( (level.teamBased && level.teamEMPed[self.team]) || (!level.teamBased && isDefined( level.empPlayer ) && level.empPlayer != self.owner ) ) - { - self.disabled = true; - self notify( "disabled" ); - } - else - { - self.disabled = undefined; - self notify( "enabled" ); - } - } -} - -deleteTeamHeadIconOnUndefined(ent, hud) -{ - ent endon( "death" ); - - while ( isDefined(ent) ) - wait 0.05; - - hud destroy(); - hud = undefined; - ent notify( "kill_entity_headicon_thread" ); -} - -setClaymoreTeamHeadIcon( team ) -{ - self endon( "death" ); - - if ( self.weaponname == "claymore_mp" && !level.allowExtendedClaymoreTrace ) - { - self waittill( "missile_stuck" ); - self waittill( "claymore_trace_fixed" ); - } - else - wait 0.05; - - if ( isDefined( self.entityHeadIcon ) ) - { - self.entityHeadIconTeam = "none"; - self.entityHeadIcon destroy(); - self.entityHeadIcon = undefined; - self notify( "kill_entity_headicon_thread" ); - } - - if ( level.teamBased ) - self maps\mp\_entityheadicons::setTeamHeadIcon( team, ( 0, 0, 20 ) ); - else if ( isDefined( self.owner ) ) - self maps\mp\_entityheadicons::setPlayerHeadIcon( self.owner, (0,0,20) ); - - thread deleteTeamHeadIconOnUndefined(self, self.entityHeadIcon); -} - - -watchClaymores() -{ - self endon( "spawned_player" ); - self endon( "disconnect" ); - - while ( 1 ) - { - self waittill( "grenade_fire", claymore, weapname ); - if ( weapname == "claymore" || weapname == "claymore_mp" ) - { - self.claymorearray = array_removeUndefined( self.claymorearray ); - - if( self.claymoreArray.size >= level.maxPerPlayerExplosives ) - self.claymoreArray[0] detonate(); - - self.claymorearray[ self.claymorearray.size ] = claymore; - claymore.owner = self; - claymore.team = self.team; - claymore.weaponName = weapname; - - claymore thread c4Damage(); - claymore thread c4EMPDamage(); - claymore thread c4EMPKillstreakWait(); - claymore thread claymoreDetonation(); - //claymore thread claymoreDetectionTrigger_wait( self.pers[ "team" ] ); - claymore thread setClaymoreTeamHeadIcon( self.pers[ "team" ] ); - claymore thread c4WatchPickup(); - claymore thread claymoreWatchTrace(); - if ( level.deleteNadeOnTeamChange ) - claymore thread deleteOnOwnerTeamChange( self ); - /# - if ( getdvarint( "scr_claymoredebug" ) ) - { - claymore thread claymoreDebug(); - } - #/ - } - } -} - -claymoreWatchTrace() -{ - if( level.allowExtendedClaymoreTrace ) - return; - - self endon( "death" ); - - // need to see if this is being placed far away from the player and not let it do that - // this will fix a legacy bug where you can stand on a ledge and plant a claymore down on the ground far below you - self Hide(); - - self waittill( "missile_stuck" ); - wait 0.05;//wait for threads - - distanceZ = 40; - - if( distanceZ * distanceZ < DistanceSquared( self.origin, self.owner.origin ) ) - { - secTrace = bulletTrace( self.owner.origin, self.owner.origin - (0, 0, distanceZ), false, self ); - - if( secTrace["fraction"] == 1 ) - { - self.owner SetWeaponAmmoStock( self.weaponname, self.owner GetWeaponAmmoStock( self.weaponname ) + 1 ); - self delete(); - return; - } - self.origin = secTrace["position"]; - } - self Show(); - self notify( "claymore_trace_fixed" ); -} - -_notUsableForJoiningPlayers( owner ) -{ - self endon ( "death" ); - level endon ( "game_ended" ); - owner endon ( "disconnect" ); - - // as players join they need to be set to not be able to use this - while( true ) - { - level waittill( "player_spawned", player ); - if( IsDefined( player ) && player != owner ) - { - self disablePlayerUse( player ); - } - } -} - -c4WatchPickup() -{ - if( !level.allowPickUpEquipment ) - return; - - self endon( "death" ); - - self waittill( "missile_stuck" ); - if( !level.allowExtendedClaymoreTrace && self.weaponname == "claymore_mp" ) - self waittill( "claymore_trace_fixed" ); - - trigger = spawn( "script_origin", self.origin ); - self thread deleteOnDeath( trigger ); - - trigger setCursorHint( "HINT_NOICON" ); - - if ( self.weaponname == "c4_mp" ) - trigger setHintString( &"MP_PICKUP_C4" ); - else if (self.weaponname == "claymore_mp" ) - trigger setHintString( &"MP_PICKUP_CLAYMORE" ); - - trigger setSelfUsable( self.owner ); - trigger thread _notUsableForJoiningPlayers( self ); - - for ( ;; ) - { - trigger waittillmatch( "trigger", self.owner ); - usePressTime = getTime(); - while( self.owner UseButtonPressed() && (getTime() - usePressTime) < 500 ) - wait .05; - - if( self.owner UseButtonPressed() ) - { - self.owner playLocalSound( "scavenger_pack_pickup" ); - self.owner SetWeaponAmmoStock( self.weaponname, self.owner GetWeaponAmmoStock( self.weaponname ) + 1 ); - - self delete(); - } - } -} - - /# -claymoreDebug() -{ - self waittill( "missile_stuck" ); - self thread showCone( acos( level.claymoreDetectionDot ), level.claymoreDetonateRadius, ( 1, .85, 0 ) ); - self thread showCone( 60, 256, ( 1, 0, 0 ) ); -} - -vectorcross( v1, v2 ) -{ - return( v1[ 1 ] * v2[ 2 ] - v1[ 2 ] * v2[ 1 ], v1[ 2 ] * v2[ 0 ] - v1[ 0 ] * v2[ 2 ], v1[ 0 ] * v2[ 1 ] - v1[ 1 ] * v2[ 0 ] ); -} - -showCone( angle, range, color ) -{ - self endon( "death" ); - - start = self.origin; - forward = anglestoforward( self.angles ); - right = vectorcross( forward, ( 0, 0, 1 ) ); - up = vectorcross( forward, right ); - - fullforward = forward * range * cos( angle ); - sideamnt = range * sin( angle ); - - while ( 1 ) - { - prevpoint = ( 0, 0, 0 ); - for ( i = 0; i <= 20; i++ ) - { - coneangle = i / 20.0 * 360; - point = start + fullforward + sideamnt * ( right * cos( coneangle ) + up * sin( coneangle ) ); - if ( i > 0 ) - { - line( start, point, color ); - line( prevpoint, point, color ); - } - prevpoint = point; - } - wait .05; - } -} -#/ - -claymoreDetonation() -{ - self endon( "death" ); - - self waittill( "missile_stuck" ); - - if( !level.allowExtendedClaymoreTrace ) - self waittill( "claymore_trace_fixed" ); - - damagearea = spawn( "trigger_radius", self.origin + ( 0, 0, 0 - level.claymoreDetonateRadius ), 0, level.claymoreDetonateRadius, level.claymoreDetonateRadius * 2 ); - self thread deleteOnDeath( damagearea ); - - while ( 1 ) - { - damagearea waittill( "trigger", player ); - - if ( getdvarint( "scr_claymoredebug" ) != 1 ) - { - if ( isdefined( self.owner ) && player == self.owner ) - continue; - if ( !friendlyFireCheck( self.owner, player, 0 ) ) - continue; - } - if ( lengthsquared( player getVelocity() ) < 10 ) - continue; - - if ( abs( player.origin[2] - self.origin[2] ) > 128 ) - continue; - - if ( !player shouldAffectClaymore( self ) ) - continue; - - if ( player damageConeTrace( self.origin, self ) > 0 ) - break; - } - - self playsound ("claymore_activated"); - - - if ( player _hasPerk( "specialty_delaymine" ) ) - wait 3.0; - else - wait level.claymoreDetectionGracePeriod; - - self detonate(); -} - -shouldAffectClaymore( claymore ) -{ - if ( isDefined( claymore.disabled ) ) - return false; - - pos = self.origin + ( 0, 0, 32 ); - - dirToPos = pos - claymore.origin; - claymoreForward = anglesToForward( claymore.angles ); - - dist = vectorDot( dirToPos, claymoreForward ); - if ( dist < level.claymoreDetectionMinDist ) - return false; - - dirToPos = vectornormalize( dirToPos ); - - dot = vectorDot( dirToPos, claymoreForward ); - return( dot > level.claymoreDetectionDot ); -} - -deleteOnDeath( ent ) -{ - self waittill( "death" ); - wait .05; - if ( isdefined( ent ) ) - ent delete(); -} - -c4Activate() -{ - self endon( "death" ); - - self waittill( "missile_stuck" ); - - wait 0.05; - - self notify( "activated" ); - self.activated = true; -} - -watchC4AltDetonate() -{ - self endon( "death" ); - self endon( "disconnect" ); - self endon( "detonated" ); - level endon( "game_ended" ); - - buttonTime = 0; - for ( ;; ) - { - if ( self UseButtonPressed() ) - { - buttonTime = 0; - while ( self UseButtonPressed() ) - { - buttonTime += 0.05; - wait( 0.05 ); - } - - println( "pressTime1: " + buttonTime ); - if ( buttonTime >= 0.5 ) - continue; - - buttonTime = 0; - while ( !self UseButtonPressed() && buttonTime < 0.5 ) - { - buttonTime += 0.05; - wait( 0.05 ); - } - - println( "delayTime: " + buttonTime ); - if ( buttonTime >= 0.5 ) - continue; - - if ( !self.c4Array.size ) - return; - - self notify( "alt_detonate" ); - } - wait( 0.05 ); - } -} - -watchC4Detonation() -{ - self endon( "death" ); - self endon( "disconnect" ); - - while ( 1 ) - { - self waittillmatch( "detonate", "c4_mp" ); - newarray = []; - for ( i = 0; i < self.c4array.size; i++ ) - { - c4 = self.c4array[ i ]; - if ( isdefined( self.c4array[ i ] ) ) - c4 thread waitAndDetonate( 0.1 ); - } - self.c4array = newarray; - self notify( "detonated" ); - } -} - - -watchC4AltDetonation() -{ - self endon( "death" ); - self endon( "disconnect" ); - - while ( 1 ) - { - self waittill( "alt_detonate" ); - weap = self getCurrentWeapon(); - if ( weap != "c4_mp" ) - { - newarray = []; - for ( i = 0; i < self.c4array.size; i++ ) - { - c4 = self.c4array[ i ]; - if ( isdefined( self.c4array[ i ] ) ) - c4 thread waitAndDetonate( 0.1 ); - } - self.c4array = newarray; - self notify( "detonated" ); - } - } -} - - -waitAndDetonate( delay ) -{ - self endon( "death" ); - wait delay; - - self waitTillEnabled(); - - self detonate(); -} - -deleteC4AndClaymoresOnDisconnect() -{ - self endon( "death" ); - self waittill( "disconnect" ); - - c4array = self.c4array; - claymorearray = self.claymorearray; - - wait .05; - - for ( i = 0; i < c4array.size; i++ ) - { - if ( isdefined( c4array[ i ] ) ) - c4array[ i ] delete(); - } - for ( i = 0; i < claymorearray.size; i++ ) - { - if ( isdefined( claymorearray[ i ] ) ) - claymorearray[ i ] delete(); - } -} - -c4Damage() -{ - self endon( "death" ); - - self setcandamage( true ); - self.maxhealth = 100000; - self.health = self.maxhealth; - - attacker = undefined; - - while ( 1 ) - { - self waittill( "damage", damage, attacker, direction_vec, point, type, modelName, tagName, partName, iDFlags, weapon ); - if ( !isPlayer( attacker ) ) - continue; - - // don't allow people to destroy C4 on their team if FF is off - if ( !friendlyFireCheck( self.owner, attacker ) ) - continue; - - - if( isDefined( weapon ) ) - { - switch( weapon ) - { - case "concussion_grenade_mp": - case "flash_grenade_mp": - case "smoke_grenade_mp": - continue; - } - } - else - { - if( damage < 5 ) - continue; - } - - break; - } - - if ( level.c4explodethisframe ) - wait .1 + randomfloat( .4 ); - else - wait .05; - - if ( !isdefined( self ) ) - return; - - level.c4explodethisframe = true; - - thread resetC4ExplodeThisFrame(); - - if ( isDefined( type ) && ( isSubStr( type, "MOD_GRENADE" ) || isSubStr( type, "MOD_EXPLOSIVE" ) ) ) - self.wasChained = true; - - if ( isDefined( iDFlags ) && ( iDFlags & level.iDFLAGS_PENETRATION ) ) - self.wasDamagedFromBulletPenetration = true; - - self.wasDamaged = true; - - if( isPlayer( attacker ) ) - { - if( isDefined( level.extraDamageFeedback ) && level.extraDamageFeedback ) - attacker maps\mp\gametypes\_damagefeedback::updateDamageFeedback( "c4" ); - if( isDefined( level.allowPrintDamage ) && level.allowPrintDamage && attacker.printDamage ) - attacker iPrintLnBold( damage ); - } - - if ( level.teamBased ) - { - // "destroyed_explosive" notify, for challenges - if ( isdefined( attacker ) && isdefined( attacker.pers[ "team" ] ) && isdefined( self.owner ) && isdefined( self.owner.pers[ "team" ] ) ) - { - if ( attacker.pers[ "team" ] != self.owner.pers[ "team" ] ) - attacker notify( "destroyed_explosive" ); - } - } - else - { - // checking isDefined attacker is defensive but it's too late in the project to risk issues by not having it - if ( isDefined( self.owner ) && isDefined( attacker ) && attacker != self.owner ) - attacker notify( "destroyed_explosive" ); - } - - self detonate( attacker ); - // won't get here; got death notify. -} - -resetC4ExplodeThisFrame() -{ - wait .05; - level.c4explodethisframe = false; -} - -saydamaged( orig, amount ) -{ - for ( i = 0; i < 60; i++ ) - { - print3d( orig, "damaged! " + amount ); - wait .05; - } -} - -waitTillEnabled() -{ - if ( !isDefined( self.disabled ) ) - return; - - self waittill( "enabled" ); - assert( !isDefined( self.disabled ) ); -} - - -c4DetectionTrigger( ownerTeam ) -{ - self waittill( "activated" ); - - trigger = spawn( "trigger_radius", self.origin - ( 0, 0, 128 ), 0, 512, 256 ); - trigger.detectId = "trigger" + getTime() + randomInt( 1000000 ); - - trigger.owner = self; - trigger thread detectIconWaiter( level.otherTeam[ ownerTeam ] ); - - self waittill( "death" ); - trigger notify( "end_detection" ); - - if ( isDefined( trigger.bombSquadIcon ) ) - trigger.bombSquadIcon destroy(); - - trigger delete(); -} - - -claymoreDetectionTrigger_wait( ownerTeam ) -{ - self endon( "death" ); - self waittill( "missile_stuck" ); - - self thread claymoreDetectionTrigger( ownerTeam ); -} - -claymoreDetectionTrigger( ownerTeam ) -{ - trigger = spawn( "trigger_radius", self.origin - ( 0, 0, 128 ), 0, 512, 256 ); - trigger.detectId = "trigger" + getTime() + randomInt( 1000000 ); - - trigger.owner = self; - trigger thread detectIconWaiter( level.otherTeam[ ownerTeam ] ); - - self waittill( "death" ); - trigger notify( "end_detection" ); - - if ( isDefined( trigger.bombSquadIcon ) ) - trigger.bombSquadIcon destroy(); - - trigger delete(); -} - - -detectIconWaiter( detectTeam ) -{ - self endon( "end_detection" ); - level endon( "game_ended" ); - - while ( !level.gameEnded ) - { - self waittill( "trigger", player ); - - if ( !player.detectExplosives ) - continue; - - if ( level.teamBased && player.team != detectTeam ) - continue; - else if ( !level.teamBased && player == self.owner.owner ) - continue; - - if ( isDefined( player.bombSquadIds[ self.detectId ] ) ) - continue; - - player thread showHeadIcon( self ); - } -} - - -setupBombSquad() -{ - self.bombSquadIds = []; - - if ( self.detectExplosives && !self.bombSquadIcons.size ) - { - for ( index = 0; index < 4; index++ ) - { - self.bombSquadIcons[ index ] = newClientHudElem( self ); - self.bombSquadIcons[ index ].x = 0; - self.bombSquadIcons[ index ].y = 0; - self.bombSquadIcons[ index ].z = 0; - self.bombSquadIcons[ index ].alpha = 0; - self.bombSquadIcons[ index ].archived = true; - self.bombSquadIcons[ index ] setShader( "waypoint_bombsquad", 14, 14 ); - self.bombSquadIcons[ index ] setWaypoint( false, false ); - self.bombSquadIcons[ index ].detectId = ""; - } - } - else if ( !self.detectExplosives ) - { - for ( index = 0; index < self.bombSquadIcons.size; index++ ) - self.bombSquadIcons[ index ] destroy(); - - self.bombSquadIcons = []; - } -} - - -showHeadIcon( trigger ) -{ - triggerDetectId = trigger.detectId; - useId = -1; - for ( index = 0; index < 4; index++ ) - { - detectId = self.bombSquadIcons[ index ].detectId; - - if ( detectId == triggerDetectId ) - return; - - if ( detectId == "" ) - useId = index; - } - - if ( useId < 0 ) - return; - - self.bombSquadIds[ triggerDetectId ] = true; - - self.bombSquadIcons[ useId ].x = trigger.origin[ 0 ]; - self.bombSquadIcons[ useId ].y = trigger.origin[ 1 ]; - self.bombSquadIcons[ useId ].z = trigger.origin[ 2 ] + 24 + 128; - - self.bombSquadIcons[ useId ] fadeOverTime( 0.25 ); - self.bombSquadIcons[ useId ].alpha = 1; - self.bombSquadIcons[ useId ].detectId = trigger.detectId; - - while ( isAlive( self ) && isDefined( trigger ) && self isTouching( trigger ) ) - wait( 0.05 ); - - if ( !isDefined( self ) ) - return; - - self.bombSquadIcons[ useId ].detectId = ""; - self.bombSquadIcons[ useId ] fadeOverTime( 0.25 ); - self.bombSquadIcons[ useId ].alpha = 0; - self.bombSquadIds[ triggerDetectId ] = undefined; -} - - -// these functions are used with scripted weapons (like c4, claymores, artillery) -// returns an array of objects representing damageable entities (including players) within a given sphere. -// each object has the property damageCenter, which represents its center (the location from which it can be damaged). -// each object also has the property entity, which contains the entity that it represents. -// to damage it, call damageEnt() on it. -getDamageableEnts( pos, radius, doLOS, startRadius ) -{ - ents = []; - - if ( !isdefined( doLOS ) ) - doLOS = false; - - if ( !isdefined( startRadius ) ) - startRadius = 0; - - radiusSq = radius * radius; - - // players - players = level.players; - for ( i = 0; i < players.size; i++ ) - { - if ( !isalive( players[ i ] ) || players[ i ].sessionstate != "playing" ) - continue; - - playerpos = get_damageable_player_pos( players[ i ] ); - distSq = distanceSquared( pos, playerpos ); - if ( distSq < radiusSq && ( !doLOS || weaponDamageTracePassed( pos, playerpos, startRadius, players[ i ] ) ) ) - { - ents[ ents.size ] = get_damageable_player( players[ i ], playerpos ); - } - } - - // grenades - grenades = getentarray( "grenade", "classname" ); - for ( i = 0; i < grenades.size; i++ ) - { - entpos = get_damageable_grenade_pos( grenades[ i ] ); - distSq = distanceSquared( pos, entpos ); - if ( distSq < radiusSq && ( !doLOS || weaponDamageTracePassed( pos, entpos, startRadius, grenades[ i ] ) ) ) - { - ents[ ents.size ] = get_damageable_grenade( grenades[ i ], entpos ); - } - } - - destructibles = getentarray( "destructible", "targetname" ); - for ( i = 0; i < destructibles.size; i++ ) - { - entpos = destructibles[ i ].origin; - distSq = distanceSquared( pos, entpos ); - if ( distSq < radiusSq && ( !doLOS || weaponDamageTracePassed( pos, entpos, startRadius, destructibles[ i ] ) ) ) - { - newent = spawnstruct(); - newent.isPlayer = false; - newent.isADestructable = false; - newent.entity = destructibles[ i ]; - newent.damageCenter = entpos; - ents[ ents.size ] = newent; - } - } - - destructables = getentarray( "destructable", "targetname" ); - for ( i = 0; i < destructables.size; i++ ) - { - entpos = destructables[ i ].origin; - distSq = distanceSquared( pos, entpos ); - if ( distSq < radiusSq && ( !doLOS || weaponDamageTracePassed( pos, entpos, startRadius, destructables[ i ] ) ) ) - { - newent = spawnstruct(); - newent.isPlayer = false; - newent.isADestructable = true; - newent.entity = destructables[ i ]; - newent.damageCenter = entpos; - ents[ ents.size ] = newent; - } - } - - //sentries - sentries = getentarray( "misc_turret", "classname" ); - foreach ( sentry in sentries ) - { - entpos = sentry.origin + (0,0,32); - distSq = distanceSquared( pos, entpos ); - if ( distSq < radiusSq && ( !doLOS || weaponDamageTracePassed( pos, entpos, startRadius, sentry ) ) ) - { - if ( sentry.model == "sentry_minigun" ) - ents[ ents.size ] = get_damageable_sentry(sentry, entpos); - } - } - - return ents; -} - - -getEMPDamageEnts( pos, radius, doLOS, startRadius ) -{ - ents = []; - - if ( !isDefined( doLOS ) ) - doLOS = false; - - if ( !isDefined( startRadius ) ) - startRadius = 0; - - grenades = getEntArray( "grenade", "classname" ); - foreach ( grenade in grenades ) - { - //if ( !isDefined( grenade.weaponName ) ) - // continue; - - entpos = grenade.origin; - dist = distance( pos, entpos ); - if ( dist < radius && ( !doLOS || weaponDamageTracePassed( pos, entpos, startRadius, grenade ) ) ) - ents[ ents.size ] = grenade; - } - - turrets = getEntArray( "misc_turret", "classname" ); - foreach ( turret in turrets ) - { - //if ( !isDefined( turret.weaponName ) ) - // continue; - - entpos = turret.origin; - dist = distance( pos, entpos ); - if ( dist < radius && ( !doLOS || weaponDamageTracePassed( pos, entpos, startRadius, turret ) ) ) - ents[ ents.size ] = turret; - } - - return ents; -} - - -weaponDamageTracePassed( from, to, startRadius, ent ) -{ - midpos = undefined; - - diff = to - from; - if ( lengthsquared( diff ) < startRadius * startRadius ) - return true; - - dir = vectornormalize( diff ); - midpos = from + ( dir[ 0 ] * startRadius, dir[ 1 ] * startRadius, dir[ 2 ] * startRadius ); - - trace = bullettrace( midpos, to, false, ent ); - - if ( getdvarint( "scr_damage_debug" ) != 0 ) - { - thread debugprint( from, ".dmg" ); - if ( isdefined( ent ) ) - thread debugprint( to, "." + ent.classname ); - else - thread debugprint( to, ".undefined" ); - if ( trace[ "fraction" ] == 1 ) - { - thread debugline( midpos, to, ( 1, 1, 1 ) ); - } - else - { - thread debugline( midpos, trace[ "position" ], ( 1, .9, .8 ) ); - thread debugline( trace[ "position" ], to, ( 1, .4, .3 ) ); - } - } - - return( trace[ "fraction" ] == 1 ); -} - -// eInflictor = the entity that causes the damage (e.g. a claymore) -// eAttacker = the player that is attacking -// iDamage = the amount of damage to do -// sMeansOfDeath = string specifying the method of death (e.g. "MOD_PROJECTILE_SPLASH") -// sWeapon = string specifying the weapon used (e.g. "claymore_mp") -// damagepos = the position damage is coming from -// damagedir = the direction damage is moving in -damageEnt( eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, damagepos, damagedir ) -{ - if ( self.isPlayer ) - { - self.damageOrigin = damagepos; - self.entity thread [[ level.callbackPlayerDamage ]]( - eInflictor,// eInflictor The entity that causes the damage.( e.g. a turret ) - eAttacker,// eAttacker The entity that is attacking. - iDamage,// iDamage Integer specifying the amount of damage done - 0,// iDFlags Integer specifying flags that are to be applied to the damage - sMeansOfDeath,// sMeansOfDeath Integer specifying the method of death - sWeapon,// sWeapon The weapon number of the weapon used to inflict the damage - damagepos,// vPoint The point the damage is from? - damagedir,// vDir The direction of the damage - "none",// sHitLoc The location of the hit - 0// psOffsetTime The time offset for the damage - ); - } - else - { - // destructable walls and such can only be damaged in certain ways. - if ( self.isADestructable && ( sWeapon == "artillery_mp" || sWeapon == "claymore_mp" || sWeapon == "stealth_bomb_mp" ) ) - return; - - self.entity notify( "damage", iDamage, eAttacker, ( 0, 0, 0 ), ( 0, 0, 0 ), "MOD_EXPLOSIVE", "", "", "", undefined, sWeapon ); - } -} - - -debugline( a, b, color ) -{ - for ( i = 0; i < 30 * 20; i++ ) - { - line( a, b, color ); - wait .05; - } -} - -debugprint( pt, txt ) -{ - for ( i = 0; i < 30 * 20; i++ ) - { - print3d( pt, txt ); - wait .05; - } -} - - -onWeaponDamage( eInflictor, sWeapon, meansOfDeath, damage, eAttacker ) -{ - self endon( "death" ); - self endon( "disconnect" ); - - switch( sWeapon ) - { - case "concussion_grenade_mp": - // should match weapon settings in gdt - if ( !isDefined( eInflictor ) )//check to ensure inflictor wasnt destroyed. - return; - - if( meansOfDeath == "MOD_IMPACT" ) // do not cause stun effect if it was direct hit - return; - - radius = 512; - scale = 1 - ( distance( self.origin, eInflictor.origin ) / radius ); - - if ( scale < 0 ) - scale = 0; - - time = 2 + ( 4 * scale ); - - if ( isDefined( self.stunScaler ) ) - time = time * self.stunScaler; - - wait( 0.05 ); - eAttacker notify( "stun_hit" ); - self notify( "concussed", eAttacker ); - if( eAttacker != self ) - eAttacker maps\mp\gametypes\_missions::processChallenge( "ch_alittleconcussed" ); - self shellShock( "concussion_grenade_mp", time ); - self.concussionEndTime = getTime() + ( time * 1000 ); - if( IsDefined( eInflictor.owner ) && eInflictor.owner == eAttacker && isDefined( level.extraDamageFeedback ) && level.extraDamageFeedback ) - eAttacker thread maps\mp\gametypes\_damagefeedback::updateDamageFeedback( "stun" ); - break; - - case "weapon_cobra_mk19_mp": - // mk19 is too powerful with shellshock slowdown - break; - - default: - // shellshock will only be done if meansofdeath is an appropriate type and if there is enough damage. - maps\mp\gametypes\_shellshock::shellshockOnDamage( meansOfDeath, damage ); - break; - } - -} - -// weapon stowing logic =================================================================== - -// weapon class boolean helpers -isPrimaryWeapon( weapName ) -{ - if ( weapName == "none" ) - return false; - - if ( weaponInventoryType( weapName ) != "primary" ) - return false; - - switch ( weaponClass( weapName ) ) - { - case "rifle": - case "smg": - case "mg": - case "spread": - case "pistol": - case "rocketlauncher": - case "sniper": - return true; - - default: - return false; - } -} - - -isAltModeWeapon( weapName ) -{ - if ( weapName == "none" ) - return false; - - return ( weaponInventoryType( weapName ) == "altmode" ); -} - -isInventoryWeapon( weapName ) -{ - if ( weapName == "none" ) - return false; - - return ( weaponInventoryType( weapName ) == "item" ); -} - -isRiotShield( weapName ) -{ - if ( weapName == "none" ) - return false; - - return ( WeaponType( weapName ) == "riotshield" ); -} - -isOffhandWeapon( weapName ) -{ - if ( weapName == "none" ) - return false; - - return ( weaponInventoryType( weapName ) == "offhand" ); -} - -isSideArm( weapName ) -{ - if ( weapName == "none" ) - return false; - - if ( weaponInventoryType( weapName ) != "primary" ) - return false; - - return ( weaponClass( weapName ) == "pistol" ); -} - - -// This needs for than this.. this would qualify c4 as a grenade -isGrenade( weapName ) -{ - weapClass = weaponClass( weapName ); - weapType = weaponInventoryType( weapName ); - - if ( weapClass != "grenade" ) - return false; - - if ( weapType != "offhand" ) - return false; -} - - -getStowOffsetModel( weaponName ) -{ - assert( isDefined( level.stow_offset_array ) ); - - baseName = getBaseWeaponName( weaponName ); - - return( level.stow_offset_array[baseName] ); -} - - -stowPriorityWeapon() -{ - assert( isdefined( level.stow_priority_model_array ) ); - - // returns the first large projectil the player owns in case player owns more than one - foreach ( weapon_name, priority_weapon in level.stow_priority_model_array ) - { - weaponName = getBaseWeaponName( weapon_name ); - weaponList = self getWeaponsListAll(); - - foreach ( weapon in weaponList ) - { - if( self getCurrentWeapon() == weapon ) - continue; - - if ( weaponName == getBaseWeaponName( weapon ) ) - return weaponName + "_mp"; - } - } - - return ""; -} - -// thread loop life = player's life -updateStowedWeapon() -{ - self endon( "spawned" ); - self endon( "killed_player" ); - self endon( "disconnect" ); - - self.tag_stowed_back = undefined; - self.tag_stowed_hip = undefined; - - team = self.team; - class = self.class; - - self thread stowedWeaponsRefresh(); - - while ( true ) - { - self waittill( "weapon_change", newWeapon ); - - if ( newWeapon == "none" ) - continue; - - self thread stowedWeaponsRefresh(); - } -} - -stowedWeaponsRefresh() -{ - self endon( "spawned" ); - self endon( "killed_player" ); - self endon( "disconnect" ); - - detach_all_weapons(); - stow_on_back(); - stow_on_hip(); -} - - -detach_all_weapons() -{ - if ( isDefined( self.tag_stowed_back ) ) - self detach_back_weapon(); - - if ( isDefined( self.tag_stowed_hip ) ) - self detach_hip_weapon(); -} - - -detach_back_weapon() -{ - detach_success = self detachIfAttached( self.tag_stowed_back, "tag_stowed_back" ); - - // test for bug - //assertex( detach_success, "Detaching: " + self.tag_stowed_back + " from tag: tag_stowed_back failed." ); - self.tag_stowed_back = undefined; -} - - -detach_hip_weapon() -{ - detach_success = self detachIfAttached( self.tag_stowed_hip, "tag_stowed_hip" ); - - // test for bug - //assertex( detach_success, "Detaching: " + detach_model + " from tag: tag_stowed_hip failed." ); - self.tag_stowed_hip = undefined; -} - - -stow_on_back() -{ - prof_begin( "stow_on_back" ); - currentWeapon = self getCurrentWeapon(); - currentIsAlt = isAltModeWeapon( currentWeapon ); - - assert( !isDefined( self.tag_stowed_back ) ); - - stowWeapon = undefined; - stowCamo = 0; - large_projectile = self stowPriorityWeapon(); - stowOffsetModel = undefined; - - if ( large_projectile != "" ) - { - stowWeapon = large_projectile; - } - else - { - weaponsList = self getWeaponsListPrimaries(); - foreach ( weaponName in weaponsList ) - { - if ( weaponName == currentWeapon ) - continue; - - invType = weaponInventoryType( weaponName ); - - if ( invType != "primary" ) - { - if ( invType == "altmode" ) - continue; - - if ( weaponClass( weaponName ) == "pistol" ) - continue; - } - - if ( WeaponType( weaponName ) == "riotshield" ) - continue; - - // Don't stow the current on our back when we're using the alt - if ( currentIsAlt && weaponAltWeaponName( weaponName ) == currentWeapon ) - continue; - - stowWeapon = weaponName; - stowOffsetModel = getStowOffsetModel( stowWeapon ); - - if ( stowWeapon == self.primaryWeapon ) - stowCamo = self.loadoutPrimaryCamo; - else if ( stowWeapon == self.secondaryWeapon ) - stowCamo = self.loadoutSecondaryCamo; - else - stowCamo = 0; - } - } - - if ( !isDefined( stowWeapon ) ) - { - prof_end( "stow_on_back" ); - return; - } - - if ( large_projectile != "" ) - { - self.tag_stowed_back = level.stow_priority_model_array[ large_projectile ]; - } - else - { - self.tag_stowed_back = getWeaponModel( stowWeapon, stowCamo ); - } - - if ( isDefined( stowOffsetModel ) ) - { - self attach( stowOffsetModel, "tag_stowed_back", true ); - attachTag = "tag_stow_back_mid_attach"; - } - else - { - attachTag = "tag_stowed_back"; - } - - self attach( self.tag_stowed_back, attachTag, true ); - - hideTagList = GetWeaponHideTags( stowWeapon ); - - if ( !isDefined( hideTagList ) ) - { - prof_end( "stow_on_back" ); - return; - } - - for ( i = 0; i < hideTagList.size; i++ ) - self HidePart( hideTagList[ i ], self.tag_stowed_back ); - - prof_end( "stow_on_back" ); -} - -stow_on_hip() -{ - currentWeapon = self getCurrentWeapon(); - - assert( !isDefined( self.tag_stowed_hip ) ); - - stowWeapon = undefined; - - weaponsList = self getWeaponsListOffhands(); - foreach ( weaponName in weaponsList ) - { - if ( weaponName == currentWeapon ) - continue; - - if ( weaponName != "c4_mp" && weaponName != "claymore_mp" ) - continue; - - stowWeapon = weaponName; - } - - if ( !isDefined( stowWeapon ) ) - return; - - self.tag_stowed_hip = getWeaponModel( stowWeapon ); - self attach( self.tag_stowed_hip, "tag_stowed_hip_rear", true ); - - hideTagList = GetWeaponHideTags( stowWeapon ); - - if ( !isDefined( hideTagList ) ) - return; - - for ( i = 0; i < hideTagList.size; i++ ) - self HidePart( hideTagList[ i ], self.tag_stowed_hip ); -} - - -updateSavedLastWeapon() -{ - self endon( "death" ); - self endon( "disconnect" ); - - currentWeapon = self.currentWeaponAtSpawn; - self.saved_lastWeapon = currentWeapon; - - for ( ;; ) - { - self waittill( "weapon_change", newWeapon ); - - if ( newWeapon == "none" ) - { - self.saved_lastWeapon = currentWeapon; - continue; - } - - weaponInvType = weaponInventoryType( newWeapon ); - - if ( weaponInvType != "primary" && weaponInvType != "altmode" ) - { - self.saved_lastWeapon = currentWeapon; - continue; - } - - if ( newWeapon == "onemanarmy_mp" ) - { - self.saved_lastWeapon = currentWeapon; - continue; - } - - self updateMoveSpeedScale( "primary" ); - - self.saved_lastWeapon = currentWeapon; - currentWeapon = newWeapon; - } -} - - -EMPPlayer( numSeconds ) -{ - self endon( "disconnect" ); - self endon( "death" ); - - self thread clearEMPOnDeath(); - -} - - -clearEMPOnDeath() -{ - self endon( "disconnect" ); - - self waittill( "death" ); -} - - -updateMoveSpeedScale( weaponType ) -{ - /* - if ( self _hasPerk( "specialty_lightweight" ) ) - self.moveSpeedScaler = 1.10; - else - self.moveSpeedScaler = 1; - */ - - if ( !isDefined( weaponType ) || weaponType == "primary" || weaponType != "secondary" ) - weaponType = self.primaryWeapon; - else - weaponType = self.secondaryWeapon; - - if( isDefined(self.primaryWeapon ) && self.primaryWeapon == "riotshield_mp" ) - { - self setMoveSpeedScale( .8 * self.moveSpeedScaler ); - return; - } - - if ( !isDefined( weaponType ) ) - weapClass = "none"; - else - weapClass = weaponClass( weaponType ); - - - switch ( weapClass ) - { - case "rifle": - self setMoveSpeedScale( 0.95 * self.moveSpeedScaler ); - break; - case "pistol": - self setMoveSpeedScale( 1.0 * self.moveSpeedScaler ); - break; - case "mg": - self setMoveSpeedScale( 0.875 * self.moveSpeedScaler ); - break; - case "smg": - self setMoveSpeedScale( 1.0 * self.moveSpeedScaler ); - break; - case "spread": - self setMoveSpeedScale( .95 * self.moveSpeedScaler ); - break; - case "rocketlauncher": - self setMoveSpeedScale( 0.80 * self.moveSpeedScaler ); - break; - case "sniper": - self setMoveSpeedScale( 1.0 * self.moveSpeedScaler ); - break; - default: - self setMoveSpeedScale( 1.0 * self.moveSpeedScaler ); - break; - } -} - - -buildWeaponData( filterPerks ) -{ - attachmentList = getAttachmentList(); - max_weapon_num = 149; - - baseWeaponData = []; - - for( weaponId = 0; weaponId <= max_weapon_num; weaponId++ ) - { - baseName = tablelookup( "mp/statstable.csv", 0, weaponId, 4 ); - if( baseName == "" ) - continue; - - assetName = baseName + "_mp"; - - if ( !isSubStr( tableLookup( "mp/statsTable.csv", 0, weaponId, 2 ), "weapon_" ) ) - continue; - - if ( weaponInventoryType( assetName ) != "primary" ) - continue; - - weaponInfo = spawnStruct(); - weaponInfo.baseName = baseName; - weaponInfo.assetName = assetName; - weaponInfo.variants = []; - - weaponInfo.variants[0] = assetName; - // the alphabetize function is slow so we try not to do it for every weapon/attachment combo; a code solution would be better. - attachmentNames = []; - for ( innerLoopCount = 0; innerLoopCount < 6; innerLoopCount++ ) - { - // generating attachment combinations - attachmentName = tablelookup( "mp/statStable.csv", 0, weaponId, innerLoopCount + 11 ); - - if ( filterPerks ) - { - switch ( attachmentName ) - { - case "fmj": - case "xmags": - case "rof": - continue; - } - } - - if( attachmentName == "" ) - break; - - attachmentNames[attachmentName] = true; - } - - // generate an alphabetized attachment list - attachments = []; - foreach ( attachmentName in attachmentList ) - { - if ( !isDefined( attachmentNames[attachmentName] ) ) - continue; - - weaponInfo.variants[weaponInfo.variants.size] = baseName + "_" + attachmentName + "_mp"; - attachments[attachments.size] = attachmentName; - } - - for ( i = 0; i < (attachments.size - 1); i++ ) - { - colIndex = tableLookupRowNum( "mp/attachmentCombos.csv", 0, attachments[i] ); - for ( j = i + 1; j < attachments.size; j++ ) - { - if ( tableLookup( "mp/attachmentCombos.csv", 0, attachments[j], colIndex ) == "no" ) - continue; - - weaponInfo.variants[weaponInfo.variants.size] = baseName + "_" + attachments[i] + "_" + attachments[j] + "_mp"; - } - } - - baseWeaponData[baseName] = weaponInfo; - } - - return ( baseWeaponData ); -} - -monitorSemtex() -{ - self endon( "disconnect" ); - - for( ;; ) - { - self waittill( "grenade_fire", weapon ); - - if ( !isSubStr(weapon.model, "semtex" ) ) - continue; - - weapon waittill( "missile_stuck", stuckTo ); - - if ( !isPlayer( stuckTo ) ) - continue; - - if ( level.teamBased && isDefined( stuckTo.team ) && stuckTo.team == self.team ) - { - weapon.isStuck = "friendly"; - continue; - } - - weapon.isStuck = "enemy"; - weapon.stuckEnemyEntity = stuckTo; - - stuckTo maps\mp\gametypes\_hud_message::playerCardSplashNotify( "semtex_stuck", self ); - - self thread maps\mp\gametypes\_hud_message::SplashNotify( "stuck_semtex", 100 ); - self notify( "process", "ch_bullseye" ); - } -} - - -turret_monitorUse() -{ - for( ;; ) - { - self waittill ( "trigger", player ); - - self thread turret_playerThread( player ); - } -} - -turret_playerThread( player ) -{ - player endon ( "death" ); - player endon ( "disconnect" ); - - player notify ( "weapon_change", "none" ); - - self waittill ( "turret_deactivate" ); - - player notify ( "weapon_change", player getCurrentWeapon() ); -} diff --git a/userraw/maps/mp/killstreaks/_emp.gsc b/userraw/maps/mp/killstreaks/_emp.gsc deleted file mode 100644 index 652a133..0000000 --- a/userraw/maps/mp/killstreaks/_emp.gsc +++ /dev/null @@ -1,562 +0,0 @@ -#include maps\mp\_utility; -#include common_scripts\utility; - - -init() -{ - level._effect[ "emp_flash" ] = loadfx( "explosions/emp_flash_mp" ); - - level.teamEMPed["allies"] = false; - level.teamEMPed["axis"] = false; - level.empPlayer = undefined; - - if ( level.teamBased ) - level thread EMP_TeamTracker(); - else - level thread EMP_PlayerTracker(); - - level.killstreakFuncs["emp"] = ::EMP_Use; - - setDvarIfUninitialized( "scr_empEffectsAll", true ); - level.empEffectsAll = getDvarInt( "scr_empEffectsAll" ); - - level thread onPlayerConnect(); -} - - - -onPlayerConnect() -{ - for(;;) - { - level waittill("connected", player); - player thread onPlayerSpawned(); - } -} - - -onPlayerSpawned() -{ - self endon("disconnect"); - - for(;;) - { - self waittill( "spawned_player" ); - - if ( (level.teamBased && level.teamEMPed[self.team]) || (!level.teamBased && isDefined( level.empPlayer ) && level.empPlayer != self) ) - self setEMPJammed( true ); - } -} - - -EMP_Use( lifeId, delay ) -{ - assert( isDefined( self ) ); - - if ( !isDefined( delay ) ) - delay = 5.0; - - myTeam = self.pers["team"]; - otherTeam = level.otherTeam[myTeam]; - - if ( level.teamBased ) - self thread EMP_JamTeam( otherTeam, 60.0, delay ); - else - self thread EMP_JamPlayers( self, 60.0, delay ); - - self maps\mp\_matchdata::logKillstreakEvent( "emp", self.origin ); - self notify( "used_emp" ); - - return true; -} - - -EMP_JamTeam( teamName, duration, delay ) -{ - level endon ( "game_ended" ); - - assert( teamName == "allies" || teamName == "axis" ); - - //wait ( delay ); - - thread teamPlayerCardSplash( "used_emp", self ); - - level notify ( "EMP_JamTeam" + teamName ); - level endon ( "EMP_JamTeam" + teamName ); - - foreach ( player in level.players ) - { - player playLocalSound( "emp_activate" ); - - if ( player.team != teamName ) - continue; - - if ( player _hasPerk( "specialty_localjammer" ) ) - player RadarJamOff(); - } - - visionSetNaked( "coup_sunblind", 0.1 ); - thread empEffects(); - - wait ( 0.1 ); - - // resetting the vision set to the same thing won't normally have an effect. - // however, if the client receives the previous visionset change in the same packet as this one, - // this will force them to lerp from the bright one to the normal one. - visionSetNaked( "coup_sunblind", 0 ); - visionSetNaked( getDvar( "mapname" ), 3.0 ); - - level.teamEMPed[teamName] = true; - level notify ( "emp_update" ); - - if(!level.empEffectsAll) - level destroyActiveVehiclesTeam( teamName , self ); - else - level destroyActiveVehicles( self ); - - maps\mp\gametypes\_hostmigration::waitLongDurationWithHostMigrationPause( duration ); - - level.teamEMPed[teamName] = false; - - foreach ( player in level.players ) - { - if ( player.team != teamName ) - continue; - - if ( player _hasPerk( "specialty_localjammer" ) ) - player RadarJamOn(); - } - - level notify ( "emp_update" ); -} - -EMP_JamPlayers( owner, duration, delay ) -{ - level notify ( "EMP_JamPlayers" ); - level endon ( "EMP_JamPlayers" ); - - assert( isDefined( owner ) ); - - //wait ( delay ); - - foreach ( player in level.players ) - { - player playLocalSound( "emp_activate" ); - - if ( player == owner ) - continue; - - if ( player _hasPerk( "specialty_localjammer" ) ) - player RadarJamOff(); - } - - visionSetNaked( "coup_sunblind", 0.1 ); - thread empEffects(); - - wait ( 0.1 ); - - // resetting the vision set to the same thing won't normally have an effect. - // however, if the client receives the previous visionset change in the same packet as this one, - // this will force them to lerp from the bright one to the normal one. - visionSetNaked( "coup_sunblind", 0 ); - visionSetNaked( getDvar( "mapname" ), 3.0 ); - - level notify ( "emp_update" ); - - level.empPlayer = owner; - level.empPlayer thread empPlayerFFADisconnect(); - - if(!level.empEffectsAll) - level destroyActiveVehiclesNotSelf( owner ); - else - level destroyActiveVehicles( owner ); - - level notify ( "emp_update" ); - - maps\mp\gametypes\_hostmigration::waitLongDurationWithHostMigrationPause( duration ); - - foreach ( player in level.players ) - { - if ( player == owner ) - continue; - - if ( player _hasPerk( "specialty_localjammer" ) ) - player RadarJamOn(); - } - - level.empPlayer = undefined; - level notify ( "emp_update" ); - level notify ( "emp_ended" ); -} - -empPlayerFFADisconnect() -{ - level endon ( "EMP_JamPlayers" ); - level endon ( "emp_ended" ); - - self waittill( "disconnect" ); - level notify ( "emp_update" ); -} - -empEffects() -{ - foreach( player in level.players ) - { - playerForward = anglestoforward( player.angles ); - playerForward = ( playerForward[0], playerForward[1], 0 ); - playerForward = VectorNormalize( playerForward ); - - empDistance = 20000; - - empEnt = Spawn( "script_model", player.origin + ( 0, 0, 8000 ) + Vector_Multiply( playerForward, empDistance ) ); - empEnt setModel( "tag_origin" ); - empEnt.angles = empEnt.angles + ( 270, 0, 0 ); - empEnt thread empEffect( player ); - } -} - -empEffect( player ) -{ - player endon( "disconnect" ); - - wait( 0.5 ); - PlayFXOnTagForClients( level._effect[ "emp_flash" ], self, "tag_origin", player ); -} - -EMP_TeamTracker() -{ - level endon ( "game_ended" ); - - for ( ;; ) - { - level waittill_either ( "joined_team", "emp_update" ); - - foreach ( player in level.players ) - { - if ( player.team == "spectator" ) - continue; - - player setEMPJammed( level.teamEMPed[player.team] ); - } - } -} - - -EMP_PlayerTracker() -{ - level endon ( "game_ended" ); - - for ( ;; ) - { - level waittill_either ( "joined_team", "emp_update" ); - - foreach ( player in level.players ) - { - if ( player.team == "spectator" ) - continue; - - if ( isDefined( level.empPlayer ) && level.empPlayer != player ) - player setEMPJammed( true ); - else - player setEMPJammed( false ); - } - } -} - -doSilentEMPTeam( teamName, duration, delay, owner ) -{ - level endon ( "game_ended" ); - - assert( teamName == "allies" || teamName == "axis" ); - - //wait ( delay ); - - level notify ( "EMP_JamTeam" + teamName ); - level endon ( "EMP_JamTeam" + teamName ); - - foreach ( player in level.players ) - { - if ( player.team != teamName ) - continue; - - if ( player _hasPerk( "specialty_localjammer" ) ) - player RadarJamOff(); - } - - level.teamEMPed[teamName] = true; - level notify ( "emp_update" ); - - if(!level.empEffectsAll) - level destroyActiveVehiclesTeam( teamName , owner ); - else - level destroyActiveVehicles( owner ); - - maps\mp\gametypes\_hostmigration::waitLongDurationWithHostMigrationPause( duration ); - - level.teamEMPed[teamName] = false; - - foreach ( player in level.players ) - { - if ( player.team != teamName ) - continue; - - if ( player _hasPerk( "specialty_localjammer" ) ) - player RadarJamOn(); - } - - level notify ( "emp_update" ); -} - -doSilentEMPPlayer( owner, duration, delay ) -{ - level notify ( "EMP_JamPlayers" ); - level endon ( "EMP_JamPlayers" ); - - assert( isDefined( owner ) ); - - //wait ( delay ); - - foreach ( player in level.players ) - { - if ( player == owner ) - continue; - - if ( player _hasPerk( "specialty_localjammer" ) ) - player RadarJamOff(); - } - - level notify ( "emp_update" ); - - level.empPlayer = owner; - level.empPlayer thread empPlayerFFADisconnect(); - - if(!level.empEffectsAll) - level destroyActiveVehiclesNotSelf( owner ); - else - level destroyActiveVehicles( owner ); - - level notify ( "emp_update" ); - - maps\mp\gametypes\_hostmigration::waitLongDurationWithHostMigrationPause( duration ); - - foreach ( player in level.players ) - { - if ( player == owner ) - continue; - - if ( player _hasPerk( "specialty_localjammer" ) ) - player RadarJamOn(); - } - - level.empPlayer = undefined; - level notify ( "emp_update" ); - level notify ( "emp_ended" ); -} - -destroyActiveVehicles( attacker ) -{ - if ( isDefined( attacker ) ) - { - foreach ( heli in level.helis ) - radiusDamage( heli.origin, 384, 5000, 5000, attacker ); - - foreach ( littleBird in level.littleBird ) - radiusDamage( littleBird.origin, 384, 5000, 5000, attacker ); - - foreach ( turret in level.turrets ) - radiusDamage( turret.origin, 16, 5000, 5000, attacker ); - - foreach ( rocket in level.rockets ) - rocket notify ( "death" ); - - if ( level.teamBased ) - { - foreach ( uav in level.uavModels["allies"] ) - radiusDamage( uav.origin, 384, 5000, 5000, attacker ); - - foreach ( uav in level.uavModels["axis"] ) - radiusDamage( uav.origin, 384, 5000, 5000, attacker ); - } - else - { - foreach ( uav in level.uavModels ) - radiusDamage( uav.origin, 384, 5000, 5000, attacker ); - } - - if ( isDefined( level.ac130player ) ) - radiusDamage( level.ac130.planeModel.origin+(0,0,10), 1000, 5000, 5000, attacker ); - } - else - { - foreach ( heli in level.helis ) - radiusDamage( heli.origin, 384, 5000, 5000 ); - - foreach ( littleBird in level.littleBird ) - radiusDamage( littleBird.origin, 384, 5000, 5000 ); - - foreach ( turret in level.turrets ) - radiusDamage( turret.origin, 16, 5000, 5000 ); - - foreach ( rocket in level.rockets ) - rocket notify ( "death" ); - - if ( level.teamBased ) - { - foreach ( uav in level.uavModels["allies"] ) - radiusDamage( uav.origin, 384, 5000, 5000 ); - - foreach ( uav in level.uavModels["axis"] ) - radiusDamage( uav.origin, 384, 5000, 5000 ); - } - else - { - foreach ( uav in level.uavModels ) - radiusDamage( uav.origin, 384, 5000, 5000 ); - } - - if ( isDefined( level.ac130player ) ) - radiusDamage( level.ac130.planeModel.origin+(0,0,10), 1000, 5000, 5000 ); - } -} - -destroyActiveVehiclesNotSelf( attacker ) -{ - if ( isDefined( attacker ) ) - { - foreach ( heli in level.helis ) - if (!isDefined(heli.owner) || heli.owner != attacker) - radiusDamage( heli.origin, 384, 5000, 5000, attacker ); - - foreach ( littleBird in level.littleBird ) - if(!isDefined(littleBird.owner) || littleBird.owner != attacker) - radiusDamage( littleBird.origin, 384, 5000, 5000, attacker ); - - foreach ( turret in level.turrets ) - if(!isDefined(turret.owner) || turret.owner != attacker) - radiusDamage( turret.origin, 16, 5000, 5000, attacker ); - - foreach ( rocket in level.rockets ) - if(!isDefined(rocket.owner) || rocket.owner != attacker) - rocket notify ( "death" ); - - if ( level.teamBased ) - { - foreach ( uav in level.uavModels["allies"] ) - radiusDamage( uav.origin, 384, 5000, 5000, attacker ); - - foreach ( uav in level.uavModels["axis"] ) - radiusDamage( uav.origin, 384, 5000, 5000, attacker ); - } - else - { - foreach ( uav in level.uavModels ) - if(!isDefined(uav.owner) || uav.owner != attacker) - radiusDamage( uav.origin, 384, 5000, 5000, attacker ); - } - - if ( isDefined( level.ac130player ) ) - if (level.ac130player != attacker) - radiusDamage( level.ac130.planeModel.origin+(0,0,10), 1000, 5000, 5000, attacker ); - } - else - { - foreach ( heli in level.helis ) - radiusDamage( heli.origin, 384, 5000, 5000 ); - - foreach ( littleBird in level.littleBird ) - radiusDamage( littleBird.origin, 384, 5000, 5000 ); - - foreach ( turret in level.turrets ) - radiusDamage( turret.origin, 16, 5000, 5000 ); - - foreach ( rocket in level.rockets ) - rocket notify ( "death" ); - - if ( level.teamBased ) - { - foreach ( uav in level.uavModels["allies"] ) - radiusDamage( uav.origin, 384, 5000, 5000 ); - - foreach ( uav in level.uavModels["axis"] ) - radiusDamage( uav.origin, 384, 5000, 5000 ); - } - else - { - foreach ( uav in level.uavModels ) - radiusDamage( uav.origin, 384, 5000, 5000 ); - } - - if ( isDefined( level.ac130player ) ) - radiusDamage( level.ac130.planeModel.origin+(0,0,10), 1000, 5000, 5000 ); - } -} - -destroyActiveVehiclesTeam( Team, attacker ) -{ - if ( isDefined( attacker ) ) - { - foreach ( heli in level.helis ) - if(heli.team == Team) - radiusDamage( heli.origin, 384, 5000, 5000, attacker ); - - foreach ( littleBird in level.littleBird ) - if(littleBird.team == Team) - radiusDamage( littleBird.origin, 384, 5000, 5000, attacker ); - - foreach ( turret in level.turrets ) - if(turret.team == Team) - radiusDamage( turret.origin, 16, 5000, 5000, attacker ); - - foreach ( rocket in level.rockets ) - if(rocket.team == Team) - rocket notify ( "death" ); - - if ( Team == "allies" ) - { - foreach ( uav in level.uavModels["allies"] ) - radiusDamage( uav.origin, 384, 5000, 5000, attacker ); - } - else - { - foreach ( uav in level.uavModels["axis"] ) - radiusDamage( uav.origin, 384, 5000, 5000, attacker ); - } - - if ( isDefined( level.ac130player ) ) - if(level.ac130player.team == Team) - radiusDamage( level.ac130.planeModel.origin+(0,0,10), 1000, 5000, 5000, attacker ); - } - else - { - foreach ( heli in level.helis ) - if(heli.team == Team) - radiusDamage( heli.origin, 384, 5000, 5000 ); - - foreach ( littleBird in level.littleBird ) - if(littleBird.team == Team) - radiusDamage( littleBird.origin, 384, 5000, 5000 ); - - foreach ( turret in level.turrets ) - if(turret.team == Team) - radiusDamage( turret.origin, 16, 5000, 5000 ); - - foreach ( rocket in level.rockets ) - if(rocket.team == Team) - rocket notify ( "death" ); - - if ( Team == "allies" ) - { - foreach ( uav in level.uavModels["allies"] ) - radiusDamage( uav.origin, 384, 5000, 5000 ); - } - else - { - foreach ( uav in level.uavModels["axis"] ) - radiusDamage( uav.origin, 384, 5000, 5000 ); - } - - if ( isDefined( level.ac130player ) ) - if(level.ac130player.team == Team) - radiusDamage( level.ac130.planeModel.origin+(0,0,10), 1000, 5000, 5000 ); - } -} \ No newline at end of file diff --git a/userraw/maps/mp/killstreaks/_killstreaks.gsc b/userraw/maps/mp/killstreaks/_killstreaks.gsc deleted file mode 100644 index 358d3e1..0000000 --- a/userraw/maps/mp/killstreaks/_killstreaks.gsc +++ /dev/null @@ -1,932 +0,0 @@ -#include maps\mp\_utility; -#include maps\mp\gametypes\_hud_util; -#include common_scripts\utility; - -KILLSTREAK_STRING_TABLE = "mp/killstreakTable.csv"; - -init() -{ - // &&1 Kill Streak! - precacheString( &"MP_KILLSTREAK_N" ); - precacheString( &"MP_NUKE_ALREADY_INBOUND" ); - precacheString( &"MP_UNAVILABLE_IN_LASTSTAND" ); - precacheString( &"MP_UNAVAILABLE_WHEN_EMP" ); - precacheString( &"MP_UNAVAILABLE_USING_TURRET" ); - precacheString( &"MP_UNAVAILABLE_WHEN_INCAP" ); - precacheString( &"MP_HELI_IN_QUEUE" ); - - initKillstreakData(); - - level.killstreakFuncs = []; - level.killstreakSetupFuncs = []; - level.killstreakWeapons = []; - - level.killStreakMod = 0; - - thread maps\mp\killstreaks\_ac130::init(); - thread maps\mp\killstreaks\_remotemissile::init(); - thread maps\mp\killstreaks\_uav::init(); - thread maps\mp\killstreaks\_airstrike::init(); - thread maps\mp\killstreaks\_airdrop::init(); - thread maps\mp\killstreaks\_helicopter::init(); - thread maps\mp\killstreaks\_autosentry::init(); - thread maps\mp\killstreaks\_tank::init(); - thread maps\mp\killstreaks\_emp::init(); - thread maps\mp\killstreaks\_nuke::init(); - - level.killstreakRoundDelay = getIntProperty( "scr_game_killstreakdelay", 8 ); - - setDvarIfUninitialized( "scr_killstreaksRollover", false ); - setDvarIfUninitialized( "scr_maxKillstreakRollover", 10 ); - setDvarIfUninitialized( "scr_killstreakHud", false ); - level.killstreaksRollOver = getDvarInt("scr_killstreaksRollover"); - level.maxKillstreakRollover = getDvarInt("scr_maxKillstreakRollover"); - level.killstreakHud = getDvarInt("scr_killstreakHud"); - - level thread onPlayerConnect(); -} - - -initKillstreakData() -{ - for ( i = 1; true; i++ ) - { - retVal = tableLookup( KILLSTREAK_STRING_TABLE, 0, i, 1 ); - if ( !isDefined( retVal ) || retVal == "" ) - break; - - streakRef = tableLookup( KILLSTREAK_STRING_TABLE, 0, i, 1 ); - assert( streakRef != "" ); - - streakUseHint = tableLookupIString( KILLSTREAK_STRING_TABLE, 0, i, 6 ); - assert( streakUseHint != &"" ); - precacheString( streakUseHint ); - - streakEarnDialog = tableLookup( KILLSTREAK_STRING_TABLE, 0, i, 8 ); - assert( streakEarnDialog != "" ); - game[ "dialog" ][ streakRef ] = streakEarnDialog; - - streakAlliesUseDialog = tableLookup( KILLSTREAK_STRING_TABLE, 0, i, 9 ); - assert( streakAlliesUseDialog != "" ); - game[ "dialog" ][ "allies_friendly_" + streakRef + "_inbound" ] = "use_" + streakAlliesUseDialog; - game[ "dialog" ][ "allies_enemy_" + streakRef + "_inbound" ] = "enemy_" + streakAlliesUseDialog; - - streakAxisUseDialog = tableLookup( KILLSTREAK_STRING_TABLE, 0, i, 10 ); - assert( streakAxisUseDialog != "" ); - game[ "dialog" ][ "axis_friendly_" + streakRef + "_inbound" ] = "use_" + streakAxisUseDialog; - game[ "dialog" ][ "axis_enemy_" + streakRef + "_inbound" ] = "enemy_" + streakAxisUseDialog; - - streakWeapon = tableLookup( KILLSTREAK_STRING_TABLE, 0, i, 12 ); - precacheItem( streakWeapon ); - - streakPoints = int( tableLookup( KILLSTREAK_STRING_TABLE, 0, i, 13 ) ); - assert( streakPoints != 0 ); - maps\mp\gametypes\_rank::registerScoreInfo( "killstreak_" + streakRef, streakPoints ); - - streakShader = tableLookup( KILLSTREAK_STRING_TABLE, 0, i, 14 ); - precacheShader( streakShader ); - - streakShader = tableLookup( KILLSTREAK_STRING_TABLE, 0, i, 15 ); - if ( streakShader != "" ) - precacheShader( streakShader ); - } -} - - -onPlayerConnect() -{ - for ( ;; ) - { - level waittill( "connected", player ); - - if( !isDefined ( player.pers[ "killstreaks" ] ) ) - player.pers[ "killstreaks" ] = []; - - if( !isDefined ( player.pers[ "kID" ] ) ) - player.pers[ "kID" ] = 10; - - if( !isDefined ( player.pers[ "kIDs_valid" ] ) ) - player.pers[ "kIDs_valid" ] = []; - - player.lifeId = 0; - - if ( isDefined( player.pers["deaths"] ) ) - player.lifeId = player.pers["deaths"]; - - player VisionSetMissilecamForPlayer( game["thermal_vision"] ); - - player thread onPlayerSpawned(); - player thread onPlayerChangeKit(); - } -} - - -onPlayerSpawned() -{ - self endon( "disconnect" ); - - for ( ;; ) - { - self waittill( "spawned_player" ); - self thread killstreakUseWaiter(); - self thread waitForChangeTeam(); - - if (level.killstreakHud == 1) - self thread initKillstreakHud( 145 ); - else if (level.killstreakHud == 2) - self thread initMW3KillstreakHud(); - - self giveOwnedKillstreakItem( true ); - } -} - -onPlayerChangeKit() -{ - self endon( "disconnect" ); - - for ( ;; ) - { - self waittill( "changed_kit" ); - self giveOwnedKillstreakItem(); - } -} - - -waitForChangeTeam() -{ - self endon ( "disconnect" ); - - self notify ( "waitForChangeTeam" ); - self endon ( "waitForChangeTeam" ); - - for ( ;; ) - { - self waittill ( "joined_team" ); - clearKillstreaks(); - } -} - - -isRideKillstreak( streakName ) -{ - switch( streakName ) - { - case "helicopter_minigun": - case "helicopter_mk19": - case "ac130": - case "predator_missile": - return true; - - default: - return false; - } -} - -isCarryKillstreak( streakName ) -{ - switch( streakName ) - { - case "sentry": - case "sentry_gl": - return true; - - default: - return false; - } -} - - -deadlyKillstreak( streakName ) -{ - switch ( streakName ) - { - case "predator_missile": - case "precision_airstrike": - case "harrier_airstrike": - //case "helicopter": - //case "helicopter_flares": - case "stealth_airstrike": - //case "helicopter_minigun": - case "ac130": - return true; - } - - return false; -} - - -killstreakUsePressed() -{ - streakName = self.pers["killstreaks"][0].streakName; - lifeId = self.pers["killstreaks"][0].lifeId; - isEarned = self.pers["killstreaks"][0].earned; - awardXp = self.pers["killstreaks"][0].awardXp; - kID = self.pers["killstreaks"][0].kID; - - assert( isDefined( streakName ) ); - assert( isDefined( level.killstreakFuncs[ streakName ] ) ); - - if ( !self isOnGround() && ( isRideKillstreak( streakName ) || isCarryKillstreak( streakName ) ) ) - return ( false ); - - if ( self isUsingRemote() ) - return ( false ); - - if ( isDefined( self.selectingLocation ) ) - return ( false ); - - if ( deadlyKillstreak( streakName ) && level.killstreakRoundDelay && getGametypeNumLives() ) - { - if ( level.gracePeriod - level.inGracePeriod < level.killstreakRoundDelay ) - { - self iPrintLnBold( &"MP_UNAVAILABLE_FOR_N", (level.killstreakRoundDelay - (level.gracePeriod - level.inGracePeriod)) ); - return ( false ); - } - } - - if ( (level.teamBased && level.teamEMPed[self.team]) || (!level.teamBased && isDefined( level.empPlayer ) && level.empPlayer != self) ) - { - self iPrintLnBold( &"MP_UNAVAILABLE_WHEN_EMP" ); - return ( false ); - } - - if ( self IsUsingTurret() && ( isRideKillstreak( streakName ) || isCarryKillstreak( streakName ) ) ) - { - self iPrintLnBold( &"MP_UNAVAILABLE_USING_TURRET" ); - return ( false ); - } - - if ( isDefined( self.lastStand ) && isRideKillstreak( streakName ) ) - { - self iPrintLnBold( &"MP_UNAVILABLE_IN_LASTSTAND" ); - return ( false ); - } - - if ( !self isWeaponEnabled() ) - return ( false ); - - if ( streakName == "airdrop" || streakName == "airdrop_sentry_minigun" || streakName == "airdrop_mega" ) - { - if ( !self [[ level.killstreakFuncs[ streakName ] ]]( lifeId, kID ) ) - return ( false ); - } - else - { - if ( !self [[ level.killstreakFuncs[ streakName ] ]]( lifeId ) ) - return ( false ); - } - - self usedKillstreak( streakName, awardXp ); - self shuffleKillStreaksFILO( streakName, kID ); - self giveOwnedKillstreakItem(); - - return ( true ); -} - - -//this overwrites killstreak at index 0 and decrements all other killstreaks (FCLS style) -shuffleKillStreaksFILO( streakName, kID ) -{ - self _setActionSlot( 4, "" ); - - arraySize = self.pers["killstreaks"].size; - - streakIndex = -1; - for ( i = 0; i < arraySize; i++ ) - { - if ( self.pers["killstreaks"][i].streakName != streakName ) - continue; - - if ( isDefined( kID ) && self.pers["killstreaks"][i].kID != kID ) - continue; - - streakIndex = i; - break; - } - assert( streakIndex >= 0 ); - - self.pers["killstreaks"][streakIndex] = undefined; - - for( i = streakIndex + 1; i < arraySize; i++ ) - { - if ( i == arraySize - 1 ) - { - self.pers["killstreaks"][i-1] = self.pers["killstreaks"][i]; - self.pers["killstreaks"][i] = undefined; - } - else - { - self.pers["killstreaks"][i-1] = self.pers["killstreaks"][i]; - } - } -} - - -usedKillstreak( streakName, awardXp ) -{ - self playLocalSound( "weap_c4detpack_trigger_plr" ); - - if ( awardXp ) - self thread [[ level.onXPEvent ]]( "killstreak_" + streakName ); - - self thread maps\mp\gametypes\_missions::useHardpoint( streakName ); - - awardref = maps\mp\_awards::getKillstreakAwardRef( streakName ); - if ( isDefined( awardref ) ) - self thread incPlayerStat( awardref, 1 ); - - team = self.team; - - if ( level.teamBased ) - { - thread leaderDialog( team + "_friendly_" + streakName + "_inbound", team ); - - if ( getKillstreakInformEnemy( streakName ) ) - thread leaderDialog( team + "_enemy_" + streakName + "_inbound", level.otherTeam[ team ] ); - } - else - { - self thread leaderDialogOnPlayer( team + "_friendly_" + streakName + "_inbound" ); - - if ( getKillstreakInformEnemy( streakName ) ) - { - excludeList[0] = self; - thread leaderDialog( team + "_enemy_" + streakName + "_inbound", undefined, undefined, excludeList ); - } - } -} - - -clearKillstreaks() -{ - foreach ( index, streakStruct in self.pers["killstreaks"] ) - self.pers["killstreaks"][index] = undefined; -} - -getFirstPrimaryWeapon() -{ - weaponsList = self getWeaponsListPrimaries(); - - assert ( isDefined( weaponsList[0] ) ); - assert ( !isKillstreakWeapon( weaponsList[0] ) ); - - if ( weaponsList[0] == "onemanarmy_mp" ) - { - assert ( isDefined( weaponsList[1] ) ); - assert ( !isKillstreakWeapon( weaponsList[1] ) ); - - return weaponsList[1]; - } - - return weaponsList[0]; -} - - -killstreakUseWaiter() -{ - self endon( "disconnect" ); - self endon( "finish_death" ); - level endon( "game_ended" ); - - self.lastKillStreak = 0; - if ( !isDefined( self.pers["lastEarnedStreak"] ) ) - self.pers["lastEarnedStreak"] = undefined; - - self thread finishDeathWaiter(); - - for ( ;; ) - { - self waittill ( "weapon_change", newWeapon ); - - if ( !isAlive( self ) ) - continue; - - if ( !isDefined( self.pers["killstreaks"][0] ) ) - continue; - - if ( newWeapon != getKillstreakWeapon( self.pers["killstreaks"][0].streakName ) ) - continue; - - waittillframeend; - - streakName = self.pers["killstreaks"][0].streakName; - result = self killstreakUsePressed(); - - //no force switching weapon for ridable killstreaks - if ( !isRideKillstreak( streakName ) || !result ) - { - if ( !self hasWeapon( self getLastWeapon() ) ) - self switchToWeapon( self getFirstPrimaryWeapon() ); - else - self switchToWeapon( self getLastWeapon() ); - } - - // give time to switch to the near weapon; when the weapon is none (such as during a "disableWeapon()" period - // re-enabling the weapon immediately does a "weapon_change" to the killstreak weapon we just used. In the case that - // we have two of that killstreak, it immediately uses the second one - if ( self getCurrentWeapon() == "none" ) - { - while ( self getCurrentWeapon() == "none" ) - wait ( 0.05 ); - - waittillframeend; - } - } -} - - -finishDeathWaiter() -{ - self endon ( "disconnect" ); - level endon ( "game_ended" ); - - self waittill ( "death" ); - wait ( 0.05 ); - self notify ( "finish_death" ); - self.pers["lastEarnedStreak"] = undefined; -} - - -checkKillstreakReward( streakCount ) -{ - self notify( "got_killstreak", streakCount ); - - maxVal = 0; - killStreaks = []; - foreach ( streakVal, streakName in self.killStreaks ) - { - killStreaks[streakName] = streakVal; - if ( streakVal > maxVal ) - maxVal = streakVal; - } - - foreach ( streakVal, streakName in self.killStreaks ) - { - actualVal = streakVal + level.killStreakMod; - - if ( actualVal > streakCount ) - break; - - if ( isDefined( self.pers["lastEarnedStreak"] ) && killStreaks[streakName] <= killStreaks[self.pers["lastEarnedStreak"]] ) - continue; - - if ( isSubStr( streakName, "-rollover" ) ) - { - if (!level.killstreaksRollover || (level.killstreaksRollover == 2 && !self _hasPerk("specialty_rollover"))) - continue; - else - { - curRollover = int(strtok(strtok(streakName, "-")[1], "rollover")[0]); - if (curRollover > level.maxKillstreakRollover) - continue; - - if ( isDefined( game["defcon"] ) && game["defcon"] > 2 ) - { - self.pers["lastEarnedStreak"] = streakName; - continue; - } - - useStreakName = strTok( streakName, "-" )[0]; - } - } - else - { - useStreakName = streakName; - } - - if ( self tryGiveKillstreak( useStreakName, int(max( actualVal, streakCount )) ) ) - { - self thread killstreakEarned( useStreakName ); - self.pers["lastEarnedStreak"] = streakName; - } - } -} - - -killstreakEarned( streakName ) -{ - if ( self getPlayerData( "killstreaks", 0 ) == streakName ) - { - self.firstKillstreakEarned = getTime(); - } - else if ( self getPlayerData( "killstreaks", 2 ) == streakName && isDefined( self.firstKillstreakEarned ) ) - { - if ( getTime() - self.firstKillstreakEarned < 20000 ) - self thread maps\mp\gametypes\_missions::genericChallenge( "wargasm" ); - } -} - - -rewardNotify( streakName, streakVal ) -{ - self endon( "disconnect" ); - - self maps\mp\gametypes\_hud_message::killstreakSplashNotify( streakName, streakVal ); -} - - -tryGiveKillstreak( streakName, streakVal ) -{ - level notify ( "gave_killstreak", streakName ); - - if ( !level.gameEnded ) - self thread rewardNotify( streakName, streakVal ); - - self giveKillstreak( streakName, streakVal, true ); - return true; -} - - -giveKillstreak( streakName, isEarned, awardXp, owner ) -{ - self endon ( "disconnect" ); - - weapon = getKillstreakWeapon( streakName ); - - self giveKillstreakWeapon( weapon ); - - // shuffle existing killstreaks up a notch - for( i = self.pers["killstreaks"].size; i >= 0; i-- ) - self.pers["killstreaks"][i + 1] = self.pers["killstreaks"][i]; - - self.pers["killstreaks"][0] = spawnStruct(); - self.pers["killstreaks"][0].streakName = streakName; - self.pers["killstreaks"][0].earned = isDefined( isEarned ) && isEarned; - self.pers["killstreaks"][0].awardxp = isDefined( awardXp ) && awardXp; - self.pers["killstreaks"][0].owner = owner; - - self.pers["killstreaks"][0].kID = self.pers["kID"]; - self.pers["kIDs_valid"][self.pers["kID"]] = true; - - self.pers["kID"]++; - - if ( !self.pers["killstreaks"][0].earned ) - self.pers["killstreaks"][0].lifeId = -1; - else - self.pers["killstreaks"][0].lifeId = self.pers["deaths"]; - - // probably obsolete unless we bring back the autoshotty - if ( isdefined( level.killstreakSetupFuncs[ streakName ] ) ) - self [[ level.killstreakSetupFuncs[ streakName ] ]](); - - if ( isDefined( isEarned ) && isEarned && isDefined( awardXp ) && awardXp ) - self notify( "received_earned_killstreak" ); -} - - -giveKillstreakWeapon( weapon ) -{ - weaponList = self getWeaponsListItems(); - - foreach ( item in weaponList ) - { - if ( !isSubStr( item, "killstreak" ) ) - continue; - - if ( self getCurrentWeapon() == item ) - continue; - - self takeWeapon( item ); - } - - self _giveWeapon( weapon, 0 ); - self _setActionSlot( 4, "weapon", weapon ); -} - - -getStreakCost( streakName ) -{ - return int( tableLookup( KILLSTREAK_STRING_TABLE, 1, streakName, 4 ) ); -} - - -getKillstreakHint( streakName ) -{ - return tableLookupIString( KILLSTREAK_STRING_TABLE, 1, streakName, 6 ); -} - - -getKillstreakInformEnemy( streakName ) -{ - return int( tableLookup( KILLSTREAK_STRING_TABLE, 1, streakName, 11 ) ); -} - - -getKillstreakSound( streakName ) -{ - return tableLookup( KILLSTREAK_STRING_TABLE, 1, streakName, 7 ); -} - - -getKillstreakDialog( streakName ) -{ - return tableLookup( KILLSTREAK_STRING_TABLE, 1, streakName, 8 ); -} - - -getKillstreakWeapon( streakName ) -{ - return tableLookup( KILLSTREAK_STRING_TABLE, 1, streakName, 12 ); -} - -getKillstreakIcon( streakName ) -{ - return tableLookup( KILLSTREAK_STRING_TABLE, 1, streakName, 14 ); -} - -getKillstreakCrateIcon( streakName ) -{ - return tableLookup( KILLSTREAK_STRING_TABLE, 1, streakName, 15 ); -} - - -giveOwnedKillstreakItem( skipDialog ) -{ - if ( !isDefined( self.pers["killstreaks"][0] ) ) - return; - - streakName = self.pers["killstreaks"][0].streakName; - - weapon = getKillstreakWeapon( streakName ); - self giveKillstreakWeapon( weapon ); - - if ( !isDefined( skipDialog ) && !level.inGracePeriod ) - self leaderDialogOnPlayer( streakName, "killstreak_earned" ); -} - - -initRideKillstreak() -{ - self _disableUsability(); - result = self initRideKillstreak_internal(); - - if ( isDefined( self ) ) - self _enableUsability(); - - return result; -} - -initRideKillstreak_internal() -{ - laptopWait = self waittill_any_timeout( 1.0, "disconnect", "death", "weapon_switch_started" ); - - if ( laptopWait == "weapon_switch_started" ) - return ( "fail" ); - - if ( !isAlive( self ) ) - return "fail"; - - if ( laptopWait == "disconnect" || laptopWait == "death" ) - { - if ( laptopWait == "disconnect" ) - return ( "disconnect" ); - - if ( self.team == "spectator" ) - return "fail"; - - return ( "success" ); - } - - if ( self isEMPed() || self isNuked() ) - { - return ( "fail" ); - } - - self VisionSetNakedForPlayer( "black_bw", 0.75 ); - blackOutWait = self waittill_any_timeout( 0.80, "disconnect", "death" ); - - if ( blackOutWait != "disconnect" ) - { - self thread clearRideIntro( 1.0 ); - - if ( self.team == "spectator" ) - return "fail"; - } - - if ( !isAlive( self ) ) - return "fail"; - - if ( self isEMPed() || self isNuked() ) - return "fail"; - - if ( blackOutWait == "disconnect" ) - return ( "disconnect" ); - else - return ( "success" ); -} - - -clearRideIntro( delay ) -{ - self endon( "disconnect" ); - - if ( isDefined( delay ) ) - wait( delay ); - - //self freezeControlsWrapper( false ); - - if ( !isDefined( level.nukeVisionInProgress ) ) - self VisionSetNakedForPlayer( getDvar( "mapname" ), 0 ); -} - -destroyOnEvents(elem) -{ - self waittill_either("disconnect", "spawned_player"); - elem destroy(); -} - -initKillstreakHud(inity) -{ - self endon( "death" ); - self endon( "disconnect" ); - - streakVals = GetArrayKeys(self.killStreaks); - hasHardline = self _hasPerk("specialty_hardline"); - - self.killStreakHudElems = []; - - // the killstreak counter - index = self.killStreakHudElems.size; - self.killStreakHudElems[index] = self createFontString( "objective", 2 ); - self.killStreakHudElems[index].foreground = false; - self.killStreakHudElems[index].hideWhenInMenu = true; - self.killStreakHudElems[index].fontScale = 0.60; - self.killStreakHudElems[index].font = "hudbig"; - self.killStreakHudElems[index].alpha = 1; - self.killStreakHudElems[index].glow = 1; - self.killStreakHudElems[index].glowColor = ( 0, 0, 1 ); - self.killStreakHudElems[index].glowAlpha = 1; - self.killStreakHudElems[index].color = ( 1.0, 1.0, 1.0 ); - self thread destroyOnEvents(self.killStreakHudElems[index]); - highestStreak = -1; - - for (i = 0; i < streakVals.size; i++) - { - streakVal = streakVals[i]; - streakName = self.killStreaks[streakVal]; - - if (isSubStr(streakName, "-rollover")) - continue; - - streakShader = maps\mp\killstreaks\_killstreaks::getKillstreakIcon( streakName ); - streakCost = maps\mp\killstreaks\_killstreaks::getStreakCost( streakName ); - if (hasHardline) - streakCost--; - - // each killstreak icon - index = self.killStreakHudElems.size; - self.killStreakHudElems[index] = self createFontString( "objective", 2 ); - self.killStreakHudElems[index].foreground = false; - self.killStreakHudElems[index].hideWhenInMenu = true; - self.killStreakHudElems[index].fontScale = 0.60; - self.killStreakHudElems[index].font = "hudbig"; - self.killStreakHudElems[index].alpha = 1; - self.killStreakHudElems[index].glow = 1; - self.killStreakHudElems[index].glowColor = ( 0, 0, 1 ); - self.killStreakHudElems[index].glowAlpha = 1; - self.killStreakHudElems[index].color = ( 1.0, 1.0, 1.0 ); - self.killStreakHudElems[index] setPoint( "RIGHT", "RIGHT", 0, inity - 25 * i ); - self.killStreakHudElems[index] setShader( streakShader, 20, 20 ); - self.killStreakHudElems[index].ks_cost = streakCost; - self thread destroyOnEvents(self.killStreakHudElems[index]); - - if (streakCost > highestStreak) - highestStreak = streakCost; - } - - for(first=true;;) - { - if (first) - first = false; - else - self waittill( "killed_enemy" ); - - curStreak = self.pers["cur_kill_streak"]; - timesRolledOver = int(curStreak / highestStreak); - if (level.killstreaksRollover == 1 || (level.killstreaksRollover == 2 && self _hasPerk("specialty_rollover"))) - curStreak %= highestStreak; - - if (timesRolledOver > level.maxKillstreakRollover) - curStreak = highestStreak; - - isUnderAStreak = false; - - for (i = self.killStreakHudElems.size - 1; i >= 1; i--) - { - streakElem = self.killStreakHudElems[i]; - if (curStreak < streakElem.ks_cost) - { - isUnderAStreak = true; - self.killStreakHudElems[0] setPoint( "RIGHT", "RIGHT", -25, inity - 25 * (i - 1) ); - self.killStreakHudElems[0] setText( streakElem.ks_cost - curStreak ); - } - } - - if (!isUnderAStreak && self.killStreakHudElems.size) - { - self.killStreakHudElems[0] setPoint( "RIGHT", "RIGHT", -25, inity - 25 * (self.killStreakHudElems.size - 1 - 1) ); - self.killStreakHudElems[0] setText( "Done" ); - } - } -} - -initMW3KillstreakHud() -{ - self endon( "death" ); - self endon( "disconnect" ); - - streakVals = GetArrayKeys(self.killStreaks); - hasHardline = self _hasPerk("specialty_hardline"); - - self.killStreakHudElems = []; - self.killStreakShellsElems = []; - highestStreak = -1; - - for (i = 0; i < streakVals.size; i++) - { - streakVal = streakVals[i]; - streakName = self.killStreaks[streakVal]; - - if (isSubStr(streakName, "-rollover")) - continue; - - streakShader = maps\mp\killstreaks\_killstreaks::getKillstreakIcon( streakName ); - streakCost = maps\mp\killstreaks\_killstreaks::getStreakCost( streakName ); - if (hasHardline) - streakCost--; - - if (streakCost > highestStreak) - highestStreak = streakCost; - - // the shader - ksIcon = createIcon( streakShader, 20, 20 ); - ksIcon setPoint( "BOTTOM RIGHT", "BOTTOM RIGHT", -32, -90 + -25 * i ); - ksIcon.alpha = 0.4; - ksIcon.hideWhenInMenu = true; - ksIcon.foreground = true; - ksIcon.ks_cost = streakCost; - self thread destroyOnEvents(ksIcon); - self.killStreakHudElems[self.killStreakHudElems.size] = ksIcon; - } - - // the shells - if (highestStreak > 0) - { - h = -53; - for(i = 0; i < highestStreak; i++) - { - ksShell = NewClientHudElem( self ); - ksShell.x = 40; - ksShell.y = h; - ksShell.alignX = "right"; - ksShell.alignY = "bottom"; - ksShell.horzAlign = "right"; - ksShell.vertAlign = "bottom"; - ksShell setshader("white", 10, 2); - ksShell.alpha = 0.3; - ksShell.hideWhenInMenu = true; - ksShell.foreground = false; - self thread destroyOnEvents(ksShell); - self.killStreakShellsElems[i] = ksShell; - - h -= 4; - } - } - - for(first=true;;) - { - if (first) - first = false; - else - self waittill( "killed_enemy" ); - - curStreak = self.pers["cur_kill_streak"]; - timesRolledOver = int(curStreak / highestStreak); - if (level.killstreaksRollover == 1 || (level.killstreaksRollover == 2 && self _hasPerk("specialty_rollover"))) - curStreak %= highestStreak; - - if (timesRolledOver > level.maxKillstreakRollover) - curStreak = highestStreak; - - // update the shells - for (i = 0; i < self.killStreakShellsElems.size; i++) - { - elem = self.killStreakShellsElems[i]; - if (curStreak > i) - elem.alpha = 0.85; - else - elem.alpha = 0.3; - } - - // update the ks icons - for (i = 0; i < self.killStreakHudElems.size; i++) - { - elem = self.killStreakHudElems[i]; - - if (curStreak >= elem.ks_cost) - elem.alpha = 0.9; - else - elem.alpha = 0.4; - } - } -} diff --git a/userraw/maps/mp/killstreaks/_nuke.gsc b/userraw/maps/mp/killstreaks/_nuke.gsc deleted file mode 100644 index 4575906..0000000 --- a/userraw/maps/mp/killstreaks/_nuke.gsc +++ /dev/null @@ -1,457 +0,0 @@ -#include common_scripts\utility; -#include maps\mp\_utility; - -init() -{ - precacheItem( "nuke_mp" ); - precacheLocationSelector( "map_nuke_selector" ); - precacheString( &"MP_TACTICAL_NUKE_CALLED" ); - precacheString( &"MP_FRIENDLY_TACTICAL_NUKE" ); - precacheString( &"MP_TACTICAL_NUKE" ); - - level._effect[ "nuke_player" ] = loadfx( "explosions/player_death_nuke" ); - level._effect[ "nuke_flash" ] = loadfx( "explosions/player_death_nuke_flash" ); - level._effect[ "nuke_aftermath" ] = loadfx( "dust/nuke_aftermath_mp" ); - - game["strings"]["nuclear_strike"] = &"MP_TACTICAL_NUKE"; - - level.killstreakFuncs["nuke"] = ::tryUseNuke; - - setDvarIfUninitialized( "scr_nukeTimer", 10 ); - setDvarIfUninitialized( "scr_nukeCancelMode", 0 ); - setDvarIfUninitialized( "scr_nukeEndsGame", true ); - setDvarIfUninitialized( "scr_nukeKillsAll", true ); - - level.nukeTimer = getDvarInt( "scr_nukeTimer" ); - level.cancelMode = getDvarInt( "scr_nukeCancelMode" ); - level.nukeEndsGame = getDvarInt( "scr_nukeEndsGame" ); - level.nukeKillsAll = getDvarInt( "scr_nukeKillsAll" ); - - /# - setDevDvarIfUninitialized( "scr_nukeDistance", 5000 ); - setDevDvarIfUninitialized( "scr_nukeEndsGame", false ); - setDevDvarIfUninitialized( "scr_nukeDebugPosition", false ); - #/ - level.moabXP = []; - - level thread onPlayerConnect(); -} - -onPlayerConnect() -{ - for(;;) - { - level waittill("connected", player); - player thread onPlayerSpawned(); - } -} - -onPlayerSpawned() -{ - self endon("disconnect"); - - for(;;) - { - self waittill( "spawned_player" ); - - if(isDefined(level.moabXP[self.team]) || isDefined(level.moabXP[self.guid])) - self.xpScaler = 2; - } -} - -tryUseNuke( lifeId, allowCancel ) -{ - if( isDefined( level.nukeIncoming ) ) - { - self iPrintLnBold( &"MP_NUKE_ALREADY_INBOUND" ); - return false; - } - - if ( self isUsingRemote() && ( !isDefined( level.gtnw ) || !level.gtnw ) ) - return false; - - if ( !isDefined( allowCancel ) ) - allowCancel = true; - - self thread doNuke( allowCancel ); - self notify( "used_nuke" ); - - return true; -} - -delaythread_nuke( delay, func ) -{ - level endon ( "nuke_cancelled" ); - - wait ( delay ); - - thread [[ func ]](); -} - -doNuke( allowCancel ) -{ - level notify ( "nuke_cancelled" ); - level endon ( "nuke_cancelled" ); - - level.nukeInfo = spawnStruct(); - level.nukeInfo.player = self; - level.nukeInfo.team = self.pers["team"]; - - level.nukeIncoming = true; - - if(level.nukeEndsGame) - maps\mp\gametypes\_gamelogic::pauseTimer(); - - level.timeLimitOverride = true; - level.scoreLimitOverride = true; - setGameEndTime( int( gettime() + (level.nukeTimer * 1000) ) ); - setDvar( "ui_bomb_timer", 4 ); // Nuke sets '4' to avoid briefcase icon showing - - if ( level.teambased ) - { - thread teamPlayerCardSplash( "used_nuke", self, self.team ); - /* - players = level.players; - - foreach( player in level.players ) - { - playerteam = player.pers["team"]; - if ( isdefined( playerteam ) ) - { - if ( playerteam == self.pers["team"] ) - player iprintln( &"MP_TACTICAL_NUKE_CALLED", self ); - } - } - */ - } - else - { - if ( !level.hardcoreMode ) - self iprintlnbold(&"MP_FRIENDLY_TACTICAL_NUKE"); - } - - level thread delaythread_nuke( (level.nukeTimer - 3.3), ::nukeSoundIncoming ); - level thread delaythread_nuke( level.nukeTimer, ::nukeSoundExplosion ); - level thread delaythread_nuke( level.nukeTimer, ::nukeSlowMo ); - level thread delaythread_nuke( level.nukeTimer, ::nukeEffects ); - level thread delaythread_nuke( (level.nukeTimer + 0.25), ::nukeVision ); - level thread delaythread_nuke( (level.nukeTimer + 1.5), ::nukeDeath ); - level thread delaythread_nuke( (level.nukeTimer + 1.5), ::nukeEarthquake ); - level thread nukeAftermathEffect(); - - if ( level.cancelMode && allowCancel ) - level thread cancelNukeOnDeath( self ); - - clockObject = spawn( "script_origin", (0,0,0) ); - clockObject hide(); - level thread killClockObjectOnEndOn(clockObject); - - while ( !isDefined( level.nukeDetonated ) ) - { - clockObject playSound( "ui_mp_nukebomb_timer" ); - wait( 1.0 ); - } - - clockObject notify("death"); - clockObject delete(); -} - -killClockObjectOnEndOn(clockObject) -{ - clockObject endon("death"); - level waittill( "nuke_cancelled" ); - clockObject delete(); -} - -cancelNukeOnDeath( player ) -{ - level endon ( "nuke_cancelled" ); - player waittill_any( "death", "disconnect" ); - - if ( isDefined( player ) && level.cancelMode == 2 ) - player thread maps\mp\killstreaks\_emp::EMP_Use( 0, 0 ); - - level.nukeIncoming = undefined; - - level.nukeDetonated = undefined; - - maps\mp\gametypes\_gamelogic::resumeTimer(); - level.timeLimitOverride = false; - level.scoreLimitOverride = false; - level notify( "update_scorelimit" ); - - foreach(player in level.players) - player.nuked = undefined; - - setDvar( "ui_bomb_timer", 0 ); // Nuke sets '4' to avoid briefcase icon showing - - level notify ( "nuke_cancelled" ); -} - -nukeSoundIncoming() -{ - level endon ( "nuke_cancelled" ); - - foreach( player in level.players ) - player playlocalsound( "nuke_incoming" ); -} - -nukeSoundExplosion() -{ - level endon ( "nuke_cancelled" ); - - foreach( player in level.players ) - { - player playlocalsound( "nuke_explosion" ); - player playlocalsound( "nuke_wave" ); - } -} - -nukeEffects() -{ - level endon ( "nuke_cancelled" ); - - setDvar( "ui_bomb_timer", 0 ); - setGameEndTime( 0 ); - - level.nukeDetonated = true; - - if ( !level.nukeEndsGame ) - { - if ( level.teamBased ) - { - level thread maps\mp\killstreaks\_emp::doSilentEMPTeam(level.otherTeam[level.nukeInfo.team], 60, 5, level.nukeInfo.player); - - foreach (player in level.players) - { - if(level.nukeInfo.team == player.team) - { - player.xpScaler = 2; - } - } - level.moabXP[level.nukeInfo.team] = true; - } - else - { - level thread maps\mp\killstreaks\_emp::doSilentEMPPlayer(level.nukeInfo.player, 60, 5); - if(isDefined(level.nukeInfo.player)) - { - level.nukeInfo.player.xpScaler = 2; - level.moabXP[level.nukeInfo.player.guid] = true; - } - } - } - else - level maps\mp\killstreaks\_emp::destroyActiveVehicles( level.nukeInfo.player ); - - foreach( player in level.players ) - { - playerForward = anglestoforward( player.angles ); - playerForward = ( playerForward[0], playerForward[1], 0 ); - playerForward = VectorNormalize( playerForward ); - - nukeDistance = 5000; - /# nukeDistance = getDvarInt( "scr_nukeDistance" ); #/ - - nukeEnt = Spawn( "script_model", player.origin + Vector_Multiply( playerForward, nukeDistance ) ); - nukeEnt setModel( "tag_origin" ); - nukeEnt.angles = ( 0, (player.angles[1] + 180), 90 ); - - /# - if ( getDvarInt( "scr_nukeDebugPosition" ) ) - { - lineTop = ( nukeEnt.origin[0], nukeEnt.origin[1], (nukeEnt.origin[2] + 500) ); - thread draw_line_for_time( nukeEnt.origin, lineTop, 1, 0, 0, 10 ); - } - #/ - - nukeEnt thread nukeEffect( player ); - - level thread killClockObjectOnEndOn(nukeEnt); - level thread killNukeEntOn(nukeEnt); - } -} - -killNukeEntOn(nukeEnt) -{ - nukeEnt endon("death"); - level endon ( "nuke_cancelled" ); - level waittill("nuke_death"); - nukeEnt notify("death"); - nukeEnt delete(); -} - -nukeEffect( player ) -{ - level endon ( "nuke_cancelled" ); - - player endon( "disconnect" ); - - waitframe(); - PlayFXOnTagForClients( level._effect[ "nuke_flash" ], self, "tag_origin", player ); -} - -nukeAftermathEffect() -{ - level endon ( "nuke_cancelled" ); - - level waittill ( "spawning_intermission" ); - - afermathEnt = getEntArray( "mp_global_intermission", "classname" ); - afermathEnt = afermathEnt[0]; - up = anglestoup( afermathEnt.angles ); - right = anglestoright( afermathEnt.angles ); - - PlayFX( level._effect[ "nuke_aftermath" ], afermathEnt.origin, up, right ); -} - -nukeSlowMo() -{ - level endon ( "nuke_cancelled" ); - - //SetSlowMotion( , , ) - setSlowMotion( 1.0, 0.25, 0.5 ); - level waittill( "nuke_death" ); - setSlowMotion( 0.25, 1, 2.0 ); -} - -fixVisionOnCancel() -{ - level waittill ( "nuke_cancelled" ); - //reset nuke vision - visionSetNaked( getDvar( "mapname" ), 2.0 ); - level.nukeVisionInProgress = undefined; -} - -nukeVision() -{ - level endon ( "nuke_cancelled" ); - - level.nukeVisionInProgress = true; - visionSetNaked( "mpnuke", 3 ); - - level waittill( "nuke_death" ); - - visionSetNaked( "mpnuke_aftermath", 5 ); - - level thread fixVisionOnCancel(); - - - if( level.NukeEndsGame ) - { - wait 5; - level.nukeVisionInProgress = undefined; - } - else - { - wait 3.5; - level notify ( "nuke_cancelled" ); - } -} - -nukeDeath() -{ - level endon ( "nuke_cancelled" ); - - level notify( "nuke_death" ); - - maps\mp\gametypes\_hostmigration::waitTillHostMigrationDone(); - - foreach( player in level.players ) - { - if(level.teamBased) - { - if ( !level.nukeKillsAll && level.nukeInfo.team == player.pers["team"] ) - continue; - } - else - { - if ( !level.nukeKillsAll && level.nukeInfo.player == player ) - continue; - } - - player.nuked = true; - - if ( isAlive( player ) ) - player thread maps\mp\gametypes\_damage::finishPlayerDamageWrapper( level.nukeInfo.player, level.nukeInfo.player, 999999, 0, "MOD_EXPLOSIVE", "nuke_mp", player.origin, player.origin, "none", 0, 0 ); - } - - if( level.NukeEndsGame ) - { - AmbientStop(1); - - level.postRoundTime = 10; - - if ( level.teamBased ) - thread maps\mp\gametypes\_gamelogic::endGame( level.nukeInfo.team, game["strings"]["nuclear_strike"], true ); - else - { - if ( isDefined( level.nukeInfo.player ) ) - thread maps\mp\gametypes\_gamelogic::endGame( level.nukeInfo.player, game["strings"]["nuclear_strike"], true ); - else - thread maps\mp\gametypes\_gamelogic::endGame( level.nukeInfo, game["strings"]["nuclear_strike"], true ); - } - } - else - { - wait 0.05; - - maps\mp\gametypes\_gamelogic::resumeTimer(); - level.timeLimitOverride = false; - level.scoreLimitOverride = false; - level notify( "update_scorelimit" ); - - //allow next nuke to be called in, reset nuke variables - level.nukeIncoming = undefined; - level.nukeDetonated = undefined; - - //allow ridable killstreaks - foreach(player in level.players) - player.nuked = undefined; - } -} - -nukeEarthquake() -{ - level endon ( "nuke_cancelled" ); - - level waittill( "nuke_death" ); - - // TODO: need to get a different position to call this on - //earthquake( 0.6, 10, nukepos, 100000 ); - - //foreach( player in level.players ) - //player PlayRumbleOnEntity( "damage_heavy" ); -} - - -waitForNukeCancel() -{ - self waittill( "cancel_location" ); - self setblurforplayer( 0, 0.3 ); -} - -endSelectionOn( waitfor ) -{ - self endon( "stop_location_selection" ); - self waittill( waitfor ); - self thread stopNukeLocationSelection( (waitfor == "disconnect") ); -} - -endSelectionOnGameEnd() -{ - self endon( "stop_location_selection" ); - level waittill( "game_ended" ); - self thread stopNukeLocationSelection( false ); -} - -stopNukeLocationSelection( disconnected ) -{ - if ( !disconnected ) - { - self setblurforplayer( 0, 0.3 ); - self endLocationSelection(); - self.selectingLocation = undefined; - } - self notify( "stop_location_selection" ); -} diff --git a/userraw/maps/mp/perks/_perkfunctions.gsc b/userraw/maps/mp/perks/_perkfunctions.gsc deleted file mode 100644 index 6a6d201..0000000 --- a/userraw/maps/mp/perks/_perkfunctions.gsc +++ /dev/null @@ -1,1089 +0,0 @@ -/******************************************************************* -// _perkfunctions.gsc -// -// Holds all the perk set/unset and listening functions -// -// Jordan Hirsh Sept. 11th 2008 -********************************************************************/ - -#include common_scripts\utility; -#include maps\mp\_utility; -#include maps\mp\gametypes\_hud_util; -#include maps\mp\perks\_perks; - - -blastshieldUseTracker( perkName, useFunc ) -{ - self endon ( "death" ); - self endon ( "disconnect" ); - self endon ( "end_perkUseTracker" ); - level endon ( "game_ended" ); - - for ( ;; ) - { - self waittill ( "empty_offhand" ); - - if ( !isOffhandWeaponEnabled() ) - continue; - - self [[useFunc]]( self _hasPerk( "_specialty_blastshield" ) ); - } -} - -perkUseDeathTracker() -{ - self endon ( "disconnect" ); - - self waittill("death"); - self._usePerkEnabled = undefined; -} - -setRearView() -{ - //self thread perkUseTracker( "specialty_rearview", ::toggleRearView ); -} - -unsetRearView() -{ - self notify ( "end_perkUseTracker" ); -} - -toggleRearView( isEnabled ) -{ - if ( isEnabled ) - { - self _setPerk( "_specialty_rearview" ); - self SetRearViewRenderEnabled(true); - } - else - { - self _unsetPerk( "_specialty_rearview" ); - self SetRearViewRenderEnabled(false); - } -} - - -setEndGame() -{ - if ( isdefined( self.endGame ) ) - return; - - self.maxhealth = ( maps\mp\gametypes\_tweakables::getTweakableValue( "player", "maxhealth" ) * 4 ); - self.health = self.maxhealth; - self.endGame = true; - self.attackerTable[0] = ""; - self visionSetNakedForPlayer("end_game", 5 ); - self thread endGameDeath( 7 ); - self.hasDoneCombat = true; -} - - -unsetEndGame() -{ - self notify( "stopEndGame" ); - self.endGame = undefined; - revertVisionSet(); - - if (! isDefined( self.endGameTimer ) ) - return; - - self.endGameTimer destroyElem(); - self.endGameIcon destroyElem(); -} - - -revertVisionSet() -{ - self VisionSetNakedForPlayer( getDvar( "mapname" ), 1 ); -} - -endGameDeath( duration ) -{ - self endon( "death" ); - self endon( "disconnect" ); - self endon( "joined_team" ); - level endon( "game_ended" ); - self endon( "stopEndGame" ); - - wait( duration + 1 ); - //self visionSetNakedForPlayer("end_game2", 1 ); - //wait(1); - self _suicide(); -} - -setCombatHigh() -{ - self endon( "death" ); - self endon( "disconnect" ); - self endon( "unset_combathigh" ); - level endon( "end_game" ); - - self.damageBlockedTotal = 0; - if (level.combathighIsJuiced) - { - self.moveSpeedScaler = 1.25; - self maps\mp\gametypes\_weapons::updateMoveSpeedScale( "primary" ); - } - //self visionSetNakedForPlayer( "end_game", 1 ); - - if ( level.splitscreen ) - { - yOffset = 56; - iconSize = 21; // 32/1.5 - } - else - { - yOffset = 112; - iconSize = 32; - } - - self.combatHighOverlay = newClientHudElem( self ); - self.combatHighOverlay.x = 0; - self.combatHighOverlay.y = 0; - self.combatHighOverlay.alignX = "left"; - self.combatHighOverlay.alignY = "top"; - self.combatHighOverlay.horzAlign = "fullscreen"; - self.combatHighOverlay.vertAlign = "fullscreen"; - self.combatHighOverlay setshader ( "combathigh_overlay", 640, 480 ); - self.combatHighOverlay.sort = -10; - self.combatHighOverlay.archived = true; - - self.combatHighTimer = createTimer( "hudsmall", 1.0 ); - self.combatHighTimer setPoint( "CENTER", "CENTER", 0, yOffset ); - if (level.combathighIsJuiced) - self.combatHighTimer setTimer( 7.0 ); - else - self.combatHighTimer setTimer( 10.0 ); - - self.combatHighTimer.color = (.8,.8,0); - self.combatHighTimer.archived = false; - self.combatHighTimer.foreground = true; - - self.combatHighIcon = self createIcon( "specialty_painkiller", iconSize, iconSize ); - self.combatHighIcon.alpha = 0; - self.combatHighIcon setParent( self.combatHighTimer ); - self.combatHighIcon setPoint( "BOTTOM", "TOP" ); - self.combatHighIcon.archived = true; - self.combatHighIcon.sort = 1; - self.combatHighIcon.foreground = true; - - self.combatHighOverlay.alpha = 0.0; - self.combatHighOverlay fadeOverTime( 1.0 ); - self.combatHighIcon fadeOverTime( 1.0 ); - self.combatHighOverlay.alpha = 1.0; - self.combatHighIcon.alpha = 0.85; - - self thread unsetCombatHighOnDeath(); - - if (level.combathighIsJuiced) - wait( 5 ); - else - wait( 8 ); - - self.combatHighIcon fadeOverTime( 2.0 ); - self.combatHighIcon.alpha = 0.0; - - self.combatHighOverlay fadeOverTime( 2.0 ); - self.combatHighOverlay.alpha = 0.0; - - self.combatHighTimer fadeOverTime( 2.0 ); - self.combatHighTimer.alpha = 0.0; - - wait( 2 ); - self.damageBlockedTotal = undefined; - - if (level.combathighIsJuiced) - { - self.moveSpeedScaler = 1; - - if (self _hasperk( "specialty_lightweight" )) - { - self.moveSpeedScaler = 1.07; - } - - self maps\mp\gametypes\_weapons::updateMoveSpeedScale( "primary" ); - } - - self _unsetPerk( "specialty_combathigh" ); -} - -unsetCombatHighOnDeath() -{ - self endon ( "disconnect" ); - self endon ( "unset_combathigh" ); - - self waittill ( "death" ); - - if (level.combathighIsJuiced) - { - self.moveSpeedScaler = 1; - - if (self _hasperk( "specialty_lightweight" )) - { - self.moveSpeedScaler = 1.07; - } - } - - self thread _unsetPerk( "specialty_combathigh" ); -} - -unsetCombatHigh() -{ - self notify ( "unset_combathigh" ); - self.combatHighOverlay destroy(); - self.combatHighIcon destroy(); - self.combatHighTimer destroy(); - - if (level.combathighIsJuiced) - { - self.moveSpeedScaler = 1; - - if (self _hasperk( "specialty_lightweight" )) - { - self.moveSpeedScaler = 1.07; - } - } -} - -setSiege() -{ - self thread trackSiegeEnable(); - self thread trackSiegeDissable(); -} - -trackSiegeEnable() -{ - self endon ( "death" ); - self endon ( "disconnect" ); - self endon ( "stop_trackSiege" ); - - for ( ;; ) - { - self waittill ( "gambit_on" ); - - //self setStance( "crouch" ); - //self thread stanceStateListener(); - //self thread jumpStateListener(); - self.moveSpeedScaler = 0; - self maps\mp\gametypes\_weapons::updateMoveSpeedScale( "primary" ); - class = weaponClass( self getCurrentWeapon() ); - - if ( class == "pistol" || class == "smg" ) - self setSpreadOverride( 1 ); - else - self setSpreadOverride( 2 ); - - self player_recoilScaleOn( 0 ); - self allowJump(false); - } -} - -trackSiegeDissable() -{ - self endon ( "death" ); - self endon ( "disconnect" ); - self endon ( "stop_trackSiege" ); - - for ( ;; ) - { - self waittill ( "gambit_off" ); - - unsetSiege(); - } -} - -stanceStateListener() -{ - self endon ( "death" ); - self endon ( "disconnect" ); - - self notifyOnPlayerCommand( "adjustedStance", "+stance" ); - - for ( ;; ) - { - self waittill( "adjustedStance" ); - if ( self.moveSPeedScaler != 0 ) - continue; - - unsetSiege(); - } -} - -jumpStateListener() -{ - self endon ( "death" ); - self endon ( "disconnect" ); - - self notifyOnPlayerCommand( "jumped", "+goStand" ); - - for ( ;; ) - { - self waittill( "jumped" ); - if ( self.moveSPeedScaler != 0 ) - continue; - - unsetSiege(); - } -} - -unsetSiege() -{ - self.moveSpeedScaler = 1; - //if siege is not cut add check to see if - //using lightweight and siege for movespeed scaler - self resetSpreadOverride(); - self maps\mp\gametypes\_weapons::updateMoveSpeedScale( "primary" ); - self player_recoilScaleOff(); - self allowJump(true); -} - - -setFinalStand() -{ - self _setperk( "specialty_pistoldeath"); -} - -unsetFinalStand() -{ - self _unsetperk( "specialty_pistoldeath" ); -} - - -setChallenger() -{ - if ( !level.hardcoreMode ) - { - self.maxhealth = maps\mp\gametypes\_tweakables::getTweakableValue( "player", "maxhealth" ); - - if ( isDefined( self.xpScaler ) && self.xpScaler == 1 && self.maxhealth > 30 ) - { - self.xpScaler = 2; - } - } -} - -unsetChallenger() -{ - self.xpScaler = 1; -} - - -setSaboteur() -{ - self.objectiveScaler = 1.2; -} - -unsetSaboteur() -{ - self.objectiveScaler = 1; -} - - -setLightWeight() -{ - self.moveSpeedScaler = 1.07; - - if (level.combathighIsJuiced) - { - if (self _hasperk( "specialty_combathigh" )) - { - self.moveSpeedScaler = 1.4; - } - } - - self maps\mp\gametypes\_weapons::updateMoveSpeedScale( "primary" ); -} - -unsetLightWeight() -{ - self.moveSpeedScaler = 1; - self maps\mp\gametypes\_weapons::updateMoveSpeedScale( "primary" ); -} - - -setBlackBox() -{ - self.killStreakScaler = 1.5; -} - -unsetBlackBox() -{ - self.killStreakScaler = 1; -} - -setSteelNerves() -{ - self _setperk( "specialty_bulletaccuracy" ); - self _setperk( "specialty_holdbreath" ); -} - -unsetSteelNerves() -{ - self _unsetperk( "specialty_bulletaccuracy" ); - self _unsetperk( "specialty_holdbreath" ); -} - -setDelayMine() -{ -} - -unsetDelayMine() -{ -} - - -setBackShield() -{ - self AttachShieldModel( "weapon_riot_shield_mp", "tag_shield_back" ); -} - - -unsetBackShield() -{ - self DetachShieldModel( "weapon_riot_shield_mp", "tag_shield_back" ); -} - - -setLocalJammer() -{ - if ( !self isEMPed() ) - self RadarJamOn(); -} - - -unsetLocalJammer() -{ - self RadarJamOff(); -} - - -setAC130() -{ - self thread killstreakThink( "ac130", 7, "end_ac130Think" ); -} - -unsetAC130() -{ - self notify ( "end_ac130Think" ); -} - - -setSentryMinigun() -{ - self thread killstreakThink( "airdrop_sentry_minigun", 2, "end_sentry_minigunThink" ); -} - -unsetSentryMinigun() -{ - self notify ( "end_sentry_minigunThink" ); -} - -setCarePackage() -{ - self thread killstreakThink( "airdrop", 2, "endCarePackageThink" ); -} - -unsetCarePackage() -{ - self notify ( "endCarePackageThink" ); -} - -setTank() -{ - self thread killstreakThink( "tank", 6, "end_tankThink" ); -} - -unsetTank() -{ - self notify ( "end_tankThink" ); -} - -setPrecision_airstrike() -{ - println( "!precision airstrike!" ); - self thread killstreakThink( "precision_airstrike", 6, "end_precision_airstrike" ); -} - -unsetPrecision_airstrike() -{ - self notify ( "end_precision_airstrike" ); -} - -setPredatorMissile() -{ - self thread killstreakThink( "predator_missile", 4, "end_predator_missileThink" ); -} - -unsetPredatorMissile() -{ - self notify ( "end_predator_missileThink" ); -} - - -setHelicopterMinigun() -{ - self thread killstreakThink( "helicopter_minigun", 5, "end_helicopter_minigunThink" ); -} - -unsetHelicopterMinigun() -{ - self notify ( "end_helicopter_minigunThink" ); -} - - - -killstreakThink( streakName, streakVal, endonString ) -{ - self endon ( "death" ); - self endon ( "disconnect" ); - self endon ( endonString ); - - for ( ;; ) - { - self waittill ( "killed_enemy" ); - - if ( self.pers["cur_kill_streak"] != streakVal ) - continue; - - self thread maps\mp\killstreaks\_killstreaks::giveKillstreak( streakName ); - self thread maps\mp\gametypes\_hud_message::killstreakSplashNotify( streakName, streakVal ); - return; - } -} - - -setThermal() -{ - self ThermalVisionOn(); -} - - -unsetThermal() -{ - self ThermalVisionOff(); -} - - -setOneManArmy() -{ - self thread oneManArmyWeaponChangeTracker(); -} - - -unsetOneManArmy() -{ - self notify ( "stop_oneManArmyTracker" ); -} - - -oneManArmyWeaponChangeTracker() -{ - self endon ( "death" ); - self endon ( "disconnect" ); - level endon ( "game_ended" ); - self endon ( "stop_oneManArmyTracker" ); - - for ( ;; ) - { - self waittill( "weapon_change", newWeapon ); - - if ( newWeapon != "onemanarmy_mp" ) - continue; - - //if ( self isUsingRemote() ) - // continue; - - self thread selectOneManArmyClass(); - } -} - - -isOneManArmyMenu( menu ) -{ - if ( menu == game["menu_onemanarmy"] ) - return true; - - if ( isDefined( game["menu_onemanarmy_defaults_splitscreen"] ) && menu == game["menu_onemanarmy_defaults_splitscreen"] ) - return true; - - if ( isDefined( game["menu_onemanarmy_custom_splitscreen"] ) && menu == game["menu_onemanarmy_custom_splitscreen"] ) - return true; - - return false; -} - - -selectOneManArmyClass() -{ - self endon ( "death" ); - self endon ( "disconnect" ); - level endon ( "game_ended" ); - - self _disableWeaponSwitch(); - self _disableOffhandWeapons(); - self _disableUsability(); - - self openPopupMenu( game["menu_onemanarmy"] ); - - self thread closeOMAMenuOnDeath(); - - self waittill ( "menuresponse", menu, className ); - - self _enableWeaponSwitch(); - self _enableOffhandWeapons(); - self _enableUsability(); - - if ( className == "back" || !isOneManArmyMenu( menu ) || self isUsingRemote() ) - { - if ( self getCurrentWeapon() == "onemanarmy_mp" ) - { - self _disableWeaponSwitch(); - self _disableOffhandWeapons(); - self _disableUsability(); - self switchToWeapon( self getLastWeapon() ); - self waittill ( "weapon_change" ); - self _enableWeaponSwitch(); - self _enableOffhandWeapons(); - self _enableUsability(); - } - return; - } - - self thread giveOneManArmyClass( className ); -} - -closeOMAMenuOnDeath() -{ - self endon ( "menuresponse" ); - self endon ( "disconnect" ); - level endon ( "game_ended" ); - - self waittill ( "death" ); - - self _enableWeaponSwitch(); - self _enableOffhandWeapons(); - self _enableUsability(); - - self closePopupMenu(); -} - -giveOneManArmyClass( className ) -{ - self endon ( "death" ); - self endon ( "disconnect" ); - level endon ( "game_ended" ); - - if ( self _hasPerk( "specialty_omaquickchange" ) ) - { - changeDuration = 3.0; - self playLocalSound( "foly_onemanarmy_bag3_plr" ); - self playSoundToTeam( "foly_onemanarmy_bag3_npc", "allies", self ); - self playSoundToTeam( "foly_onemanarmy_bag3_npc", "axis", self ); - } - else - { - changeDuration = 6.0; - self playLocalSound( "foly_onemanarmy_bag6_plr" ); - self playSoundToTeam( "foly_onemanarmy_bag6_npc", "allies", self ); - self playSoundToTeam( "foly_onemanarmy_bag6_npc", "axis", self ); - } - - self thread omaUseBar( changeDuration ); - - self _disableWeapon(); - self _disableOffhandWeapons(); - self _disableUsability(); - - wait ( changeDuration ); - - self _enableWeapon(); - self _enableOffhandWeapons(); - self _enableUsability(); - - self.OMAClassChanged = true; - - self maps\mp\gametypes\_class::giveLoadout( self.pers["team"], className, false ); - - // handle the fact that detachAll in giveLoadout removed the CTF flag from our back - // it would probably be better to handle this in _detachAll itself, but this is a safety fix - if ( isDefined( self.carryFlag ) ) - self attach( self.carryFlag, "J_spine4", true ); - - self notify ( "changed_kit" ); - level notify ( "changed_kit" ); - - if (level.onemanarmyRefillsTubes) - return; - - weaponNameSize = self getCurrentWeapon().size; - - if( getSubStr( self getCurrentWeapon(), weaponNameSize - 6, weaponNameSize ) == "_gl_mp" ) - { - weaponName = "gl_" + getSubStr( self getCurrentWeapon(), 0, weaponNameSize - 6 ) + "_mp"; - self setWeaponAmmoClip( weaponName, 0 ); - self setWeaponAmmoStock( weaponName, 0 ); - } -} - - -omaUseBar( duration ) -{ - self endon( "disconnect" ); - - useBar = createPrimaryProgressBar( 25 ); - useBarText = createPrimaryProgressBarText( 25 ); - useBarText setText( &"MPUI_CHANGING_KIT" ); - - useBar updateBar( 0, 1 / duration ); - for ( waitedTime = 0; waitedTime < duration && isAlive( self ) && !level.gameEnded; waitedTime += 0.05 ) - wait ( 0.05 ); - - useBar destroyElem(); - useBarText destroyElem(); -} - - -setBlastShield() -{ - self thread blastshieldUseTracker( "specialty_blastshield", ::toggleBlastShield ); - self SetWeaponHudIconOverride( "primaryoffhand", "specialty_blastshield" ); -} - - -unsetBlastShield() -{ - self notify ( "end_perkUseTracker" ); - self SetWeaponHudIconOverride( "primaryoffhand", "none" ); -} - -toggleBlastShield( isEnabled ) -{ - if ( !isEnabled ) - { - self VisionSetNakedForPlayer( "black_bw", 0.15 ); - wait ( 0.15 ); - self _setPerk( "_specialty_blastshield" ); - self VisionSetNakedForPlayer( getDvar( "mapname" ), 0 ); - self playSoundToPlayer( "item_blast_shield_on", self ); - } - else - { - self VisionSetNakedForPlayer( "black_bw", 0.15 ); - wait ( 0.15 ); - self _unsetPerk( "_specialty_blastshield" ); - self VisionSetNakedForPlayer( getDvar( "mapname" ), 0 ); - self playSoundToPlayer( "item_blast_shield_off", self ); - } -} - - -setFreefall() -{ - //eventually set a listener to do a roll when falling damage is taken -} - -unsetFreefall() -{ -} - - -setTacticalInsertion() -{ - self _giveWeapon( "flare_mp", 0 ); - self giveStartAmmo( "flare_mp" ); - - self thread monitorTIUse(); -} - -unsetTacticalInsertion() -{ - self notify( "end_monitorTIUse" ); -} - -clearPreviousTISpawnpoint() -{ - self waittill_any ( "disconnect", "joined_team", "joined_spectators" ); - - if ( isDefined ( self.setSpawnpoint ) ) - self deleteTI( self.setSpawnpoint ); -} - -updateTISpawnPosition() -{ - self endon ( "death" ); - self endon ( "disconnect" ); - level endon ( "game_ended" ); - self endon ( "end_monitorTIUse" ); - - while ( isReallyAlive( self ) ) - { - if ( self isValidTISpawnPosition() ) - self.TISpawnPosition = self.origin; - - wait ( 0.05 ); - } -} - -isValidTISpawnPosition() -{ - if ( CanSpawn( self.origin ) && self IsOnGround() ) - return true; - else - return false; -} - -monitorTIUse() -{ - self endon ( "death" ); - self endon ( "disconnect" ); - level endon ( "game_ended" ); - self endon ( "end_monitorTIUse" ); - - self thread updateTISpawnPosition(); - self thread clearPreviousTISpawnpoint(); - - for ( ;; ) - { - self waittill( "grenade_fire", lightstick, weapName ); - - if ( weapName != "flare_mp" ) - continue; - - //lightstick delete(); - - if ( isDefined( self.setSpawnPoint ) ) - self deleteTI( self.setSpawnPoint ); - - if ( !isDefined( self.TISpawnPosition ) ) - continue; - - if ( self touchingBadTrigger() ) - continue; - - TIGroundPosition = playerPhysicsTrace( self.TISpawnPosition + (0,0,16), self.TISpawnPosition - (0,0,2048) ) + (0,0,1); - - glowStick = spawn( "script_model", TIGroundPosition ); - glowStick.angles = self.angles; - glowStick.team = self.team; - glowStick.enemyTrigger = spawn( "script_origin", TIGroundPosition ); - glowStick thread GlowStickSetupAndWaitForDeath( self ); - glowStick.playerSpawnPos = self.TISpawnPosition; - - glowStick thread maps\mp\gametypes\_weapons::createBombSquadModel( "weapon_light_stick_tactical_bombsquad", "tag_fire_fx", level.otherTeam[self.team], self ); - - self.setSpawnPoint = glowStick; - return; - } -} - - -GlowStickSetupAndWaitForDeath( owner ) -{ - self setModel( level.spawnGlowModel["enemy"] ); - if ( level.teamBased ) - self maps\mp\_entityheadIcons::setTeamHeadIcon( self.team , (0,0,20) ); - else - self maps\mp\_entityheadicons::setPlayerHeadIcon( owner, (0,0,20) ); - - self thread GlowStickDamageListener( owner ); - self thread GlowStickEnemyUseListener( owner ); - self thread GlowStickUseListener( owner ); - self thread GlowStickTeamUpdater( level.otherTeam[self.team], level.spawnGlow["enemy"], owner ); - - dummyGlowStick = spawn( "script_model", self.origin+ (0,0,0) ); - dummyGlowStick.angles = self.angles; - dummyGlowStick setModel( level.spawnGlowModel["friendly"] ); - dummyGlowStick setContents( 0 ); - dummyGlowStick thread GlowStickTeamUpdater( self.team, level.spawnGlow["friendly"], owner ); - - dummyGlowStick playLoopSound( "emt_road_flare_burn" ); - - self waittill ( "death" ); - - dummyGlowStick stopLoopSound(); - dummyGlowStick delete(); -} - - -GlowStickTeamUpdater( showForTeam, showEffect, owner ) -{ - self endon ( "death" ); - - // PlayFXOnTag fails if run on the same frame the parent entity was created - wait ( 0.05 ); - - //PlayFXOnTag( showEffect, self, "TAG_FX" ); - angles = self getTagAngles( "tag_fire_fx" ); - fxEnt = SpawnFx( showEffect, self getTagOrigin( "tag_fire_fx" ), anglesToForward( angles ), anglesToUp( angles ) ); - TriggerFx( fxEnt ); - - self thread deleteOnDeath( fxEnt ); - - for ( ;; ) - { - self hide(); - fxEnt hide(); - foreach ( player in level.players ) - { - if ( player.team == showForTeam && level.teamBased ) - { - self showToPlayer( player ); - fxEnt showToPlayer( player ); - } - else if ( !level.teamBased && player == owner && showEffect == level.spawnGlow["friendly"] ) - { - self showToPlayer( player ); - fxEnt showToPlayer( player ); - } - else if ( !level.teamBased && player != owner && showEffect == level.spawnGlow["enemy"] ) - { - self showToPlayer( player ); - fxEnt showToPlayer( player ); - } - } - - level waittill_either ( "joined_team", "player_spawned" ); - } -} - -deleteOnDeath( ent ) -{ - self waittill( "death" ); - if ( isdefined( ent ) ) - ent delete(); -} - -GlowStickDamageListener( owner ) -{ - self endon ( "death" ); - - self setCanDamage( true ); - // use large health to work around teamkilling issue - self.health = 5000; - - for ( ;; ) - { - self waittill ( "damage", amount, attacker ); - - if ( level.teambased && isDefined( owner ) && attacker != owner && ( isDefined( attacker.team ) && attacker.team == self.team ) ) - { - self.health += amount; - continue; - } - - if ( self.health < (5000-20) ) - { - if ( isDefined( owner ) && attacker != owner ) - { - attacker notify ( "destroyed_insertion", owner ); - attacker notify( "destroyed_explosive" ); // count towards SitRep Pro challenge - owner thread leaderDialogOnPlayer( "ti_destroyed" ); - } - - attacker thread deleteTI( self ); - } - } -} - -GlowStickUseListener( owner ) -{ - self endon ( "death" ); - level endon ( "game_ended" ); - owner endon ( "disconnect" ); - - self setCursorHint( "HINT_NOICON" ); - self setHintString( &"MP_PICKUP_TI" ); - - self thread updateEnemyUse( owner ); - - for ( ;; ) - { - self waittill ( "trigger", player ); - - player playSound( "chemlight_pu" ); - player thread setTacticalInsertion(); - player thread deleteTI( self ); - } -} - -updateEnemyUse( owner ) -{ - self endon ( "death" ); - - for ( ;; ) - { - self setSelfUsable( owner ); - level waittill_either ( "joined_team", "player_spawned" ); - } -} - -deleteTI( TI ) -{ - if (isDefined( TI.enemyTrigger ) ) - TI.enemyTrigger Delete(); - - spot = TI.origin; - spotAngles = TI.angles; - - TI Delete(); - - dummyGlowStick = spawn( "script_model", spot ); - dummyGlowStick.angles = spotAngles; - dummyGlowStick setModel( level.spawnGlowModel["friendly"] ); - - dummyGlowStick setContents( 0 ); - thread dummyGlowStickDelete( dummyGlowStick ); -} - -dummyGlowStickDelete( stick ) -{ - wait(2.5); - stick Delete(); -} - -GlowStickEnemyUseListener( owner ) -{ - self endon ( "death" ); - level endon ( "game_ended" ); - owner endon ( "disconnect" ); - - self.enemyTrigger setCursorHint( "HINT_NOICON" ); - self.enemyTrigger setHintString( &"MP_DESTROY_TI" ); - self.enemyTrigger makeEnemyUsable( owner ); - - for ( ;; ) - { - self.enemyTrigger waittill ( "trigger", player ); - - player notify ( "destroyed_insertion", owner ); - player notify( "destroyed_explosive" ); // count towards SitRep Pro challenge - - //playFX( level.spawnGlowSplat, self.origin); - - if ( isDefined( owner ) && player != owner ) - owner thread leaderDialogOnPlayer( "ti_destroyed" ); - - player thread deleteTI( self ); - } -} - -setLittlebirdSupport() -{ - self thread killstreakThink( "littlebird_support", 2, "end_littlebird_support_think" ); -} - -unsetLittlebirdSupport() -{ - self notify ( "end_littlebird_support_think" ); -} - -setC4Death() -{ - if ( ! self _hasperk( "specialty_pistoldeath" ) ) - self _setperk( "specialty_pistoldeath"); -} - -unsetC4Death() -{ - -} \ No newline at end of file diff --git a/userraw/maps/mp/perks/_perks.gsc b/userraw/maps/mp/perks/_perks.gsc deleted file mode 100644 index e6181d4..0000000 --- a/userraw/maps/mp/perks/_perks.gsc +++ /dev/null @@ -1,406 +0,0 @@ -#include common_scripts\utility; -#include maps\mp\_utility; -#include maps\mp\gametypes\_hud_util; -#include maps\mp\perks\_perkfunctions; - -init() -{ - level.perkFuncs = []; - - precacheShader( "combathigh_overlay" ); - precacheShader( "specialty_painkiller" ); - - precacheModel( "weapon_riot_shield_mp" ); - precacheModel( "viewmodel_riot_shield_mp" ); - precacheString( &"MPUI_CHANGING_KIT" ); - - //level.spawnGlowSplat = loadfx( "misc/flare_ambient_destroy" ); - - level.spawnGlowModel["enemy"] = "mil_emergency_flare_mp"; - level.spawnGlowModel["friendly"] = "mil_emergency_flare_mp"; - level.spawnGlow["enemy"] = loadfx( "misc/flare_ambient" ); - level.spawnGlow["friendly"] = loadfx( "misc/flare_ambient_green" ); - level.c4Death = loadfx( "explosions/oxygen_tank_explosion" ); - - level.spawnFire = loadfx( "props/barrelexp" ); - - precacheModel( level.spawnGlowModel["friendly"] ); - precacheModel( level.spawnGlowModel["enemy"] ); - - precacheString( &"MP_DESTROY_TI" ); - - precacheShaders(); - - level._effect["ricochet"] = loadfx( "impacts/large_metalhit_1" ); - - // perks that currently only exist in script: these will error if passed to "setPerk", etc... CASE SENSITIVE! must be lower - level.scriptPerks = []; - level.perkSetFuncs = []; - level.perkUnsetFuncs = []; - level.fauxPerks = []; - - level.scriptPerks["specialty_blastshield"] = true; - level.scriptPerks["_specialty_blastshield"] = true; - level.scriptPerks["specialty_akimbo"] = true; - level.scriptPerks["specialty_siege"] = true; - level.scriptPerks["specialty_falldamage"] = true; - level.scriptPerks["specialty_fmj"] = true; - level.scriptPerks["specialty_shield"] = true; - level.scriptPerks["specialty_feigndeath"] = true; - level.scriptPerks["specialty_shellshock"] = true; - level.scriptPerks["specialty_delaymine"] = true; - level.scriptPerks["specialty_localjammer"] = true; - level.scriptPerks["specialty_thermal"] = true; - level.scriptPerks["specialty_finalstand"] = true; - level.scriptPerks["specialty_blackbox"] = true; - level.scriptPerks["specialty_steelnerves"] = true; - level.scriptPerks["specialty_flashgrenade"] = true; - level.scriptPerks["specialty_smokegrenade"] = true; - level.scriptPerks["specialty_concussiongrenade"] = true; - level.scriptPerks["specialty_challenger"] = true; - level.scriptPerks["specialty_tacticalinsertion"] = true; - level.scriptPerks["specialty_saboteur"] = true; - level.scriptPerks["specialty_endgame"] = true; - level.scriptPerks["specialty_rearview"] = true; - level.scriptPerks["specialty_hardline"] = true; - level.scriptPerks["specialty_ac130"] = true; - level.scriptPerks["specialty_sentry_minigun"] = true; - level.scriptPerks["specialty_predator_missile"] = true; - level.scriptPerks["specialty_helicopter_minigun"] = true; - level.scriptPerks["specialty_tank"] = true; - level.scriptPerks["specialty_precision_airstrike"] = true; - level.scriptPerks["specialty_bling"] = true; - level.scriptPerks["specialty_carepackage"] = true; - level.scriptPerks["specialty_onemanarmy"] = true; - level.scriptPerks["specialty_littlebird_support"] = true; - level.scriptPerks["specialty_primarydeath"] = true; - level.scriptPerks["specialty_secondarybling"] = true; - level.scriptPerks["specialty_combathigh"] = true; - level.scriptPerks["specialty_c4death"] = true; - level.scriptPerks["specialty_explosivedamage"] = true; - level.scriptPerks["specialty_copycat"] = true; - level.scriptPerks["specialty_laststandoffhand"] = true; - level.scriptPerks["specialty_dangerclose"] = true; - - level.scriptPerks["specialty_extraspecialduration"] = true; - level.scriptPerks["specialty_rollover"] = true; - level.scriptPerks["specialty_armorpiercing"] = true; - level.scriptPerks["specialty_omaquickchange"] = true; - level.scriptPerks["specialty_fastmeleerecovery"] = true; - - level.scriptPerks["_specialty_rearview"] = true; - level.scriptPerks["_specialty_onemanarmy"] = true; - - level.fauxPerks["specialty_tacticalinsertion"] = true; - level.fauxPerks["specialty_shield"] = true; - - - /* - level.perkSetFuncs[""] = ::; - level.perkUnsetFuncs[""] = ::; - */ - - level.perkSetFuncs["specialty_blastshield"] = ::setBlastShield; - level.perkUnsetFuncs["specialty_blastshield"] = ::unsetBlastShield; - - level.perkSetFuncs["specialty_siege"] = ::setSiege; - level.perkUnsetFuncs["specialty_siege"] = ::unsetSiege; - - level.perkSetFuncs["specialty_falldamage"] = ::setFreefall; - level.perkUnsetFuncs["specialty_falldamage"] = ::unsetFreefall; - - level.perkSetFuncs["specialty_localjammer"] = ::setLocalJammer; - level.perkUnsetFuncs["specialty_localjammer"] = ::unsetLocalJammer; - - level.perkSetFuncs["specialty_thermal"] = ::setThermal; - level.perkUnsetFuncs["specialty_thermal"] = ::unsetThermal; - - level.perkSetFuncs["specialty_blackbox"] = ::setBlackBox; - level.perkUnsetFuncs["specialty_blackbox"] = ::unsetBlackBox; - - level.perkSetFuncs["specialty_lightweight"] = ::setLightWeight; - level.perkUnsetFuncs["specialty_lightweight"] = ::unsetLightWeight; - - level.perkSetFuncs["specialty_steelnerves"] = ::setSteelNerves; - level.perkUnsetFuncs["specialty_steelnerves"] = ::unsetSteelNerves; - - level.perkSetFuncs["specialty_delaymine"] = ::setDelayMine; - level.perkUnsetFuncs["specialty_delaymine"] = ::unsetDelayMine; - - level.perkSetFuncs["specialty_finalstand"] = ::setFinalStand; - level.perkUnsetFuncs["specialty_finalstand"] = ::unsetFinalStand; - - level.perkSetFuncs["specialty_combathigh"] = ::setCombatHigh; - level.perkUnsetFuncs["specialty_combathigh"] = ::unsetCombatHigh; - - level.perkSetFuncs["specialty_challenger"] = ::setChallenger; - level.perkUnsetFuncs["specialty_challenger"] = ::unsetChallenger; - - level.perkSetFuncs["specialty_saboteur"] = ::setSaboteur; - level.perkUnsetFuncs["specialty_saboteur"] = ::unsetSaboteur; - - level.perkSetFuncs["specialty_endgame"] = ::setEndGame; - level.perkUnsetFuncs["specialty_endgame"] = ::unsetEndGame; - - level.perkSetFuncs["specialty_rearview"] = ::setRearView; - level.perkUnsetFuncs["specialty_rearview"] = ::unsetRearView; - - level.perkSetFuncs["specialty_ac130"] = ::setAC130; - level.perkUnsetFuncs["specialty_ac130"] = ::unsetAC130; - - level.perkSetFuncs["specialty_sentry_minigun"] = ::setSentryMinigun; - level.perkUnsetFuncs["specialty_sentry_minigun"] = ::unsetSentryMinigun; - - level.perkSetFuncs["specialty_predator_missile"] = ::setPredatorMissile; - level.perkUnsetFuncs["specialty_predator_missile"] = ::unsetPredatorMissile; - - level.perkSetFuncs["specialty_tank"] = ::setTank; - level.perkUnsetFuncs["specialty_tank"] = ::unsetTank; - - level.perkSetFuncs["specialty_precision_airstrike"] = ::setPrecision_airstrike; - level.perkUnsetFuncs["specialty_precision_airstrike"] = ::unsetPrecision_airstrike; - - level.perkSetFuncs["specialty_helicopter_minigun"] = ::setHelicopterMinigun; - level.perkUnsetFuncs["specialty_helicopter_minigun"] = ::unsetHelicopterMinigun; - - level.perkSetFuncs["specialty_carepackage"] = ::setCarePackage; - level.perkUnsetFuncs["specialty_carepackage"] = ::unsetCarePackage; - - level.perkSetFuncs["specialty_onemanarmy"] = ::setOneManArmy; - level.perkUnsetFuncs["specialty_onemanarmy"] = ::unsetOneManArmy; - - level.perkSetFuncs["specialty_littlebird_support"] = ::setLittlebirdSupport; - level.perkUnsetFuncs["specialty_littlebird_support"] = ::unsetLittlebirdSupport; - - level.perkSetFuncs["specialty_c4death"] = ::setC4Death; - level.perkUnsetFuncs["specialty_c4death"] = ::unsetC4Death; - - level.perkSetFuncs["specialty_tacticalinsertion"] = ::setTacticalInsertion; - level.perkUnsetFuncs["specialty_tacticalinsertion"] = ::unsetTacticalInsertion; - - setDvarIfUninitialized( "combathighIsJuiced", true ); - level.combathighIsJuiced = getDvarInt( "combathighIsJuiced" ); - - setDvarIfUninitialized( "onemanarmyRefillsTubes", false ); - level.onemanarmyRefillsTubes = getDvarInt( "onemanarmyRefillsTubes" ); - - initPerkDvars(); - - level thread onPlayerConnect(); -} - - - -precacheShaders() -{ - precacheShader( "specialty_blastshield" ); -} - - -givePerk( perkName ) -{ - if ( IsSubStr( perkName, "_mp" ) ) - { - if ( perkName == "frag_grenade_mp" ) - self SetOffhandPrimaryClass( "frag" ); - if ( perkName == "throwingknife_mp" ) - self SetOffhandPrimaryClass( "throwingknife" ); - - self _giveWeapon( perkName, 0 ); - self giveStartAmmo( perkName ); - - self setPerk( perkName, false ); - return; - } - - if ( isSubStr( perkName, "specialty_null" ) || isSubStr( perkName, "specialty_weapon_" ) ) - { - self setPerk( perkName, false ); - return; - } - - self _setPerk( perkName ); - -} - - -validatePerk( perkIndex, perkName ) -{ - if ( getDvarInt ( "scr_game_perks" ) == 0 ) - { - if ( tableLookup( "mp/perkTable.csv", 1, perkName, 5 ) != "equipment" ) - return "specialty_null"; - } - - /* Validation disabled for now - if ( tableLookup( "mp/perkTable.csv", 1, perkName, 5 ) != ("perk"+perkIndex) ) - { - println( "^1Warning: (" + self.name + ") Perk " + perkName + " is not allowed for perk slot index " + perkIndex + "; replacing with no perk" ); - return "specialty_null"; - } - */ - - return perkName; -} - - -onPlayerConnect() -{ - for(;;) - { - level waittill( "connected", player ); - player thread onPlayerSpawned(); - } -} - - -onPlayerSpawned() -{ - self endon( "disconnect" ); - - self.perks = []; - self.weaponList = []; - self.omaClassChanged = false; - - for( ;; ) - { - self waittill( "spawned_player" ); - - self.omaClassChanged = false; - self thread gambitUseTracker(); - } -} - - -drawLine( start, end, timeSlice ) -{ - drawTime = int(timeSlice * 20); - for( time = 0; time < drawTime; time++ ) - { - line( start, end, (1,0,0),false, 1 ); - wait ( 0.05 ); - } -} - - -cac_modified_damage( victim, attacker, damage, meansofdeath, weapon, impactPoint, impactDir, hitLoc ) -{ - assert( isPlayer( victim ) ); - assert( isDefined( victim.team ) ); - - damageAdd = 0; - - if ( isPrimaryDamage( meansOfDeath ) ) - { - assert( isDefined( attacker ) ); - - if ( isPlayer( attacker ) && weaponInheritsPerks( weapon ) && attacker _hasPerk( "specialty_bulletdamage" ) && victim _hasPerk( "specialty_armorvest" ) ) - damageAdd += 0; - else if ( isPlayer( attacker ) && weaponInheritsPerks( weapon ) && attacker _hasPerk( "specialty_bulletdamage" ) ) - damageAdd += damage*level.bulletDamageMod; - else if ( victim _hasPerk( "specialty_armorvest" ) ) - damageAdd -= damage*(1-level.armorVestMod); - - if ( isPlayer( attacker ) && attacker _hasPerk( "specialty_fmj" ) && victim _hasPerk ( "specialty_armorvest" ) ) - damageAdd += damage*level.hollowPointDamageMod; - } - else if ( isExplosiveDamage( meansOfDeath ) ) - { - if ( isPlayer( attacker ) && weaponInheritsPerks( weapon ) && attacker _hasPerk( "specialty_explosivedamage" ) && victim _hasPerk( "_specialty_blastshield" ) ) - damageAdd += 0; - else if ( isPlayer( attacker ) && weaponInheritsPerks( weapon ) && attacker _hasPerk( "specialty_explosivedamage" ) ) - damageAdd += damage*level.explosiveDamageMod; - else if ( victim _hasPerk( "_specialty_blastshield" ) ) - damageAdd -= damage*(1-level.blastShieldMod); - - if ( isKillstreakWeapon( weapon ) && isPlayer( attacker ) && attacker _hasPerk("specialty_dangerclose") ) - damageAdd += damage*level.dangerCloseMod; - } - else if (meansOfDeath == "MOD_FALLING") - { - if ( victim _hasPerk( "specialty_falldamage" ) ) - { - //eventually set a msg to do a roll - damageAdd = 0; - damage = 0; - } - } - - //if ( ( victim.xpScaler == 2 && isDefined( attacker ) ) && ( isPlayer( attacker ) || attacker.classname == "scrip_vehicle" ) ) - // damageAdd += 200; - - if ( victim _hasperk( "specialty_combathigh" ) && !level.combathighIsJuiced ) - { - if ( IsDefined( self.damageBlockedTotal ) && (!level.teamBased || (isDefined( attacker ) && isDefined( attacker.team ) && victim.team != attacker.team)) ) - { - damageTotal = damage + damageAdd; - damageBlocked = (damageTotal - ( damageTotal / 3 )); - self.damageBlockedTotal += damageBlocked; - - if ( self.damageBlockedTotal >= 101 ) - { - self notify( "combathigh_survived" ); - self.damageBlockedTotal = undefined; - } - } - - if ( weapon != "throwingknife_mp" ) - { - switch ( meansOfDeath ) - { - case "MOD_FALLING": - case "MOD_MELEE": - break; - default: - damage = damage/3; - damageAdd = damageAdd/3; - break; - } - } - } - - return int( damage + damageAdd ); -} - -initPerkDvars() -{ - level.bulletDamageMod = getIntProperty( "perk_bulletDamage", 40 )/100; // increased bullet damage by this % - level.hollowPointDamageMod = getIntProperty( "perk_hollowPointDamage", 65 )/100; // increased bullet damage by this % - level.armorVestMod = getIntProperty( "perk_armorVest", 75 )/100; // percentage of damage you take - level.explosiveDamageMod = getIntProperty( "perk_explosiveDamage", 40 )/100; // increased explosive damage by this % - level.blastShieldMod = getIntProperty( "perk_blastShield", 45 )/100; // percentage of damage you take - level.riotShieldMod = getIntProperty( "perk_riotShield", 100 )/100; - level.dangerCloseMod = getIntProperty( "perk_dangerClose", 100 )/100; - level.armorPiercingMod = getIntProperty( "perk_armorPiercingDamage", 40 )/100; // increased bullet damage by this % -} - -// CAC: Selector function, calls the individual cac features according to player's class settings -// Info: Called every time player spawns during loadout stage -cac_selector() -{ - perks = self.specialty; - - /* - self.detectExplosives = false; - - if ( self _hasPerk( "specialty_detectexplosive" ) ) - self.detectExplosives = true; - - maps\mp\gametypes\_weapons::setupBombSquad(); - */ -} - - -gambitUseTracker() -{ - self endon ( "death" ); - self endon ( "disconnect" ); - level endon ( "game_ended" ); - - if ( getDvarInt ( "scr_game_perks" ) != 1 ) - return; - - gameFlagWait( "prematch_done" ); - - self notifyOnPlayerCommand( "gambit_on", "+frag" ); -}