2024-09-02 07:03:07 -04:00
/* p_client.c */
# include "g_local.h"
# include "m_player.h"
# include "stdlog.h" // StdLog - Mark Davies
# include "wf_classmgr.h"//acrid for WFCopyToBodyQue
FILE * zbotfile = NULL ;
int deas = 10 ;
//ERASER START
///Q2 Camera Begin
# include "camclient.h"
///Q2 Camera End
# include "p_trail.h"
# include "bot_procs.h"
# include <sys/timeb.h>
# include <time.h>
# define OPTIMIZE_INTERVAL 0.1
int num_clients = 0 ;
//ERASER END
void ClientUserinfoChanged ( edict_t * ent , char * userinfo ) ;
void SP_misc_teleporter_dest ( edict_t * ent ) ;
void WFRemoveDisguise ( edict_t * ent ) ;
void Drop_General ( edict_t * ent , gitem_t * item ) ;
void HealPlayer ( edict_t * ent ) ;
void I_AM_A_ZBOT ( edict_t * ent ) ;
qboolean ZbotCheck ( edict_t * ent , usercmd_t * ucmd ) ;
//Utility function to fix player name so it doesnt have a '%' in it
void wfFixName ( char * text )
{
int j ;
j = 0 ;
while ( j < 150 & & text [ j ] ! = 0 )
{
if ( text [ j ] = = ' % ' ) text [ j ] = ' _ ' ; // don't allow formated characters in text
+ + j ;
}
}
//
// Gross, ugly, disgustuing hack section
//
// this function is an ugly as hell hack to fix some map flaws
//
// the coop spawn spots on some maps are SNAFU. There are coop spots
// with the wrong targetname as well as spots with no name at all
//
// we use carnal knowledge of the maps to fix the coop spot targetnames to match
// that of the nearest named single player spot
static void SP_FixCoopSpots ( edict_t * self )
{
edict_t * spot ;
vec3_t d ;
spot = NULL ;
while ( 1 )
{
spot = G_Find ( spot , FOFS ( classname ) , " info_player_start " ) ;
if ( ! spot )
return ;
if ( ! spot - > targetname )
continue ;
VectorSubtract ( self - > s . origin , spot - > s . origin , d ) ;
if ( VectorLength ( d ) < 384 )
{
if ( ( ! self - > targetname ) | | Q_stricmp ( self - > targetname , spot - > targetname ) ! = 0 )
{
// gi.dprintf("FixCoopSpots changed %s at %s targetname from %s to %s\n", self->classname, vtos(self->s.origin), self->targetname, spot->targetname);
self - > targetname = spot - > targetname ;
}
return ;
}
}
}
// now if that one wasn't ugly enough for you then try this one on for size
// some maps don't have any coop spots at all, so we need to create them
// where they should have been
static void SP_CreateCoopSpots ( edict_t * self )
{
edict_t * spot ;
if ( Q_stricmp ( level . mapname , " security " ) = = 0 )
{
spot = G_Spawn ( ) ;
spot - > classname = " info_player_coop " ;
spot - > s . origin [ 0 ] = 188 - 64 ;
spot - > s . origin [ 1 ] = - 164 ;
spot - > s . origin [ 2 ] = 80 ;
spot - > targetname = " jail3 " ;
spot - > s . angles [ 1 ] = 90 ;
spot = G_Spawn ( ) ;
spot - > classname = " info_player_coop " ;
spot - > s . origin [ 0 ] = 188 + 64 ;
spot - > s . origin [ 1 ] = - 164 ;
spot - > s . origin [ 2 ] = 80 ;
spot - > targetname = " jail3 " ;
spot - > s . angles [ 1 ] = 90 ;
spot = G_Spawn ( ) ;
spot - > classname = " info_player_coop " ;
spot - > s . origin [ 0 ] = 188 + 128 ;
spot - > s . origin [ 1 ] = - 164 ;
spot - > s . origin [ 2 ] = 80 ;
spot - > targetname = " jail3 " ;
spot - > s . angles [ 1 ] = 90 ;
return ;
}
}
/*QUAKED info_player_start (1 0 0) (-16 -16 -24) (16 16 32)
The normal starting point for a level .
*/
void SP_info_player_start ( edict_t * self )
{
if ( ! coop - > value )
return ;
if ( Q_stricmp ( level . mapname , " security " ) = = 0 )
{
// invoke one of our gross, ugly, disgusting hacks
self - > think = SP_CreateCoopSpots ;
self - > nextthink = level . time + FRAMETIME ;
}
}
//ERASER START
edict_t * dm_spots [ 64 ] ;
int num_dm_spots ;
//ERASER END
/*QUAKED info_player_deathmatch (1 0 1) (-16 -16 -24) (16 16 32)
potential spawning position for deathmatch games
*/
void SP_info_player_deathmatch ( edict_t * self )
{
if ( ! deathmatch - > value )
{
G_FreeEdict ( self ) ;
return ;
}
SP_misc_teleporter_dest ( self ) ;
dm_spots [ num_dm_spots + + ] = self ; //ERASER
}
/*QUAKED info_player_coop (1 0 1) (-16 -16 -24) (16 16 32)
potential spawning position for coop games
*/
void SP_info_player_coop ( edict_t * self )
{
if ( ! coop - > value )
{
G_FreeEdict ( self ) ;
return ;
}
if ( ( Q_stricmp ( level . mapname , " jail2 " ) = = 0 ) | |
( Q_stricmp ( level . mapname , " jail4 " ) = = 0 ) | |
( Q_stricmp ( level . mapname , " mine1 " ) = = 0 ) | |
( Q_stricmp ( level . mapname , " mine2 " ) = = 0 ) | |
( Q_stricmp ( level . mapname , " mine3 " ) = = 0 ) | |
( Q_stricmp ( level . mapname , " mine4 " ) = = 0 ) | |
( Q_stricmp ( level . mapname , " lab " ) = = 0 ) | |
( Q_stricmp ( level . mapname , " boss1 " ) = = 0 ) | |
( Q_stricmp ( level . mapname , " fact3 " ) = = 0 ) | |
( Q_stricmp ( level . mapname , " biggun " ) = = 0 ) | |
( Q_stricmp ( level . mapname , " space " ) = = 0 ) | |
( Q_stricmp ( level . mapname , " command " ) = = 0 ) | |
( Q_stricmp ( level . mapname , " power2 " ) = = 0 ) | |
( Q_stricmp ( level . mapname , " strike " ) = = 0 ) )
{
// invoke one of our gross, ugly, disgusting hacks
self - > think = SP_FixCoopSpots ;
self - > nextthink = level . time + FRAMETIME ;
}
}
/*QUAKED info_player_intermission (1 0 1) (-16 -16 -24) (16 16 32)
The deathmatch intermission point will be at one of these
Use ' angles ' instead of ' angle ' , so you can set pitch or roll as well as yaw . ' pitch yaw roll '
*/
void SP_info_player_intermission ( void )
{
}
/*QUAKED info_position (1 0 1) (-16 -16 -24) (16 16 32)
Used to describe the location within a map
Use ' angles ' instead of ' angle ' , so you can set pitch or roll as well as yaw . ' pitch yaw roll '
*/
void SP_info_position ( edict_t * ent )
{
/*
gi . dprintf ( " DEBUG (Spawned info_position) Classname = %s \n " , ent - > classname ) ;
if ( ent - > message & & ent - > message [ 0 ] )
gi . dprintf ( " DEBUG (info_position) Message = %s \n " , ent - > message ) ;
*/
}
/*QUAKED item_flagreturn (1 0 1) (-16 -16 -24) (16 16 32)
Used to describe the location of the flag return base
*/
void SP_item_flagreturn ( edict_t * ent )
{
// gi.dprintf("--Spawned %s. Target = %s, ent = %d\n", ent->classname, ent->target, ent);
}
//=======================================================================
void player_pain ( edict_t * self , edict_t * other , float kick , int damage )
{
// player pain is handled at the end of the frame in P_DamageFeedback
}
qboolean IsFemale ( edict_t * ent )
{
if ( ! ent - > client )
return false ;
if ( ent - > client - > player_model = = CLASS_MODEL_FEMALE )
return true ;
else
return false ;
}
//WF
qboolean IsCyborg ( edict_t * ent )
{
if ( ! ent - > client )
return false ;
if ( ent - > client - > player_model = = CLASS_MODEL_CYBORG )
return true ;
else
return false ;
}
//WF
//Not female, male or cyborg?
qboolean IsNeutral ( edict_t * ent )
{
if ( ! ent - > client )
return false ;
if ( ( ent - > client - > player_model = = CLASS_MODEL_FEMALE ) | |
( ent - > client - > player_model = = CLASS_MODEL_MALE ) | |
( ent - > client - > player_model = = CLASS_MODEL_CYBORG ) )
return false ;
else
return true ;
}
int PlayerChangeScore ( edict_t * self , int points )
{
if ( wf_game . game_halted )
{
safe_cprintf ( self , PRINT_HIGH , " No Scoring Allowed While Game Is Suspended \n " ) ;
return false ;
}
else
self - > client - > resp . score + = points ;
return true ;
}
void ClientObituary ( edict_t * self , edict_t * inflictor , edict_t * atk )
{
int mod ;
char * message ;
char * message2 ;
qboolean ff ;
edict_t * attacker ;
qboolean special_message ;
special_message = false ;
attacker = atk ;
//If this is a death by sentry gun, then the attacker's owner
//is the real attacker
if ( ( atk - > creator ) & & ( ! atk - > client ) & & ( meansOfDeath = = MOD_SENTRY | | meansOfDeath = = MOD_SENTRY_ROCKET | | meansOfDeath = = MOD_SHRAPNEL | | meansOfDeath = = MOD_PELLET ) )
attacker = atk - > creator ;
if ( coop - > value & & attacker - > client )
meansOfDeath | = MOD_FRIENDLY_FIRE ;
//ERASER START //ACRID FIXME? teamplay
else if ( deathmatch - > value & & teamplay - > value & & attacker - > client & & SameTeam ( self , attacker ) )
{
meansOfDeath | = MOD_FRIENDLY_FIRE ;
}
//ERASER END
if ( deathmatch - > value | | coop - > value )
{
ff = meansOfDeath & MOD_FRIENDLY_FIRE ;
mod = meansOfDeath & ~ MOD_FRIENDLY_FIRE ;
message = NULL ;
message2 = " " ;
switch ( mod )
{
case MOD_SUICIDE :
message = " suicides " ;
break ;
case MOD_FALLING :
message = " cratered " ;
break ;
case MOD_CRUSH :
message = " was squished " ;
break ;
case MOD_WATER :
message = " sank like a rock " ;
break ;
case MOD_SLIME :
message = " melted " ;
break ;
case MOD_LAVA :
message = " does a back flip into the lava " ;
break ;
case MOD_FEIGN :
message = " died while trying to feign " ;
break ;
case MOD_EXPLOSIVE :
case MOD_BARREL :
message = " blew up " ;
break ;
case MOD_EXIT :
message = " found a way out " ;
break ;
//TeT - Laser is not suicide
// case MOD_TARGET_LASER:
// message = "saw the light";
// break;
case MOD_TARGET_BLASTER :
message = " got blasted " ;
break ;
case MOD_BOMB :
case MOD_SPLASH :
case MOD_TRIGGER_HURT :
message = " was in the wrong place " ;
break ;
}
if ( attacker = = self )
{
switch ( mod )
{
case MOD_HELD_GRENADE :
message = " tried to put the pin back in " ;
break ;
case MOD_HG_SPLASH :
case MOD_G_SPLASH :
if ( IsNeutral ( self ) )
message = " tripped on its own grenade " ;
else if ( IsFemale ( self ) )
message = " tripped on her own grenade " ;
else
message = " tripped on his own grenade " ;
break ;
case MOD_R_SPLASH :
if ( IsNeutral ( self ) )
message = " blew itself up " ;
else if ( IsFemale ( self ) )
message = " blew herself up " ;
else
message = " blew himself up " ;
break ;
case MOD_BFG_BLAST :
message = " should have used a smaller gun " ;
break ;
case MOD_FEIGN :
message = " died while trying to feign " ;
break ;
default :
if ( IsNeutral ( self ) )
message = " killed itself " ;
else if ( IsFemale ( self ) )
message = " killed herself " ;
else
message = " killed himself " ;
break ;
}
}
if ( message )
{
my_bprintf ( PRINT_MEDIUM , " %s %s. \n " , self - > client - > pers . netname , message ) ;
if ( deathmatch - > value )
{
if ( PlayerChangeScore ( self , CTF_SUICIDE_POINTS ) )
sl_LogScore ( & gi , self - > client - > pers . netname , " " , " Suicide " , mod , CTF_SUICIDE_POINTS ) ; // StdLog
}
self - > enemy = NULL ;
if ( special_message )
{
// safe_cprintf(self, PRINT_HIGH, "[YOU KILLED YOURSELF: ");
// if ((inflictor) && (inflictor->classname))
// safe_cprintf(self, PRINT_HIGH, " item=%s",inflictor->classname);
// safe_cprintf(self, PRINT_HIGH, "]\n");
}
//if (wfdebug) gi.dprintf("diseased = %d. Diseased by = %d\n", self->disease, self->diseased_by);
//If player is diseased, give credit to nurse who infected them
if ( self - > disease & & self - > diseased_by & & self - > diseased_by - > client & & self - > diseased_by - > inuse )
{
if ( PlayerChangeScore ( self - > diseased_by , CTF_FRAG_POINTS ) )
sl_LogScore ( & gi , self - > diseased_by - > client - > pers . netname , self - > client - > pers . netname , " Kill " , mod , CTF_FRAG_POINTS ) ; // StdLog - Mark Davies
my_bprintf ( PRINT_MEDIUM , " %s gets a frag for %s's suicide while diseased. \n " , self - > diseased_by - > client - > pers . netname , self - > client - > pers . netname ) ;
}
return ;
}
self - > enemy = attacker ;
if ( attacker & & attacker - > client )
{
switch ( mod )
{
case MOD_BLASTER :
message = " was blasted by " ;
break ;
case MOD_SHOTGUN :
message = " was gunned down by " ;
break ;
case MOD_SSHOTGUN :
message = " was blown away by " ;
message2 = " 's super shotgun " ;
break ;
case MOD_MACHINEGUN :
message = " was machinegunned by " ;
break ;
case MOD_CHAINGUN :
message = " was cut in half by " ;
message2 = " 's chaingun " ;
break ;
case MOD_GRENADE :
message = " was popped by " ;
message2 = " 's grenade " ;
break ;
case MOD_G_SPLASH :
message = " was shredded by " ;
message2 = " 's shrapnel " ;
break ;
case MOD_ROCKET :
message = " ate " ;
message2 = " 's rocket " ;
break ;
case MOD_MISSILE :
message = " was eliminated by " ;
message2 = " 's missile launcher " ;
break ;
case MOD_HOMINGROCKET :
message = " was slammed " ;
message2 = " 's homing rocket " ;
break ;
case MOD_R_SPLASH :
message = " almost dodged " ;
message2 = " 's rocket " ;
break ;
case MOD_HYPERBLASTER :
message = " was melted by " ;
message2 = " 's hyperblaster " ;
break ;
case MOD_RAILGUN :
message = " was railed by " ;
break ;
case MOD_BFG_LASER :
message = " saw the pretty lights from " ;
message2 = " 's BFG " ;
break ;
case MOD_BFG_BLAST :
message = " was disintegrated by " ;
message2 = " 's BFG blast " ;
break ;
case MOD_BFG_EFFECT :
message = " couldn't hide from " ;
message2 = " 's BFG " ;
break ;
case MOD_HANDGRENADE :
message = " caught " ;
message2 = " 's handgrenade " ;
break ;
case MOD_HG_SPLASH :
message = " didn't see " ;
message2 = " 's handgrenade " ;
break ;
case MOD_HELD_GRENADE :
message = " feels " ;
message2 = " 's pain " ;
break ;
case MOD_TELEFRAG :
message = " tried to invade " ;
message2 = " 's personal space " ;
break ;
//ZOID
case MOD_GRAPPLE :
message = " was caught by " ;
message2 = " 's grapple " ;
break ;
//ZOID
//WF
case MOD_WF_LASERBALL :
message = " was fried by " ;
message2 = " 's laserball " ;
break ;
case MOD_WF_GOODYEAR :
message = " was popped by " ;
message2 = " 's goodyear grenade " ;
break ;
case MOD_WF_PROXIMITY :
message = " swallowed " ;
message2 = " 's proximity grenade " ;
break ;
case MOD_WF_CLUSTER :
message = " was ripped by " ;
message2 = " 's cluster grenade " ;
break ;
case MOD_WF_PIPEBOMB :
message = " fell for " ;
message2 = " 's pipebomb " ;
break ;
case MOD_WF_EARTHQUAKE :
message = " was shaken by " ;
message2 = " 's earthquake " ;
break ;
case MOD_WF_FLAME :
message = " was burned by " ;
message2 = " 's flame " ;
break ;
case MOD_FLAMETHROWER :
message = " was charred by " ;
message2 = " 's flame-thrower " ;
break ;
case MOD_REVERSE_TELEFRAG :
message = " was reverse telefragged by " ;
break ;
case MOD_NAG :
message = " was NAGed to death by " ;
break ;
case MOD_SHRAPNEL :
message = " was pithed by " ;
message2 = " 's shrapnel grenade " ;
break ;
case MOD_CLUSTERROCKET :
message = " was splattered by " ;
message2 = " 's cluster rocket " ;
break ;
case MOD_DISEASE :
message = " died from " ;
message2 = " 's disease " ;
break ;
case MOD_SNIPERRIFLE :
message = " was slaughtered by " ;
message2 = " 's sniper rifle " ;
break ;
case MOD_SNIPERRIFLE_LEG :
message = " had their legs shot out by " ;
message2 = " 's sniper rifle " ;
break ;
case MOD_SNIPERRIFLE_HEAD :
message = " had his head blown off by " ;
message2 = " 's sniper rifle " ;
break ;
case MOD_SHC :
message = " burst into flames from " ;
message2 = " 's SHC rifle " ;
break ;
case MOD_NEEDLER :
message = " was needled by " ;
break ;
case MOD_CONCUSSION :
message = " lost his head from " ;
message2 = " 's concussion grenade " ;
break ;
case MOD_ARMORDART :
message = " was pierced by " ;
message2 = " 's dart " ;
break ;
case MOD_INFECTEDDART :
message = " was infected by " ;
message2 = " 's dart " ;
break ;
case MOD_NAPALMROCKET :
message = " was smoked by " ;
message2 = " 's napalm rocket " ;
break ;
case MOD_NAPALMGRENADE :
message = " got crispy from " ;
message2 = " 's napalm grenade " ;
break ;
case MOD_LIGHTNING :
message = " saw lightning from " ;
message2 = " 's lightning gun " ;
break ;
case MOD_TELSA :
message = " was exposed to " ;
message2 = " 's telsa coil " ;
break ;
case MOD_MAGNOTRON :
message = " was sucked into " ;
message2 = " 's magnotron " ;
break ;
case MOD_SHOCK :
message = " was shocked by " ;
break ;
case MOD_PELLET :
message = " was pelted by " ;
break ;
case MOD_FLAREGUN :
message = " was embarrassed to be toasted by " ;
message2 = " 's flare gun " ;
break ;
case MOD_FLARE :
message = " was snuffed by " ;
message2 = " 's flare " ;
break ;
case MOD_TRANQUILIZER :
message = " slowed to a stop from " ;
message2 = " 's tranquilizer " ;
break ;
case MOD_LRPROJECTILE :
message = " was blasted by " ;
message2 = " 's LR Projectile Launcher " ;
break ;
case MOD_BOLTEDBLASTER :
message = " expired from " ;
message2 = " 's bolted blaster " ;
break ;
case MOD_WF_TURRET :
message = " caught Turret's Syndrome from " ;
message2 = " 's Turret Grenade. " ;
break ;
case MOD_PLASMABOMB :
message = " was vaporized by " ;
break ;
case MOD_NAIL :
message = " was nailed by " ;
//message2 = "";
break ;
case MOD_MBPC :
message = " was disintegrated by " ;
message2 = " 's Pulse Cannon " ;
break ;
case MOD_SENTRY :
message = " was laid low by " ;
message2 = " 's Sentry Gun " ;
break ;
case MOD_SENTRY_ROCKET :
message = " was liquidated by " ;
message2 = " 's Sentry Gun Rocket " ;
break ;
case MOD_KAMIKAZE :
message = " didn't survive " ;
message2 = " 's Kamikaze run " ;
break ;
case MOD_TRANQUILIZERDART :
message = " did not escape " ;
message2 = " 's tranquilizer dart " ;
break ;
case MOD_DEPOT :
message = " was blown to bits by " ;
message2 = " 's supply depot " ;
break ;
case MOD_DEPOT_EXPLODE :
message = " was in the way when " ;
message2 = " blew up a supply depot " ;
break ;
case MOD_HEALINGDEPOT :
message = " was blown to bits by " ;
message2 = " 's healing depot " ;
break ;
case MOD_MEGACHAINGUN :
message = " was cut to ribbons " ;
message2 = " 's mega chaingun " ;
break ;
case MOD_SENTRYKILLER :
message = " got in the way of " ;
message2 = " 's Sentry Killer Rocket " ;
break ;
case MOD_KNIFE :
message = " was punctured by " ;
message2 = " 's knife " ;
break ;
case MOD_STINGER :
message = " was stopped by " ;
message2 = " 's stinger " ;
break ;
case MOD_KNIFEBACK :
message = " was stabbed in the back by " ;
message2 = " 's knife " ;
break ;
case MOD_FREEZER :
message = " was iced by " ; //acrid 3/99 death msg
message2 = " 's freezer " ;
break ;
case MOD_LASERCUTTER :
message = " was sliced and diced by " ;
message2 = " 's laser cutter grenade " ;
break ;
case MOD_TESLA :
message = " was electrified by " ;
message2 = " 's tesla grenade " ;
break ;
case MOD_GASGRENADE :
message = " was fumigated by " ;
message2 = " 's gas grenade " ;
break ;
case MOD_AK47 :
message = " became swiss cheese from " ;
message2 = " 's AK47 " ;
break ;
case MOD_PISTOL :
message = " was assassinated by " ;
message2 = " 's pistol " ;
break ;
case MOD_TARGET_LASER :
message = " saw " ;
message2 = " 's light " ;
break ;
case MOD_CAMERA :
message = " smiled for " ;
message2 = " 's camera " ;
break ;
}
if ( message )
{
my_bprintf ( PRINT_MEDIUM , " %s %s %s%s \n " , self - > client - > pers . netname , message , attacker - > client - > pers . netname , message2 ) ;
if ( deathmatch - > value )
{
if ( ff )
{
if ( PlayerChangeScore ( attacker , CTF_SUICIDE_POINTS ) )
sl_LogScore ( & gi , attacker - > client - > pers . netname , self - > client - > pers . netname , " Friendly Fire " , mod , CTF_SUICIDE_POINTS ) ; // StdLog - Mark Davies
}
else
{
if ( PlayerChangeScore ( attacker , CTF_FRAG_POINTS ) )
sl_LogScore ( & gi , attacker - > client - > pers . netname , self - > client - > pers . netname , " Kill " , mod , CTF_FRAG_POINTS ) ; // StdLog - Mark Davies
}
}
return ;
}
}
}
my_bprintf ( PRINT_MEDIUM , " %s died. \n " , self - > client - > pers . netname ) ;
// safe_cprintf(self, PRINT_HIGH, "[YOU WERE KILLED WITH: ");
// if ((inflictor) && (inflictor->classname))
// safe_cprintf(self, PRINT_HIGH, " %s",inflictor->classname);
// if ((attacker) && (attacker->client) && (attacker->client->pers.netname))
// safe_cprintf(self, PRINT_HIGH, " BY %s",attacker->client->pers.netname);
// safe_cprintf(self, PRINT_HIGH, "]\n");
if ( deathmatch - > value )
PlayerChangeScore ( self , - 1 ) ;
}
void Touch_Item ( edict_t * ent , edict_t * other , cplane_t * plane , csurface_t * surf ) ;
void TossClientWeapon ( edict_t * self )
{
gitem_t * item ;
edict_t * drop ;
qboolean quad ;
float spread ;
if ( ! deathmatch - > value )
return ;
//WF If player classes are on, don't drop a weapon
if ( self - > client & & ( ( ( int ) wfflags - > value & WF_NO_PLAYER_CLASSES ) = = 0 ) )
return ;
//WF
item = self - > client - > pers . weapon ;
if ( ! self - > client - > pers . inventory [ self - > client - > ammo_index ] )
item = NULL ;
if ( item & & ( strcmp ( item - > pickup_name , " Blaster " ) = = 0 ) )
item = NULL ;
if ( ! ( ( int ) ( dmflags - > value ) & DF_QUAD_DROP ) )
quad = false ;
else
quad = ( self - > client - > quad_framenum > ( level . framenum + 10 ) ) ;
if ( item & & quad )
spread = 22.5 ;
else
spread = 0.0 ;
if ( item )
{
self - > client - > v_angle [ YAW ] - = spread ;
drop = Drop_Item ( self , item ) ;
self - > client - > v_angle [ YAW ] + = spread ;
drop - > spawnflags = DROPPED_PLAYER_ITEM ;
}
if ( quad )
{
self - > client - > v_angle [ YAW ] + = spread ;
drop = Drop_Item ( self , FindItemByClassname ( " item_quad " ) ) ;
self - > client - > v_angle [ YAW ] - = spread ;
drop - > spawnflags | = DROPPED_PLAYER_ITEM ;
drop - > touch = Touch_Item ;
drop - > nextthink = level . time + ( self - > client - > quad_framenum - level . framenum ) * FRAMETIME ;
drop - > think = G_FreeEdict ;
}
}
/*
= = = = = = = = = = = = = = = = = =
LookAtKiller
= = = = = = = = = = = = = = = = = =
*/
void LookAtKiller ( edict_t * self , edict_t * inflictor , edict_t * attacker )
{
vec3_t dir ;
if ( attacker & & attacker ! = world & & attacker ! = self )
{
VectorSubtract ( attacker - > s . origin , self - > s . origin , dir ) ;
}
else if ( inflictor & & inflictor ! = world & & inflictor ! = self )
{
VectorSubtract ( inflictor - > s . origin , self - > s . origin , dir ) ;
}
else
{
self - > client - > killer_yaw = self - > s . angles [ YAW ] ;
return ;
}
if ( dir [ 0 ] )
self - > client - > killer_yaw = 180 / M_PI * atan2 ( dir [ 1 ] , dir [ 0 ] ) ;
else {
self - > client - > killer_yaw = 0 ;
if ( dir [ 1 ] > 0 )
self - > client - > killer_yaw = 90 ;
else if ( dir [ 1 ] < 0 )
self - > client - > killer_yaw = - 90 ;
}
if ( self - > client - > killer_yaw < 0 )
self - > client - > killer_yaw + = 360 ;
}
/*
= = = = = = = = = = = = = = = = = =
player_die
= = = = = = = = = = = = = = = = = =
*/
void player_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point )
{
int n ;
//Reset fov if autozoom was on
if ( self - > client - > pers . autozoom )
{
self - > client - > ps . fov = 90 ;
self - > PlayerSnipingZoom = 0 ;
}
//Free laser sight
if ( self - > lasersight )
{
G_FreeEdict ( self - > lasersight ) ;
self - > lasersight = NULL ;
}
VectorClear ( self - > avelocity ) ;
self - > takedamage = DAMAGE_YES ;
self - > movetype = MOVETYPE_TOSS ;
self - > s . modelindex2 = 0 ; // remove linked weapon model
//ZOID
self - > s . modelindex3 = 0 ; // remove linked ctf flag
//ZOID
self - > s . angles [ 0 ] = 0 ;
self - > s . angles [ 2 ] = 0 ;
self - > s . sound = 0 ;
self - > client - > weapon_sound = 0 ;
self - > maxs [ 2 ] = - 8 ;
// self->solid = SOLID_NOT;
self - > svflags | = SVF_DEADMONSTER ;
if ( ! self - > deadflag )
{
self - > client - > respawn_time = level . time + 1.0 ;
LookAtKiller ( self , inflictor , attacker ) ;
self - > client - > ps . pmove . pm_type = PM_DEAD ;
ClientObituary ( self , inflictor , attacker ) ;
//WF
/*
//Drop all the keys you are holding
for ( n = 0 ; n < game . num_items ; n + + )
{
//If this is a key and I'm holding it, then drop it
if ( ( deathmatch - > value ) & & ( itemlist [ n ] . flags & IT_KEY ) )
{
if ( self - > client - > pers . inventory [ n ] )
{
Drop_General ( self , & itemlist [ n ] ) ;
//gi.dprintf("Dropping key: %s\n", itemlist[n].classname);
}
else
{
//gi.dprintf("Key not in inventory: %d: %s\n", n, itemlist[n].classname);
}
}
}
*/
//WF
WFPlayer_Die ( self ) ;
Kamikaze_Cancel ( self ) ;
//ZOID
CTFFragBonuses ( self , inflictor , attacker ) ;
//ZOID
TossClientWeapon ( self ) ;
//ZOID
if ( self - > bot_client ) //newgrap 4/99
CTFPlayerResetGrapple ( self ) ;
else //newgrap 4/99
// CTFPlayerResetGrapple(self);
CTFPlayerResetGrapple2 ( self ) ; //newgrap 4/99
CTFDeadDropFlag ( self ) ;
CTFDeadDropTech ( self ) ;
//ZOID
if ( deathmatch - > value & & ! self - > client - > showscores )
Cmd_Help_f ( self ) ; // show scores
// clear inventory
// this is kind of ugly, but it's how we want to handle keys in coop
for ( n = 0 ; n < game . num_items ; n + + )
{
if ( coop - > value & & itemlist [ n ] . flags & IT_KEY )
self - > client - > resp . coop_respawn . inventory [ n ] = self - > client - > pers . inventory [ n ] ;
self - > client - > pers . inventory [ n ] = 0 ;
}
}
// remove powerups
self - > client - > quad_framenum = 0 ;
self - > client - > invincible_framenum = 0 ;
self - > client - > breather_framenum = 0 ;
self - > client - > enviro_framenum = 0 ;
// clear inventory
//3.20 memset(self->client->pers.inventory, 0, sizeof(self->client->pers.inventory));
//WF & ATTILA begin
if ( Jet_Active ( self ) )
{
Jet_BecomeExplosion ( self , damage ) ;
/*stop jetting when dead*/
self - > client - > Jet_framenum = 0 ;
}
//WF & ATTILA
if ( self - > health < - 40 ) //dont use its fixed || (self->client->player_special & SPECIAL_DISGUISE))
{ // gib
gi . sound ( self , CHAN_BODY , gi . soundindex ( " misc/udeath.wav " ) , 1 , ATTN_NORM , 0 ) ;
for ( n = 0 ; n < 4 ; n + + )
ThrowGib ( self , " models/objects/gibs/sm_meat/tris.md2 " , damage , GIB_ORGANIC ) ;
ThrowClientHead ( self , damage ) ;
//ZOID
self - > client - > anim_priority = ANIM_DEATH ;
self - > client - > anim_end = 0 ;
//ZOID
self - > takedamage = DAMAGE_NO ;
}
else if ( self - > frozen & & ! self - > deadflag ) //acrid 3/99 frozen death animation
{
self - > s . effects | = EF_COLOR_SHELL ;
self - > s . renderfx | = ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE ) ;
self - > client - > anim_priority = ANIM_DEATH ;
self - > s . frame = FRAME_stand01 ;
self - > client - > anim_end = FRAME_stand01 ;
self - > frozenbody = 1 ;
gi . sound ( self , CHAN_VOICE , gi . soundindex ( va ( " *death%i.wav " , ( rand ( ) % 4 ) + 1 ) ) , 1 , ATTN_NORM , 0 ) ;
}
else
{ // normal death
if ( ! self - > deadflag )
{
static int i ;
i = ( i + 1 ) % 3 ;
// start a death animation
self - > client - > anim_priority = ANIM_DEATH ;
if ( self - > client - > ps . pmove . pm_flags & PMF_DUCKED )
{
self - > s . frame = FRAME_crdeath1 - 1 ;
self - > client - > anim_end = FRAME_crdeath5 ;
}
else switch ( i )
{
case 0 :
self - > s . frame = FRAME_death101 - 1 ;
self - > client - > anim_end = FRAME_death106 ;
break ;
case 1 :
self - > s . frame = FRAME_death201 - 1 ;
self - > client - > anim_end = FRAME_death206 ;
break ;
case 2 :
self - > s . frame = FRAME_death301 - 1 ;
self - > client - > anim_end = FRAME_death308 ;
break ;
}
gi . sound ( self , CHAN_VOICE , gi . soundindex ( va ( " *death%i.wav " , ( rand ( ) % 4 ) + 1 ) ) , 1 , ATTN_NORM , 0 ) ;
}
}
self - > deadflag = DEAD_DEAD ;
self - > frozen = 0 ; //acrid 3/99
gi . linkentity ( self ) ;
}
//=======================================================================
/*
= = = = = = = = = = = = = =
InitClientPersistant
This is only called when the game first initializes in single player ,
but is called after each death and level change in deathmatch
= = = = = = = = = = = = = =
*/
void InitClientPersistant ( gclient_t * client )
{
gitem_t * item ;
int i ;
int HasVoted = client - > pers . HasVoted ;
int tmpGrenade [ GRENADE_TYPE_COUNT + 1 ] ;
int tmpSpecial [ SPECIAL_COUNT + 1 ] ;
qboolean homing_state = client - > pers . homing_state ;
int laseron = client - > pers . laseron ;
int feign = client - > pers . feign ;
int autozoom = client - > pers . autozoom ;
int fastaim = client - > pers . fastaim ;
int nospam_level = client - > pers . nospam_level ;
qboolean autoconfig = client - > pers . autoconfig ;
int player_class = client - > pers . player_class ;
int next_player_class = client - > pers . next_player_class ;
edict_t * friend_ent ;
int hasfriends = client - > pers . hasfriends ;
int isbot = client - > pers . i_am_a_bot ;
friend_ent = client - > pers . friend_ent [ 0 ] ;
//Save grenade and special counts
for ( i = 1 ; i < = GRENADE_TYPE_COUNT ; + + i )
{
tmpGrenade [ i ] = client - > pers . active_grenades [ i ] ;
}
for ( i = 1 ; i < = SPECIAL_COUNT ; + + i )
tmpSpecial [ i ] = client - > pers . active_special [ i ] ;
memset ( & client - > pers , 0 , sizeof ( client - > pers ) ) ;
//Restore grenade and special counts
for ( i = 1 ; i < = GRENADE_TYPE_COUNT ; + + i )
{
if ( tmpGrenade [ i ] < 0 ) tmpGrenade [ i ] = 0 ;
client - > pers . active_grenades [ i ] = tmpGrenade [ i ] ;
}
for ( i = 1 ; i < = SPECIAL_COUNT ; + + i )
client - > pers . active_special [ i ] = tmpSpecial [ i ] ;
item = FindItem ( " Blaster " ) ;
client - > pers . selected_item = ITEM_INDEX ( item ) ;
client - > pers . inventory [ client - > pers . selected_item ] = 1 ;
client - > pers . weapon = item ;
//ZOID
client - > pers . lastweapon = item ;
//ZOID
//ERASER START
item = FindItem ( " Grapple " ) ;
// if (grapple->value || ctf->value)
if ( ctf - > value )
{ //E
//ZOID
client - > pers . inventory [ ITEM_INDEX ( item ) ] = 1 ; //NORMAL LINE
//ZOID
} //E
else //E
{ //E
client - > pers . inventory [ ITEM_INDEX ( item ) ] = 0 ; //E
}
//ERASER END GRAPPLE TROUBLE HERE FIXME ACRID
client - > pers . i_am_a_bot = isbot ;
client - > pers . health = 100 ;
client - > pers . max_health = 100 ;
client - > pers . connected = true ;
client - > pers . friend_ent [ 0 ] = friend_ent ;
// WF & CCH: reset homing_state
client - > pers . HasVoted = HasVoted ;
client - > pers . homing_state = homing_state ;
client - > pers . laseron = laseron ;
client - > pers . feign = feign ;
client - > pers . autozoom = autozoom ;
client - > pers . fastaim = fastaim ;
client - > pers . nospam_level = nospam_level ;
client - > pers . autoconfig = autoconfig ;
client - > pers . player_class = player_class ;
client - > pers . next_player_class = next_player_class ;
client - > pers . hasfriends = hasfriends ;
// Initialize grenade type
client - > pers . grenade_num = 1 ;
client - > pers . grenade_type = GRENADE_TYPE_NORMAL ;
if ( ( ( int ) wfflags - > value & WF_NO_PLAYER_CLASSES ) = = 0 )
client - > pers . grenade_type = client - > grenade_type1 ;
// Scanner
// ClearScanner(client);
// Scanner
// CompassOff(client);//5/99 compass
}
qboolean is_bot = false ; //ERASER
void InitClientResp ( gclient_t * client , edict_t * ent )
{
// int i;
int ctf_team ;
//K2:begin
qboolean inServer = client - > resp . inServer ;
//K2:End 3/99 botcam
ctf_team = client - > resp . ctf_team ;
memset ( & client - > resp , 0 , sizeof ( client - > resp ) ) ;
client - > resp . ctf_team = ctf_team ;
//K2:begin
client - > resp . inServer = inServer ;
//K2:End 3/99 botcam
client - > resp . enterframe = level . framenum ;
client - > resp . coop_respawn = client - > pers ;
//ZOID
// if (ctf->value && (client->resp.ctf_team < CTF_TEAM1))
if ( client - > resp . ctf_team < CTF_TEAM1 )
CTFAssignTeam ( client , is_bot ) ;
//ZOID
}
/*
= = = = = = = = = = = = = = = = = =
SaveClientData
Some information that should be persistant , like health ,
is still stored in the edict structure , so it needs to
be mirrored out to the client structure before all the
edicts are wiped .
= = = = = = = = = = = = = = = = = =
*/
void SaveClientData ( void )
{
int i ;
edict_t * ent ;
for ( i = 0 ; i < game . maxclients ; i + + )
{
ent = & g_edicts [ 1 + i ] ;
if ( ! ent - > inuse )
continue ;
game . clients [ i ] . pers . health = ent - > health ;
game . clients [ i ] . pers . max_health = ent - > max_health ;
game . clients [ i ] . pers . savedFlags = ( ent - > flags & ( FL_GODMODE | FL_NOTARGET | FL_POWER_ARMOR ) ) ;
if ( coop - > value )
game . clients [ i ] . pers . score = ent - > client - > resp . score ;
}
}
void FetchClientEntData ( edict_t * ent )
{
ent - > health = ent - > client - > pers . health ;
ent - > max_health = ent - > client - > pers . max_health ;
ent - > flags | = ent - > client - > pers . savedFlags ;
if ( coop - > value )
ent - > client - > resp . score = ent - > client - > pers . score ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
SelectSpawnPoint
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = =
PlayersRangeFromSpot
Returns the distance to the nearest player from the given spot
= = = = = = = = = = = = = = = =
*/
float PlayersRangeFromSpot ( edict_t * spot )
{
edict_t * player ;
float bestplayerdistance ;
vec3_t v ;
int n ;
float playerdistance ;
bestplayerdistance = 9999999 ;
/*
for ( n = 0 ; n < num_players ; n + + ) //WF24 LINE IS for (n = 1; n <= maxclients->value; n++)
{
player = & g_edicts [ n ] ;
*/
for ( n = 0 ; n < num_players ; n + + ) //WF24 LINE IS for (n = 1; n <= maxclients->value; n++)
{
player = players [ n ] ; //ERASER ,WF USES LINE ABOVE THIS
if ( ! player - > inuse )
continue ;
if ( player - > health < = 0 )
continue ;
VectorSubtract ( spot - > s . origin , player - > s . origin , v ) ;
playerdistance = VectorLength ( v ) ;
if ( playerdistance < bestplayerdistance )
bestplayerdistance = playerdistance ;
}
return bestplayerdistance ;
}
/*
= = = = = = = = = = = = = = = =
SelectRandomDeathmatchSpawnPoint
go to a random point , but NOT the two points closest
to other players
= = = = = = = = = = = = = = = =
*/
edict_t * SelectRandomDeathmatchSpawnPoint ( void )
{
edict_t * spot , * spot1 , * spot2 ;
int count = 0 , spot_num ; //ERASER
int selection ;
float range , range1 , range2 ;
spot = NULL ;
range1 = range2 = 99999 ;
spot1 = spot2 = NULL ;
//WF USES THIS CO LINE
// while ((spot = G_Find (spot, FOFS(classname), "info_player_deathmatch")) != NULL)
while ( count < num_dm_spots )
{
spot = dm_spots [ count ] ; //ERASER
count + + ;
range = PlayersRangeFromSpot ( spot ) ;
if ( range < range1 )
{
range1 = range ;
spot1 = spot ;
}
else if ( range < range2 )
{
range2 = range ;
spot2 = spot ;
}
}
if ( ! count )
return NULL ;
if ( count < = 2 )
{
spot1 = spot2 = NULL ;
}
else
count - = 2 ;
selection = rand ( ) % count ;
spot = NULL ;
spot_num = 0 ; //ERASER
do
{
//WF24 USES spot = G_Find (spot, FOFS(classname), "info_player_deathmatch");
spot = dm_spots [ spot_num + + ] ; //ERASER
if ( spot = = spot1 | | spot = = spot2 )
selection + + ;
} while ( selection - - ) ;
return spot ;
}
/*
= = = = = = = = = = = = = = = =
SelectFarthestDeathmatchSpawnPoint
= = = = = = = = = = = = = = = =
*/
edict_t * SelectFarthestDeathmatchSpawnPoint ( void )
{
edict_t * bestspot ;
float bestdistance , bestplayerdistance ;
edict_t * spot ;
int spot_num ; //ERASER
spot = NULL ;
bestspot = NULL ;
bestdistance = 0 ;
spot_num = 0 ; //ERASER
//WF24 USES while ((spot = G_Find (spot, FOFS(classname), "info_player_deathmatch")) != NULL)
while ( spot_num < num_dm_spots ) //ERASER
{
spot = dm_spots [ spot_num + + ] ; //ERASER
bestplayerdistance = PlayersRangeFromSpot ( spot ) ;
if ( bestplayerdistance > bestdistance )
{
bestspot = spot ;
bestdistance = bestplayerdistance ;
}
}
if ( bestspot )
{
return bestspot ;
}
// if there is a player just spawned on each and every start spot
// we have no choice to turn one into a telefrag meltdown
//WF USES spot = G_Find (NULL, FOFS(classname), "info_player_deathmatch");
spot = dm_spots [ 0 ] ; //ERASER
return spot ;
}
edict_t * SelectDeathmatchSpawnPoint ( void )
{
if ( ( int ) ( dmflags - > value ) & DF_SPAWN_FARTHEST )
return SelectFarthestDeathmatchSpawnPoint ( ) ;
else
return SelectRandomDeathmatchSpawnPoint ( ) ;
}
edict_t * SelectCoopSpawnPoint ( edict_t * ent )
{
int index ;
edict_t * spot = NULL ;
char * target ;
index = ent - > client - game . clients ;
// player 0 starts in normal player spawn point
if ( ! index )
return NULL ;
spot = NULL ;
// assume there are four coop spots at each spawnpoint
while ( 1 )
{
spot = G_Find ( spot , FOFS ( classname ) , " info_player_coop " ) ;
if ( ! spot )
return NULL ; // we didn't have enough...
target = spot - > targetname ;
if ( ! target )
target = " " ;
if ( Q_stricmp ( game . spawnpoint , target ) = = 0 )
{ // this is a coop spawn point for one of the clients here
index - - ;
if ( ! index )
return spot ; // this is it
}
}
return spot ;
}
/*
= = = = = = = = = = =
SelectSpawnPoint
Chooses a player start , deathmatch start , coop start , etc
= = = = = = = = = = = =
*/
void SelectSpawnPoint ( edict_t * ent , vec3_t origin , vec3_t angles )
{
edict_t * spot = NULL ;
if ( deathmatch - > value )
//ZOID
if ( ctf - > value )
spot = SelectCTFSpawnPoint ( ent ) ;
else
//ZOID
spot = SelectDeathmatchSpawnPoint ( ) ;
else if ( coop - > value )
spot = SelectCoopSpawnPoint ( ent ) ;
// find a single player start spot
if ( ! spot )
{
// gi.dprintf("DEBUG - No CTF Spawn Point.\n");
while ( ( spot = G_Find ( spot , FOFS ( classname ) , " info_player_start " ) ) ! = NULL )
{
if ( ! game . spawnpoint [ 0 ] & & ! spot - > targetname )
break ;
if ( ! game . spawnpoint [ 0 ] | | ! spot - > targetname )
continue ;
if ( Q_stricmp ( game . spawnpoint , spot - > targetname ) = = 0 )
break ;
}
if ( ! spot )
{
// gi.dprintf("DEBUG - No Spawn Point Without Target.\n");
if ( ! game . spawnpoint [ 0 ] )
{ // there wasn't a spawnpoint without a target, so use any
spot = G_Find ( spot , FOFS ( classname ) , " info_player_start " ) ;
}
if ( ! spot )
gi . error ( " Couldn't find spawn point %s \n " , game . spawnpoint ) ;
}
}
VectorCopy ( spot - > s . origin , origin ) ;
origin [ 2 ] + = 9 ;
VectorCopy ( spot - > s . angles , angles ) ;
}
//======================================================================
void InitBodyQue ( void )
{
int i ;
edict_t * ent ;
level . body_que = 0 ;
for ( i = 0 ; i < BODY_QUEUE_SIZE ; i + + )
{
ent = G_Spawn ( ) ;
ent - > classname = " bodyque " ;
}
}
//ERASER START
void Body_droptofloor ( edict_t * ent )
{
trace_t tr ;
vec3_t dest ;
float * v ;
v = tv ( - 15 , - 15 , - 24 ) ;
VectorCopy ( v , ent - > mins ) ;
v = tv ( 15 , 15 , 15 ) ;
VectorCopy ( v , ent - > maxs ) ;
v = tv ( 0 , 0 , - 128 ) ;
VectorAdd ( ent - > s . origin , v , dest ) ;
ent - > s . origin [ 2 ] + = 32 ;
tr = gi . trace ( ent - > s . origin , ent - > mins , ent - > maxs , dest , ent , MASK_SOLID ) ;
VectorCopy ( tr . endpos , ent - > s . origin ) ;
gi . linkentity ( ent ) ;
if ( tr . ent )
ent - > nextthink = level . time + 0.1 ;
}
//ERASER END
void body_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point )
{
int n ;
if ( self - > health < - 40 )
{
gi . sound ( self , CHAN_BODY , gi . soundindex ( " misc/udeath.wav " ) , 1 , ATTN_NORM , 0 ) ;
for ( n = 0 ; n < 4 ; n + + )
ThrowGib ( self , " models/objects/gibs/sm_meat/tris.md2 " , damage , GIB_ORGANIC ) ;
self - > s . origin [ 2 ] - = 48 ;
ThrowClientHead ( self , damage ) ;
self - > takedamage = DAMAGE_NO ;
}
}
void CopyToBodyQue ( edict_t * ent )
{
edict_t * body ;
// grab a body que and cycle to the next one
body = & g_edicts [ ( int ) maxclients - > value + level . body_que + 1 ] ;
level . body_que = ( level . body_que + 1 ) % BODY_QUEUE_SIZE ;
// FIXME: send an effect on the removed body
gi . unlinkentity ( ent ) ;
// body->frozenbody =1;//acrid 3/99 this may be a solution if theres problems between the ent pointer and body
gi . unlinkentity ( body ) ;
body - > s = ent - > s ;
body - > s . number = body - g_edicts ;
body - > svflags = ent - > svflags ;
VectorCopy ( ent - > mins , body - > mins ) ;
VectorCopy ( ent - > maxs , body - > maxs ) ;
VectorCopy ( ent - > absmin , body - > absmin ) ;
VectorCopy ( ent - > absmax , body - > absmax ) ;
VectorCopy ( ent - > size , body - > size ) ;
body - > solid = ent - > solid ;
body - > clipmask = ent - > clipmask ;
body - > owner = ent - > owner ;
// body->s.effects = 0;
// body->s.renderfx = 0;
body - > movetype = ent - > movetype ;
body - > die = body_die ;
body - > takedamage = DAMAGE_YES ;
gi . linkentity ( body ) ;
}
void WFCopyToBodyQue ( edict_t * ent )
{
edict_t * body ;
char modelname [ 64 ] ; //acrid
int classnum ; //acrid
// grab a body que and cycle to the next one
body = & g_edicts [ ( int ) maxclients - > value + level . body_que + 1 ] ;
level . body_que = ( level . body_que + 1 ) % BODY_QUEUE_SIZE ;
// FIXME: send an effect on the removed body
gi . unlinkentity ( ent ) ;
gi . unlinkentity ( body ) ;
//new skin fix code
body - > wf_team = ent - > client - > resp . ctf_team ;
body - > model = ent - > model ; //needed????? 3/99
classnum = ent - > client - > pers . player_class ;
sprintf ( modelname , " wfactory/models/decoys/%s/tris.md2 " , classinfo [ classnum ] . model_name ) ;
body - > s . modelindex = gi . modelindex ( modelname ) ;
body - > s . skinnum = classinfo [ classnum ] . decoyskin ;
if ( body - > wf_team = = CTF_TEAM1 ) //team 1
{
+ + body - > s . skinnum ;
}
else
{
//team 2
}
//end new skin fix
// body->s = ent->s;
VectorCopy ( ent - > s . origin , body - > s . origin ) ; //acrid
VectorCopy ( ent - > s . angles , body - > s . angles ) ; //acrid
VectorCopy ( ent - > s . old_origin , body - > s . old_origin ) ; //acrid
body - > s . frame = ent - > s . frame ; //acrid
body - > s . number = body - g_edicts ;
body - > svflags = ent - > svflags ;
VectorCopy ( ent - > mins , body - > mins ) ;
VectorCopy ( ent - > maxs , body - > maxs ) ;
VectorCopy ( ent - > absmin , body - > absmin ) ;
VectorCopy ( ent - > absmax , body - > absmax ) ;
VectorCopy ( ent - > size , body - > size ) ;
body - > solid = ent - > solid ;
body - > s . event = ent - > s . event ; //acrid
body - > clipmask = ent - > clipmask ;
body - > owner = ent - > owner ;
body - > s . effects = ent - > s . effects ;
body - > s . renderfx = ent - > s . renderfx ;
//If they were carrying the flag, clear the glow - GREGG
if ( body - > s . effects & ( EF_FLAG1 | EF_FLAG2 ) )
{
body - > s . effects = 0 ;
body - > s . renderfx = 0 ;
}
body - > movetype = ent - > movetype ;
body - > die = body_die ;
body - > takedamage = DAMAGE_YES ;
gi . linkentity ( body ) ;
}
void respawn ( edict_t * self )
{
if ( deathmatch - > value | | coop - > value )
{
if ( ( ( int ) wfflags - > value & WF_NO_PLAYER_CLASSES ) = = 0 )
{ //for stopping instant gib creating a extra body//may need !self->frozenbody
if ( self - > health > - 40 & & ! self - > bot_client )
WFCopyToBodyQue ( self ) ;
//use normal que if instant gib
else
CopyToBodyQue ( self ) ;
}
//if wfflags use normal que
else
{
CopyToBodyQue ( self ) ;
}
PutClientInServer ( self ) ;
// add a teleportation effect
self - > s . event = EV_PLAYER_TELEPORT ;
// hold in place briefly
self - > client - > ps . pmove . pm_flags = PMF_TIME_TELEPORT ;
self - > client - > ps . pmove . pm_time = 14 ;
self - > client - > respawn_time = level . time ;
return ;
}
// restart the entire server
gi . AddCommandString ( " menu_loadgame \n " ) ;
}
//==============================================================
// WF: Weapons Factory user setup */
static void WFClientSetup ( edict_t * ent )
{
int i ;
//Set aliases required for mod
stuffcmd ( ent , " alias +thrust \" cmd thrust on \" \n " ) ;
stuffcmd ( ent , " alias -thrust \" cmd thrust off \" \n " ) ;
stuffcmd ( ent , " alias +grapple \" +use \" \n " ) ; //newgrap 4/99
stuffcmd ( ent , " alias -grapple \" -use \" \n " ) ; //newgrap 4/99
stuffcmd ( ent , " alias +rzoom \" fov 30;+mlook \" \n " ) ;
stuffcmd ( ent , " alias -rzoom \" fov 90;-mlook \" \n " ) ;
//stuffcmd(ent,"alias wfhelp \"cmd wfhelp\"\n");
//stuffcmd(ent,"alias vote \"cmd vote\"\n");
//FORCE SOME BINDS
// stuffcmd(ent,"bind \";\" cmd special\n");
// stuffcmd(ent,"bind v +thrust\n");
// stuffcmd(ent,"bind b cmd grenade\n");
//note - removed mlook from rzoom command
//Clear grenade and special item limits
for ( i = 1 ; i < = GRENADE_TYPE_COUNT ; + + i )
ent - > client - > pers . active_grenades [ i ] = 0 ;
for ( i = 1 ; i < = SPECIAL_COUNT ; + + i )
ent - > client - > pers . active_special [ i ] = 0 ;
}
//WF
/*
= = = = = = = = = = =
PutClientInServer
Called when a player connects to a server or respawns in
a deathmatch .
= = = = = = = = = = = =
*/
void ShowGun ( edict_t * ent ) ; //ERASER
void PutClientInServer ( edict_t * ent )
{
vec3_t mins = { - 16 , - 16 , - 24 } ;
vec3_t maxs = { 16 , 16 , 32 } ;
int index ;
vec3_t spawn_origin , spawn_angles ;
gclient_t * client ;
int i ;
client_persistant_t saved ;
client_respawn_t resp ;
//ERASER START
bot_team_t * team ;
lag_trail_t * lag_trail ;
lag_trail_t * lag_angles ;
float latency ;
if ( ! the_client & & ! ent - > bot_client & & ( num_players < = 1 ) )
the_client = ent ;
// find a spawn point
// do it before setting health back up, so farthest
// ranging doesn't count this client
SelectSpawnPoint ( ent , spawn_origin , spawn_angles ) ;
index = ent - g_edicts - 1 ;
client = ent - > client ;
HealPlayer ( ent ) ;
//Did class change?
if ( ent - > client - > pers . player_class ! = ent - > client - > pers . next_player_class )
{
//Remove all their old stuff lying around
// gi.dprintf("Class changed-removing stuff. Old class=%d, New Class=%d\n",ent->client->pers.player_class, ent->client->pers.next_player_class);
WFPlayer_ChangeClassTeam ( ent ) ;
}
ent - > client - > pers . player_class = ent - > client - > pers . next_player_class ;
// deathmatch wipes most client data every spawn
if ( deathmatch - > value )
{
char userinfo [ MAX_INFO_STRING ] ;
resp = client - > resp ;
memcpy ( userinfo , client - > pers . userinfo , sizeof ( userinfo ) ) ;
InitClientPersistant ( client ) ;
ClientUserinfoChanged ( ent , userinfo ) ;
}
else if ( coop - > value )
{
int n ;
char userinfo [ MAX_INFO_STRING ] ;
resp = client - > resp ;
memcpy ( userinfo , client - > pers . userinfo , sizeof ( userinfo ) ) ;
// this is kind of ugly, but it's how we want to handle keys in coop
for ( n = 0 ; n < MAX_ITEMS ; n + + )
{
if ( itemlist [ n ] . flags & IT_KEY )
resp . coop_respawn . inventory [ n ] = client - > pers . inventory [ n ] ;
}
client - > pers = resp . coop_respawn ;
ClientUserinfoChanged ( ent , userinfo ) ;
if ( resp . score > client - > pers . score )
client - > pers . score = resp . score ;
}
else
{
memset ( & resp , 0 , sizeof ( resp ) ) ;
}
// clear everything but the persistant data
saved = client - > pers ;
//ERASER START
team = client - > team ;
lag_trail = client - > lag_trail ;
lag_angles = client - > lag_angles ;
latency = client - > latency ;
//ERASER END
memset ( client , 0 , sizeof ( * client ) ) ;
client - > pers = saved ;
client - > resp = resp ;
//ERASER START
client - > team = team ;
client - > lag_trail = lag_trail ;
client - > lag_angles = lag_angles ;
client - > latency = latency ;
if ( client - > pers . health < = 0 )
InitClientPersistant ( client ) ;
//ERASER END
// copy some data from the client to the entity
FetchClientEntData ( ent ) ;
if ( ! ent - > wf_team ) ent - > wf_team = client - > resp . ctf_team ;
// clear entity values
ent - > groundentity = NULL ;
if ( ! ent - > bot_client ) //ERASER
ent - > client = & game . clients [ index ] ;
ent - > takedamage = DAMAGE_AIM ;
ent - > movetype = MOVETYPE_WALK ;
ent - > viewheight = 22 ;
ent - > inuse = true ;
ent - > classname = " player " ;
ent - > mass = 200 ;
ent - > solid = SOLID_BBOX ;
ent - > deadflag = DEAD_NO ;
ent - > air_finished = level . time + 12 ;
ent - > clipmask = MASK_PLAYERSOLID ;
ent - > model = " players/male/tris.md2 " ;
//ERASER START
if ( ! ent - > bot_client )
{
ent - > pain = player_pain ;
ent - > die = player_die ;
}
//ERASER END MIDDLE 2 LINES NORMAL WF24 CODE
ent - > waterlevel = 0 ;
ent - > watertype = 0 ;
ent - > flags & = ~ FL_NO_KNOCKBACK ;
ent - > svflags & = ~ SVF_DEADMONSTER ;
// acrid 3/99 start unfrozen
ent - > frozen = 0 ;
ent - > frozenbody = 0 ;
VectorCopy ( mins , ent - > mins ) ;
VectorCopy ( maxs , ent - > maxs ) ;
VectorClear ( ent - > velocity ) ;
// clear playerstate values
memset ( & ent - > client - > ps , 0 , sizeof ( client - > ps ) ) ;
client - > ps . pmove . origin [ 0 ] = spawn_origin [ 0 ] * 8 ;
client - > ps . pmove . origin [ 1 ] = spawn_origin [ 1 ] * 8 ;
client - > ps . pmove . origin [ 2 ] = spawn_origin [ 2 ] * 8 ;
//ZOID
client - > ps . pmove . pm_flags & = ~ PMF_NO_PREDICTION ;
//ZOID
if ( ! ent - > bot_client ) //ERASER
{ //E
if ( deathmatch - > value & & ( ( int ) dmflags - > value & DF_FIXED_FOV ) )
{
client - > ps . fov = 90 ;
}
else
{
client - > ps . fov = atoi ( Info_ValueForKey ( client - > pers . userinfo , " fov " ) ) ;
if ( client - > ps . fov < 1 )
client - > ps . fov = 90 ;
else if ( client - > ps . fov > 160 )
client - > ps . fov = 160 ;
}
client - > ps . gunindex = gi . modelindex ( client - > pers . weapon - > view_model ) ;
}
client - > ps . gunindex = gi . modelindex ( client - > pers . weapon - > view_model ) ;
// clear entity state values
ent - > s . effects = 0 ;
// sknum is player num and weapon number
// weapon number will be added in changeweapon
ent - > s . skinnum = ent - g_edicts - 1 ;
ent - > s . modelindex = 255 ; // will use the skin specified model
ent - > s . modelindex2 = 255 ; // custom gun model
if ( ent - > bot_client )
{
ShowGun ( ent ) ;
}
ent - > s . frame = 0 ;
VectorCopy ( spawn_origin , ent - > s . origin ) ;
ent - > s . origin [ 2 ] + = 1 ; // make sure off ground
VectorCopy ( ent - > s . origin , ent - > s . old_origin ) ;
// set the delta angle
for ( i = 0 ; i < 3 ; i + + )
client - > ps . pmove . delta_angles [ i ] = ANGLE2SHORT ( spawn_angles [ i ] - client - > resp . cmd_angles [ i ] ) ;
ent - > s . angles [ PITCH ] = 0 ;
ent - > s . angles [ YAW ] = spawn_angles [ YAW ] ;
ent - > s . angles [ ROLL ] = 0 ;
VectorCopy ( ent - > s . angles , client - > ps . viewangles ) ;
VectorCopy ( ent - > s . angles , client - > v_angle ) ;
//WF - for flash grenades
client - > blindBase = 0 ;
client - > blindTime = 0 ;
//Clear disguise stuff
ent - > disguised = 0 ;
ent - > disguising = 0 ;
ent - > disguisetime = 0 ;
ent - > disguisingteam = 0 ;
ent - > disguisedteam = 0 ;
ent - > disguiseshots = 0 ;
lasersight_off ( ent ) ;
//Stop any disease
ent - > disease = 0 ;
ent - > cantmove = 0 ;
ent - > Slower = 0 ;
ent - > client - > weapon_damage = DAMAGE_BLASTER ; //blaster is startup weapon
//WF
//set the team of the entity
ent - > wf_team = client - > resp . ctf_team ;
//set respawn protection time
ent - > client - > protecttime = level . time + RESPAWN_PROTECT_TIME ;
//Set player classes
//Fixup class if team is set but there is no next_player_class
/*
if ( ( client - > resp . ctf_team > 0 ) & & ( ent - > client - > pers . next_player_class = = 0 ) )
{
//Can we use current setting?
if ( ent - > client - > pers . player_class )
{
ent - > client - > pers . next_player_class = ent - > client - > pers . player_class ;
}
//Just assign them to the first class if all else fails
else
{
ent - > client - > pers . next_player_class = 1 ;
}
}
*/
/* Old position of this code
//Did class change?
if ( ent - > client - > pers . player_class ! = ent - > client - > pers . next_player_class )
{
//Remove all their old stuff lying around
// gi.dprintf("Class changed-removing stuff. Old class=%d, New Class=%d\n",ent->client->pers.player_class, ent->client->pers.next_player_class);
WFPlayer_ChangeClassTeam ( ent ) ;
}
ent - > client - > pers . player_class = ent - > client - > pers . next_player_class ;
*/
if ( ( ( ( int ) wfflags - > value & WF_NO_PLAYER_CLASSES ) = = 0 ) & & ( ent - > client - > pers . player_class ) )
{
// gi.dprintf("Player Classes Used\n");
wf_InitPlayerClass ( ent - > client ) ;
}
// else if ((int)wfflags->value & WF_RESPAWN_ARMED)
// {
// ent->client->pers.next_player_class = CLASS_SUPERMAN;
// ent->client->pers.player_class = CLASS_SUPERMAN;
// wf_InitPlayerClass(ent->client);
// }
else
{
ent - > client - > pers . next_player_class = 0 ;
ent - > client - > pers . player_class = 0 ;
}
Cmd_ShowClass ( ent ) ;
//Pick the best weapon for the class
NoAmmoWeaponChange ( ent ) ;
//ZOID
if ( CTFStartClient ( ent ) )
return ;
//ZOID
if ( ! KillBox ( ent ) )
{ // could't spawn in?
}
gi . linkentity ( ent ) ;
//ERASER START
if ( ! ent - > map )
ent - > map = G_CopyString ( ent - > client - > pers . netname ) ;
//ERASER END
// force the current weapon up
client - > newweapon = client - > pers . weapon ;
if ( ! ent - > bot_client ) //ERASER
ChangeWeapon ( ent ) ;
//If this is a zbot player, mess them up.
if ( ent - > client - > pers . i_am_a_bot )
I_AM_A_ZBOT ( ent ) ;
//ERASER START
ent - > last_max_z = 32 ;
ent - > jump_ent = NULL ;
ent - > duck_ent = NULL ;
ent - > last_trail_dropped = NULL ;
if ( ! ent - > bot_client )
{
if ( ent - > client - > lag_trail )
{
// init the lag_trail
for ( i = 0 ; i < 10 ; i + + )
{
VectorCopy ( ent - > s . origin , ( * ent - > client - > lag_trail ) [ i ] ) ;
VectorCopy ( ent - > client - > v_angle , ( * ent - > client - > lag_angles ) [ i ] ) ;
}
}
if ( ( bot_calc_nodes - > value ) & & ( trail [ 0 ] - > timestamp ) )
{ // find a trail node to start checking from
if ( ( i = ClosestNodeToEnt ( ent , false , true ) ) > - 1 )
{
ent - > last_trail_dropped = trail [ i ] ;
}
}
}
//ERASER END
}
/* Anti-ZBot Support Code */
void wf_strdate ( char * s ) ;
void wf_strtime ( char * s ) ;
void zbotFileOpen ( )
{
char path [ 100 ] ;
zbotfile = NULL ;
//Is zbot detection on?
if ( ( ( int ) wfflags - > value & WF_ZBOT_DETECT ) = = 0 )
return ;
strcpy ( path , gamedir - > string ) ;
# if defined(_WIN32) || defined(WIN32)
strcat ( path , " \\ zbot.log " ) ;
# else
strcat ( path , " /zbot.log " ) ;
# endif
if ( ( zbotfile = fopen ( path , " a " ) ) ! = NULL )
{
fprintf ( zbotfile , " \n SERVER RESTART \n " ) ;
gi . dprintf ( " ZBot Protection Enabled \n " ) ;
}
}
void zbotLogAttack ( edict_t * ent , int type )
{
char tDate [ 50 ] ;
char tTime [ 50 ] ;
char * stype ;
if ( type = = 2 ) stype = " @zbot " ;
else if ( type = = 3 ) stype = " #zbot " ;
else stype = " !zbot " ;
if ( ! zbotfile ) return ;
//value = Info_ValueForKey (userinfo, "ip");
wf_strdate ( tDate ) ;
wf_strtime ( tTime ) ;
fprintf ( zbotfile , " %s %s: Name = %s, Type = %s \n " ,
tDate , tTime , ent - > client - > pers . netname , stype ) ;
fflush ( zbotfile ) ;
}
void zbotFileClose ( )
{
if ( zbotfile ) fclose ( zbotfile ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
ClientBeginDeathmatch
A client has just connected to the server in
deathmatch mode , so clear everything out before starting them .
= = = = = = = = = = = = = = = = = = = = =
*/
void ClientBeginDeathmatch ( edict_t * ent )
{
G_InitEdict ( ent ) ;
//ERASER START
if ( ctf - > value )
ent - > client - > team = NULL ;
//ERASER END
InitClientResp ( ent - > client , ent ) ; //WF34 ADDED ENT
if ( ! ent - > wf_team ) ent - > wf_team = ent - > client - > resp . ctf_team ;
// locate ent at a spawn point
PutClientInServer ( ent ) ;
ent - > client - > pers . autozoom = 1 ; //default sniper rifle to auto-zoom
//WF34 START
// -- ANTI-ZBOT STARTS -- //
//ent->client->resp.bot_start = level.time + 5 + (rand() % 5);
//ent->client->resp.bot_end = 0;
//ent->client->resp.bot_end2 = 0;
//ent->client->resp.bot_end3 = 0;
//Send these commands. User must respond back with all 3
// between 5 and 9 seconds later.
/* C.O. For Lithium Test
if ( ( int ) wfflags - > value & WF_ZBOT_DETECT )
{
stuffcmd ( ent , " !zbot \n " ) ;
ent - > client - > resp . bot_end = level . time + 4 ;
stuffcmd ( ent , " @zbot \n " ) ;
ent - > client - > resp . bot_end2 = level . time + 4 ;
stuffcmd ( ent , " #zbot \n " ) ;
ent - > client - > resp . bot_end3 = level . time + 4 ;
ent - > client - > resp . bot_retries = 0 ;
ent - > client - > resp . bot_retries = 2 ;
ent - > client - > resp . bot_retries = 3 ;
}
C . O . For Lithium Test */
// -- ANTI-ZBOT ENDS -- //
//Enforce cl_forwardspeed and cl_sidespeed 5/99 acrid
if ( ! ent - > bot_client )
{
stuffcmd ( ent , " cl_forwardspeed 200 \n " ) ;
stuffcmd ( ent , " cl_sidespeed 200 \n " ) ;
}
//ERASER START
///Q2 Camera Begin
EntityListAdd ( ent ) ;
///Q2 Camera End
//ERASER END
//WF34 SE
// Voting
ent - > client - > pers . HasVoted = false ;
// Homing
ent - > client - > pers . homing_state = 1 ;
// Feign
ent - > client - > pers . feign = 0 ;
if ( level . intermissiontime )
{
MoveClientToIntermission ( ent ) ;
}
else
{ //WF34 E
// send effect
gi . WriteByte ( svc_muzzleflash ) ;
gi . WriteShort ( ent - g_edicts ) ;
gi . WriteByte ( MZ_LOGIN ) ;
gi . multicast ( ent - > s . origin , MULTICAST_PVS ) ;
} //WF34
my_bprintf ( PRINT_HIGH , " %s entered the game \n " , ent - > client - > pers . netname ) ;
//WF24 S Setup user
WFClientSetup ( ent ) ;
sl_LogPlayerConnect ( & gi , level , ent ) ; // StdLog - Mark Davies
//WF24 E
// make sure all view stuff is valid
ClientEndServerFrame ( ent ) ;
}
/*
= = = = = = = = = = =
ClientBegin
called when a client has finished connecting , and is ready
to be placed into the game . This will happen every level load .
= = = = = = = = = = = =
*/ //WF24 IS A BIT DIF
void botAddPlayer ( edict_t * ent ) ;
void ClientBegin ( edict_t * ent )
{
int i ;
//Check if player in cam mode botcam
if ( ent - > client - > bIsCamera )
{
ent - > client - > bIsCamera = false ;
botAddPlayer ( ent ) ;
}
ent - > client = game . clients + ( ent - g_edicts - 1 ) ;
//ERASER START
players [ num_players + + ] = ent ;
num_clients + + ;
if ( ! ctf - > value )
{ // make sure grapple is removed if CTF has been disabled
ent - > client - > pers . inventory [ ITEM_INDEX ( FindItem ( " Grapple " ) ) ] = 0 ;
}
//ERASER END
if ( deathmatch - > value )
{
//ERASER START (TeT - commented out to prevent overflows)
// if (bot_show_connect_info->value)
// gi.centerprintf(ent, "\n\n=====================================\nThe Eraser Bot v%1.3f\nby Ryan Feltrin (aka Ridah)\n\nRead the readme.txt file\nlocated in the Eraser directory!\n\nVisit http://impact.frag.com/\nfor Eraser news\n\n-------------------------------------\n", ERASER_VERSION, maxclients->value);
//
// if (teamplay->value && !ctf->value)
// safe_cprintf(ent, PRINT_HIGH, "\n\n=====================================\nServer has enabled TEAMPLAY!\n\nType: \"cmd teams\" to see the list of teams\nType: \"cmd join <teamname>\" to join a team\n\n");
//ERASER END
ClientBeginDeathmatch ( ent ) ;
return ;
}
// if there is already a body waiting for us (a loadgame), just
// take it, otherwise spawn one from scratch
if ( ent - > inuse = = true )
{
// the client has cleared the client side viewangles upon
// connecting to the server, which is different than the
// state when the game is saved, so we need to compensate
// with deltaangles
for ( i = 0 ; i < 3 ; i + + )
ent - > client - > ps . pmove . delta_angles [ i ] = ANGLE2SHORT ( ent - > client - > ps . viewangles [ i ] ) ;
}
else
{
// a spawn point will completely reinitialize the entity
// except for the persistant data that was initialized at
// ClientConnect() time
G_InitEdict ( ent ) ;
ent - > classname = " player " ;
InitClientResp ( ent - > client , ent ) ; //WF34 ADDED ENT
PutClientInServer ( ent ) ;
}
if ( level . intermissiontime )
{
MoveClientToIntermission ( ent ) ;
}
else
{
// send effect if in a multiplayer game
if ( game . maxclients > 1 )
{
gi . WriteByte ( svc_muzzleflash ) ;
gi . WriteShort ( ent - g_edicts ) ;
gi . WriteByte ( MZ_LOGIN ) ;
gi . multicast ( ent - > s . origin , MULTICAST_PVS ) ;
my_bprintf ( PRINT_HIGH , " %s entered the game \n " , ent - > client - > pers . netname ) ;
}
}
//WF24 S Setup user
WFClientSetup ( ent ) ;
//WF24 E
// make sure all view stuff is valid
ClientEndServerFrame ( ent ) ;
}
/*
= = = = = = = = = = =
ClientUserInfoChanged
called whenever the player updates a userinfo variable .
The game can override any of the settings in place
( forcing skins or names , etc ) before copying it off .
= = = = = = = = = = = =
*/
void ClientUserinfoChanged ( edict_t * ent , char * userinfo )
{
char * s ;
int playernum ;
// check for malformed or illegal info strings
if ( ! Info_Validate ( userinfo ) )
{
strcpy ( userinfo , " \\ name \\ badinfo \\ skin \\ male/grunt " ) ;
}
// set name
s = Info_ValueForKey ( userinfo , " name " ) ;
//Remove any "%" from name
wfFixName ( s ) ;
// start - mdavies
// Has the player got a name
if ( strlen ( ent - > client - > pers . netname ) )
{
// has the name changed
if ( strcmp ( ent - > client - > pers . netname , s ) )
{
//int iTimeInSeconds = level.time;
// log player rename
sl_LogPlayerRename ( & gi ,
ent - > client - > pers . netname ,
s ) ;
}
}
// end - mdavies
strncpy ( ent - > client - > pers . netname , s , sizeof ( ent - > client - > pers . netname ) - 1 ) ;
// set skin
s = Info_ValueForKey ( userinfo , " skin " ) ;
playernum = ent - g_edicts - 1 ;
// combine name and skin into a configstring
//ZOID
// if (ctf->value)
CTFAssignSkin ( ent , s ) ;
// else
//ZOID
// gi.configstring (CS_PLAYERSKINS+playernum, va("%s\\%s", ent->client->pers.netname, s) );
// fov
if ( deathmatch - > value & & ( ( int ) dmflags - > value & DF_FIXED_FOV ) )
{
ent - > client - > ps . fov = 90 ;
}
else
{
ent - > client - > ps . fov = atoi ( Info_ValueForKey ( userinfo , " fov " ) ) ;
if ( ent - > client - > ps . fov < 1 )
ent - > client - > ps . fov = 90 ;
else if ( ent - > client - > ps . fov > 160 )
ent - > client - > ps . fov = 160 ;
}
// handedness
s = Info_ValueForKey ( userinfo , " hand " ) ;
if ( strlen ( s ) )
{
ent - > client - > pers . hand = atoi ( s ) ;
}
// save off the userinfo in case we want to check something later
strncpy ( ent - > client - > pers . userinfo , userinfo , sizeof ( ent - > client - > pers . userinfo ) - 1 ) ;
}
/*
= = = = = = = = = = =
ClientConnect
Called when a player begins connecting to the server .
The game can refuse entrance to a client by returning false .
If the client is allowed , the connection process will continue
and eventually get to ClientBegin ( )
Changing levels will NOT cause this to be called again , but
loadgames will .
= = = = = = = = = = = =
*/
qboolean ClientConnect ( edict_t * ent , char * userinfo )
{
char * value ;
char * tmp ;
int i ;
// check to see if they are on the banned IP list
value = Info_ValueForKey ( userinfo , " ip " ) ;
// drop port #
tmp = value ;
if ( ! ent - > bot_client )
2024-09-02 07:12:54 -04:00
/* while (tmp)
2024-09-02 07:03:07 -04:00
{
if ( * ( + + tmp ) = = ' : ' )
{
* tmp = ( char ) NULL ;
break ;
}
2024-09-02 07:12:54 -04:00
} */ // mv: who thought of this
2024-09-02 07:03:07 -04:00
if ( IsBanned ( value ) )
{
gi . dprintf ( " *** Banned IP %s tried to connect! \n " , value ) ;
Info_SetValueForKey ( userinfo , " rejmsg " , " You are banned. " ) ;
return false ;
}
// check for a password
if ( ! ent - > bot_client ) //ERASER
{
value = Info_ValueForKey ( userinfo , " password " ) ;
if ( ( wfpassword ) & & ( strcmp ( wfpassword - > string , value ) ! = 0 ) )
return false ;
}
// they can connect
ent - > client = game . clients + ( ent - g_edicts - 1 ) ;
// if there is already a body waiting for us (a loadgame), just
// take it, otherwise spawn one from scratch
if ( ent - > inuse = = false )
{
// clear the respawning variables
//ZOID -- force team join
ent - > client - > resp . ctf_team = - 1 ;
//ZOID
is_bot = ent - > bot_client ; //ERASER// make sure bot's join a team
InitClientResp ( ent - > client , ent ) ; //WF34 ADDED ENT
is_bot = false ; //ERASER
if ( ! game . autosaved | | ! ent - > client - > pers . weapon )
InitClientPersistant ( ent - > client ) ;
if ( ! ent - > wf_team ) ent - > wf_team = ent - > client - > resp . ctf_team ;
}
//ERASER START
// do real client specific stuff
if ( ! ent - > bot_client )
{
int i ;
ent - > client - > team = NULL ;
ent - > client - > lag_trail = gi . TagMalloc ( sizeof ( lag_trail_t ) , TAG_GAME ) ;
ent - > client - > lag_angles = gi . TagMalloc ( sizeof ( lag_trail_t ) , TAG_GAME ) ;
// init the lag_trail
for ( i = 0 ; i < 10 ; i + + )
{
VectorCopy ( ent - > s . origin , ( * ent - > client - > lag_trail ) [ i ] ) ;
VectorCopy ( ent - > client - > v_angle , ( * ent - > client - > lag_angles ) [ i ] ) ;
}
}
//ERASER END
// Clear active grenade and special item counts
//gi.dprintf("Debug: clear grenade counts. After =\n");
for ( i = 1 ; i < = GRENADE_TYPE_COUNT ; + + i )
ent - > client - > pers . active_grenades [ i ] = 0 ;
for ( i = 1 ; i < = SPECIAL_COUNT ; + + i )
ent - > client - > pers . active_special [ i ] = 0 ;
ClientUserinfoChanged ( ent , userinfo ) ;
if ( game . maxclients > 1 )
gi . dprintf ( " %s connected \n " , ent - > client - > pers . netname ) ;
//make sure they don't start with a old players class 5/99
if ( ! ent - > bot_client )
{
if ( ent - > client - > pers . player_class ! = 0 )
{
ent - > client - > pers . player_class = 0 ;
ent - > client - > pers . next_player_class = 0 ;
// gi.dprintf("Connected with a class\n");
}
}
ent - > svflags = 0 ; // make sure we start with known default
ent - > client - > pers . connected = true ;
return true ;
}
/*
= = = = = = = = = = =
ClientDisconnect
Called when a player drops from the server .
Will not be called between levels .
= = = = = = = = = = = =
*/
void botRemovePlayer ( edict_t * self ) ; //ERASER
void ClientDisconnect ( edict_t * ent )
{
int playernum ;
//K2
int i ;
edict_t * other ;
//K2
if ( ! ent - > client )
return ;
//See if it's the ref
if ( wf_game . ref_ent = = ent )
wf_game . ref_ent = NULL ;
//ERASER START
///Q2 Camera Begin
EntityListRemove ( ent ) ;
///Q2 Camera End
//K2: If player was in cammode, he was already removed 3/99
if ( ! ent - > client - > bIsCamera )
botRemovePlayer ( ent ) ;
//ERASER END
my_bprintf ( PRINT_HIGH , " %s disconnected \n " , ent - > client - > pers . netname ) ;
// update chase cam if being followed
for ( i = 0 ; i < = num_players ; i + + ) {
other = players [ i ] ;
if ( ! other | | other - > bot_client )
continue ;
if ( other - > inuse & & other - > client - > chase_target = = ent )
{
other - > client - > chase_target - > inuse = false ;
UpdateChaseCam ( other ) ;
}
}
//K2:End //3/99 botcam acrid
ent - > client - > resp . inServer = false ; //3/99 botcam
//WF
sl_LogPlayerDisconnect ( & gi , level , ent ) ; // StdLog - Mark Davies
WFPlayer_ChangeClassTeam ( ent ) ;
//WF
//ZOID
CTFDeadDropFlag ( ent ) ;
CTFDeadDropTech ( ent ) ;
//ZOID
// send effect
gi . WriteByte ( svc_muzzleflash ) ;
gi . WriteShort ( ent - g_edicts ) ;
gi . WriteByte ( MZ_LOGOUT ) ;
gi . multicast ( ent - > s . origin , MULTICAST_PVS ) ;
gi . unlinkentity ( ent ) ;
ent - > s . modelindex = 0 ;
ent - > solid = SOLID_NOT ;
ent - > inuse = false ;
ent - > classname = " disconnected " ;
ent - > client - > pers . connected = false ;
playernum = ent - g_edicts - 1 ;
gi . configstring ( CS_PLAYERSKINS + playernum , " " ) ;
}
//==============================================================
edict_t * pm_passent ;
// pmove doesn't need to know about passent and contentmask
trace_t PM_trace ( vec3_t start , vec3_t mins , vec3_t maxs , vec3_t end )
{
if ( pm_passent - > health > 0 )
return gi . trace ( start , mins , maxs , end , pm_passent , MASK_PLAYERSOLID ) ;
else
return gi . trace ( start , mins , maxs , end , pm_passent , MASK_DEADSOLID ) ;
}
unsigned CheckBlock ( void * b , int c )
{
int v , i ;
v = 0 ;
for ( i = 0 ; i < c ; i + + )
v + = ( ( byte * ) b ) [ i ] ;
return v ;
}
void PrintPmove ( pmove_t * pm )
{
unsigned c1 , c2 ;
c1 = CheckBlock ( & pm - > s , sizeof ( pm - > s ) ) ;
c2 = CheckBlock ( & pm - > cmd , sizeof ( pm - > cmd ) ) ;
Com_Printf ( " sv %3i:%i %i \n " , pm - > cmd . impulse , c1 , c2 ) ;
}
/*
= = = = = = = = = = = = = =
ClientThink
This will be called once for each client frame , which will
usually be a couple times for each server frame .
= = = = = = = = = = = = = =
*/
int last_bot = 0 ; //ERASER
# define BOT_THINK_TIME 0.03 //ERASER// never do bot thinks for more than this time
void ClientThink ( edict_t * ent , usercmd_t * ucmd )
{
gclient_t * client ;
edict_t * other ;
int i , j ;
pmove_t pm ;
qboolean jetting ;
//ERASER START
int count = 0 , start ;
clock_t start_time , now ;
int playernum ;
char userinfo [ MAX_INFO_STRING ] ; //acrid 3/99 freeze
//ZBOT DETECTION FROM LITHIUM
if ( ( int ) wfflags - > value & WF_ZBOT_DETECT )
{
if ( ZbotCheck ( ent , ucmd ) )
{
zbotLogAttack ( ent , 1 ) ;
//my_bprintf (PRINT_MEDIUM,"SYSTEM MESSAGE: %s has been kicked for using a ZBot.\n", ent->client->pers.netname);
safe_cprintf ( ent , PRINT_HIGH , " You have been kicked for using a ZBot. \n " ) ;
stuffcmd ( ent , " disconnect \n " ) ; // kick out zbots.
my_bprintf ( PRINT_HIGH , " %s is using a ZBot! \n " , ent - > client - > pers . netname ) ;
I_AM_A_ZBOT ( ent ) ;
}
}
//ZBOT DETECTION FROM LITHIUM
if ( paused )
{
gi . centerprintf ( ent , " PAUSED \n \n (type \" botpause \" to resume) " ) ;
ent - > client - > ps . pmove . pm_flags | = PMF_NO_PREDICTION ;
return ;
}
//ERASER END
//Acrid freeze 3/99
if ( ent - > frozen )
{
if ( level . time < ent - > frozentime )
{ ent - > client - > ps . pmove . pm_type = PM_DEAD ;
if ( ent - > client - > buttons & BUTTON_ATTACK ) //4/99 acrid
{
ent - > client - > buttons & = ~ BUTTON_ATTACK ;
}
return ;
}
else
{
playernum = ent - g_edicts - 1 ;
strcpy ( userinfo , ent - > client - > pers . userinfo ) ;
ent - > frozen = 0 ;
Info_SetValueForKey ( userinfo , " skin " , ent - > oldskin ) ;
ClientUserinfoChanged ( ent , userinfo ) ;
}
}
level . current_entity = ent ;
client = ent - > client ;
if ( level . intermissiontime )
{
client - > ps . pmove . pm_type = PM_FREEZE ;
// can exit intermission after five seconds
if ( level . time > level . intermissiontime + 5.0
& & ( ucmd - > buttons & BUTTON_ANY ) )
level . exitintermission = true ;
return ;
}
//Feign Acrid
if ( client - > pers . feign )
{
if ( ent - > health < = 0 )
client - > pers . feign = 0 ;
//oldfeign else
// return;
}
//ERASER START
///Q2 Camera Begin
if ( ent - > client - > bIsCamera )
{
CameraThink ( ent , ucmd ) ;
return ;
}
///Q2 Camera End
if ( ent - > bot_client )
return ;
if ( client - > on_hook = = true ) //newgrap 4/99
{
CTFGrapplePull2 ( ent ) ;
client - > ps . pmove . gravity = 0 ;
}
else
{
client - > ps . pmove . gravity = sv_gravity - > value ;
}
//gi.dprintf("f: %i, s: %i, u: %i\n", ucmd->forwardmove, ucmd->sidemove, ucmd->upmove);
//gi.dprintf("%i, %i\n", ucmd->buttons, client->ps.pmove.pm_flags);
//ERASER END 2 LINES ALREADY CO
pm_passent = ent ;
//ZOID
if ( ent - > client - > chase_target ) {
client - > resp . cmd_angles [ 0 ] = SHORT2ANGLE ( ucmd - > angles [ 0 ] ) ;
client - > resp . cmd_angles [ 1 ] = SHORT2ANGLE ( ucmd - > angles [ 1 ] ) ;
client - > resp . cmd_angles [ 2 ] = SHORT2ANGLE ( ucmd - > angles [ 2 ] ) ;
return ;
}
//ZOID
// set up for pmove
memset ( & pm , 0 , sizeof ( pm ) ) ;
if ( ent - > movetype = = MOVETYPE_NOCLIP )
client - > ps . pmove . pm_type = PM_SPECTATOR ;
else if ( ent - > s . modelindex ! = 255 )
client - > ps . pmove . pm_type = PM_GIB ;
else if ( ent - > deadflag )
client - > ps . pmove . pm_type = PM_DEAD ;
else
client - > ps . pmove . pm_type = PM_NORMAL ;
//Enforce cl_forwardspeed and cl_sidespeed 5/99 acrid
if ( ! ent - > bot_client )
{
if ( ucmd - > forwardmove > 400 | | ucmd - > sidemove > 400 )
{
stuffcmd ( ent , " cl_forwardspeed 200 \n " ) ;
stuffcmd ( ent , " cl_sidespeed 200 \n " ) ;
}
}
// client->ps.pmove.gravity = sv_gravity->value;newgrap 4/99
//WF24 S
if ( ent - > flags & FL_BOOTS )
client - > ps . pmove . gravity = sv_gravity - > value * 0.25 ;
if ( ent - > Slower > level . time )
{
ucmd - > forwardmove * = 0.5 ;
ucmd - > sidemove * = 0.5 ;
ucmd - > upmove * = 0.5 ;
}
//WF & ATTILA begin
//Turn off thrusting state if the WF_NO_FLYING flag is set
//This is set here so the feature can be turned off mid-game
//Some classes can't fly
if ( ent - > client & &
( ( ( int ) wfflags - > value & WF_NO_FLYING ) | |
( ( ent - > client - > player_special & SPECIAL_JETPACK ) = = 0 ) ) )
{
ent - > client - > thrusting = 0 ;
}
//Thrust if you are not all the way in the water
if ( ( ent - > client - > thrusting ) & & ( ent - > waterlevel < 3 ) )
// if ( Jet_Active(ent) )
Jet_ApplyJet ( ent , ucmd ) ; //FIXME NODES
//WF24 E & ATTILA end
pm . s = client - > ps . pmove ;
for ( i = 0 ; i < 3 ; i + + )
{
pm . s . origin [ i ] = ent - > s . origin [ i ] * 8 ;
pm . s . velocity [ i ] = ent - > velocity [ i ] * 8 ;
}
//WF34 START
if ( ent - > superslow )
{
// ucmd->forwardmove *= 0.4;
// ucmd->sidemove *= 0.4;
// ucmd->upmove *= 0.4;
ucmd - > forwardmove * = 0.75 ;
ucmd - > sidemove * = 0.75 ;
ucmd - > upmove * = 0.75 ;
}
if ( ent - > lame )
{
ucmd - > forwardmove * = 0.5 ;
ucmd - > sidemove * = 0.5 ;
ucmd - > upmove * = 0.5 ;
}
//WF34 END
//Feign Acrid
if ( client - > pers . feign ) //newfeign 3/99
{
ucmd - > forwardmove * = 0.0 ;
ucmd - > sidemove * = 0.0 ;
ucmd - > upmove * = 0.0 ;
}
if ( memcmp ( & client - > old_pmove , & pm . s , sizeof ( pm . s ) ) )
{
pm . snapinitial = true ;
// gi.dprintf ("pmove changed!\n");
}
pm . cmd = * ucmd ;
pm . trace = PM_trace ; // adds default parms
pm . pointcontents = gi . pointcontents ;
// perform a pmove
gi . Pmove ( & pm ) ;
// save results of pmove
client - > ps . pmove = pm . s ;
client - > old_pmove = pm . s ;
for ( i = 0 ; i < 3 ; i + + )
{
ent - > s . origin [ i ] = pm . s . origin [ i ] * 0.125 ;
ent - > velocity [ i ] = pm . s . velocity [ i ] * 0.125 ;
}
jetting = Jet_Active ( ent ) ;
for ( i = 0 ; i < 3 ; i + + )
{
if ( ! jetting
| | ( jetting
& & ( fabs ( ( float ) pm . s . velocity [ i ] * 0.125 ) < fabs ( ent - > velocity [ i ] ) ) ) )
{
ent - > velocity [ i ] = pm . s . velocity [ i ] * 0.125 ;
}
}
//FIXME NODES? dont remember //newfeign 3/99
//Feign Acrid
if ( ! client - > pers . feign )
{
VectorCopy ( pm . mins , ent - > mins ) ;
VectorCopy ( pm . maxs , ent - > maxs ) ;
}
client - > resp . cmd_angles [ 0 ] = SHORT2ANGLE ( ucmd - > angles [ 0 ] ) ;
client - > resp . cmd_angles [ 1 ] = SHORT2ANGLE ( ucmd - > angles [ 1 ] ) ;
client - > resp . cmd_angles [ 2 ] = SHORT2ANGLE ( ucmd - > angles [ 2 ] ) ;
//WF24 S & ATTILA begin
if ( jetting )
if ( pm . groundentity ) //are we on ground
if ( Jet_AvoidGround ( ent ) ) //then lift us if possible
pm . groundentity = NULL ; //FIXME NODES //now we are no longer on ground
//WF24 E & ATTILA end
if ( ent - > groundentity & & ! pm . groundentity & & ( pm . cmd . upmove > = 10 ) & & ( pm . waterlevel = = 0 ) )
{
gi . sound ( ent , CHAN_VOICE , gi . soundindex ( " *jump1.wav " ) , 1 , ATTN_NORM , 0 ) ;
PlayerNoise ( ent , ent - > s . origin , PNOISE_SELF ) ;
}
//Feign Acrid
if ( ! client - > pers . feign ) //newfeign 3/99
ent - > viewheight = pm . viewheight ;
ent - > waterlevel = pm . waterlevel ;
ent - > watertype = pm . watertype ;
ent - > groundentity = pm . groundentity ;
if ( pm . groundentity )
ent - > groundentity_linkcount = pm . groundentity - > linkcount ;
if ( ent - > deadflag )
{
client - > ps . viewangles [ ROLL ] = 40 ;
client - > ps . viewangles [ PITCH ] = - 15 ;
client - > ps . viewangles [ YAW ] = client - > killer_yaw ;
}
//Feign Acrid
else if ( ! client - > pers . feign ) //newfeign 3/99
{
VectorCopy ( pm . viewangles , client - > v_angle ) ;
VectorCopy ( pm . viewangles , client - > ps . viewangles ) ;
}
//ZOID
if ( ent - > bot_client ) //newgrap 4/99
{
if ( client - > ctf_grapple )
CTFGrapplePull ( client - > ctf_grapple ) ;
}
//ZOID
// handle cloaking ability
if ( ent - > client - > cloaking )
{
if ( ucmd - > forwardmove ! = 0 | | ucmd - > sidemove ! = 0 )
{
ent - > svflags & = ~ SVF_NOCLIENT ;
ent - > client - > cloaking = false ;
}
else
{
if ( ent - > svflags & SVF_NOCLIENT )
{
if ( ent - > client - > pers . inventory [ ITEM_INDEX ( FindItem ( " Cells " ) ) ] > = CLOAK_AMMO )
{
ent - > client - > cloakdrain + + ;
if ( ent - > client - > cloakdrain = = CLOAK_DRAIN )
{
ent - > client - > pers . inventory [ ITEM_INDEX ( FindItem ( " Cells " ) ) ] - = CLOAK_AMMO ;
ent - > client - > cloakdrain = 0 ;
}
}
else
{
ent - > svflags & = ~ SVF_NOCLIENT ;
ent - > client - > cloaking = false ;
}
}
else
{
if ( ent - > client - > cloaking )
{
if ( level . time > ent - > client - > cloaktime )
{
ent - > svflags | = SVF_NOCLIENT ;
ent - > client - > cloakdrain = 0 ;
}
}
else
{
ent - > client - > cloaktime = level . time + CLOAK_ACTIVATE_TIME ;
ent - > client - > cloaking = true ;
}
}
}
}
gi . linkentity ( ent ) ;
if ( ent - > movetype ! = MOVETYPE_NOCLIP )
G_TouchTriggers ( ent ) ;
// touch other objects
for ( i = 0 ; i < pm . numtouch ; i + + )
{
other = pm . touchents [ i ] ;
for ( j = 0 ; j < i ; j + + )
if ( pm . touchents [ j ] = = other )
break ;
if ( j ! = i )
continue ; // duplicated
if ( ! other - > touch )
continue ;
//acrid 3/99
if ( other - > frozen & & other - > client )
{
// only touch-unfreeze if we have the same skin acrid3
if ( ! strcmp ( Info_ValueForKey ( ent - > client - > pers . userinfo , " skin " ) , other - > oldskin ) )
{ botDebugPrint ( " frozen and have same skin \n " ) ;
// find the player number
playernum = other - g_edicts - 1 ;
// get the userinfo
strcpy ( userinfo , other - > client - > pers . userinfo ) ;
// unfreeze me and restore skin
other - > frozen = 0 ;
Info_SetValueForKey ( userinfo , " skin " , other - > oldskin ) ;
ClientUserinfoChanged ( other , userinfo ) ;
}
}
// ******************
other - > touch ( other , ent , NULL , NULL ) ;
}
//ERASER START
if ( ( client - > latency > 0 ) & & ! ( client - > buttons & BUTTON_ATTACK ) & & ( ucmd - > buttons & BUTTON_ATTACK ) )
{
if ( ( level . time - client - > firing_delay ) > 0.1 )
client - > firing_delay = level . time + ( client - > latency / 1000 ) ;
if ( client - > firing_delay > level . time ) // turn it off
{
ucmd - > buttons & = ~ BUTTON_ATTACK ;
if ( ucmd - > buttons > = BUTTON_ANY )
ucmd - > buttons - = BUTTON_ANY ;
}
}
if ( ( client - > latency > 0 ) & & ! ( ucmd - > buttons & BUTTON_ATTACK ) & & ( client - > firing_delay > ( level . time - 0.1 ) ) & & ( client - > firing_delay < = level . time ) )
{ // remember the button after it was released when simulating lag
ucmd - > buttons | = BUTTON_ATTACK ;
}
//ERASER END
client - > oldbuttons = client - > buttons ;
client - > buttons = ucmd - > buttons ;
client - > latched_buttons | = client - > buttons & ~ client - > oldbuttons ;
// save light level the player is standing on for
// monster sighting AI
ent - > light_level = ucmd - > lightlevel ;
// fire weapon from final position if needed
if ( client - > latched_buttons & BUTTON_ATTACK
//ZOID
& & ent - > movetype ! = MOVETYPE_NOCLIP
//ZOID
)
{
if ( ! client - > weapon_thunk )
{
client - > weapon_thunk = true ;
Think_Weapon ( ent ) ;
}
}
//WF24 S ST
if ( ( ent - > client - > kamikaze_mode & 1 ) & & ( ent - > client - > kamikaze_framenum < = level . framenum ) )
Kamikaze_Explode ( ent ) ;
//WF24 E ST
//ZOID
//regen tech
CTFApplyRegeneration ( ent ) ;
//ZOID
//ZOID
//K2: Changed to use playerlist botcam
// update chase cam if being followed
// for (i = 1; i <= maxclients->value; i++) {
// other = g_edicts + i;
for ( i = 0 ; i < = num_players ; i + + ) {
other = players [ i ] ;
if ( ! other | | other - > bot_client )
continue ;
if ( other - > inuse & & other - > client - > chase_target = = ent ) //orig from here
UpdateChaseCam ( other ) ;
}
//ZOID
//WF34 START
//WF
if ( ent - > cantmove )
VectorCopy ( ent - > LockedPosition , ent - > s . origin ) ;
//WF34 END
//ERASER START
// =========================================================
// check for a bots to think
if ( ( num_players > 2 ) & & ( num_clients = = 1 ) )
{
int save = - 1 , loop_count = 0 ;
vec3_t org ;
start = last_bot ;
start_time = clock ( ) ;
now = start_time ;
// go to the next bot
last_bot + + ;
if ( last_bot > = num_players )
last_bot = 0 ;
VectorCopy ( ent - > s . origin , org ) ;
org [ 2 ] + = ent - > viewheight ;
while ( ( count < 5 ) & & ( ( ( double ) ( now - start_time ) ) < 50 ) )
{
// don't do client's, or bot's in this client's view
while ( ( players [ last_bot ] - > last_think_time = = level . time )
| | ( ! players [ last_bot ] - > bot_client )
| | ( ( gi . inPVS ( org , players [ last_bot ] - > s . origin ) )
& & ( ( players [ last_bot ] - > nextthink > = level . time )
| | ( players [ last_bot ] - > nextthink = level . time + 0.1 )
)
) // this makes the bot think by itself (smooth movement)
)
{
last_bot + + ;
if ( last_bot = = num_players )
last_bot = 0 ;
loop_count + + ;
if ( players [ last_bot ] - > bot_client & & ( last_bot = = start ) ) // we've done all bots
goto done_all_bots ;
if ( loop_count > num_players )
goto done_all_bots ;
}
if ( start = = 0 )
start = last_bot ;
if ( ( level . time - players [ last_bot ] - > last_think_time ) > = 0.1 )
{
players [ last_bot ] - > think ( players [ last_bot ] ) ;
players [ last_bot ] - > nextthink = - 1 ; // don't think by themselves
count + + ;
save = last_bot ;
}
if ( last_bot = = start ) // we've done all bots
break ;
last_bot + + ;
if ( last_bot = = num_players )
last_bot = 0 ;
loop_count + + ;
if ( loop_count > num_players )
goto done_all_bots ;
now = clock ( ) ;
}
}
done_all_bots :
/*
// check for firing between server frames
for ( i = 0 ; i < num_players ; i + + )
{
if ( ( players [ i ] - > bot_client )
& & ( players [ i ] - > dmg )
// && ( (timebuffer.millitm < players[i]->lastattack_time.millitm)
// || ((timebuffer.millitm - players[i]->lastattack_time.millitm) >= 50)
// )
)
{
bot_FireWeapon ( players [ i ] ) ;
players [ i ] - > dmg = 0 ;
}
}
*/
if ( ! dedicated - > value )
OptimizeRouteCache ( ) ; //crash???
// =========================================================
// Check to see if player pressing the "use" key newgrap 4/99
if ( ent - > client - > buttons & BUTTON_USE & & ! ent - > deadflag & &
client - > hook_frame < = level . framenum )
{
if ( ( ent - > client - > player_special & SPECIAL_GRAPPLE ) = = 0 )
{
safe_cprintf ( ent , PRINT_HIGH , " Sorry - This class cannot use the grapple. \n " ) ;
return ;
}
else if ( ent - > movetype = = MOVETYPE_NOCLIP )
{
return ;
}
else
{
int damage = 10 ;
CTFGrappleFire2 ( ent , vec3_origin , damage , 0 ) ;
// CTFWeapon_Grapple_Fire2 (ent);
}
}
if ( Ended_Grappling ( client ) & & ! ent - > deadflag & & client - > ctf_grapple )
{
CTFPlayerResetGrapple2 ( ent ) ;
}
}
//ERASER END
/*
= = = = = = = = = = = = = =
ClientBeginServerFrame
This will be called once for each server frame , before running
any other entities in the world .
= = = = = = = = = = = = = =
*/
//ERASER START
void trigger_elevator_use ( edict_t * self , edict_t * other , edict_t * activator ) ;
void Use_Plat ( edict_t * ent , edict_t * other , edict_t * activator ) ;
void CTFFlagThink ( edict_t * ent ) ;
//ERASER END
void VectorRotate ( vec3_t in , vec3_t angles , vec3_t out ) ; //WF34
void ClientBeginServerFrame ( edict_t * ent )
{
gclient_t * client ;
int i ; //ERASER
int buttonMask ;
// qboolean noise = false;
// vec3_t temp,new;//WF34
// float volume = 1.0;
// int blood;//WF34
if ( ent - > bot_client ) //ERASER
return ; //E
if ( level . intermissiontime )
return ;
//ERASER START
///Q2 Camera Begin
if ( ent - > client - > bIsCamera )
{
return ;
}
///Q2 Camera End
//ERASER END
client = ent - > client ;
/* C.O. For Lithium Test
// -- ANTI-ZBOT STARTS -- //
if ( ent - > client - > resp . bot_start > 0 & & ent - > client - > resp . bot_start < = level . time )
{
//ent->client->resp.bot_start = 0;
//stuffcmd(ent, "!zbot\n");
//ent->client->resp.bot_end = level.time + 4;
//stuffcmd(ent, "@zbot\n");
//ent->client->resp.bot_end2 = level.time + 4;
//stuffcmd(ent, "#zbot\n");
//ent->client->resp.bot_end3 = level.time + 4;
}
if ( ent - > client - > resp . bot_end > 0 & & ent - > client - > resp . bot_end < = level . time )
{
//If the player ping is too high, try again later
if ( ent - > client - > resp . bot_retries < = 4 )
{
ent - > client - > resp . bot_start = level . time + 5 + ( rand ( ) % 5 ) ;
ent - > client - > resp . bot_end = 0 ;
+ + ent - > client - > resp . bot_retries ;
}
else
{
ent - > client - > resp . bot_end = 0 ;
zbotLogAttack ( ent , 1 ) ;
//my_bprintf (PRINT_MEDIUM,"SYSTEM MESSAGE: %s has been kicked for using a ZBot.\n", ent->client->pers.netname);
safe_cprintf ( ent , PRINT_HIGH , " You have been kicked for using a ZBot (or you have a bad connection). \n " ) ;
stuffcmd ( ent , " disconnect \n " ) ; // kick out zbots.
}
}
if ( ent - > client - > resp . bot_end2 > 0 & & ent - > client - > resp . bot_end2 < = level . time )
{
//If the player ping is too high, try again later
if ( ent - > client - > resp . bot_retries2 < = 4 )
{
ent - > client - > resp . bot_start = level . time + 5 + ( rand ( ) % 5 ) ;
ent - > client - > resp . bot_end2 = 0 ;
+ + ent - > client - > resp . bot_retries2 ;
}
else
{
ent - > client - > resp . bot_end2 = 0 ;
zbotLogAttack ( ent , 2 ) ;
//my_bprintf (PRINT_MEDIUM,"SYSTEM MESSAGE: %s has been kicked for using a ZBot.\n", ent->client->pers.netname);
safe_cprintf ( ent , PRINT_HIGH , " You have been kicked for using a ZBot (or you have a bad connection). \n " ) ;
stuffcmd ( ent , " disconnect \n " ) ; // kick out zbots.
}
}
if ( ent - > client - > resp . bot_end3 > 0 & & ent - > client - > resp . bot_end3 < = level . time )
{
//If the player ping is too high, try again later
if ( ent - > client - > resp . bot_retries3 < = 4 )
{
ent - > client - > resp . bot_start = level . time + 5 + ( rand ( ) % 5 ) ;
ent - > client - > resp . bot_end3 = 0 ;
+ + ent - > client - > resp . bot_retries3 ;
}
else
{
ent - > client - > resp . bot_end3 = 0 ;
zbotLogAttack ( ent , 3 ) ;
//my_bprintf (PRINT_MEDIUM,"SYSTEM MESSAGE: %s has been kicked for using a ZBot.\n", ent->client->pers.netname);
safe_cprintf ( ent , PRINT_HIGH , " You have been kicked for using a ZBot (or you have a bad connection). \n " ) ;
stuffcmd ( ent , " disconnect \n " ) ; // kick out zbots.
}
}
C . O . For Lithium Test
*/
// -- ANTI-ZBOT ENDS -- //
// run weapon animations if it hasn't been done by a ucmd_t
if ( ! client - > weapon_thunk
//ZOID
& & ent - > movetype ! = MOVETYPE_NOCLIP
//ZOID
)
Think_Weapon ( ent ) ;
else
client - > weapon_thunk = false ;
//ERASER START
if ( client - > latency > 0 )
{
// -- save the location in the lag_trail
// filter the trails down one position
for ( i = 9 ; i > 0 ; i - - )
{
VectorCopy ( ( * client - > lag_trail ) [ i - 1 ] , ( * client - > lag_trail ) [ i ] ) ;
VectorCopy ( ( * client - > lag_angles ) [ i - 1 ] , ( * client - > lag_angles ) [ i ] ) ;
}
VectorCopy ( ent - > s . origin , ( * client - > lag_trail ) [ 0 ] ) ;
VectorCopy ( ent - > client - > v_angle , ( * client - > lag_angles ) [ 0 ] ) ;
// -- done.
}
//ERASER END
if ( ent - > deadflag )
{
// wait for any button just going down
if ( level . time > client - > respawn_time )
{
// in deathmatch, only wait for attack button
if ( deathmatch - > value )
buttonMask = BUTTON_ATTACK ;
else
buttonMask = - 1 ;
if ( ( client - > latched_buttons & buttonMask ) | |
( deathmatch - > value & & ( ( int ) dmflags - > value & DF_FORCE_RESPAWN ) ) )
{
respawn ( ent ) ;
client - > latched_buttons = 0 ;
}
}
return ;
}
// add player trail so monsters can follow
/* if (!deathmatch->value)
// if ((int)wfflags->value & WF_DECOY_PURSUE)
if ( ! visible ( ent , PlayerTrail_LastSpot ( ) ) )
// PlayerTrail_Add (ent->s.old_origin);//WF24 LINE//ACRID FIXME MAJOR TROUBLE
PlayerTrail_Add ( ent , ent - > s . old_origin , NULL , false , false , NODE_NORMAL ) ;
*/ //FIXME NODES
//WF24 E
client - > latched_buttons = 0 ;
//WF34 START
if ( ( ent - > disguised | | ent - > disguisedteam ) & & ( ent - > disguiseshots = = 0 ) )
{
WFRemoveDisguise ( ent ) ;
}
//See if menu is up
if ( ent - > client - > menu )
{
//check timeout value of menu
if ( ( client - > menu - > MenuTimeout ) & & ( level . time > client - > menu - > MenuTimeout ) )
{
client - > menu - > MenuTimeout = 0 ;
PMenu_Close ( ent ) ;
}
}
//ERASER START
// if (gi.pointcontents(ent->s.origin) & CONTENTS_LADDER)
// check for new node(s)
if ( bot_calc_nodes - > value )
{
CheckMoveForNodes ( ent ) ;
}
//if (ent->groundentity)
//gi.dprintf("%s\n", ent->groundentity->classname);
if ( ent - > flags & FL_SHOWPATH )
{
// set the target location
if ( ! ent - > goalentity ) // spawn it
{
ent - > goalentity = G_Spawn ( ) ;
ent - > goalentity - > classname = " player goal " ;
VectorCopy ( ent - > mins , ent - > goalentity - > mins ) ;
VectorCopy ( ent - > maxs , ent - > goalentity - > maxs ) ;
VectorCopy ( ent - > s . origin , ent - > goalentity - > s . origin ) ;
ent - > goalentity - > s . modelindex = 255 ;
gi . linkentity ( ent - > goalentity ) ;
}
if ( ent - > client - > buttons & BUTTON_ATTACK )
{
VectorCopy ( ent - > s . origin , ent - > goalentity - > s . origin ) ;
ent - > goalentity - > s . modelindex = 255 ;
gi . linkentity ( ent - > goalentity ) ;
}
Debug_ShowPathToGoal ( ent , ent - > goalentity ) ;
}
//gi.dprintf("%i\n", ent->waterlevel);
// HACK, send bots to us if we have the flag, and also summon some helper bots
if ( ctf - > value & & CarryingFlag ( ent ) ) // &&
// (!ent->movetarget || !ent->movetarget->item || (ent->movetarget->item->pickup != CTFPickup_Flag)))
{
edict_t * flag , * enemy_flag , * plyr , * self ;
int i = 0 , count = 0 , ideal ;
static float last_checkhelp = 0 ;
self = ent ;
if ( self - > client - > resp . ctf_team = = CTF_TEAM1 )
{
flag = flag1_ent ;
enemy_flag = flag2_ent ;
}
else
{
flag = flag2_ent ;
enemy_flag = flag1_ent ;
}
// look for some helpers
if ( last_checkhelp < ( level . time - 0.5 ) )
{
for ( i = 0 ; i < num_players ; i + + )
{
plyr = players [ i ] ;
if ( plyr - > client - > resp . ctf_team ! = self - > client - > resp . ctf_team )
{
if ( ( plyr - > enemy ! = self )
& & ( ! plyr - > target_ent | |
( plyr - > target_ent - > think ! = CTFFlagThink ) | |
( entdist ( plyr , plyr - > target_ent ) > 1000 ) )
& & ( entdist ( plyr , self ) < 2000 ) )
{ // send this enemy to us
plyr - > enemy = self ;
}
// continue;
}
if ( ( plyr ! = self ) & & ( plyr - > target_ent = = self ) )
count + + ;
}
ideal = ( ( int ) ceil ( ( 1.0 * ( float ) num_players ) / 4.0 ) ) ;
if ( count < ideal )
{
for ( i = 0 ; ( i < num_players & & count < ideal ) ; i + + )
{
plyr = players [ i ] ;
if ( plyr - > client - > resp . ctf_team ! = self - > client - > resp . ctf_team )
continue ;
if ( plyr - > target_ent = = self )
continue ;
if ( entdist ( plyr , self ) > 700 )
continue ;
if ( ! gi . inPVS ( plyr - > s . origin , self - > s . origin ) )
continue ;
plyr - > target_ent = self ;
if ( + + count > = ideal )
break ;
}
}
else if ( count > ideal ) // release a defender
{
for ( i = 0 ; ( i < num_players & & count < ideal ) ; i + + )
{
plyr = players [ i ] ;
if ( plyr - > client - > resp . ctf_team ! = self - > client - > resp . ctf_team )
continue ;
if ( plyr - > target_ent ! = self )
continue ;
plyr - > target_ent = NULL ;
break ;
}
}
last_checkhelp = level . time + random ( ) * 0.5 ;
}
}
if ( ent - > flags & FL_SHOW_FLAGPATHS )
{
edict_t * trav ;
// show lines between alternate routes
trav = NULL ;
while ( trav = G_Find ( trav , FOFS ( classname ) , " flag_path_src " ) )
{
if ( ! trav - > last_goal | | ! trav - > target_ent )
continue ; // not complete, don't save
trav - > s . modelindex = gi . modelindex ( " models/objects/gibs/chest/tris.md2 " ) ;
if ( trav - > last_goal )
{
gi . WriteByte ( svc_temp_entity ) ;
gi . WriteByte ( TE_BFG_LASER ) ;
gi . WritePosition ( trav - > s . origin ) ;
gi . WritePosition ( trav - > last_goal - > s . origin ) ;
gi . multicast ( trav - > s . origin , MULTICAST_PVS ) ;
}
if ( trav - > target_ent )
{
gi . WriteByte ( svc_temp_entity ) ;
gi . WriteByte ( TE_BFG_LASER ) ;
gi . WritePosition ( trav - > s . origin ) ;
gi . WritePosition ( trav - > target_ent - > s . origin ) ;
gi . multicast ( trav - > s . origin , MULTICAST_PHS ) ;
}
}
}
}
2024-09-02 07:12:54 -04:00
//ERASER END