TuD|ASALA

search and rescue

Recommended Posts

Hey guys! I'm currently playing online MOD called "Veteran Federations Search and Rescue" Promod. They have a gametype named search and rescue. It's mainly like search and destroy but when you get killed a dog tag pops up. When an ally picks it you'll be re spawn and if an enemy picks it up you'll be eliminated for the round.

I was trying to find a similar mod to play LAN with my friends but I couldn't. So please if anyone know a link. Please reply. Thank you

Share this post


Link to post
Share on other sites

Hi

I own the public server you mentioned, and I am the creator of mod, there's no public ready-to-play version of search and rescue available, but there are some open source scripts available for the gametype. I myself didn't base it on any of them, but you can look-up openwarfare mod, which I heard had pretty much same gametype along with many others.

Feel free to join [v.F] community discord: https://discord.gg/ZrcvUjB

Share this post


Link to post
Share on other sites

Hi, Open Warfare MoD does not have Search and Rescue as a gametype or Kill confirmed. It does have Search and Destroy ( half of SR) 

There are gametype cfg available but SR itself has to be then built into the OW MoD. I guess there must be a MoD out there with it in 🙂 It’s come from somewhere. I don’t know about ProMoD so much and if it  can be played with that by default or the MoD also needs altering for it. 

SR is a really nice gameplay and I only seen 2 servers on the list with this style. Soon to be 3 though 😉 

Share this post


Link to post
Share on other sites

SR was based on KC, its publicly available but you will need changes. You can have it on any mod, but you need to compile in the stuff that is required.

  • Like 1

Share this post


Link to post
Share on other sites
Posted (edited)

In fact Search & Rescue is a copy of Help Mode from Call of Duty Frontlines, but in Frontlines as a Mode you can play at ANY Team Based gametype with/without Help Mode, as Search & Destroy.

Here a video of us playing Targets Gametype with Help Mode in 2016. (Help Mode was created in 2008)

https://youtu.be/g8qSKf6t6xk

Targets in a harder version of SD, where the strike team must destroy BOTH targets instead of any of them.

Cheers

Edited by Hajas

Share this post


Link to post
Share on other sites

That's not really the same thing, but it could've got the inspiration from sure, I think sr was ported from one of the newer cods, the dogtag fx is the same as well. What I meant up there is that you can base SR on KC that is available online for cod4, without starting from scratch.

Share this post


Link to post
Share on other sites
Posted (edited)
#include common_scripts\utility;
#include maps\mp\_utility;
#include maps\mp\gametypes\_hud_util;

