示例#1
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);
	}
}
示例#2
0
// Used for both the view weapon (ps is valid) and the world modelother character models (ps is NULL)
// The main player will have this called for BOTH cases, so effects like light and sound should only be done on the
//	world model case.
void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent, int team, vector3 *newAngles, qboolean thirdPerson ) {
	refEntity_t gun, barrel, flash;
	vector3 angles;
	weapon_t weaponNum;
	weaponInfo_t *weapon;
	centity_t *nonPredictedCent;

	if ( !thirdPerson && cg_fakeGun.integer ) {
		weaponNum = (weapon_t)cg_fakeGun.integer;
	}
	else {
		weaponNum = (weapon_t)cent->currentState.weapon;
	}

	if ( weaponNum == WP_EMPLACED_GUN )
		return;

	// spectator mode, don't draw it...
	if ( cg.predictedPlayerState.pm_type == PM_SPECTATOR
		&& cent->currentState.number == cg.predictedPlayerState.clientNum )
	{
		return;
	}

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

	memset( &gun, 0, sizeof(gun) );

	// only do this if we are in first person, since world weapons are now handled on the server by Ghoul2
	if ( !thirdPerson ) {
		// add the weapon
		VectorCopy( &parent->lightingOrigin, &gun.lightingOrigin );
		gun.shadowPlane = parent->shadowPlane;
		gun.renderfx = parent->renderfx;

		// this player, in first person view
		if ( ps )
			gun.hModel = weapon->viewModel;
		else
			gun.hModel = weapon->weaponModel;
		if ( !gun.hModel )
			return;

		if ( !ps ) {
			// add weapon ready sound
			if ( (cent->currentState.eFlags & EF_FIRING) && weapon->firingSound ) {
				trap->S_AddLoopingSound( cent->currentState.number, &cent->lerpOrigin, &vec3_origin,
					weapon->firingSound
				);
			}
			else if ( weapon->readySound ) {
				trap->S_AddLoopingSound( cent->currentState.number, &cent->lerpOrigin, &vec3_origin,
					weapon->readySound
				);
			}
		}

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

		if ( !CG_IsMindTricked( cent->currentState.trickedEntIndex, cg.snap->ps.clientNum ) ) {
			// don't draw the weapon if the player is invisible
			CG_AddWeaponWithPowerups( &gun, cent->currentState.powerups );
		}

		if ( weaponNum == WP_STUN_BATON ) {
			int i;

			for ( i = 0; i < 3; i++ ) {
				memset( &barrel, 0, sizeof(barrel) );
				VectorCopy( &parent->lightingOrigin, &barrel.lightingOrigin );
				barrel.shadowPlane = parent->shadowPlane;
				barrel.renderfx = parent->renderfx;

				if ( i == 0 ) {
					barrel.hModel = trap->R_RegisterModel( "models/weapons2/stun_baton/baton_barrel.md3" );
				}
				else if ( i == 1 ) {
					barrel.hModel = trap->R_RegisterModel( "models/weapons2/stun_baton/baton_barrel2.md3" );
				}
				else {
					barrel.hModel = trap->R_RegisterModel( "models/weapons2/stun_baton/baton_barrel3.md3" );
				}
				angles.yaw = 0;
				angles.pitch = 0;
				angles.roll = 0;

				AnglesToAxis( &angles, barrel.axis );

				if ( i == 0 ) {
					CG_PositionRotatedEntityOnTag( &barrel, parent, weapon->handsModel, "tag_barrel" );
				}
				else if ( i == 1 ) {
					CG_PositionRotatedEntityOnTag( &barrel, parent, weapon->handsModel, "tag_barrel2" );
				}
				else {
					CG_PositionRotatedEntityOnTag( &barrel, parent, weapon->handsModel, "tag_barrel3" );
				}
				CG_AddWeaponWithPowerups( &barrel, cent->currentState.powerups );
			}
		}
		else {
			// 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 = 0;

				AnglesToAxis( &angles, barrel.axis );

				CG_PositionRotatedEntityOnTag( &barrel, parent, weapon->handsModel, "tag_barrel" );

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

	memset( &flash, 0, sizeof(flash) );
	CG_PositionEntityOnTag( &flash, &gun, gun.hModel, "tag_flash" );

	VectorCopy( &flash.origin, &cg.lastFPFlashPoint );

	// Do special charge bits
	// Make the guns do their charging visual in True View.
	if ( (ps || cg.renderingThirdPerson || cg.predictedPlayerState.clientNum != cent->currentState.number || cg_trueGuns.integer) &&
		((cent->currentState.modelindex2 == WEAPON_CHARGING_ALT && weaponNum == WP_BRYAR_PISTOL) ||
		(cent->currentState.modelindex2 == WEAPON_CHARGING_ALT && weaponNum == WP_BRYAR_OLD) ||
		(weaponNum == WP_BOWCASTER && cent->currentState.modelindex2 == WEAPON_CHARGING) ||
		(weaponNum == WP_DEMP2 && cent->currentState.modelindex2 == WEAPON_CHARGING_ALT)) ) {
		int shader = 0;
		float val = 0.0f;
		float scale = 1.0f;
		addspriteArgStruct_t fxSArgs;
		vector3 flashorigin, flashdir;

		if ( !thirdPerson ) {
			VectorCopy( &flash.origin, &flashorigin );
			VectorCopy( &flash.axis[0], &flashdir );
		}
		else {
			mdxaBone_t boltMatrix;

			// it's quite possible that we may have have no weapon model and be in a valid state, so return here if this is the case
			if ( !trap->G2API_HasGhoul2ModelOnIndex( &(cent->ghoul2), 1 ) )
				return;

			// Couldn't find bolt point.
			if ( !trap->G2API_GetBoltMatrix( cent->ghoul2, 1, 0, &boltMatrix, newAngles, &cent->lerpOrigin, cg.time,
				cgs.gameModels, &cent->modelScale ) ) {
				return;
			}

			BG_GiveMeVectorFromMatrix( &boltMatrix, ORIGIN, &flashorigin );
			BG_GiveMeVectorFromMatrix( &boltMatrix, POSITIVE_X, &flashdir );
		}

		if ( weaponNum == WP_BRYAR_PISTOL || weaponNum == WP_BRYAR_OLD ) {
			// Hardcoded max charge time of 1 second
			val = (cg.time - cent->currentState.constantLight) * 0.001f;
			shader = media.gfx.world.bryarFrontFlash;
		}
		else if ( weaponNum == WP_BOWCASTER ) {
			// Hardcoded max charge time of 1 second
			val = (cg.time - cent->currentState.constantLight) * 0.001f;
			shader = media.gfx.world.greenFrontFlash;
		}
		else if ( weaponNum == WP_DEMP2 ) {
			val = (cg.time - cent->currentState.constantLight) * 0.001f;
			shader = media.gfx.world.lightningFlash;
			scale = 1.75f;
		}

		if ( val < 0.0f )
			val = 0.0f;
		else if ( val > 1.0f ) {
			val = 1.0f;
			if ( ps && cent->currentState.number == ps->clientNum )
				CGCam_Shake( 0.2f, 100 );
		}
		else if ( ps && cent->currentState.number == ps->clientNum )
			CGCam_Shake( val * val * 0.6f, 100 );

		val += random() * 0.5f;

		VectorCopy( &flashorigin, &fxSArgs.origin );
		VectorClear( &fxSArgs.vel );
		VectorClear( &fxSArgs.accel );
		fxSArgs.scale = 3.0f*val*scale;
		fxSArgs.dscale = 0.0f;
		fxSArgs.sAlpha = 0.7f;
		fxSArgs.eAlpha = 0.7f;
		fxSArgs.rotation = random() * 360;
		fxSArgs.bounce = 0.0f;
		fxSArgs.life = 1.0f;
		fxSArgs.shader = shader;
		fxSArgs.flags = 0x08000000;

		trap->FX_AddSprite( &fxSArgs );
	}

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

	// if the index of the nonPredictedCent is not the same as the clientNum then this is a fake player (like on the
	//	single player podiums), so go ahead and use the cent
	if ( nonPredictedCent - cg_entities != cent->currentState.clientNum )
		nonPredictedCent = cent;

	// add the flash
	if ( weaponNum != WP_DEMP2 || (nonPredictedCent->currentState.eFlags & EF_FIRING) ) {
		// impulse flash
		if ( cg.time - cent->muzzleFlashTime > MUZZLE_FLASH_TIME )
			return;
	}

	if ( ps || cg.renderingThirdPerson || cg_trueGuns.integer
		|| cent->currentState.number != cg.predictedPlayerState.clientNum ) {
		// Make sure we don't do the thirdperson model effects for the local player if we're in first person
		vector3 flashorigin, flashdir;
		refEntity_t	tpflash;

		memset( &tpflash, 0, sizeof(tpflash) );

		if ( !thirdPerson ) {
			CG_PositionEntityOnTag( &tpflash, &gun, gun.hModel, "tag_flash" );
			VectorCopy( &tpflash.origin, &flashorigin );
			VectorCopy( &tpflash.axis[0], &flashdir );
		}
		else {
			mdxaBone_t boltMatrix;

			// it's quite possible that we may have have no weapon model and be in a valid state, so return here if this is the case
			if ( !trap->G2API_HasGhoul2ModelOnIndex( &(cent->ghoul2), 1 ) )
				return;

			// Couldn't find bolt point.
			if ( !trap->G2API_GetBoltMatrix( cent->ghoul2, 1, 0, &boltMatrix, newAngles, &cent->lerpOrigin, cg.time, cgs.gameModels, &cent->modelScale ) )
				return;

			BG_GiveMeVectorFromMatrix( &boltMatrix, ORIGIN, &flashorigin );
			BG_GiveMeVectorFromMatrix( &boltMatrix, POSITIVE_X, &flashdir );
		}

		if ( cg.time - cent->muzzleFlashTime <= MUZZLE_FLASH_TIME + 10 ) {
			// Handle muzzle flashes
			if ( cent->currentState.eFlags & EF_ALT_FIRING ) {
				// Check the alt firing first.
				if ( weapon->altMuzzleEffect ) {
					if ( !thirdPerson )
						trap->FX_PlayEntityEffectID( weapon->altMuzzleEffect, &flashorigin, tpflash.axis, -1, -1, -1, -1 );
					else
						trap->FX_PlayEffectID( weapon->altMuzzleEffect, &flashorigin, &flashdir, -1, -1, qfalse );
				}
			}
			else {
				// Regular firing
				if ( weapon->muzzleEffect ) {
					if ( !thirdPerson )
						trap->FX_PlayEntityEffectID( weapon->muzzleEffect, &flashorigin, tpflash.axis, -1, -1, -1, -1 );
					else
						trap->FX_PlayEffectID( weapon->muzzleEffect, &flashorigin, &flashdir, -1, -1, qfalse );
				}
			}
		}

		if ( weapon->flashDlightColor.r || weapon->flashDlightColor.g || weapon->flashDlightColor.b ) {
			trap->R_AddLightToScene( &flashorigin, 300 + (rand() & 31), weapon->flashDlightColor.r, weapon->flashDlightColor.g,
				weapon->flashDlightColor.b );
		}
	}
}
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
        }
    }
}