void G_LoadAnimFileSet( gentity_t *ent, const char *modelName ) { //load its animation config char animName[MAX_QPATH]; char *GLAName; char *slash = NULL; char *strippedName; if ( ent->playerModel == -1 ) { return; } //get the location of the animation.cfg GLAName = gi.G2API_GetGLAName( &ent->ghoul2[ent->playerModel] ); //now load and parse the animation.cfg, animsounds.cfg and set the animFileIndex if ( !GLAName) { Com_Printf( S_COLOR_RED"Failed find animation file name models/players/%s/animation.cfg\n", modelName ); strippedName="broken"; } else { Q_strncpyz( animName, GLAName, sizeof( animName ), qtrue ); slash = strrchr( animName, '/' ); if ( slash ) { *slash = 0; } strippedName = COM_SkipPath( animName ); } //now load and parse the animation.cfg, animsounds.cfg and set the animFileIndex if ( !G_ParseAnimFileSet( modelName, strippedName, &ent->client->clientInfo.animFileIndex ) ) { Com_Printf( S_COLOR_RED"Failed to load animation file set models/players/%s/animation.cfg\n", modelName ); } }
void SP_misc_model_ghoul( gentity_t *ent ) { #if 1 ent->s.modelindex = G_ModelIndex( ent->model ); gi.G2API_InitGhoul2Model(ent->ghoul2, ent->model, ent->s.modelindex); ent->s.radius = 50; #else char name1[200] = "models/players/kyle/model.glm"; ent->s.modelindex = G_ModelIndex( name1 ); gi.G2API_InitGhoul2Model(ent->ghoul2, name1, ent->s.modelindex); ent->s.radius = 150; // we found the model ok - load it's animation config temp_animFileIndex = G_ParseAnimFileSet("_humanoid", "kyle"); if ( temp_animFileIndex<0 ) { Com_Printf( S_COLOR_RED"Failed to load animation file set models/players/jedi/animation.cfg\n"); } ent->s.angles[0] = 0; ent->s.angles[1] = 90; ent->s.angles[2] = 0; ent->s.origin[2] = 20; ent->s.origin[1] = 80; // ent->s.modelScale[0] = ent->s.modelScale[1] = ent->s.modelScale[2] = 0.8f; VectorSet (ent->mins, -16, -16, -37); VectorSet (ent->maxs, 16, 16, 32); //#if _DEBUG //loadsavecrash // VectorCopy(ent->mins, ent->s.mins); // VectorCopy(ent->maxs, ent->s.maxs); //#endif ent->contents = CONTENTS_BODY; ent->clipmask = MASK_NPCSOLID; G_SetOrigin( ent, ent->s.origin ); VectorCopy( ent->s.angles, ent->s.apos.trBase ); ent->health = 1000; // ent->s.modelindex = G_ModelIndex( "models/weapons2/blaster_r/g2blaster_w.glm" ); // gi.G2API_InitGhoul2Model(ent->ghoul2, "models/weapons2/blaster_r/g2blaster_w.glm", ent->s.modelindex); // gi.G2API_AddBolt(&ent->ghoul2[0], "*weapon"); // gi.G2API_AttachG2Model(&ent->ghoul2[1],&ent->ghoul2[0], 0, 0); gi.linkentity (ent); animation_t *animations = level.knownAnimFileSets[temp_animFileIndex].animations; int anim = BOTH_STAND3; float animSpeed = 50.0f / animations[anim].frameLerp; gi.G2API_SetBoneAnim(&ent->ghoul2[0], "model_root", animations[anim].firstFrame, (animations[anim].numFrames -1 )+ animations[anim].firstFrame, BONE_ANIM_OVERRIDE_FREEZE , animSpeed, cg.time); // int test = gi.G2API_GetSurfaceRenderStatus(&ent->ghoul2[0], "l_hand"); // gi.G2API_SetSurfaceOnOff(&ent->ghoul2[0], "l_arm",0x00000100); // test = gi.G2API_GetSurfaceRenderStatus(&ent->ghoul2[0], "l_hand"); // gi.G2API_SetNewOrigin(&ent->ghoul2[0], gi.G2API_AddBolt(&ent->ghoul2[0], "rhang_tag_bone")); // ent->s.apos.trDelta[1] = 10; // ent->s.apos.trType = TR_LINEAR; ent->nextthink = level.time + 1000; ent->e_ThinkFunc = thinkF_set_MiscAnim; #endif }
void NPC_PrecacheAnimationCFG( const char *NPC_type ) { 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(); // 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 ( G_ParseLiteral( &p, "{" ) ) { return; } // 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", 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 ), qtrue ); 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; } } } } }
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; }
void NPC_PrecacheAnimationCFG( const char *NPC_type ) { char *token; char *value; char *p; int junk; if ( !Q_stricmp( "random", NPC_type ) ) {//sorry, can't precache a random just yet return; } p = NPCParms; COM_BeginParseSession(); // 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 ( G_ParseLiteral( &p, "{" ) ) { return; } // 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", NPC_type ); return; } if ( !Q_stricmp( token, "}" ) ) { break; } // legsmodel if ( !Q_stricmp( token, "legsmodel" ) ) { if ( G_ParseString( &p, &value ) ) { continue; } G_ParseAnimFileSet( value, &junk, qfalse ); return; } } }