/*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();
	
	maps\mp\gametypes\_globallogic::registerRoundSwitchDvar( level.gameType, 3, 0, 9 );
	maps\mp\gametypes\_globallogic::registerTimeLimitDvar( level.gameType, 2.5, 0, 1440 );
	maps\mp\gametypes\_globallogic::registerScoreLimitDvar( level.gameType, 4, 0, 500 );
	maps\mp\gametypes\_globallogic::registerRoundLimitDvar( level.gameType, 0, 0, 12 );
	maps\mp\gametypes\_globallogic::registerNumLivesDvar( level.gameType, 1, 0, 10 );

	level.scr_sr_dogtag_autoremoval_time = 20;
	level.scr_sr_dogtag_obits = 1;
	
	level.teamBased = true;
	level.overrideTeamScore = true;
	level.onPrecacheGameType = ::onPrecacheGameType;
	level.onStartGameType = ::onStartGameType;
	level.onSpawnPlayer = ::onSpawnPlayer;
	level.onPlayerKilled = ::onPlayerKilled;
	level.onDeadEvent = ::onDeadEvent;
	level.onOneLeftEvent = ::onOneLeftEvent;
	level.onTimeLimit = ::onTimeLimit;
	level.onRoundSwitch = ::onRoundSwitch;
	
	level.endGameOnScoreLimit = false;
	
	game["dialog"]["gametype"] = "searchdestroy";
	game["dialog"]["offense_obj"] = "obj_destroy";
	game["dialog"]["defense_obj"] = "obj_defend";
}


onPrecacheGameType()
{
	game["bombmodelname"] = "mil_tntbomb_mp";
	game["bombmodelnameobj"] = "mil_tntbomb_mp";
	game["bomb_dropped_sound"] = "mp_war_objective_lost";
	game["bomb_recovered_sound"] = "mp_war_objective_taken";
	precacheModel(game["bombmodelname"]);
	precacheModel(game["bombmodelnameobj"]);

	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("compass_waypoint_target");
	precacheShader("compass_waypoint_target_a");
	precacheShader("compass_waypoint_target_b");
	precacheShader("compass_waypoint_defend");
	precacheShader("compass_waypoint_defend_a");
	precacheShader("compass_waypoint_defend_b");
	precacheShader("compass_waypoint_defuse");
	precacheShader("compass_waypoint_defuse_a");
	precacheShader("compass_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" );	

	precacheModel( "prop_flag_neutral" );
	precacheModel( "prop_flag_russian" );
}

onRoundSwitch()
{
	if ( !isdefined( game["switchedsides"] ) )
		game["switchedsides"] = false;
	
	if ( game["teamScores"]["allies"] == level.scorelimit - 1 && game["teamScores"]["axis"] == level.scorelimit - 1 )
	{
		// overtime! team that's ahead in kills gets to defend.
		aheadTeam = getBetterTeam();
		if ( aheadTeam != game["defenders"] )
		{
			game["switchedsides"] = !game["switchedsides"];
		}
		else
		{
			level.halftimeSubCaption = "";
		}
		level.halftimeType = "overtime";
	}
	else
	{
		level.halftimeType = "halftime";
		game["switchedsides"] = !game["switchedsides"];
	}
}

getBetterTeam()
{
	kills["allies"] = 0;
	kills["axis"] = 0;
	deaths["allies"] = 0;
	deaths["axis"] = 0;
	
	for ( i = 0; i < level.players.size; i++ )
	{
		player = level.players[i];
		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";
}

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");
	
	maps\mp\gametypes\_globallogic::setObjectiveText( game["attackers"], &"OBJECTIVES_SD_ATTACKER" );
	maps\mp\gametypes\_globallogic::setObjectiveText( game["defenders"], &"OBJECTIVES_SD_DEFENDER" );

	if ( level.splitscreen )
	{
		maps\mp\gametypes\_globallogic::setObjectiveScoreText( game["attackers"], &"OBJECTIVES_SD_ATTACKER" );
		maps\mp\gametypes\_globallogic::setObjectiveScoreText( game["defenders"], &"OBJECTIVES_SD_DEFENDER" );
	}
	else
	{
		maps\mp\gametypes\_globallogic::setObjectiveScoreText( game["attackers"], &"OBJECTIVES_SD_ATTACKER_SCORE" );
		maps\mp\gametypes\_globallogic::setObjectiveScoreText( game["defenders"], &"OBJECTIVES_SD_DEFENDER_SCORE" );
	}
	maps\mp\gametypes\_globallogic::setObjectiveHintText( game["attackers"], &"OBJECTIVES_SD_ATTACKER_HINT" );
	maps\mp\gametypes\_globallogic::setObjectiveHintText( game["defenders"], &"OBJECTIVES_SD_DEFENDER_HINT" );

	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 * level.dvar[ "xp_multi" ] );
	maps\mp\gametypes\_rank::registerScoreInfo( "loss", 1 * level.dvar[ "xp_multi" ] );
	maps\mp\gametypes\_rank::registerScoreInfo( "tie", 1.5 * level.dvar[ "xp_multi" ] );
	
	maps\mp\gametypes\_rank::registerScoreInfo( "kill", 5 * level.dvar[ "xp_multi" ] );
	maps\mp\gametypes\_rank::registerScoreInfo( "headshot", 5 * level.dvar[ "xp_multi" ] );
	maps\mp\gametypes\_rank::registerScoreInfo( "assist", 2 * level.dvar[ "xp_multi" ] );
	maps\mp\gametypes\_rank::registerScoreInfo( "plant", 10 * level.dvar[ "xp_multi" ] );
	maps\mp\gametypes\_rank::registerScoreInfo( "defuse", 10 * level.dvar[ "xp_multi" ] );
	
	thread updateGametypeDvars();
	
	thread bombs();
}


onSpawnPlayer()
{
	self.isPlanting = false;
	self.isDefusing = false;
	self.isBombCarrier = false;

	if(self.pers["team"] == game["attackers"])
		spawnPointName = "mp_sd_spawn_attacker";
	else
		spawnPointName = "mp_sd_spawn_defender";

	if ( level.multiBomb && !isDefined( self.carryIcon ) && self.pers["team"] == game["attackers"] && !level.bombPlanted )
	{
		if ( level.splitscreen )
		{
			self.carryIcon = createIcon( "hud_suitcase_bomb", 35, 35 );
			self.carryIcon setPoint( "BOTTOM RIGHT", "BOTTOM RIGHT", -10, -50 );
			self.carryIcon.alpha = 0.75;
		}
		else
		{
			self.carryIcon = createIcon( "hud_suitcase_bomb", 50, 50 );
			self.carryIcon setPoint( "CENTER", "CENTER", 220, 140 );
			self.carryIcon.alpha = 0.75;
		}
	}

	spawnPoints = getEntArray( spawnPointName, "classname" );
	assert( spawnPoints.size );
	spawnpoint = maps\mp\gametypes\_spawnlogic::getSpawnpoint_Random( spawnPoints );

	self spawn( spawnpoint.origin, spawnpoint.angles );

	level notify ( "spawned_player" );
}

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 )
{
	if ( isdefined( winningTeam ) )
		[[level._setTeamScore]]( winningTeam, [[level._getTeamScore]]( winningTeam ) + 1 );
	
	thread maps\mp\gametypes\_globallogic::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;
		
		sd_endGame( game["defenders"], game["strings"][game["attackers"]+"_eliminated"] );
	}
	else if ( team == game["defenders"] )
	{
		sd_endGame( game["attackers"], game["strings"][game["defenders"]+"_eliminated"] );
	}
}


onOneLeftEvent( team )
{
	if ( level.bombExploded || level.bombDefused )
		return;
	
	//if ( team == game["attackers"] )
	warnLastPlayer( team );
}


onTimeLimit()
{
	if ( level.teamBased )
		sd_endGame( game["defenders"], game["strings"]["time_limit_reached"] );
	else
		sd_endGame( undefined, game["strings"]["time_limit_reached"] );
}


warnLastPlayer( team )
{
	if ( !isdefined( level.warnedLastPlayer ) )
		level.warnedLastPlayer = [];
	
	if ( isDefined( level.warnedLastPlayer[team] ) )
		return;
		
	level.warnedLastPlayer[team] = true;

	players = level.players;
	for ( i = 0; i < players.size; i++ )
	{
		player = players[i];

		if ( isDefined( player.pers["team"] ) && player.pers["team"] == team && isdefined( player.pers["class"] ) )
		{
			if ( player.sessionstate == "playing" && !player.afk )
				break;
		}
	}
	
	if ( i == players.size )
		return;
	
	players[i] thread giveLastAttackerWarning();
}


giveLastAttackerWarning()
{
	self endon("death");
	self endon("disconnect");
	
	fullHealthTime = 0;
	interval = .05;
	
	while(1)
	{
		if ( self.health != self.maxhealth )
			fullHealthTime = 0;
		else
			fullHealthTime += interval;
		
		wait interval;
		
		if (self.health == self.maxhealth && fullHealthTime >= 3)
			break;
	}
	
	//self iprintlnbold(&"MP_YOU_ARE_THE_ONLY_REMAINING_PLAYER");
	self maps\mp\gametypes\_globallogic::leaderDialogOnPlayer( "last_alive" );
	
	self maps\mp\gametypes\_missions::lastManSD();
}


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;

	trigger = getEnt( "sd_bomb_pickup_trig", "targetname" );
	if ( !isDefined( trigger ) )
	{
		maps\mp\_utility::error("No sd_bomb_pickup_trig trigger found in map.");
		return;
	}
	
	visuals[0] = getEnt( "sd_bomb", "targetname" );
	if ( !isDefined( visuals[0] ) )
	{
		maps\mp\_utility::error("No sd_bomb script_model found in map.");
		return;
	}

	precacheModel( "prop_suitcase_bomb" );	
	visuals[0] setModel( "prop_suitcase_bomb" );
	visuals[0] thread rotate();
	
	if ( !level.multiBomb )
	{
		level.sdBomb = maps\mp\gametypes\_gameobjects::createCarryObject( game["attackers"], trigger, visuals, (0,0,32) );
		level.sdBomb maps\mp\gametypes\_gameobjects::allowCarry( "friendly" );
		level.sdBomb maps\mp\gametypes\_gameobjects::set2DIcon( "friendly", "compass_waypoint_bomb" );
		level.sdBomb maps\mp\gametypes\_gameobjects::set3DIcon( "friendly", "waypoint_bomb" );
		level.sdBomb maps\mp\gametypes\_gameobjects::setVisibleTeam( "friendly" );
		level.sdBomb maps\mp\gametypes\_gameobjects::setCarryIcon( "hud_suitcase_bomb" );
		level.sdBomb.allowWeapons = true;
		level.sdBomb.onPickup = ::onPickup;
		level.sdBomb.onDrop = ::onDrop;
	}
	else
	{
		trigger delete();
		visuals[0] delete();
	}
	
	
	level.bombZones = [];
	
	bombZones = getEntArray( "bombzone", "targetname" );
	
	for ( index = 0; index < bombZones.size; index++ )
	{
		trigger = bombZones[index];
		visuals = getEntArray( bombZones[index].target, "targetname" );
		
		bombZone = maps\mp\gametypes\_gameobjects::createUseObject( game["defenders"], trigger, visuals, (0,0,64) );
		bombZone maps\mp\gametypes\_gameobjects::allowUse( "enemy" );
		bombZone maps\mp\gametypes\_gameobjects::setUseTime( level.plantTime );
		bombZone maps\mp\gametypes\_gameobjects::setUseText( &"MP_PLANTING_EXPLOSIVE" );
		bombZone maps\mp\gametypes\_gameobjects::setUseHintText( &"PLATFORM_HOLD_TO_PLANT_EXPLOSIVES" );
		if ( !level.multiBomb )
			bombZone maps\mp\gametypes\_gameobjects::setKeyObject( level.sdBomb );
		label = bombZone maps\mp\gametypes\_gameobjects::getLabel();
		bombZone.label = label;
		bombZone maps\mp\gametypes\_gameobjects::set2DIcon( "friendly", "compass_waypoint_defend" + label );
		bombZone maps\mp\gametypes\_gameobjects::set3DIcon( "friendly", "waypoint_defend" + label );
		bombZone maps\mp\gametypes\_gameobjects::set2DIcon( "enemy", "compass_waypoint_target" + label );
		bombZone maps\mp\gametypes\_gameobjects::set3DIcon( "enemy", "waypoint_target" + label );
		bombZone maps\mp\gametypes\_gameobjects::setVisibleTeam( "any" );
		bombZone.onBeginUse = ::onBeginUse;
		bombZone.onEndUse = ::onEndUse;
		bombZone.onUse = ::onUsePlantObject;
		bombZone.onCantUse = ::onCantUse;
		bombZone.useWeapon = "briefcase_bomb_mp";
		
		for ( i = 0; i < visuals.size; i++ )
		{
			if ( isDefined( visuals[i].script_exploder ) )
			{
				bombZone.exploderIndex = visuals[i].script_exploder;
				break;
			}
		}
		
		level.bombZones[level.bombZones.size] = bombZone;
		
		bombZone.bombDefuseTrig = getent( visuals[0].target, "targetname" );
		assert( isdefined( bombZone.bombDefuseTrig ) );
		bombZone.bombDefuseTrig.origin += (0,0,-10000);
		bombZone.bombDefuseTrig.label = label;
	}
	
	for ( index = 0; index < level.bombZones.size; index++ )
	{
		array = [];
		for ( otherindex = 0; otherindex < level.bombZones.size; otherindex++ )
		{
			if ( otherindex != index )
				array[ array.size ] = level.bombZones[otherindex];
		}
		level.bombZones[index].otherBombZones = array;
	}
}

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();
			}
		}
	}
}

onEndUse( team, player, result )
{
	if ( !isAlive( player ) )
		return;
		
	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();
			}
		}
	}
}

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" );
		if ( !level.hardcoreMode )
			iPrintLn( &"MP_EXPLOSIVES_PLANTED_BY", player );
		maps\mp\gametypes\_globallogic::leaderDialog( "bomb_planted" );

		maps\mp\gametypes\_globallogic::givePlayerScore( "plant", player );
		player thread [[level.onXPEvent]]( "plant" );
	}
}

onUseDefuseObject( player )
{
	wait .05;
	
	player notify ( "bomb_defused" );
	player logString( "bomb defused: " + self.label );
	level thread bombDefused();
	
	// disable this bomb zone
	self maps\mp\gametypes\_gameobjects::disableObject();
	
	if ( !level.hardcoreMode )
		iPrintLn( &"MP_EXPLOSIVES_DEFUSED_BY", player );
	maps\mp\gametypes\_globallogic::leaderDialog( "bomb_defused" );

	maps\mp\gametypes\_globallogic::givePlayerScore( "defuse", player );
	player thread [[level.onXPEvent]]( "defuse" );
}


onDrop( player )
{
	if ( !level.bombPlanted )
	{
		if ( isDefined( player ) && isDefined( player.name ) )
			printOnTeamArg( &"MP_EXPLOSIVES_DROPPED_BY", game["attackers"], player );

		if ( isDefined( player ) )
		 	player logString( "bomb dropped" );
		 else
		 	logString( "bomb dropped" );
	}

	self maps\mp\gametypes\_gameobjects::set3DIcon( "friendly", "waypoint_bomb" );
	
	maps\mp\_utility::playSoundOnPlayers( game["bomb_dropped_sound"], game["attackers"] );
}


onPickup( player )
{
	player.isBombCarrier = true;

	self maps\mp\gametypes\_gameobjects::set3DIcon( "friendly", "waypoint_defend" );

	if ( !level.bombDefused )
	{
		if ( isDefined( player ) && isDefined( player.name ) )
			printOnTeamArg( &"MP_EXPLOSIVES_RECOVERED_BY", game["attackers"], player );
			
		maps\mp\gametypes\_globallogic::leaderDialog( "bomb_taken", player.pers["team"] );
		player logString( "bomb taken" );
	}		
	maps\mp\_utility::playSoundOnPlayers( game["bomb_recovered_sound"], game["attackers"] );
}


onReset()
{
}


bombPlanted( destroyedObj, player )
{
	maps\mp\gametypes\_globallogic::pauseTimer();
	level.bombPlanted = true;
	
	destroyedObj.visuals[0] thread maps\mp\gametypes\_globallogic::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 - vector_scale( 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" );
	/*
	destroyedObj maps\mp\gametypes\_gameobjects::set2DIcon( "friendly", undefined );
	destroyedObj maps\mp\gametypes\_gameobjects::set2DIcon( "enemy", undefined );
	destroyedObj maps\mp\gametypes\_gameobjects::set3DIcon( "friendly", undefined );
	destroyedObj maps\mp\gametypes\_gameobjects::set3DIcon( "enemy", undefined );
	*/
	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", "compass_waypoint_defuse" + label );
	defuseObject maps\mp\gametypes\_gameobjects::set2DIcon( "enemy", "compass_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\_globallogic::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 );
	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 );
	
	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");
	wait level.bombTimer;
}

