/* ====================== CG_GetOriginForTag places the position of the tag into "org" returns the index of the tag it used, so we can cycle through tag's with the same name ====================== */ int CG_GetOriginForTag(centity_t *cent, refEntity_t *parent, char *tagName, int startIndex, vec3_t org, vec3_t axis[3]) { int i; orientation_t lerped; int retval; // lerp the tag retval = trap_R_LerpTag(&lerped, parent, tagName, startIndex); if (retval < 0) { return retval; } VectorCopy(parent->origin, org); for (i = 0 ; i < 3 ; i++) { VectorMA(org, lerped.origin[i], parent->axis[i], org); } if (axis) { // had to cast away the const to avoid compiler problems... MatrixMultiply(lerped.axis, ((refEntity_t *)parent)->axis, axis); } return retval; }
static void RegisterClientModelnameWithFallback (clientInfo_t *ci, const char *modelName, const char *skinName, const char *headModelName, const char *headSkinName, const char *teamName, qboolean dontForceTeamSkin) { if (CG_RegisterClientModelname(ci, modelName, skinName, headModelName, headSkinName, "", dontForceTeamSkin)) { const char *dir, *fallback, *s; int i; cg.teamModel.newAnims = qfalse; if (cg.teamModel.torsoModel) { orientation_t tag; // if the torso model has the "tag_flag" if (trap_R_LerpTag(&tag, cg.teamModel.torsoModel, 0, 0, 1, "tag_flag")) { cg.teamModel.newAnims = qtrue; } } // sounds dir = cg.teamModel.modelName; fallback = (cgs.gametype >= GT_TEAM) ? DEFAULT_TEAM_MODEL : DEFAULT_MODEL; for (i = 0; i < MAX_CUSTOM_SOUNDS; i++) { s = cg_customSoundNames[i]; if (!s) { break; } cg.teamModel.sounds[i] = 0; // if the model didn't load use the sounds of the default model cg.teamModel.sounds[i] = trap_S_RegisterSound(va("sound/player/%s/%s", dir, s + 1), qfalse); if (!cg.teamModel.sounds[i]) cg.teamModel.sounds[i] = trap_S_RegisterSound(va("sound/player/%s/%s", fallback, s + 1), qfalse); } } }
/* ====================== UI_PositionEntityOnTag ====================== */ static qboolean UI_PositionEntityOnTag( refEntity_t *entity, const refEntity_t *parent, clipHandle_t parentModel, char *tagName ) { int i; orientation_t lerped; qboolean returnValue; // lerp the tag returnValue = trap_R_LerpTag( &lerped, parentModel, parent->oldframe, parent->frame, 1.0 - parent->backlerp, tagName ); // FIXME: allow origin offsets along tag? VectorCopy( parent->origin, entity->origin ); for ( i = 0 ; i < 3 ; i++ ) { VectorMA( entity->origin, lerped.origin[i], parent->axis[i], entity->origin ); } // cast away const because of compiler problems MatrixMultiply( lerped.axis, ((refEntity_t*)parent)->axis, entity->axis ); entity->backlerp = parent->backlerp; return returnValue; }
/* ================== G_CalcMoveSpeeds; adapted from BG_CalcMoveSpeeds ================== */ static void G_CalcMoveSpeeds( bg_character_t *character ) { char *tags[2] = {"tag_footleft", "tag_footright"}; vec3_t oldPos[2] = { { 0, 0, 0 }, { 0, 0, 0 } }; grefEntity_t refent; animation_t *anim; int i, j, k; float totalSpeed; int numSpeed; int lastLow, low; orientation_t o[2]; memset( &refent, 0, sizeof(refent) ); refent.hModel = character->mesh; for( i = 0; i < character->animModelInfo->numAnimations; i++ ) { anim = character->animModelInfo->animations[i]; if( anim->moveSpeed >= 0 ) { continue; } totalSpeed = 0; lastLow = -1; numSpeed = 0; // for each frame for( j = 0; j < anim->numFrames; j++ ) { refent.frame = anim->firstFrame + j; refent.oldframe = refent.frame; refent.torsoFrameModel = refent.oldTorsoFrameModel = refent.frameModel = refent.oldframeModel = anim->mdxFile; // for each foot for( k = 0; k < 2; k++ ) { if( trap_R_LerpTag( &o[k], &refent, tags[k], 0 ) < 0 ) { G_Error( "G_CalcMoveSpeeds: unable to find tag %s, cannot calculate movespeed", tags[k] ); } } // find the contact foot if( anim->flags & ANIMFL_LADDERANIM ) { if( o[0].origin[0] > o[1].origin[0] ) low = 0; else low = 1; totalSpeed += fabs( oldPos[low][2] - o[low].origin[2] ); } else { if( o[0].origin[2] < o[1].origin[2] ) low = 0; else low = 1; totalSpeed += fabs( oldPos[low][0] - o[low].origin[0] ); } numSpeed++; // save the positions for( k = 0; k < 2; k++ ) { VectorCopy( o[k].origin, oldPos[k] ); } lastLow = low; } // record the speed anim->moveSpeed = rint((totalSpeed/numSpeed) * 1000.0 / anim->frameLerp); } }
void Wolfcam_LoadModels (void) { char modelStr[MAX_QPATH]; //char tmpStr[MAX_QPATH]; //char skinStr[MAX_QPATH]; char *skin; int i; //FIXME modification count can't be changed by cgame? static int modc = -1; static int modchead = -1; static int modctorso = -1; static int modclegs = -1; static int modcheadcolor = -1; static int modctorsocolor = -1; static int modclegscolor = -1; qboolean checkSkins; Wolfcam_LoadTeamModel(); Wolfcam_LoadOurModel(); checkSkins = qfalse; //if (cg_enemyModel.modificationCount) { if (cg_enemyModel.modificationCount != modc || cg_enemyHeadSkin.modificationCount != modchead || cg_enemyTorsoSkin.modificationCount != modctorso || cg_enemyLegsSkin.modificationCount != modclegs ) { EM_Loaded = 0; modc = cg_enemyModel.modificationCount; modchead = cg_enemyHeadSkin.modificationCount; modctorso = cg_enemyTorsoSkin.modificationCount; modclegs = cg_enemyLegsSkin.modificationCount; checkSkins = qtrue; for (i = 0; i < MAX_CLIENTS; i++) { clientInfo_t *ci; ci = &cgs.clientinfo[i]; ci->headEnemySkinAlt = 0; ci->torsoEnemySkinAlt = 0; ci->legsEnemySkinAlt = 0; } } if (EM_Loaded == 0 && cg_enemyModel.string && *cg_enemyModel.string) { Q_strncpyz (modelStr, cg_enemyModel.string, sizeof(modelStr)); if ((skin = strchr(modelStr, '/')) == NULL) { //Com_Printf("using default\n"); skin = "default"; } else *skin++ = 0; //memcpy(&EM_ModelInfo, ci, sizeof(EM_ModelInfo)); Q_strncpyz(EM_ModelInfo.modelName, modelStr, sizeof(EM_ModelInfo.modelName)); Q_strncpyz(EM_ModelInfo.skinName, skin, sizeof(EM_ModelInfo.skinName)); if (cgs.gametype >= GT_TEAM && Q_stricmp(EM_ModelInfo.skinName, "pm") != 0) { //FIXME why is this here //Q_strncpyz(EM_ModelInfo.skinName, "default", sizeof(EM_ModelI\nfo.skinName)); } Q_strncpyz(EM_ModelInfo.headModelName, EM_ModelInfo.modelName, sizeof(EM_ModelInfo.headModelName)); Q_strncpyz(EM_ModelInfo.headSkinName, EM_ModelInfo.skinName, sizeof(EM_ModelInfo.headSkinName)); if (CG_RegisterClientModelname(&EM_ModelInfo, EM_ModelInfo.modelName, EM_ModelInfo.skinName, EM_ModelInfo.headModelName, EM_ModelInfo.headSkinName, "", qtrue)) { const char *dir, *fallback, *s; //char modelName[MAX_QPATH]; //char skinName[MAX_QPATH]; EM_Loaded = 1; EM_ModelInfo.newAnims = qfalse; if (EM_ModelInfo.torsoModel) { orientation_t tag; // if the torso model has the "tag_flag" if (trap_R_LerpTag(&tag, EM_ModelInfo.torsoModel, 0, 0, 1, "tag_flag")) { EM_ModelInfo.newAnims = qtrue; } } //FIXME not here #if 0 if (cg_enemyHeadSkin.string && *cg_enemyHeadSkin.string) { CG_GetModelAndSkinName(cg_enemyHeadSkin.string, modelName, skinName); if (!*modelName) { Q_strncpyz(modelName, modelStr, sizeof(modelName)); } EM_ModelInfo.headSkin = CG_RegisterSkinVertexLight(va("models/players/%s/head_%s.skin", modelName, skinName)); if (!EM_ModelInfo.headSkin) { Com_Printf("couldn't load head skin '%s %s'\n", modelName, skinName); } } if (cg_enemyTorsoSkin.string && *cg_enemyTorsoSkin.string) { CG_GetModelAndSkinName(cg_enemyTorsoSkin.string, modelName, skinName); if (!*modelName) { Q_strncpyz(modelName, modelStr, sizeof(modelName)); } EM_ModelInfo.torsoSkin = CG_RegisterSkinVertexLight(va("models/players/%s/upper_%s.skin", modelName, skinName)); if (!EM_ModelInfo.torsoSkin) { Com_Printf("couldn't load torso skin '%s %s'\n", modelName, skinName); } } if (cg_enemyLegsSkin.string && *cg_enemyLegsSkin.string) { CG_GetModelAndSkinName(cg_enemyLegsSkin.string, modelName, skinName); if (!*modelName) { Q_strncpyz(modelName, modelStr, sizeof(modelName)); } Com_Printf("legs model: %s skin: %s\n", modelName, skinName); EM_ModelInfo.legsSkin = CG_RegisterSkinVertexLight(va("models/players/%s/lower_%s.skin", modelName, skinName)); if (!EM_ModelInfo.legsSkin) { Com_Printf("couldn't load legs skin '%s %s'\n", modelName, skinName); } } #endif // sounds dir = EM_ModelInfo.modelName; fallback = (cgs.gametype >= GT_TEAM) ? DEFAULT_TEAM_MODEL : DEFAULT_MODEL; for (i = 0; i < MAX_CUSTOM_SOUNDS; i++) { s = cg_customSoundNames[i]; if (!s) { break; } EM_ModelInfo.sounds[i] = 0; // if the model didn't load use the sounds of the default model EM_ModelInfo.sounds[i] = trap_S_RegisterSound(va("sound/player/%s/%s", dir, s + 1), qfalse); if (!EM_ModelInfo.sounds[i]) EM_ModelInfo.sounds[i] = trap_S_RegisterSound(va("sound/player/%s/%s", fallback, s + 1), qfalse); } } else EM_Loaded = -1; } else if (EM_Loaded == 0) { // request to switch back to default models //Com_Printf("back to old models\n"); EM_Loaded = -1; } if (cg_enemyHeadColor.modificationCount != modcheadcolor || cg_enemyTorsoColor.modificationCount != modctorsocolor || cg_enemyLegsColor.modificationCount != modclegscolor ) { SC_ByteVec3ColorFromCvar(EC_Colors[0], &cg_enemyHeadColor); EC_Colors[0][3] = 255; SC_ByteVec3ColorFromCvar(EC_Colors[1], &cg_enemyTorsoColor); EC_Colors[1][3] = 255; SC_ByteVec3ColorFromCvar(EC_Colors[2], &cg_enemyLegsColor); EC_Colors[2][3] = 255; modcheadcolor = cg_enemyHeadColor.modificationCount; modctorsocolor = cg_enemyTorsoColor.modificationCount; modclegscolor = cg_enemyLegsColor.modificationCount; EC_Loaded = 1; } if (checkSkins && (*cg_enemyHeadSkin.string || *cg_enemyTorsoSkin.string || *cg_enemyLegsSkin.string)) { Com_Printf("reset alt enemy skins\n"); for (i = 0; i < MAX_CLIENTS; i++) { clientInfo_t *ci; ci = &cgs.clientinfo[i]; ci->headEnemySkinAlt = 0; ci->torsoEnemySkinAlt = 0; ci->legsEnemySkinAlt = 0; } } }