#include common_scripts\utility; #include maps\mp\_utility; #include maps\mp\gametypes\_hud_util; //////////////////////////// //Custom SD gametype file/// // /// //For iSnipe 2.* or higher// // By iNuke //// //////////////////////////// // Rallypoints should be destroyed on leaving your team/getting killed // Compass icons need to be looked at // Doesn't seem to be setting angle on spawn so that you are facing your rallypoint /* Search and Destroy Attackers objective: Bomb one of 2 positions Defenders objective: Defend these 2 positions / Defuse planted bombs Round ends: When one team is eliminated, bomb explodes, bomb is defused, or roundlength time is reached Map ends: When one team reaches the score limit, or time limit or round limit is reached Respawning: Players remain dead for the round and will respawn at the beginning of the next round Level requirements ------------------ Allied Spawnpoints: classname mp_sd_spawn_attacker Allied players spawn from these. Place at least 16 of these relatively close together. Axis Spawnpoints: classname mp_sd_spawn_defender Axis players spawn from these. Place at least 16 of these relatively close together. Spectator Spawnpoints: classname mp_global_intermission Spectators spawn from these and intermission is viewed from these positions. Atleast one is required, any more and they are randomly chosen between. Bombzones: classname trigger_multiple targetname bombzone script_gameobjectname bombzone script_bombmode_original script_bombmode_single script_bombmode_dual script_team Set to allies or axis. This is used to set which team a bombzone is used by in dual bomb mode. script_label Set to A or B. This sets the letter shown on the compass in original mode. This is a volume of space in which the bomb can planted. Must contain an origin brush. Bomb: classname trigger_lookat targetname bombtrigger script_gameobjectname bombzone This should be a 16x16 unit trigger with an origin brush placed so that it's center lies on the bottom plane of the trigger. Must be in the level somewhere. This is the trigger that is used when defusing a bomb. It gets moved to the position of the planted bomb model. Level script requirements ------------------------- Team Definitions: game["attackers"] = "allies"; game["defenders"] = "axis"; This sets which team is attacking and which team is defending. Attackers plant the bombs. Defenders protect the targets. Exploder Effects: Setting script_noteworthy on a bombzone trigger to an exploder group can be used to trigger additional effects. */ /*QUAKED mp_sd_spawn_attacker (0.0 1.0 0.0) (-16 -16 0) (16 16 72) Attacking players spawn randomly at one of these positions at the beginning of a round.*/ /*QUAKED mp_sd_spawn_defender (1.0 0.0 0.0) (-16 -16 0) (16 16 72) Defending players spawn randomly at one of these positions at the beginning of a round.*/ main() { if(getdvar("mapname") == "mp_background") return; maps\mp\gametypes\_globallogic::init(); maps\mp\gametypes\_callbacksetup::SetupCallbacks(); maps\mp\gametypes\_globallogic::SetupCallbacks(); registerRoundSwitchDvar( level.gameType, 3, 0, 9 ); registerTimeLimitDvar( level.gameType, 2.5, 0, 1440 ); registerScoreLimitDvar( level.gameType, 1, 0, 500 ); registerRoundLimitDvar( level.gameType, 0, 0, 12 ); registerWinLimitDvar( level.gameType, 4, 0, 12 ); registerNumLivesDvar( level.gameType, 1, 0, 10 ); registerHalfTimeDvar( level.gameType, 0, 0, 1 ); level.objectiveBased = true; level.teamBased = true; level.onPrecacheGameType = ::onPrecacheGameType; level.onStartGameType = ::onStartGameType; level.getSpawnPoint = ::getSpawnPoint; level.onSpawnPlayer = ::onSpawnPlayer; level.onPlayerKilled = ::onPlayerKilled; level.onDeadEvent = ::onDeadEvent; level.onOneLeftEvent = ::onOneLeftEvent; level.onTimeLimit = ::onTimeLimit; level.onNormalDeath = ::onNormalDeath; level.initGametypeAwards = ::initGametypeAwards; //game["dialog"]["gametype"] = "searchdestroy"; if ( getDvarInt( "g_hardcore" ) ) game["dialog"]["gametype"] = "hc_" + game["dialog"]["gametype"]; else if ( getDvarInt( "camera_thirdPerson" ) ) game["dialog"]["gametype"] = "thirdp_" + game["dialog"]["gametype"]; else if ( getDvarInt( "scr_diehard" ) ) game["dialog"]["gametype"] = "dh_" + game["dialog"]["gametype"]; else if (getDvarInt( "scr_" + level.gameType + "_promode" ) ) game["dialog"]["gametype"] = game["dialog"]["gametype"] + "_pro"; //game["dialog"]["offense_obj"] = "obj_destroy"; //game["dialog"]["defense_obj"] = "obj_defend"; } onPrecacheGameType() { game["bomb_dropped_sound"] = "mp_war_objective_lost"; game["bomb_recovered_sound"] = "mp_war_objective_taken"; precacheShader("cardtitle_bullet"); precacheShader("cardtitle_bloodsplat"); precacheShader("cardicon_patch"); precacheShader("hud_status_dead"); precacheShader("waypoint_bomb"); precacheShader("hud_suitcase_bomb"); precacheShader("waypoint_target"); precacheShader("waypoint_target_a"); precacheShader("waypoint_target_b"); precacheShader("waypoint_defend"); precacheShader("waypoint_defend_a"); precacheShader("waypoint_defend_b"); precacheShader("waypoint_defuse"); precacheShader("waypoint_defuse_a"); precacheShader("waypoint_defuse_b"); precacheShader("waypoint_escort"); /* precacheShader("waypoint_target"); precacheShader("waypoint_target_a"); precacheShader("waypoint_target_b"); precacheShader("waypoint_defend"); precacheShader("waypoint_defend_a"); precacheShader("waypoint_defend_b"); precacheShader("waypoint_defuse"); precacheShader("waypoint_defuse_a"); precacheShader("waypoint_defuse_b"); */ precacheString( &"MP_EXPLOSIVES_RECOVERED_BY" ); precacheString( &"MP_EXPLOSIVES_DROPPED_BY" ); precacheString( &"MP_EXPLOSIVES_PLANTED_BY" ); precacheString( &"MP_EXPLOSIVES_DEFUSED_BY" ); precacheString( &"PLATFORM_HOLD_TO_PLANT_EXPLOSIVES" ); precacheString( &"PLATFORM_HOLD_TO_DEFUSE_EXPLOSIVES" ); precacheString( &"MP_CANT_PLANT_WITHOUT_BOMB" ); precacheString( &"MP_PLANTING_EXPLOSIVE" ); precacheString( &"MP_DEFUSING_EXPLOSIVE" ); } onStartGameType() { if ( !isDefined( game["switchedsides"] ) ) game["switchedsides"] = false; if ( game["switchedsides"] ) { oldAttackers = game["attackers"]; oldDefenders = game["defenders"]; game["attackers"] = oldDefenders; game["defenders"] = oldAttackers; } setClientNameMode( "manual_change" ); game["strings"]["target_destroyed"] = &"MP_TARGET_DESTROYED"; game["strings"]["bomb_defused"] = &"MP_BOMB_DEFUSED"; precacheString( game["strings"]["target_destroyed"] ); precacheString( game["strings"]["bomb_defused"] ); level._effect["bombexplosion"] = loadfx("explosions/tanker_explosion"); setObjectiveText( game["attackers"], "Eliminate enemy snipers" ); setObjectiveText( game["defenders"], "Eliminate enemy snipers" ); if ( level.splitscreen ) { setObjectiveScoreText( game["attackers"], &"OBJECTIVES_SD_ATTACKER" ); setObjectiveScoreText( game["defenders"], &"OBJECTIVES_SD_DEFENDER" ); } else { setObjectiveScoreText( game["attackers"], &"OBJECTIVES_SD_ATTACKER_SCORE" ); setObjectiveScoreText( game["defenders"], &"OBJECTIVES_SD_DEFENDER_SCORE" ); } setObjectiveHintText( game["attackers"], "Eliminate enemy snipers" ); setObjectiveHintText( game["defenders"], "Eliminate enemy snipers" ); level.spawnMins = ( 0, 0, 0 ); level.spawnMaxs = ( 0, 0, 0 ); maps\mp\gametypes\_spawnlogic::placeSpawnPoints( "mp_sd_spawn_attacker" ); maps\mp\gametypes\_spawnlogic::placeSpawnPoints( "mp_sd_spawn_defender" ); level.mapCenter = maps\mp\gametypes\_spawnlogic::findBoxCenter( level.spawnMins, level.spawnMaxs ); setMapCenter( level.mapCenter ); allowed[0] = "sd"; allowed[1] = "bombzone"; allowed[2] = "blocker"; maps\mp\gametypes\_gameobjects::main(allowed); maps\mp\gametypes\_rank::registerScoreInfo( "win", 2 ); maps\mp\gametypes\_rank::registerScoreInfo( "loss", 1 ); maps\mp\gametypes\_rank::registerScoreInfo( "tie", 1.5 ); maps\mp\gametypes\_rank::registerScoreInfo( "kill", 50 ); maps\mp\gametypes\_rank::registerScoreInfo( "headshot", 50 ); maps\mp\gametypes\_rank::registerScoreInfo( "assist", 20 ); maps\mp\gametypes\_rank::registerScoreInfo( "plant", 100 ); maps\mp\gametypes\_rank::registerScoreInfo( "defuse", 100 ); thread updateGametypeDvars(); thread bombs(); } getSpawnPoint() { if(self.pers["team"] == game["attackers"]) spawnPointName = "mp_sd_spawn_attacker"; else spawnPointName = "mp_sd_spawn_defender"; spawnPoints = maps\mp\gametypes\_spawnlogic::getSpawnpointArray( spawnPointName ); assert( spawnPoints.size ); spawnpoint = maps\mp\gametypes\_spawnlogic::getSpawnpoint_Random( spawnPoints ); return spawnpoint; } onSpawnPlayer() { self.isPlanting = false; self.isDefusing = false; self.isBombCarrier = false; if ( level.multiBomb && !isDefined( self.carryIcon ) && self.pers["team"] == game["attackers"] && !level.bombPlanted ) { if ( level.splitscreen ) { self.carryIcon = createIcon( "hud_suitcase_bomb", 33, 33 ); self.carryIcon setPoint( "BOTTOM RIGHT", "BOTTOM RIGHT", 0, -78 ); self.carryIcon.alpha = 0.75; } else { self.carryIcon = createIcon( "hud_suitcase_bomb", 50, 50 ); self.carryIcon setPoint( "BOTTOM RIGHT", "BOTTOM RIGHT", -90, -65 ); self.carryIcon.alpha = 0.75; } } level notify ( "spawned_player" ); } onPlayerKilled(eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration, killId) { thread checkAllowSpectating(); } checkAllowSpectating() { wait ( 0.05 ); update = false; if ( !level.aliveCount[ game["attackers"] ] ) { level.spectateOverride[game["attackers"]].allowEnemySpectate = 1; update = true; } if ( !level.aliveCount[ game["defenders"] ] ) { level.spectateOverride[game["defenders"]].allowEnemySpectate = 1; update = true; } if ( update ) maps\mp\gametypes\_spectating::updateSpectateSettings(); } sd_endGame( winningTeam, endReasonText ) { thread maps\mp\gametypes\_gamelogic::endGame( winningTeam, endReasonText ); } onDeadEvent( team ) { if ( level.bombExploded || level.bombDefused ) return; if ( team == "all" ) { if ( level.bombPlanted ) sd_endGame( game["attackers"], game["strings"][game["defenders"]+"_eliminated"] ); else sd_endGame( game["defenders"], game["strings"][game["attackers"]+"_eliminated"] ); } else if ( team == game["attackers"] ) { if ( level.bombPlanted ) return; level thread sd_endGame( game["defenders"], game["strings"][game["attackers"]+"_eliminated"] ); } else if ( team == game["defenders"] ) { level thread sd_endGame( game["attackers"], game["strings"][game["defenders"]+"_eliminated"] ); } } onOneLeftEvent( team ) { if ( level.bombExploded || level.bombDefused ) return; lastPlayer = getLastLivingPlayer( team ); lastPlayer thread giveLastOnTeamWarning(); } onNormalDeath( victim, attacker, lifeId ) { score = maps\mp\gametypes\_rank::getScoreInfoValue( "kill" ); assert( isDefined( score ) ); team = victim.team; if ( game["state"] == "postgame" && (victim.team == game["defenders"] || !level.bombPlanted) ) attacker.finalKill = true; if ( victim.isPlanting ) { thread maps\mp\_matchdata::logKillEvent( lifeId, "planting" ); } else if ( victim.isBombCarrier ) { attacker incPlayerStat( "bombcarrierkills", 1 ); thread maps\mp\_matchdata::logKillEvent( lifeId, "carrying" ); } else if ( victim.isDefusing ) { thread maps\mp\_matchdata::logKillEvent( lifeId, "defusing" ); } if ( attacker.isBombCarrier ) attacker incPlayerStat( "killsasbombcarrier", 1 ); } giveLastOnTeamWarning() { self endon("death"); self endon("disconnect"); level endon( "game_ended" ); self waitTillRecoveredHealth( 3 ); otherTeam = getOtherTeam( self.pers["team"] ); level thread teamPlayerCardSplash( "callout_lastteammemberalive", self, self.pers["team"] ); level thread teamPlayerCardSplash( "callout_lastenemyalive", self, otherTeam ); level notify ( "last_alive", self ); self maps\mp\gametypes\_missions::lastManSD(); } onTimeLimit() { sd_endGame( game["defenders"], game["strings"]["time_limit_reached"] ); } updateGametypeDvars() { level.plantTime = dvarFloatValue( "planttime", 5, 0, 20 ); level.defuseTime = dvarFloatValue( "defusetime", 5, 0, 20 ); level.bombTimer = dvarFloatValue( "bombtimer", 45, 1, 300 ); level.multiBomb = dvarIntValue( "multibomb", 0, 0, 1 ); } bombs() { level.bombPlanted = false; level.bombDefused = false; level.bombExploded = false; } onBeginUse( player ) { if ( self maps\mp\gametypes\_gameobjects::isFriendlyTeam( player.pers["team"] ) ) { player playSound( "mp_bomb_defuse" ); //player.isDefusing = true; if ( isDefined( level.sdBombModel ) ) level.sdBombModel hide(); } else { player.isPlanting = true; if ( level.multibomb ) { for ( i = 0; i < self.otherBombZones.size; i++ ) { //self.otherBombZones[i] maps\mp\gametypes\_gameobjects::disableObject(); self.otherBombZones[i] maps\mp\gametypes\_gameobjects::allowUse( "none" ); self.otherBombZones[i] maps\mp\gametypes\_gameobjects::setVisibleTeam( "friendly" ); } } } } onEndUse( team, player, result ) { if ( !isDefined( player ) ) return; if ( isAlive( player ) ) { player.isDefusing = false; player.isPlanting = false; } if ( self maps\mp\gametypes\_gameobjects::isFriendlyTeam( player.pers["team"] ) ) { if ( isDefined( level.sdBombModel ) && !result ) { level.sdBombModel show(); } } else { if ( level.multibomb && !result ) { for ( i = 0; i < self.otherBombZones.size; i++ ) { //self.otherBombZones[i] maps\mp\gametypes\_gameobjects::enableObject(); self.otherBombZones[i] maps\mp\gametypes\_gameobjects::allowUse( "enemy" ); self.otherBombZones[i] maps\mp\gametypes\_gameobjects::setVisibleTeam( "any" ); } } } } onCantUse( player ) { player iPrintLnBold( &"MP_CANT_PLANT_WITHOUT_BOMB" ); } onUsePlantObject( player ) { // planted the bomb if ( !self maps\mp\gametypes\_gameobjects::isFriendlyTeam( player.pers["team"] ) ) { level thread bombPlanted( self, player ); //player logString( "bomb planted: " + self.label ); // disable all bomb zones except this one for ( index = 0; index < level.bombZones.size; index++ ) { if ( level.bombZones[index] == self ) continue; level.bombZones[index] maps\mp\gametypes\_gameobjects::disableObject(); } player playSound( "mp_bomb_plant" ); player notify ( "bomb_planted" ); leaderDialog( "bomb_planted" ); level thread teamPlayerCardSplash( "callout_bombplanted", player ); } } onUseDefuseObject( player ) { player notify ( "bomb_defused" ); level thread bombDefused(); // disable this bomb zone self maps\mp\gametypes\_gameobjects::disableObject(); //if ( !level.hardcoreMode ) // iPrintLn( &"MP_EXPLOSIVES_DEFUSED_BY", player ); leaderDialog( "bomb_defused" ); level thread teamPlayerCardSplash( "callout_bombdefused", player ); if ( isDefined( level.bombOwner ) && ( level.bombOwner.bombPlantedTime + 3000 + (level.defuseTime*1000) ) > getTime() && isReallyAlive( level.bombOwner ) ) player thread maps\mp\gametypes\_hud_message::SplashNotify( "ninja_defuse", ( maps\mp\gametypes\_rank::getScoreInfoValue( "defuse" ) ) ); else player thread maps\mp\gametypes\_hud_message::SplashNotify( "defuse", maps\mp\gametypes\_rank::getScoreInfoValue( "defuse" ) ); player thread maps\mp\gametypes\_rank::giveRankXP( "defuse" ); maps\mp\gametypes\_gamescore::givePlayerScore( "defuse", player ); player incPlayerStat( "bombsdefused", 1 ); player thread maps\mp\_matchdata::logGameEvent( "defuse", player.origin ); } onDrop( player ) { self maps\mp\gametypes\_gameobjects::set2DIcon( "friendly", "waypoint_bomb" ); self maps\mp\gametypes\_gameobjects::set3DIcon( "friendly", "waypoint_bomb" ); maps\mp\_utility::playSoundOnPlayers( game["bomb_dropped_sound"], game["attackers"] ); } onPickup( player ) { player.isBombCarrier = true; player incPlayerStat( "bombscarried", 1 ); player thread maps\mp\_matchdata::logGameEvent( "pickup", player.origin ); self maps\mp\gametypes\_gameobjects::set2DIcon( "friendly", "waypoint_escort" ); self maps\mp\gametypes\_gameobjects::set3DIcon( "friendly", "waypoint_escort" ); if ( !level.bombDefused ) { teamPlayerCardSplash( "callout_bombtaken", player, player.team ); leaderDialog( "bomb_taken", player.pers["team"] ); } maps\mp\_utility::playSoundOnPlayers( game["bomb_recovered_sound"], game["attackers"] ); } onReset() { } bombPlanted( destroyedObj, player ) { maps\mp\gametypes\_gamelogic::pauseTimer(); level.bombPlanted = true; destroyedObj.visuals[0] thread maps\mp\gametypes\_gamelogic::playTickingSound(); level.tickingObject = destroyedObj.visuals[0]; level.timeLimitOverride = true; setGameEndTime( int( gettime() + (level.bombTimer * 1000) ) ); setDvar( "ui_bomb_timer", 1 ); if ( !level.multiBomb ) { level.sdBomb maps\mp\gametypes\_gameobjects::allowCarry( "none" ); level.sdBomb maps\mp\gametypes\_gameobjects::setVisibleTeam( "none" ); level.sdBomb maps\mp\gametypes\_gameobjects::setDropped(); level.sdBombModel = level.sdBomb.visuals[0]; } else { for ( index = 0; index < level.players.size; index++ ) { if ( isDefined( level.players[index].carryIcon ) ) level.players[index].carryIcon destroyElem(); } trace = bulletTrace( player.origin + (0,0,20), player.origin - (0,0,2000), false, player ); tempAngle = randomfloat( 360 ); forward = (cos( tempAngle ), sin( tempAngle ), 0); forward = vectornormalize( forward - common_scripts\utility::vector_multiply( trace["normal"], vectordot( forward, trace["normal"] ) ) ); dropAngles = vectortoangles( forward ); level.sdBombModel = spawn( "script_model", trace["position"] ); level.sdBombModel.angles = dropAngles; level.sdBombModel setModel( "prop_suitcase_bomb" ); } destroyedObj maps\mp\gametypes\_gameobjects::allowUse( "none" ); destroyedObj maps\mp\gametypes\_gameobjects::setVisibleTeam( "none" ); label = destroyedObj maps\mp\gametypes\_gameobjects::getLabel(); // create a new object to defuse with. trigger = destroyedObj.bombDefuseTrig; trigger.origin = level.sdBombModel.origin; visuals = []; defuseObject = maps\mp\gametypes\_gameobjects::createUseObject( game["defenders"], trigger, visuals, (0,0,32) ); defuseObject maps\mp\gametypes\_gameobjects::allowUse( "friendly" ); defuseObject maps\mp\gametypes\_gameobjects::setUseTime( level.defuseTime ); defuseObject maps\mp\gametypes\_gameobjects::setUseText( &"MP_DEFUSING_EXPLOSIVE" ); defuseObject maps\mp\gametypes\_gameobjects::setUseHintText( &"PLATFORM_HOLD_TO_DEFUSE_EXPLOSIVES" ); defuseObject maps\mp\gametypes\_gameobjects::setVisibleTeam( "any" ); defuseObject maps\mp\gametypes\_gameobjects::set2DIcon( "friendly", "waypoint_defuse" + label ); defuseObject maps\mp\gametypes\_gameobjects::set2DIcon( "enemy", "waypoint_defend" + label ); defuseObject maps\mp\gametypes\_gameobjects::set3DIcon( "friendly", "waypoint_defuse" + label ); defuseObject maps\mp\gametypes\_gameobjects::set3DIcon( "enemy", "waypoint_defend" + label ); defuseObject.label = label; defuseObject.onBeginUse = ::onBeginUse; defuseObject.onEndUse = ::onEndUse; defuseObject.onUse = ::onUseDefuseObject; defuseObject.useWeapon = "briefcase_bomb_defuse_mp"; BombTimerWait(); setDvar( "ui_bomb_timer", 0 ); destroyedObj.visuals[0] maps\mp\gametypes\_gamelogic::stopTickingSound(); if ( level.gameEnded || level.bombDefused ) return; level.bombExploded = true; explosionOrigin = level.sdBombModel.origin; level.sdBombModel hide(); if ( isdefined( player ) ) { destroyedObj.visuals[0] radiusDamage( explosionOrigin, 512, 200, 20, player ); player incPlayerStat( "targetsdestroyed", 1 ); } else destroyedObj.visuals[0] radiusDamage( explosionOrigin, 512, 200, 20 ); rot = randomfloat(360); explosionEffect = spawnFx( level._effect["bombexplosion"], explosionOrigin + (0,0,50), (0,0,1), (cos(rot),sin(rot),0) ); triggerFx( explosionEffect ); PlayRumbleOnPosition( "grenade_rumble", explosionOrigin ); earthquake( 0.75, 2.0, explosionOrigin, 2000 ); thread playSoundinSpace( "exp_suitcase_bomb_main", explosionOrigin ); if ( isDefined( destroyedObj.exploderIndex ) ) exploder( destroyedObj.exploderIndex ); for ( index = 0; index < level.bombZones.size; index++ ) level.bombZones[index] maps\mp\gametypes\_gameobjects::disableObject(); defuseObject maps\mp\gametypes\_gameobjects::disableObject(); setGameEndTime( 0 ); wait 3; sd_endGame( game["attackers"], game["strings"]["target_destroyed"] ); } BombTimerWait() { level endon( "game_ended" ); level endon( "bomb_defused" ); maps\mp\gametypes\_hostmigration::waitLongDurationWithGameEndTimeUpdate( level.bombTimer ); } bombDefused() { level.tickingObject maps\mp\gametypes\_gamelogic::stopTickingSound(); level.bombDefused = true; setDvar( "ui_bomb_timer", 0 ); level notify("bomb_defused"); wait 1.5; setGameEndTime( 0 ); sd_endGame( game["defenders"], game["strings"]["bomb_defused"] ); } initGametypeAwards() { maps\mp\_awards::initStatAward( "targetsdestroyed", 0, maps\mp\_awards::highestWins ); maps\mp\_awards::initStatAward( "bombsplanted", 0, maps\mp\_awards::highestWins ); maps\mp\_awards::initStatAward( "bombsdefused", 0, maps\mp\_awards::highestWins ); maps\mp\_awards::initStatAward( "bombcarrierkills", 0, maps\mp\_awards::highestWins ); maps\mp\_awards::initStatAward( "bombscarried", 0, maps\mp\_awards::highestWins ); maps\mp\_awards::initStatAward( "killsasbombcarrier", 0, maps\mp\_awards::highestWins ); }