playSoundinSpace( alias, origin )
{
	org = spawn( "script_origin", origin );
	org.origin = origin;
	org playSound( alias  );
	wait 10; // MP doesn't have "sounddone" notifies =(
	org delete();
}

bombDefused()
{
	level.tickingObject maps\mp\gametypes\_globallogic::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"] );
}

onPlayerKilled(eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration)
{
	thread checkAllowSpectating();

	// No tags for falling, suicides or team kills
	//if( isPlayer( attacker ) && attacker.pers["team"] != self.pers["team"] && attacker != self )
	if( isPlayer( attacker ) && attacker != self && sHitLoc != "head" && sHitLoc != "helmet" && sMeansOfDeath != "MOD_MELEE") {
		if (isDefined(self.revivedOnce) && self.revivedOnce == true) { // Has already been revived once so no more revival
			broadcastInfo("eliminate", attacker, self);
		} else {
			broadcastInfo("shot", attacker, self);
			self thread spawnTags( attacker );
		}
	} else if (sHitLoc == "head" || sHitLoc == "helmet") {
		broadcastInfo("hs", attacker, self);
	}  else if (sMeansOfDeath == "MOD_MELEE") {
		broadcastInfo("knife", attacker, self);	
	} else if ( sMeansOfDeath == "MOD_FALLING" || ( isPlayer( attacker ) && attacker == self ) ) {
		broadcastInfo("suicide", attacker, self);
	}
}

