/* ================== CG_SetInitialSnapshot This will only happen on the very first snapshot, or on tourney restarts. All other times will use CG_TransitionSnapshot instead. FIXME: Also called by map_restart? ================== */ void CG_SetInitialSnapshot( snapshot_t *snap ) { int i; centity_t *cent; entityState_t *state; cg.snap = snap; if ((cg_entities[snap->ps.clientNum].ghoul2 == NULL) && trap_G2_HaveWeGhoul2Models(cgs.clientinfo[snap->ps.clientNum].ghoul2Model)) { trap_G2API_DuplicateGhoul2Instance(cgs.clientinfo[snap->ps.clientNum].ghoul2Model, &cg_entities[snap->ps.clientNum].ghoul2); CG_CopyG2WeaponInstance(FIRST_WEAPON, cg_entities[snap->ps.clientNum].ghoul2); } BG_PlayerStateToEntityState( &snap->ps, &cg_entities[ snap->ps.clientNum ].currentState, qfalse ); // sort out solid entities CG_BuildSolidList(); CG_ExecuteNewServerCommands( snap->serverCommandSequence ); // set our local weapon selection pointer to // what the server has indicated the current weapon is CG_Respawn(); for ( i = 0 ; i < cg.snap->numEntities ; i++ ) { state = &cg.snap->entities[ i ]; cent = &cg_entities[ state->number ]; memcpy(¢->currentState, state, sizeof(entityState_t)); //cent->currentState = *state; cent->interpolate = qfalse; cent->currentValid = qtrue; if ( jk2startversion == VERSION_1_02 ) { // MVSDK: Version Magic! cent->currentState.torsoAnim = MV_MapAnimation104( cent->currentState.torsoAnim ); cent->currentState.legsAnim = MV_MapAnimation104( cent->currentState.legsAnim ); } CG_ResetEntity( cent ); // check for events CG_CheckEvents( cent ); } }
/* ================== CG_SetInitialSnapshot This will only happen on the very first snapshot, or on tourney restarts. All other times will use CG_TransitionSnapshot instead. FIXME: Also called by map_restart? ================== */ void CG_SetInitialSnapshot( snapshot_t *snap ) { int i; centity_t *cent; entityState_t *state; cg.snap = snap; if ((cg_entities[snap->ps.clientNum].ghoul2 == NULL) && trap_G2_HaveWeGhoul2Models(cgs.clientinfo[snap->ps.clientNum].ghoul2Model)) { trap_G2API_DuplicateGhoul2Instance(cgs.clientinfo[snap->ps.clientNum].ghoul2Model, &cg_entities[snap->ps.clientNum].ghoul2); CG_CopyG2WeaponInstance(&cg_entities[snap->ps.clientNum], FIRST_WEAPON, cg_entities[snap->ps.clientNum].ghoul2); if (trap_G2API_AddBolt(cg_entities[snap->ps.clientNum].ghoul2, 0, "face") == -1) { //check now to see if we have this bone for setting anims and such cg_entities[snap->ps.clientNum].noFace = qtrue; } } BG_PlayerStateToEntityState( &snap->ps, &cg_entities[ snap->ps.clientNum ].currentState, qfalse ); // sort out solid entities CG_BuildSolidList(); CG_ExecuteNewServerCommands( snap->serverCommandSequence ); // set our local weapon selection pointer to // what the server has indicated the current weapon is CG_Respawn(); for ( i = 0 ; i < cg.snap->numEntities ; i++ ) { state = &cg.snap->entities[ i ]; cent = &cg_entities[ state->number ]; memcpy(¢->currentState, state, sizeof(entityState_t)); //cent->currentState = *state; cent->interpolate = qfalse; cent->currentValid = qtrue; CG_ResetEntity( cent ); // check for events CG_CheckEvents( cent ); } }
void CG_KillCEntityInstances() { int i = 0; while (i < MAX_GENTITIES) { if (i >= MAX_CLIENTS) { //do not clear G2 instances on client ents, they are constant if (cg_entities[i].ghoul2 && trap_G2_HaveWeGhoul2Models(cg_entities[i].ghoul2)) { trap_G2API_CleanGhoul2Models(&(cg_entities[i].ghoul2)); } } /* else { //we must do this, because otherwise after a map_restart it seems to return bad angles in matrices produced by GetBoltMatrix if (cgs.clientinfo[i].ghoul2Model || cg_entities[i].ghoul2) { CG_LoadClientInfo(&cgs.clientinfo[i]); if (cg_entities[i].ghoul2 != cgs.clientinfo[i].ghoul2Model) { if (cg_entities[i].ghoul2 && trap_G2_HaveWeGhoul2Models(cg_entities[i].ghoul2)) { trap_G2API_CleanGhoul2Models(&(cg_entities[i].ghoul2)); } trap_G2API_DuplicateGhoul2Instance(cgs.clientinfo[i].ghoul2Model, &cg_entities[i].ghoul2); } } } */ cg_entities[i].isATST = 0; cg_entities[i].atstFootClang = 0; cg_entities[i].atstSwinging = 0; cg_entities[i].bolt1 = 0; cg_entities[i].bolt2 = 0; cg_entities[i].bolt3 = 0; cg_entities[i].bolt4 = 0; cg_entities[i].saberLength = SABER_LENGTH_MAX; cg_entities[i].saberExtendTime = 0; cg_entities[i].boltInfo = 0; cg_entities[i].frame_minus1_refreshed = 0; cg_entities[i].frame_minus2_refreshed = 0; cg_entities[i].dustTrailTime = 0; cg_entities[i].ghoul2weapon = NULL; // cg_entities[i].torsoBolt = 0; cg_entities[i].trailTime = 0; cg_entities[i].frame_hold_time = 0; cg_entities[i].frame_hold_refreshed = 0; cg_entities[i].trickAlpha = 0; cg_entities[i].trickAlphaTime = 0; VectorClear(cg_entities[i].turAngles); cg_entities[i].weapon = 0; cg_entities[i].teamPowerEffectTime = 0; cg_entities[i].teamPowerType = 0; i++; } }
/* ================= CG_ServerCommand The string has been tokenized and can be retrieved with Cmd_Argc() / Cmd_Argv() ================= */ static void CG_ServerCommand( void ) { const char *cmd; char text[MAX_SAY_TEXT]; cmd = CG_Argv(0); if ( !cmd[0] ) { // server claimed the command return; } if ( !strcmp( cmd, "spd" ) ) { const char *ID; int holdInt,count,i; char string[1204]; count = trap_Argc(); ID = CG_Argv(1); holdInt = atoi(ID); memset( &string, 0, sizeof( string ) ); Com_sprintf( string,sizeof(string)," \"%s\"", (const char *) CG_Argv(2)); for (i=3;i<count;i++) { Com_sprintf( string,sizeof(string)," %s \"%s\"", string, (const char *) CG_Argv(i)); } trap_SP_Print(holdInt, (byte *)string); return; } if ( !strcmp( cmd, "nfr" ) ) { //"nfr" == "new force rank" (want a short string) int doMenu = 0; int setTeam = 0; int newRank = 0; if (trap_Argc() < 3) { #ifdef _DEBUG Com_Printf("WARNING: Invalid newForceRank string\n"); #endif return; } newRank = atoi(CG_Argv(1)); doMenu = atoi(CG_Argv(2)); setTeam = atoi(CG_Argv(3)); trap_Cvar_Set("ui_rankChange", va("%i", newRank)); trap_Cvar_Set("ui_myteam", va("%i", setTeam)); if (!( trap_Key_GetCatcher() & KEYCATCH_UI ) && doMenu) { trap_OpenUIMenu(3); } return; } if ( !strcmp( cmd, "kg2" ) ) { //Kill a ghoul2 instance in this slot. //If it has been occupied since this message was sent somehow, the worst that can (should) happen //is the instance will have to reinit with its current info. int indexNum = 0; int argNum = trap_Argc(); int i = 1; if (argNum < 1) { return; } while (i < argNum) { indexNum = atoi(CG_Argv(i)); if (cg_entities[indexNum].ghoul2 && trap_G2_HaveWeGhoul2Models(cg_entities[indexNum].ghoul2)) { if (indexNum < MAX_CLIENTS) { //You try to do very bad thing! #ifdef _DEBUG Com_Printf("WARNING: Tried to kill a client ghoul2 instance with a kg2 command!\n"); #endif return; } trap_G2API_CleanGhoul2Models(&(cg_entities[indexNum].ghoul2)); } i++; } return; } if ( !strcmp( cmd, "cp" ) ) { char strEd[MAX_STRIPED_SV_STRING]; CG_CheckSVStripEdRef(strEd, CG_Argv(1)); CG_CenterPrint( strEd, SCREEN_HEIGHT * 0.30, BIGCHAR_WIDTH ); return; } if ( !strcmp( cmd, "cs" ) ) { CG_ConfigStringModified(); return; } if ( !strcmp( cmd, "print" ) ) { char strEd[MAX_STRIPED_SV_STRING]; CG_CheckSVStripEdRef(strEd, CG_Argv(1)); CG_Printf( "%s", strEd ); return; } if ( !strcmp( cmd, "chat" ) ) { if ( !cg_teamChatsOnly.integer ) { trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); Q_strncpyz( text, CG_Argv(1), MAX_SAY_TEXT ); CG_RemoveChatEscapeChar( text ); CG_Printf( "%s\n", text ); } return; } if ( !strcmp( cmd, "tchat" ) ) { trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); Q_strncpyz( text, CG_Argv(1), MAX_SAY_TEXT ); CG_RemoveChatEscapeChar( text ); CG_AddToTeamChat( text ); CG_Printf( "%s\n", text ); return; } if ( !strcmp( cmd, "vchat" ) ) { CG_VoiceChat( SAY_ALL ); return; } if ( !strcmp( cmd, "vtchat" ) ) { CG_VoiceChat( SAY_TEAM ); return; } if ( !strcmp( cmd, "vtell" ) ) { CG_VoiceChat( SAY_TELL ); return; } if ( !strcmp( cmd, "scores" ) ) { CG_ParseScores(); return; } if ( !strcmp( cmd, "tinfo" ) ) { CG_ParseTeamInfo(); return; } if ( !strcmp( cmd, "map_restart" ) ) { CG_MapRestart(); return; } if ( Q_stricmp (cmd, "remapShader") == 0 ) { if (trap_Argc() == 4) { trap_R_RemapShader(CG_Argv(1), CG_Argv(2), CG_Argv(3)); } } // loaddeferred can be both a servercmd and a consolecmd if ( !strcmp( cmd, "loaddefered" ) ) { // FIXME: spelled wrong, but not changing for demo CG_LoadDeferredPlayers(); return; } // clientLevelShot is sent before taking a special screenshot for // the menu system during development if ( !strcmp( cmd, "clientLevelShot" ) ) { cg.levelShot = qtrue; return; } CG_Printf( "Unknown client game command: %s\n", cmd ); }
//frees all ghoul2 stuff and npc stuff from a centity -rww void CG_KillCEntityG2(int entNum) { int j; clientInfo_t *ci = NULL; centity_t *cent = &cg_entities[entNum]; if (entNum < MAX_CLIENTS) { ci = &cgs.clientinfo[entNum]; } else { ci = cent->npcClient; } if (ci) { if (ci == cent->npcClient) { //never going to be != cent->ghoul2, unless cent->ghoul2 has already been removed (and then this ptr is not valid) ci->ghoul2Model = NULL; } else if (ci->ghoul2Model == cent->ghoul2) { ci->ghoul2Model = NULL; } else if (ci->ghoul2Model && trap_G2_HaveWeGhoul2Models(ci->ghoul2Model)) { trap_G2API_CleanGhoul2Models(&ci->ghoul2Model); ci->ghoul2Model = NULL; } //Clean up any weapon instances for custom saber stuff j = 0; while (j < MAX_SABERS) { if (ci->ghoul2Weapons[j] && trap_G2_HaveWeGhoul2Models(ci->ghoul2Weapons[j])) { trap_G2API_CleanGhoul2Models(&ci->ghoul2Weapons[j]); ci->ghoul2Weapons[j] = NULL; } j++; } } if (cent->ghoul2 && trap_G2_HaveWeGhoul2Models(cent->ghoul2)) { trap_G2API_CleanGhoul2Models(¢->ghoul2); cent->ghoul2 = NULL; } if (cent->grip_arm && trap_G2_HaveWeGhoul2Models(cent->grip_arm)) { trap_G2API_CleanGhoul2Models(¢->grip_arm); cent->grip_arm = NULL; } if (cent->frame_hold && trap_G2_HaveWeGhoul2Models(cent->frame_hold)) { trap_G2API_CleanGhoul2Models(¢->frame_hold); cent->frame_hold = NULL; } if (cent->npcClient) { CG_DestroyNPCClient(¢->npcClient); } cent->isRagging = qfalse; //just in case. cent->ikStatus = qfalse; cent->localAnimIndex = 0; }
static void CG_ServerCommand( void ) { const char *cmd; char text[MAX_SAY_TEXT]; qboolean IRCG = qfalse; cmd = CG_Argv(0); if ( !cmd[0] ) { // server claimed the command return; } #if 0 // never seems to get used -Ste if ( !strcmp( cmd, "spd" ) ) { const char *ID; int holdInt,count,i; char string[1204]; count = trap_Argc(); ID = CG_Argv(1); holdInt = atoi(ID); memset( &string, 0, sizeof( string ) ); Com_sprintf( string,sizeof(string)," \"%s\"", (const char *) CG_Argv(2)); for (i=3;i<count;i++) { Com_sprintf( string,sizeof(string)," %s \"%s\"", string, (const char *) CG_Argv(i)); } trap_SP_Print(holdInt, (byte *)string); return; } #endif if (!strcmp(cmd, "sxd")) { //siege extended data, contains extra info certain classes may want to know about other clients CG_ParseSiegeExtendedData(); return; } if (!strcmp(cmd, "sb")) { //siege briefing display CG_SiegeBriefingDisplay(atoi(CG_Argv(1)), 0); return; } if ( !strcmp( cmd, "scl" ) ) { //if (!( trap_Key_GetCatcher() & KEYCATCH_UI )) //Well, I want it to come up even if the briefing display is up. { trap_OpenUIMenu(UIMENU_CLASSSEL); //UIMENU_CLASSSEL } return; } if ( !strcmp( cmd, "spc" ) ) { trap_Cvar_Set("ui_myteam", "3"); trap_OpenUIMenu(UIMENU_PLAYERCONFIG); //UIMENU_CLASSSEL return; } if ( !strcmp( cmd, "nfr" ) ) { //"nfr" == "new force rank" (want a short string) int doMenu = 0; int setTeam = 0; int newRank = 0; if (trap_Argc() < 3) { #ifdef _DEBUG Com_Printf("WARNING: Invalid newForceRank string\n"); #endif return; } newRank = atoi(CG_Argv(1)); doMenu = atoi(CG_Argv(2)); setTeam = atoi(CG_Argv(3)); trap_Cvar_Set("ui_rankChange", va("%i", newRank)); trap_Cvar_Set("ui_myteam", va("%i", setTeam)); if (!( trap_Key_GetCatcher() & KEYCATCH_UI ) && doMenu) { trap_OpenUIMenu(UIMENU_PLAYERCONFIG); } return; } if ( !strcmp( cmd, "kg2" ) ) { //Kill a ghoul2 instance in this slot. //If it has been occupied since this message was sent somehow, the worst that can (should) happen //is the instance will have to reinit with its current info. int indexNum = 0; int argNum = trap_Argc(); int i = 1; if (argNum < 1) { return; } while (i < argNum) { indexNum = atoi(CG_Argv(i)); if (cg_entities[indexNum].ghoul2 && trap_G2_HaveWeGhoul2Models(cg_entities[indexNum].ghoul2)) { if (indexNum < MAX_CLIENTS) { //You try to do very bad thing! #ifdef _DEBUG Com_Printf("WARNING: Tried to kill a client ghoul2 instance with a kg2 command!\n"); #endif return; } CG_KillCEntityG2(indexNum); } i++; } return; } if (!strcmp(cmd, "kls")) { //kill looping sounds int indexNum = 0; int argNum = trap_Argc(); centity_t *clent = NULL; centity_t *trackerent = NULL; if (argNum < 1) { assert(0); return; } indexNum = atoi(CG_Argv(1)); if (indexNum != -1) { clent = &cg_entities[indexNum]; } if (argNum >= 2) { indexNum = atoi(CG_Argv(2)); if (indexNum != -1) { trackerent = &cg_entities[indexNum]; } } if (clent) { CG_S_StopLoopingSound(clent->currentState.number, -1); } if (trackerent) { CG_S_StopLoopingSound(trackerent->currentState.number, -1); } return; } if (!strcmp(cmd, "ircg")) { //this means param 2 is the body index and we want to copy to bodyqueue on it IRCG = qtrue; } if (!strcmp(cmd, "rcg") || IRCG) { //rcg - Restore Client Ghoul (make sure limbs are reattached and ragdoll state is reset - this must be done reliably) int indexNum = 0; int argNum = trap_Argc(); centity_t *clent; if (argNum < 1) { assert(0); return; } indexNum = atoi(CG_Argv(1)); if (indexNum < 0 || indexNum >= MAX_CLIENTS) { assert(0); return; } clent = &cg_entities[indexNum]; //assert(clent->ghoul2); if (!clent->ghoul2) { //this can happen while connecting as a client return; } #ifdef _DEBUG if (!trap_G2_HaveWeGhoul2Models(clent->ghoul2)) { assert(!"Tried to reset state on a bad instance. Crash is inevitable."); } #endif if (IRCG) { int bodyIndex = 0; int weaponIndex = 0; int side = 0; centity_t *body; assert(argNum >= 3); bodyIndex = atoi(CG_Argv(2)); weaponIndex = atoi(CG_Argv(3)); side = atoi(CG_Argv(4)); body = &cg_entities[bodyIndex]; if (side) { body->teamPowerType = qtrue; //light side } else { body->teamPowerType = qfalse; //dark side } CG_BodyQueueCopy(body, clent->currentState.number, weaponIndex); } //reattach any missing limbs if (clent->torsoBolt) { CG_ReattachLimb(clent); } //make sure ragdoll state is reset if (clent->isRagging) { clent->isRagging = qfalse; trap_G2API_SetRagDoll(clent->ghoul2, NULL); //calling with null parms resets to no ragdoll. } //clear all the decals as well trap_G2API_ClearSkinGore(clent->ghoul2); clent->weapon = 0; clent->ghoul2weapon = NULL; //force a weapon reinit return; } if ( !strcmp( cmd, "cp" ) ) { char strEd[MAX_STRINGED_SV_STRING]; CG_CheckSVStringEdRef(strEd, CG_Argv(1)); CG_CenterPrint( strEd, SCREEN_HEIGHT * 0.30, BIGCHAR_WIDTH ); return; } if ( !strcmp( cmd, "cps" ) ) { char strEd[MAX_STRINGED_SV_STRING]; char *x = (char *)CG_Argv(1); if (x[0] == '@') { x++; } trap_SP_GetStringTextString(x, strEd, MAX_STRINGED_SV_STRING); CG_CenterPrint( strEd, SCREEN_HEIGHT * 0.20, BIGCHAR_WIDTH ); return; } if ( !strcmp( cmd, "cs" ) ) { CG_ConfigStringModified(); return; } if ( !strcmp( cmd, "print" ) ) { char strEd[MAX_STRINGED_SV_STRING]; CG_CheckSVStringEdRef(strEd, CG_Argv(1)); CG_Printf( "%s", strEd ); return; } if ( !strcmp( cmd, "chat" ) ) { if ( !cg_teamChatsOnly.integer ) { trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); Q_strncpyz( text, CG_Argv(1), MAX_SAY_TEXT ); CG_RemoveChatEscapeChar( text ); CG_ChatBox_AddString(text); CG_Printf( "*%s\n", text ); } return; } if ( !strcmp( cmd, "tchat" ) ) { trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); Q_strncpyz( text, CG_Argv(1), MAX_SAY_TEXT ); CG_RemoveChatEscapeChar( text ); CG_ChatBox_AddString(text); CG_Printf( "*%s\n", text ); return; } //chat with location, possibly localized. if ( !strcmp( cmd, "lchat" ) ) { if ( !cg_teamChatsOnly.integer ) { char name[MAX_STRING_CHARS]; char loc[MAX_STRING_CHARS]; char color[8]; char message[MAX_STRING_CHARS]; if (trap_Argc() < 4) { return; } strcpy(name, CG_Argv(1)); strcpy(loc, CG_Argv(2)); strcpy(color, CG_Argv(3)); strcpy(message, CG_Argv(4)); if (loc[0] == '@') { //get localized text trap_SP_GetStringTextString(loc+1, loc, MAX_STRING_CHARS); } trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); //Q_strncpyz( text, CG_Argv(1), MAX_SAY_TEXT ); Com_sprintf(text, MAX_SAY_TEXT, "%s<%s>^%s%s", name, loc, color, message); CG_RemoveChatEscapeChar( text ); CG_ChatBox_AddString(text); CG_Printf( "*%s\n", text ); } return; } if ( !strcmp( cmd, "ltchat" ) ) { char name[MAX_STRING_CHARS]; char loc[MAX_STRING_CHARS]; char color[8]; char message[MAX_STRING_CHARS]; if (trap_Argc() < 4) { return; } strcpy(name, CG_Argv(1)); strcpy(loc, CG_Argv(2)); strcpy(color, CG_Argv(3)); strcpy(message, CG_Argv(4)); if (loc[0] == '@') { //get localized text trap_SP_GetStringTextString(loc+1, loc, MAX_STRING_CHARS); } trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); //Q_strncpyz( text, CG_Argv(1), MAX_SAY_TEXT ); Com_sprintf(text, MAX_SAY_TEXT, "%s<%s> ^%s%s", name, loc, color, message); CG_RemoveChatEscapeChar( text ); CG_ChatBox_AddString(text); CG_Printf( "*%s\n", text ); return; } if ( !strcmp( cmd, "scores" ) ) { CG_ParseScores(); return; } if ( !strcmp( cmd, "tinfo" ) ) { CG_ParseTeamInfo(); return; } if ( !strcmp( cmd, "map_restart" ) ) { CG_MapRestart(); return; } if ( Q_stricmp (cmd, "remapShader") == 0 ) { if (trap_Argc() == 4) { trap_R_RemapShader(CG_Argv(1), CG_Argv(2), CG_Argv(3)); } } // loaddeferred can be both a servercmd and a consolecmd if ( !strcmp( cmd, "loaddefered" ) ) { // FIXME: spelled wrong, but not changing for demo CG_LoadDeferredPlayers(); return; } // clientLevelShot is sent before taking a special screenshot for // the menu system during development if ( !strcmp( cmd, "clientLevelShot" ) ) { cg.levelShot = qtrue; return; } CG_Printf( "Unknown client game command: %s\n", cmd ); }
void SetupGameGhoul2Model(gclient_t *client, char *modelname) { int handle; char afilename[MAX_QPATH]; char /**GLAName,*/ *slash; char GLAName[MAX_QPATH]; vec3_t tempVec = {0,0,0}; // First things first. If this is a ghoul2 model, then let's make sure we demolish this first. if (client->ghoul2 && trap_G2_HaveWeGhoul2Models(client->ghoul2)) { trap_G2API_CleanGhoul2Models(&(client->ghoul2)); } /* Com_sprintf( afilename, sizeof( afilename ), "models/players/%s/model.glm", modelname ); handle = trap_G2API_InitGhoul2Model(&client->ghoul2, afilename, 0, 0, -20, 0, 0); if (handle<0) { Com_sprintf( afilename, sizeof( afilename ), "models/players/kyle/model.glm" ); handle = trap_G2API_InitGhoul2Model(&client->ghoul2, afilename, 0, 0, -20, 0, 0); if (handle<0) { return; } } */ //rww - just load the "standard" model for the server" if (!precachedKyle) { Com_sprintf( afilename, sizeof( afilename ), "models/players/kyle/model.glm" ); handle = trap_G2API_InitGhoul2Model(&precachedKyle, afilename, 0, 0, -20, 0, 0); if (handle<0) { return; } } if (precachedKyle && trap_G2_HaveWeGhoul2Models(precachedKyle)) { trap_G2API_DuplicateGhoul2Instance(precachedKyle, &client->ghoul2); } else { return; } // The model is now loaded. GLAName[0] = 0; if (!BGPAFtextLoaded) { //get the location of the animation.cfg //GLAName = trap_G2API_GetGLAName( client->ghoul2, 0); trap_G2API_GetGLAName( client->ghoul2, 0, GLAName); if (!GLAName[0]) { if (!BG_ParseAnimationFile("models/players/_humanoid/animation.cfg")) { Com_Printf( "Failed to load animation file %s\n", afilename ); return; } return; } Q_strncpyz( afilename, GLAName, sizeof( afilename )); slash = Q_strrchr( afilename, '/' ); if ( slash ) { strcpy(slash, "/animation.cfg"); } // Now afilename holds just the path to the animation.cfg else { // Didn't find any slashes, this is a raw filename right in base (whish isn't a good thing) return; } // Try to load the animation.cfg for this model then. if ( !BG_ParseAnimationFile( afilename ) ) { // The GLA's animations failed if (!BG_ParseAnimationFile("models/players/_humanoid/animation.cfg")) { Com_Printf( "Failed to load animation file %s\n", afilename ); return; } } } trap_G2API_AddBolt(client->ghoul2, 0, "*r_hand"); trap_G2API_AddBolt(client->ghoul2, 0, "*l_hand"); // NOTE - ensure this sequence of bolt and bone accessing are always the same because the client expects them in a certain order trap_G2API_SetBoneAnim(client->ghoul2, 0, "model_root", 0, 12, BONE_ANIM_OVERRIDE_LOOP, 1.0f, level.time, -1, -1); trap_G2API_SetBoneAngles(client->ghoul2, 0, "upper_lumbar", tempVec, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, NULL, 0, level.time); trap_G2API_SetBoneAngles(client->ghoul2, 0, "cranium", tempVec, BONE_ANGLES_POSTMULT, POSITIVE_Z, NEGATIVE_Y, POSITIVE_X, NULL, 0, level.time); if (!g2SaberInstance) { trap_G2API_InitGhoul2Model(&g2SaberInstance, "models/weapons2/saber/saber_w.glm", 0, 0, -20, 0, 0); if (g2SaberInstance) { // indicate we will be bolted to model 0 (ie the player) on bolt 0 (always the right hand) when we get copied trap_G2API_SetBoltInfo(g2SaberInstance, 0, 0); // now set up the gun bolt on it trap_G2API_AddBolt(g2SaberInstance, 0, "*flash"); } } if (g2SaberInstance) { trap_G2API_CopySpecificGhoul2Model(g2SaberInstance, 0, client->ghoul2, 1); } }
void JKG_DrawWeaponHolsters( centity_t *cent, refEntity_t legs, float shadowPlane ) { if (cent->currentState.weapon > 0 // UQ1: Issues with weapon 0??? && !(cent->currentState.number == cg.predictedPlayerState.clientNum && !cg.renderingThirdPerson) && cent->currentState.number == cg.clientNum // UQ1: Enemy ones??? Best data transfer method??? && (cent && cent->ghoul2 && cent->currentState.eType != ET_NPC)) { int HOLSTER_POINT = 0; int NUM_HOLSTERS = 5; // UQ1: Extra 2 look stupid... int i = 0; cgItemData_t *LIGHT_ITEMS_LIST[5]; cgItemData_t *HEAVY_ITEMS_LIST[5]; int NUM_LIGHT_ITEMS = 0; int NUM_HEAVY_ITEMS = 0; #ifdef _DEBUG //CG_Printf("Adding holster items...\n"); #endif //_DEBUG for (i = 0; i < 3; i++) LIGHT_ITEMS_LIST[i] = NULL; for (i = 0; i < 2; i++) HEAVY_ITEMS_LIST[i] = NULL; // Create Light Items List... for (i = 0; i < MAX_ACI_SLOTS; i++) { unsigned int weap, var; // FIXME: How to get enemy player ACI list???? // Events? Even the data for just 4 holsters would be crazy... if (cg.playerACI[i] < 0) continue; if (cg.playerInventory[cg.playerACI[i]].id->weapon == cg.predictedPlayerState.weapon) continue; if (cg.playerInventory[cg.playerACI[i]].equipped) continue; if (!cg.playerInventory[cg.playerACI[i]].id) continue; weap = cg.playerInventory[cg.playerACI[i]].id->weapon; var = cg.playerInventory[cg.playerACI[i]].id->variation; // How did this get through equipped above??? if (weap == cent->currentState.weapon) continue; // Quick and dirty choice of where to put guns based on weight... if (cg.playerInventory[cg.playerACI[i]].id->weight > 1) continue; // Too heavy for waist... // FIXME: Sort by new WEAPON_TYPE value... LIGHT_ITEMS_LIST[NUM_LIGHT_ITEMS] = cg.playerInventory[cg.playerACI[i]].id; NUM_LIGHT_ITEMS++; if (NUM_LIGHT_ITEMS >= 3) break; // Full... } // Create Heavy Items List... for (i = 0; i < MAX_ACI_SLOTS; i++) { unsigned int weap, var; // FIXME: How to get enemy player ACI list???? // Events? Even the data for just 4 holsters would be crazy... if (cg.playerACI[i] < 0) continue; if (cg.playerInventory[cg.playerACI[i]].equipped) continue; if (!cg.playerInventory[cg.playerACI[i]].id) continue; weap = cg.playerInventory[cg.playerACI[i]].id->weapon; var = cg.playerInventory[cg.playerACI[i]].id->variation; // How did this get through equipped above??? if (weap == cent->currentState.weapon) continue; // Quick and dirty choice of where to put guns based on weight... if (cg.playerInventory[cg.playerACI[i]].id->weight <= 1) continue; // Too light for back... // FIXME: Sort by new WEAPON_TYPE value... HEAVY_ITEMS_LIST[NUM_HEAVY_ITEMS] = cg.playerInventory[cg.playerACI[i]].id; NUM_HEAVY_ITEMS++; if (NUM_HEAVY_ITEMS >= 2) break; // Full... } for(HOLSTER_POINT = 0; HOLSTER_POINT < NUM_HOLSTERS; HOLSTER_POINT++) { void *weaponGhoul2 = NULL; refEntity_t holsterRefEnt; int WEAPON_NUM = 0; weaponInfo_t *weapon = NULL; if (HOLSTER_POINT == 0 && NUM_LIGHT_ITEMS < 1) continue; // No more light items to draw... if (HOLSTER_POINT == 1 && NUM_LIGHT_ITEMS < 2) continue; // No more light items to draw... //if (HOLSTER_POINT == 2 && NUM_LIGHT_ITEMS < 3) continue; // No more light items to draw... if (HOLSTER_POINT == 2) continue; // Disabled... if (HOLSTER_POINT == 3 && NUM_HEAVY_ITEMS < 1) continue; // No more heavy items to draw... if (HOLSTER_POINT == 4 && NUM_HEAVY_ITEMS < 2) continue; // No more heavy items to draw... if (HOLSTER_POINT < 3) { if (LIGHT_ITEMS_LIST[HOLSTER_POINT]) { // Light Items (waist)... WEAPON_NUM = LIGHT_ITEMS_LIST[HOLSTER_POINT]->weapon; if (WEAPON_NUM <= 0) continue; weapon = CG_WeaponInfo (WEAPON_NUM, LIGHT_ITEMS_LIST[HOLSTER_POINT]->variation); } else { continue; } } else { if (HEAVY_ITEMS_LIST[HOLSTER_POINT-3]) { // Heavy Items (back)... WEAPON_NUM = HEAVY_ITEMS_LIST[HOLSTER_POINT-3]->weapon; if (WEAPON_NUM <= 0) continue; weapon = CG_WeaponInfo (WEAPON_NUM, HEAVY_ITEMS_LIST[HOLSTER_POINT-3]->variation); } else { continue; } } if (!weapon) continue; memset( &holsterRefEnt, 0, sizeof( holsterRefEnt ) ); weaponGhoul2 = weapon->g2WorldModel; if (trap_G2_HaveWeGhoul2Models(weaponGhoul2)) { char bone_name[MAX_QPATH]; vec3_t holsterAngles, end, fwd, rt, originalOrigin; // UQ1: Which bone are we using? if (HOLSTER_POINT == 0) Q_strncpyz( bone_name , "pelvis", sizeof( bone_name ) ); if (HOLSTER_POINT == 1) Q_strncpyz( bone_name , "pelvis", sizeof( bone_name ) ); if (HOLSTER_POINT == 2) Q_strncpyz( bone_name , "thoracic", sizeof( bone_name ) ); if (HOLSTER_POINT == 3) Q_strncpyz( bone_name , "thoracic", sizeof( bone_name ) ); if (HOLSTER_POINT == 4) Q_strncpyz( bone_name , "thoracic", sizeof( bone_name ) ); //if (HOLSTER_POINT == 4) Q_strncpyz( bone_name , "ltibia", sizeof( bone_name ) ); // UQ1: These look really dumb.... //if (HOLSTER_POINT == 5) Q_strncpyz( bone_name , "rtibia", sizeof( bone_name ) ); // UQ1: These look really dumb.... // UQ1: Set exact org/angles for this bone... if (!CG_SnapRefEntToBone(cent, &holsterRefEnt, bone_name)) { #ifdef _DEBUG CG_Printf("Holster point %i NOT drawn (snap to bone issue)...\n", HOLSTER_POINT); assert(0); #endif // continue; } VectorCopy( legs.modelScale, holsterRefEnt.modelScale); holsterRefEnt.radius = legs.radius; VectorCopy(holsterRefEnt.origin, originalOrigin); VectorCopy(cent->lerpAngles, holsterAngles); holsterAngles[PITCH] = 0; holsterAngles[ROLL] = 0; AngleVectors( holsterAngles, fwd, rt, NULL ); // UQ1: Now modify the org/angles... switch (HOLSTER_POINT) { case 0: // "pelvis" left VectorMA( originalOrigin, -2, fwd, end ); VectorMA( end, -6, rt, end ); VectorCopy(end, holsterRefEnt.origin); holsterRefEnt.origin[2] += 8; // because the bones suck for placement... //AxisToAngles(holsterRefEnt.axis, holsterAngles); holsterAngles[PITCH] += 90; //holsterAngles[YAW] -= 90; holsterAngles[ROLL] += 90; holsterAngles[PITCH] += 30; holsterAngles[YAW] -= 50; holsterAngles[ROLL] -= 50; break; case 1: // "pelvis" right VectorMA( originalOrigin, -2, fwd, end ); VectorMA( end, 6, rt, end ); VectorCopy(end, holsterRefEnt.origin); holsterRefEnt.origin[2] += 8; // because the bones suck for placement... //AxisToAngles(holsterRefEnt.axis, holsterAngles); holsterAngles[PITCH] += 90; holsterAngles[YAW] += 180; holsterAngles[ROLL] += 90; holsterAngles[PITCH] -= 30; holsterAngles[YAW] += 50; holsterAngles[ROLL] += 50; break; case 2: // "thoracic" left - used for center pistol - where on the back is this meant to fit??? VectorMA( originalOrigin, -4, fwd, end ); VectorMA( end, -2, rt, end ); VectorCopy(end, holsterRefEnt.origin); holsterRefEnt.origin[2] += 8; // because the bones suck for placement... //AxisToAngles(holsterRefEnt.axis, holsterAngles); holsterAngles[PITCH] += 90; //holsterAngles[YAW] -= 90; holsterAngles[ROLL] += 90; holsterAngles[PITCH] += 10;//d_poff.value; holsterAngles[YAW] += 0;//d_yoff.value; holsterAngles[ROLL] += 0;//d_roff.value; break; case 3: // "thoracic" left VectorMA( originalOrigin, -4, fwd, end ); VectorMA( end, -6, rt, end ); VectorCopy(end, holsterRefEnt.origin); holsterRefEnt.origin[2] += 6; // because the bones suck for placement... //AxisToAngles(holsterRefEnt.axis, holsterAngles); holsterAngles[PITCH] += 90; //holsterAngles[YAW] -= 90; holsterAngles[ROLL] += 90; holsterAngles[PITCH] += 10 + 25; holsterAngles[YAW] += 50 + 15; holsterAngles[ROLL] += 50; break; case 4: // "thoracic" right VectorMA( originalOrigin, -4, fwd, end ); VectorMA( end, 6, rt, end ); VectorCopy(end, holsterRefEnt.origin); holsterRefEnt.origin[2] += 6; // because the bones suck for placement... //AxisToAngles(holsterRefEnt.axis, holsterAngles); holsterAngles[PITCH] += 90; holsterAngles[YAW] += 180; holsterAngles[ROLL] += 90; holsterAngles[PITCH] -= 10 + 25; holsterAngles[YAW] -= 50 + 15; holsterAngles[ROLL] -= 50; break; /*case 5: // UQ1: These look really dumb.... // "ltibia" VectorMA( originalOrigin, -4, fwd, end ); VectorMA( end, -4, rt, end ); VectorCopy(end, holsterRefEnt.origin); holsterRefEnt.origin[2] += 8; // because the bones suck for placement... holsterAngles[PITCH] += 90; //holsterAngles[YAW] -= 90; holsterAngles[ROLL] += 90; holsterAngles[PITCH] -= d_poff.value; holsterAngles[YAW] -= d_yoff.value; holsterAngles[ROLL] -= d_roff.value; break; case 6: // UQ1: These look really dumb.... // "rtibia" VectorMA( originalOrigin, -4, fwd, end ); VectorMA( end, 4, rt, end ); VectorCopy(end, holsterRefEnt.origin); holsterRefEnt.origin[2] += 8; // because the bones suck for placement... holsterAngles[PITCH] += 90; holsterAngles[YAW] += 180; holsterAngles[ROLL] += 90; holsterAngles[PITCH] += d_poff.value; holsterAngles[YAW] += d_yoff.value; holsterAngles[ROLL] += d_roff.value; break;*/ default: continue; // should never see this... break; } holsterRefEnt.reType = RT_MODEL; holsterRefEnt.hModel = 0; holsterRefEnt.ghoul2 = weaponGhoul2; AnglesToAxis(holsterAngles, holsterRefEnt.axis); holsterRefEnt.shadowPlane = shadowPlane; CG_AddWeaponWithPowerups( &holsterRefEnt, cent->currentState.powerups ); #ifdef _DEBUG //CG_Printf("Holster point %i drawn at %f %f %f (P.ORG %f %f %f)...\n", HOLSTER_POINT, holsterRefEnt.origin[0], holsterRefEnt.origin[1], holsterRefEnt.origin[2], cent->lerpOrigin[0], cent->lerpOrigin[1], cent->lerpOrigin[2]); #endif //_DEBUG } #ifdef _DEBUG else { //CG_Printf("Holster point %i NOT drawn...\n", HOLSTER_POINT); //assert(0); } #endif //_DEBUG } } }