Beispiel #1
0
static void Wolfcam_LoadTeamModel (void)
{
	char modelStr[MAX_QPATH];
	//char modelName[MAX_QPATH];
	//char skinName[MAX_QPATH];
	char *skin;
	int i;
	//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;

	if (cg_teamHeadColor.modificationCount != modcheadcolor  ||
		cg_teamTorsoColor.modificationCount != modctorsocolor  ||
		cg_teamLegsColor.modificationCount != modclegscolor
		) {
		SC_ByteVec3ColorFromCvar(cg.teamColors[0], &cg_teamHeadColor);
		cg.teamColors[0][3] = 255;
		SC_ByteVec3ColorFromCvar(cg.teamColors[1], &cg_teamTorsoColor);
		cg.teamColors[1][3] = 255;
		SC_ByteVec3ColorFromCvar(cg.teamColors[2], &cg_teamLegsColor);
		cg.teamColors[2][3] = 255;
		modcheadcolor = cg_teamHeadColor.modificationCount;
		modctorsocolor = cg_teamTorsoColor.modificationCount;
		modclegscolor = cg_teamLegsColor.modificationCount;
		//EC_Loaded = 1;
	}

	if (cg_teamModel.modificationCount != TeamModel_modc  ||
		cg_teamHeadSkin.modificationCount != modchead  ||
		cg_teamTorsoSkin.modificationCount != modctorso  ||
		cg_teamLegsSkin.modificationCount != modclegs

) {
		//EM_Loaded = 0;
		TeamModel_modc = cg_teamModel.modificationCount;
		modchead = cg_teamHeadSkin.modificationCount;
		modctorso = cg_teamTorsoSkin.modificationCount;
		modclegs = cg_teamLegsSkin.modificationCount;
	} else {
		return;
	}

	Com_Printf("loading team models\n");

	for (i = 0;  i < MAX_CLIENTS;  i++) {
		clientInfo_t *ci;

		ci = &cgs.clientinfo[i];
		ci->headSkinAlt = 0;
		ci->torsoSkinAlt = 0;
		ci->legsSkinAlt = 0;
	}

	//if (cg_teamModel.v.string && *cg_teamModel.v.string) {
	//if (*cg_teamModel.string  ||  *cg_teamHeadSkin.string  ||  *cg_teamTorsoSkin.string  ||  *cg_teamLegsSkin.string) {
	if (*cg_teamModel.string) {
		Q_strncpyz (modelStr, cg_teamModel.string, sizeof(modelStr));
	} else {
		//FIXME changes in cg_ourModel
		// use this for black listed enemy model as teammate
		Q_strncpyz(modelStr, cg_ourModel.string, sizeof(modelStr));
	}

		if ((skin = strchr(modelStr, '/')) == NULL) {
			skin = "default";
			cg.useTeamSkins = qtrue;
		} else {
			*skin++ = 0;
			cg.useTeamSkins = qfalse;
		}

		Q_strncpyz(cg.teamModel.modelName, modelStr, sizeof(cg.teamModel.modelName));
		Q_strncpyz(cg.teamModel.skinName, skin, sizeof(cg.teamModel.skinName));
		Q_strncpyz(cg.teamModelRed.modelName, modelStr, sizeof(cg.teamModelRed.modelName));
		Q_strncpyz(cg.teamModelRed.skinName, skin, sizeof(cg.teamModelRed.skinName));
		Q_strncpyz(cg.teamModelBlue.modelName, modelStr, sizeof(cg.teamModelBlue.modelName));
		Q_strncpyz(cg.teamModelBlue.skinName, skin, sizeof(cg.teamModelBlue.skinName));


		Q_strncpyz(cg.teamModel.headModelName, cg.teamModel.modelName, sizeof(cg.teamModel.headModelName));
		Q_strncpyz(cg.teamModel.headSkinName, cg.teamModel.skinName, sizeof(cg.teamModel.headSkinName));
		Q_strncpyz(cg.teamModelRed.headModelName, cg.teamModelRed.modelName, sizeof(cg.teamModelRed.headModelName));
		Q_strncpyz(cg.teamModelRed.headSkinName, cg.teamModelRed.skinName, sizeof(cg.teamModelRed.headSkinName));
		Q_strncpyz(cg.teamModelBlue.headModelName, cg.teamModelBlue.modelName, sizeof(cg.teamModelBlue.headModelName));
		Q_strncpyz(cg.teamModelBlue.headSkinName, cg.teamModelBlue.skinName, sizeof(cg.teamModelBlue.headSkinName));

		//cg.teamModel.team = TEAM_BLUE;
		//if (CG_RegisterClientModelname(&cg.teamModel, cg.teamModel.modelName, cg.teamModel.skinName, cg.teamModel.headModelName, cg.teamModel.headSkinName, "", useDefaultTeamSkins ? qfalse : qtrue)) {

		RegisterClientModelnameWithFallback(&cg.teamModel, cg.teamModel.modelName, cg.teamModel.skinName, cg.teamModel.headModelName, cg.teamModel.headSkinName, "", qtrue);

		cg.teamModelRed.team = TEAM_RED;
		RegisterClientModelnameWithFallback(&cg.teamModelRed, cg.teamModelRed.modelName, cg.teamModelRed.skinName, cg.teamModelRed.headModelName, cg.teamModelRed.headSkinName, "", qfalse);

		cg.teamModelBlue.team = TEAM_BLUE;
		RegisterClientModelnameWithFallback(&cg.teamModelBlue, cg.teamModelBlue.modelName, cg.teamModelBlue.skinName, cg.teamModelBlue.headModelName, cg.teamModelBlue.headSkinName, "", qfalse);

	if (*cg_teamHeadSkin.string  ||  *cg_teamTorsoSkin.string  ||  *cg_teamLegsSkin.string) {
		Com_Printf("reseting altskins\n");

		for (i = 0;  i < MAX_CLIENTS;  i++) {
			clientInfo_t *ci;

			ci = &cgs.clientinfo[i];
			ci->headSkinAlt = 0;
			ci->torsoSkinAlt = 0;
			ci->legsSkinAlt = 0;
		}
	}
}
Beispiel #2
0
void Wolfcam_AddPlayerWeapon (const refEntity_t *parent, centity_t *cent, int team)
{
	refEntity_t	gun;
	refEntity_t	barrel;
	refEntity_t	flash;
	vec3_t		angles;
	weapon_t	weaponNum;
	const weaponInfo_t	*weapon;
	centity_t	*nonPredictedCent;
//	int	col
	clientInfo_t	*ci;
	float flashSize;
	float dlight[3];
	float f;
	qboolean revertColors = qfalse;
	vec3_t origColor1;
	vec3_t origColor2;

	if (!cent->inCurrentSnapshot) {
		// this can happen with /follow which can stay in victim position
		// (frag hover)
		return;
	}

	ci = &cgs.clientinfo[ cent->currentState.clientNum ];
	weaponNum = cent->currentState.weapon;

	if (weaponNum <= WP_NONE  ||  weaponNum >= WP_NUM_WEAPONS) {
		return;
	}

	CG_RegisterWeapon( weaponNum );
	weapon = &cg_weapons[weaponNum];

	// add the weapon
	memset( &gun, 0, sizeof( gun ) );
	VectorCopy( parent->lightingOrigin, gun.lightingOrigin );
	gun.shadowPlane = parent->shadowPlane;
	gun.renderfx = parent->renderfx;

	// set custom shading for railgun refire rate
	if (0) {  //( ps ) {
	} else {
		if (weaponNum == WP_RAILGUN) {
			qboolean teamRail;
			qboolean enemyRail;

			if (cg_railUseOwnColors.integer  &&  CG_IsUs(ci)) {
				VectorCopy(ci->color1, origColor1);
				VectorCopy(ci->color2, origColor2);
				VectorCopy(cg.color1, ci->color1);
				VectorCopy(cg.color2, ci->color2);
				revertColors = qtrue;
			}

			teamRail = CG_IsTeammate(ci);
			enemyRail = CG_IsEnemy(ci);
			if (cgs.gametype < GT_TEAM) {
				if (!CG_IsUs(ci)) {
					if (*cg_enemyRailItemColor.string) {
						SC_ByteVec3ColorFromCvar(gun.shaderRGBA, &cg_enemyRailItemColor);
						gun.shaderRGBA[3] = 255;
					} else {
						gun.shaderRGBA[0] = 255 * ci->color1[0];
						gun.shaderRGBA[1] = 255 * ci->color1[1];
						gun.shaderRGBA[2] = 255 * ci->color1[2];
						gun.shaderRGBA[3] = 255;
					}
				} else {
					gun.shaderRGBA[0] = 255 * ci->color1[0];
					gun.shaderRGBA[1] = 255 * ci->color1[1];
					gun.shaderRGBA[2] = 255 * ci->color1[2];
					gun.shaderRGBA[3] = 255;
				}
			} else {  // team game
				if (!CG_IsUs(ci)  &&  teamRail) {
					if (cg_teamRailItemColorTeam.integer) {
						if (ci->team == TEAM_RED) {
							SC_ByteVec3ColorFromCvar(gun.shaderRGBA, &cg_weaponRedTeamColor);
						} else {
							SC_ByteVec3ColorFromCvar(gun.shaderRGBA, &cg_weaponBlueTeamColor);
						}
						gun.shaderRGBA[3] = 255;
					} else if (*cg_teamRailItemColor.string) {
						SC_ByteVec3ColorFromCvar(gun.shaderRGBA, &cg_teamRailItemColor);
						gun.shaderRGBA[3] = 255;
					} else {
						gun.shaderRGBA[0] = 255 * ci->color1[0];
						gun.shaderRGBA[1] = 255 * ci->color1[1];
						gun.shaderRGBA[2] = 255 * ci->color1[2];
						gun.shaderRGBA[3] = 255;
					}
				} else if (!CG_IsUs(ci)  &&  enemyRail) {
					if (cg_enemyRailItemColorTeam.integer) {
						if (ci->team == TEAM_RED) {
							SC_ByteVec3ColorFromCvar(gun.shaderRGBA, &cg_weaponRedTeamColor);
						} else {
							SC_ByteVec3ColorFromCvar(gun.shaderRGBA, &cg_weaponBlueTeamColor);
						}
						gun.shaderRGBA[3] = 255;
					} else if (*cg_enemyRailItemColor.string) {
						SC_ByteVec3ColorFromCvar(gun.shaderRGBA, &cg_enemyRailItemColor);
						gun.shaderRGBA[3] = 255;
					} else {
						gun.shaderRGBA[0] = 255 * ci->color1[0];
						gun.shaderRGBA[1] = 255 * ci->color1[1];
						gun.shaderRGBA[2] = 255 * ci->color1[2];
						gun.shaderRGBA[3] = 255;
					}
				} else {  // us
					gun.shaderRGBA[0] = 255 * ci->color1[0];
					gun.shaderRGBA[1] = 255 * ci->color1[1];
					gun.shaderRGBA[2] = 255 * ci->color1[2];
					gun.shaderRGBA[3] = 255;
				}
			}

			// end weapon == WP_RAILGUN
			//cent->pe.muzzleFlashTime
			//Com_Printf("yes....\n");
			//f = cg.time - (cent->pe.muzzleFlashTime + 1500);
			f = cg.time - (cent->pe.muzzleFlashTime + 1460);  // hack
			//Com_Printf("f %f\n", f);
			if (f < 0) {
				f = 1.0 - (f / -1500);
				gun.shaderRGBA[0] *= 0.314 * f;
				gun.shaderRGBA[1] *= 0.314 * f;
				gun.shaderRGBA[2] *= 0.314 * f;
			}
		}
	}

	gun.hModel = weapon->weaponModel;
	if (!gun.hModel) {
		//Com_Printf("no gun model '%s'\n", weapNamesCasual[weaponNum]);
		//FIXME grapple returns here
		//FIXME fx
		//CG_PositionEntityOnTag(&gun, parent, parent->hModel, "tag_weapon");
		//CG_CheckFxWeaponFlash(cent, weaponNum, gun.origin);
		//return;
	}

	CG_PositionEntityOnTag( &gun, parent, parent->hModel, "tag_weapon");

    CG_ScaleModel(&gun, cg_gunSize.value);

	// custom weapon shaders
	{
		vmCvar_t *firstPersonShaders[MAX_WEAPONS] = { NULL, &cg_firstPersonShaderWeaponGauntlet, &cg_firstPersonShaderWeaponMachineGun, &cg_firstPersonShaderWeaponShotgun, &cg_firstPersonShaderWeaponGrenadeLauncher, &cg_firstPersonShaderWeaponRocketLauncher, &cg_firstPersonShaderWeaponLightningGun, &cg_firstPersonShaderWeaponRailGun, &cg_firstPersonShaderWeaponPlasmaGun, &cg_firstPersonShaderWeaponBFG, &cg_firstPersonShaderWeaponGrapplingHook, &cg_firstPersonShaderWeaponNailGun, &cg_firstPersonShaderWeaponProximityLauncher, &cg_firstPersonShaderWeaponChainGun, &cg_firstPersonShaderWeaponHeavyMachineGun };

		if (firstPersonShaders[weaponNum]  &&  *(firstPersonShaders[weaponNum]->string)) {
			gun.customShader = trap_R_RegisterShader(firstPersonShaders[weaponNum]->string);
		}
	}

	if (gun.hModel) {
		if (cg_drawGun.integer > 2) {
			gun.customShader = cgs.media.ghostWeaponShader;
			gun.shaderRGBA[0] = 255;
			gun.shaderRGBA[1] = 255;
			gun.shaderRGBA[2] = 255;
			gun.shaderRGBA[3] = 255;
		}

		CG_AddWeaponWithPowerups( &gun, cent->currentState.powerups );
	}

	// add the spinning barrel
	if ( weapon->barrelModel ) {
		memset( &barrel, 0, sizeof( barrel ) );
		VectorCopy( parent->lightingOrigin, barrel.lightingOrigin );
		barrel.shadowPlane = parent->shadowPlane;
		barrel.renderfx = parent->renderfx;

		barrel.hModel = weapon->barrelModel;
		angles[YAW] = 0;
		angles[PITCH] = 0;
		angles[ROLL] = CG_MachinegunSpinAngle( cent );
		AnglesToAxis( angles, barrel.axis );

		CG_PositionRotatedEntityOnTag( &barrel, &gun, weapon->weaponModel, "tag_barrel" );

        CG_ScaleModel(&barrel, cg_gunSize.value);

		if (cg_drawGun.integer > 2) {
			barrel.customShader = cgs.media.ghostWeaponShader;
			barrel.shaderRGBA[0] = 255;
			barrel.shaderRGBA[1] = 255;
			barrel.shaderRGBA[2] = 255;
			barrel.shaderRGBA[3] = 255;
		}

		CG_AddWeaponWithPowerups( &barrel, cent->currentState.powerups );
	}

	// make sure we aren't looking at cg.predictedPlayerEntity for LG
	nonPredictedCent = &cg_entities[cent->currentState.clientNum];

#if 0
	// if the index of the nonPredictedCent is not the same as the clientNum
	// then this is a fake player (like on teh single player podiums), so
	// go ahead and use the cent
	if( ( nonPredictedCent - cg_entities ) != cent->currentState.clientNum ) {
		nonPredictedCent = cent;
		//Com_Printf("fake player %d  ->  %d\n", nonPredictedCent - cg_entities, cent->currentState.clientNum);
	}
#endif


	// add the flash
	//if ( ( weaponNum == WP_LIGHTNING || weaponNum == WP_GAUNTLET || weaponNum == WP_GRAPPLING_HOOK )  &&  (cent->currentState.eFlags & EF_FIRING)) {
	if ( ( weaponNum == WP_LIGHTNING || weaponNum == WP_GAUNTLET || weaponNum == WP_GRAPPLING_HOOK )  &&  (nonPredictedCent->currentState.eFlags & EF_FIRING)) {
		// && ( nonPredictedCent->currentState.eFlags & EF_FIRING ) ) {
		// continuous flash
	} else {
		//int ftime;

		if (weaponNum == WP_LIGHTNING  &&  cent->currentState.eFlags & EF_FIRING) {
			//Com_Printf("%f wtf ps %p\n", cg.ftime, ps);
		}
		// impulse flash
		//if ( cg.time - cent->pe.muzzleFlashTime > MUZZLE_FLASH_TIME && !cent->pe.railgunFlash ) {
		if ( cg.time - nonPredictedCent->pe.muzzleFlashTime > MUZZLE_FLASH_TIME && !nonPredictedCent->pe.railgunFlash ) {
			//Com_Printf("returning for %d (%d)\n", cent - cg_entities, cent->currentState.number);
			//goto bolt;
			// not called, in case code changes
			if (revertColors) {
				VectorCopy(origColor1, ci->color1);
				VectorCopy(origColor2, ci->color2);
			}
			return;
		}
	}

	memset( &flash, 0, sizeof( flash ) );
	VectorCopy( parent->lightingOrigin, flash.lightingOrigin );
	flash.shadowPlane = parent->shadowPlane;
	flash.renderfx = parent->renderfx;

	flash.hModel = weapon->flashModel;
	/*
	if (weaponNum == WP_HEAVY_MACHINEGUN) {
		flash.hModel = cg_weapons[WP_MACHINEGUN].flashModel;
	}
	*/

	if (!flash.hModel) {
		//Com_Printf("no flash model '%s'\n", weapNamesCasual[weaponNum]);
		//FIXME fx
		//return;
	}
	angles[YAW] = 0;
	angles[PITCH] = 0;
	angles[ROLL] = crandom() * 10;
	AnglesToAxis( angles, flash.axis );

	// colorize the railgun blast
	if ( weaponNum == WP_RAILGUN ) {
		//clientInfo_t	*ci;

		//ci = &cgs.clientinfo[ cent->currentState.clientNum ];
		if (cg_railUseOwnColors.integer  &&  CG_IsUs(ci)) {
			flash.shaderRGBA[0] = 255 * cg.color1[0];
			flash.shaderRGBA[1] = 255 * cg.color1[1];
			flash.shaderRGBA[2] = 255 * cg.color1[2];
		} else {
			flash.shaderRGBA[0] = 255 * ci->color1[0];
			flash.shaderRGBA[1] = 255 * ci->color1[1];
			flash.shaderRGBA[2] = 255 * ci->color1[2];
		}
	}

	if (0) {  //(weapon->hasFlashScript) {
		//CG_RunQ3mmeFlashScript(weapon, dlight, flash.shaderRGBA, &flashSize);
		//VectorCopy(flash.origin, ScriptVars.origin);
		//CG_RunQ3mmeScript((char *)weapon->flashScript);
		//return;
	} else {
		dlight[0] = weapon->flashDlightColor[0];
		dlight[1] = weapon->flashDlightColor[1];
		dlight[2] = weapon->flashDlightColor[2];


		/*
		flash.shaderRGBA[0] = 255;
		flash.shaderRGBA[1] = 255;
		flash.shaderRGBA[2] = 255;
		flash.shaderRGBA[3] = 0;
		*/

		flashSize = 300 + (rand()&31);
	}

	CG_PositionRotatedEntityOnTag( &flash, &gun, weapon->weaponModel, "tag_flash");
	//Com_Printf("ps:%d  %p\n", ps != NULL, cent);

	if (0) {  //(cent == &cg.predictedPlayerEntity  &&  !cg.renderingThirdPerson  &&  !ps) {
		// don't run flash script twice for first person view
	} else if (EffectScripts.weapons[weaponNum].hasFlashScript) {
		//CG_RunQ3mmeFlashScript(weapon, dlight, flash.shaderRGBA, &flashSize);
		//memset(&ScriptVars, 0, sizeof(ScriptVars));
		//CG_Printf("addplayerweapon()  flash script cent %d\n", cent - cg_entities);
		CG_ResetScriptVars();
		CG_CopyPlayerDataToScriptData(cent);
		VectorCopy(flash.origin, ScriptVars.origin);
		VectorCopy(flash.origin, ScriptVars.parentOrigin);

		VectorCopy(cent->lastFlashIntervalPosition, ScriptVars.lastIntervalPosition);
		ScriptVars.lastIntervalTime = cent->lastFlashIntervalTime;
		VectorCopy(cent->lastFlashDistancePosition, ScriptVars.lastDistancePosition);
		ScriptVars.lastDistanceTime = cent->lastFlashDistanceTime;

		CG_RunQ3mmeScript((char *)EffectScripts.weapons[weaponNum].flashScript, NULL);

		VectorCopy(ScriptVars.lastIntervalPosition, cent->lastFlashIntervalPosition);
		cent->lastFlashIntervalTime = ScriptVars.lastIntervalTime;
		VectorCopy(ScriptVars.lastDistancePosition, cent->lastFlashDistancePosition);
		cent->lastFlashDistanceTime = ScriptVars.lastDistanceTime;
		//return;
	}

	if (!cg_muzzleFlash.integer) {
		// pass
	} else {
		if (flash.hModel) {
			CG_AddRefEntity(&flash);
		}
	}

	// bolt:
	if (1) {
		// add lightning bolt
		if (1) {
			CG_LightningBolt( nonPredictedCent, flash.origin );

			//Com_Printf("adding bolt\n");
			// add rail trail
			CG_SpawnRailTrail( cent, flash.origin );

			//if ((dlight[0]  ||  dlight[1]  ||  dlight[2])  &&  !weapon->hasFlashScript) {
			if ((dlight[0]  ||  dlight[1]  ||  dlight[2])  &&  !EffectScripts.weapons[weaponNum].hasFlashScript) {
				trap_R_AddLightToScene(flash.origin, flashSize, dlight[0], dlight[1], dlight[2]);
			}
		}
	} else {
		//Com_Printf("%f no...\n", cg.ftime);
	}

	if (revertColors) {
		VectorCopy(origColor1, ci->color1);
		VectorCopy(origColor2, ci->color2);
	}
}
Beispiel #3
0
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;
		}
	}
}