broadcastInfo(type, attacker, victim, debugMsg) {
	for ( i = 0; i < level.players.size; i++ ) {
		msg = "";
		if (type == "shot") {
			if (level.players[i].pers["team"] == attacker.pers["team"]) {
				msg += attacker.name + " knocked out ";
			} else {
				msg += attacker.name + " knocked out ";
			}
			if (level.players[i].pers["team"] == victim.pers["team"]) {
				msg += victim.name;
			} else {
				msg += victim.name;
			}

		} else if (type == "hs") {
			if (level.players[i].pers["team"] == attacker.pers["team"]) {
				msg += attacker.name + " has eliminated ";
			} else {
				msg += attacker.name + " has eliminated ";
			}
			if (level.players[i].pers["team"] == victim.pers["team"]) {
				msg += victim.name + " with a headshot";
			} else {
				msg += victim.name + " with a headshot";
			}
		} else if (type == "knife") {
			if (level.players[i].pers["team"] == attacker.pers["team"]) {
				msg += attacker.name + " has eliminated ";
			} else {
				msg += attacker.name + " has eliminated ";
			}
			if (level.players[i].pers["team"] == victim.pers["team"]) {
				msg += victim.name + " with a knife";
			} else {
				msg += victim.name + " with a knife";
			}
		} else if (type == "suicide") {
			if (level.players[i].pers["team"] == victim.pers["team"]) {
				msg += victim.name + " killed himself, accidentally?";
			} else {
				msg += victim.name + " killed himself, accidentally?";
			}
		} else if (type == "revive") {
			if (level.players[i].pers["team"] == attacker.pers["team"]) {
				msg += attacker.name + " revived ";
			} else {
				msg += attacker.name + " revived ";
			}
			if (level.players[i].pers["team"] == victim.pers["team"]) {
				msg += victim.name;
			} else {
				msg += victim.name;
			}
		} else if (type == "eliminate") {
			if (level.players[i].pers["team"] == victim.pers["team"]) {
				msg += victim.name + " has been eliminated";
			} else {
				msg += victim.name + " has been eliminated";
			}
		} else if (type == "debug") {
			msg = debugMsg;
		}
		ClientPrint(level.players[i], msg);
	}
}

