s1-scripts-dev/raw/maps/mp/_threatdetection.gsc
2025-05-21 16:23:17 +02:00

1022 lines
27 KiB
Plaintext

#include maps\mp\_utility;
#include common_scripts\utility;
#include maps\mp\gametypes\_hud_util;
// threatDetection style options are:
// glow -- glowy vfx blobs
// model -- script model of the threat that is posed
// vfx_model -- a vfx posed model
// attached_glow -- glowy vfx blobs that are attached to the players
// stencil_outline -- red dot/line things in screen space stenciled to the player's shape
init()
{
level._threatdetection = SpawnStruct();
level._threatdetection.default_style = "stencil_outline";
SetDevDvarIfUninitialized( "threat_detection_mark_time", 3 );
SetDevDvarIfUninitialized( "threat_detection_highlight_style", level._threatdetection.default_style );
level._threatdetection.activeStyle = GetDvar( "threat_detection_highlight_style", level._threatdetection.default_style );
level thread onPlayerConnect();
level thread watchAgentSpawn();
}
changeThreatStyle( threatStyle )
{
if( threatStyle == level._threatdetection.activeStyle )
return;
//turn everything off
foreach( p in level.players )
{
//model and vfx_model
if( IsDefined( p._threatdetection.mark_enemy_model ) )
p._threatdetection.mark_enemy_model Delete();
if( IsDefined( p._threatdetection.mark_friendly_model ) )
p._threatdetection.mark_friendly_model Delete();
//vfx
if( IsDefined( p.mark_fx ) && IsDefined( p.mark_fx.fx_ent ))
{
foreach( i, fx in p.mark_fx.fx_ent )
{
if( IsDefined( fx.enemyMarker ) )
fx.enemyMarker Delete();
if( IsDefined( fx.friendlyMarker ) )
fx.friendlyMarker Delete();
if( IsDefined( fx.enemyLosMarker ) )
fx.enemyLosMarker Delete();
if( IsDefined( fx.friendlyLosMarker ) )
fx.friendlyLosMarker Delete();
}
}
}
//turn on the new one
foreach( p in level.players )
p threat_init( threatStyle );
level._threatdetection.activeStyle = threatStyle;
}
GetThreatStyle()
{
threatStyle = GetDvar( "threat_detection_highlight_style", level._threatdetection.default_style );
if( threatStyle != level._threatdetection.activeStyle )
changeThreatStyle( threatStyle );
return threatStyle;
}
onPlayerConnect()
{
for(;;)
{
level waittill("connected", player);
player thread onPlayerSpawned();
}
}
watchAgentSpawn()
{
while (true)
{ // note that this could miss an agent if multiple agents are spawned the same frame.
level waittill( "spawned_agent", agent );
agent._threatdetection = SpawnStruct();
agent._threatdetection.showlist = [];
agent thread onAgentSpawned();
}
}
onAgentSpawned()
{
self endon("death");
self childthread monitorThreatHighlight();
self childthread cleanUpOnDeath();
}
//called from player connect
onPlayerSpawned()
{
self endon("disconnect");
self._threatdetection = SpawnStruct();
self._threatdetection.showlist = [];
self waittill( "spawned_player" );
childthread monitorThreatHighlight();
childthread cleanUpOnDeath();
//if( self != level.players[0] )
//{
//childthread debugHelper();
//}
// Monitors if/when threat overlay should be displayed.
childthread monitorThreatHighlightNotification();
//for respawns
while( 1 )
{
self waittill( "spawned_player" );
threatStyle = GetThreatStyle();
if( threatStyle == "attached_glow" )
visitFXEnt( ::visitorRelink, ::getHostileMarker, undefined );
}
}
// Monitors if/when threat overlay should be displayed.
monitorThreatHighlightNotification()
{
// Create a new hud element on client for the overlay. Set initially to have an alpha of 0.0 so it's not visible.
notification_overlay_element = NewClientHudElem( self );
notification_overlay_element.x = 0;
notification_overlay_element.y = 0;
notification_overlay_element.alignX = "left";
notification_overlay_element.alignY = "top";
notification_overlay_element.horzAlign = "fullscreen";
notification_overlay_element.vertAlign = "fullscreen";
notification_overlay_element SetShader( "paint_overlay", 640, 480 );
notification_overlay_element.alpha = 0.0;
notification_overlay_element.color = ( 0, 0, 0 );
notification_overlay_element.sort = -3;
// Make sure nothing is getting set unexpectedly elsewhere.
Assert( !IsDefined(notification_overlay_element.hidden));
notification_overlay_element.hidden = true;
FadeInTime = 0.5;
FadeOutTime = .3;
while(1)
{
AssertEx(IsDefined(self._threatdetection), "_threatdetection isn't defined");
// Check if the showlist isn't empty (value updated in monitorThreatHighlight())
if(self._threatdetection.showlist.size != 0)
{
// If hud element (overlay) is hidden, branch out a thread to fade the overlay in and out.
if( notification_overlay_element.hidden )
{
notification_overlay_element.hidden = false;
notification_overlay_element childthread threatNotificationOverlayFlash( FadeInTime, FadeOutTime );
}
}
else // If showlist is empty...
{
// ...and the hud element is visible, tell the looping thread to stop fading the overlay in and out.
if(!notification_overlay_element.hidden)
{
notification_overlay_element.hidden = true;
notification_overlay_element notify( "stop_overlay_flash" );
// If the overlay wasn't completely faded out, force it to fade out quickly.
if(notification_overlay_element.alpha > 0.0)
{
notification_overlay_element FadeOverTime( FadeOutTime );
notification_overlay_element.color = ( 0, 0, 0 );
notification_overlay_element.alpha = 0.0;
wait( FadeOutTime );
}
}
}
wait(0.05);
}
}
// Called on the overlay hud element in monitorThreatHighlightNotification() to cause it to fade in and out until notified to stop.
threatNotificationOverlayFlash( FadeInTime, FadeOutTime )
{
self endon( "stop_overlay_flash" );
self FadeOverTime( FadeInTime );
self.color = ( 1, 1, 1 );
self.alpha = 1.0;
/*while(1)
{
self FadeOverTime( FadeInTime );
self.alpha = 1.0;
wait( FadeInTime );
self FadeOverTime( FadeOutTime );
self.alpha = 0.0;
wait( FadeOutTime );
}*/
}
debugHelper()
{
while( 1 )
{
dist = Distance( self.origin, level.players[0].origin );
Print3d( self.origin + (0,0,64), dist );
thread draw_line_for_time( level.players[0].origin, self.origin, 1,1,1, 0.3 );
if( isdefined( self._threatdetection.mark_enemy_model ) )
thread draw_line_for_time( level.players[0].origin, self._threatdetection.mark_enemy_model.origin, 1,1,1, 0.3 );
wait 0.3;
}
}
cleanUpOnDeath()
{
self endon("disconnect");
while( 1 )
{
self waittill("death");
self removeThreatEvents();
}
}
removeThreatEvents()
{
foreach(player in level.players)
{
foreach( obj in player._threatdetection.showlist )
{
if(obj.player == self)
{
obj.endTime = 0;
}
}
}
threatStyle = GetThreatStyle();
if( threatStyle == "attached_glow" )
{
visitFXEnt( ::visitorHideAll, ::getHostileMarker, undefined );
}
}
detection_highlight_hud_effect_on( player, duration, bLessIntense )
{
Assert( IsDefined( player ) );
radar_highlight = NewClientHudElem( player );
if( isDefined ( bLessIntense ) && bLessIntense )
radar_highlight.color = (0.1, 0.0015, 0.0015);
else
radar_highlight.color = (1.0, 0.015, 0.015);
radar_highlight.alpha = 1.0;
radar_highlight SetRadarHighlight( duration );
return radar_highlight;
}
detection_highlight_hud_effect_off( radar_highlight )
{
if(isDefined(radar_highlight))
{
radar_highlight Destroy();
}
}
detection_highlight_hud_effect( player, duration, bLessIntense, playerEndonString )
{
radar_highlight = detection_highlight_hud_effect_on( player, duration, bLessIntense );
if ( IsDefined( playerEndonString ) )
player waittill_notify_or_timeout( playerEndonString, duration );
else
wait duration;
detection_highlight_hud_effect_off( radar_highlight );
}
detection_grenade_hud_effect( player, position, duration, radius )
{
Assert( IsDefined( player ) );
radar_ping = NewHudElem();
radar_ping.x = position[0];
radar_ping.y = position[1];
radar_ping.z = position[2];
SetDevDvarIfUninitialized("scr_paintexplosionalpha",1.0);
SetDevDvarIfUninitialized("scr_paintexplosionred",1.0);
SetDevDvarIfUninitialized("scr_paintexplosiongreen",0.015);
SetDevDvarIfUninitialized("scr_paintexplosionblue",0.015);
SetDevDvarIfUninitialized("scr_paintexplosionwidth",500);
radar_ping.color = (GetDvarFloat("scr_paintexplosionred"), GetDvarFloat("scr_paintexplosiongreen"), GetDvarFloat("scr_paintexplosionblue"));
radar_ping.alpha = GetDvarFloat("scr_paintexplosionalpha"); // mp uses 5 bits to store alpha
width = GetDvarInt("paintexplosionwidth");
// doubling radius and duration so we have no chance of it cycling
radar_ping SetRadarPing(int(radius + width / 2), int(width), duration + .05);
// /# IPrintLn("PING"); #/
wait duration;
// /# IPrintLn("PONG"); #/
if(isDefined(radar_ping))
{
radar_ping Destroy();
}
}
/*
=============
///ScriptDocBegin
"Name: exo_ping_hud_effect( <position> , <duration> , <radius> , <player>, <bLessIntense> )"
"Summary: creates an effect for the Exo Ping tactical equipment."
"Module: Entity"
"CallOn: a player"
"MandatoryArg: <position>: the position of the effect"
"MandatoryArg: <duration>: the duraction of the effect"
"MandatoryArg: <radius>: the radius of the effect"
"OptionalArg: <player>: the client to show this effect to. If undefined, the effect shows to all clients."
"OptionalArg: <bLessIntense>: less intense version of the effect. If false or undefined, uses the default color."
"Example: thread maps\mp\_threatdetection::exo_ping_hud_effect( self.origin + ( 0, 0, 40 ), EXO_PING_DURATION, EXO_PING_RANGE, self, true );"
"SPMP: singleplayer"
///ScriptDocEnd
=============
*/
exo_ping_hud_effect( position, duration, radius, player, bLessIntense )
{
radar_ping = undefined;
if ( IsDefined( player ) )
radar_ping = NewClientHudElem( player );
else
radar_ping = NewHudElem();
radar_ping.x = position[0];
radar_ping.y = position[1];
radar_ping.z = position[2];
SetDevDvarIfUninitialized( "scr_exopingwidth", 100 );
if( isDefined( bLessIntense ) && bLessIntense )
radar_ping.color = ( 0.05, 0.05, 0.05 );
else
radar_ping.color = ( 0.8, 0.8, 0.8 );
radar_ping.alpha = 0.05; // mp uses 5 bits to store alpha
width = GetDvarInt( "scr_exopingwidth", 100 );
// doubling radius and duration so we have no chance of it cycling
radar_ping SetRadarPing( int( radius ), int( width ), duration + .05 );
wait duration;
if(isDefined(radar_ping))
{
radar_ping Destroy();
}
}
addThreatEvent( players_arr, event_duration_sec, event_type, updateHostile, updateFriendly, bPlaySound )
{
if( !IsAlive( self ) )
return;
currTime = GetTime();
endTime = currTime + ( event_duration_sec * 1000 );
losEndTime = endTime - ( 9 * ( event_duration_sec * 1000 ) / 10 );
threatStyle = GetThreatStyle();
if( endTime - losEndTime < 250 )
losEndTime = 250 + currTime;
if( threatStyle == "model" )
{
losEndTime = currTime;
}
else if( threatStyle == "vfx_model" )
{
losEndTime = currTime;
}
else if( threatStyle == "attached_glow" )
{
losEndTime = endTime; //attached glow stays glowy
}
else if( threatStyle == "stencil_outline" )
{
losEndTime = endTime;
}
foreach( p in players_arr )
{
//if( p == self )
// continue;
found = false;
foreach( obj in self._threatdetection.showlist )
{
if( obj.player == p )
{
//only update the time if it would last longer
if( endTime > obj.endTime )
{
obj.endTime = endTime;
obj.losEndTime = losEndTime;
obj.eventType = event_type;
}
found = true;
break;
}
}
if( !found )
{
index = self._threatdetection.showlist.size;
self._threatdetection.showlist[ index ] = SpawnStruct();
self._threatdetection.showlist[ index ].player = p;
self._threatdetection.showlist[ index ].endTime = endTime;
self._threatdetection.showlist[ index ].losEndTime = losEndTime;
self._threatdetection.showlist[ index ].eventType = event_type;
if (IsPlayer(self))
{
if( !isDefined( bPlaySound ) || bPlaySound )
self PlayLocalSound( "flag_spawned" ); // Play the flag_spawned oneshot any time someone is added to the showlist.
}
}
}
if (IsPlayer(self))
{
if( updateFriendly )
visitFXEnt( ::visitorUpdateMarkerPos, ::getFriendlyMarker, undefined );
if( updateHostile )
visitFXEnt( ::visitorUpdateMarkerPos, ::getHostileMarker, undefined );
}
}
stopThreatEventType( eventType )
{
foreach( obj in self._threatdetection.showlist )
{
if ( obj.eventType == eventType )
{
obj.endTime = 0;
}
}
threatStyle = GetThreatStyle();
if( threatStyle == "attached_glow" )
{
visitFXEnt( ::visitorHideAll, ::getHostileMarker, undefined );
}
}
visitFXEnt( visitorFn, accessorFn, show_to )
{
threatStyle = GetThreatStyle();
if( threatStyle == "glow" )
{
assert( IsPlayer( self ) );
foreach( i, fx in self.mark_fx.fx_ent )
{
assert( IsDefined( [[accessorFn]]( fx ) ) );
[[visitorFn]]( [[accessorFn]]( fx ), show_to, level._threatdetection.fx_data[i][0] );
}
}
else if( threatStyle == "model" )
{
assert( IsPlayer( self ) );
assert( IsDefined( [[accessorFn]]( self._threatdetection ) ) );
[[visitorFn]]( [[accessorFn]]( self._threatdetection ), show_to, "tag_origin" );
}
else if( threatStyle == "vfx_model" )
{
assert( IsPlayer( self ) );
assert( IsDefined( [[accessorFn]]( self._threatdetection ) ) );
[[visitorFn]]( [[accessorFn]]( self._threatdetection ), show_to, "tag_origin" );
}
else if( threatStyle == "attached_glow" )
{
assert( IsPlayer( self ) );
foreach( i, fx in self.mark_fx.fx_ent )
{
assert( IsDefined( [[accessorFn]]( fx ) ) );
[[visitorFn]]( [[accessorFn]]( fx ), show_to, level._threatdetection.fx_data[i][0] );
}
}
else if( threatStyle == "stencil_outline" )
{
[[visitorFn]]( self, show_to, "tag_origin" );
}
else
{
AssertEx( 0, "unknown threat style " + threatStyle + ". i dont know how to set it up" );
}
}
visitorRelink( member, player, bone )
{
member Unlink();
member.origin = self GetTagOrigin( bone );
member.angles = self GetTagAngles( bone );
member LinkTo( self, bone );
wait .05;
playFXOnTag( member.fx, member, "tag_origin" );
}
visitorHideAll( member, player, bone )
{
threatStyle = GetThreatStyle();
if( threatStyle == "attached_glow" )
{
StopFXOnTag( member.fx, member, "tag_origin" );
}
}
visitorUpdateMarkerPos( member, player, bone )
{
threatStyle = GetThreatStyle();
member.origin = self GetTagOrigin( bone );
member.angles = self GetTagAngles( bone );
if( threatStyle == "glow" )
{
triggerFx( member );
}
else if( threatStyle == "model" )
{
//update model pose now
desired_pose = "mp_hud_" + self GetStance() + "_char";
assert( isdefined( member ) );
is_hostile = ( member != self._threatDetection.mark_friendly_model );
if( is_hostile )
{
desired_pose += "_hostile";
}
current_pose = member.model;
if( desired_pose != current_pose )
member SetModel( desired_pose );
}
else if( threatStyle == "vfx_model" )
{
switch( self GetStance() )
{
case "prone":
desired_pose = "threat_detect_model_prone";
break;
case "crouch":
desired_pose = "threat_detect_model_crouch";
break;
case "stand":
//fallthrough
default:
desired_pose = "threat_detect_model_stand";//self.stance;
break;
}
assert( isdefined( member ) );
is_hostile = ( member != self._threatDetection.mark_friendly_model );
current_pose = self._threatdetection.friendly_pose;
if( is_hostile )
{
desired_pose += "_hostile";
current_pose = self._threatdetection.hostile_pose;
}
assert( IsDefined( current_pose ) );
if( current_pose != desired_pose )
{
forward = AnglesToForward( self.angles );
up = AnglesToUp( self.angles );
if( is_hostile )
{
self._threatdetection.mark_enemy_model delete();
self._threatdetection.mark_enemy_model = SpawnFx( GetFX( desired_pose ), self.origin, forward, up );
self._threatdetection.mark_enemy_model hide();
self._threatdetection.hostile_pose = desired_pose;
}
else
{
self._threatdetection.mark_friendly_model delete();
self._threatdetection.mark_friendly_model = SpawnFx( GetFX( desired_pose ), self.origin, forward, up );
self._threatdetection.mark_friendly_model hide();
self._threatdetection.friendly_pose = desired_pose;
}
}
if( is_hostile )
TriggerFX( self._threatdetection.mark_enemy_model );
else
TriggerFX( self._threatdetection.mark_friendly_model );
}
else if( threatStyle == "attached_glow" )
{
//do nothing on purpose
}
else if( threatStyle == "stencil_outline" )
{
//do nothing on purpose
}
else
{
AssertEx( 0, "unknown threat style " + threatStyle + ". i dont know how to set it up" );
}
}
getHostileMarker( obj )
{
threatStyle = GetThreatStyle();
if( threatStyle == "glow" )
return obj.enemyMarker;
else if( threatStyle == "model" )
return obj.mark_enemy_model;
else if( threatStyle == "vfx_model" )
return obj.mark_enemy_model;
else if( threatStyle == "attached_glow" )
return obj;
else if( threatStyle == "stencil_outline" )
return obj;
else
{
AssertEx( 0, "unknown threat style " + threatStyle + ". i dont know how to set it up" );
}
}
getFriendlyMarker( obj )
{
threatStyle = GetThreatStyle();
if( threatStyle == "glow" )
return obj.friendlyMarker;
else if( threatStyle == "model" )
return obj.mark_friendly_model;
else if( threatStyle == "vfx_model" )
return obj.mark_friendly_model;
else
{
AssertEx( 0, "unknown threat style " + threatStyle + ". i dont know how to set it up" );
}
}
getFriendlyLOSMarker( obj )
{
threatStyle = GetThreatStyle();
if( threatStyle == "glow" )
return obj.friendlyLOSMarker;
else if( threatStyle == "model" )
return obj.mark_friendly_model;
else if( threatStyle == "vfx_model" )
return obj.mark_friendly_model;
else
{
AssertEx( 0, "unknown threat style " + threatStyle + ". i dont know how to set it up" );
}
}
getHostileLOSMarker( obj )
{
threatStyle = GetThreatStyle();
if( threatStyle == "glow" )
return obj.enemyLOSMarker;
else if( threatStyle == "model" )
return obj.mark_enemy_model;
else if( threatStyle == "vfx_model" )
return obj.mark_enemy_model;
else if( threatStyle == "attached_glow" )
return obj;
else if( threatStyle == "stencil_outline" )
return obj;
else
{
AssertEx( 0, "unknown threat style " + threatStyle + ". i dont know how to set it up" );
}
}
//left for an exmple
visitHideAllMarkers( memberArr, player, bone )
{
assert( !isdefined( player ) );
foreach( m in memberArr )
{
m Hide();
}
}
accessAllMarkers( obj )
{
assert( isdefined( obj) );
return [obj.friendlyMarker, obj.enemyMarker, obj.friendlyLOSMarker, obj.enemyLOSMarker];
}
getNormalDirectionVec( raw_vec )
{
return VectorNormalize( flat_origin( raw_vec ) );
}
monitorThreatHighlight()
{
self threat_init( GetThreatStyle() );
height_offset = ( 0, 0, 32 );
all_hidden = false;
while( 1 )
{
wait .05;
currTime = GetTime();
anyoneNeedsDraw = false;
foreach( obj in self._threatdetection.showlist )
{
if( obj.endTime >= currTime )
{
if( !IsDefined( obj.player ) )
{
self._threatdetection.showlist = array_remove( self._threatdetection.showlist, obj );
continue;
}
obj.los = false;
//see if we're even in the view cone for the guy on the list
forward = getNormalDirectionVec( anglesToForward( obj.player.angles ) );
toTarget = getNormalDirectionVec( self.origin - obj.player.origin );
cos = VectorDot( toTarget, forward );
//we will cast against +/- 90
if( cos < 0 )
continue;
if( check_los( obj ) )
{
//use LOS vfx
obj.los = true;
//if we're in LOS we have a different end time
if( obj.losEndTime <= currTime )
{
self._threatdetection.showlist = array_remove( self._threatdetection.showlist, obj );
continue;
}
}
anyoneNeedsDraw = true;
}
else
{
self._threatdetection.showlist = array_remove( self._threatdetection.showlist, obj );
}
}
threatStyle = GetThreatStyle();
if( !all_hidden )
{
all_hidden = true;
if( threatStyle == "glow" )
{
foreach( i, fx in self.mark_fx.fx_ent )
{
fx.enemyMarker hide();
fx.friendlyMarker hide();
fx.enemyLosMarker hide();
fx.friendlyLosMarker hide();
}
}
else if( threatStyle == "model" )
{
self._threatdetection.mark_friendly_model hide();
self._threatdetection.mark_enemy_model hide();
}
else if( threatStyle == "vfx_model" )
{
self._threatdetection.mark_friendly_model hide();
self._threatdetection.mark_enemy_model hide();
}
else if( threatStyle == "attached_glow" )
{
foreach( i, obj in self.mark_fx.fx_ent )
{
StopFXOnTag( obj.fx, obj, "tag_origin" );
obj hide();
}
}
else if( threatStyle == "stencil_outline" )
{
self clearThreatDetected();
}
else
{
AssertEx( 0, "unknown threat style " + threatStyle + ". i dont know how to set it up" );
}
}
if( !anyoneNeedsDraw )
continue;
//walk the list of players and show to who we want
foreach( p in self._threatdetection.showlist )
{
assert( isdefined( p ) );
if( p.los )
{
assert( p.losEndTime >= currTime );
showThreat( p.player, ::getFriendlyLOSMarker, ::getHostileLOSMarker, ::visitorUpdateLOSMarker );
prepare_show_threat( all_hidden, threatStyle, p.player );//playfxontag needs to be after the show of the ent
all_hidden = false;
}
else
{
assert( p.endTime >= currTime );
//if we cant see our target make sure we cant see the marker object
result = BulletTrace( p.player.origin + height_offset, self.origin + height_offset, true, p.player );
if( result["fraction"] < 1 && !isplayer(result["entity"]) ) // we can't see the blob
{
showThreat( p.player, ::getFriendlyMarker, ::getHostileMarker, ::visitorShowToPlayer );
prepare_show_threat( all_hidden, threatStyle, p.player );//playfxontag needs to be after the show of the ent
all_hidden = false;
}
}
}
}
}
prepare_show_threat( already_drawn, threatStyle, player )
{
if( already_drawn ) //meaning we have not shown to anyone yet this frame
{
if( threatStyle == "attached_glow" )
{
assert( IsPlayer( self ) );
showThreat( player, ::getFriendlyLOSMarker, ::getHostileLOSMarker, ::visitorRetriggerFX );
}
}
}
visitorRetriggerFX( member, player, bone )
{
/#
threatStyle = GetThreatStyle();
assert(threatStyle == "attached_glow" );
#/
//StopFXOnTag( member.fx, member, "tag_origin" );//stop is happening in the hide of monitorThreatHighlight
PlayFXOnTag( member.fx, member, "tag_origin" );
}
check_los( obj )
{
//temp to solve problem if player is behind partial cover.
if( BulletTracePassed( obj.player GetEye(), self GetEye(), false, obj.player ) )
return true;
return false;
}
threat_init( threatStyle )
{
mark_fx_struct = SpawnStruct();
mark_fx_struct.fx_ent = [];
if( threatStyle == "glow" )
{
foreach ( i,fx in level._threatdetection.fx_data )
{
mark_fx_ent = SpawnStruct();
mark_fx_ent.origin = self GetTagOrigin( fx[0] );
mark_fx_ent.angles = self GetTagAngles( fx[0] );
mark_fx_ent.enemyMarker = SpawnFx( fx[1], mark_fx_ent.origin );
triggerFx( mark_fx_ent.enemyMarker );
mark_fx_ent.enemyMarker hide();
mark_fx_ent.enemyLosMarker = SpawnFx( fx[3], mark_fx_ent.origin );
triggerFx( mark_fx_ent.enemyLosMarker );
mark_fx_ent.enemyLosMarker hide();
mark_fx_ent.friendlyMarker = SpawnFx( fx[2], mark_fx_ent.origin );
triggerFx( mark_fx_ent.friendlyMarker );
mark_fx_ent.friendlyMarker hide();
mark_fx_ent.friendlyLosMarker = SpawnFx( fx[4], mark_fx_ent.origin );
triggerFx( mark_fx_ent.friendlyLosMarker );
mark_fx_ent.friendlyLosMarker hide();
mark_fx_struct.fx_ent[ i ] = mark_fx_ent;
}
self.mark_fx = mark_fx_struct;
}
else if( threatStyle == "model" )
{
model = spawn( "script_model", self.origin );
model.origin = self.origin;
model.angles = self.angles;
//print( "we would like to use " + self.model );
model setmodel( level._threatdetection.friendlyModel );
model SetContents( 0 );
//model codescripts\character::attachHead( "alias_africa_militia_heads_mp", xmodelalias\alias_africa_militia_heads_mp::main() );
self._threatDetection.mark_friendly_model = model;
model = spawn( "script_model", self.origin );
model.origin = self.origin;
model.angles = self.angles;
//print( "we would like to use " + self.model );
model setmodel( level._threatdetection.hostileModel );
model SetContents( 0 );
//model codescripts\character::attachHead( "alias_africa_militia_heads_mp", xmodelalias\alias_africa_militia_heads_mp::main() );
self._threatDetection.mark_enemy_model = model;
}
else if( threatStyle == "vfx_model")
{
self._threatDetection.mark_friendly_model = SpawnStruct();
self._threatDetection.mark_friendly_model = SpawnFx( GetFX( "threat_detect_model_stand" ), self.origin, AnglesToForward( self.angles ), AnglesToUp( self.angles ) );
self._threatDetection.friendly_pose = "threat_detect_model_stand";
self._threatDetection.mark_enemy_model = SpawnStruct();
self._threatDetection.mark_enemy_model = SpawnFx( GetFX( "threat_detect_model_stand_hostile" ), self.origin, AnglesToForward( self.angles ), AnglesToUp( self.angles ) );
self._threatDetection.hostile_pose = "threat_detect_model_stand_hostile";
}
else if( threatStyle == "attached_glow" )
{
foreach ( i,fx in level._threatdetection.fx_data )
{
tag_org = spawn_tag_origin();
tag_org show(); //spawn_tag_origin calls hide and if we dont show it, it will not be sent to any clients
tag_org.origin = self GetTagOrigin( fx[0] );
tag_org.angles = self GetTagAngles( fx[0] );
tag_org LinkTo( self, fx[0] );
tag_org.fx = fx[1];
//wait .05;
//PlayFXOnTag( tag_org.fx, tag_org, "tag_origin" );
mark_fx_struct.fx_ent[ i ] = tag_org;
}
self.mark_fx = mark_fx_struct;
}
else if( threatStyle == "stencil_outline" )
{
// does nothing on purpose
}
else
{
AssertEx( 0, "unknown threat style " + threatStyle + ". i dont know how to set it up" );
}
}
visitorUpdateLOSMarker( member, player, bone )
{
visitorUpdateMarkerPos( member, player, bone );
visitorShowToPlayer( member, player, bone );
}
visitorShowToPlayer( member, player, bone )
{
assert( IsDefined( player ) && isplayer( player ) );
assert( IsDefined( member ) );
threatStyle = GetThreatStyle();
if (threatStyle == "stencil_outline")
{
member threatDetectedToPlayer( player );
}
else
{
member showToPlayer( player );
}
}
showThreat( player, friendlyFn, hostileFn, visitorFn )
{
if ( player == self )
return;
memberFunc = hostileFn;
if( ( level.teamBased || level.multiteambased ) && player.team == self.team )
{
memberFunc = friendlyFn;
}
//for FFA
else if( player == self )
{
memberFunc = friendlyFn;
}
visitFXEnt( visitorFn, memberFunc, player );
}