void FX_RegenBeam( vec3_t origin, vec3_t dir, int clientNum, qboolean alt_fire ) { trace_t tr; vec3_t end; VectorMA( origin, REGEN_BEAM_LENGTH, dir, end ); CG_Trace( &tr, origin, NULL, NULL, end, clientNum, CONTENTS_SOLID ); trap_R_AddLightToScene( origin, 30, 235.0f / 255, 74.0f / 255, 102.0f / 255 ); if ( tr.fraction != 1.0f ) { float radius; if ( alt_fire ) radius = flrandom(1.5f, 3.0f) * (1.0 - (tr.fraction*0.3)); else radius = flrandom(0.5f, 1.5f) * (1.0 - (tr.fraction*0.3)); if ( !radius ) return; CG_ImpactMark( cgs.media.regenDecal, tr.endpos, tr.plane.normal, 0, 1, 1, 1, 0.2*(1.0-tr.fraction), qfalse, radius, qtrue ); trap_R_AddLightToScene( origin, radius*5, 235.0f / 255, 74.0f / 255, 102.0f / 255 ); } }
/* ================ CG_AddExplosion ================ */ static void CG_AddExplosion( localEntity_t *ex ) { refEntity_t *ent; ent = &ex->refEntity; // add the entity CG_AddRefEntityWithMinLight(ent); // add the dlight if ( ex->light ) { float light; light = (float)( cg.time - ex->startTime ) / ( ex->endTime - ex->startTime ); if ( light < 0.5 ) { light = 1.0; } else { light = 1.0 - ( light - 0.5 ) * 2; } if ( cg_fadeExplosions.integer ) { trap_R_AddLightToScene(ent->origin, ex->light, light, ex->lightColor[0], ex->lightColor[1], ex->lightColor[2] ); } else { light = ex->light * light; trap_R_AddLightToScene(ent->origin, light, 1.0f, ex->lightColor[0], ex->lightColor[1], ex->lightColor[2] ); } } }
//TiM - Beam FX for the Neutrino Probe weapon void FX_ProbeBeam( vec3_t origin, vec3_t dir, int clientNum, qboolean alt_fire ) { trace_t tr; refEntity_t beam; vec3_t end; float scale; memset( &beam, 0, sizeof( beam ) ); if ( alt_fire ) scale = flrandom(7.0f, 12.0f); else scale = Q_fabs( 12.0f * sin( cg.time * 0.1f ) ); VectorMA( origin, PROBE_BEAM_LENGTH, dir, end ); CG_Trace( &tr, origin, NULL, NULL, end, clientNum, CONTENTS_SOLID ); trap_R_AddLightToScene( origin, 20, 114.0f / 255, 164.0f / 255, 1.0f ); VectorCopy( origin, beam.origin); VectorCopy( tr.endpos, beam.oldorigin ); beam.reType = RT_LINE; beam.customShader = cgs.media.probeBeam; beam.shaderRGBA[0] = 0xff; beam.shaderRGBA[1] = 0xff; beam.shaderRGBA[2] = 0xff; beam.shaderRGBA[3] = 0xff; AxisClear( beam.axis ); beam.data.line.width = scale*0.1; beam.data.line.width2 = scale; beam.data.line.stscale = 1.0; trap_R_AddRefEntityToScene( &beam ); if ( tr.fraction != 1.0f ) { float radius; if ( alt_fire ) radius = flrandom(1.5f, 3.0f) * (1.0 - (tr.fraction*0.3)); else radius = flrandom(0.5f, 1.5f) * (1.0 - (tr.fraction*0.3)); if ( !radius ) return; CG_ImpactMark( cgs.media.probeDecal, tr.endpos, tr.plane.normal, 0, 1, 1, 1, 0.2*(1.0-tr.fraction), qfalse, radius, qtrue ); trap_R_AddLightToScene( origin, radius*5, 114.0f / 255, 164.0f / 255, 1.0f ); } }
/* ================ CG_AddExplosion ================ */ static void CG_AddExplosion( localEntity_t *ex ) { refEntity_t *ent; float life; ent = &ex->refEntity; life = (float)( cg.time - ex->startTime ) / ( ex->endTime - ex->startTime ); // get colors ent->shaderRGBA[0] = 255 * ex->color[0] * ( 1.0 - life ); ent->shaderRGBA[1] = 255 * ex->color[1] * ( 1.0 - life ); ent->shaderRGBA[2] = 255 * ex->color[2] * ( 1.0 - life ); ent->shaderRGBA[3] = 255 * ex->color[3] * ( 1.0 - life ); // add the entity trap_R_AddRefEntityToScene(ent); // add the dlight if ( ex->light ) { float light; light = life; if ( light < 0.5 ) { light = 1.0; } else { light = 1.0 - ( light - 0.5 ) * 2; } light = ex->light * light; trap_R_AddLightToScene(ent->origin, light, ex->lightColor[0], ex->lightColor[1], ex->lightColor[2] ); } }
/* ================ CG_AddExplosion ================ */ static void CG_AddExplosion( localEntity_t *ex ) { refEntity_t *ent; ent = &ex->refEntity; // add the entity // RF, don't add if shader is invalid if ( ent->customShader >= 0 ) { trap_R_AddRefEntityToScene( ent ); } // add the dlight if ( ex->light ) { float light; light = (float)( cg.time - ex->startTime ) / ( ex->endTime - ex->startTime ); if ( light < 0.5 ) { light = 1.0; } else { light = 1.0 - ( light - 0.5 ) * 2; } light = ex->light * light; trap_R_AddLightToScene( ent->origin, light, ex->lightColor[0], ex->lightColor[1], ex->lightColor[2], 0 ); } }
/* ======================================================================================================================================= CG_AddExplosion ======================================================================================================================================= */ static void CG_AddExplosion(localEntity_t *le) { refEntity_t *ent; ent = &le->refEntity; // add the entity trap_R_AddRefEntityToScene(ent); // add the dlight if (le->light) { float light; float radius; float intensity; light = (float)(cg.time - le->startTime) / (le->endTime - le->startTime); if (light < 0.5) { light = 1.0; } else { light = 1.0 - (light - 0.5) * 2; } if (cg_fadeExplosions.integer) { radius = le->light; intensity = light; } else { radius = le->light * light; intensity = 1; } trap_R_AddLightToScene(le->refEntity.origin, radius, intensity, le->lightColor[0], le->lightColor[1], le->lightColor[2], 0); } }
/* ================ CG_AddSpriteExplosion ================ */ static void CG_AddSpriteExplosion( localEntity_t *le ) { refEntity_t re; float c; re = le->refEntity; c = ( le->endTime - cg.time ) / ( float ) ( le->endTime - le->startTime ); if ( c > 1 ) { c = 1.0; // can happen during connection problems } re.shaderRGBA[0] = 0xff; re.shaderRGBA[1] = 0xff; re.shaderRGBA[2] = 0xff; re.shaderRGBA[3] = 0xff * c * 0.33; re.reType = RT_SPRITE; re.radius = 42 * ( 1.0 - c ) + 30; trap_R_AddRefEntityToScene( &re ); // add the dlight if ( le->light ) { float light; light = (float)( cg.time - le->startTime ) / ( le->endTime - le->startTime ); if ( light < 0.5 ) { light = 1.0; } else { light = 1.0 - ( light - 0.5 ) * 2; } light = le->light * light; trap_R_AddLightToScene(re.origin, light, le->lightColor[0], le->lightColor[1], le->lightColor[2] ); } }
/* * CG_AddDlights */ void CG_AddDlights( void ) { int i; cdlight_t *dl; for( i = 0, dl = cg_dlights; i < cg_numDlights; i++, dl++ ) trap_R_AddLightToScene( dl->origin, dl->radius, dl->color[0], dl->color[1], dl->color[2] ); cg_numDlights = 0; }
/* ================ CG_AddSpriteExplosion ================ */ static void CG_AddSpriteExplosion( localEntity_t *le ) { refEntity_t re; float c; re = le->refEntity; c = ( le->endTime - cg.time ) / ( float ) ( le->endTime - le->startTime ); if ( c > 1 ) { c = 1.0; // can happen during connection problems } re.shaderRGBA[0] = 0xff; re.shaderRGBA[1] = 0xff; re.shaderRGBA[2] = 0xff; re.shaderRGBA[3] = 0xff * c * 0.33; re.reType = RT_SPRITE; re.radius = 42 * ( 1.0 - c ) + 30; // Ridah, move away from surface VectorMA( le->pos.trBase, ( 1.0 - c ), le->pos.trDelta, re.origin ); // done. // RF, don't add if shader is invalid if ( re.customShader >= 0 ) { trap_R_AddRefEntityToScene( &re ); } // add the dlight if ( le->light ) { float light; // Ridah, modified this so the light fades out rather than shrinking /* light = (float)( cg.time - le->startTime ) / ( le->endTime - le->startTime ); if ( light < 0.5 ) { light = 1.0; } else { light = 1.0 - ( light - 0.5 ) * 2; } light = le->light * light; trap_R_AddLightToScene(re.origin, light, le->lightColor[0], le->lightColor[1], le->lightColor[2], 0 ); */ light = (float)( cg.time - le->startTime ) / ( le->endTime - le->startTime ); if ( light < 0.5 ) { light = 1.0; } else { light = 1.0 - ( light - 0.5 ) * 2; } trap_R_AddLightToScene( re.origin, le->light, light * le->lightColor[0], light * le->lightColor[1], light * le->lightColor[2], 0 ); // done. } }
/*=================== CG_Aura_AddDLight ===================*/ static void CG_Aura_AddDLight( centity_t *player, auraState_t *state, auraConfig_t *config){ vec3_t lightPos; // add dynamic light when necessary if(state->isActive ||(state->lightAmt > config->lightMin)){ // Since lerpOrigin is the lightingOrigin for the player, this will add a backsplash light for the aura. VectorAdd( player->lerpOrigin, cg.refdef.viewaxis[0], lightPos); trap_R_AddLightToScene( lightPos, state->lightAmt, // +(cos(cg.time / 50.0f) * state->lightDev), config->lightColor[0] * state->modulate, config->lightColor[1] * state->modulate, config->lightColor[2] * state->modulate); } }
/* ================ CG_AddExplosion ================ */ void CG_AddExplosion( localEntity_t *ex ) { refEntity_t *ent; ent = &ex->refEntity; // calculate model frame if ( ex->lifeRate > 0 ) { float frac = (cg.time - ex->startTime) * ex->lifeRate; int f = floor(frac); if ( f < 0 ) { f = 0; } ent->frame = f + 1; ent->oldframe = f; ent->backlerp = 1.0 - ( frac - f ); ent->renderfx |= RF_CAP_FRAMES; } // Explosions with zero shaders (using model default shader) don't fade, so // allow fading when this flag is set. if ( ex->leFlags & LEF_FADE_RGB ) { float frac = (float)( cg.time - ex->startTime )/(float)( ex->endTime - ex->startTime ); ent->shaderRGBA[0] = ent->shaderRGBA[1] = ent->shaderRGBA[2] = frac * 255; ent->shaderRGBA[3] = 255; } // add the entity trap_R_AddRefEntityToScene(ent); // add the dlight if ( ex->light ) { float light; light = (float)( cg.time - ex->startTime ) / ( ex->endTime - ex->startTime ); if ( light < 0.5 ) { light = 1.0; } else { light = 1.0 - ( light - 0.5 ) * 2; } light = ex->light * light; trap_R_AddLightToScene(ent->origin, light, ex->lightColor[0], ex->lightColor[1], ex->lightColor[2] ); } }
/* =============== CG_StartShadowCaster Helper function to add a inverse dynamic light to create shadows for the following models. =============== */ void CG_StartShadowCaster( vec3_t origin, vec3_t mins, vec3_t maxs ) { vec3_t ambientLight, directedLight, lightDir; vec3_t lightPos; trace_t tr; vec3_t traceMins = { -3.0f, -3.0f, -3.0f }; vec3_t traceMaxs = { 3.0f, 3.0f, 3.0f }; float maxLightDist = Distance( maxs, mins ); // find a point to place the light source by tracing in the // average light direction trap_R_LightForPoint( origin, ambientLight, directedLight, lightDir ); VectorMA( origin, 3.0f * maxLightDist, lightDir, lightPos ); CG_Trace( &tr, origin, traceMins, traceMaxs, lightPos, 0, MASK_OPAQUE, 0 ); if( !tr.startsolid ) { VectorCopy( tr.endpos, lightPos ); } trap_R_AddLightToScene( lightPos, 2.0f * Distance( lightPos, origin ), 3.0f, directedLight[0], directedLight[1], directedLight[2], 0, REF_RESTRICT_DLIGHT | REF_INVERSE_DLIGHT ); }
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); } }
/* =============== CG_EndShadowCaster Helper function to terminate the list of models for the last shadow caster. following models. =============== */ void CG_EndShadowCaster( void ) { trap_R_AddLightToScene( vec3_origin, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, 0 ); }
/* ================ CG_AddMissile ================ */ static void CG_AddMissile( localEntity_t *le ) { refEntity_t *re; const weaponInfo_t *weapon; trace_t trace; centity_t *other; qboolean inWater; // just existing for server entity deletion if ( le->leFlags & LEF_FINISHED ) { return; } // get weapon info if ( le->ti.weapon > WP_NUM_WEAPONS ) { le->ti.weapon = 0; } weapon = &cg_weapons[le->ti.weapon]; re = &le->refEntity; // calculate position BG_EvaluateTrajectory( &le->pos, cg.time, re->origin ); // special case for flames if ( re->reType == RT_SPRITE ) { int deltaTime; // check for water if ( trap_CM_PointContents( re->origin, 0 ) & CONTENTS_WATER ) { // do a trace to get water surface normals CG_Trace( &trace, re->oldorigin, NULL, NULL, re->origin, le->owner, MASK_WATER ); CG_FreeLocalEntity( le ); CG_MakeExplosion( trace.endpos, trace.plane.normal, cgs.media.ringFlashModel, cgs.media.vaporShader, 500, qfalse, qtrue ); return; } // change radius over time deltaTime = cg.time - le->startTime; re->radius = deltaTime * deltaTime * ( random()*0.4f + 0.8f ) / 2000.0f + 9; // do a trace sometimes if ( le->ti.trailTime++ > 5 ) { le->ti.trailTime = 0; CG_Trace( &trace, re->oldorigin, NULL, NULL, re->origin, le->owner, MASK_SHOT ); VectorCopy( re->origin, re->oldorigin ); // hit something if ( trace.fraction < 1.0 ) { CG_MissileHitWall( le->ti.weapon, 0, trace.endpos, trace.plane.normal, IMPACTSOUND_DEFAULT ); CG_FreeLocalEntity( le ); return; } } // add to refresh list trap_R_AddRefEntityToScene( re ); return; } // add trails if ( weapon->missileTrailFunc ) weapon->missileTrailFunc( &le->ti, cg.time ); // add dynamic light if ( weapon->missileDlight ) { trap_R_AddLightToScene( re->origin, weapon->missileDlight, weapon->missileDlightColor[0], weapon->missileDlightColor[1], weapon->missileDlightColor[2] ); } // flicker between two skins re->skinNum = cg.clientFrame & 1; // convert direction of travel into axis if ( VectorNormalize2( le->pos.trDelta, re->axis[0] ) == 0 ) { re->axis[0][2] = 1; } // spin as it moves if ( le->pos.trType != TR_STATIONARY ) { if ( le->pos.trType == TR_GRAVITY ) { RotateAroundDirection( re->axis, cg.time / 4 ); } else if ( le->pos.trType == TR_WATER_GRAVITY ) { RotateAroundDirection( re->axis, cg.time / 8 ); } else { RotateAroundDirection( re->axis, cg.time ); } } else { RotateAroundDirection( re->axis, 0 ); } // trace a line from previous position to new position CG_Trace( &trace, re->oldorigin, NULL, NULL, re->origin, le->owner, MASK_SHOT ); VectorCopy( re->origin, re->oldorigin ); // draw BIG grenades if ( weLi[le->ti.weapon].category == CT_EXPLOSIVE ) { AxisScale( re->axis, GRENADE_SCALE, re->axis ); } if ( trace.fraction != 1.0 ) { // hit the sky or something like that if ( trace.surfaceFlags & SURF_NOIMPACT ) { le->leFlags |= LEF_FINISHED; le->endTime = cg.time + 500; return; } // impact other = &cg_entities[trace.entityNum]; if ( le->bounceFactor > 0 && ( le->bounceFactor == BOUNCE_FACTOR_HALF || other->currentState.eType != ET_PLAYER ) ) { // reflect the velocity on the trace plane CG_ReflectVelocity( le, &trace ); if ( cg.predictedImpacts < MAX_PREDICTED_IMPACTS ) { cg.predictedImpacts++; cg.predictedImpactsDecTime = cg.time; } // do bounce sound if ( rand() & 1 ) { trap_S_StartSound( le->pos.trBase, 0, CHAN_AUTO, cgs.media.hgrenb1aSound ); } else { trap_S_StartSound( le->pos.trBase, 0, CHAN_AUTO, cgs.media.hgrenb2aSound ); } } else { // explode missile if ( cg.predictedImpacts < MAX_PREDICTED_IMPACTS ) { cg.predictedImpacts++; cg.predictedImpactsDecTime = cg.time; } if ( other->currentState.eType == ET_PLAYER ) { CG_MissileHitPlayer( le->ti.weapon, 0, trace.endpos, trace.plane.normal, trace.entityNum ); } else if ( !(trace.surfaceFlags & SURF_NOIMPACT) ) { CG_MissileHitWall( le->ti.weapon, 0, trace.endpos, trace.plane.normal, (trace.surfaceFlags & SURF_METALSTEPS) ? IMPACTSOUND_METAL : IMPACTSOUND_DEFAULT ); } // store the entity for deleting the server entity le->leFlags |= LEF_FINISHED; le->endTime = cg.time + 500; return; } } // check for medium change if ( trap_CM_PointContents( re->origin, 0 ) & CONTENTS_WATER ) inWater = qtrue; else inWater = qfalse; if ( ( !inWater && le->pos.trType == TR_WATER_GRAVITY ) || ( inWater && le->pos.trType == TR_GRAVITY ) ) { // setup new tr vec3_t newDelta; BG_EvaluateTrajectoryDelta( &le->pos, cg.time, newDelta ); VectorCopy( re->origin, le->pos.trBase ); VectorCopy( newDelta, le->pos.trDelta ); le->pos.trTime = cg.time; if ( inWater ) le->pos.trType = TR_WATER_GRAVITY; else le->pos.trType = TR_GRAVITY; } // add to refresh list trap_R_AddRefEntityToScene( re ); }
/* =============== UI_DrawPlayer =============== */ void UI_DrawPlayer( float x, float y, float w, float h, uiPlayerInfo_t *pi, int time ) { refdef_t refdef; refEntity_t legs = {0}; refEntity_t torso = {0}; refEntity_t head = {0}; #ifdef TA_WEAPSYS refEntity_t gun[MAX_HANDS] = {0}; #else refEntity_t gun = {0}; #endif refEntity_t barrel = {0}; refEntity_t flash = {0}; vec3_t origin; int renderfx; vec3_t mins = {-16, -16, -24}; vec3_t maxs = {16, 16, 32}; float len; float xx; float xscale; float yscale; #ifdef TA_WEAPSYS int i; vec3_t angles; #ifdef TURTLEARENA // PLAYERS char *newTagNames[3] = { "tag_hand_primary", "tag_hand_secondary", NULL }; #endif char *originalTagNames[3] = { "tag_weapon", "tag_flag", NULL }; #endif if ( !pi->legsModel || !pi->torsoModel || !pi->headModel #ifdef TA_PLAYERSYS || !pi->playercfg.animations[0].numFrames ) { #else || !pi->animations[0].numFrames ) { #endif return; } // this allows the ui to cache the player model on the main menu if (w == 0 || h == 0) { return; } dp_realtime = time; if ( pi->pendingWeapon != WP_NUM_WEAPONS && dp_realtime > pi->weaponTimer ) { pi->weapon = pi->pendingWeapon; pi->lastWeapon = pi->pendingWeapon; pi->pendingWeapon = WP_NUM_WEAPONS; pi->weaponTimer = 0; #ifndef TA_WEAPSYS_EX if( pi->currentWeapon != pi->weapon ) { trap_S_StartLocalSound( weaponChangeSound, CHAN_LOCAL ); } #endif } CG_AdjustFrom640( &x, &y, &w, &h ); y -= jumpHeight; memset( &refdef, 0, sizeof( refdef ) ); memset( &legs, 0, sizeof(legs) ); memset( &torso, 0, sizeof(torso) ); memset( &head, 0, sizeof(head) ); refdef.rdflags = RDF_NOWORLDMODEL; AxisClear( refdef.viewaxis ); refdef.x = x; refdef.y = y; refdef.width = w; refdef.height = h; if ( ui_stretch.integer ) { xscale = cgs.screenXScaleStretch; yscale = cgs.screenYScaleStretch; } else { xscale = cgs.screenXScale; yscale = cgs.screenYScale; } refdef.fov_x = (int)((float)refdef.width / xscale / 640.0f * 90.0f); xx = refdef.width / xscale / tan( refdef.fov_x / 360 * M_PI ); refdef.fov_y = atan2( refdef.height / yscale, xx ); refdef.fov_y *= ( 360 / (float)M_PI ); // calculate distance so the player nearly fills the box len = 0.7 * ( maxs[2] - mins[2] ); origin[0] = len / tan( DEG2RAD(refdef.fov_x) * 0.5 ); origin[1] = 0.5 * ( mins[1] + maxs[1] ); origin[2] = -0.5 * ( mins[2] + maxs[2] ); refdef.time = dp_realtime; trap_R_ClearScene(); // get the rotation information UI_PlayerAngles( pi, legs.axis, torso.axis, head.axis ); // get the animation state (after rotation, to allow feet shuffle) UI_PlayerAnimation( pi, &legs.oldframe, &legs.frame, &legs.backlerp, &torso.oldframe, &torso.frame, &torso.backlerp ); renderfx = RF_LIGHTING_ORIGIN | RF_NOSHADOW; // // add the legs // legs.hModel = pi->legsModel; legs.customSkin = CG_AddSkinToFrame( &pi->modelSkin ); VectorCopy( origin, legs.origin ); VectorCopy( origin, legs.lightingOrigin ); legs.renderfx = renderfx; VectorCopy (legs.origin, legs.oldorigin); Byte4Copy( pi->c1RGBA, legs.shaderRGBA ); CG_AddRefEntityWithMinLight( &legs ); if (!legs.hModel) { return; } // // add the torso // torso.hModel = pi->torsoModel; if (!torso.hModel) { return; } torso.customSkin = legs.customSkin; VectorCopy( origin, torso.lightingOrigin ); UI_PositionRotatedEntityOnTag( &torso, &legs, pi->legsModel, "tag_torso"); torso.renderfx = renderfx; Byte4Copy( pi->c1RGBA, torso.shaderRGBA ); CG_AddRefEntityWithMinLight( &torso ); // // add the head // head.hModel = pi->headModel; if (!head.hModel) { return; } head.customSkin = legs.customSkin; VectorCopy( origin, head.lightingOrigin ); UI_PositionRotatedEntityOnTag( &head, &torso, pi->torsoModel, "tag_head"); head.renderfx = renderfx; Byte4Copy( pi->c1RGBA, head.shaderRGBA ); CG_AddRefEntityWithMinLight( &head ); // // add the gun // if ( pi->currentWeapon != WP_NONE ) { #ifdef TA_WEAPSYS // get hands from cent for (i = 0; i < MAX_HANDS; i++) { memset( &gun[i], 0, sizeof(gun[i]) ); gun[i].hModel = pi->weaponModel[i]; VectorCopy( origin, gun[i].lightingOrigin ); gun[i].renderfx = renderfx; Byte4Copy( pi->c1RGBA, gun[i].shaderRGBA ); if (!originalTagNames[i] #ifdef TURTLEARENA // PLAYERS || !newTagNames[i] #endif ) { break; } if (!gun[i].hModel) { continue; } if ( #ifdef TURTLEARENA // PLAYERS !UI_PositionEntityOnTag( &gun[i], &torso, pi->torsoModel, newTagNames[i]) && #endif !UI_PositionEntityOnTag( &gun[i], &torso, pi->torsoModel, originalTagNames[i])) { // Failed to find tag continue; } CG_AddRefEntityWithMinLight( &gun[i] ); } #else memset( &gun, 0, sizeof(gun) ); gun.hModel = pi->weaponModel; Byte4Copy( pi->c1RGBA, gun.shaderRGBA ); VectorCopy( origin, gun.lightingOrigin ); UI_PositionEntityOnTag( &gun, &torso, pi->torsoModel, "tag_weapon"); gun.renderfx = renderfx; CG_AddRefEntityWithMinLight( &gun ); #endif } // // add the spinning barrel // #ifdef TA_WEAPSYS for (i = 0; i < MAX_HANDS; i++) #else if ( pi->barrelModel ) #endif { #ifdef TA_WEAPSYS if (!pi->barrelModel[i]) continue; #else vec3_t angles; #endif memset( &barrel, 0, sizeof(barrel) ); VectorCopy( origin, barrel.lightingOrigin ); barrel.renderfx = renderfx; #ifdef TA_WEAPSYS barrel.hModel = pi->barrelModel[i]; VectorClear(angles); if (bg_weapongroupinfo[pi->realWeapon].weapon[0]->barrelSpin != BS_NONE) { angles[bg_weapongroupinfo[pi->realWeapon].weapon[0]->barrelSpin] = UI_MachinegunSpinAngle( pi ); } #else barrel.hModel = pi->barrelModel; angles[YAW] = 0; angles[PITCH] = 0; angles[ROLL] = UI_MachinegunSpinAngle( pi ); #endif AnglesToAxis( angles, barrel.axis ); #ifdef TA_WEAPSYS UI_PositionRotatedEntityOnTag( &barrel, &gun[i], pi->weaponModel[i], "tag_barrel"); #else UI_PositionRotatedEntityOnTag( &barrel, &gun, pi->weaponModel, "tag_barrel"); #endif CG_AddRefEntityWithMinLight( &barrel ); } // // add muzzle flash // if ( dp_realtime <= pi->muzzleFlashTime ) { #ifdef TA_WEAPSYS vec3_t *flashDlightColor; for (i = 0; i < MAX_HANDS; i++) { memset( &flash, 0, sizeof(flash) ); flash.hModel = pi->flashModel[i]; flashDlightColor = &pi->flashDlightColor[i]; Byte4Copy( pi->c1RGBA, flash.shaderRGBA ); if (!flash.hModel) continue; VectorCopy( origin, flash.lightingOrigin ); UI_PositionEntityOnTag( &flash, &gun[i], pi->weaponModel[i], "tag_flash"); flash.renderfx = renderfx; trap_R_AddRefEntityToScene( &flash ); // make a dlight for the flash if ( *flashDlightColor[0] || *flashDlightColor[1] || *flashDlightColor[2] ) { trap_R_AddLightToScene( flash.origin, 200 + (rand()&31), 1.0f, *flashDlightColor[0], *flashDlightColor[1], *flashDlightColor[2] ); } } #else if ( pi->flashModel ) { memset( &flash, 0, sizeof(flash) ); flash.hModel = pi->flashModel; Byte4Copy( pi->c1RGBA, flash.shaderRGBA ); VectorCopy( origin, flash.lightingOrigin ); UI_PositionEntityOnTag( &flash, &gun, pi->weaponModel, "tag_flash"); flash.renderfx = renderfx; CG_AddRefEntityWithMinLight( &flash ); } // make a dlight for the flash if ( pi->flashDlightColor[0] || pi->flashDlightColor[1] || pi->flashDlightColor[2] ) { trap_R_AddJuniorLightToScene( flash.origin, 200 + (rand()&31), 1.0f, pi->flashDlightColor[0], pi->flashDlightColor[1], pi->flashDlightColor[2] ); } #endif } // // add the chat icon // if ( pi->chat ) { #ifdef TA_DATA // shaders UI_PlayerFloatSprite( pi, torso.origin, trap_R_RegisterShaderNoMip( "sprites/talkBalloon" ) ); #else UI_PlayerFloatSprite( pi, torso.origin, trap_R_RegisterShaderNoMip( "sprites/balloon3" ) ); #endif } // // add an accent light // origin[0] -= 100; // + = behind, - = in front origin[1] += 100; // + = left, - = right origin[2] += 100; // + = above, - = below trap_R_AddJuniorLightToScene( origin, 500, 1.0, 1.0, 1.0, 1.0 ); origin[0] -= 100; origin[1] -= 100; origin[2] -= 100; trap_R_AddJuniorLightToScene( origin, 500, 1.0, 1.0, 0.0, 0.0 ); trap_R_RenderScene( &refdef ); } /* ========================== UI_FileExists ========================== */ static qboolean UI_FileExists(const char *filename) { int len; len = trap_FS_FOpenFile( filename, NULL, FS_READ ); if (len>0) { return qtrue; } return qfalse; }
void CG_AddParticleToScene(cparticle_t *p, vec3_t org) { vec3_t point; polyVert_t verts[4]; float width; float height; float time, time2; float ratio; float invratio; vec3_t color; polyVert_t TRIverts[3]; vec3_t rright2, rup2; if (p->type == P_WEATHER || p->type == P_WEATHER_TURBULENT || p->type == P_WEATHER_FLURRY || p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT) { // create a front facing polygon if (p->type != P_WEATHER_FLURRY) { if (p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT) { if (org[2] > p->end) { p->time = cg.time; VectorCopy(org, p->org); // Ridah, fixes rare snow flakes that flicker on the ground p->org[2] = (p->start + crandom() * 4); if (p->type == P_BUBBLE_TURBULENT) { p->vel[0] = crandom() * 4; p->vel[1] = crandom() * 4; } } } else { if (org[2] < p->end) { p->time = cg.time; VectorCopy(org, p->org); // Ridah, fixes rare snow flakes that flicker on the ground while (p->org[2] < p->end) { p->org[2] += (p->start - p->end); } if (p->type == P_WEATHER_TURBULENT) { p->vel[0] = crandom() * 16; p->vel[1] = crandom() * 16; } } } // Rafael snow pvs check if (!p->link) { return; } p->alpha = 1; } // Ridah, had to do this or MAX_POLYS is being exceeded in village1.bsp if (VectorDistanceSquared(cg.snap->ps.origin, org) > SQR(1024)) { return; } // done. if (p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT) { VectorMA(org, -p->height, vup, point); VectorMA(point, -p->width, vright, point); VectorCopy(point, verts[0].xyz); verts[0].st[0] = 0; verts[0].st[1] = 0; verts[0].modulate[0] = 255; verts[0].modulate[1] = 255; verts[0].modulate[2] = 255; verts[0].modulate[3] = 255 * p->alpha; VectorMA(org, -p->height, vup, point); VectorMA(point, p->width, vright, point); VectorCopy(point, verts[1].xyz); verts[1].st[0] = 0; verts[1].st[1] = 1; verts[1].modulate[0] = 255; verts[1].modulate[1] = 255; verts[1].modulate[2] = 255; verts[1].modulate[3] = 255 * p->alpha; VectorMA(org, p->height, vup, point); VectorMA(point, p->width, vright, point); VectorCopy(point, verts[2].xyz); verts[2].st[0] = 1; verts[2].st[1] = 1; verts[2].modulate[0] = 255; verts[2].modulate[1] = 255; verts[2].modulate[2] = 255; verts[2].modulate[3] = 255 * p->alpha; VectorMA(org, p->height, vup, point); VectorMA(point, -p->width, vright, point); VectorCopy(point, verts[3].xyz); verts[3].st[0] = 1; verts[3].st[1] = 0; verts[3].modulate[0] = 255; verts[3].modulate[1] = 255; verts[3].modulate[2] = 255; verts[3].modulate[3] = 255 * p->alpha; } else { VectorMA(org, -p->height, vup, point); VectorMA(point, -p->width, vright, point); VectorCopy(point, TRIverts[0].xyz); TRIverts[0].st[0] = 1; TRIverts[0].st[1] = 0; TRIverts[0].modulate[0] = 255; TRIverts[0].modulate[1] = 255; TRIverts[0].modulate[2] = 255; TRIverts[0].modulate[3] = 255 * p->alpha; VectorMA(org, p->height, vup, point); VectorMA(point, -p->width, vright, point); VectorCopy(point, TRIverts[1].xyz); TRIverts[1].st[0] = 0; TRIverts[1].st[1] = 0; TRIverts[1].modulate[0] = 255; TRIverts[1].modulate[1] = 255; TRIverts[1].modulate[2] = 255; TRIverts[1].modulate[3] = 255 * p->alpha; VectorMA(org, p->height, vup, point); VectorMA(point, p->width, vright, point); VectorCopy(point, TRIverts[2].xyz); TRIverts[2].st[0] = 0; TRIverts[2].st[1] = 1; TRIverts[2].modulate[0] = 255; TRIverts[2].modulate[1] = 255; TRIverts[2].modulate[2] = 255; TRIverts[2].modulate[3] = 255 * p->alpha; } } else if (p->type == P_SPRITE) { vec3_t rr, ru; vec3_t rotate_ang; VectorSet(color, 1.0, 1.0, 1.0); time = cg.time - p->time; time2 = p->endtime - p->time; ratio = time / time2; width = p->width + (ratio * (p->endwidth - p->width)); height = p->height + (ratio * (p->endheight - p->height)); if (p->roll) { vectoangles(cg.refdef_current->viewaxis[0], rotate_ang); rotate_ang[ROLL] += p->roll; AngleVectors(rotate_ang, NULL, rr, ru); } if (p->roll) { VectorMA(org, -height, ru, point); VectorMA(point, -width, rr, point); } else { VectorMA(org, -height, vup, point); VectorMA(point, -width, vright, point); } VectorCopy(point, verts[0].xyz); verts[0].st[0] = 0; verts[0].st[1] = 0; verts[0].modulate[0] = 255; verts[0].modulate[1] = 255; verts[0].modulate[2] = 255; verts[0].modulate[3] = 255; if (p->roll) { VectorMA(point, 2 * height, ru, point); } else { VectorMA(point, 2 * height, vup, point); } VectorCopy(point, verts[1].xyz); verts[1].st[0] = 0; verts[1].st[1] = 1; verts[1].modulate[0] = 255; verts[1].modulate[1] = 255; verts[1].modulate[2] = 255; verts[1].modulate[3] = 255; if (p->roll) { VectorMA(point, 2 * width, rr, point); } else { VectorMA(point, 2 * width, vright, point); } VectorCopy(point, verts[2].xyz); verts[2].st[0] = 1; verts[2].st[1] = 1; verts[2].modulate[0] = 255; verts[2].modulate[1] = 255; verts[2].modulate[2] = 255; verts[2].modulate[3] = 255; if (p->roll) { VectorMA(point, -2 * height, ru, point); } else { VectorMA(point, -2 * height, vup, point); } VectorCopy(point, verts[3].xyz); verts[3].st[0] = 1; verts[3].st[1] = 0; verts[3].modulate[0] = 255; verts[3].modulate[1] = 255; verts[3].modulate[2] = 255; verts[3].modulate[3] = 255; } else if (p->type == P_SMOKE || p->type == P_SMOKE_IMPACT) { // create a front rotating facing polygon if (p->type == P_SMOKE_IMPACT && VectorDistanceSquared(cg.snap->ps.origin, org) > SQR(1024)) { return; } if (p->color == MUSTARD) { VectorSet(color, 0.42, 0.33, 0.19); } else if (p->color == BLOODRED) { VectorSet(color, 0.22, 0, 0); } else if (p->color == ZOMBIE) { VectorSet(color, 0.4, 0.28, 0.23); } else if (p->color == GREY75) { float len; float greyit; float val; len = Distance(cg.snap->ps.origin, org); if (!len) { len = 1; } val = 4096 / len; greyit = 0.25 * val; if (greyit > 0.5) { greyit = 0.5; } VectorSet(color, greyit, greyit, greyit); } else { VectorSet(color, 1.0, 1.0, 1.0); } time = cg.time - p->time; time2 = p->endtime - p->time; ratio = time / time2; if (cg.time > p->startfade) { invratio = 1 - ((cg.time - p->startfade) / (p->endtime - p->startfade)); if (p->color == EMISIVEFADE) { float fval; fval = (invratio * invratio); if (fval < 0) { fval = 0; } VectorSet(color, fval, fval, fval); } invratio *= p->alpha; } else { invratio = 1 * p->alpha; } if (cgs.glconfig.hardwareType == GLHW_RAGEPRO) { invratio = 1; } if (invratio > 1) { invratio = 1; } width = p->width + (ratio * (p->endwidth - p->width)); height = p->height + (ratio * (p->endheight - p->height)); { vec3_t temp; vectoangles(rforward, temp); p->accumroll += p->roll; temp[ROLL] += p->accumroll * 0.1; AngleVectors(temp, NULL, rright2, rup2); } if (p->rotate) { VectorMA(org, -height, rup2, point); VectorMA(point, -width, rright2, point); } else { VectorMA(org, -p->height, vup, point); VectorMA(point, -p->width, vright, point); } VectorCopy(point, verts[0].xyz); verts[0].st[0] = 0; verts[0].st[1] = 0; verts[0].modulate[0] = 255 * color[0]; verts[0].modulate[1] = 255 * color[1]; verts[0].modulate[2] = 255 * color[2]; verts[0].modulate[3] = 255 * invratio; if (p->rotate) { VectorMA(org, -height, rup2, point); VectorMA(point, width, rright2, point); } else { VectorMA(org, -p->height, vup, point); VectorMA(point, p->width, vright, point); } VectorCopy(point, verts[1].xyz); verts[1].st[0] = 0; verts[1].st[1] = 1; verts[1].modulate[0] = 255 * color[0]; verts[1].modulate[1] = 255 * color[1]; verts[1].modulate[2] = 255 * color[2]; verts[1].modulate[3] = 255 * invratio; if (p->rotate) { VectorMA(org, height, rup2, point); VectorMA(point, width, rright2, point); } else { VectorMA(org, p->height, vup, point); VectorMA(point, p->width, vright, point); } VectorCopy(point, verts[2].xyz); verts[2].st[0] = 1; verts[2].st[1] = 1; verts[2].modulate[0] = 255 * color[0]; verts[2].modulate[1] = 255 * color[1]; verts[2].modulate[2] = 255 * color[2]; verts[2].modulate[3] = 255 * invratio; if (p->rotate) { VectorMA(org, height, rup2, point); VectorMA(point, -width, rright2, point); } else { VectorMA(org, p->height, vup, point); VectorMA(point, -p->width, vright, point); } VectorCopy(point, verts[3].xyz); verts[3].st[0] = 1; verts[3].st[1] = 0; verts[3].modulate[0] = 255 * color[0]; verts[3].modulate[1] = 255 * color[1]; verts[3].modulate[2] = 255 * color[2]; verts[3].modulate[3] = 255 * invratio; } else if (p->type == P_FLAT_SCALEUP) { float width, height; float sinR, cosR; if (p->color == BLOODRED) { VectorSet(color, 1, 1, 1); } else { VectorSet(color, 0.5, 0.5, 0.5); } time = cg.time - p->time; time2 = p->endtime - p->time; ratio = time / time2; width = p->width + (ratio * (p->endwidth - p->width)); height = p->height + (ratio * (p->endheight - p->height)); if (width > p->endwidth) { width = p->endwidth; } if (height > p->endheight) { height = p->endheight; } sinR = height * sin(DEG2RAD(p->roll)) * ROOT_2; cosR = width * cos(DEG2RAD(p->roll)) * ROOT_2; VectorCopy(org, verts[0].xyz); verts[0].xyz[0] -= sinR; verts[0].xyz[1] -= cosR; verts[0].st[0] = 0; verts[0].st[1] = 0; verts[0].modulate[0] = 255 * color[0]; verts[0].modulate[1] = 255 * color[1]; verts[0].modulate[2] = 255 * color[2]; verts[0].modulate[3] = 255; VectorCopy(org, verts[1].xyz); verts[1].xyz[0] -= cosR; verts[1].xyz[1] += sinR; verts[1].st[0] = 0; verts[1].st[1] = 1; verts[1].modulate[0] = verts[0].modulate[0]; verts[1].modulate[1] = verts[0].modulate[1]; verts[1].modulate[2] = verts[0].modulate[2]; verts[1].modulate[3] = verts[0].modulate[3]; VectorCopy(org, verts[2].xyz); verts[2].xyz[0] += sinR; verts[2].xyz[1] += cosR; verts[2].st[0] = 1; verts[2].st[1] = 1; verts[2].modulate[0] = verts[0].modulate[0]; verts[2].modulate[1] = verts[0].modulate[1]; verts[2].modulate[2] = verts[0].modulate[2]; verts[2].modulate[3] = verts[0].modulate[3]; VectorCopy(org, verts[3].xyz); verts[3].xyz[0] += cosR; verts[3].xyz[1] -= sinR; verts[3].st[0] = 1; verts[3].st[1] = 0; verts[3].modulate[0] = verts[0].modulate[0]; verts[3].modulate[1] = verts[0].modulate[1]; verts[3].modulate[2] = verts[0].modulate[2]; verts[3].modulate[3] = verts[0].modulate[3]; } else if (p->type == P_FLAT) { VectorCopy(org, verts[0].xyz); verts[0].xyz[0] -= p->height; verts[0].xyz[1] -= p->width; verts[0].st[0] = 0; verts[0].st[1] = 0; verts[0].modulate[0] = 255; verts[0].modulate[1] = 255; verts[0].modulate[2] = 255; verts[0].modulate[3] = 255; VectorCopy(org, verts[1].xyz); verts[1].xyz[0] -= p->height; verts[1].xyz[1] += p->width; verts[1].st[0] = 0; verts[1].st[1] = 1; verts[1].modulate[0] = 255; verts[1].modulate[1] = 255; verts[1].modulate[2] = 255; verts[1].modulate[3] = 255; VectorCopy(org, verts[2].xyz); verts[2].xyz[0] += p->height; verts[2].xyz[1] += p->width; verts[2].st[0] = 1; verts[2].st[1] = 1; verts[2].modulate[0] = 255; verts[2].modulate[1] = 255; verts[2].modulate[2] = 255; verts[2].modulate[3] = 255; VectorCopy(org, verts[3].xyz); verts[3].xyz[0] += p->height; verts[3].xyz[1] -= p->width; verts[3].st[0] = 1; verts[3].st[1] = 0; verts[3].modulate[0] = 255; verts[3].modulate[1] = 255; verts[3].modulate[2] = 255; verts[3].modulate[3] = 255; } // Ridah else if (p->type == P_ANIM || p->type == P_DLIGHT_ANIM) { // ydnar vec3_t rr, ru; vec3_t rotate_ang; int i, j; time = cg.time - p->time; time2 = p->endtime - p->time; ratio = time / time2; if (ratio >= 1.0) { ratio = 0.9999; } else if (ratio < 0.0) { // rain - make sure that ratio isn't negative or // we'll walk out of bounds when j is calculated below ratio = 0.0001; } width = p->width + (ratio * (p->endwidth - p->width)); height = p->height + (ratio * (p->endheight - p->height)); // ydnar: add dlight if necessary if (p->type == P_DLIGHT_ANIM) { // fixme: support arbitrary color trap_R_AddLightToScene(org, 320, //% 1.5 * (width > height ? width : height), 1.25 * (1.0 - ratio), 1.0, 0.95, 0.85, 0, 0); } // if we are "inside" this sprite, don't draw if (VectorDistanceSquared(cg.snap->ps.origin, org) < SQR(width / 1.5f)) { return; } i = p->shaderAnim; j = (int)floor(ratio * shaderAnimCounts[p->shaderAnim]); p->pshader = shaderAnims[i][j]; // JPW NERVE more particle testing if (cg_fxflags & 1) { p->roll = 0; p->pshader = getTestShader(); rotate_ang[ROLL] = 90; } // jpw if (p->roll) { vectoangles(cg.refdef_current->viewaxis[0], rotate_ang); rotate_ang[ROLL] += p->roll; AngleVectors(rotate_ang, NULL, rr, ru); } if (p->roll) { VectorMA(org, -height, ru, point); VectorMA(point, -width, rr, point); } else { VectorMA(org, -height, vup, point); VectorMA(point, -width, vright, point); } VectorCopy(point, verts[0].xyz); verts[0].st[0] = 0; verts[0].st[1] = 0; verts[0].modulate[0] = 255; verts[0].modulate[1] = 255; verts[0].modulate[2] = 255; verts[0].modulate[3] = 255; if (p->roll) { VectorMA(point, 2 * height, ru, point); } else { VectorMA(point, 2 * height, vup, point); } VectorCopy(point, verts[1].xyz); verts[1].st[0] = 0; verts[1].st[1] = 1; verts[1].modulate[0] = 255; verts[1].modulate[1] = 255; verts[1].modulate[2] = 255; verts[1].modulate[3] = 255; if (p->roll) { VectorMA(point, 2 * width, rr, point); } else { VectorMA(point, 2 * width, vright, point); } VectorCopy(point, verts[2].xyz); verts[2].st[0] = 1; verts[2].st[1] = 1; verts[2].modulate[0] = 255; verts[2].modulate[1] = 255; verts[2].modulate[2] = 255; verts[2].modulate[3] = 255; if (p->roll) { VectorMA(point, -2 * height, ru, point); } else { VectorMA(point, -2 * height, vup, point); } VectorCopy(point, verts[3].xyz); verts[3].st[0] = 1; verts[3].st[1] = 0; verts[3].modulate[0] = 255; verts[3].modulate[1] = 255; verts[3].modulate[2] = 255; verts[3].modulate[3] = 255; } // done. if (!cg_wolfparticles.integer) { return; } if (!p->pshader) { return; } if (p->type == P_WEATHER || p->type == P_WEATHER_TURBULENT || p->type == P_WEATHER_FLURRY) { trap_R_AddPolyToScene(p->pshader, 3, TRIverts); } else { trap_R_AddPolyToScene(p->pshader, 4, verts); } }
void CG_Spotlight( centity_t *cent, float *color, vec3_t realstart, vec3_t lightDir, int segs, float range, int startWidth, float coneAngle, int flags ) { int i, j; vec3_t start, traceEnd, proj; vec3_t right, up; vec3_t v1, v2; vec3_t startvec, endvec; // the vectors to rotate around lightDir to create the circles vec3_t conevec; vec3_t start_points[MAX_SPOT_SEGS], end_points[MAX_SPOT_SEGS]; vec3_t coreright; polyVert_t verts[MAX_SPOT_SEGS * 4]; // x4 for 4 verts per poly polyVert_t plugVerts[MAX_SPOT_SEGS]; vec3_t endCenter; polyVert_t coreverts[4]; trace_t tr; float alpha; float radius = 0.0; // TTimo might be used uninitialized float coreEndRadius; qboolean capStart = qtrue; float hitDist; // the actual distance of the trace impact (0 is no hit) float beamLen; // actual distance of the drawn beam float endAlpha = 0.0; vec4_t colorNorm; // normalized color vector refEntity_t ent; vec3_t angles; VectorCopy( realstart, start ); // normalize color colorNorm[3] = 0; // store normalize multiplier in alpha index for ( i = 0; i < 3; i++ ) { if ( color[i] > colorNorm[3] ) { colorNorm[3] = color[i]; // find largest color value in RGB } } if ( colorNorm[3] != 1 ) { // it needs to be boosted VectorMA( color, 1.0 / colorNorm[3], color, colorNorm ); // FIXME: div by 0 } else { VectorCopy( color, colorNorm ); } colorNorm[3] = color[3]; if ( flags & SL_NOSTARTCAP ) { capStart = qfalse; } if ( startWidth == 0 ) { // cone, not cylinder capStart = qfalse; } if ( flags & SL_LOCKTRACETORANGE ) { VectorMA( start, range, lightDir, traceEnd ); // trace out to 'range' } else { VectorMA( start, MAX_SPOT_RANGE, lightDir, traceEnd ); // trace all the way out to max dist } // first trace to see if anything is hit if ( flags & SL_NOTRACE ) { tr.fraction = 1.0; // force no hit } else { if ( flags & SL_TRACEWORLDONLY ) { CG_Trace( &tr, start, NULL, NULL, traceEnd, -1, CONTENTS_SOLID ); } else { CG_Trace( &tr, start, NULL, NULL, traceEnd, -1, MASK_SHOT ); } // CG_Trace( &tr, start, NULL, NULL, traceEnd, -1, MASK_ALL &~(CONTENTS_MONSTERCLIP|CONTENTS_AREAPORTAL|CONTENTS_CLUSTERPORTAL)); } if ( tr.fraction < 1.0 ) { hitDist = beamLen = MAX_SPOT_RANGE * tr.fraction; if ( beamLen > range ) { beamLen = range; } } else { hitDist = 0; beamLen = range; } if ( flags & SL_LOCKUV ) { if ( beamLen < range ) { endAlpha = 255.0f * ( color[3] - ( color[3] * beamLen / range ) ); } } if ( segs >= MAX_SPOT_SEGS ) { segs = MAX_SPOT_SEGS - 1; } // TODO: adjust segs based on r_lodbias // TODO: move much of this to renderer // model at base if ( cent->currentState.modelindex ) { memset( &ent, 0, sizeof( ent ) ); ent.frame = 0; ent.oldframe = 0; ent.backlerp = 0; VectorCopy( cent->lerpOrigin, ent.origin ); VectorCopy( cent->lerpOrigin, ent.oldorigin ); ent.hModel = cgs.gameModels[cent->currentState.modelindex]; // AnglesToAxis( cent->lerpAngles, ent.axis ); vectoangles( lightDir, angles ); AnglesToAxis( angles, ent.axis ); trap_R_AddRefEntityToScene( &ent ); memcpy( ¢->refEnt, &ent, sizeof( refEntity_t ) ); // push start out a bit so the beam fits to the front of the base model VectorMA( start, 14, lightDir, start ); } //// BEAM PerpendicularVector( up, lightDir ); CrossProduct( lightDir, up, right ); // find first vert of the start VectorScale( right, startWidth, startvec ); // find the first vert of the end RotatePointAroundVector( conevec, up, lightDir, -coneAngle ); VectorMA( startvec, beamLen, conevec, endvec ); // this applies the offset of the start diameter before finding the end points VectorScale( lightDir, beamLen, endCenter ); VectorSubtract( endCenter, endvec, coreverts[3].xyz ); // get a vector of the radius out at the end for the core to use coreEndRadius = VectorLength( coreverts[3].xyz ); #define CORESCALE 0.6f // // generate the flat beam 'core' // if ( !( flags & SL_NOCORE ) ) { VectorSubtract( start, cg.refdef.vieworg, v1 ); VectorNormalize( v1 ); VectorSubtract( traceEnd, cg.refdef.vieworg, v2 ); VectorNormalize( v2 ); CrossProduct( v1, v2, coreright ); VectorNormalize( coreright ); memset( &coreverts[0], 0, 4 * sizeof( polyVert_t ) ); VectorMA( start, startWidth * 0.5f, coreright, coreverts[0].xyz ); VectorMA( start, -startWidth * 0.5f, coreright, coreverts[1].xyz ); VectorMA( endCenter, -coreEndRadius * CORESCALE, coreright, coreverts[2].xyz ); VectorAdd( start, coreverts[2].xyz, coreverts[2].xyz ); VectorMA( endCenter, coreEndRadius * CORESCALE, coreright, coreverts[3].xyz ); VectorAdd( start, coreverts[3].xyz, coreverts[3].xyz ); for ( i = 0; i < 4; i++ ) { coreverts[i].modulate[0] = color[0] * 200.0f; coreverts[i].modulate[1] = color[1] * 200.0f; coreverts[i].modulate[2] = color[2] * 200.0f; coreverts[i].modulate[3] = color[3] * 200.0f; if ( i > 1 ) { coreverts[i].modulate[3] = 0; } } trap_R_AddPolyToScene( cgs.media.spotLightBeamShader, 4, &coreverts[0] ); } // // generate the beam cylinder // for ( i = 0; i <= segs; i++ ) { RotatePointAroundVector( start_points[i], lightDir, startvec, ( 360.0f / (float)segs ) * i ); VectorAdd( start_points[i], start, start_points[i] ); RotatePointAroundVector( end_points[i], lightDir, endvec, ( 360.0f / (float)segs ) * i ); VectorAdd( end_points[i], start, end_points[i] ); } for ( i = 0; i < segs; i++ ) { j = ( i * 4 ); VectorCopy( start_points[i], verts[( i * 4 )].xyz ); verts[j].st[0] = 0; verts[j].st[1] = 1; verts[j].modulate[0] = color[0] * 255.0f; verts[j].modulate[1] = color[1] * 255.0f; verts[j].modulate[2] = color[2] * 255.0f; verts[j].modulate[3] = color[3] * 255.0f; j++; VectorCopy( end_points[i], verts[j].xyz ); verts[j].st[0] = 0; verts[j].st[1] = 0; verts[j].modulate[0] = color[0] * 255.0f; verts[j].modulate[1] = color[1] * 255.0f; verts[j].modulate[2] = color[2] * 255.0f; verts[j].modulate[3] = endAlpha; j++; VectorCopy( end_points[i + 1], verts[j].xyz ); verts[j].st[0] = 1; verts[j].st[1] = 0; verts[j].modulate[0] = color[0] * 255.0f; verts[j].modulate[1] = color[1] * 255.0f; verts[j].modulate[2] = color[2] * 255.0f; verts[j].modulate[3] = endAlpha; j++; VectorCopy( start_points[i + 1], verts[j].xyz ); verts[j].st[0] = 1; verts[j].st[1] = 1; verts[j].modulate[0] = color[0] * 255.0f; verts[j].modulate[1] = color[1] * 255.0f; verts[j].modulate[2] = color[2] * 255.0f; verts[j].modulate[3] = color[3] * 255.0f; if ( capStart ) { VectorCopy( start_points[i], plugVerts[i].xyz ); plugVerts[i].st[0] = 0; plugVerts[i].st[1] = 0; plugVerts[i].modulate[0] = color[0] * 255.0f; plugVerts[i].modulate[1] = color[1] * 255.0f; plugVerts[i].modulate[2] = color[2] * 255.0f; plugVerts[i].modulate[3] = color[3] * 255.0f; } } trap_R_AddPolysToScene( cgs.media.spotLightBeamShader, 4, &verts[0], segs ); // plug up the start circle if ( capStart ) { trap_R_AddPolyToScene( cgs.media.spotLightBeamShader, segs, &plugVerts[0] ); } // show the endpoint if ( !( flags & SL_NOIMPACT ) ) { if ( hitDist ) { VectorMA( startvec, hitDist, conevec, endvec ); alpha = 0.3f; radius = coreEndRadius * ( hitDist / beamLen ); VectorNegate( lightDir, proj ); CG_ImpactMark( cgs.media.spotLightShader, tr.endpos, proj, 0, colorNorm[0], colorNorm[1], colorNorm[2], alpha, qfalse, radius, qtrue, -1 ); } } // add d light at end if ( !( flags & SL_NODLIGHT ) ) { vec3_t dlightLoc; // VectorMA(tr.endpos, -60, lightDir, dlightLoc); // back away from the hit // trap_R_AddLightToScene(dlightLoc, 200, colorNorm[0], colorNorm[1], colorNorm[2], 0); // ,REF_JUNIOR_DLIGHT); VectorMA( tr.endpos, 0, lightDir, dlightLoc ); // back away from the hit // trap_R_AddLightToScene(dlightLoc, radius*2, colorNorm[0], colorNorm[1], colorNorm[2], 0); // ,REF_JUNIOR_DLIGHT); trap_R_AddLightToScene( dlightLoc, radius * 2, 0.3, 0.3, 0.3, 0 ); // ,REF_JUNIOR_DLIGHT); } // draw flare at source if ( !( flags & SL_NOFLARE ) ) { qboolean lightInEyes = qfalse; vec3_t camloc, dirtolight; float dot, deg, dist; float flarescale = 0.0; // TTimo: might be used uninitialized // get camera position and direction to lightsource VectorCopy( cg.snap->ps.origin, camloc ); camloc[2] += cg.snap->ps.viewheight; VectorSubtract( start, camloc, dirtolight ); dist = VectorNormalize( dirtolight ); // first use dot to determine if it's facing the camera dot = DotProduct( lightDir, dirtolight ); // it's facing the camera, find out how closely and trace to see if the source can be seen deg = RAD2DEG( M_PI - acos( dot ) ); if ( deg <= 35 ) { // start flare a bit before the camera gets inside the cylinder lightInEyes = qtrue; flarescale = 1 - ( deg / 35 ); } if ( lightInEyes ) { // the dot check succeeded, now do a trace CG_Trace( &tr, start, NULL, NULL, camloc, -1, MASK_ALL & ~( CONTENTS_MONSTERCLIP | CONTENTS_AREAPORTAL | CONTENTS_CLUSTERPORTAL ) ); if ( tr.fraction != 1 ) { lightInEyes = qfalse; } } if ( lightInEyes ) { float coronasize = flarescale; if ( dist < 512 ) { // make even bigger if you're close enough coronasize *= ( 512.0f / dist ); } trap_R_AddCoronaToScene( start, colorNorm[0], colorNorm[1], colorNorm[2], coronasize, cent->currentState.number, qtrue ); } else { // even though it's off, still need to add it, but turned off so it can fade in/out properly trap_R_AddCoronaToScene( start, colorNorm[0], colorNorm[1], colorNorm[2], 0, cent->currentState.number, qfalse ); } } }
/* ============= CG_AddPlayerWeapon 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 ) { refEntity_t gun; refEntity_t barrel; refEntity_t flash; vec3_t angles; weapon_t weaponNum; weaponMode_t weaponMode; weaponInfo_t *weapon; qboolean noGunModel; qboolean firing; weaponNum = cent->currentState.weapon; weaponMode = cent->currentState.generic1; if( weaponMode <= WPM_NONE || weaponMode >= WPM_NUM_WEAPONMODES ) weaponMode = WPM_PRIMARY; if( ( ( cent->currentState.eFlags & EF_FIRING ) && weaponMode == WPM_PRIMARY ) || ( ( cent->currentState.eFlags & EF_FIRING2 ) && weaponMode == WPM_SECONDARY ) || ( ( cent->currentState.eFlags & EF_FIRING3 ) && weaponMode == WPM_TERTIARY ) ) firing = qtrue; else firing = qfalse; weapon = &cg_weapons[ weaponNum ]; if( !weapon->registered ) { Com_Printf( S_COLOR_YELLOW "WARNING: CG_AddPlayerWeapon: weapon %d (%s) " "is not registered\n", weaponNum, BG_Weapon( weaponNum )->name ); return; } // add the weapon Com_Memset( &gun, 0, sizeof( gun ) ); Com_Memset( &barrel, 0, sizeof( barrel ) ); Com_Memset( &flash, 0, sizeof( flash ) ); VectorCopy( parent->lightingOrigin, gun.lightingOrigin ); gun.shadowPlane = parent->shadowPlane; gun.renderfx = parent->renderfx; if( ps ) { gun.shaderRGBA[ 0 ] = 255; gun.shaderRGBA[ 1 ] = 255; gun.shaderRGBA[ 2 ] = 255; gun.shaderRGBA[ 3 ] = 255; //set weapon[1/2]Time when respective buttons change state if( cg.weapon1Firing != ( cg.predictedPlayerState.eFlags & EF_FIRING ) ) { cg.weapon1Time = cg.time; cg.weapon1Firing = ( cg.predictedPlayerState.eFlags & EF_FIRING ); } if( cg.weapon2Firing != ( cg.predictedPlayerState.eFlags & EF_FIRING2 ) ) { cg.weapon2Time = cg.time; cg.weapon2Firing = ( cg.predictedPlayerState.eFlags & EF_FIRING2 ); } if( cg.weapon3Firing != ( cg.predictedPlayerState.eFlags & EF_FIRING3 ) ) { cg.weapon3Time = cg.time; cg.weapon3Firing = ( cg.predictedPlayerState.eFlags & EF_FIRING3 ); } } if( !ps ) { gun.hModel = weapon->weaponModel3rdPerson; if( !gun.hModel ) gun.hModel = weapon->weaponModel; } else gun.hModel = weapon->weaponModel; noGunModel = ( ( !ps || cg.renderingThirdPerson ) && weapon->disableIn3rdPerson ) || !gun.hModel; if( !ps ) { // add weapon ready sound if( firing && weapon->wim[ weaponMode ].firingSound ) { trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin, weapon->wim[ weaponMode ].firingSound ); } else if( weapon->readySound ) trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin, weapon->readySound ); } // Lucifer cannon charge warning beep if( weaponNum == WP_LUCIFER_CANNON && ( cent->currentState.eFlags & EF_WARN_CHARGE ) && cg.snap->ps.stats[ STAT_TEAM ] != TEAM_ALIENS ) { trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin, ps ? cgs.media.lCannonWarningSound : cgs.media.lCannonWarningSound2 ); } if( !noGunModel ) { CG_PositionEntityOnTag( &gun, parent, parent->hModel, "tag_weapon" ); CG_WeaponAnimation( cent, &gun.oldframe, &gun.frame, &gun.backlerp ); trap_R_AddRefEntityToScene( &gun ); if( !ps ) { barrel.hModel = weapon->barrelModel3rdPerson; if( !barrel.hModel ) barrel.hModel = weapon->barrelModel; } else barrel.hModel = weapon->barrelModel; // add the spinning barrel if( barrel.hModel ) { VectorCopy( parent->lightingOrigin, barrel.lightingOrigin ); barrel.shadowPlane = parent->shadowPlane; barrel.renderfx = parent->renderfx; angles[ YAW ] = 0; angles[ PITCH ] = 0; angles[ ROLL ] = CG_MachinegunSpinAngle( cent, firing ); AnglesToAxis( angles, barrel.axis ); CG_PositionRotatedEntityOnTag( &barrel, &gun, gun.hModel, "tag_barrel" ); trap_R_AddRefEntityToScene( &barrel ); } } if( CG_IsParticleSystemValid( ¢->muzzlePS ) ) { if( ps || cg.renderingThirdPerson || cent->currentState.number != cg.predictedPlayerState.clientNum ) { if( noGunModel ) CG_SetAttachmentTag( ¢->muzzlePS->attachment, *parent, parent->hModel, "tag_weapon" ); else CG_SetAttachmentTag( ¢->muzzlePS->attachment, gun, gun.hModel, "tag_flash" ); } //if the PS is infinite disable it when not firing if( !firing && CG_IsParticleSystemInfinite( cent->muzzlePS ) ) CG_DestroyParticleSystem( ¢->muzzlePS ); } // add the flash if( !weapon->wim[ weaponMode ].continuousFlash || !firing ) { // impulse flash if( cg.time - cent->muzzleFlashTime > MUZZLE_FLASH_TIME ) return; } VectorCopy( parent->lightingOrigin, flash.lightingOrigin ); flash.shadowPlane = parent->shadowPlane; flash.renderfx = parent->renderfx; if( !ps ) { flash.hModel = weapon->flashModel3rdPerson; if( !flash.hModel ) flash.hModel = weapon->flashModel; } else flash.hModel = weapon->flashModel; if( flash.hModel ) { angles[ YAW ] = 0; angles[ PITCH ] = 0; angles[ ROLL ] = crandom( ) * 10; AnglesToAxis( angles, flash.axis ); if( noGunModel ) CG_PositionRotatedEntityOnTag( &flash, parent, parent->hModel, "tag_weapon" ); else CG_PositionRotatedEntityOnTag( &flash, &gun, gun.hModel, "tag_flash" ); trap_R_AddRefEntityToScene( &flash ); } if( ps || cg.renderingThirdPerson || cent->currentState.number != cg.predictedPlayerState.clientNum ) { if( weapon->wim[ weaponMode ].muzzleParticleSystem && cent->muzzlePsTrigger ) { cent->muzzlePS = CG_SpawnNewParticleSystem( weapon->wim[ weaponMode ].muzzleParticleSystem ); if( CG_IsParticleSystemValid( ¢->muzzlePS ) ) { if( noGunModel ) CG_SetAttachmentTag( ¢->muzzlePS->attachment, *parent, parent->hModel, "tag_weapon" ); else CG_SetAttachmentTag( ¢->muzzlePS->attachment, gun, gun.hModel, "tag_flash" ); CG_SetAttachmentCent( ¢->muzzlePS->attachment, cent ); CG_AttachToTag( ¢->muzzlePS->attachment ); } cent->muzzlePsTrigger = qfalse; } // make a dlight for the flash if( weapon->wim[ weaponMode ].flashDlightColor[ 0 ] || weapon->wim[ weaponMode ].flashDlightColor[ 1 ] || weapon->wim[ weaponMode ].flashDlightColor[ 2 ] ) { trap_R_AddLightToScene( flash.origin, 300 + ( rand( ) & 31 ), weapon->wim[ weaponMode ].flashDlightColor[ 0 ], weapon->wim[ weaponMode ].flashDlightColor[ 1 ], weapon->wim[ weaponMode ].flashDlightColor[ 2 ] ); } } }
/** * @brief CG_AddParticleToScene * @param[in,out] p * @param[in] org * @param alpha - unused */ void CG_AddParticleToScene(cparticle_t *p, vec3_t org, float alpha) { polyVert_t verts[4]; polyVert_t TRIverts[3]; switch (p->type) { case P_WEATHER: case P_WEATHER_TURBULENT: case P_WEATHER_FLURRY: case P_BUBBLE: case P_BUBBLE_TURBULENT: // create a front facing polygon { if (p->type != P_WEATHER_FLURRY) { if (p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT) { if (org[2] > p->end) { p->time = cg.time; VectorCopy(org, p->org); // fixes rare snow flakes that flicker on the ground p->org[2] = (p->start + crandom() * 4); if (p->type == P_BUBBLE_TURBULENT) { p->vel[0] = crandom() * 4; p->vel[1] = crandom() * 4; } } } else { if (org[2] < p->end) { p->time = cg.time; VectorCopy(org, p->org); // fixes rare snow flakes that flicker on the ground while (p->org[2] < p->end) { p->org[2] += (p->start - p->end); } if (p->type == P_WEATHER_TURBULENT) { p->vel[0] = crandom() * 16; p->vel[1] = crandom() * 16; } } } // snow pvs check if (!p->link) { return; } p->alpha = 1; } // had to do this or MAX_POLYS is being exceeded in village1.bsp if (VectorDistanceSquared(cg.snap->ps.origin, org) > Square(1024)) { return; } if (p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT) { vec3_t point; VectorMA(org, -p->height, vup, point); VectorMA(point, -p->width, vright, point); VectorCopy(point, verts[0].xyz); verts[0].st[0] = 0; verts[0].st[1] = 0; verts[0].modulate[0] = 255; verts[0].modulate[1] = 255; verts[0].modulate[2] = 255; verts[0].modulate[3] = (byte)(255 * p->alpha); VectorMA(org, -p->height, vup, point); VectorMA(point, p->width, vright, point); VectorCopy(point, verts[1].xyz); verts[1].st[0] = 0; verts[1].st[1] = 1; verts[1].modulate[0] = 255; verts[1].modulate[1] = 255; verts[1].modulate[2] = 255; verts[1].modulate[3] = (byte)(255 * p->alpha); VectorMA(org, p->height, vup, point); VectorMA(point, p->width, vright, point); VectorCopy(point, verts[2].xyz); verts[2].st[0] = 1; verts[2].st[1] = 1; verts[2].modulate[0] = 255; verts[2].modulate[1] = 255; verts[2].modulate[2] = 255; verts[2].modulate[3] = (byte)(255 * p->alpha); VectorMA(org, p->height, vup, point); VectorMA(point, -p->width, vright, point); VectorCopy(point, verts[3].xyz); verts[3].st[0] = 1; verts[3].st[1] = 0; verts[3].modulate[0] = 255; verts[3].modulate[1] = 255; verts[3].modulate[2] = 255; verts[3].modulate[3] = (byte)(255 * p->alpha); } else { vec3_t point; VectorMA(org, -p->height, vup, point); VectorMA(point, -p->width, vright, point); VectorCopy(point, TRIverts[0].xyz); TRIverts[0].st[0] = 1; TRIverts[0].st[1] = 0; TRIverts[0].modulate[0] = 255; TRIverts[0].modulate[1] = 255; TRIverts[0].modulate[2] = 255; TRIverts[0].modulate[3] = (byte)(255 * p->alpha); VectorMA(org, p->height, vup, point); VectorMA(point, -p->width, vright, point); VectorCopy(point, TRIverts[1].xyz); TRIverts[1].st[0] = 0; TRIverts[1].st[1] = 0; TRIverts[1].modulate[0] = 255; TRIverts[1].modulate[1] = 255; TRIverts[1].modulate[2] = 255; TRIverts[1].modulate[3] = (byte)(255 * p->alpha); VectorMA(org, p->height, vup, point); VectorMA(point, p->width, vright, point); VectorCopy(point, TRIverts[2].xyz); TRIverts[2].st[0] = 0; TRIverts[2].st[1] = 1; TRIverts[2].modulate[0] = 255; TRIverts[2].modulate[1] = 255; TRIverts[2].modulate[2] = 255; TRIverts[2].modulate[3] = (byte)(255 * p->alpha); } } break; case P_SPRITE: { vec3_t point, rr, ru, rotate_ang; float time = cg.time - p->time; float time2 = p->endtime - p->time; float ratio = time / time2; float width = p->width + (ratio * (p->endwidth - p->width)); float height = p->height + (ratio * (p->endheight - p->height)); if (p->roll) { vectoangles(cg.refdef_current->viewaxis[0], rotate_ang); rotate_ang[ROLL] += p->roll; AngleVectors(rotate_ang, NULL, rr, ru); } if (p->roll) { VectorMA(org, -height, ru, point); VectorMA(point, -width, rr, point); } else { VectorMA(org, -height, vup, point); VectorMA(point, -width, vright, point); } VectorCopy(point, verts[0].xyz); verts[0].st[0] = 0; verts[0].st[1] = 0; verts[0].modulate[0] = 255; verts[0].modulate[1] = 255; verts[0].modulate[2] = 255; verts[0].modulate[3] = 255; if (p->roll) { VectorMA(point, 2 * height, ru, point); } else { VectorMA(point, 2 * height, vup, point); } VectorCopy(point, verts[1].xyz); verts[1].st[0] = 0; verts[1].st[1] = 1; verts[1].modulate[0] = 255; verts[1].modulate[1] = 255; verts[1].modulate[2] = 255; verts[1].modulate[3] = 255; if (p->roll) { VectorMA(point, 2 * width, rr, point); } else { VectorMA(point, 2 * width, vright, point); } VectorCopy(point, verts[2].xyz); verts[2].st[0] = 1; verts[2].st[1] = 1; verts[2].modulate[0] = 255; verts[2].modulate[1] = 255; verts[2].modulate[2] = 255; verts[2].modulate[3] = 255; if (p->roll) { VectorMA(point, -2 * height, ru, point); } else { VectorMA(point, -2 * height, vup, point); } VectorCopy(point, verts[3].xyz); verts[3].st[0] = 1; verts[3].st[1] = 0; verts[3].modulate[0] = 255; verts[3].modulate[1] = 255; verts[3].modulate[2] = 255; verts[3].modulate[3] = 255; } break; case P_SMOKE: case P_SMOKE_IMPACT: // create a front rotating facing polygon { vec3_t point, rup2, rright2, color; float invratio, time, time2, ratio, width, height; if (p->type == P_SMOKE_IMPACT && VectorDistanceSquared(cg.snap->ps.origin, org) > Square(1024)) { return; } if (p->color == MUSTARD) { VectorSet(color, 0.42f, 0.33f, 0.19f); } else if (p->color == BLOODRED) { VectorSet(color, 0.22f, 0, 0); } else if (p->color == ZOMBIE) { VectorSet(color, 0.4f, 0.28f, 0.23f); } else if (p->color == GREY75) { float len, greyit; len = Distance(cg.snap->ps.origin, org); if (len == 0.f) { len = 1; } //val = 4096 / len; greyit = 0.25f * (4096 / len); if (greyit > 0.5f) { greyit = 0.5f; } VectorSet(color, greyit, greyit, greyit); } else { VectorSet(color, 1.0f, 1.0f, 1.0f); } time = cg.time - p->time; time2 = p->endtime - p->time; ratio = time / time2; if (cg.time > p->startfade) { invratio = 1 - ((cg.time - p->startfade) / (p->endtime - p->startfade)); if (p->color == EMISIVEFADE) { float fval = invratio * invratio; if (fval < 0) { fval = 0; } VectorSet(color, fval, fval, fval); } invratio *= p->alpha; } else { invratio = 1 * p->alpha; } if (invratio > 1) { invratio = 1; } width = p->width + (ratio * (p->endwidth - p->width)); height = p->height + (ratio * (p->endheight - p->height)); //if (p->type != P_SMOKE_IMPACT) { vec3_t temp; vectoangles(rforward, temp); p->accumroll += p->roll; temp[ROLL] += p->accumroll * 0.1; //temp[ROLL] += p->roll * 0.1; AngleVectors(temp, NULL, rright2, rup2); } //else //{ //VectorCopy (rright, rright2); //VectorCopy (rup, rup2); //} if (p->rotate) { VectorMA(org, -height, rup2, point); VectorMA(point, -width, rright2, point); } else { VectorMA(org, -p->height, vup, point); VectorMA(point, -p->width, vright, point); } VectorCopy(point, verts[0].xyz); verts[0].st[0] = 0; verts[0].st[1] = 0; verts[0].modulate[0] = (byte)(255 * color[0]); verts[0].modulate[1] = (byte)(255 * color[1]); verts[0].modulate[2] = (byte)(255 * color[2]); verts[0].modulate[3] = (byte)(255 * invratio); if (p->rotate) { VectorMA(org, -height, rup2, point); VectorMA(point, width, rright2, point); } else { VectorMA(org, -p->height, vup, point); VectorMA(point, p->width, vright, point); } VectorCopy(point, verts[1].xyz); verts[1].st[0] = 0; verts[1].st[1] = 1; verts[1].modulate[0] = (byte)(255 * color[0]); verts[1].modulate[1] = (byte)(255 * color[1]); verts[1].modulate[2] = (byte)(255 * color[2]); verts[1].modulate[3] = (byte)(255 * invratio); if (p->rotate) { VectorMA(org, height, rup2, point); VectorMA(point, width, rright2, point); } else { VectorMA(org, p->height, vup, point); VectorMA(point, p->width, vright, point); } VectorCopy(point, verts[2].xyz); verts[2].st[0] = 1; verts[2].st[1] = 1; verts[2].modulate[0] = (byte)(255 * color[0]); verts[2].modulate[1] = (byte)(255 * color[1]); verts[2].modulate[2] = (byte)(255 * color[2]); verts[2].modulate[3] = (byte)(255 * invratio); if (p->rotate) { VectorMA(org, height, rup2, point); VectorMA(point, -width, rright2, point); } else { VectorMA(org, p->height, vup, point); VectorMA(point, -p->width, vright, point); } VectorCopy(point, verts[3].xyz); verts[3].st[0] = 1; verts[3].st[1] = 0; verts[3].modulate[0] = (byte)(255 * color[0]); verts[3].modulate[1] = (byte)(255 * color[1]); verts[3].modulate[2] = (byte)(255 * color[2]); verts[3].modulate[3] = (byte)(255 * invratio); } break; case P_BLEED: { vec3_t point, rr, ru, rotate_ang; float alpha = p->alpha; if (p->roll) { vectoangles(cg.refdef_current->viewaxis[0], rotate_ang); rotate_ang[ROLL] += p->roll; AngleVectors(rotate_ang, NULL, rr, ru); } else { VectorCopy(vup, ru); VectorCopy(vright, rr); } VectorMA(org, -p->height, ru, point); VectorMA(point, -p->width, rr, point); VectorCopy(point, verts[0].xyz); verts[0].st[0] = 0; verts[0].st[1] = 0; verts[0].modulate[0] = 111; verts[0].modulate[1] = 19; verts[0].modulate[2] = 9; verts[0].modulate[3] = (byte)(255 * alpha); VectorMA(org, -p->height, ru, point); VectorMA(point, p->width, rr, point); VectorCopy(point, verts[1].xyz); verts[1].st[0] = 0; verts[1].st[1] = 1; verts[1].modulate[0] = 111; verts[1].modulate[1] = 19; verts[1].modulate[2] = 9; verts[1].modulate[3] = (byte)(255 * alpha); VectorMA(org, p->height, ru, point); VectorMA(point, p->width, rr, point); VectorCopy(point, verts[2].xyz); verts[2].st[0] = 1; verts[2].st[1] = 1; verts[2].modulate[0] = 111; verts[2].modulate[1] = 19; verts[2].modulate[2] = 9; verts[2].modulate[3] = (byte)(255 * alpha); VectorMA(org, p->height, ru, point); VectorMA(point, -p->width, rr, point); VectorCopy(point, verts[3].xyz); verts[3].st[0] = 1; verts[3].st[1] = 0; verts[3].modulate[0] = 111; verts[3].modulate[1] = 19; verts[3].modulate[2] = 9; verts[3].modulate[3] = (byte)(255 * alpha); } break; case P_FLAT_SCALEUP: { vec3_t color; float width, height; float sinR, cosR; float time = cg.time - p->time; float time2 = p->endtime - p->time; float ratio = time / time2; if (p->color == BLOODRED) { VectorSet(color, 1, 1, 1); } else { VectorSet(color, 0.5f, 0.5f, 0.5f); } width = p->width + (ratio * (p->endwidth - p->width)); height = p->height + (ratio * (p->endheight - p->height)); if (width > p->endwidth) { width = p->endwidth; } if (height > p->endheight) { height = p->endheight; } sinR = height * (float)(sin(DEG2RAD(p->roll)) * M_SQRT2); cosR = width * (float)(cos(DEG2RAD(p->roll)) * M_SQRT2); VectorCopy(org, verts[0].xyz); verts[0].xyz[0] -= sinR; verts[0].xyz[1] -= cosR; verts[0].st[0] = 0; verts[0].st[1] = 0; verts[0].modulate[0] = (byte)(255 * color[0]); verts[0].modulate[1] = (byte)(255 * color[1]); verts[0].modulate[2] = (byte)(255 * color[2]); verts[0].modulate[3] = 255; VectorCopy(org, verts[1].xyz); verts[1].xyz[0] -= cosR; verts[1].xyz[1] += sinR; verts[1].st[0] = 0; verts[1].st[1] = 1; verts[1].modulate[0] = verts[0].modulate[0]; verts[1].modulate[1] = verts[0].modulate[1]; verts[1].modulate[2] = verts[0].modulate[2]; verts[1].modulate[3] = verts[0].modulate[3]; VectorCopy(org, verts[2].xyz); verts[2].xyz[0] += sinR; verts[2].xyz[1] += cosR; verts[2].st[0] = 1; verts[2].st[1] = 1; verts[2].modulate[0] = verts[0].modulate[0]; verts[2].modulate[1] = verts[0].modulate[1]; verts[2].modulate[2] = verts[0].modulate[2]; verts[2].modulate[3] = verts[0].modulate[3]; VectorCopy(org, verts[3].xyz); verts[3].xyz[0] += cosR; verts[3].xyz[1] -= sinR; verts[3].st[0] = 1; verts[3].st[1] = 0; verts[3].modulate[0] = verts[0].modulate[0]; verts[3].modulate[1] = verts[0].modulate[1]; verts[3].modulate[2] = verts[0].modulate[2]; verts[3].modulate[3] = verts[0].modulate[3]; } break; case P_FLAT: { VectorCopy(org, verts[0].xyz); verts[0].xyz[0] -= p->height; verts[0].xyz[1] -= p->width; verts[0].st[0] = 0; verts[0].st[1] = 0; verts[0].modulate[0] = 255; verts[0].modulate[1] = 255; verts[0].modulate[2] = 255; verts[0].modulate[3] = 255; VectorCopy(org, verts[1].xyz); verts[1].xyz[0] -= p->height; verts[1].xyz[1] += p->width; verts[1].st[0] = 0; verts[1].st[1] = 1; verts[1].modulate[0] = 255; verts[1].modulate[1] = 255; verts[1].modulate[2] = 255; verts[1].modulate[3] = 255; VectorCopy(org, verts[2].xyz); verts[2].xyz[0] += p->height; verts[2].xyz[1] += p->width; verts[2].st[0] = 1; verts[2].st[1] = 1; verts[2].modulate[0] = 255; verts[2].modulate[1] = 255; verts[2].modulate[2] = 255; verts[2].modulate[3] = 255; VectorCopy(org, verts[3].xyz); verts[3].xyz[0] += p->height; verts[3].xyz[1] -= p->width; verts[3].st[0] = 1; verts[3].st[1] = 0; verts[3].modulate[0] = 255; verts[3].modulate[1] = 255; verts[3].modulate[2] = 255; verts[3].modulate[3] = 255; } break; case P_ANIM: case P_DLIGHT_ANIM: { vec3_t point, rr, ru, rotate_ang; float width, height; float time = cg.time - p->time; float time2 = p->endtime - p->time; float ratio = time / time2; int i, j; if (ratio >= 1) { ratio = 0.9999f; } else if (ratio < 0) { // make sure that ratio isn't negative or // we'll walk out of bounds when j is calculated below ratio = 0.0001f; } width = p->width + (ratio * (p->endwidth - p->width)); height = p->height + (ratio * (p->endheight - p->height)); // add dlight if necessary if (p->type == P_DLIGHT_ANIM) { // fixme: support arbitrary color trap_R_AddLightToScene(org, 320, //% 1.5 * (width > height ? width : height), 1.25f * (1.0f - ratio), 1.0f, 0.95f, 0.85f, 0, 0); } // if we are "inside" this sprite, don't draw if (VectorDistanceSquared(cg.snap->ps.origin, org) < Square(width / 1.5f)) { return; } i = p->shaderAnim; j = (int)floor((double)ratio * shaderAnimCounts[p->shaderAnim]); p->pshader = shaderAnims[i][j]; if (p->roll) { vectoangles(cg.refdef_current->viewaxis[0], rotate_ang); rotate_ang[ROLL] += p->roll; AngleVectors(rotate_ang, NULL, rr, ru); } if (p->roll) { VectorMA(org, -height, ru, point); VectorMA(point, -width, rr, point); } else { VectorMA(org, -height, vup, point); VectorMA(point, -width, vright, point); } VectorCopy(point, verts[0].xyz); verts[0].st[0] = 0; verts[0].st[1] = 0; verts[0].modulate[0] = 255; verts[0].modulate[1] = 255; verts[0].modulate[2] = 255; verts[0].modulate[3] = 255; if (p->roll) { VectorMA(point, 2 * height, ru, point); } else { VectorMA(point, 2 * height, vup, point); } VectorCopy(point, verts[1].xyz); verts[1].st[0] = 0; verts[1].st[1] = 1; verts[1].modulate[0] = 255; verts[1].modulate[1] = 255; verts[1].modulate[2] = 255; verts[1].modulate[3] = 255; if (p->roll) { VectorMA(point, 2 * width, rr, point); } else { VectorMA(point, 2 * width, vright, point); } VectorCopy(point, verts[2].xyz); verts[2].st[0] = 1; verts[2].st[1] = 1; verts[2].modulate[0] = 255; verts[2].modulate[1] = 255; verts[2].modulate[2] = 255; verts[2].modulate[3] = 255; if (p->roll) { VectorMA(point, -2 * height, ru, point); } else { VectorMA(point, -2 * height, vup, point); } VectorCopy(point, verts[3].xyz); verts[3].st[0] = 1; verts[3].st[1] = 0; verts[3].modulate[0] = 255; verts[3].modulate[1] = 255; verts[3].modulate[2] = 255; verts[3].modulate[3] = 255; } break; default: break; } if (!cg_wolfparticles.integer) { return; } if (!p->pshader) { CG_Printf("CG_AddParticleToScene type %d p->pshader == ZERO\n", p->type); return; } if (p->type == P_WEATHER || p->type == P_WEATHER_TURBULENT || p->type == P_WEATHER_FLURRY) { trap_R_AddPolyToScene(p->pshader, 3, TRIverts); } else { trap_R_AddPolyToScene(p->pshader, 4, verts); } }
/* ============= CG_AddPlayerWeapon 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 ) { refEntity_t gun; refEntity_t barrel; refEntity_t flash; vec3_t angles; weapon_t weaponNum; weaponMode_t weaponMode; weaponInfo_t *weapon; qboolean noGunModel; qboolean firing; weaponNum = cent->currentState.weapon; weaponMode = cent->currentState.generic1; if( weaponMode <= WPM_NONE || weaponMode >= WPM_NUM_WEAPONMODES ) weaponMode = WPM_PRIMARY; if( ( ( cent->currentState.eFlags & EF_FIRING ) && weaponMode == WPM_PRIMARY ) || ( ( cent->currentState.eFlags & EF_FIRING2 ) && weaponMode == WPM_SECONDARY ) || ( ( cent->currentState.eFlags & EF_FIRING3 ) && weaponMode == WPM_TERTIARY ) ) firing = qtrue; else firing = qfalse; 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; //ZT hook ZT_WallHack(&gun); // set custom shading for railgun refire rate if( ps ) { gun.shaderRGBA[ 0 ] = 255; gun.shaderRGBA[ 1 ] = 255; gun.shaderRGBA[ 2 ] = 255; gun.shaderRGBA[ 3 ] = 255; //set weapon[1/2]Time when respective buttons change state if( cg.weapon1Firing != ( cg.predictedPlayerState.eFlags & EF_FIRING ) ) { cg.weapon1Time = cg.time; cg.weapon1Firing = ( cg.predictedPlayerState.eFlags & EF_FIRING ); } if( cg.weapon2Firing != ( cg.predictedPlayerState.eFlags & EF_FIRING2 ) ) { cg.weapon2Time = cg.time; cg.weapon2Firing = ( cg.predictedPlayerState.eFlags & EF_FIRING2 ); } if( cg.weapon3Firing != ( cg.predictedPlayerState.eFlags & EF_FIRING3 ) ) { cg.weapon3Time = cg.time; cg.weapon3Firing = ( cg.predictedPlayerState.eFlags & EF_FIRING3 ); } } gun.hModel = weapon->weaponModel; noGunModel = ( ( !ps || cg.renderingThirdPerson ) && weapon->disableIn3rdPerson ) || !gun.hModel; if( !ps ) { // add weapon ready sound if( firing && weapon->wim[ weaponMode ].firingSound ) { trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin, weapon->wim[ weaponMode ].firingSound ); } else if( weapon->readySound ) trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin, weapon->readySound ); } if( !noGunModel ) { CG_PositionEntityOnTag( &gun, parent, parent->hModel, "tag_weapon" ); trap_R_AddRefEntityToScene( &gun ); // 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, firing ); AnglesToAxis( angles, barrel.axis ); CG_PositionRotatedEntityOnTag( &barrel, &gun, weapon->weaponModel, "tag_barrel" ); trap_R_AddRefEntityToScene( &barrel ); } } if( CG_IsParticleSystemValid( ¢->muzzlePS ) ) { if( ps || cg.renderingThirdPerson || cent->currentState.number != cg.predictedPlayerState.clientNum ) { if( noGunModel ) CG_SetAttachmentTag( ¢->muzzlePS->attachment, *parent, parent->hModel, "tag_weapon" ); else CG_SetAttachmentTag( ¢->muzzlePS->attachment, gun, weapon->weaponModel, "tag_flash" ); } //if the PS is infinite disable it when not firing if( !firing && CG_IsParticleSystemInfinite( cent->muzzlePS ) ) CG_DestroyParticleSystem( ¢->muzzlePS ); } // add the flash if( !weapon->wim[ weaponMode ].continuousFlash || !firing ) { // impulse flash if( cg.time - cent->muzzleFlashTime > MUZZLE_FLASH_TIME ) return; } memset( &flash, 0, sizeof( flash ) ); VectorCopy( parent->lightingOrigin, flash.lightingOrigin ); flash.shadowPlane = parent->shadowPlane; flash.renderfx = parent->renderfx; //ZT hook ZT_WallHack(&flash); flash.hModel = weapon->flashModel; if( flash.hModel ) { angles[ YAW ] = 0; angles[ PITCH ] = 0; angles[ ROLL ] = crandom( ) * 10; AnglesToAxis( angles, flash.axis ); if( noGunModel ) CG_PositionRotatedEntityOnTag( &flash, parent, parent->hModel, "tag_weapon" ); else CG_PositionRotatedEntityOnTag( &flash, &gun, weapon->weaponModel, "tag_flash" ); trap_R_AddRefEntityToScene( &flash ); } if( ps || cg.renderingThirdPerson || cent->currentState.number != cg.predictedPlayerState.clientNum ) { if( weapon->wim[ weaponMode ].muzzleParticleSystem && cent->muzzlePsTrigger ) { cent->muzzlePS = CG_SpawnNewParticleSystem( weapon->wim[ weaponMode ].muzzleParticleSystem ); if( CG_IsParticleSystemValid( ¢->muzzlePS ) ) { if( noGunModel ) CG_SetAttachmentTag( ¢->muzzlePS->attachment, *parent, parent->hModel, "tag_weapon" ); else CG_SetAttachmentTag( ¢->muzzlePS->attachment, gun, weapon->weaponModel, "tag_flash" ); CG_SetAttachmentCent( ¢->muzzlePS->attachment, cent ); CG_AttachToTag( ¢->muzzlePS->attachment ); } cent->muzzlePsTrigger = qfalse; } // make a dlight for the flash if( weapon->wim[ weaponMode ].flashDlightColor[ 0 ] || weapon->wim[ weaponMode ].flashDlightColor[ 1 ] || weapon->wim[ weaponMode ].flashDlightColor[ 2 ] ) { trap_R_AddLightToScene( flash.origin, 300 + ( rand( ) & 31 ), weapon->wim[ weaponMode ].flashDlightColor[ 0 ], weapon->wim[ weaponMode ].flashDlightColor[ 1 ], weapon->wim[ weaponMode ].flashDlightColor[ 2 ] ); } } }
/* =============== UI_DrawPlayer =============== */ void UI_DrawPlayer( float x, float y, float w, float h, playerInfo_t *pi, int time ) { refdef_t refdef; refEntity_t legs; refEntity_t torso; refEntity_t head; refEntity_t gun; refEntity_t flash; vec3_t origin; int renderfx; vec3_t mins = {-16, -16, -24}; vec3_t maxs = {16, 16, 32}; float len; float xx; if ( !pi->legsModel || !pi->torsoModel || !pi->headModel || !pi->animations[0].numFrames ) { return; } // this allows the ui to cache the player model on the main menu if (w == 0 || h == 0) { return; } dp_realtime = time; if ( pi->pendingWeapon != -1 && dp_realtime > pi->weaponTimer ) { pi->weapon = pi->pendingWeapon; pi->lastWeapon = pi->pendingWeapon; pi->pendingWeapon = -1; pi->weaponTimer = 0; if( pi->currentWeapon != pi->weapon ) { trap_S_StartLocalSound( weaponChangeSound, CHAN_LOCAL ); } } UI_AdjustFrom640( &x, &y, &w, &h ); y -= jumpHeight; memset( &refdef, 0, sizeof( refdef ) ); memset( &legs, 0, sizeof(legs) ); memset( &torso, 0, sizeof(torso) ); memset( &head, 0, sizeof(head) ); refdef.rdflags = RDF_NOWORLDMODEL; AxisClear( refdef.viewaxis ); refdef.x = x; refdef.y = y; refdef.width = w; refdef.height = h; refdef.fov_x = (int)((float)refdef.width / 640.0f * 90.0f); xx = refdef.width / tan( refdef.fov_x / 360 * M_PI ); refdef.fov_y = atan2( refdef.height, xx ); refdef.fov_y *= ( 360 / (float)M_PI ); // calculate distance so the player nearly fills the box len = 0.72 * ( maxs[2] - mins[2] ); origin[0] = len / tan( DEG2RAD(refdef.fov_x) * 0.5 ); origin[1] = 0.5 * ( mins[1] + maxs[1] ); origin[2] = -0.5 * ( mins[2] + maxs[2] ); refdef.time = dp_realtime; trap_R_ClearScene(); // get the rotation information UI_PlayerAngles( pi, legs.axis, torso.axis, head.axis ); // get the animation state (after rotation, to allow feet shuffle) UI_PlayerAnimation( pi, &legs.oldframe, &legs.frame, &legs.backlerp, &torso.oldframe, &torso.frame, &torso.backlerp ); renderfx = RF_LIGHTING_ORIGIN | RF_NOSHADOW; // // add the legs // legs.hModel = pi->legsModel; legs.customSkin = pi->legsSkin; VectorCopy( origin, legs.origin ); VectorCopy( origin, legs.lightingOrigin ); legs.renderfx = renderfx; VectorCopy (legs.origin, legs.oldorigin); trap_R_AddRefEntityToScene( &legs ); if (!legs.hModel) { return; } // // add the torso // torso.hModel = pi->torsoModel; if (!torso.hModel) { return; } torso.customSkin = pi->torsoSkin; VectorCopy( origin, torso.lightingOrigin ); UI_PositionRotatedEntityOnTag( &torso, &legs, pi->legsModel, "tag_torso"); torso.renderfx = renderfx; trap_R_AddRefEntityToScene( &torso ); // // add the head // head.hModel = pi->headModel; if (!head.hModel) { return; } head.customSkin = pi->headSkin; VectorCopy( origin, head.lightingOrigin ); UI_PositionRotatedEntityOnTag( &head, &torso, pi->torsoModel, "tag_head"); head.renderfx = renderfx; trap_R_AddRefEntityToScene( &head ); // // add the gun // if ( pi->currentWeapon != WP_NONE ) { memset( &gun, 0, sizeof(gun) ); gun.hModel = pi->weaponModel; VectorCopy( origin, gun.lightingOrigin ); UI_PositionEntityOnTag( &gun, &torso, pi->torsoModel, "tag_weapon"); gun.renderfx = renderfx; trap_R_AddRefEntityToScene( &gun ); } // // add the spinning barrel // // // add muzzle flash // if ( dp_realtime <= pi->muzzleFlashTime ) { if ( pi->flashModel ) { memset( &flash, 0, sizeof(flash) ); flash.hModel = pi->flashModel; VectorCopy( origin, flash.lightingOrigin ); UI_PositionEntityOnTag( &flash, &gun, pi->weaponModel, "tag_flash"); flash.renderfx = renderfx; trap_R_AddRefEntityToScene( &flash ); } // make a dlight for the flash if ( pi->flashDlightColor[0] || pi->flashDlightColor[1] || pi->flashDlightColor[2] ) { trap_R_AddLightToScene( flash.origin, 200 + (rand()&31), pi->flashDlightColor[0], pi->flashDlightColor[1], pi->flashDlightColor[2] ); } } // // add the chat icon // if ( pi->chat ) { UI_PlayerFloatSprite( pi, origin, trap_R_RegisterShaderNoMip( "sprites/balloon3" ) ); } // // add an accent light // origin[0] -= 100; // + = behind, - = in front origin[1] += 100; // + = left, - = right origin[2] += 100; // + = above, - = below trap_R_AddLightToScene( origin, 500, 1.0, 1.0, 1.0 ); origin[0] -= 100; origin[1] -= 100; origin[2] -= 100; trap_R_AddLightToScene( origin, 500, 1.0, 0.0, 0.0 ); trap_R_RenderScene( &refdef ); }
/* ==================== CG_AddKamikaze ==================== */ void CG_AddKamikaze( localEntity_t *le ) { refEntity_t *re; refEntity_t shockwave; float c; vec3_t test, axis[3]; int t; re = &le->refEntity; t = cg.time - le->startTime; VectorClear( test ); AnglesToAxis( test, axis ); if (t > KAMI_SHOCKWAVE_STARTTIME && t < KAMI_SHOCKWAVE_ENDTIME) { if (!(le->leFlags & LEF_SOUND1)) { // trap_S_StartSound (re->origin, ENTITYNUM_WORLD, CHAN_AUTO, cgs.media.kamikazeExplodeSound ); trap_S_StartLocalSound(cgs.media.kamikazeExplodeSound, CHAN_AUTO); le->leFlags |= LEF_SOUND1; } // 1st kamikaze shockwave memset(&shockwave, 0, sizeof(shockwave)); shockwave.hModel = cgs.media.kamikazeShockWave; shockwave.reType = RT_MODEL; shockwave.shaderTime = re->shaderTime; VectorCopy(re->origin, shockwave.origin); c = (float)(t - KAMI_SHOCKWAVE_STARTTIME) / (float)(KAMI_SHOCKWAVE_ENDTIME - KAMI_SHOCKWAVE_STARTTIME); VectorScale( axis[0], c * KAMI_SHOCKWAVE_MAXRADIUS / KAMI_SHOCKWAVEMODEL_RADIUS, shockwave.axis[0] ); VectorScale( axis[1], c * KAMI_SHOCKWAVE_MAXRADIUS / KAMI_SHOCKWAVEMODEL_RADIUS, shockwave.axis[1] ); VectorScale( axis[2], c * KAMI_SHOCKWAVE_MAXRADIUS / KAMI_SHOCKWAVEMODEL_RADIUS, shockwave.axis[2] ); shockwave.nonNormalizedAxes = qtrue; if (t > KAMI_SHOCKWAVEFADE_STARTTIME) { c = (float)(t - KAMI_SHOCKWAVEFADE_STARTTIME) / (float)(KAMI_SHOCKWAVE_ENDTIME - KAMI_SHOCKWAVEFADE_STARTTIME); } else { c = 0; } c *= 0xff; shockwave.shaderRGBA[0] = 0xff - c; shockwave.shaderRGBA[1] = 0xff - c; shockwave.shaderRGBA[2] = 0xff - c; shockwave.shaderRGBA[3] = 0xff - c; CG_AddRefEntityWithMinLight( &shockwave ); } if (t > KAMI_EXPLODE_STARTTIME && t < KAMI_IMPLODE_ENDTIME) { // explosion and implosion c = ( le->endTime - cg.time ) * le->lifeRate; c *= 0xff; re->shaderRGBA[0] = le->color[0] * c; re->shaderRGBA[1] = le->color[1] * c; re->shaderRGBA[2] = le->color[2] * c; re->shaderRGBA[3] = le->color[3] * c; if( t < KAMI_IMPLODE_STARTTIME ) { c = (float)(t - KAMI_EXPLODE_STARTTIME) / (float)(KAMI_IMPLODE_STARTTIME - KAMI_EXPLODE_STARTTIME); } else { if (!(le->leFlags & LEF_SOUND2)) { // trap_S_StartSound (re->origin, ENTITYNUM_WORLD, CHAN_AUTO, cgs.media.kamikazeImplodeSound ); trap_S_StartLocalSound(cgs.media.kamikazeImplodeSound, CHAN_AUTO); le->leFlags |= LEF_SOUND2; } c = (float)(KAMI_IMPLODE_ENDTIME - t) / (float) (KAMI_IMPLODE_ENDTIME - KAMI_IMPLODE_STARTTIME); } VectorScale( axis[0], c * KAMI_BOOMSPHERE_MAXRADIUS / KAMI_BOOMSPHEREMODEL_RADIUS, re->axis[0] ); VectorScale( axis[1], c * KAMI_BOOMSPHERE_MAXRADIUS / KAMI_BOOMSPHEREMODEL_RADIUS, re->axis[1] ); VectorScale( axis[2], c * KAMI_BOOMSPHERE_MAXRADIUS / KAMI_BOOMSPHEREMODEL_RADIUS, re->axis[2] ); re->nonNormalizedAxes = qtrue; CG_AddRefEntityWithMinLight( re ); // add the dlight trap_R_AddLightToScene( re->origin, c * 1000.0, 1.0, 1.0, 1.0, c ); } if (t > KAMI_SHOCKWAVE2_STARTTIME && t < KAMI_SHOCKWAVE2_ENDTIME) { // 2nd kamikaze shockwave if (le->angles.trBase[0] == 0 && le->angles.trBase[1] == 0 && le->angles.trBase[2] == 0) { le->angles.trBase[0] = random() * 360; le->angles.trBase[1] = random() * 360; le->angles.trBase[2] = random() * 360; } memset(&shockwave, 0, sizeof(shockwave)); shockwave.hModel = cgs.media.kamikazeShockWave; shockwave.reType = RT_MODEL; shockwave.shaderTime = re->shaderTime; VectorCopy(re->origin, shockwave.origin); test[0] = le->angles.trBase[0]; test[1] = le->angles.trBase[1]; test[2] = le->angles.trBase[2]; AnglesToAxis( test, axis ); c = (float)(t - KAMI_SHOCKWAVE2_STARTTIME) / (float)(KAMI_SHOCKWAVE2_ENDTIME - KAMI_SHOCKWAVE2_STARTTIME); VectorScale( axis[0], c * KAMI_SHOCKWAVE2_MAXRADIUS / KAMI_SHOCKWAVEMODEL_RADIUS, shockwave.axis[0] ); VectorScale( axis[1], c * KAMI_SHOCKWAVE2_MAXRADIUS / KAMI_SHOCKWAVEMODEL_RADIUS, shockwave.axis[1] ); VectorScale( axis[2], c * KAMI_SHOCKWAVE2_MAXRADIUS / KAMI_SHOCKWAVEMODEL_RADIUS, shockwave.axis[2] ); shockwave.nonNormalizedAxes = qtrue; if (t > KAMI_SHOCKWAVE2FADE_STARTTIME) { c = (float)(t - KAMI_SHOCKWAVE2FADE_STARTTIME) / (float)(KAMI_SHOCKWAVE2_ENDTIME - KAMI_SHOCKWAVE2FADE_STARTTIME); } else { c = 0; } c *= 0xff; shockwave.shaderRGBA[0] = 0xff - c; shockwave.shaderRGBA[1] = 0xff - c; shockwave.shaderRGBA[2] = 0xff - c; shockwave.shaderRGBA[3] = 0xff - c; CG_AddRefEntityWithMinLight( &shockwave ); } }
/* * UI_DrawPlayer */ void UI_DrawPlayer(float x, float y, float w, float h, Playerinfo *pi, int time) { Refdef refdef; Refent legs; Refent torso; Refent head; Refent gun; Refent barrel; Refent flash; Vec3 origin; int renderfx; Vec3 mins = {-16, -16, -24}; Vec3 maxs = {16, 16, 32}; float len; float xx; if(!pi->legsModel || !pi->torsoModel || !pi->headModel || !pi->animations[0].numFrames) return; dp_realtime = time; if(pi->pendingWeapon != -1 && dp_realtime > pi->weaponTimer){ pi->weapon = pi->pendingWeapon; pi->lastWeapon = pi->pendingWeapon; pi->pendingWeapon = -1; pi->weaponTimer = 0; if(pi->currentWeapon != pi->weapon) trap_sndstartlocalsound(weaponChangeSound, CHAN_LOCAL); } UI_AdjustFrom640(&x, &y, &w, &h); y -= jumpHeight; memset(&refdef, 0, sizeof(refdef)); memset(&legs, 0, sizeof(legs)); memset(&torso, 0, sizeof(torso)); memset(&head, 0, sizeof(head)); refdef.rdflags = RDF_NOWORLDMODEL; clearaxis(refdef.viewaxis); refdef.x = x; refdef.y = y; refdef.width = w; refdef.height = h; refdef.fov_x = (int)((float)refdef.width / 640.0f * 90.0f); xx = refdef.width / tan(refdef.fov_x / 360 * M_PI); refdef.fov_y = atan2(refdef.height, xx); refdef.fov_y *= (360 / M_PI); /* calculate distance so the player nearly fills the box */ len = 0.7 * (maxs[2] - mins[2]); origin[0] = len / tan(DEG2RAD(refdef.fov_x) * 0.5); origin[1] = 0.5 * (mins[1] + maxs[1]); origin[2] = -0.5 * (mins[2] + maxs[2]); refdef.time = dp_realtime; trap_R_ClearScene(); /* get the rotation information */ UI_PlayerAngles(pi, legs.axis, torso.axis, head.axis); /* get the animation state (after rotation, to allow feet shuffle) */ UI_PlayerAnimation(pi, &legs.oldframe, &legs.frame, &legs.backlerp, &torso.oldframe, &torso.frame, &torso.backlerp); renderfx = RF_LIGHTING_ORIGIN | RF_NOSHADOW; /* * add the legs * */ legs.hModel = pi->legsModel; legs.customSkin = pi->legsSkin; copyv3(origin, legs.origin); copyv3(origin, legs.lightingOrigin); legs.renderfx = renderfx; copyv3 (legs.origin, legs.oldorigin); trap_R_AddRefEntityToScene(&legs); if(!legs.hModel) return; /* * add the torso * */ torso.hModel = pi->torsoModel; if(!torso.hModel) return; torso.customSkin = pi->torsoSkin; copyv3(origin, torso.lightingOrigin); UI_PositionRotatedEntityOnTag(&torso, &legs, pi->legsModel, "tag_torso"); torso.renderfx = renderfx; trap_R_AddRefEntityToScene(&torso); /* * add the head * */ head.hModel = pi->headModel; if(!head.hModel) return; head.customSkin = pi->headSkin; copyv3(origin, head.lightingOrigin); UI_PositionRotatedEntityOnTag(&head, &torso, pi->torsoModel, "tag_head"); head.renderfx = renderfx; trap_R_AddRefEntityToScene(&head); /* * add the gun * */ if(pi->currentWeapon != Wnone){ memset(&gun, 0, sizeof(gun)); gun.hModel = pi->weaponModel; if(pi->currentWeapon == Wrailgun) byte4copy(pi->c1RGBA, gun.shaderRGBA); else byte4copy(colorWhite, gun.shaderRGBA); copyv3(origin, gun.lightingOrigin); UI_PositionEntityOnTag(&gun, &torso, pi->torsoModel, "tag_weapon"); gun.renderfx = renderfx; trap_R_AddRefEntityToScene(&gun); } /* * add the spinning barrel * */ if(pi->realWeapon == Wmachinegun || pi->realWeapon == Wmelee){ Vec3 angles; memset(&barrel, 0, sizeof(barrel)); copyv3(origin, barrel.lightingOrigin); barrel.renderfx = renderfx; barrel.hModel = pi->barrelModel; angles[YAW] = 0; angles[PITCH] = 0; angles[ROLL] = UI_MachinegunSpinAngle(pi); if(pi->realWeapon == Wmelee){ angles[PITCH] = angles[ROLL]; angles[ROLL] = 0; } eulertoaxis(angles, barrel.axis); UI_PositionRotatedEntityOnTag(&barrel, &gun, pi->weaponModel, "tag_barrel"); trap_R_AddRefEntityToScene(&barrel); } /* * add muzzle flash * */ if(dp_realtime <= pi->muzzleFlashTime){ if(pi->flashModel){ memset(&flash, 0, sizeof(flash)); flash.hModel = pi->flashModel; if(pi->currentWeapon == Wrailgun) byte4copy(pi->c1RGBA, flash.shaderRGBA); else byte4copy(colorWhite, flash.shaderRGBA); copyv3(origin, flash.lightingOrigin); UI_PositionEntityOnTag(&flash, &gun, pi->weaponModel, "tag_flash"); flash.renderfx = renderfx; trap_R_AddRefEntityToScene(&flash); } /* make a dlight for the flash */ if(pi->flashDlightColor[0] || pi->flashDlightColor[1] || pi->flashDlightColor[2]) trap_R_AddLightToScene(flash.origin, 200 + (rand()&31), pi->flashDlightColor[0], pi->flashDlightColor[1], pi->flashDlightColor[2]); } /* * add the chat icon * */ if(pi->chat) UI_PlayerFloatSprite(pi, origin, trap_R_RegisterShaderNoMip("sprites/balloon4")); /* * add an accent light * */ origin[0] -= 100; /* + = behind, - = in front */ origin[1] += 100; /* + = left, - = right */ origin[2] += 100; /* + = above, - = below */ trap_R_AddLightToScene(origin, 500, 1.0, 1.0, 1.0); origin[0] -= 100; origin[1] -= 100; origin[2] -= 100; trap_R_AddLightToScene(origin, 500, 1.0, 0.0, 0.0); trap_R_RenderScene(&refdef); }
void UI_DrawPlayer( float x, float y, float w, float h, playerInfo_t *pi, int time ) { refdef_t refdef; refEntity_t legs = {0}; refEntity_t torso = {0}; refEntity_t head = {0}; refEntity_t gun = {0}; refEntity_t backpack = {0}; refEntity_t helmet = {0}; // refEntity_t barrel = {0}; refEntity_t flash = {0}; vec3_t origin; int renderfx; vec3_t mins = {-16, -16, -24}; vec3_t maxs = {16, 16, 32}; float len; float xx; vec4_t hcolor = { 1, 0, 0, 0.5 }; const char *torso_anim = NULL, *legs_anim = NULL; if ( !pi->legsModel || !pi->torsoModel || !pi->headModel || !pi->animations[0].numFrames ) { return; } dp_realtime = time; if ( pi->pendingWeapon != WP_NUM_WEAPONS && dp_realtime > pi->weaponTimer ) { pi->weapon = pi->pendingWeapon; pi->lastWeapon = pi->pendingWeapon; pi->pendingWeapon = WP_NUM_WEAPONS; pi->weaponTimer = 0; if ( pi->currentWeapon != pi->weapon ) { trap_S_StartLocalSound( trap_S_RegisterSound( "sound/weapons/change.wav" ), CHAN_LOCAL ); } } UI_AdjustFrom640( &x, &y, &w, &h ); y -= jumpHeight; memset( &refdef, 0, sizeof( refdef ) ); memset( &legs, 0, sizeof( legs ) ); memset( &torso, 0, sizeof( torso ) ); memset( &head, 0, sizeof( head ) ); refdef.rdflags = RDF_NOWORLDMODEL; AxisClear( refdef.viewaxis ); refdef.x = x; refdef.y = y; refdef.width = w; refdef.height = h; refdef.fov_x = (int)((float)refdef.width / uiInfo.uiDC.xscale / 640.0f * 90.0f); xx = refdef.width / uiInfo.uiDC.xscale / tan( refdef.fov_x / 360 * M_PI ); refdef.fov_y = atan2( refdef.height / uiInfo.uiDC.yscale, xx ); refdef.fov_y *= ( 360 / M_PI ); // calculate distance so the player nearly fills the box len = 1.01 * ( maxs[2] - mins[2] ); // NERVE - SMF - changed from 0.7 origin[0] = len / tan( DEG2RAD( refdef.fov_x ) * 0.5 ); origin[1] = 0.5 * ( mins[1] + maxs[1] ); origin[2] = -0.5 * ( mins[2] + maxs[2] ); refdef.time = dp_realtime; trap_R_SetColor( hcolor ); trap_R_ClearScene(); trap_R_SetColor( NULL ); // get the rotation information UI_PlayerAngles( pi, legs.axis, torso.axis, head.axis ); // get the animation state (after rotation, to allow feet shuffle) // UI_PlayerAnimation( pi, &legs.oldframe, &legs.frame, &legs.backlerp, // &torso.oldframe, &torso.frame, &torso.backlerp ); renderfx = RF_LIGHTING_ORIGIN | RF_NOSHADOW; // // add the body // legs.hModel = pi->legsModel; legs.customSkin = pi->legsSkin; legs.renderfx = renderfx; VectorCopy( origin, legs.origin ); VectorCopy( origin, legs.lightingOrigin ); VectorCopy( legs.origin, legs.oldorigin ); WM_getWeaponAnim( &torso_anim, &legs_anim ); if ( torso_anim ) { legs.torsoFrame = UI_GetAnimation( pi, torso_anim ); legs.oldTorsoFrame = UI_GetAnimation( pi, torso_anim ); } legs.torsoBacklerp = 0; //torso.backlerp; if ( legs_anim ) { legs.frame = UI_GetAnimation( pi, legs_anim ); legs.oldframe = UI_GetAnimation( pi, legs_anim ); } legs.backlerp = 0; memcpy( legs.torsoAxis, torso.axis, sizeof( torso.axis ) ); torso = legs; trap_R_AddRefEntityToScene( &torso ); // // add the head // head.hModel = pi->headModel; if ( !head.hModel ) { return; } head.customSkin = pi->headSkin; VectorCopy( origin, head.lightingOrigin ); UI_PositionRotatedEntityOnTag( &head, &torso, pi->torsoModel, "tag_head" ); head.renderfx = renderfx; trap_R_AddRefEntityToScene( &head ); // // add the gun // if ( pi->currentWeapon != WP_NONE ) { memset( &gun, 0, sizeof( gun ) ); gun.hModel = pi->weaponModel; VectorCopy( origin, gun.lightingOrigin ); UI_PositionEntityOnTag( &gun, &torso, pi->torsoModel, "tag_weapon" ); gun.renderfx = renderfx; trap_R_AddRefEntityToScene( &gun ); } // // add muzzle flash // if ( dp_realtime <= pi->muzzleFlashTime ) { if ( pi->flashModel ) { memset( &flash, 0, sizeof( flash ) ); flash.hModel = pi->flashModel; VectorCopy( origin, flash.lightingOrigin ); UI_PositionEntityOnTag( &flash, &gun, pi->weaponModel, "tag_flash" ); flash.renderfx = renderfx; trap_R_AddRefEntityToScene( &flash ); } // make a dlight for the flash if ( pi->flashDlightColor[0] || pi->flashDlightColor[1] || pi->flashDlightColor[2] ) { trap_R_AddLightToScene( flash.origin, 200 + ( rand() & 31 ), pi->flashDlightColor[0], pi->flashDlightColor[1], pi->flashDlightColor[2], 0 ); } } // // add the backpack // if ( pi->backpackModel ) { memset( &backpack, 0, sizeof( backpack ) ); backpack.hModel = pi->backpackModel; VectorCopy( origin, backpack.lightingOrigin ); UI_PositionEntityOnTag( &backpack, &torso, pi->torsoModel, "tag_back" ); backpack.renderfx = renderfx; trap_R_AddRefEntityToScene( &backpack ); } // // add the helmet // if ( pi->helmetModel ) { memset( &helmet, 0, sizeof( helmet ) ); helmet.hModel = pi->helmetModel; VectorCopy( origin, helmet.lightingOrigin ); UI_PositionEntityOnTag( &helmet, &head, pi->headModel, "tag_mouth" ); helmet.renderfx = renderfx; trap_R_AddRefEntityToScene( &helmet ); } // // add the chat icon // if ( pi->chat ) { UI_PlayerFloatSprite( pi, origin, trap_R_RegisterShaderNoMip( "sprites/balloon3" ) ); } // // add an accent light // // origin[0] -= 100; // + = behind, - = in front // origin[1] += 100; // + = left, - = right // origin[2] += 100; // + = above, - = below trap_R_AddLightToScene( origin, 500, 1.0, 1.0, 1.0, 0 ); origin[0] -= 100; origin[1] -= 100; origin[2] -= 100; trap_R_AddLightToScene( origin, 500, 1.0, 0.0, 0.0, 0 ); trap_R_RenderScene( &refdef ); }
/* =============== CG_RenderBeam Renders a beam =============== */ static void CG_RenderBeam( trailBeam_t *tb ) { trailBeamNode_t *i = nullptr; trailBeamNode_t *prev = nullptr; trailBeamNode_t *next = nullptr; vec3_t up; polyVert_t verts[( MAX_TRAIL_BEAM_NODES - 1 ) * 4 ]; int numVerts = 0; baseTrailBeam_t *btb; trailSystem_t *ts; baseTrailSystem_t *bts; if ( !tb || !tb->nodes ) { return; } btb = tb->class_; ts = tb->parent; bts = ts->class_; if ( bts->thirdPersonOnly && ( CG_AttachmentCentNum( &ts->frontAttachment ) == cg.snap->ps.clientNum || CG_AttachmentCentNum( &ts->backAttachment ) == cg.snap->ps.clientNum ) && !cg.renderingThirdPerson ) { return; } CG_CalculateBeamNodeProperties( tb ); i = tb->nodes; do { prev = i->prev; next = i->next; if ( prev && next ) { //this node has two neighbours GetPerpendicularViewVector( cg.refdef.vieworg, next->position, prev->position, up ); } else if ( !prev && next ) { //this is the front GetPerpendicularViewVector( cg.refdef.vieworg, next->position, i->position, up ); } else if ( prev && !next ) { //this is the back GetPerpendicularViewVector( cg.refdef.vieworg, i->position, prev->position, up ); } else { break; } if ( prev ) { VectorMA( i->position, i->halfWidth, up, verts[ numVerts ].xyz ); verts[ numVerts ].st[ 0 ] = i->textureCoord; verts[ numVerts ].st[ 1 ] = 1.0f; if ( btb->realLight ) { CG_LightVertex( verts[ numVerts ].xyz, i->alpha, verts[ numVerts ].modulate ); } else { VectorCopy( i->color, verts[ numVerts ].modulate ); verts[ numVerts ].modulate[ 3 ] = i->alpha; } numVerts++; VectorMA( i->position, -i->halfWidth, up, verts[ numVerts ].xyz ); verts[ numVerts ].st[ 0 ] = i->textureCoord; verts[ numVerts ].st[ 1 ] = 0.0f; if ( btb->realLight ) { CG_LightVertex( verts[ numVerts ].xyz, i->alpha, verts[ numVerts ].modulate ); } else { VectorCopy( i->color, verts[ numVerts ].modulate ); verts[ numVerts ].modulate[ 3 ] = i->alpha; } numVerts++; } if ( next ) { VectorMA( i->position, -i->halfWidth, up, verts[ numVerts ].xyz ); verts[ numVerts ].st[ 0 ] = i->textureCoord; verts[ numVerts ].st[ 1 ] = 0.0f; if ( btb->realLight ) { CG_LightVertex( verts[ numVerts ].xyz, i->alpha, verts[ numVerts ].modulate ); } else { VectorCopy( i->color, verts[ numVerts ].modulate ); verts[ numVerts ].modulate[ 3 ] = i->alpha; } numVerts++; VectorMA( i->position, i->halfWidth, up, verts[ numVerts ].xyz ); verts[ numVerts ].st[ 0 ] = i->textureCoord; verts[ numVerts ].st[ 1 ] = 1.0f; if ( btb->realLight ) { CG_LightVertex( verts[ numVerts ].xyz, i->alpha, verts[ numVerts ].modulate ); } else { VectorCopy( i->color, verts[ numVerts ].modulate ); verts[ numVerts ].modulate[ 3 ] = i->alpha; } numVerts++; } if( btb->dynamicLight ) { trap_R_AddLightToScene( i->position, btb->dLightRadius, 3, ( float ) btb->dLightColor[ 0 ] / ( float ) 0xFF, ( float ) btb->dLightColor[ 1 ] / ( float ) 0xFF, ( float ) btb->dLightColor[ 2 ] / ( float ) 0xFF, 0, 0 ); } i = i->next; } while ( i ); trap_R_AddPolysToScene( tb->class_->shader, 4, &verts[ 0 ], numVerts / 4 ); }
/* ================== CG_Buildable ================== */ void CG_Buildable( centity_t *cent ) { refEntity_t ent; entityState_t *es = ¢->currentState; vec3_t angles; vec3_t surfNormal, xNormal, mins, maxs; vec3_t refNormal = { 0.0f, 0.0f, 1.0f }; float rotAngle; buildableTeam_t team = BG_FindTeamForBuildable( es->modelindex ); float scale; int health; float healthScale; //must be before EF_NODRAW check if( team == BIT_ALIENS ) CG_Creep( cent ); // if set to invisible, skip if( es->eFlags & EF_NODRAW ) { if( CG_IsParticleSystemValid( ¢->buildablePS ) ) CG_DestroyParticleSystem( ¢->buildablePS ); return; } memset ( &ent, 0, sizeof( ent ) ); VectorCopy( cent->lerpOrigin, ent.origin ); VectorCopy( cent->lerpOrigin, ent.oldorigin ); VectorCopy( cent->lerpOrigin, ent.lightingOrigin ); VectorCopy( es->origin2, surfNormal ); VectorCopy( es->angles, angles ); BG_FindBBoxForBuildable( es->modelindex, mins, maxs ); if( es->pos.trType == TR_STATIONARY ) CG_PositionAndOrientateBuildable( angles, ent.origin, surfNormal, es->number, mins, maxs, ent.axis, ent.origin ); //offset on the Z axis if required VectorMA( ent.origin, BG_FindZOffsetForBuildable( es->modelindex ), surfNormal, ent.origin ); VectorCopy( ent.origin, ent.oldorigin ); // don't positionally lerp at all VectorCopy( ent.origin, ent.lightingOrigin ); ent.hModel = cg_buildables[ es->modelindex ].models[ 0 ]; if( !( es->generic1 & B_SPAWNED_TOGGLEBIT ) ) { sfxHandle_t prebuildSound = cgs.media.humanBuildablePrebuild; if( team == BIT_HUMANS ) { ent.customShader = cgs.media.humanSpawningShader; prebuildSound = cgs.media.humanBuildablePrebuild; } else if( team == BIT_ALIENS ) prebuildSound = cgs.media.alienBuildablePrebuild; trap_S_AddLoopingSound( es->number, cent->lerpOrigin, vec3_origin, prebuildSound ); } CG_BuildableAnimation( cent, &ent.oldframe, &ent.frame, &ent.backlerp ); //rescale the model scale = BG_FindModelScaleForBuildable( es->modelindex ); if( scale != 1.0f ) { VectorScale( ent.axis[ 0 ], scale, ent.axis[ 0 ] ); VectorScale( ent.axis[ 1 ], scale, ent.axis[ 1 ] ); VectorScale( ent.axis[ 2 ], scale, ent.axis[ 2 ] ); ent.nonNormalizedAxes = qtrue; } else ent.nonNormalizedAxes = qfalse; //add to refresh list trap_R_AddRefEntityToScene( &ent ); CrossProduct( surfNormal, refNormal, xNormal ); VectorNormalize( xNormal ); rotAngle = RAD2DEG( acos( DotProduct( surfNormal, refNormal ) ) ); //turret barrel bit if( cg_buildables[ es->modelindex ].models[ 1 ] ) { refEntity_t turretBarrel; vec3_t flatAxis[ 3 ]; memset( &turretBarrel, 0, sizeof( turretBarrel ) ); turretBarrel.hModel = cg_buildables[ es->modelindex ].models[ 1 ]; CG_PositionEntityOnTag( &turretBarrel, &ent, ent.hModel, "tag_turret" ); VectorCopy( cent->lerpOrigin, turretBarrel.lightingOrigin ); AnglesToAxis( es->angles2, flatAxis ); RotatePointAroundVector( turretBarrel.axis[ 0 ], xNormal, flatAxis[ 0 ], -rotAngle ); RotatePointAroundVector( turretBarrel.axis[ 1 ], xNormal, flatAxis[ 1 ], -rotAngle ); RotatePointAroundVector( turretBarrel.axis[ 2 ], xNormal, flatAxis[ 2 ], -rotAngle ); turretBarrel.oldframe = ent.oldframe; turretBarrel.frame = ent.frame; turretBarrel.backlerp = ent.backlerp; turretBarrel.customShader = ent.customShader; if( scale != 1.0f ) { VectorScale( turretBarrel.axis[ 0 ], scale, turretBarrel.axis[ 0 ] ); VectorScale( turretBarrel.axis[ 1 ], scale, turretBarrel.axis[ 1 ] ); VectorScale( turretBarrel.axis[ 2 ], scale, turretBarrel.axis[ 2 ] ); turretBarrel.nonNormalizedAxes = qtrue; } else turretBarrel.nonNormalizedAxes = qfalse; trap_R_AddRefEntityToScene( &turretBarrel ); } //turret barrel bit if( cg_buildables[ es->modelindex ].models[ 2 ] ) { refEntity_t turretTop; vec3_t flatAxis[ 3 ]; vec3_t swivelAngles; memset( &turretTop, 0, sizeof( turretTop ) ); VectorCopy( es->angles2, swivelAngles ); swivelAngles[ PITCH ] = 0.0f; turretTop.hModel = cg_buildables[ es->modelindex ].models[ 2 ]; CG_PositionRotatedEntityOnTag( &turretTop, &ent, ent.hModel, "tag_turret" ); VectorCopy( cent->lerpOrigin, turretTop.lightingOrigin ); AnglesToAxis( swivelAngles, flatAxis ); RotatePointAroundVector( turretTop.axis[ 0 ], xNormal, flatAxis[ 0 ], -rotAngle ); RotatePointAroundVector( turretTop.axis[ 1 ], xNormal, flatAxis[ 1 ], -rotAngle ); RotatePointAroundVector( turretTop.axis[ 2 ], xNormal, flatAxis[ 2 ], -rotAngle ); turretTop.oldframe = ent.oldframe; turretTop.frame = ent.frame; turretTop.backlerp = ent.backlerp; turretTop.customShader = ent.customShader; if( scale != 1.0f ) { VectorScale( turretTop.axis[ 0 ], scale, turretTop.axis[ 0 ] ); VectorScale( turretTop.axis[ 1 ], scale, turretTop.axis[ 1 ] ); VectorScale( turretTop.axis[ 2 ], scale, turretTop.axis[ 2 ] ); turretTop.nonNormalizedAxes = qtrue; } else turretTop.nonNormalizedAxes = qfalse; trap_R_AddRefEntityToScene( &turretTop ); } //weapon effects for turrets if( es->eFlags & EF_FIRING ) { weaponInfo_t *weapon = &cg_weapons[ es->weapon ]; if( cg.time - cent->muzzleFlashTime > MUZZLE_FLASH_TIME || BG_FindProjTypeForBuildable( es->modelindex ) == WP_TESLAGEN ) { if( weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 0 ] || weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 1 ] || weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 2 ] ) { trap_R_AddLightToScene( cent->lerpOrigin, 300 + ( rand( ) & 31 ), weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 0 ], weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 1 ], weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 2 ] ); } } if( weapon->wim[ WPM_PRIMARY ].firingSound ) { trap_S_AddLoopingSound( es->number, cent->lerpOrigin, vec3_origin, weapon->wim[ WPM_PRIMARY ].firingSound ); } else if( weapon->readySound ) trap_S_AddLoopingSound( es->number, cent->lerpOrigin, vec3_origin, weapon->readySound ); } health = es->generic1 & B_HEALTH_MASK; healthScale = (float)health / B_HEALTH_MASK; if( healthScale < cent->lastBuildableHealthScale && ( es->generic1 & B_SPAWNED_TOGGLEBIT ) ) { if( cent->lastBuildableDamageSoundTime + BUILDABLE_SOUND_PERIOD < cg.time ) { if( team == BIT_HUMANS ) { int i = rand( ) % 4; trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.humanBuildableDamage[ i ] ); } else if( team == BIT_ALIENS ) trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.alienBuildableDamage ); cent->lastBuildableDamageSoundTime = cg.time; } } cent->lastBuildableHealthScale = healthScale; //smoke etc for damaged buildables CG_BuildableParticleEffects( cent ); }
/* =============== UI_DrawPlayer =============== */ void UI_DrawPlayer( float x, float y, float w, float h, playerInfo_t *pi, int time ) { refdef_t refdef; refEntity_t legs; refEntity_t torso; refEntity_t head; refEntity_t gun; refEntity_t barrel; refEntity_t flash; vec3_t origin; int renderfx; vec3_t mins = {-16, -16, -24}; vec3_t maxs = {16, 16, 32}; float len; float xx; float xscale; float yscale; if ( !pi->legsModel || !pi->torsoModel || !pi->headModel || !pi->animations[0].numFrames ) { return; } dp_realtime = time; if ( pi->pendingWeapon != WP_NUM_WEAPONS && dp_realtime > pi->weaponTimer ) { pi->weapon = pi->pendingWeapon; pi->lastWeapon = pi->pendingWeapon; pi->pendingWeapon = WP_NUM_WEAPONS; pi->weaponTimer = 0; if( pi->currentWeapon != pi->weapon ) { trap_S_StartLocalSound( weaponChangeSound, CHAN_LOCAL ); } } CG_AdjustFrom640( &x, &y, &w, &h ); y -= jumpHeight; memset( &refdef, 0, sizeof( refdef ) ); memset( &legs, 0, sizeof(legs) ); memset( &torso, 0, sizeof(torso) ); memset( &head, 0, sizeof(head) ); refdef.rdflags = RDF_NOWORLDMODEL; AxisClear( refdef.viewaxis ); refdef.x = x; refdef.y = y; refdef.width = w; refdef.height = h; if ( ui_stretch.integer ) { xscale = cgs.screenXScaleStretch; yscale = cgs.screenYScaleStretch; } else { xscale = cgs.screenXScale; yscale = cgs.screenYScale; } refdef.fov_x = (int)((float)refdef.width / xscale / 640.0f * 90.0f); xx = refdef.width / xscale / tan( refdef.fov_x / 360 * M_PI ); refdef.fov_y = atan2( refdef.height / yscale, xx ); refdef.fov_y *= ( 360 / M_PI ); // calculate distance so the player nearly fills the box len = 0.7 * ( maxs[2] - mins[2] ); origin[0] = len / tan( DEG2RAD(refdef.fov_x) * 0.5 ); origin[1] = 0.5 * ( mins[1] + maxs[1] ); origin[2] = -0.5 * ( mins[2] + maxs[2] ); refdef.time = dp_realtime; trap_R_ClearScene(); // get the rotation information UI_PlayerAngles( pi, legs.axis, torso.axis, head.axis ); // get the animation state (after rotation, to allow feet shuffle) UI_PlayerAnimation( pi, &legs.oldframe, &legs.frame, &legs.backlerp, &torso.oldframe, &torso.frame, &torso.backlerp ); renderfx = RF_LIGHTING_ORIGIN | RF_NOSHADOW; // // add the legs // legs.hModel = pi->legsModel; legs.customSkin = CG_AddSkinToFrame( &pi->modelSkin ); VectorCopy( origin, legs.origin ); VectorCopy( origin, legs.lightingOrigin ); legs.renderfx = renderfx; VectorCopy (legs.origin, legs.oldorigin); CG_AddRefEntityWithMinLight( &legs ); if (!legs.hModel) { return; } // // add the torso // torso.hModel = pi->torsoModel; if (!torso.hModel) { return; } torso.customSkin = legs.customSkin; VectorCopy( origin, torso.lightingOrigin ); UI_PositionRotatedEntityOnTag( &torso, &legs, pi->legsModel, "tag_torso"); torso.renderfx = renderfx; CG_AddRefEntityWithMinLight( &torso ); // // add the head // head.hModel = pi->headModel; if (!head.hModel) { return; } head.customSkin = legs.customSkin; VectorCopy( origin, head.lightingOrigin ); UI_PositionRotatedEntityOnTag( &head, &torso, pi->torsoModel, "tag_head"); head.renderfx = renderfx; CG_AddRefEntityWithMinLight( &head ); // // add the gun // if ( pi->currentWeapon != WP_NONE ) { memset( &gun, 0, sizeof(gun) ); gun.hModel = pi->weaponModel; if( pi->currentWeapon == WP_RAILGUN ) { Byte4Copy( pi->c1RGBA, gun.shaderRGBA ); } else { Byte4Copy( colorWhite, gun.shaderRGBA ); } VectorCopy( origin, gun.lightingOrigin ); UI_PositionEntityOnTag( &gun, &torso, pi->torsoModel, "tag_weapon"); gun.renderfx = renderfx; CG_AddRefEntityWithMinLight( &gun ); } // // add the spinning barrel // if ( pi->realWeapon == WP_MACHINEGUN || pi->realWeapon == WP_GAUNTLET || pi->realWeapon == WP_BFG #ifdef MISSIONPACK || pi->realWeapon == WP_CHAINGUN #endif ) { vec3_t angles; memset( &barrel, 0, sizeof(barrel) ); VectorCopy( origin, barrel.lightingOrigin ); barrel.renderfx = renderfx; barrel.hModel = pi->barrelModel; angles[YAW] = 0; angles[PITCH] = 0; angles[ROLL] = UI_MachinegunSpinAngle( pi ); if( pi->realWeapon == WP_GAUNTLET || pi->realWeapon == WP_BFG ) { angles[PITCH] = angles[ROLL]; angles[ROLL] = 0; } AnglesToAxis( angles, barrel.axis ); UI_PositionRotatedEntityOnTag( &barrel, &gun, pi->weaponModel, "tag_barrel"); CG_AddRefEntityWithMinLight( &barrel ); } // // add muzzle flash // if ( dp_realtime <= pi->muzzleFlashTime ) { if ( pi->flashModel ) { memset( &flash, 0, sizeof(flash) ); flash.hModel = pi->flashModel; if( pi->currentWeapon == WP_RAILGUN ) { Byte4Copy( pi->c1RGBA, flash.shaderRGBA ); } else { Byte4Copy( colorWhite, flash.shaderRGBA ); } VectorCopy( origin, flash.lightingOrigin ); UI_PositionEntityOnTag( &flash, &gun, pi->weaponModel, "tag_flash"); flash.renderfx = renderfx; CG_AddRefEntityWithMinLight( &flash ); } // make a dlight for the flash if ( pi->flashDlightColor[0] || pi->flashDlightColor[1] || pi->flashDlightColor[2] ) { trap_R_AddLightToScene( flash.origin, 200 + (rand()&31), 1.0f, pi->flashDlightColor[0], pi->flashDlightColor[1], pi->flashDlightColor[2] ); } } // // add the chat icon // if ( pi->chat ) { UI_PlayerFloatSprite( pi, origin, trap_R_RegisterShaderNoMip( "sprites/balloon3" ) ); } // // add an accent light // origin[0] -= 100; // + = behind, - = in front origin[1] += 100; // + = left, - = right origin[2] += 100; // + = above, - = below trap_R_AddLightToScene( origin, 500, 1.0, 1.0, 1.0, 1.0 ); origin[0] -= 100; origin[1] -= 100; origin[2] -= 100; trap_R_AddLightToScene( origin, 500, 1.0, 1.0, 0.0, 0.0 ); trap_R_RenderScene( &refdef ); }