spawnTags(attacker)
{
	self.pers["tag"] = true;
	// wait(0.5);

	// place spawnpoint on ground
	basePosition = playerPhysicsTrace(self.origin, self.origin + (0, 0, -99999));

	// create pickup trigger
	trigger = spawn("trigger_radius", basePosition, 0, 20, 100);
	trigger endon("picked_up");
	trigger endon("timed_out");
	trigger.owner = attacker;
	trigger.team = attacker.pers["team"];

	// Friendly tags
	friendlyTag = spawn( "script_model", basePosition + ( 0, 0, 0 ) );
	friendlyTag endon( "picked_up" );
	friendlyTag endon( "timed_out" );
	friendlyTag setModel( "prop_flag_neutral" );
	friendlyTag.team = self.pers["team"];
	friendlyTag.owner = self;

	// Enemy tags
	enemyTag = spawn( "script_model", basePosition + ( 0, 0, 0 ) );
	enemyTag endon( "picked_up" );
	enemyTag endon( "timed_out" );
	enemyTag setModel( "prop_flag_russian" );
	if (attacker.pers["team"] != self.pers["team"]) {
		enemyTag.team = attacker.pers["team"];
	} else {
		if (self.pers["team"] == "axis") {
			enemyTag.team = "allies";
		} else {
			enemyTag.team = "axis";
		}
	}
	enemyTag.owner = self;

	//Delete on disconnect
	self thread onJoinedDisconnect( enemyTag, friendlyTag, trigger );

	// //Rotate
	// friendlyTag thread rotate();
	// enemyTag thread rotate();

	// Show tags to proper teams
	friendlyTag thread showTagToTeam();
	enemyTag thread showTagToTeam();

	// Wait for another player to pickup the dogtags
	trigger thread removeTriggerOnPickup( friendlyTag, enemyTag, trigger );

	// Remove the trigger and dogtags if the dog tag expire
	if( level.scr_sr_dogtag_autoremoval_time > 0 ) {
		trigger thread removeTriggerOnTimeout( friendlyTag, enemyTag, trigger, attacker );
	}
}

