2013-04-19 02:52:48 +00:00
//NPC_stats.cpp
# include "b_local.h"
# include "b_public.h"
# include "anims.h"
# include "../ghoul2/G2.h"
extern qboolean NPCsPrecached ;
# include "../namespace_begin.h"
extern qboolean WP_SaberParseParms ( const char * SaberName , saberInfo_t * saber ) ;
extern void WP_RemoveSaber ( saberInfo_t * sabers , int saberNum ) ;
# include "../namespace_end.h"
stringID_table_t TeamTable [ ] =
{
ENUM2STRING ( NPCTEAM_FREE ) , // caution, some code checks a team_t via "if (!team_t_varname)" so I guess this should stay as entry 0, great or what? -slc
ENUM2STRING ( NPCTEAM_PLAYER ) ,
ENUM2STRING ( NPCTEAM_ENEMY ) ,
ENUM2STRING ( NPCTEAM_NEUTRAL ) , // most droids are team_neutral, there are some exceptions like Probe,Seeker,Interrogator
" " , - 1
} ;
// this list was made using the model directories, this MUST be in the same order as the CLASS_ enum in teams.h
stringID_table_t ClassTable [ ] =
{
ENUM2STRING ( CLASS_NONE ) , // hopefully this will never be used by an npc), just covering all bases
ENUM2STRING ( CLASS_ATST ) , // technically droid...
ENUM2STRING ( CLASS_BARTENDER ) ,
ENUM2STRING ( CLASS_BESPIN_COP ) ,
ENUM2STRING ( CLASS_CLAW ) ,
ENUM2STRING ( CLASS_COMMANDO ) ,
ENUM2STRING ( CLASS_DESANN ) ,
ENUM2STRING ( CLASS_FISH ) ,
ENUM2STRING ( CLASS_FLIER2 ) ,
ENUM2STRING ( CLASS_GALAK ) ,
ENUM2STRING ( CLASS_GLIDER ) ,
ENUM2STRING ( CLASS_GONK ) , // droid
ENUM2STRING ( CLASS_GRAN ) ,
ENUM2STRING ( CLASS_HOWLER ) ,
// ENUM2STRING(CLASS_RANCOR),
ENUM2STRING ( CLASS_IMPERIAL ) ,
ENUM2STRING ( CLASS_IMPWORKER ) ,
ENUM2STRING ( CLASS_INTERROGATOR ) , // droid
ENUM2STRING ( CLASS_JAN ) ,
ENUM2STRING ( CLASS_JEDI ) ,
ENUM2STRING ( CLASS_KYLE ) ,
ENUM2STRING ( CLASS_LANDO ) ,
ENUM2STRING ( CLASS_LIZARD ) ,
ENUM2STRING ( CLASS_LUKE ) ,
ENUM2STRING ( CLASS_MARK1 ) , // droid
ENUM2STRING ( CLASS_MARK2 ) , // droid
ENUM2STRING ( CLASS_GALAKMECH ) , // droid
ENUM2STRING ( CLASS_MINEMONSTER ) ,
ENUM2STRING ( CLASS_MONMOTHA ) ,
ENUM2STRING ( CLASS_MORGANKATARN ) ,
ENUM2STRING ( CLASS_MOUSE ) , // droid
ENUM2STRING ( CLASS_MURJJ ) ,
ENUM2STRING ( CLASS_PRISONER ) ,
ENUM2STRING ( CLASS_PROBE ) , // droid
ENUM2STRING ( CLASS_PROTOCOL ) , // droid
ENUM2STRING ( CLASS_R2D2 ) , // droid
ENUM2STRING ( CLASS_R5D2 ) , // droid
ENUM2STRING ( CLASS_REBEL ) ,
ENUM2STRING ( CLASS_REBORN ) ,
ENUM2STRING ( CLASS_REELO ) ,
ENUM2STRING ( CLASS_REMOTE ) ,
ENUM2STRING ( CLASS_RODIAN ) ,
ENUM2STRING ( CLASS_SEEKER ) , // droid
ENUM2STRING ( CLASS_SENTRY ) ,
ENUM2STRING ( CLASS_SHADOWTROOPER ) ,
ENUM2STRING ( CLASS_STORMTROOPER ) ,
ENUM2STRING ( CLASS_SWAMP ) ,
ENUM2STRING ( CLASS_SWAMPTROOPER ) ,
ENUM2STRING ( CLASS_TAVION ) ,
ENUM2STRING ( CLASS_TRANDOSHAN ) ,
ENUM2STRING ( CLASS_UGNAUGHT ) ,
ENUM2STRING ( CLASS_JAWA ) ,
ENUM2STRING ( CLASS_WEEQUAY ) ,
ENUM2STRING ( CLASS_BOBAFETT ) ,
//ENUM2STRING(CLASS_ROCKETTROOPER),
//ENUM2STRING(CLASS_PLAYER),
ENUM2STRING ( CLASS_VEHICLE ) ,
ENUM2STRING ( CLASS_RANCOR ) ,
ENUM2STRING ( CLASS_WAMPA ) ,
" " , - 1
} ;
stringID_table_t BSTable [ ] =
{
ENUM2STRING ( BS_DEFAULT ) , //# default behavior for that NPC
ENUM2STRING ( BS_ADVANCE_FIGHT ) , //# Advance to captureGoal and shoot enemies if you can
ENUM2STRING ( BS_SLEEP ) , //# Play awake script when startled by sound
ENUM2STRING ( BS_FOLLOW_LEADER ) , //# Follow your leader and shoot any enemies you come across
ENUM2STRING ( BS_JUMP ) , //# Face navgoal and jump to it.
ENUM2STRING ( BS_SEARCH ) , //# Using current waypoint as a base), search the immediate branches of waypoints for enemies
ENUM2STRING ( BS_WANDER ) , //# Wander down random waypoint paths
ENUM2STRING ( BS_NOCLIP ) , //# Moves through walls), etc.
ENUM2STRING ( BS_REMOVE ) , //# Waits for player to leave PVS then removes itself
ENUM2STRING ( BS_CINEMATIC ) , //# Does nothing but face it's angles and move to a goal if it has one
//the rest are internal only
" " , - 1 ,
} ;
# define stringIDExpand(str, strEnum) str, strEnum, ENUM2STRING(strEnum)
stringID_table_t BSETTable [ ] =
{
ENUM2STRING ( BSET_SPAWN ) , //# script to use when first spawned
ENUM2STRING ( BSET_USE ) , //# script to use when used
ENUM2STRING ( BSET_AWAKE ) , //# script to use when awoken/startled
ENUM2STRING ( BSET_ANGER ) , //# script to use when aquire an enemy
ENUM2STRING ( BSET_ATTACK ) , //# script to run when you attack
ENUM2STRING ( BSET_VICTORY ) , //# script to run when you kill someone
ENUM2STRING ( BSET_LOSTENEMY ) , //# script to run when you can't find your enemy
ENUM2STRING ( BSET_PAIN ) , //# script to use when take pain
ENUM2STRING ( BSET_FLEE ) , //# script to use when take pain below 50% of health
ENUM2STRING ( BSET_DEATH ) , //# script to use when killed
ENUM2STRING ( BSET_DELAYED ) , //# script to run when self->delayScriptTime is reached
ENUM2STRING ( BSET_BLOCKED ) , //# script to run when blocked by a friendly NPC or player
ENUM2STRING ( BSET_BUMPED ) , //# script to run when bumped into a friendly NPC or player (can set bumpRadius)
ENUM2STRING ( BSET_STUCK ) , //# script to run when blocked by a wall
ENUM2STRING ( BSET_FFIRE ) , //# script to run when player shoots their own teammates
ENUM2STRING ( BSET_FFDEATH ) , //# script to run when player kills a teammate
stringIDExpand ( " " , BSET_INVALID ) ,
" " , - 1 ,
} ;
# include "../namespace_begin.h"
extern stringID_table_t WPTable [ ] ;
extern stringID_table_t FPTable [ ] ;
# include "../namespace_end.h"
char * TeamNames [ TEAM_NUM_TEAMS ] =
{
" " ,
// "starfleet",
// "borg",
// "parasite",
// "scavengers",
// "klingon",
// "malon",
// "hirogen",
// "imperial",
// "stasis",
// "species8472",
// "dreadnought",
// "forge",
// "disguise",
// "player (not valid)"
" player " ,
" enemy " ,
" neutral "
} ;
// this list was made using the model directories, this MUST be in the same order as the CLASS_ enum in teams.h
char * ClassNames [ CLASS_NUM_CLASSES ] =
{
" " , // class none
" atst " ,
" bartender " ,
" bespin_cop " ,
" claw " ,
" commando " ,
" desann " ,
" fish " ,
" flier2 " ,
" galak " ,
" glider " ,
" gonk " ,
" gran " ,
" howler " ,
" imperial " ,
" impworker " ,
" interrogator " ,
" jan " ,
" jedi " ,
" kyle " ,
" lando " ,
" lizard " ,
" luke " ,
" mark1 " ,
" mark2 " ,
" galak_mech " ,
" minemonster " ,
" monmotha " ,
" morgankatarn " ,
" mouse " ,
" murjj " ,
" prisoner " ,
" probe " ,
" protocol " ,
" r2d2 " ,
" r5d2 " ,
" rebel " ,
" reborn " ,
" reelo " ,
" remote " ,
" rodian " ,
" seeker " ,
" sentry " ,
" shadowtrooper " ,
" stormtrooper " ,
" swamp " ,
" swamptrooper " ,
" tavion " ,
" trandoshan " ,
" ugnaught " ,
" weequay " ,
" bobafett " ,
" vehicle " ,
" rancor " ,
" wampa " ,
} ;
/*
NPC_ReactionTime
*/
//FIXME use grandom in here
int NPC_ReactionTime ( void )
{
return 200 * ( 6 - NPCInfo - > stats . reactions ) ;
}
//
// parse support routines
//
# include "../namespace_begin.h"
extern qboolean BG_ParseLiteral ( const char * * data , const char * string ) ;
# include "../namespace_end.h"
//
// NPC parameters file : scripts/NPCs.cfg
//
# define MAX_NPC_DATA_SIZE 0x20000
char NPCParms [ MAX_NPC_DATA_SIZE ] ;
char NPCFile [ MAX_QPATH ] ;
/*
team_t TranslateTeamName ( const char * name )
{
int n ;
for ( n = ( NPCTEAM_FREE + 1 ) ; n < NPCTEAM_NUM_TEAMS ; n + + )
{
if ( Q_stricmp ( TeamNames [ n ] , name ) = = 0 )
{
return ( ( team_t ) n ) ;
}
}
return NPCTEAM_FREE ;
}
class_t TranslateClassName ( const char * name )
{
int n ;
for ( n = ( CLASS_NONE + 1 ) ; n < CLASS_NUM_CLASSES ; n + + )
{
if ( Q_stricmp ( ClassNames [ n ] , name ) = = 0 )
{
return ( ( class_t ) n ) ;
}
}
return CLASS_NONE ; // I hope this never happens, maybe print a warning
}
*/
/*
static race_t TranslateRaceName ( const char * name )
{
if ( ! Q_stricmp ( name , " human " ) )
{
return RACE_HUMAN ;
}
return RACE_NONE ;
}
*/
/*
static rank_t TranslateRankName ( const char * name )
Should be used to determine pip bolt - ons
*/
static rank_t TranslateRankName ( const char * name )
{
if ( ! Q_stricmp ( name , " civilian " ) )
{
return RANK_CIVILIAN ;
}
if ( ! Q_stricmp ( name , " crewman " ) )
{
return RANK_CREWMAN ;
}
if ( ! Q_stricmp ( name , " ensign " ) )
{
return RANK_ENSIGN ;
}
if ( ! Q_stricmp ( name , " ltjg " ) )
{
return RANK_LT_JG ;
}
if ( ! Q_stricmp ( name , " lt " ) )
{
return RANK_LT ;
}
if ( ! Q_stricmp ( name , " ltcomm " ) )
{
return RANK_LT_COMM ;
}
if ( ! Q_stricmp ( name , " commander " ) )
{
return RANK_COMMANDER ;
}
if ( ! Q_stricmp ( name , " captain " ) )
{
return RANK_CAPTAIN ;
}
return RANK_CIVILIAN ;
}
# include "../namespace_begin.h"
extern saber_colors_t TranslateSaberColor ( const char * name ) ;
# include "../namespace_end.h"
/* static int MethodNameToNumber( const char *name ) {
if ( ! Q_stricmp ( name , " EXPONENTIAL " ) ) {
return METHOD_EXPONENTIAL ;
}
if ( ! Q_stricmp ( name , " LINEAR " ) ) {
return METHOD_LINEAR ;
}
if ( ! Q_stricmp ( name , " LOGRITHMIC " ) ) {
return METHOD_LOGRITHMIC ;
}
if ( ! Q_stricmp ( name , " ALWAYS " ) ) {
return METHOD_ALWAYS ;
}
if ( ! Q_stricmp ( name , " NEVER " ) ) {
return METHOD_NEVER ;
}
return - 1 ;
}
static int ItemNameToNumber ( const char * name , int itemType ) {
// int n;
for ( n = 0 ; n < bg_numItems ; n + + ) {
if ( bg_itemlist [ n ] . type ! = itemType ) {
continue ;
}
if ( Q_stricmp ( bg_itemlist [ n ] . classname , name ) = = 0 ) {
return bg_itemlist [ n ] . tag ;
}
}
return - 1 ;
}
*/
//rwwFIXMEFIXME: movetypes
/*
static int MoveTypeNameToEnum ( const char * name )
{
if ( ! Q_stricmp ( " runjump " , name ) )
{
return MT_RUNJUMP ;
}
else if ( ! Q_stricmp ( " walk " , name ) )
{
return MT_WALK ;
}
else if ( ! Q_stricmp ( " flyswim " , name ) )
{
return MT_FLYSWIM ;
}
else if ( ! Q_stricmp ( " static " , name ) )
{
return MT_STATIC ;
}
return MT_STATIC ;
}
*/
//#define CONVENIENT_ANIMATION_FILE_DEBUG_THING
# ifdef CONVENIENT_ANIMATION_FILE_DEBUG_THING
void SpewDebugStuffToFile ( animation_t * anims )
{
char BGPAFtext [ 40000 ] ;
fileHandle_t f ;
int i = 0 ;
trap_FS_FOpenFile ( " file_of_debug_stuff_SP.txt " , & f , FS_WRITE ) ;
if ( ! f )
{
return ;
}
BGPAFtext [ 0 ] = 0 ;
while ( i < MAX_ANIMATIONS )
{
strcat ( BGPAFtext , va ( " %i %i \n " , i , anims [ i ] . frameLerp ) ) ;
i + + ;
}
trap_FS_Write ( BGPAFtext , strlen ( BGPAFtext ) , f ) ;
trap_FS_FCloseFile ( f ) ;
}
# endif
qboolean G_ParseAnimFileSet ( const char * filename , const char * animCFG , int * animFileIndex )
{
* animFileIndex = BG_ParseAnimationFile ( filename , NULL , qfalse ) ;
//if it's humanoid we should have it cached and return it, if it is not it will be loaded (unless it's also cached already)
if ( * animFileIndex = = - 1 )
{
return qfalse ;
}
//I guess this isn't really even needed game-side.
//BG_ParseAnimationSndFile(filename, *animFileIndex);
return qtrue ;
}
void NPC_PrecacheAnimationCFG ( const char * NPC_type )
{
#if 0 //rwwFIXMEFIXME: Actually precache stuff here.
char filename [ MAX_QPATH ] ;
const char * token ;
const char * value ;
const char * p ;
int junk ;
if ( ! Q_stricmp ( " random " , NPC_type ) )
{ //sorry, can't precache a random just yet
return ;
}
p = NPCParms ;
COM_BeginParseSession ( NPCFile ) ;
// look for the right NPC
while ( p )
{
token = COM_ParseExt ( & p , qtrue ) ;
if ( token [ 0 ] = = 0 )
return ;
if ( ! Q_stricmp ( token , NPC_type ) )
{
break ;
}
SkipBracedSection ( & p ) ;
}
if ( ! p )
{
return ;
}
if ( BG_ParseLiteral ( & p , " { " ) )
{
return ;
}
// parse the NPC info block
while ( 1 )
{
token = COM_ParseExt ( & p , qtrue ) ;
if ( ! token [ 0 ] )
{
Com_Printf ( S_COLOR_RED " ERROR: unexpected EOF while parsing '%s' \n " , NPC_type ) ;
return ;
}
if ( ! Q_stricmp ( token , " } " ) )
{
break ;
}
// legsmodel
if ( ! Q_stricmp ( token , " legsmodel " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
//must copy data out of this pointer into a different part of memory because the funcs we're about to call will call COM_ParseExt
Q_strncpyz ( filename , value , sizeof ( filename ) ) ;
G_ParseAnimFileSet ( filename , filename , & junk ) ;
return ;
}
// playerModel
if ( ! Q_stricmp ( token , " playerModel " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
/*
char animName [ MAX_QPATH ] ;
char * GLAName ;
char * slash = NULL ;
char * strippedName ;
int handle = gi . G2API_PrecacheGhoul2Model ( va ( " models/players/%s/model.glm " , value ) ) ;
if ( handle > 0 ) //FIXME: isn't 0 a valid handle?
{
GLAName = gi . G2API_GetAnimFileNameIndex ( handle ) ;
if ( GLAName )
{
Q_strncpyz ( animName , GLAName , sizeof ( animName ) , qtrue ) ;
slash = strrchr ( animName , ' / ' ) ;
if ( slash )
{
* slash = 0 ;
}
strippedName = COM_SkipPath ( animName ) ;
//must copy data out of this pointer into a different part of memory because the funcs we're about to call will call COM_ParseExt
Q_strncpyz ( filename , value , sizeof ( filename ) , qtrue ) ;
G_ParseAnimFileSet ( value , strippedName , & junk ) ; //qfalse );
//FIXME: still not precaching the animsounds.cfg?
return ;
}
}
*/
//rwwFIXMEFIXME: Do this properly.
}
}
# endif
}
extern int NPC_WeaponsForTeam ( team_t team , int spawnflags , const char * NPC_type ) ;
void NPC_PrecacheWeapons ( team_t playerTeam , int spawnflags , char * NPCtype )
{
int weapons = NPC_WeaponsForTeam ( playerTeam , spawnflags , NPCtype ) ;
int curWeap ;
for ( curWeap = WP_SABER ; curWeap < WP_NUM_WEAPONS ; curWeap + + )
{
if ( weapons & ( 1 < < curWeap ) )
{
RegisterItem ( BG_FindItemForWeapon ( ( weapon_t ) curWeap ) ) ;
}
}
#if 0 //rwwFIXMEFIXME: actually precache weapons here
int weapons = NPC_WeaponsForTeam ( playerTeam , spawnflags , NPCtype ) ;
gitem_t * item ;
for ( int curWeap = WP_SABER ; curWeap < WP_NUM_WEAPONS ; curWeap + + )
{
if ( ( weapons & ( 1 < < curWeap ) ) )
{
item = FindItemForWeapon ( ( ( weapon_t ) ( curWeap ) ) ) ; //precache the weapon
CG_RegisterItemSounds ( ( item - bg_itemlist ) ) ;
CG_RegisterItemVisuals ( ( item - bg_itemlist ) ) ;
//precache the in-hand/in-world ghoul2 weapon model
char weaponModel [ 64 ] ;
strcpy ( weaponModel , weaponData [ curWeap ] . weaponMdl ) ;
if ( char * spot = strstr ( weaponModel , " .md3 " ) ) {
* spot = 0 ;
spot = strstr ( weaponModel , " _w " ) ; //i'm using the in view weapon array instead of scanning the item list, so put the _w back on
if ( ! spot ) {
strcat ( weaponModel , " _w " ) ;
}
strcat ( weaponModel , " .glm " ) ; //and change to ghoul2
}
gi . G2API_PrecacheGhoul2Model ( weaponModel ) ; // correct way is item->world_model
}
}
# endif
}
/*
void NPC_Precache ( char * NPCName )
Precaches NPC skins , tgas and md3s .
*/
void NPC_Precache ( gentity_t * spawner )
{
npcteam_t playerTeam = NPCTEAM_FREE ;
const char * token ;
const char * value ;
const char * p ;
char * patch ;
char sound [ MAX_QPATH ] ;
qboolean md3Model = qfalse ;
char playerModel [ MAX_QPATH ] ;
char customSkin [ MAX_QPATH ] ;
if ( ! Q_stricmp ( " random " , spawner - > NPC_type ) )
{ //sorry, can't precache a random just yet
return ;
}
strcpy ( customSkin , " default " ) ;
p = NPCParms ;
COM_BeginParseSession ( NPCFile ) ;
// look for the right NPC
while ( p )
{
token = COM_ParseExt ( & p , qtrue ) ;
if ( token [ 0 ] = = 0 )
return ;
if ( ! Q_stricmp ( token , spawner - > NPC_type ) )
{
break ;
}
SkipBracedSection ( & p ) ;
}
if ( ! p )
{
return ;
}
if ( BG_ParseLiteral ( & p , " { " ) )
{
return ;
}
// parse the NPC info block
while ( 1 )
{
token = COM_ParseExt ( & p , qtrue ) ;
if ( ! token [ 0 ] )
{
Com_Printf ( S_COLOR_RED " ERROR: unexpected EOF while parsing '%s' \n " , spawner - > NPC_type ) ;
return ;
}
if ( ! Q_stricmp ( token , " } " ) )
{
break ;
}
// headmodel
if ( ! Q_stricmp ( token , " headmodel " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
if ( ! Q_stricmp ( " none " , value ) )
{
}
else
{
//Q_strncpyz( ri.headModelName, value, sizeof(ri.headModelName), qtrue);
}
md3Model = qtrue ;
continue ;
}
// torsomodel
if ( ! Q_stricmp ( token , " torsomodel " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
if ( ! Q_stricmp ( " none " , value ) )
{
}
else
{
//Q_strncpyz( ri.torsoModelName, value, sizeof(ri.torsoModelName), qtrue);
}
md3Model = qtrue ;
continue ;
}
// legsmodel
if ( ! Q_stricmp ( token , " legsmodel " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
//Q_strncpyz( ri.legsModelName, value, sizeof(ri.legsModelName), qtrue);
md3Model = qtrue ;
continue ;
}
// playerModel
if ( ! Q_stricmp ( token , " playerModel " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
Q_strncpyz ( playerModel , value , sizeof ( playerModel ) ) ;
md3Model = qfalse ;
continue ;
}
// customSkin
if ( ! Q_stricmp ( token , " customSkin " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
Q_strncpyz ( customSkin , value , sizeof ( customSkin ) ) ;
continue ;
}
// playerTeam
if ( ! Q_stricmp ( token , " playerTeam " ) )
{
char tk [ 4096 ] ; //rww - hackilicious!
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
//playerTeam = TranslateTeamName(value);
Com_sprintf ( tk , sizeof ( tk ) , " NPC%s " , token ) ;
playerTeam = ( team_t ) GetIDForString ( TeamTable , tk ) ;
continue ;
}
// snd
if ( ! Q_stricmp ( token , " snd " ) ) {
if ( COM_ParseString ( & p , & value ) ) {
continue ;
}
if ( ! ( spawner - > r . svFlags & SVF_NO_BASIC_SOUNDS ) )
{
//FIXME: store this in some sound field or parse in the soundTable like the animTable...
Q_strncpyz ( sound , value , sizeof ( sound ) ) ;
patch = strstr ( sound , " / " ) ;
if ( patch )
{
* patch = 0 ;
}
spawner - > s . csSounds_Std = G_SoundIndex ( va ( " *$%s " , sound ) ) ;
}
continue ;
}
// sndcombat
if ( ! Q_stricmp ( token , " sndcombat " ) ) {
if ( COM_ParseString ( & p , & value ) ) {
continue ;
}
if ( ! ( spawner - > r . svFlags & SVF_NO_COMBAT_SOUNDS ) )
{
//FIXME: store this in some sound field or parse in the soundTable like the animTable...
Q_strncpyz ( sound , value , sizeof ( sound ) ) ;
patch = strstr ( sound , " / " ) ;
if ( patch )
{
* patch = 0 ;
}
spawner - > s . csSounds_Combat = G_SoundIndex ( va ( " *$%s " , sound ) ) ;
}
continue ;
}
// sndextra
if ( ! Q_stricmp ( token , " sndextra " ) ) {
if ( COM_ParseString ( & p , & value ) ) {
continue ;
}
if ( ! ( spawner - > r . svFlags & SVF_NO_EXTRA_SOUNDS ) )
{
//FIXME: store this in some sound field or parse in the soundTable like the animTable...
Q_strncpyz ( sound , value , sizeof ( sound ) ) ;
patch = strstr ( sound , " / " ) ;
if ( patch )
{
* patch = 0 ;
}
spawner - > s . csSounds_Extra = G_SoundIndex ( va ( " *$%s " , sound ) ) ;
}
continue ;
}
// sndjedi
if ( ! Q_stricmp ( token , " sndjedi " ) ) {
if ( COM_ParseString ( & p , & value ) ) {
continue ;
}
if ( ! ( spawner - > r . svFlags & SVF_NO_EXTRA_SOUNDS ) )
{
//FIXME: store this in some sound field or parse in the soundTable like the animTable...
Q_strncpyz ( sound , value , sizeof ( sound ) ) ;
patch = strstr ( sound , " / " ) ;
if ( patch )
{
* patch = 0 ;
}
spawner - > s . csSounds_Jedi = G_SoundIndex ( va ( " *$%s " , sound ) ) ;
}
continue ;
}
if ( ! Q_stricmp ( token , " weapon " ) )
{
int curWeap ;
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
curWeap = GetIDForString ( WPTable , value ) ;
if ( curWeap > WP_NONE & & curWeap < WP_NUM_WEAPONS )
{
RegisterItem ( BG_FindItemForWeapon ( ( weapon_t ) curWeap ) ) ;
}
continue ;
}
}
// If we're not a vehicle, then an error here would be valid...
if ( ! spawner - > client | | spawner - > client - > NPC_class ! = CLASS_VEHICLE )
{
if ( md3Model )
{
Com_Printf ( " MD3 model using NPCs are not supported in MP \n " ) ;
}
else
{ //if we have a model/skin then index them so they'll be registered immediately
//when the client gets a configstring update.
char modelName [ MAX_QPATH ] ;
Com_sprintf ( modelName , sizeof ( modelName ) , " models/players/%s/model.glm " , playerModel ) ;
if ( customSkin [ 0 ] )
{ //append it after a *
strcat ( modelName , va ( " *%s " , customSkin ) ) ;
}
G_ModelIndex ( modelName ) ;
}
}
//precache this NPC's possible weapons
NPC_PrecacheWeapons ( playerTeam , spawner - > spawnflags , spawner - > NPC_type ) ;
// CG_RegisterNPCCustomSounds( &ci );
// CG_RegisterNPCEffects( playerTeam );
//rwwFIXMEFIXME: same
//FIXME: Look for a "sounds" directory and precache death, pain, alert sounds
}
#if 0
void NPC_BuildRandom ( gentity_t * NPC )
{
int sex , color , head ;
sex = Q_irand ( 0 , 2 ) ;
color = Q_irand ( 0 , 2 ) ;
switch ( sex )
{
case 0 : //female
head = Q_irand ( 0 , 2 ) ;
switch ( head )
{
default :
case 0 :
Q_strncpyz ( NPC - > client - > renderInfo . headModelName , " garren " , sizeof ( NPC - > client - > renderInfo . headModelName ) , qtrue ) ;
break ;
case 1 :
Q_strncpyz ( NPC - > client - > renderInfo . headModelName , " garren/salma " , sizeof ( NPC - > client - > renderInfo . headModelName ) , qtrue ) ;
break ;
case 2 :
Q_strncpyz ( NPC - > client - > renderInfo . headModelName , " garren/mackey " , sizeof ( NPC - > client - > renderInfo . headModelName ) , qtrue ) ;
color = Q_irand ( 3 , 5 ) ; //torso needs to be afam
break ;
}
switch ( color )
{
default :
case 0 :
Q_strncpyz ( NPC - > client - > renderInfo . torsoModelName , " crewfemale/gold " , sizeof ( NPC - > client - > renderInfo . torsoModelName ) , qtrue ) ;
break ;
case 1 :
Q_strncpyz ( NPC - > client - > renderInfo . torsoModelName , " crewfemale " , sizeof ( NPC - > client - > renderInfo . torsoModelName ) , qtrue ) ;
break ;
case 2 :
Q_strncpyz ( NPC - > client - > renderInfo . torsoModelName , " crewfemale/blue " , sizeof ( NPC - > client - > renderInfo . torsoModelName ) , qtrue ) ;
break ;
case 3 :
Q_strncpyz ( NPC - > client - > renderInfo . torsoModelName , " crewfemale/aframG " , sizeof ( NPC - > client - > renderInfo . torsoModelName ) , qtrue ) ;
break ;
case 4 :
Q_strncpyz ( NPC - > client - > renderInfo . torsoModelName , " crewfemale/aframR " , sizeof ( NPC - > client - > renderInfo . torsoModelName ) , qtrue ) ;
break ;
case 5 :
Q_strncpyz ( NPC - > client - > renderInfo . torsoModelName , " crewfemale/aframB " , sizeof ( NPC - > client - > renderInfo . torsoModelName ) , qtrue ) ;
break ;
}
Q_strncpyz ( NPC - > client - > renderInfo . legsModelName , " crewfemale " , sizeof ( NPC - > client - > renderInfo . legsModelName ) , qtrue ) ;
break ;
default :
case 1 : //male
case 2 : //male
head = Q_irand ( 0 , 4 ) ;
switch ( head )
{
default :
case 0 :
Q_strncpyz ( NPC - > client - > renderInfo . headModelName , " chakotay/nelson " , sizeof ( NPC - > client - > renderInfo . headModelName ) , qtrue ) ;
break ;
case 1 :
Q_strncpyz ( NPC - > client - > renderInfo . headModelName , " paris/chase " , sizeof ( NPC - > client - > renderInfo . headModelName ) , qtrue ) ;
break ;
case 2 :
Q_strncpyz ( NPC - > client - > renderInfo . headModelName , " doctor/pasty " , sizeof ( NPC - > client - > renderInfo . headModelName ) , qtrue ) ;
break ;
case 3 :
Q_strncpyz ( NPC - > client - > renderInfo . headModelName , " kim/durk " , sizeof ( NPC - > client - > renderInfo . headModelName ) , qtrue ) ;
break ;
case 4 :
Q_strncpyz ( NPC - > client - > renderInfo . headModelName , " paris/kray " , sizeof ( NPC - > client - > renderInfo . headModelName ) , qtrue ) ;
break ;
}
switch ( color )
{
default :
case 0 :
Q_strncpyz ( NPC - > client - > renderInfo . torsoModelName , " crewthin/red " , sizeof ( NPC - > client - > renderInfo . torsoModelName ) , qtrue ) ;
break ;
case 1 :
Q_strncpyz ( NPC - > client - > renderInfo . torsoModelName , " crewthin " , sizeof ( NPC - > client - > renderInfo . torsoModelName ) , qtrue ) ;
break ;
case 2 :
Q_strncpyz ( NPC - > client - > renderInfo . torsoModelName , " crewthin/blue " , sizeof ( NPC - > client - > renderInfo . torsoModelName ) , qtrue ) ;
break ;
//NOTE: 3 - 5 should be red, gold & blue, afram hands
}
Q_strncpyz ( NPC - > client - > renderInfo . legsModelName , " crewthin " , sizeof ( NPC - > client - > renderInfo . legsModelName ) , qtrue ) ;
break ;
}
NPC - > s . modelScale [ 0 ] = NPC - > s . modelScale [ 1 ] = NPC - > s . modelScale [ 2 ] = Q_irand ( 87 , 102 ) / 100.0f ;
// NPC->client->race = RACE_HUMAN;
NPC - > NPC - > rank = RANK_CREWMAN ;
NPC - > client - > playerTeam = NPC - > s . teamowner = TEAM_PLAYER ;
NPC - > client - > clientInfo . customBasicSoundDir = " kyle " ; //FIXME: generic default?
}
# endif
extern void SetupGameGhoul2Model ( gentity_t * ent , char * modelname , char * skinName ) ;
qboolean NPC_ParseParms ( const char * NPCName , gentity_t * NPC )
{
const char * token ;
const char * value ;
const char * p ;
int n ;
float f ;
char * patch ;
char sound [ MAX_QPATH ] ;
char playerModel [ MAX_QPATH ] ;
char customSkin [ MAX_QPATH ] ;
renderInfo_t * ri = & NPC - > client - > renderInfo ;
gNPCstats_t * stats = NULL ;
qboolean md3Model = qtrue ;
char surfOff [ 1024 ] ;
char surfOn [ 1024 ] ;
qboolean parsingPlayer = qfalse ;
vec3_t playerMins ;
vec3_t playerMaxs ;
int npcSaber1 = 0 ;
int npcSaber2 = 0 ;
VectorSet ( playerMins , - 15 , - 15 , DEFAULT_MINS_2 ) ;
VectorSet ( playerMaxs , 15 , 15 , DEFAULT_MAXS_2 ) ;
strcpy ( customSkin , " default " ) ;
if ( ! NPCName | | ! NPCName [ 0 ] )
{
NPCName = " Player " ;
}
if ( ! NPC - > s . number & & NPC - > client ! = NULL )
{ //player, only want certain data
parsingPlayer = qtrue ;
}
if ( NPC - > NPC )
{
stats = & NPC - > NPC - > stats ;
/*
NPC - > NPC - > allWeaponOrder [ 0 ] = WP_BRYAR_PISTOL ;
NPC - > NPC - > allWeaponOrder [ 1 ] = WP_SABER ;
NPC - > NPC - > allWeaponOrder [ 2 ] = WP_IMOD ;
NPC - > NPC - > allWeaponOrder [ 3 ] = WP_SCAVENGER_RIFLE ;
NPC - > NPC - > allWeaponOrder [ 4 ] = WP_TRICORDER ;
NPC - > NPC - > allWeaponOrder [ 6 ] = WP_NONE ;
NPC - > NPC - > allWeaponOrder [ 6 ] = WP_NONE ;
NPC - > NPC - > allWeaponOrder [ 7 ] = WP_NONE ;
*/
// fill in defaults
stats - > aggression = 3 ;
stats - > aim = 3 ;
stats - > earshot = 1024 ;
stats - > evasion = 3 ;
stats - > hfov = 90 ;
stats - > intelligence = 3 ;
stats - > move = 3 ;
stats - > reactions = 3 ;
stats - > vfov = 60 ;
stats - > vigilance = 0.1f ;
stats - > visrange = 1024 ;
stats - > health = 0 ;
stats - > yawSpeed = 90 ;
stats - > walkSpeed = 90 ;
stats - > runSpeed = 300 ;
stats - > acceleration = 15 ; //Increase/descrease speed this much per frame (20fps)
}
else
{
stats = NULL ;
}
//Set defaults
//FIXME: should probably put default torso and head models, but what about enemies
//that don't have any- like Stasis?
//Q_strncpyz( ri->headModelName, DEFAULT_HEADMODEL, sizeof(ri->headModelName), qtrue);
//Q_strncpyz( ri->torsoModelName, DEFAULT_TORSOMODEL, sizeof(ri->torsoModelName), qtrue);
//Q_strncpyz( ri->legsModelName, DEFAULT_LEGSMODEL, sizeof(ri->legsModelName), qtrue);
//FIXME: should we have one for weapon too?
memset ( ( char * ) surfOff , 0 , sizeof ( surfOff ) ) ;
memset ( ( char * ) surfOn , 0 , sizeof ( surfOn ) ) ;
/*
ri - > headYawRangeLeft = 50 ;
ri - > headYawRangeRight = 50 ;
ri - > headPitchRangeUp = 40 ;
ri - > headPitchRangeDown = 50 ;
ri - > torsoYawRangeLeft = 60 ;
ri - > torsoYawRangeRight = 60 ;
ri - > torsoPitchRangeUp = 30 ;
ri - > torsoPitchRangeDown = 70 ;
*/
ri - > headYawRangeLeft = 80 ;
ri - > headYawRangeRight = 80 ;
ri - > headPitchRangeUp = 45 ;
ri - > headPitchRangeDown = 45 ;
ri - > torsoYawRangeLeft = 60 ;
ri - > torsoYawRangeRight = 60 ;
ri - > torsoPitchRangeUp = 30 ;
ri - > torsoPitchRangeDown = 50 ;
VectorCopy ( playerMins , NPC - > r . mins ) ;
VectorCopy ( playerMaxs , NPC - > r . maxs ) ;
NPC - > client - > ps . crouchheight = CROUCH_MAXS_2 ;
NPC - > client - > ps . standheight = DEFAULT_MAXS_2 ;
//rwwFIXMEFIXME: ...
/*
NPC - > client - > moveType = MT_RUNJUMP ;
NPC - > client - > dismemberProbHead = 100 ;
NPC - > client - > dismemberProbArms = 100 ;
NPC - > client - > dismemberProbHands = 100 ;
NPC - > client - > dismemberProbWaist = 100 ;
NPC - > client - > dismemberProbLegs = 100 ;
NPC - > s . modelScale [ 0 ] = NPC - > s . modelScale [ 1 ] = NPC - > s . modelScale [ 2 ] = 1.0f ;
*/
NPC - > client - > ps . customRGBA [ 0 ] = 255 ;
NPC - > client - > ps . customRGBA [ 1 ] = 255 ;
NPC - > client - > ps . customRGBA [ 2 ] = 255 ;
NPC - > client - > ps . customRGBA [ 3 ] = 255 ;
if ( ! Q_stricmp ( " random " , NPCName ) )
{ //Randomly assemble a starfleet guy
//NPC_BuildRandom( NPC );
Com_Printf ( " RANDOM NPC NOT SUPPORTED IN MP \n " ) ;
return qfalse ;
}
else
{
int fp ;
p = NPCParms ;
COM_BeginParseSession ( NPCFile ) ;
// look for the right NPC
while ( p )
{
token = COM_ParseExt ( & p , qtrue ) ;
if ( token [ 0 ] = = 0 )
{
return qfalse ;
}
if ( ! Q_stricmp ( token , NPCName ) )
{
break ;
}
SkipBracedSection ( & p ) ;
}
if ( ! p )
{
return qfalse ;
}
if ( BG_ParseLiteral ( & p , " { " ) )
{
return qfalse ;
}
// parse the NPC info block
while ( 1 )
{
token = COM_ParseExt ( & p , qtrue ) ;
if ( ! token [ 0 ] )
{
Com_Printf ( S_COLOR_RED " ERROR: unexpected EOF while parsing '%s' \n " , NPCName ) ;
return qfalse ;
}
if ( ! Q_stricmp ( token , " } " ) )
{
break ;
}
//===MODEL PROPERTIES===========================================================
// custom color
if ( ! Q_stricmp ( token , " customRGBA " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
if ( ! Q_stricmp ( value , " random " ) )
{
NPC - > client - > ps . customRGBA [ 0 ] = Q_irand ( 0 , 255 ) ;
NPC - > client - > ps . customRGBA [ 1 ] = Q_irand ( 0 , 255 ) ;
NPC - > client - > ps . customRGBA [ 2 ] = Q_irand ( 0 , 255 ) ;
NPC - > client - > ps . customRGBA [ 3 ] = 255 ;
}
else
{
NPC - > client - > ps . customRGBA [ 0 ] = atoi ( value ) ;
if ( COM_ParseInt ( & p , & n ) )
{
continue ;
}
NPC - > client - > ps . customRGBA [ 1 ] = n ;
if ( COM_ParseInt ( & p , & n ) )
{
continue ;
}
NPC - > client - > ps . customRGBA [ 2 ] = n ;
if ( COM_ParseInt ( & p , & n ) )
{
continue ;
}
NPC - > client - > ps . customRGBA [ 3 ] = n ;
}
continue ;
}
// headmodel
if ( ! Q_stricmp ( token , " headmodel " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
if ( ! Q_stricmp ( " none " , value ) )
{
//Zero the head clamp range so the torso & legs don't lag behind
ri - > headYawRangeLeft =
ri - > headYawRangeRight =
ri - > headPitchRangeUp =
ri - > headPitchRangeDown = 0 ;
}
continue ;
}
// torsomodel
if ( ! Q_stricmp ( token , " torsomodel " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
if ( ! Q_stricmp ( " none " , value ) )
{
//Zero the torso clamp range so the legs don't lag behind
ri - > torsoYawRangeLeft =
ri - > torsoYawRangeRight =
ri - > torsoPitchRangeUp =
ri - > torsoPitchRangeDown = 0 ;
}
continue ;
}
// legsmodel
if ( ! Q_stricmp ( token , " legsmodel " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
/*
Q_strncpyz ( ri - > legsModelName , value , sizeof ( ri - > legsModelName ) , qtrue ) ;
//Need to do this here to get the right index
G_ParseAnimFileSet ( ri - > legsModelName , ri - > legsModelName , & ci - > animFileIndex ) ;
*/
continue ;
}
// playerModel
if ( ! Q_stricmp ( token , " playerModel " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
Q_strncpyz ( playerModel , value , sizeof ( playerModel ) ) ;
md3Model = qfalse ;
continue ;
}
// customSkin
if ( ! Q_stricmp ( token , " customSkin " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
Q_strncpyz ( customSkin , value , sizeof ( customSkin ) ) ;
continue ;
}
// surfOff
if ( ! Q_stricmp ( token , " surfOff " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
if ( surfOff [ 0 ] )
{
Q_strcat ( ( char * ) surfOff , sizeof ( surfOff ) , " , " ) ;
Q_strcat ( ( char * ) surfOff , sizeof ( surfOff ) , value ) ;
}
else
{
Q_strncpyz ( surfOff , value , sizeof ( surfOff ) ) ;
}
continue ;
}
// surfOn
if ( ! Q_stricmp ( token , " surfOn " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
if ( surfOn [ 0 ] )
{
Q_strcat ( ( char * ) surfOn , sizeof ( surfOn ) , " , " ) ;
Q_strcat ( ( char * ) surfOn , sizeof ( surfOn ) , value ) ;
}
else
{
Q_strncpyz ( surfOn , value , sizeof ( surfOn ) ) ;
}
continue ;
}
//headYawRangeLeft
if ( ! Q_stricmp ( token , " headYawRangeLeft " ) )
{
if ( COM_ParseInt ( & p , & n ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
if ( n < 0 )
{
Com_Printf ( S_COLOR_YELLOW " WARNING: bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
ri - > headYawRangeLeft = n ;
continue ;
}
//headYawRangeRight
if ( ! Q_stricmp ( token , " headYawRangeRight " ) )
{
if ( COM_ParseInt ( & p , & n ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
if ( n < 0 )
{
Com_Printf ( S_COLOR_YELLOW " WARNING: bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
ri - > headYawRangeRight = n ;
continue ;
}
//headPitchRangeUp
if ( ! Q_stricmp ( token , " headPitchRangeUp " ) )
{
if ( COM_ParseInt ( & p , & n ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
if ( n < 0 )
{
Com_Printf ( S_COLOR_YELLOW " WARNING: bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
ri - > headPitchRangeUp = n ;
continue ;
}
//headPitchRangeDown
if ( ! Q_stricmp ( token , " headPitchRangeDown " ) )
{
if ( COM_ParseInt ( & p , & n ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
if ( n < 0 )
{
Com_Printf ( S_COLOR_YELLOW " WARNING: bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
ri - > headPitchRangeDown = n ;
continue ;
}
//torsoYawRangeLeft
if ( ! Q_stricmp ( token , " torsoYawRangeLeft " ) )
{
if ( COM_ParseInt ( & p , & n ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
if ( n < 0 )
{
Com_Printf ( S_COLOR_YELLOW " WARNING: bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
ri - > torsoYawRangeLeft = n ;
continue ;
}
//torsoYawRangeRight
if ( ! Q_stricmp ( token , " torsoYawRangeRight " ) )
{
if ( COM_ParseInt ( & p , & n ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
if ( n < 0 )
{
Com_Printf ( S_COLOR_YELLOW " WARNING: bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
ri - > torsoYawRangeRight = n ;
continue ;
}
//torsoPitchRangeUp
if ( ! Q_stricmp ( token , " torsoPitchRangeUp " ) )
{
if ( COM_ParseInt ( & p , & n ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
if ( n < 0 )
{
Com_Printf ( S_COLOR_YELLOW " WARNING: bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
ri - > torsoPitchRangeUp = n ;
continue ;
}
//torsoPitchRangeDown
if ( ! Q_stricmp ( token , " torsoPitchRangeDown " ) )
{
if ( COM_ParseInt ( & p , & n ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
if ( n < 0 )
{
Com_Printf ( S_COLOR_YELLOW " WARNING: bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
ri - > torsoPitchRangeDown = n ;
continue ;
}
// Uniform XYZ scale
if ( ! Q_stricmp ( token , " scale " ) )
{
if ( COM_ParseInt ( & p , & n ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
if ( n < 0 )
{
Com_Printf ( " bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
if ( n ! = 100 )
{
NPC - > client - > ps . iModelScale = n ; //so the client knows
if ( n > = 1024 )
{
Com_Printf ( " WARNING: MP does not support scaling up to or over 1024% \n " ) ;
n = 1023 ;
}
NPC - > modelScale [ 0 ] = NPC - > modelScale [ 1 ] = NPC - > modelScale [ 2 ] = n / 100.0f ;
}
continue ;
}
//X scale
if ( ! Q_stricmp ( token , " scaleX " ) )
{
if ( COM_ParseInt ( & p , & n ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
if ( n < 0 )
{
Com_Printf ( " bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
if ( n ! = 100 )
{
Com_Printf ( " MP doesn't support xyz scaling, use 'scale'. \n " ) ;
//NPC->s.modelScale[0] = n/100.0f;
}
continue ;
}
//Y scale
if ( ! Q_stricmp ( token , " scaleY " ) )
{
if ( COM_ParseInt ( & p , & n ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
if ( n < 0 )
{
Com_Printf ( " bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
if ( n ! = 100 )
{
Com_Printf ( " MP doesn't support xyz scaling, use 'scale'. \n " ) ;
//NPC->s.modelScale[1] = n/100.0f;
}
continue ;
}
//Z scale
if ( ! Q_stricmp ( token , " scaleZ " ) )
{
if ( COM_ParseInt ( & p , & n ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
if ( n < 0 )
{
Com_Printf ( " bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
if ( n ! = 100 )
{
Com_Printf ( " MP doesn't support xyz scaling, use 'scale'. \n " ) ;
// NPC->s.modelScale[2] = n/100.0f;
}
continue ;
}
//===AI STATS=====================================================================
if ( ! parsingPlayer )
{
// aggression
if ( ! Q_stricmp ( token , " aggression " ) ) {
if ( COM_ParseInt ( & p , & n ) ) {
SkipRestOfLine ( & p ) ;
continue ;
}
if ( n < 1 | | n > 5 ) {
Com_Printf ( " bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
if ( NPC - > NPC )
{
stats - > aggression = n ;
}
continue ;
}
// aim
if ( ! Q_stricmp ( token , " aim " ) ) {
if ( COM_ParseInt ( & p , & n ) ) {
SkipRestOfLine ( & p ) ;
continue ;
}
if ( n < 1 | | n > 5 ) {
Com_Printf ( " bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
if ( NPC - > NPC )
{
stats - > aim = n ;
}
continue ;
}
// earshot
if ( ! Q_stricmp ( token , " earshot " ) ) {
if ( COM_ParseFloat ( & p , & f ) ) {
SkipRestOfLine ( & p ) ;
continue ;
}
if ( f < 0.0f )
{
Com_Printf ( " bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
if ( NPC - > NPC )
{
stats - > earshot = f ;
}
continue ;
}
// evasion
if ( ! Q_stricmp ( token , " evasion " ) )
{
if ( COM_ParseInt ( & p , & n ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
if ( n < 1 | | n > 5 )
{
Com_Printf ( S_COLOR_YELLOW " WARNING: bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
if ( NPC - > NPC )
{
stats - > evasion = n ;
}
continue ;
}
// hfov
if ( ! Q_stricmp ( token , " hfov " ) ) {
if ( COM_ParseInt ( & p , & n ) ) {
SkipRestOfLine ( & p ) ;
continue ;
}
if ( n < 30 | | n > 180 ) {
Com_Printf ( " bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
if ( NPC - > NPC )
{
stats - > hfov = n ; // / 2; //FIXME: Why was this being done?!
}
continue ;
}
// intelligence
if ( ! Q_stricmp ( token , " intelligence " ) ) {
if ( COM_ParseInt ( & p , & n ) ) {
SkipRestOfLine ( & p ) ;
continue ;
}
if ( n < 1 | | n > 5 ) {
Com_Printf ( " bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
if ( NPC - > NPC )
{
stats - > intelligence = n ;
}
continue ;
}
// move
if ( ! Q_stricmp ( token , " move " ) ) {
if ( COM_ParseInt ( & p , & n ) ) {
SkipRestOfLine ( & p ) ;
continue ;
}
if ( n < 1 | | n > 5 ) {
Com_Printf ( " bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
if ( NPC - > NPC )
{
stats - > move = n ;
}
continue ;
}
// reactions
if ( ! Q_stricmp ( token , " reactions " ) ) {
if ( COM_ParseInt ( & p , & n ) ) {
SkipRestOfLine ( & p ) ;
continue ;
}
if ( n < 1 | | n > 5 ) {
Com_Printf ( " bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
if ( NPC - > NPC )
{
stats - > reactions = n ;
}
continue ;
}
// shootDistance
if ( ! Q_stricmp ( token , " shootDistance " ) ) {
if ( COM_ParseFloat ( & p , & f ) ) {
SkipRestOfLine ( & p ) ;
continue ;
}
if ( f < 0.0f )
{
Com_Printf ( " bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
if ( NPC - > NPC )
{
stats - > shootDistance = f ;
}
continue ;
}
// vfov
if ( ! Q_stricmp ( token , " vfov " ) ) {
if ( COM_ParseInt ( & p , & n ) ) {
SkipRestOfLine ( & p ) ;
continue ;
}
if ( n < 30 | | n > 180 ) {
Com_Printf ( " bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
if ( NPC - > NPC )
{
stats - > vfov = n / 2 ;
}
continue ;
}
// vigilance
if ( ! Q_stricmp ( token , " vigilance " ) ) {
if ( COM_ParseFloat ( & p , & f ) ) {
SkipRestOfLine ( & p ) ;
continue ;
}
if ( f < 0.0f )
{
Com_Printf ( " bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
if ( NPC - > NPC )
{
stats - > vigilance = f ;
}
continue ;
}
// visrange
if ( ! Q_stricmp ( token , " visrange " ) ) {
if ( COM_ParseFloat ( & p , & f ) ) {
SkipRestOfLine ( & p ) ;
continue ;
}
if ( f < 0.0f )
{
Com_Printf ( " bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
if ( NPC - > NPC )
{
stats - > visrange = f ;
}
continue ;
}
// race
// if ( !Q_stricmp( token, "race" ) )
// {
// if ( COM_ParseString( &p, &value ) )
// {
// continue;
// }
// NPC->client->race = TranslateRaceName(value);
// continue;
// }
// rank
if ( ! Q_stricmp ( token , " rank " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
if ( NPC - > NPC )
{
NPC - > NPC - > rank = TranslateRankName ( value ) ;
}
continue ;
}
}
// health
if ( ! Q_stricmp ( token , " health " ) )
{
if ( COM_ParseInt ( & p , & n ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
if ( n < 0 )
{
Com_Printf ( S_COLOR_YELLOW " WARNING: bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
if ( NPC - > NPC )
{
stats - > health = n ;
}
else if ( parsingPlayer )
{
NPC - > client - > ps . stats [ STAT_MAX_HEALTH ] = NPC - > client - > pers . maxHealth = n ;
}
continue ;
}
// fullName
if ( ! Q_stricmp ( token , " fullName " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
NPC - > fullName = G_NewString ( value ) ;
continue ;
}
// playerTeam
if ( ! Q_stricmp ( token , " playerTeam " ) )
{
char tk [ 4096 ] ; //rww - hackilicious!
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
Com_sprintf ( tk , sizeof ( tk ) , " NPC%s " , token ) ;
NPC - > client - > playerTeam = NPC - > s . teamowner = ( team_t ) GetIDForString ( TeamTable , tk ) ; //TranslateTeamName(value);
continue ;
}
// enemyTeam
if ( ! Q_stricmp ( token , " enemyTeam " ) )
{
char tk [ 4096 ] ; //rww - hackilicious!
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
Com_sprintf ( tk , sizeof ( tk ) , " NPC%s " , token ) ;
NPC - > client - > enemyTeam = ( team_t ) GetIDForString ( TeamTable , tk ) ; //TranslateTeamName(value);
continue ;
}
// class
if ( ! Q_stricmp ( token , " class " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
NPC - > client - > NPC_class = ( class_t ) GetIDForString ( ClassTable , value ) ;
NPC - > s . NPC_class = NPC - > client - > NPC_class ; //we actually only need this value now, but at the moment I don't feel like changing the 200+ references to client->NPC_class.
// No md3's for vehicles.
if ( NPC - > client - > NPC_class = = CLASS_VEHICLE )
{
if ( ! NPC - > m_pVehicle )
{ //you didn't spawn this guy right!
Com_Printf ( S_COLOR_RED " ERROR: Tried to spawn a vehicle NPC (%s) without using NPC_Vehicle or 'NPC spawn vehicle <vehiclename>'!!! Bad, bad, bad! Shame on you! \n " , NPCName ) ;
return qfalse ;
}
md3Model = qfalse ;
}
continue ;
}
// dismemberment probability for head
if ( ! Q_stricmp ( token , " dismemberProbHead " ) ) {
if ( COM_ParseInt ( & p , & n ) ) {
SkipRestOfLine ( & p ) ;
continue ;
}
if ( n < 0 )
{
Com_Printf ( " bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
if ( NPC - > NPC )
{
// NPC->client->dismemberProbHead = n;
//rwwFIXMEFIXME: support for this?
}
continue ;
}
// dismemberment probability for arms
if ( ! Q_stricmp ( token , " dismemberProbArms " ) ) {
if ( COM_ParseInt ( & p , & n ) ) {
SkipRestOfLine ( & p ) ;
continue ;
}
if ( n < 0 )
{
Com_Printf ( " bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
if ( NPC - > NPC )
{
// NPC->client->dismemberProbArms = n;
}
continue ;
}
// dismemberment probability for hands
if ( ! Q_stricmp ( token , " dismemberProbHands " ) ) {
if ( COM_ParseInt ( & p , & n ) ) {
SkipRestOfLine ( & p ) ;
continue ;
}
if ( n < 0 )
{
Com_Printf ( " bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
if ( NPC - > NPC )
{
// NPC->client->dismemberProbHands = n;
}
continue ;
}
// dismemberment probability for waist
if ( ! Q_stricmp ( token , " dismemberProbWaist " ) ) {
if ( COM_ParseInt ( & p , & n ) ) {
SkipRestOfLine ( & p ) ;
continue ;
}
if ( n < 0 )
{
Com_Printf ( " bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
if ( NPC - > NPC )
{
// NPC->client->dismemberProbWaist = n;
}
continue ;
}
// dismemberment probability for legs
if ( ! Q_stricmp ( token , " dismemberProbLegs " ) ) {
if ( COM_ParseInt ( & p , & n ) ) {
SkipRestOfLine ( & p ) ;
continue ;
}
if ( n < 0 )
{
Com_Printf ( " bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
if ( NPC - > NPC )
{
// NPC->client->dismemberProbLegs = n;
}
continue ;
}
//===MOVEMENT STATS============================================================
if ( ! Q_stricmp ( token , " width " ) )
{
if ( COM_ParseInt ( & p , & n ) )
{
continue ;
}
NPC - > r . mins [ 0 ] = NPC - > r . mins [ 1 ] = - n ;
NPC - > r . maxs [ 0 ] = NPC - > r . maxs [ 1 ] = n ;
continue ;
}
if ( ! Q_stricmp ( token , " height " ) )
{
if ( COM_ParseInt ( & p , & n ) )
{
continue ;
}
if ( NPC - > client - > NPC_class = = CLASS_VEHICLE
& & NPC - > m_pVehicle
& & NPC - > m_pVehicle - > m_pVehicleInfo
& & NPC - > m_pVehicle - > m_pVehicleInfo - > type = = VH_FIGHTER )
{ //a flying vehicle's origin must be centered in bbox and it should spawn on the ground
//trace_t tr;
//vec3_t bottom;
//float adjust = 32.0f;
NPC - > r . maxs [ 2 ] = NPC - > client - > ps . standheight = ( n / 2.0f ) ;
NPC - > r . mins [ 2 ] = - NPC - > r . maxs [ 2 ] ;
NPC - > s . origin [ 2 ] + = ( DEFAULT_MINS_2 - NPC - > r . mins [ 2 ] ) + 0.125f ;
VectorCopy ( NPC - > s . origin , NPC - > client - > ps . origin ) ;
VectorCopy ( NPC - > s . origin , NPC - > r . currentOrigin ) ;
G_SetOrigin ( NPC , NPC - > s . origin ) ;
trap_LinkEntity ( NPC ) ;
//now trace down
/*
VectorCopy ( NPC - > s . origin , bottom ) ;
bottom [ 2 ] - = adjust ;
trap_Trace ( & tr , NPC - > s . origin , NPC - > r . mins , NPC - > r . maxs , bottom , NPC - > s . number , MASK_NPCSOLID ) ;
if ( ! tr . allsolid & & ! tr . startsolid )
{
G_SetOrigin ( NPC , tr . endpos ) ;
trap_LinkEntity ( NPC ) ;
}
*/
}
else
{
NPC - > r . mins [ 2 ] = DEFAULT_MINS_2 ; //Cannot change
NPC - > r . maxs [ 2 ] = NPC - > client - > ps . standheight = n + DEFAULT_MINS_2 ;
}
NPC - > radius = n ;
continue ;
}
if ( ! Q_stricmp ( token , " crouchheight " ) )
{
if ( COM_ParseInt ( & p , & n ) )
{
continue ;
}
NPC - > client - > ps . crouchheight = n + DEFAULT_MINS_2 ;
continue ;
}
if ( ! parsingPlayer )
{
if ( ! Q_stricmp ( token , " movetype " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
if ( Q_stricmp ( " flyswim " , value ) = = 0 )
{
NPC - > client - > ps . eFlags2 | = EF2_FLYING ;
}
//NPC->client->moveType = (movetype_t)MoveTypeNameToEnum(value);
//rwwFIXMEFIXME: support for movetypes
continue ;
}
// yawSpeed
if ( ! Q_stricmp ( token , " yawSpeed " ) ) {
if ( COM_ParseInt ( & p , & n ) ) {
SkipRestOfLine ( & p ) ;
continue ;
}
if ( n < = 0 ) {
Com_Printf ( " bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
if ( NPC - > NPC )
{
stats - > yawSpeed = ( ( float ) ( n ) ) ;
}
continue ;
}
// walkSpeed
if ( ! Q_stricmp ( token , " walkSpeed " ) )
{
if ( COM_ParseInt ( & p , & n ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
if ( n < 0 )
{
Com_Printf ( S_COLOR_YELLOW " WARNING: bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
if ( NPC - > NPC )
{
stats - > walkSpeed = n ;
}
continue ;
}
//runSpeed
if ( ! Q_stricmp ( token , " runSpeed " ) )
{
if ( COM_ParseInt ( & p , & n ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
if ( n < 0 )
{
Com_Printf ( S_COLOR_YELLOW " WARNING: bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
if ( NPC - > NPC )
{
stats - > runSpeed = n ;
}
continue ;
}
//acceleration
if ( ! Q_stricmp ( token , " acceleration " ) )
{
if ( COM_ParseInt ( & p , & n ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
if ( n < 0 )
{
Com_Printf ( S_COLOR_YELLOW " WARNING: bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
if ( NPC - > NPC )
{
stats - > acceleration = n ;
}
continue ;
}
//sex - skip in MP
if ( ! Q_stricmp ( token , " sex " ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//===MISC===============================================================================
// default behavior
if ( ! Q_stricmp ( token , " behavior " ) )
{
if ( COM_ParseInt ( & p , & n ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
if ( n < BS_DEFAULT | | n > = NUM_BSTATES )
{
Com_Printf ( S_COLOR_YELLOW " WARNING: bad %s in NPC '%s' \n " , token , NPCName ) ;
continue ;
}
if ( NPC - > NPC )
{
NPC - > NPC - > defaultBehavior = ( bState_t ) ( n ) ;
}
continue ;
}
}
// snd
if ( ! Q_stricmp ( token , " snd " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
if ( ! ( NPC - > r . svFlags & SVF_NO_BASIC_SOUNDS ) )
{
//FIXME: store this in some sound field or parse in the soundTable like the animTable...
Q_strncpyz ( sound , value , sizeof ( sound ) ) ;
patch = strstr ( sound , " / " ) ;
if ( patch )
{
* patch = 0 ;
}
// ci->customBasicSoundDir = G_NewString( sound );
//rwwFIXMEFIXME: Hooray for violating client server rules
}
continue ;
}
// sndcombat
if ( ! Q_stricmp ( token , " sndcombat " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
if ( ! ( NPC - > r . svFlags & SVF_NO_COMBAT_SOUNDS ) )
{
//FIXME: store this in some sound field or parse in the soundTable like the animTable...
Q_strncpyz ( sound , value , sizeof ( sound ) ) ;
patch = strstr ( sound , " / " ) ;
if ( patch )
{
* patch = 0 ;
}
// ci->customCombatSoundDir = G_NewString( sound );
}
continue ;
}
// sndextra
if ( ! Q_stricmp ( token , " sndextra " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
if ( ! ( NPC - > r . svFlags & SVF_NO_EXTRA_SOUNDS ) )
{
//FIXME: store this in some sound field or parse in the soundTable like the animTable...
Q_strncpyz ( sound , value , sizeof ( sound ) ) ;
patch = strstr ( sound , " / " ) ;
if ( patch )
{
* patch = 0 ;
}
// ci->customExtraSoundDir = G_NewString( sound );
}
continue ;
}
// sndjedi
if ( ! Q_stricmp ( token , " sndjedi " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
if ( ! ( NPC - > r . svFlags & SVF_NO_EXTRA_SOUNDS ) )
{
//FIXME: store this in some sound field or parse in the soundTable like the animTable...
Q_strncpyz ( sound , value , sizeof ( sound ) ) ;
patch = strstr ( sound , " / " ) ;
if ( patch )
{
* patch = 0 ;
}
//ci->customJediSoundDir = G_NewString( sound );
}
continue ;
}
//New NPC/jedi stats:
//starting weapon
if ( ! Q_stricmp ( token , " weapon " ) )
{
int weap ;
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
//FIXME: need to precache the weapon, too? (in above func)
weap = GetIDForString ( WPTable , value ) ;
if ( weap > = WP_NONE & & weap < = WP_NUM_WEAPONS ) ///*WP_BLASTER_PISTOL*/WP_SABER ) //?!
{
NPC - > client - > ps . weapon = weap ;
NPC - > client - > ps . stats [ STAT_WEAPONS ] | = ( 1 < < NPC - > client - > ps . weapon ) ;
if ( weap > WP_NONE )
{
// RegisterItem( FindItemForWeapon( (weapon_t)(NPC->client->ps.weapon) ) ); //precache the weapon
NPC - > client - > ps . ammo [ weaponData [ NPC - > client - > ps . weapon ] . ammoIndex ] = 100 ; //FIXME: max ammo!
}
}
continue ;
}
if ( ! parsingPlayer )
{
//altFire
if ( ! Q_stricmp ( token , " altFire " ) )
{
if ( COM_ParseInt ( & p , & n ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
if ( NPC - > NPC )
{
if ( n ! = 0 )
{
NPC - > NPC - > scriptFlags | = SCF_ALT_FIRE ;
}
}
continue ;
}
//Other unique behaviors/numbers that are currently hardcoded?
}
//force powers
fp = GetIDForString ( FPTable , token ) ;
if ( fp > = FP_FIRST & & fp < NUM_FORCE_POWERS )
{
if ( COM_ParseInt ( & p , & n ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//FIXME: need to precache the fx, too? (in above func)
//cap
if ( n > 5 )
{
n = 5 ;
}
else if ( n < 0 )
{
n = 0 ;
}
if ( n )
{ //set
NPC - > client - > ps . fd . forcePowersKnown | = ( 1 < < fp ) ;
}
else
{ //clear
NPC - > client - > ps . fd . forcePowersKnown & = ~ ( 1 < < fp ) ;
}
NPC - > client - > ps . fd . forcePowerLevel [ fp ] = n ;
continue ;
}
//max force power
if ( ! Q_stricmp ( token , " forcePowerMax " ) )
{
if ( COM_ParseInt ( & p , & n ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
NPC - > client - > ps . fd . forcePowerMax = n ;
continue ;
}
//force regen rate - default is 100ms
if ( ! Q_stricmp ( token , " forceRegenRate " ) )
{
if ( COM_ParseInt ( & p , & n ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//NPC->client->ps.forcePowerRegenRate = n;
//rwwFIXMEFIXME: support this?
continue ;
}
//force regen amount - default is 1 (points per second)
if ( ! Q_stricmp ( token , " forceRegenAmount " ) )
{
if ( COM_ParseInt ( & p , & n ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//NPC->client->ps.forcePowerRegenAmount = n;
//rwwFIXMEFIXME: support this?
continue ;
}
//have a sabers.cfg and just name your saber in your NPCs.cfg/ICARUS script
//saber name
if ( ! Q_stricmp ( token , " saber " ) )
{
char * saberName ;
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
saberName = ( char * ) BG_TempAlloc ( 4096 ) ; //G_NewString( value );
strcpy ( saberName , value ) ;
WP_SaberParseParms ( saberName , & NPC - > client - > saber [ 0 ] ) ;
npcSaber1 = G_ModelIndex ( va ( " @%s " , saberName ) ) ;
BG_TempFree ( 4096 ) ;
continue ;
}
//second saber name
if ( ! Q_stricmp ( token , " saber2 " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
if ( ! ( NPC - > client - > saber [ 0 ] . saberFlags & SFL_TWO_HANDED ) )
{ //can't use a second saber if first one is a two-handed saber...?
char * saberName = ( char * ) BG_TempAlloc ( 4096 ) ; //G_NewString( value );
strcpy ( saberName , value ) ;
WP_SaberParseParms ( saberName , & NPC - > client - > saber [ 1 ] ) ;
if ( ( NPC - > client - > saber [ 1 ] . saberFlags & SFL_TWO_HANDED ) )
{ //tsk tsk, can't use a twoHanded saber as second saber
WP_RemoveSaber ( NPC - > client - > saber , 1 ) ;
}
else
{
//NPC->client->ps.dualSabers = qtrue;
npcSaber2 = G_ModelIndex ( va ( " @%s " , saberName ) ) ;
}
BG_TempFree ( 4096 ) ;
}
continue ;
}
// saberColor
if ( ! Q_stricmp ( token , " saberColor " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
if ( NPC - > client )
{
saber_colors_t color = TranslateSaberColor ( value ) ;
for ( n = 0 ; n < MAX_BLADES ; n + + )
{
NPC - > client - > saber [ 0 ] . blade [ n ] . color = color ;
}
}
continue ;
}
if ( ! Q_stricmp ( token , " saberColor2 " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
if ( NPC - > client )
{
NPC - > client - > saber [ 0 ] . blade [ 1 ] . color = TranslateSaberColor ( value ) ;
}
continue ;
}
if ( ! Q_stricmp ( token , " saberColor3 " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
if ( NPC - > client )
{
NPC - > client - > saber [ 0 ] . blade [ 2 ] . color = TranslateSaberColor ( value ) ;
}
continue ;
}
if ( ! Q_stricmp ( token , " saberColor4 " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
if ( NPC - > client )
{
NPC - > client - > saber [ 0 ] . blade [ 3 ] . color = TranslateSaberColor ( value ) ;
}
continue ;
}
if ( ! Q_stricmp ( token , " saberColor5 " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
if ( NPC - > client )
{
NPC - > client - > saber [ 0 ] . blade [ 4 ] . color = TranslateSaberColor ( value ) ;
}
continue ;
}
if ( ! Q_stricmp ( token , " saberColor6 " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
if ( NPC - > client )
{
NPC - > client - > saber [ 0 ] . blade [ 5 ] . color = TranslateSaberColor ( value ) ;
}
continue ;
}
if ( ! Q_stricmp ( token , " saberColor7 " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
if ( NPC - > client )
{
NPC - > client - > saber [ 0 ] . blade [ 6 ] . color = TranslateSaberColor ( value ) ;
}
continue ;
}
if ( ! Q_stricmp ( token , " saberColor8 " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
if ( NPC - > client )
{
NPC - > client - > saber [ 0 ] . blade [ 7 ] . color = TranslateSaberColor ( value ) ;
}
continue ;
}
if ( ! Q_stricmp ( token , " saber2Color " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
if ( NPC - > client )
{
saber_colors_t color = TranslateSaberColor ( value ) ;
for ( n = 0 ; n < MAX_BLADES ; n + + )
{
NPC - > client - > saber [ 1 ] . blade [ n ] . color = color ;
}
}
continue ;
}
if ( ! Q_stricmp ( token , " saber2Color2 " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
if ( NPC - > client )
{
NPC - > client - > saber [ 1 ] . blade [ 1 ] . color = TranslateSaberColor ( value ) ;
}
continue ;
}
if ( ! Q_stricmp ( token , " saber2Color3 " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
if ( NPC - > client )
{
NPC - > client - > saber [ 1 ] . blade [ 2 ] . color = TranslateSaberColor ( value ) ;
}
continue ;
}
if ( ! Q_stricmp ( token , " saber2Color4 " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
if ( NPC - > client )
{
NPC - > client - > saber [ 1 ] . blade [ 3 ] . color = TranslateSaberColor ( value ) ;
}
continue ;
}
if ( ! Q_stricmp ( token , " saber2Color5 " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
if ( NPC - > client )
{
NPC - > client - > saber [ 1 ] . blade [ 4 ] . color = TranslateSaberColor ( value ) ;
}
continue ;
}
if ( ! Q_stricmp ( token , " saber2Color6 " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
if ( NPC - > client )
{
NPC - > client - > saber [ 1 ] . blade [ 5 ] . color = TranslateSaberColor ( value ) ;
}
continue ;
}
if ( ! Q_stricmp ( token , " saber2Color7 " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
if ( NPC - > client )
{
NPC - > client - > saber [ 1 ] . blade [ 6 ] . color = TranslateSaberColor ( value ) ;
}
continue ;
}
if ( ! Q_stricmp ( token , " saber2Color8 " ) )
{
if ( COM_ParseString ( & p , & value ) )
{
continue ;
}
if ( NPC - > client )
{
NPC - > client - > saber [ 1 ] . blade [ 7 ] . color = TranslateSaberColor ( value ) ;
}
continue ;
}
//saber length
if ( ! Q_stricmp ( token , " saberLength " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 4.0f )
{
f = 4.0f ;
}
for ( n = 0 ; n < MAX_BLADES ; n + + )
{
NPC - > client - > saber [ 0 ] . blade [ n ] . lengthMax = f ;
}
continue ;
}
if ( ! Q_stricmp ( token , " saberLength2 " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 4.0f )
{
f = 4.0f ;
}
NPC - > client - > saber [ 0 ] . blade [ 1 ] . lengthMax = f ;
continue ;
}
if ( ! Q_stricmp ( token , " saberLength3 " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 4.0f )
{
f = 4.0f ;
}
NPC - > client - > saber [ 0 ] . blade [ 2 ] . lengthMax = f ;
continue ;
}
if ( ! Q_stricmp ( token , " saberLength4 " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 4.0f )
{
f = 4.0f ;
}
NPC - > client - > saber [ 0 ] . blade [ 3 ] . lengthMax = f ;
continue ;
}
if ( ! Q_stricmp ( token , " saberLength5 " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 4.0f )
{
f = 4.0f ;
}
NPC - > client - > saber [ 0 ] . blade [ 4 ] . lengthMax = f ;
continue ;
}
if ( ! Q_stricmp ( token , " saberLength6 " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 4.0f )
{
f = 4.0f ;
}
NPC - > client - > saber [ 0 ] . blade [ 5 ] . lengthMax = f ;
continue ;
}
if ( ! Q_stricmp ( token , " saberLength7 " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 4.0f )
{
f = 4.0f ;
}
NPC - > client - > saber [ 0 ] . blade [ 6 ] . lengthMax = f ;
continue ;
}
if ( ! Q_stricmp ( token , " saberLength8 " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 4.0f )
{
f = 4.0f ;
}
NPC - > client - > saber [ 0 ] . blade [ 7 ] . lengthMax = f ;
continue ;
}
if ( ! Q_stricmp ( token , " saber2Length " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 4.0f )
{
f = 4.0f ;
}
for ( n = 0 ; n < MAX_BLADES ; n + + )
{
NPC - > client - > saber [ 1 ] . blade [ n ] . lengthMax = f ;
}
continue ;
}
if ( ! Q_stricmp ( token , " saber2Length2 " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 4.0f )
{
f = 4.0f ;
}
NPC - > client - > saber [ 1 ] . blade [ 1 ] . lengthMax = f ;
continue ;
}
if ( ! Q_stricmp ( token , " saber2Length3 " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 4.0f )
{
f = 4.0f ;
}
NPC - > client - > saber [ 1 ] . blade [ 2 ] . lengthMax = f ;
continue ;
}
if ( ! Q_stricmp ( token , " saber2Length4 " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 4.0f )
{
f = 4.0f ;
}
NPC - > client - > saber [ 1 ] . blade [ 3 ] . lengthMax = f ;
continue ;
}
if ( ! Q_stricmp ( token , " saber2Length5 " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 4.0f )
{
f = 4.0f ;
}
NPC - > client - > saber [ 1 ] . blade [ 4 ] . lengthMax = f ;
continue ;
}
if ( ! Q_stricmp ( token , " saber2Length6 " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 4.0f )
{
f = 4.0f ;
}
NPC - > client - > saber [ 1 ] . blade [ 5 ] . lengthMax = f ;
continue ;
}
if ( ! Q_stricmp ( token , " saber2Length7 " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 4.0f )
{
f = 4.0f ;
}
NPC - > client - > saber [ 1 ] . blade [ 6 ] . lengthMax = f ;
continue ;
}
if ( ! Q_stricmp ( token , " saber2Length8 " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 4.0f )
{
f = 4.0f ;
}
NPC - > client - > saber [ 1 ] . blade [ 7 ] . lengthMax = f ;
continue ;
}
//saber radius
if ( ! Q_stricmp ( token , " saberRadius " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 0.25f )
{
f = 0.25f ;
}
for ( n = 0 ; n < MAX_BLADES ; n + + )
{
NPC - > client - > saber [ 0 ] . blade [ n ] . radius = f ;
}
continue ;
}
if ( ! Q_stricmp ( token , " saberRadius2 " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 0.25f )
{
f = 0.25f ;
}
NPC - > client - > saber [ 0 ] . blade [ 1 ] . radius = f ;
continue ;
}
if ( ! Q_stricmp ( token , " saberRadius3 " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 0.25f )
{
f = 0.25f ;
}
NPC - > client - > saber [ 0 ] . blade [ 2 ] . radius = f ;
continue ;
}
if ( ! Q_stricmp ( token , " saberRadius4 " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 0.25f )
{
f = 0.25f ;
}
NPC - > client - > saber [ 0 ] . blade [ 3 ] . radius = f ;
continue ;
}
if ( ! Q_stricmp ( token , " saberRadius5 " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 0.25f )
{
f = 0.25f ;
}
NPC - > client - > saber [ 0 ] . blade [ 4 ] . radius = f ;
continue ;
}
if ( ! Q_stricmp ( token , " saberRadius6 " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 0.25f )
{
f = 0.25f ;
}
NPC - > client - > saber [ 0 ] . blade [ 5 ] . radius = f ;
continue ;
}
if ( ! Q_stricmp ( token , " saberRadius7 " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 0.25f )
{
f = 0.25f ;
}
NPC - > client - > saber [ 0 ] . blade [ 6 ] . radius = f ;
continue ;
}
if ( ! Q_stricmp ( token , " saberRadius8 " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 0.25f )
{
f = 0.25f ;
}
NPC - > client - > saber [ 0 ] . blade [ 7 ] . radius = f ;
continue ;
}
if ( ! Q_stricmp ( token , " saber2Radius " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 0.25f )
{
f = 0.25f ;
}
for ( n = 0 ; n < MAX_BLADES ; n + + )
{
NPC - > client - > saber [ 1 ] . blade [ n ] . radius = f ;
}
continue ;
}
if ( ! Q_stricmp ( token , " saber2Radius2 " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 0.25f )
{
f = 0.25f ;
}
NPC - > client - > saber [ 1 ] . blade [ 1 ] . radius = f ;
continue ;
}
if ( ! Q_stricmp ( token , " saber2Radius3 " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 0.25f )
{
f = 0.25f ;
}
NPC - > client - > saber [ 1 ] . blade [ 2 ] . radius = f ;
continue ;
}
if ( ! Q_stricmp ( token , " saber2Radius4 " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 0.25f )
{
f = 0.25f ;
}
NPC - > client - > saber [ 1 ] . blade [ 3 ] . radius = f ;
continue ;
}
if ( ! Q_stricmp ( token , " saber2Radius5 " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 0.25f )
{
f = 0.25f ;
}
NPC - > client - > saber [ 1 ] . blade [ 4 ] . radius = f ;
continue ;
}
if ( ! Q_stricmp ( token , " saber2Radius6 " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 0.25f )
{
f = 0.25f ;
}
NPC - > client - > saber [ 1 ] . blade [ 5 ] . radius = f ;
continue ;
}
if ( ! Q_stricmp ( token , " saber2Radius7 " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 0.25f )
{
f = 0.25f ;
}
NPC - > client - > saber [ 1 ] . blade [ 6 ] . radius = f ;
continue ;
}
if ( ! Q_stricmp ( token , " saber2Radius8 " ) )
{
if ( COM_ParseFloat ( & p , & f ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( f < 0.25f )
{
f = 0.25f ;
}
NPC - > client - > saber [ 1 ] . blade [ 7 ] . radius = f ;
continue ;
}
//ADD:
//saber sounds (on, off, loop)
//loop sound (like Vader's breathing or droid bleeps, etc.)
//starting saber style
if ( ! Q_stricmp ( token , " saberStyle " ) )
{
if ( COM_ParseInt ( & p , & n ) )
{
SkipRestOfLine ( & p ) ;
continue ;
}
//cap
if ( n < 0 )
{
n = 0 ;
}
else if ( n > 5 )
{
n = 5 ;
}
NPC - > client - > ps . fd . saberAnimLevel = n ;
/*
if ( parsingPlayer )
{
cg . saberAnimLevelPending = n ;
}
*/
continue ;
}
if ( ! parsingPlayer )
{
Com_Printf ( " WARNING: unknown keyword '%s' while parsing '%s' \n " , token , NPCName ) ;
}
SkipRestOfLine ( & p ) ;
}
}
/*
Ghoul2 Insert Start
*/
if ( ! md3Model )
{
qboolean setTypeBack = qfalse ;
if ( npcSaber1 = = 0 )
{ //use "kyle" for a default then
npcSaber1 = G_ModelIndex ( " @Kyle " ) ;
WP_SaberParseParms ( " Kyle " , & NPC - > client - > saber [ 0 ] ) ;
}
NPC - > s . npcSaber1 = npcSaber1 ;
NPC - > s . npcSaber2 = npcSaber2 ;
if ( ! customSkin [ 0 ] )
{
strcpy ( customSkin , " default " ) ;
}
if ( NPC - > client & & NPC - > client - > NPC_class = = CLASS_VEHICLE )
{ //vehicles want their names fed in as models
//we put the $ in front to indicate a name and not a model
strcpy ( playerModel , va ( " $%s " , NPCName ) ) ;
}
SetupGameGhoul2Model ( NPC , playerModel , customSkin ) ;
if ( ! NPC - > NPC_type )
{ //just do this for now so NPC_Precache can see the name.
NPC - > NPC_type = ( char * ) NPCName ;
setTypeBack = qtrue ;
}
NPC_Precache ( NPC ) ; //this will just soundindex some values for sounds on the client,
if ( setTypeBack )
{ //don't want this being set if we aren't ready yet.
NPC - > NPC_type = NULL ;
}
}
else
{
Com_Printf ( " MD3 MODEL NPC'S ARE NOT SUPPORTED IN MP! \n " ) ;
return qfalse ;
}
/*
Ghoul2 Insert End
*/
/*
if ( NPCsPrecached )
{ //Spawning in after initial precache, our models are precached, we just need to set our clientInfo
CG_RegisterClientModels ( NPC - > s . number ) ;
CG_RegisterNPCCustomSounds ( ci ) ;
CG_RegisterNPCEffects ( NPC - > client - > playerTeam ) ;
}
*/
//rwwFIXMEFIXME: Do something here I guess to properly precache stuff.
return qtrue ;
}
# ifdef _XBOX
char * npcParseBuffer = NULL ;
# else
char npcParseBuffer [ MAX_NPC_DATA_SIZE ] ;
# endif
void NPC_LoadParms ( void )
{
int len , totallen , npcExtFNLen , mainBlockLen , fileCnt , i ;
// const char *filename = "ext_data/NPC2.cfg";
char /**buffer,*/ * holdChar , * marker ;
char npcExtensionListBuf [ 2048 ] ; // The list of file names read in
fileHandle_t f ;
len = 0 ;
//remember where to store the next one
totallen = mainBlockLen = len ;
marker = NPCParms + totallen ;
* marker = 0 ;
//now load in the extra .npc extensions
fileCnt = trap_FS_GetFileList ( " ext_data/NPCs " , " .npc " , npcExtensionListBuf , sizeof ( npcExtensionListBuf ) ) ;
# ifdef _XBOX
npcParseBuffer = ( char * ) Z_Malloc ( MAX_NPC_DATA_SIZE , TAG_TEMP_WORKSPACE , qfalse , 4 ) ;
# endif
holdChar = npcExtensionListBuf ;
for ( i = 0 ; i < fileCnt ; i + + , holdChar + = npcExtFNLen + 1 )
{
npcExtFNLen = strlen ( holdChar ) ;
// Com_Printf( "Parsing %s\n", holdChar );
len = trap_FS_FOpenFile ( va ( " ext_data/NPCs/%s " , holdChar ) , & f , FS_READ ) ;
if ( len = = - 1 )
{
Com_Printf ( " error reading file \n " ) ;
}
else
{
if ( totallen + len > = MAX_NPC_DATA_SIZE ) {
G_Error ( " NPC extensions (*.npc) are too large " ) ;
}
trap_FS_Read ( npcParseBuffer , len , f ) ;
npcParseBuffer [ len ] = 0 ;
len = COM_Compress ( npcParseBuffer ) ;
strcat ( marker , npcParseBuffer ) ;
strcat ( marker , " \n " ) ;
len + + ;
trap_FS_FCloseFile ( f ) ;
totallen + = len ;
marker = NPCParms + totallen ;
//*marker = 0; //rww - make sure this is null or strcat will not append to the correct place
//rww 12/19/02-actually the probelm was npcParseBuffer not being nul-term'd, which could cause issues in the strcat too
}
}
# ifdef _XBOX
Z_Free ( npcParseBuffer ) ;
npcParseBuffer = NULL ;
# endif
}