示例#1
0
static void IT_ParseWeaponParms( const char **holdBuf ) {
	int i;

	while ( holdBuf ) {
		const char *token = COM_ParseExt( holdBuf, qtrue );

		if ( !Q_stricmp( token, "}" ) ) {
			// end of data for this weapon
			break;
		}

		// loop through possible parameters
		for ( i = 0; i < IT_PARM_MAX; i++ ) {
			if ( !Q_stricmp( token, ItemParms[i].parmName ) ) {
				ItemParms[i].func( holdBuf );
				break;
			}
		}

		if ( i < IT_PARM_MAX ) {
			// find parameter???
			continue;
		}

		Com_Printf( S_COLOR_YELLOW "WARNING: bad parameter in external item data '%s'\n", token );
		SkipRestOfLine( holdBuf );
	}
}
static void IT_ParseWeaponParms(const char **holdBuf)
{
	static int	weaponNum,ammoNum;
	const char	*token;
	int		i;


	while (holdBuf)
	{
		token = COM_ParseExt( holdBuf, qtrue );

		if (!Q_stricmp( token, "}" ))	// End of data for this weapon
			break;

		// Loop through possible parameters
		for (i=0;i<IT_PARM_MAX;++i)
		{
			if (!Q_stricmp(token,ItemParms[i].parmName))	
			{
				ItemParms[i].func(holdBuf);
				break;
			}
		}

		if (i < IT_PARM_MAX)	// Find parameter???
		{
			continue;
		}

		gi.Printf("bad parameter in external weapon data '%s'\n", token);
		SkipRestOfLine(holdBuf);
		
	}
}
/**

  @author   Mikkel B. Stegmann
  @version  4-17-2000

  @return   Nothing.

*/
void AFReader::SkipComments() {
    int ch;
    ch = getc( fh );
    if ( ch==COMMENT_CHAR ) {
        SkipRestOfLine();
        SkipComments();
    } else {
        ungetc( ch, fh );
    }
}
示例#4
0
static void IT_Max( const char **holdBuf ) {
	int tokenInt;

	for ( int i = 0; i < 3; i++ ) {
		if ( COM_ParseInt( holdBuf, &tokenInt ) ) {
			SkipRestOfLine( holdBuf );
			return;
		}
		bg_itemlist[itemNum].maxs[i] = tokenInt;
	}
}
示例#5
0
void WPN_AltSplashRadius(const char **holdBuf)
{
	float	tokenFlt;

	if( COM_ParseFloat(holdBuf,&tokenFlt))
	{
		SkipRestOfLine(holdBuf);
		return;
	}

	weaponData[wpnParms.weaponNum].altSplashRadius = tokenFlt;
}
示例#6
0
void WPN_AltSplashDamage(const char **holdBuf)
{
	int		tokenInt;

	if( COM_ParseInt(holdBuf,&tokenInt))
	{
		SkipRestOfLine(holdBuf);
		return;
	}

	weaponData[wpnParms.weaponNum].altSplashDamage = tokenInt;
}
示例#7
0
static void IT_Count( const char **holdBuf ) {
	int tokenInt;

	if ( COM_ParseInt( holdBuf, &tokenInt ) ) {
		SkipRestOfLine( holdBuf );
		return;
	}

	if ( tokenInt < 0 || tokenInt > 1000 ) {
		gi.Printf( "WARNING: bad Count in external item data '%d'\n", tokenInt );
		return;
	}
	bg_itemlist[itemNum].quantity = tokenInt;
}
示例#8
0
//--------------------------------------------
void WPN_AltMissileLight(const char **holdBuf)
{
	float	tokenFlt;

	if ( COM_ParseFloat(holdBuf,&tokenFlt)) 
	{
		SkipRestOfLine(holdBuf);
	}

	if ((tokenFlt < 0) || (tokenFlt > 255 )) // FIXME :What are the right values?
	{
		gi.Printf(S_COLOR_YELLOW"WARNING: bad altmissilelight in external weapon data '%f'\n", tokenFlt);
	}
	weaponData[wpnParms.weaponNum].alt_missileDlight = tokenFlt;
}
static void IT_Min(const char **holdBuf)
{
	int		tokenInt;
	int		i;

	for (i=0;i<3;++i)
	{
		if ( COM_ParseInt(holdBuf,&tokenInt)) 
		{
			SkipRestOfLine(holdBuf);
			return;
		}

		bg_itemlist[itemParms.itemNum].mins[i] = tokenInt;
	}

}
示例#10
0
//--------------------------------------------
void WPN_AltEnergyPerShot(const char **holdBuf)
{
	int		tokenInt;

	if ( COM_ParseInt(holdBuf,&tokenInt)) 
	{
		SkipRestOfLine(holdBuf);
		return;
	}

	if ((tokenInt < 0) || (tokenInt > 1000 )) // FIXME :What are the right values?
	{
		gi.Printf(S_COLOR_YELLOW"WARNING: bad AltEnergyPerShot in external weapon data '%d'\n", tokenInt);
		return;
	}
	weaponData[wpnParms.weaponNum].altEnergyPerShot = tokenInt;
}
示例#11
0
//--------------------------------------------
void WPN_AmmoMax(const char **holdBuf)
{
	int		tokenInt;

	if ( COM_ParseInt(holdBuf,&tokenInt)) 
	{
		SkipRestOfLine(holdBuf);
		return;
	}

	if ((tokenInt < 0) || (tokenInt > 1000 )) 
	{
		gi.Printf(S_COLOR_YELLOW"WARNING: bad Ammo Max in external weapon data '%d'\n", tokenInt);
		return;
	}
	ammoData[wpnParms.ammoNum].max = tokenInt;
}
示例#12
0
//--------------------------------------------
void WPN_BarrelCount(const char **holdBuf)
{
	int		tokenInt;

	if ( COM_ParseInt(holdBuf,&tokenInt)) 
	{
		SkipRestOfLine(holdBuf);
		return;
	}

	if ((tokenInt < 0) || (tokenInt > 4 )) 
	{
		gi.Printf(S_COLOR_YELLOW"WARNING: bad Range in external weapon data '%d'\n", tokenInt);
		return;
	}

	weaponData[wpnParms.weaponNum].numBarrels = tokenInt;
}
示例#13
0
//--------------------------------------------
void WPN_AmmoType(const char **holdBuf)
{
	int		tokenInt;

	if ( COM_ParseInt(holdBuf,&tokenInt)) 
	{
		SkipRestOfLine(holdBuf);
		return;
	}

	if ((tokenInt < AMMO_NONE ) || (tokenInt >= AMMO_MAX ))
	{
		gi.Printf(S_COLOR_YELLOW"WARNING: bad Ammotype in external weapon data '%d'\n", tokenInt);
		return;
	}

	weaponData[wpnParms.weaponNum].ammoIndex = tokenInt;
}
示例#14
0
static void IT_Count(const char **holdBuf)
{
	int		tokenInt;

	if ( COM_ParseInt(holdBuf,&tokenInt)) 
	{
		SkipRestOfLine(holdBuf);
		return;
	}

	if ((tokenInt < 0) || (tokenInt > 1000 )) // FIXME :What are the right values?
	{
		gi.Printf("WARNING: bad Count in external item data '%d'\n", tokenInt);
		return;
	}
	bg_itemlist[itemParms.itemNum].quantity = tokenInt;

}
示例#15
0
//--------------------------------------------
static void WP_ParseWeaponParms(const char **holdBuf)
{
	const char	*token;
	int		i;


	while (holdBuf)
	{
		token = COM_ParseExt( holdBuf, qtrue );

		if (!Q_stricmp( token, "}" ))	// End of data for this weapon
			break;

		// Loop through possible parameters
		for (i=0;i<WPN_PARM_MAX;++i)
		{
			if (!Q_stricmp(token,WpnParms[i].parmName))	
			{
				WpnParms[i].func(holdBuf);
				break;
			}
		}

		if (i < WPN_PARM_MAX)	// Find parameter???
		{
			continue;
		}

		if ( !Q_stricmp( token, "firingForce" ) ||
			!Q_stricmp( token, "altFiringForce") ||
			!Q_stricmp( token, "chargeForce" ) ||
			!Q_stricmp( token, "altChargeForce") ||
			!Q_stricmp( token, "stopForce" ) ||
			!Q_stricmp( token, "selectForce" ) )
		{
			SkipRestOfLine( holdBuf );
			continue;	// Deprecated. Originally part of Force Feedback stuff, which is illegal to redistribute. --eez
		}
		Com_Error(ERR_FATAL,"bad parameter in external weapon data '%s'\n", token);		
	}
}
示例#16
0
//--------------------------------------------
void WPN_AltMissileLightColor(const char **holdBuf)
{
	int i;
	float	tokenFlt;

	for (i=0;i<3;++i)
	{
		if ( COM_ParseFloat(holdBuf,&tokenFlt)) 
		{
			SkipRestOfLine(holdBuf);
			continue;
		}

		if ((tokenFlt < 0) || (tokenFlt > 1 ))
		{
			gi.Printf(S_COLOR_YELLOW"WARNING: bad altmissilelightcolor in external weapon data '%f'\n", tokenFlt);
			continue;
		}
		weaponData[wpnParms.weaponNum].alt_missileDlightColor[i] = tokenFlt;
	}

}
示例#17
0
qboolean WP_SaberParseParms( const char *SaberName, saberInfo_t *saber, qboolean setColors ) 
{
	const char	*token;
	const char	*value;
	const char	*p;
	float	f;
	int		n;

	if ( !saber ) 
	{
		return qfalse;
	}
	
	//Set defaults so that, if it fails, there's at least something there
	WP_SaberSetDefaults( saber, setColors );

	if ( !SaberName || !SaberName[0] ) 
	{
		return qfalse;
	}

	saber->name = G_NewString( SaberName );
	//try to parse it out
	p = SaberParms;
	COM_BeginParseSession();

	// look for the right saber
	while ( p )
	{
		token = COM_ParseExt( &p, qtrue );
		if ( token[0] == 0 )
		{
			return qfalse;
		}

		if ( !Q_stricmp( token, SaberName ) ) 
		{
			break;
		}

		SkipBracedSection( &p );
	}
	if ( !p ) 
	{
		return qfalse;
	}

	if ( G_ParseLiteral( &p, "{" ) ) 
	{
		return qfalse;
	}
		
	// parse the saber info block
	while ( 1 ) 
	{
		token = COM_ParseExt( &p, qtrue );
		if ( !token[0] ) 
		{
			gi.Printf( S_COLOR_RED"ERROR: unexpected EOF while parsing '%s'\n", SaberName );
			return qfalse;
		}

		if ( !Q_stricmp( token, "}" ) ) 
		{
			break;
		}

		//saber fullName
		if ( !Q_stricmp( token, "name" ) ) 
		{
			if ( COM_ParseString( &p, &value ) ) 
			{
				continue;
			}
			saber->fullName = G_NewString( value );
			continue;
		}

		//saber type
		if ( !Q_stricmp( token, "saberType" ) ) 
		{
			if ( COM_ParseString( &p, &value ) ) 
			{
				continue;
			}
			int saberType = GetIDForString( SaberTable, value );
			if ( saberType >= SABER_SINGLE && saberType <= NUM_SABERS )
			{
				saber->type = (saberType_t)saberType;
			}
			continue;
		}

		//saber hilt
		if ( !Q_stricmp( token, "saberModel" ) ) 
		{
			if ( COM_ParseString( &p, &value ) ) 
			{
				continue;
			}
			saber->model = G_NewString( value );
			continue;
		}

		if ( !Q_stricmp( token, "customSkin" ) )
		{
			if ( COM_ParseString( &p, &value ) ) 
			{
				continue;
			}
			saber->skin = G_NewString( value );
			continue;
		}

		//on sound
		if ( !Q_stricmp( token, "soundOn" ) ) 
		{
			if ( COM_ParseString( &p, &value ) ) 
			{
				continue;
			}
			saber->soundOn = G_SoundIndex( G_NewString( value ) );
			continue;
		}

		//loop sound
		if ( !Q_stricmp( token, "soundLoop" ) ) 
		{
			if ( COM_ParseString( &p, &value ) ) 
			{
				continue;
			}
			saber->soundLoop = G_SoundIndex( G_NewString( value ) );
			continue;
		}

		//off sound
		if ( !Q_stricmp( token, "soundOff" ) ) 
		{
			if ( COM_ParseString( &p, &value ) ) 
			{
				continue;
			}
			saber->soundOff = G_SoundIndex( G_NewString( value ) );
			continue;
		}

		if ( !Q_stricmp( token, "numBlades" ) ) 
		{
			if ( COM_ParseInt( &p, &n ) ) 
			{
				SkipRestOfLine( &p );
				continue;
			}
			if ( n < 1 || n >= MAX_BLADES )
			{
				G_Error( "WP_SaberParseParms: saber %s has illegal number of blades (%d) max: %d", SaberName, n, MAX_BLADES );
				continue;
			}
			saber->numBlades = n;
			continue;
		}

		// saberColor
		if ( !Q_stricmpn( token, "saberColor", 10 ) ) 
		{
			if ( !setColors )
			{//don't actually want to set the colors
				//read the color out anyway just to advance the *p pointer
				COM_ParseString( &p, &value );
				continue;
			}
			else
			{
				if (strlen(token)==10)
				{
					n = -1;
				}
				else if (strlen(token)==11)
				{
					n = atoi(&token[10])-1;
					if (n > 7 || n < 1 )
					{
						gi.Printf( S_COLOR_YELLOW"WARNING: bad saberColor '%s' in %s\n", token, SaberName );
						//read the color out anyway just to advance the *p pointer
						COM_ParseString( &p, &value );
						continue;
					}
				}
				else
				{
					gi.Printf( S_COLOR_YELLOW"WARNING: bad saberColor '%s' in %s\n", token, SaberName );
					//read the color out anyway just to advance the *p pointer
					COM_ParseString( &p, &value );
					continue;
				}

				if ( COM_ParseString( &p, &value ) )	//read the color
				{
					continue;
				}

				if (n==-1)
				{//NOTE: this fills in the rest of the blades with the same color by default
					saber_colors_t color = TranslateSaberColor( value );
					for ( n = 0; n < MAX_BLADES; n++ )
					{
						saber->blade[n].color = color;
					}
				} else 
				{
					saber->blade[n].color = TranslateSaberColor( value );
				}
				continue;
			}
		}

		//saber length
		if ( !Q_stricmpn( token, "saberLength", 11 ) ) 
		{
			if (strlen(token)==11)
			{
				n = -1;
			}
			else if (strlen(token)==12)
			{
				n = atoi(&token[11])-1;
				if (n > 7 || n < 1 )
				{
					gi.Printf( S_COLOR_YELLOW"WARNING: bad saberLength '%s' in %s\n", token, SaberName );
					continue;
				}
			}
			else
			{
				gi.Printf( S_COLOR_YELLOW"WARNING: bad saberLength '%s' in %s\n", token, SaberName );
				continue;
			}

			if ( COM_ParseFloat( &p, &f ) ) 
			{
				SkipRestOfLine( &p );
				continue;
			}
			//cap
			if ( f < 4.0f )
			{
				f = 4.0f;
			}

			if (n==-1)
			{//NOTE: this fills in the rest of the blades with the same length by default
				for ( n = 0; n < MAX_BLADES; n++ )
				{
					saber->blade[n].lengthMax = f;
				}
			}
			else
			{
				saber->blade[n].lengthMax = f;
			}
			continue;
		}

		//blade radius
		if ( !Q_stricmpn( token, "saberRadius", 11 ) ) 
		{
			if (strlen(token)==11)
			{
				n = -1;
			}
			else if (strlen(token)==12)
			{
				n = atoi(&token[11])-1;
				if (n > 7 || n < 1 )
				{
					gi.Printf( S_COLOR_YELLOW"WARNING: bad saberRadius '%s' in %s\n", token, SaberName );
					continue;
				}
			}
			else
			{
				gi.Printf( S_COLOR_YELLOW"WARNING: bad saberRadius '%s' in %s\n", token, SaberName );
				continue;
			}

			if ( COM_ParseFloat( &p, &f ) ) 
			{
				SkipRestOfLine( &p );
				continue;
			}
			//cap
			if ( f < 0.25f )
			{
				f = 0.25f;
			}
			if (n==-1)
			{//NOTE: this fills in the rest of the blades with the same length by default
				for ( n = 0; n < MAX_BLADES; n++ )
				{
					saber->blade[n].radius = f;
				}
			}
			else
			{
				saber->blade[n].radius = f;
			}
			continue;
		}

		//locked saber style
		if ( !Q_stricmp( token, "saberStyle" ) ) 
		{
			if ( COM_ParseString( &p, &value ) ) 
			{
				continue;
			}
			saber->style = TranslateSaberStyle( value );
			continue;
		}

		//maxChain
		if ( !Q_stricmp( token, "maxChain" ) ) 
		{
			if ( COM_ParseInt( &p, &n ) ) 
			{
				SkipRestOfLine( &p );
				continue;
			}
			saber->maxChain = n;
			continue;
		}

		//lockable
		if ( !Q_stricmp( token, "lockable" ) ) 
		{
			if ( COM_ParseInt( &p, &n ) ) 
			{
				SkipRestOfLine( &p );
				continue;
			}
			saber->lockable = ((qboolean)(n!=0));
			continue;
		}

		//throwable
		if ( !Q_stricmp( token, "throwable" ) ) 
		{
			if ( COM_ParseInt( &p, &n ) ) 
			{
				SkipRestOfLine( &p );
				continue;
			}
			saber->throwable = ((qboolean)(n!=0));
			continue;
		}

		//disarmable
		if ( !Q_stricmp( token, "disarmable" ) ) 
		{
			if ( COM_ParseInt( &p, &n ) ) 
			{
				SkipRestOfLine( &p );
				continue;
			}
			saber->disarmable = ((qboolean)(n!=0));
			continue;
		}

		//active blocking
		if ( !Q_stricmp( token, "blocking" ) ) 
		{
			if ( COM_ParseInt( &p, &n ) ) 
			{
				SkipRestOfLine( &p );
				continue;
			}
			saber->activeBlocking = ((qboolean)(n!=0));
			continue;
		}

		//twoHanded
		if ( !Q_stricmp( token, "twoHanded" ) ) 
		{
			if ( COM_ParseInt( &p, &n ) ) 
			{
				SkipRestOfLine( &p );
				continue;
			}
			saber->twoHanded = ((qboolean)(n!=0));
			continue;
		}

		//force power restrictions
		if ( !Q_stricmp( token, "forceRestrict" ) ) 
		{
			if ( COM_ParseString( &p, &value ) ) 
			{
				continue;
			}
			int fp = GetIDForString( FPTable, value );
			if ( fp >= FP_FIRST && fp < NUM_FORCE_POWERS )
			{
				saber->forceRestrictions |= (1<<fp);
			}
			continue;
		}

		//lockBonus
		if ( !Q_stricmp( token, "lockBonus" ) ) 
		{
			if ( COM_ParseInt( &p, &n ) ) 
			{
				SkipRestOfLine( &p );
				continue;
			}
			saber->lockBonus = n;
			continue;
		}

		//parryBonus
		if ( !Q_stricmp( token, "parryBonus" ) ) 
		{
			if ( COM_ParseInt( &p, &n ) ) 
			{
				SkipRestOfLine( &p );
				continue;
			}
			saber->parryBonus = n;
			continue;
		}

		//breakParryBonus
		if ( !Q_stricmp( token, "breakParryBonus" ) ) 
		{
			if ( COM_ParseInt( &p, &n ) ) 
			{
				SkipRestOfLine( &p );
				continue;
			}
			saber->breakParryBonus = n;
			continue;
		}

		//disarmBonus
		if ( !Q_stricmp( token, "disarmBonus" ) ) 
		{
			if ( COM_ParseInt( &p, &n ) ) 
			{
				SkipRestOfLine( &p );
				continue;
			}
			saber->disarmBonus = n;
			continue;
		}

		//single blade saber style
		if ( !Q_stricmp( token, "singleBladeStyle" ) ) 
		{
			if ( COM_ParseString( &p, &value ) ) 
			{
				continue;
			}
			saber->singleBladeStyle = TranslateSaberStyle( value );
			continue;
		}

		//single blade throwable
		if ( !Q_stricmp( token, "singleBladeThrowable" ) ) 
		{
			if ( COM_ParseInt( &p, &n ) ) 
			{
				SkipRestOfLine( &p );
				continue;
			}
			saber->singleBladeThrowable = ((qboolean)(n!=0));
			continue;
		}

		//broken replacement saber1 (right hand)
		if ( !Q_stricmp( token, "brokenSaber1" ) ) 
		{
			if ( COM_ParseString( &p, &value ) ) 
			{
				continue;
			}
			saber->brokenSaber1 = G_NewString( value );
			continue;
		}
		
		//broken replacement saber2 (left hand)
		if ( !Q_stricmp( token, "brokenSaber2" ) ) 
		{
			if ( COM_ParseString( &p, &value ) ) 
			{
				continue;
			}
			saber->brokenSaber2 = G_NewString( value );
			continue;
		}

		//spins and does damage on return from saberthrow
		if ( !Q_stricmp( token, "returnDamage" ) ) 
		{
			if ( COM_ParseInt( &p, &n ) ) 
			{
				SkipRestOfLine( &p );
				continue;
			}
			saber->returnDamage = ((qboolean)(n!=0));
			continue;
		}

		if ( !Q_stricmp( token, "notInMP" ) ) 
		{//ignore this
			SkipRestOfLine( &p );
			continue;
		}

		gi.Printf( "WARNING: unknown keyword '%s' while parsing '%s'\n", token, SaberName );
		SkipRestOfLine( &p );
	}

	//FIXME: precache the saberModel(s)?

	if ( saber->type == SABER_SITH_SWORD )
	{//precache all the sith sword sounds
		Saber_SithSwordPrecache();
	}

	return qtrue;
}
示例#18
0
void WPN_FuncSkip( const char **holdBuf)
{
	SkipRestOfLine(holdBuf);
}
示例#19
0
/*
==============
Bot_ScriptParseAllCharacters
==============
*/
void Bot_ScriptParseAllCharacters()
{
	char           *pScript;
	char           *token;
	bot_script_global_data_t *bsd;
	char            params[MAX_TOKEN_CHARS];

	if(!level.scriptEntity)
	{
		return;
	}

	pScript = level.scriptEntity;
	COM_BeginParseSession("Bot_ScriptParse");
	numScriptCharacters = 0;
	memset(botCharacterScriptData, 0, sizeof(botCharacterScriptData));

	while(1)
	{
		token = COM_Parse(&pScript);
		// we are expecting a name here
		if(!token[0])
		{
			// end of script
			break;
		}
		if(token[0] == '{' || token[0] == '}')
		{
			G_Error("Bot_ScriptParse(), Error (line %d): entry identifier expected, '%s' found.\n", 1 + COM_GetCurrentParseLine(),
					token);
		}
		// is this a bot?
		if(Q_stricmp(token, "BOT") != 0)
		{
			// not a bot, skip this whole entry
			SkipRestOfLine(&pScript);
			// skip this section
			SkipBracedSection(&pScript);
			//
			continue;
		}
		// this is the name
		if(numScriptCharacters == MAX_BOT_SCRIPT_CHARACTERS)
		{
			G_Error
				("Bot_ScriptParse(), Error (line %d): MAX_BOT_SCRIPT_CHARACTERS exceeded (%i), too many bot script characters\n",
				 1 + COM_GetCurrentParseLine(), MAX_BOT_SCRIPT_CHARACTERS);
			break;
		}
		bsd = &botCharacterScriptData[numScriptCharacters++];
		bsd->lineNum = 1 + COM_GetCurrentParseLine();
		// read the name
		token = COM_Parse(&pScript);
		// we are expecting a name here
		if(!token[0])
		{
			G_Error("Bot_ScriptParse(), Error (line %d): name expected, end of line found.\n", 1 + COM_GetCurrentParseLine());
		}
		if(token[0] == '{' || token[0] == '}')
		{
			G_Error("Bot_ScriptParse(), Error (line %d): name expected, '%s' found.\n", 1 + COM_GetCurrentParseLine(), token);
		}
		// allocate the name
		bsd->name = G_Alloc(strlen(token) + 1);
		Q_strncpyz(bsd->name, token, strlen(token) + 1);
		// read the params
		memset(params, 0, sizeof(params));
		while((token = COM_ParseExt(&pScript, qfalse)) && token[0])
		{
			if(strlen(params) + strlen(token) >= sizeof(params))
			{
				G_Error("Bot_ScriptParse(), Error (line %d): parameters exceed maximum size\n", 1 + COM_GetCurrentParseLine());
			}
			if(strlen(params) > 0)
			{
				Q_strcat(params, sizeof(params), " ");
			}
			Q_strcat(params, sizeof(params), token);
		}
		// allocate the params
		bsd->params = G_Alloc(strlen(params) + 1);
		Q_strncpyz(bsd->params, params, strlen(params) + 1);
		// allocate memory for this character script
		bsd->data = G_Alloc(sizeof(bot_script_data_t));
		memset(bsd->data, 0, sizeof(bot_script_data_t));
		// now parse the script data for this character
		Bot_ScriptParse(bsd->data, &pScript);
	}
}
示例#20
0
qboolean UI_SaberParseParm( const char *saberName, const char *parmname, char *saberData ) 
{
	const char	*token;
	const char	*value;
	const char	*p;

	if ( !saberName || !saberName[0] ) 
	{
		return qfalse;
	}

	//try to parse it out
	p = SaberParms;
	COM_BeginParseSession();

	// look for the right saber
	while ( p )
	{
		token = COM_ParseExt( &p, qtrue );
		if ( token[0] == 0 )
		{
			return qfalse;
		}

		if ( !Q_stricmp( token, saberName ) ) 
		{
			break;
		}

		SkipBracedSection( &p );
	}
	if ( !p ) 
	{
		return qfalse;
	}

	if ( UI_ParseLiteral( &p, "{" ) ) 
	{
		return qfalse;
	}
		
	// parse the saber info block
	while ( 1 ) 
	{
		token = COM_ParseExt( &p, qtrue );
		if ( !token[0] ) 
		{
			ui.Printf( S_COLOR_RED"ERROR: unexpected EOF while parsing '%s'\n", saberName );
			return qfalse;
		}

		if ( !Q_stricmp( token, "}" ) ) 
		{
			break;
		}

		if ( !Q_stricmp( token, parmname ) ) 
		{
			if ( COM_ParseString( &p, &value ) ) 
			{
				continue;
			}
			strcpy( saberData, value );
			return qtrue;
		}

		SkipRestOfLine( &p );
		continue;
	}

	return qfalse;
}
示例#21
0
static void UI_ManageDeckLoading( void )
{
	char			fileRoute[MAX_QPATH];
	char			mapRoute[MAX_QPATH];
	char			info[MAX_TOKEN_CHARS];
	fileHandle_t	f;
	int				file_len;
	char			*textPtr;
	char			buffer[20000];
	char			*token;

	//get the map name
	trap_GetConfigString( CS_SERVERINFO, info, sizeof( info ) );
	Com_sprintf( mapRoute, sizeof( fileRoute ), "maps/%s", Info_ValueForKey( info, "mapname" ) );

	//check for language
	UI_LanguageFilename( mapRoute, "turbolift", fileRoute );

	file_len = trap_FS_FOpenFile( fileRoute, &f, FS_READ );

	if ( file_len <= 1 )
	{
		//Com_Printf( S_COLOR_YELLOW "WARNING: Attempted to load %s, but wasn't found.\n", fileRoute );
		UI_TurboliftMenu_LoadDecks();
		return;
	}

	trap_FS_Read( buffer, file_len, f );
	trap_FS_FCloseFile( f );

	if ( !buffer[0] )
	{
		Com_Printf( S_COLOR_RED "ERROR: Attempted to load %s, but no data was read.\n", fileRoute );
		UI_TurboliftMenu_LoadDecks();
		return;
	}

	s_turbolift.numDecks = 0;
	memset( &s_turbolift.deckData, 0, sizeof( s_turbolift.deckData ) );
	buffer[file_len] = '\0';

	COM_BeginParseSession();
	textPtr = buffer;

	//Com_Printf( S_COLOR_RED "Beginning Parse\n" );

	//expected format is 'decknum' <space> 'deck Desc'
	while( 1 )
	{
		token = COM_Parse( &textPtr );
		if ( !token[0] )
			break;

		//Com_Printf( S_COLOR_RED "First Token: %s\n", token );

		//in case of Scooter's EF SP style DAT files, which require 'DECK' in front of the number
		if ( !Q_strncmp( token, "DECK", 4 ) )
			token += 4;

		//grab the deck number
		s_turbolift.deckData[s_turbolift.numDecks].deckNum = atoi( token );

		token = COM_ParseExt( &textPtr, qfalse );
		if (!token[0])
			continue;

		//Com_Printf( S_COLOR_RED "Second Token: %s\n", token );

		Q_strncpyz( s_turbolift.deckData[s_turbolift.numDecks].deckDesc, 
					token,
					sizeof( s_turbolift.deckData[s_turbolift.numDecks].deckDesc ) );

		s_turbolift.numDecks++;

		//if this is an EF SP style script, there may be more data after these two. ignore them
		if ( COM_ParseExt( &textPtr, qfalse ) == NULL )
			SkipRestOfLine( &textPtr );
	}

	qsort( s_turbolift.deckData, s_turbolift.numDecks, sizeof( deckData_t ), SortDecks );
}
示例#22
0
/*
=================
CM_ParseShader

The current text pointer is at the explicit text definition of the
shader.  Parse it into the global shader variable.

This extracts all the info from the shader required for physics and collision
It is designed to *NOT* load any image files and not require any of the renderer to 
be initialised.
=================
*/
static void CM_ParseShader( CCMShader *shader, const char **text )
{
	char	*token;

	token = COM_ParseExt( text, qtrue );
	if ( token[0] != '{' )
	{
		Com_Printf( S_COLOR_YELLOW "WARNING: expecting '{', found '%s' instead in shader '%s'\n", token, shader->shader );
		return;
	}

	while ( true )
	{
		token = COM_ParseExt( text, qtrue );
		if ( !token[0] )
		{
			Com_Printf( S_COLOR_YELLOW "WARNING: no concluding '}' in shader %s\n", shader->shader );
			return;
		}

		// end of shader definition
		if ( token[0] == '}' )
		{
			break;
		}
		// stage definition
		else if ( token[0] == '{' )
		{
			SkipBracedSection( text );
			continue;
		}
		// material deprecated as of 11 Jan 01
		// material undeprecated as of 7 May 01 - q3map_material deprecated
		else if ( !Q_stricmp( token, "material" ) || !Q_stricmp( token, "q3map_material" ) )
		{
			SV_ParseMaterial( shader, text );
		}
		// sun parms
		// q3map_sun deprecated as of 11 Jan 01
		else if ( !Q_stricmp( token, "sun" ) || !Q_stricmp( token, "q3map_sun" ) ) 
		{
			float	a, b;

			token = COM_ParseExt( text, qfalse );
			shader->sunLight[0] = atof( token );
			token = COM_ParseExt( text, qfalse );
			shader->sunLight[1] = atof( token );
			token = COM_ParseExt( text, qfalse );
			shader->sunLight[2] = atof( token );
			
			VectorNormalize( shader->sunLight );

			token = COM_ParseExt( text, qfalse );
			a = atof( token );
			VectorScale( shader->sunLight, a, shader->sunLight);

			token = COM_ParseExt( text, qfalse );
			a = DEG2RAD(atof( token ));

			token = COM_ParseExt( text, qfalse );
			b = DEG2RAD(atof( token ));

			shader->sunDirection[0] = cos( a ) * cos( b );
			shader->sunDirection[1] = sin( a ) * cos( b );
			shader->sunDirection[2] = sin( b );
		}
		else if ( !Q_stricmp( token, "surfaceParm" ) ) 
		{
			SV_ParseSurfaceParm( shader, text );
			continue;
		}
		else if ( !Q_stricmp( token, "fogParms" ) ) 
		{
			if ( !CM_ParseVector( shader, text, 3, shader->fogColor ) ) 
			{
				return;
			}

			token = COM_ParseExt( text, qfalse );
			if ( !token[0] ) 
			{
				Com_Printf( S_COLOR_YELLOW "WARNING: missing parm for 'fogParms' keyword in shader '%s'\n", shader->shader );
				continue;
			}
			shader->depthForOpaque = atof( token );

			// skip any old gradient directions
			SkipRestOfLine( (const char **)text );
			continue;
		}
		else if ( !Q_stricmp( token, "damageShader" ) ) 
		{
			CCMShader	*damageShader;

			token = COM_ParseExt( text, qfalse );
			if ( !token[0] ) 
			{
				Com_Printf( S_COLOR_YELLOW "WARNING: missing parm for 'damageShader' keyword in shader '%s'\n", shader->shader );
				continue;
			}
			damageShader = CM_GetShaderInfo(token);
			if(damageShader)
			{
				shader->damageShaderNum = damageShader - cm.shaders;
			}

			token = COM_ParseExt( text, qfalse );
			if(token)
			{
				shader->damage = atof(token);
			}
			continue;
		}
		// 
		// location hit mesh load
		//
		else if ( !Q_stricmp( token, "hitLocation" ) )
		{
			// grab the filename of the hit location texture
			token = COM_ParseExt( text, qfalse );
			if ( !token[0] )
			{
				break;
			}
			Q_strncpyz(shader->hitLocation, token, MAX_QPATH);
			continue;
		}
		// 
		// location hit material mesh load
		//
		else if ( !Q_stricmp( token, "hitMaterial" ) )
		{
			// grab the filename of the hit location texture
			token = COM_ParseExt( text, qfalse );
			if ( !token[0] )
			{
				break;
			}
			Q_strncpyz(shader->hitMaterial, token, MAX_QPATH);
			continue;
		}
	}
	return;
}
示例#23
0
文件: g_script.c 项目: ETrun/ETrun
/*
==============
G_Script_ScriptParse

  Parses the script for the given entity
==============
*/
void G_Script_ScriptParse(gentity_t *ent) {
	char                    *pScript;
	qboolean                wantName;
	qboolean                inScript;
	int                     eventNum;
	g_script_event_t        events[G_MAX_SCRIPT_STACK_ITEMS];
	int                     numEventItems;
	g_script_event_t        *curEvent;
	char                    params[MAX_INFO_STRING];
	g_script_stack_action_t *action;
	int                     i;
	int                     bracketLevel;
	qboolean                buildScript;

	if (!ent->scriptName) {
		return;
	}
	if (!level.scriptEntity) {
		return;
	}

	buildScript = trap_Cvar_VariableIntegerValue("com_buildScript");

	pScript  = level.scriptEntity;
	wantName = qtrue;
	inScript = qfalse;
	COM_BeginParseSession("G_Script_ScriptParse");
	bracketLevel  = 0;
	numEventItems = 0;

	memset(events, 0, sizeof (events));

	for (;;) {
		char *token;

		token = COM_Parse(&pScript);

		if (!token[0]) {
			if (!wantName) {
				G_Error("G_Script_ScriptParse(), Error (line %d): '}' expected, end of script found.\n", COM_GetCurrentParseLine());
			}
			break;
		}

		// end of script
		if (token[0] == '}') {
			if (inScript) {
				break;
			}
			if (wantName) {
				G_Error("G_Script_ScriptParse(), Error (line %d): '}' found, but not expected.\n", COM_GetCurrentParseLine());
			}
			wantName = qtrue;
		} else if (token[0] == '{') {
			if (wantName) {
				G_Error("G_Script_ScriptParse(), Error (line %d): '{' found, NAME expected.\n", COM_GetCurrentParseLine());
			}
		} else if (wantName) {
			if (!Q_stricmp(token, "bot")) {
				// a bot, skip this whole entry
				SkipRestOfLine(&pScript);
				// skip this section
				SkipBracedSection(&pScript);
				//
				continue;
			}
			if (!Q_stricmp(token, "entity")) {
				// this is an entity, so go back to look for a name
				continue;
			}
			if (!Q_stricmp(ent->scriptName, token)) {
				inScript      = qtrue;
				numEventItems = 0;
			}
			wantName = qfalse;
		} else if (inScript) {
			Q_strlwr(token);
			eventNum = G_Script_EventForString(token);
			if (eventNum < 0) {
				G_Error("G_Script_ScriptParse(), Error (line %d): unknown event: %s.\n", COM_GetCurrentParseLine(), token);
			}

			if (numEventItems >= G_MAX_SCRIPT_STACK_ITEMS) {
				G_Error("G_Script_ScriptParse(), Error (line %d): G_MAX_SCRIPT_STACK_ITEMS reached (%d)\n", COM_GetCurrentParseLine(), G_MAX_SCRIPT_STACK_ITEMS);
			}

			curEvent           = &events[numEventItems];
			curEvent->eventNum = eventNum;
			memset(params, 0, sizeof (params));

			// parse any event params before the start of this event's actions
			while ((token = COM_Parse(&pScript)) != NULL && (token[0] != '{')) {
				if (!token[0]) {
					G_Error("G_Script_ScriptParse(), Error (line %d): '}' expected, end of script found.\n", COM_GetCurrentParseLine());
				}

				if (strlen(params)) {      // add a space between each param
					Q_strcat(params, sizeof (params), " ");
				}
				Q_strcat(params, sizeof (params), token);
			}

			if (strlen(params)) {        // copy the params into the event
				curEvent->params = G_Alloc(strlen(params) + 1);
				Q_strncpyz(curEvent->params, params, strlen(params) + 1);
			}

			// parse the actions for this event
			while ((token = COM_Parse(&pScript)) != NULL && (token[0] != '}')) {
				if (!token[0]) {
					G_Error("G_Script_ScriptParse(), Error (line %d): '}' expected, end of script found.\n", COM_GetCurrentParseLine());
				}

				action = G_Script_ActionForString(token);
				if (!action) {
					G_Error("G_Script_ScriptParse(), Error (line %d): unknown action: %s.\n", COM_GetCurrentParseLine(), token);
				}

				curEvent->stack.items[curEvent->stack.numItems].action = action;

				memset(params, 0, sizeof (params));

				// Ikkyo - Parse for {}'s if this is a set command
				// Nico, added "create" & "delete" condition
				if (!Q_stricmp(action->actionString, "set") ||
				    !Q_stricmp(action->actionString, "create") ||
				    !Q_stricmp(action->actionString, "delete")) {
					token = COM_Parse(&pScript);
					if (token[0] != '{') {
						COM_ParseError("'{' expected, found: %s.\n", token);
					}

					while ((token = COM_Parse(&pScript)) != NULL && (token[0] != '}')) {
						if (strlen(params)) {     // add a space between each param
							Q_strcat(params, sizeof (params), " ");
						}

						if (strrchr(token, ' ')) {    // need to wrap this param in quotes since it has more than one word
							Q_strcat(params, sizeof (params), "\"");
						}

						Q_strcat(params, sizeof (params), token);

						if (strrchr(token, ' ')) {    // need to wrap this param in quotes since it has mor
							Q_strcat(params, sizeof (params), "\"");
						}
					}
				} else
				// hackly precaching of custom characters
				if (!Q_stricmp(token, "spawnbot")) {
					// this is fairly indepth, so I'll move it to a separate function for readability
					G_Script_ParseSpawnbot(&pScript, params, MAX_INFO_STRING);
				} else {
					token = COM_ParseExt(&pScript, qfalse);
					for (i = 0; token[0]; ++i) {
						if (strlen(params)) {     // add a space between each param
							Q_strcat(params, sizeof (params), " ");
						}

						if (i == 0) {
							// Special case: playsound's need to be cached on startup to prevent in-game pauses
							if (!Q_stricmp(action->actionString, "playsound")) {
								G_SoundIndex(token);
							} else if (!Q_stricmp(action->actionString, "changemodel")) {
								G_ModelIndex(token);
							} else if (buildScript &&
							           (!Q_stricmp(action->actionString, "mu_start") ||
							            !Q_stricmp(action->actionString, "mu_play") ||
							            !Q_stricmp(action->actionString, "mu_queue") ||
							            !Q_stricmp(action->actionString, "startcam")) &&
							           strlen(token)) {
								trap_SendServerCommand(-1, va("addToBuild %s\n", token));
							}
						}

						if ((i == 0 || i == 1) && !Q_stricmp(action->actionString, "remapshader")) {
							G_ShaderIndex(token);
						}

						if (strrchr(token, ' ')) {    // need to wrap this param in quotes since it has more than one word
							Q_strcat(params, sizeof (params), "\"");
						}

						Q_strcat(params, sizeof (params), token);

						if (strrchr(token, ' ')) {    // need to wrap this param in quotes since it has more than one word
							Q_strcat(params, sizeof (params), "\"");
						}

						token = COM_ParseExt(&pScript, qfalse);
					}
				}

				if (strlen(params)) {     // copy the params into the event
					curEvent->stack.items[curEvent->stack.numItems].params = G_Alloc(strlen(params) + 1);
					Q_strncpyz(curEvent->stack.items[curEvent->stack.numItems].params, params, strlen(params) + 1);
				}

				curEvent->stack.numItems++;

				if (curEvent->stack.numItems >= G_MAX_SCRIPT_STACK_ITEMS) {
					G_Error("G_Script_ScriptParse(): script exceeded G_MAX_SCRIPT_STACK_ITEMS (%d), line %d\n", G_MAX_SCRIPT_STACK_ITEMS, COM_GetCurrentParseLine());
				}
			}

			numEventItems++;
		} else {   // skip this character completely
			// TTimo gcc: suggest parentheses around assignment used as truth value
			while ((token = COM_Parse(&pScript)) != NULL) {
				if (!token[0]) {
					G_Error("G_Script_ScriptParse(), Error (line %d): '}' expected, end of script found.\n", COM_GetCurrentParseLine());
				} else if (token[0] == '{') {
					bracketLevel++;
				} else if (token[0] == '}' && !--bracketLevel) {
					break;
				}
			}
		}
	}

	// alloc and copy the events into the gentity_t for this cast
	if (numEventItems > 0) {
		ent->scriptEvents = G_Alloc(sizeof (g_script_event_t) * numEventItems);
		memcpy(ent->scriptEvents, events, sizeof (g_script_event_t) * numEventItems);
		ent->numScriptEvents = numEventItems;
	}
}
示例#24
0
qboolean BG_ParseRankNames( char* fileName, rankNames_t rankNames[] ) {
	fileHandle_t	f;
	int				file_len;
	char			charText[20000];
	char*			textPtr;
	char*			token;
	int				i = 0;

	file_len = trap_FS_FOpenFile( fileName, &f, FS_READ );

	if ( file_len<= 0 ) {
		return qfalse;
	}

	if ( file_len >= ( sizeof(charText) - 1) ) {
		Com_Printf( S_COLOR_RED "File length of %s is too long.\n", fileName );
	}

	memset( &charText, 0, sizeof( charText ) );
	memset( rankNames, 0, sizeof( rankNames ) );

	trap_FS_Read( charText, file_len, f );

	charText[file_len] = 0;

	trap_FS_FCloseFile( f );

	COM_BeginParseSession();

	textPtr = charText;

	token = COM_Parse( &textPtr );

	if ( !token[0] ) {
		Com_Printf( S_COLOR_RED "No data found in buffer: %s\n", fileName );
		return qfalse;
	}

	if ( Q_stricmpn( token, "{", 1 ) ) {
		Com_Printf( S_COLOR_RED "No beginning { found in %s\n", fileName );
		return qfalse;
	}

	//Parse out the default cell.  Default has no names anyway,
	//but in case a n00bie modder put names in anyway.
	SkipBracedSection( &textPtr );

	while( 1 ) {
		//lastPtr = textPtr;
		token = COM_Parse( &textPtr );
		if( !token[0] ) {
			break;
		}

		if ( i >= MAX_RANKS ) {
			break;
		}

		//If we hit an open brace (ie, assuming we hit the start of a new rank cell)
		if ( !Q_stricmpn( token, "{", 1 ) ) {
			while ( 1 ) {
				token = COM_Parse( &textPtr );
				if( !token[0] ) {
					break;
				}

				//We hit a MenuTexture entry, since this uses { symbols, we'll skip these to stop errors.
				if ( !Q_stricmpn( token, "MenuTexture", 11 ) ) {
					SkipRestOfLine( &textPtr );
					continue;
				}

				if ( !Q_stricmpn( token, "ConsoleName", 11) ) {
					if ( COM_ParseString( &textPtr, &token ) ) {
						continue;
					}

					Q_strncpyz( rankNames[i].consoleName, token, sizeof( rankNames[i].consoleName ) );

					continue;
				}
				else if ( !Q_stricmpn( token, "FormalName", 10) ) {
					if ( COM_ParseString( &textPtr, &token ) ) {
						continue;
					}

					Q_strncpyz( rankNames[i].formalName, token, sizeof( rankNames[i].formalName ) );

					continue;
				}
				//We hit the end of the cell.
				else if ( !Q_stricmpn( token, "}", 1 ) ) {
					break;
				}
			}

			//Error check.  If we didn't get both a formal and console name, pwn the caller. ;P
			if ( !rankNames[i].consoleName[0] || !rankNames[i].formalName[0] ) {
				Com_Printf( S_COLOR_RED "One or more rank names were not found in rank#: %i\n", i );
				return qfalse;
			}
			else {
				i++;
			}
		}
	}
	return qtrue;
}
示例#25
0
/*
================
Lexer::ReadToken
================
*/
const Token *Lexer::ReadToken( void ) {
	if ( tokPos == -1 )
		tokPos = 0;
	else if ( tokIsUnread ) {
		tokIsUnread = false;
		return &token;
	}
	while ( bufPos < bufSize ) {
		// Single line comments
		if ( !lineComment.IsEmpty() &&
			String::CmpPrefix((const char *)(buffer+bufPos), lineComment.c_str()) == 0 ) {
			if ( !(flags & LEXER_FULL_LINES) && tokPos > 0 ) {
				FinishToken();
				return &token;
			}
			bufPos += 2;
			if ( tokPos > 0 ) {
				SkipRestOfLine();
				return &token;
			}
			SkipRestOfLine();

			continue;
		}
		// Multiline comments
		else if ( !blockComment[0].IsEmpty() &&
			String::CmpPrefix((const char *)(buffer+bufPos), blockComment[0].c_str()) == 0 ) {
				if ( !(flags & LEXER_FULL_LINES) && tokPos > 0 ) {
					FinishToken();
					return &token;
				}
				bufPos += 2;
				int l = line;
				SkipToCommentEnd(); 
				// If changed line during comment, finish the line.
				if ( (flags & LEXER_FULL_LINES) && l != line && tokPos > 0 ) {
					FinishToken();
					return &token;
				}
				continue;
		}

		switch( buffer[bufPos] ) {
			// Ignore whitespaces
			case ' ':
			case '\t':
				SkipWhiteSpaces();
				if ( flags & LEXER_FULL_LINES )
					AddToToken( ' ' );
				else if ( tokPos > 0 ) {
					FinishToken();
					return &token;
				}
				continue;

			// Newlines
			case '\n':
			case '\r':
				if ( !tokPos ) {
					FinishLine();
					continue;
				}
				FinishLine();
				return &token;

			// Quoted tokens
			case '\"':
			case '\'':
				if ( flags & LEXER_FULL_LINES ) {
					ParseQuoted();
					continue;
				}
				if ( tokPos > 0 ) {
					FinishToken();
					return &token;
				}
				ParseQuoted();
				return &token;

			default:
				// Check for single char tokens
				if ( (flags & LEXER_FULL_LINES) == 0 && !singleTokenChars.IsEmpty() ) {
					char c = buffer[bufPos];
					const char *chars = singleTokenChars.c_str();
					int num = singleTokenChars.Length();
					for( int i=0; i<num; i++ ) {
						if ( c != chars[i] )
							continue;
						if ( tokPos == 0 ) {
							AddToToken( buffer[bufPos] );
							bufPos++;
						}
						FinishToken();
						return &token;
					}
				}
				// Add this char to the token
				AddToToken( buffer[bufPos] );
				bufPos++;
				continue;
		}
	}
	if ( tokPos > 0 ) {
		FinishToken();
		return &token;
	}
	line = 0;

	return NULL;
}
示例#26
0
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];
	clientInfo_t	*ci = &NPC->client->clientInfo;
	renderInfo_t	*ri = &NPC->client->renderInfo;
	gNPCstats_t		*stats = NULL;
	qboolean	md3Model = qtrue;
	char	surfOff[1024];
	char	surfOn[1024];

	strcpy(customSkin,"default");
	if ( !NPCName || !NPCName[0]) 
	{
		NPCName = "Player";
	}

	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->moveType		= MT_RUNJUMP;
		stats->yawSpeed		= 90;
		stats->walkSpeed	= 90;
		stats->runSpeed		= 300;
		stats->acceleration	= 15;//Increase/descrease speed this much per frame (20fps)
	}
	else
	{
		stats = NULL;
	}

	Q_strncpyz( ci->name, NPCName, sizeof( ci->name ) );
	
	NPC->playerModel = -1;
	
	//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);
	memset( ri->headModelName, 0, sizeof( ri->headModelName ) );
	memset( ri->torsoModelName, 0, sizeof( ri->torsoModelName ) );
	memset( ri->legsModelName, 0, sizeof( ri->legsModelName ) );
	//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->mins);
	VectorCopy(playerMaxs, NPC->maxs);
	NPC->client->crouchheight = CROUCH_MAXS_2;
	NPC->client->standheight = DEFAULT_MAXS_2;

	NPC->client->dismemberProbHead = 100;
	NPC->client->dismemberProbArms = 100;
	NPC->client->dismemberProbHands = 100;
	NPC->client->dismemberProbWaist = 100;
	NPC->client->dismemberProbLegs = 100;
	

	if ( !Q_stricmp( "random", NPCName ) )
	{//Randomly assemble a starfleet guy
		NPC_BuildRandom( NPC );
	}
	else
	{
		p = NPCParms;
		COM_BeginParseSession();

		// 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 ( G_ParseLiteral( &p, "{" ) ) 
		{
			return qfalse;
		}
			
		// parse the NPC info block
		while ( 1 ) 
		{
			token = COM_ParseExt( &p, qtrue );
			if ( !token[0] ) 
			{
				gi.Printf( S_COLOR_RED"ERROR: unexpected EOF while parsing '%s'\n", NPCName );
				return qfalse;
			}

			if ( !Q_stricmp( token, "}" ) ) 
			{
				break;
			}
	//===MODEL PROPERTIES===========================================================
			// headmodel
			if ( !Q_stricmp( token, "headmodel" ) ) 
			{
				if ( COM_ParseString( &p, &value ) ) 
				{
					continue;
				}

				if(!Q_stricmp("none", value))
				{
					ri->headModelName[0] = NULL;
					//Zero the head clamp range so the torso & legs don't lag behind
					ri->headYawRangeLeft = 
					ri->headYawRangeRight = 
					ri->headPitchRangeUp = 
					ri->headPitchRangeDown = 0;
				}
				else
				{
					Q_strncpyz( ri->headModelName, value, sizeof(ri->headModelName), qtrue);
				}
				continue;
			}
			
			// torsomodel
			if ( !Q_stricmp( token, "torsomodel" ) ) 
			{
				if ( COM_ParseString( &p, &value ) ) 
				{
					continue;
				}

				if(!Q_stricmp("none", value))
				{
					ri->torsoModelName[0] = NULL;
					//Zero the torso clamp range so the legs don't lag behind
					ri->torsoYawRangeLeft = 
					ri->torsoYawRangeRight = 
					ri->torsoPitchRangeUp = 
					ri->torsoPitchRangeDown = 0;
				}
				else
				{
					Q_strncpyz( ri->torsoModelName, value, sizeof(ri->torsoModelName), qtrue);
				}
				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), qtrue);			
				md3Model = qfalse;
				continue;
			}
			
			// customSkin
			if ( !Q_stricmp( token, "customSkin" ) ) 
			{
				if ( COM_ParseString( &p, &value ) ) 
				{
					continue;
				}
				Q_strncpyz( customSkin, value, sizeof(customSkin), qtrue);			
				continue;
			}

			// surfOff
			if ( !Q_stricmp( token, "surfOff" ) ) 
			{
				if ( COM_ParseString( &p, &value ) ) 
				{
					continue;
				}
				if ( surfOff[0] )
				{
					strncat( (char *)surfOff, ",", sizeof(surfOff) );
					strncat( (char *)surfOff, value, sizeof(surfOff) );
				}
				else
				{
					Q_strncpyz( surfOff, value, sizeof(surfOff), qtrue);
				}
				continue;
			}
			
			// surfOn
			if ( !Q_stricmp( token, "surfOn" ) ) 
			{
				if ( COM_ParseString( &p, &value ) ) 
				{
					continue;
				}
				if ( surfOn[0] )
				{
					strncat( (char *)surfOn, ",", sizeof(surfOn) );
					strncat( (char *)surfOn, value, sizeof(surfOn) );
				}
				else
				{
					Q_strncpyz( surfOn, value, sizeof(surfOn), qtrue);
				}
				continue;
			}
			
			//headYawRangeLeft
			if ( !Q_stricmp( token, "headYawRangeLeft" ) ) 
			{
				if ( COM_ParseInt( &p, &n ) ) 
				{
					SkipRestOfLine( &p );
					continue;
				}
				if ( n < 0 ) 
				{
					gi.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 ) 
				{
					gi.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 ) 
				{
					gi.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 ) 
				{
					gi.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 ) 
				{
					gi.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 ) 
				{
					gi.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 ) 
				{
					gi.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 ) 
				{
					gi.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 ) 
				{
					gi.Printf(  "bad %s in NPC '%s'\n", token, NPCName );
					continue;
				}
				if (n != 100)
				{
					NPC->s.modelScale[0] = NPC->s.modelScale[1] = NPC->s.modelScale[2] = n/100.0f;
				}
				continue;
			}

			//X scale
			if ( !Q_stricmp( token, "scaleX" ) ) 
			{
				if ( COM_ParseInt( &p, &n ) ) 
				{
					SkipRestOfLine( &p );
					continue;
				}
				if ( n < 0 ) 
				{
					gi.Printf(  "bad %s in NPC '%s'\n", token, NPCName );
					continue;
				}
				if (n != 100)
				{
					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 ) 
				{
					gi.Printf(  "bad %s in NPC '%s'\n", token, NPCName );
					continue;
				}
				if (n != 100)
				{
					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 ) 
				{
					gi.Printf(  "bad %s in NPC '%s'\n", token, NPCName );
					continue;
				}
				if (n != 100)
				{
					NPC->s.modelScale[2] = n/100.0f;
				}
				continue;
			}

	//===AI STATS=====================================================================
			// aggression
			if ( !Q_stricmp( token, "aggression" ) ) {
				if ( COM_ParseInt( &p, &n ) ) {
					SkipRestOfLine( &p );
					continue;
				}
				if ( n < 1 || n > 5 ) {
					gi.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 ) {
					gi.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 ) 
				{
					gi.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 ) 
				{
					gi.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 ) {
					gi.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 ) {
					gi.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 ) {
					gi.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 ) {
					gi.Printf( "bad %s in NPC '%s'\n", token, NPCName );
					continue;
				}
				if ( NPC->NPC )
				{
					stats->reactions = n;
				}
				continue;
			}

			// shootDistance
			if ( !Q_stricmp( token, "saberColor" ) ) {
				if ( COM_ParseString( &p, &value ) ) 
				{
					continue;
				}
				if ( NPC->client )
				{
					NPC->client->ps.saberColor = TranslateSaberColor( value );
				}
				continue;
			}

			// shootDistance
			if ( !Q_stricmp( token, "shootDistance" ) ) {
				if ( COM_ParseFloat( &p, &f ) ) {
					SkipRestOfLine( &p );
					continue;
				}
				if ( f < 0.0f ) 
				{
					gi.Printf( "bad %s in NPC '%s'\n", token, NPCName );
					continue;
				}
				if ( NPC->NPC )
				{
					stats->shootDistance = f;
				}
				continue;
			}

			// shootDistance
			if ( !Q_stricmp( token, "health" ) ) 
			{
				if ( COM_ParseInt( &p, &n ) ) 
				{
					SkipRestOfLine( &p );
					continue;
				}
				if ( n < 0 ) 
				{
					gi.Printf( S_COLOR_YELLOW"WARNING: bad %s in NPC '%s'\n", token, NPCName );
					continue;
				}
				if ( NPC->NPC )
				{
					stats->health = n;
				}
				continue;
			}

			// vfov
			if ( !Q_stricmp( token, "vfov" ) ) {
				if ( COM_ParseInt( &p, &n ) ) {
					SkipRestOfLine( &p );
					continue;
				}
				if ( n < 30 || n > 180 ) {
					gi.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 ) 
				{
					gi.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 ) 
				{
					gi.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;
			}

			// fullName
			if ( !Q_stricmp( token, "fullName" ) ) 
			{
				if ( COM_ParseString( &p, &value ) ) 
				{
					continue;
				}
				NPC->fullName = G_NewString(value);
				continue;
			}

			// playerTeam
			if ( !Q_stricmp( token, "playerTeam" ) ) 
			{
				if ( COM_ParseString( &p, &value ) ) 
				{
					continue;
				}
				NPC->client->playerTeam = TranslateTeamName(value);
				continue;
			}

			// enemyTeam
			if ( !Q_stricmp( token, "enemyTeam" ) ) 
			{
				if ( COM_ParseString( &p, &value ) ) 
				{
					continue;
				}
				NPC->client->enemyTeam = TranslateTeamName(value);
				continue;
			}

			// class
			if ( !Q_stricmp( token, "class" ) ) 
			{
				if ( COM_ParseString( &p, &value ) ) 
				{
					continue;
				}
				NPC->client->NPC_class = TranslateClassName(value);
				continue;
			}

			// dismemberment probability for head
			if ( !Q_stricmp( token, "dismemberProbHead" ) ) {
				if ( COM_ParseInt( &p, &n ) ) {
					SkipRestOfLine( &p );
					continue;
				}
				if ( n < 0 ) 
				{
					gi.Printf( "bad %s in NPC '%s'\n", token, NPCName );
					continue;
				}
				if ( NPC->NPC )
				{
					NPC->client->dismemberProbHead = n;
				}
				continue;
			}

			// dismemberment probability for arms
			if ( !Q_stricmp( token, "dismemberProbArms" ) ) {
				if ( COM_ParseInt( &p, &n ) ) {
					SkipRestOfLine( &p );
					continue;
				}
				if ( n < 0 ) 
				{
					gi.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 ) 
				{
					gi.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 ) 
				{
					gi.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 ) 
				{
					gi.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->mins[0] = NPC->mins[1] = -n;
				NPC->maxs[0] = NPC->maxs[1] = n;
				continue;
			}

			if ( !Q_stricmp( token, "height" ) ) 
			{
				if ( COM_ParseInt( &p, &n ) ) 
				{
					continue;
				}

				NPC->mins[2] = DEFAULT_MINS_2;//Cannot change
				NPC->maxs[2] = NPC->client->standheight = n + DEFAULT_MINS_2;
				NPC->radius = n;
				continue;
			}

			if ( !Q_stricmp( token, "crouchheight" ) ) 
			{
				if ( COM_ParseInt( &p, &n ) ) 
				{
					continue;
				}

				NPC->client->crouchheight = n + DEFAULT_MINS_2;
				continue;
			}

			if ( !Q_stricmp( token, "movetype" ) ) 
			{
				if ( COM_ParseString( &p, &value ) ) 
				{
					continue;
				}

				if ( NPC->NPC )
				{
					stats->moveType = (movetype_t)MoveTypeNameToEnum(value);
				}
				continue;
			}
				
			// yawSpeed
			if ( !Q_stricmp( token, "yawSpeed" ) ) {
				if ( COM_ParseInt( &p, &n ) ) {
					SkipRestOfLine( &p );
					continue;
				}
				if ( n <= 0) {
					gi.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 ) 
				{
					gi.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 ) 
				{
					gi.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 ) 
				{
					gi.Printf( S_COLOR_YELLOW"WARNING: bad %s in NPC '%s'\n", token, NPCName );
					continue;
				}
				if ( NPC->NPC )
				{
					stats->acceleration = n;
				}
				continue;
			}
	//===MISC===============================================================================
			// default behavior
			if ( !Q_stricmp( token, "behavior" ) ) 
			{
				if ( COM_ParseInt( &p, &n ) ) 
				{
					SkipRestOfLine( &p );
					continue;
				}
				if ( n < BS_DEFAULT || n >= NUM_BSTATES ) 
				{
					gi.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->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 );
				}
				continue;
			}

			// sndcombat
			if ( !Q_stricmp( token, "sndcombat" ) ) {
				if ( COM_ParseString( &p, &value ) ) {
					continue;
				}
				if ( !(NPC->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->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->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;
			}

			gi.Printf( "WARNING: unknown keyword '%s' while parsing '%s'\n", token, NPCName );
			SkipRestOfLine( &p );
		}
	}

	ci->infoValid = qfalse;

/*
Ghoul2 Insert Start
*/
	if ( !md3Model )
	{
		NPC->weaponModel = -1;
		G_SetG2PlayerModel( NPC, playerModel, customSkin, surfOff, surfOn );
	}
/*
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 );
	}

	return qtrue;
}
示例#27
0
/*
=================
CL_OpenJoystickRemap

joystickIdent could be a name or hash
=================
*/
qboolean CL_OpenJoystickRemap( int localPlayerNum, const char *joystickName, const char *joystickIdent ) {
	fileHandle_t	f;
	char		filename[MAX_QPATH];
	char		*buffer, *text, *token;
	int			len, i;
	joyevent_t	joyevent;
	int			key;

	if ( !joystickName ) {
		return qfalse;
	}

	if ( !joystickIdent ) {
		joystickIdent = joystickName;
	}

	// check if already loaded
	for ( i = 0; i < CL_MAX_SPLITVIEW; i++ ) {
		if ( !strcmp(joyDevice[i].ident, joystickIdent ) ) {
			break;
		}
	}

	if ( i != CL_MAX_SPLITVIEW ) {
		playerJoyRemapIndex[localPlayerNum] = i;
		joyDevice[i].references++;
		return qtrue;
	}

	// find free slot
	for ( i = 0; i < CL_MAX_SPLITVIEW; i++ ) {
		if ( !joyDevice[i].references ) {
			break;
		}
	}

	if ( i == CL_MAX_SPLITVIEW ) {
		Com_Printf("BUG: Tried to open joystick but no free slot\n");
		playerJoyRemapIndex[localPlayerNum] = -1;
		return qfalse;
	}

	playerJoyRemapIndex[localPlayerNum] = i;

	// initialize remap
	Com_Memset( &joyDevice[i], 0, sizeof ( joyDevice[0] ) );
	Q_strncpyz( joyDevice[i].ident, joystickIdent, sizeof ( joyDevice[i].ident ) );
	Q_strncpyz( joyDevice[i].name, joystickName, sizeof ( joyDevice[i].ident ) );
	joyDevice[i].references = 1;

	Com_sprintf( filename, sizeof ( filename ), "joy-%s-%s.txt", JOY_PLATFORM, joyDevice[i].ident );
	len = FS_SV_FOpenFileRead( filename, &f );
	if ( !f ) {
		return qfalse;
	}

	buffer = Hunk_AllocateTempMemory(len+1);

	FS_Read (buffer, len, f);

	// guarantee that it will have a trailing 0 for string operations
	buffer[len] = 0;
	FS_FCloseFile( f );

	text = buffer;

	while ( 1 ) {
		token = COM_Parse( &text );
		if ( !*token ) {
			break;
		}

		if ( !CL_StringToJoyEvent( token, &joyevent) )
		{
			SkipRestOfLine( &text );
			Com_Printf ("\"%s\" isn't a valid joystick event in %s\n", token, filename );
			continue;
		}

		token = COM_ParseExt( &text, qfalse );
		if ( !*token ) {
			Com_Printf("WARNING: Missing key for joy event in %s\n", filename );
			continue;
		}

		key = Key_StringToKeynum( token );
		if ( key == -1 )
		{
			Com_Printf( "\"%s\" isn't a valid key in %s\n", token, filename );
			continue;
		}

		if ( !CL_SetKeyForJoyEvent( localPlayerNum, &joyevent, key ) ) {
			Com_Printf ("Max joystick remaps reached (%d), cannot add remap for %s.\n", MAX_JOY_REMAPS, CL_JoyEventToString( &joyevent ) );
			break;
		}
	}

	Hunk_FreeTempMemory( buffer );

	return qtrue;
}
示例#28
0
//void UI_SaberGetHiltInfo( const char *singleHilts[MAX_SABER_HILTS], const char *staffHilts[MAX_SABER_HILTS] )
void UI_SaberGetHiltInfo(void){
	int	numSingleHilts = 0, numStaffHilts = 0;
	const char	*saberName;
	const char	*token;
	const char	*p;

	//go through all the loaded sabers and put the valid ones in the proper list
	p = SaberParms;
	COM_BeginParseSession("saberlist");

	// look for a saber
	while ( p )
	{
		token = COM_ParseExt( &p, qtrue );
		if ( token[0] == 0 )
		{//invalid name
			continue;
		}
		saberName = String_Alloc( token );
		//see if there's a "{" on the next line
		SkipRestOfLine( &p );

		if ( UI_ParseLiteralSilent( &p, "{" ) ) 
		{//nope, not a name, keep looking
			continue;
		}

		//this is a saber name
		if ( !UI_SaberValidForPlayerInMP( saberName ) )
		{
			SkipBracedSection( &p );
			continue;
		}

		if ( UI_IsSaberTwoHanded( saberName ) )
		{
#ifndef DYNAMICMEMORY_SABERS
			if ( numStaffHilts < MAX_SABER_HILTS-1 )//-1 because we have to NULL terminate the list
			{
				staffHilts[numStaffHilts++] = saberName;
			}
			else
			{
				Com_Printf( "WARNING: too many two-handed sabers, ignoring saber '%s'\n", saberName );
			}
#else
			UI_ReaAllocMem((void *)&saberStaffHiltInfo, sizeof(char *), numStaffHilts+1);
			saberStaffHiltInfo[numStaffHilts++] = (char *) saberName;
#endif
		}
		else
		{
#ifndef DYNAMICMEMORY_SABERS
			if ( numSingleHilts < MAX_SABER_HILTS-1 )//-1 because we have to NULL terminate the list
			{
				singleHilts[numSingleHilts++] = saberName;
			}
			else
			{
				Com_Printf( "WARNING: too many one-handed sabers, ignoring saber '%s'\n", saberName );
			}
#else
			UI_ReaAllocMem((void *)&saberSingleHiltInfo, sizeof(char *), numSingleHilts+1);
			saberSingleHiltInfo[numSingleHilts++] = (char *) saberName;
#endif
		}
		//skip the whole braced section and move on to the next entry
		SkipBracedSection( &p );
	}
	//null terminate the list so the UI code knows where to stop listing them
#ifndef DYNAMICMEMORY_SABERS
	singleHilts[numSingleHilts] = NULL;
	staffHilts[numStaffHilts] = NULL;
#else
	saberSingleHiltCount = numSingleHilts;
	saberStaffHiltCount = numStaffHilts;
#endif
}
示例#29
0
/*
==================
Sym_Init
==================
*/
void Sym_Init( long addr ) {
	TCHAR moduleName[MAX_STRING_CHARS];
	MEMORY_BASIC_INFORMATION mbi;

	VirtualQuery( (void*)addr, &mbi, sizeof(mbi) );

	GetModuleFileName( (HMODULE)mbi.AllocationBase, moduleName, sizeof( moduleName ) );

	char *ext = moduleName + strlen( moduleName );
	while( ext > moduleName && *ext != '.' ) {
		ext--;
	}
	if ( ext == moduleName ) {
		strcat( moduleName, ".map" );
	} else {
		strcpy( ext, ".map" );
	}

	module_t *module = (module_t *) malloc( sizeof( module_t ) );
	module->name = (char *) malloc( strlen( moduleName ) + 1 );
	strcpy( module->name, moduleName );
	module->address = (int)mbi.AllocationBase;
	module->symbols = NULL;
	module->next = modules;
	modules = module;

	FILE *fp = fopen( moduleName, "rb" );
	if ( fp == NULL ) {
		return;
	}

	int pos = ftell( fp );
	fseek( fp, 0, SEEK_END );
	int length = ftell( fp );
	fseek( fp, pos, SEEK_SET );

	char *text = (char *) malloc( length+1 );
	fread( text, 1, length, fp );
	text[length] = '\0';
	fclose( fp );

	const char *ptr = text;

	// skip up to " Address" on a new line
	while( *ptr != '\0' ) {
		SkipWhiteSpace( &ptr );
		if ( idStr::Cmpn( ptr, "Address", 7 ) == 0 ) {
			SkipRestOfLine( &ptr );
			break;
		}
		SkipRestOfLine( &ptr );
	}

	int symbolAddress;
	int symbolLength;
	char symbolName[MAX_STRING_CHARS];
	symbol_t *symbol;

	// parse symbols
	while( *ptr != '\0' ) {

		SkipWhiteSpace( &ptr );

		ParseHexNumber( &ptr );
		if ( *ptr == ':' ) {
			ptr++;
		} else {
			break;
		}
		ParseHexNumber( &ptr );

		SkipWhiteSpace( &ptr );

		// parse symbol name
		symbolLength = 0;
		while( *ptr != '\0' && *ptr != ' ' ) {
			symbolName[symbolLength++] = *ptr++;
			if ( symbolLength >= sizeof( symbolName ) - 1 ) {
				break;
			}
		}
		symbolName[symbolLength++] = '\0';

		SkipWhiteSpace( &ptr );

		// parse symbol address
		symbolAddress = ParseHexNumber( &ptr );

		SkipRestOfLine( &ptr );

		symbol = (symbol_t *) malloc( sizeof( symbol_t ) );
		symbol->name = (char *) malloc( symbolLength );
		strcpy( symbol->name, symbolName );
		symbol->address = symbolAddress;
		symbol->next = module->symbols;
		module->symbols = symbol;
	}

	free( text );
}
示例#30
0
/*
=================
CM_ParseShader

The current text pointer is at the explicit text definition of the
shader.  Parse it into the global shader variable.

This extracts all the info from the shader required for physics and collision
It is designed to *NOT* load any image files and not require any of the renderer to 
be initialised.
=================
*/
static void CM_ParseShader( CCMShader *shader, const char **text )
{
	char	*token;

	token = COM_ParseExt( text, qtrue );
	if ( token[0] != '{' )
	{
		Com_Printf( S_COLOR_YELLOW "WARNING: expecting '{', found '%s' instead in shader '%s'\n", token, shader->shader );
		return;
	}

	while ( true )
	{
		token = COM_ParseExt( text, qtrue );
		if ( !token[0] )
		{
			Com_Printf( S_COLOR_YELLOW "WARNING: no concluding '}' in shader %s\n", shader->shader );
			return;
		}

		// end of shader definition
		if ( token[0] == '}' )
		{
			break;
		}
		// stage definition
		else if ( token[0] == '{' )
		{
			SkipBracedSection( text );
			continue;
		}
		// material deprecated as of 11 Jan 01
		// material undeprecated as of 7 May 01 - q3map_material deprecated
		else if ( !Q_stricmp( token, "material" ) || !Q_stricmp( token, "q3map_material" ) )
		{
			SV_ParseMaterial( shader, text );
		}
		// sun parms
		// q3map_sun deprecated as of 11 Jan 01
		else if ( !Q_stricmp( token, "sun" ) || !Q_stricmp( token, "q3map_sun" ) ) 
		{
//			float	a, b;

			token = COM_ParseExt( text, qfalse );
//			shader->sunLight[0] = atof( token );
			token = COM_ParseExt( text, qfalse );
//			shader->sunLight[1] = atof( token );
			token = COM_ParseExt( text, qfalse );
//			shader->sunLight[2] = atof( token );
			
//			VectorNormalize( shader->sunLight );

			token = COM_ParseExt( text, qfalse );
//			a = atof( token );
//			VectorScale( shader->sunLight, a, shader->sunLight);

			token = COM_ParseExt( text, qfalse );
//			a = DEG2RAD(atof( token ));

			token = COM_ParseExt( text, qfalse );
//			b = DEG2RAD(atof( token ));

//			shader->sunDirection[0] = cos( a ) * cos( b );
//			shader->sunDirection[1] = sin( a ) * cos( b );
//			shader->sunDirection[2] = sin( b );
		}
		else if ( !Q_stricmp( token, "surfaceParm" ) ) 
		{
			SV_ParseSurfaceParm( shader, text );
			continue;
		}
		else if ( !Q_stricmp( token, "fogParms" ) ) 
		{
			vec3_t				fogColor;
			if ( !CM_ParseVector( shader, text, 3, fogColor ) ) 
			{
				return;
			}

			token = COM_ParseExt( text, qfalse );
			if ( !token[0] ) 
			{
				Com_Printf( S_COLOR_YELLOW "WARNING: missing parm for 'fogParms' keyword in shader '%s'\n", shader->shader );
				continue;
			}
//			shader->depthForOpaque = atof( token );

			// skip any old gradient directions
			SkipRestOfLine( (const char **)text );
			continue;
		}
	}
	return;
}