rotate()
{
	self endon( "picked_up" );
	self endon( "timed_out" );

	while( true )
	{
		self rotateyaw( 360, 1.5, 0, 0 );
		wait( 1.5 );
		self rotateyaw( 360 ,1.5, 0, 0 );
		wait( 1.5 );
	}
}

showTagToTeam()
{
	while( isDefined( self ) ) // use while() in case player changes team!
	{
		self hide();
		for( i = 0 ; i < level.players.size ; i ++ )
		{
			player = level.players[i];

			if ( player.pers["team"] == self.team )
				self showToPlayer( player );
		}
		wait( 0.05 );
	}
}


onJoinedDisconnect( enemyTag, friendlyTag, trigger )
{
	self endon( "spawned_player" );
	self endon( "game_ended" );

	self waittill_any( "disconnect", "joined_team", "joined_spectators" );

	// Notify to stop other threads
	trigger notify( "picked_up" );
	friendlyTag notify( "picked_up" );
	enemyTag notify( "picked_up" );

	trigger notify( "timed_out" );
	friendlyTag notify( "timed_out" );
	enemyTag notify( "timed_out" );

	// Delete Trigger and Model
	if( isDefined( trigger ) ) {
		trigger delete();
	}

	if( isDefined( friendlyTag ) ) {
		friendlyTag delete();
	}

	if( isDefined( enemyTag ) ) {
		enemyTag delete ();
	}
}

removeTriggerOnPickup( friendlyTag, enemyTag, trigger )
{
	trigger endon( "timed_out" );
	friendlyTag endon( "timed_out" );
	enemyTag endon( "timed_out" );

	trigger waittill( "trigger", player );

	// If by some chance a dead player activates the trigger, the dogtag will simply be deleted!
	if ( isAlive( player ) ) {

		// Cannot pick up dogtag if in spawn protection.......may be Invisible
		if( isDefined( player.spawn_protected ) && player.spawn_protected == true ) {
			player thread removeTriggerOnPickup( friendlyTag, enemyTag, trigger );
			return;
		}

		// Friendly team picks up Dogtag
		if( player.pers["team"] == friendlyTag.team ) {

			player playLocalSound( "mp_war_objective_taken" );

			// Show assist point for saving friendly
			player maps\mp\gametypes\_globallogic::incPersStat( "assists", 1 );
			player.assists = player maps\mp\gametypes\_globallogic::getPersStat( "assists" );

			// Send notice to players according to team
			if ( level.scr_sr_dogtag_obits == 1 && player.pers["team"] == "allies" )
			broadcastInfo("revive", player, friendlyTag.owner);

			if ( level.scr_sr_dogtag_obits == 1 && player.pers["team"] == "axis" )
			broadcastInfo("revive", player, friendlyTag.owner);

			//Respawn tag owner
			friendlyTag.owner clearLowerMessage();
			friendlyTag.owner.toBeRespawned = true;
			friendlyTag.owner.toBeRespawnedOrigin = player.origin;
			trigger thread revivePlayer(friendlyTag.owner);

			player logString( player.pers["team"] + " " + "kill denied" );

			// Notify trigger and model picked up
			trigger notify( "picked_up" );
			friendlyTag notify( "picked_up" );
			enemyTag notify( "picked_up" );

			// Delete Trigger and Model
			trigger delete();
			friendlyTag delete();
			enemyTag delete ();

		}

		// Enemy team picks up DogTag
		if ( player.pers["team"] == enemyTag.team ) {

			// Send notice to players according to team
			if ( level.scr_sr_dogtag_obits == 1 && player.pers["team"] == "allies" )
			broadcastInfo("eliminate", player, enemyTag.owner);

			if ( level.scr_sr_dogtag_obits == 1 && player.pers["team"] == "axis" )
			broadcastInfo("eliminate", player, enemyTag.owner);

			player logString( player.pers["team"] + " " + "kill confirmed" );

			enemyTag.owner.pers["tag"] = false;
			player playLocalSound( "mp_war_objective_lost" );

			// Notify trigger and model picked up
			trigger notify( "picked_up" );
			friendlyTag notify( "picked_up" );
			enemyTag notify( "picked_up" );

			// Delete Trigger and Model
			trigger delete();
			friendlyTag delete();
			enemyTag delete ();
		}
	} else {
		player thread removeTriggerOnPickup( friendlyTag, enemyTag, trigger );
		return;
	}
}

revivePlayer(player) {
	// wait(1.0);
	if (!level.gameEnded) {
		player.pers["tag"] = false;
		player.revivedOnce = true;
		player thread [[level.spawnPlayer]]();		
	}
}

removeTriggerOnTimeout( friendlyTag, enemyTag, trigger, attacker )
{
	trigger endon( "picked_up" );
	friendlyTag endon( "picked_up" );
	enemyTag endon( "picked_up" );

	// Wait for this tag to timeout
	wait( level.scr_sr_dogtag_autoremoval_time );

	if( !level.gameEnded ) {
		// Send notice to players according to team
		if ( level.scr_sr_dogtag_obits == 1 && attacker.pers["team"] == "allies" )
			iprintln(enemyTag.owner.name + " has been eliminated");

		if ( level.scr_sr_dogtag_obits == 1 && attacker.pers["team"] == "axis" )
			iprintln(enemyTag.owner.name + " has been eliminated");
	}

	// Notify trigger and model timed out
	trigger notify( "timed_out" );
	friendlyTag notify( "timed_out" );
	enemyTag notify( "timed_out" );

	// Delete Trigger and Model
	trigger delete();
	friendlyTag delete();
	enemyTag delete();
}

I can't remember exactly where this originated, I think a fork of OW. I pulled it out, and removed any dependencies for OW, no custom models etc. Uses flags instead of tags etc. It was very much a bodge in 5 minutes kinda thing, but it did work pretty well. 

Just add it to gametypes and load.

I no longer have use for it, so I hope it helps someone.

Edited by vsg
  • Thanks 1

Share this post


Link to post
Share on other sites

IIRC, a OW modder made cod4 versions of several gametypes from later cod games. Including Infection etc.

Share this post


Link to post
Share on other sites

Come and have a play of sr here fmjcod4.com:28990 😎

It's using OW. Might need some tweaks for gameplay times of rounds and amount blah blah but just started this server and as of yet no players.🤐 WIP..

 

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.