📄 cg_effects.c
字号:
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//
// cg_effects.c -- these functions generate localentities, usually as a result
// of event processing
#include "cg_local.h"
/*
==================
CG_BubbleTrail
Bullets shot underwater
==================
*/
void CG_BubbleTrail( vec3_t start, vec3_t end, float spacing ) {
vec3_t move;
vec3_t vec;
float len;
int i;
if ( cg_noProjectileTrail.integer ) {
return;
}
VectorCopy (start, move);
VectorSubtract (end, start, vec);
len = VectorNormalize (vec);
// advance a random amount first
i = rand() % (int)spacing;
VectorMA( move, i, vec, move );
VectorScale (vec, spacing, vec);
for ( ; i < len; i += spacing ) {
localEntity_t *le;
refEntity_t *re;
le = CG_AllocLocalEntity();
le->leFlags = LEF_PUFF_DONT_SCALE;
le->leType = LE_MOVE_SCALE_FADE;
le->startTime = cg.time;
le->endTime = cg.time + 1000 + random() * 250;
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
re = &le->refEntity;
re->shaderTime = cg.time / 1000.0f;
re->reType = RT_SPRITE;
re->rotation = 0;
re->radius = 3;
re->customShader = cgs.media.waterBubbleShader;
re->shaderRGBA[0] = 0xff;
re->shaderRGBA[1] = 0xff;
re->shaderRGBA[2] = 0xff;
re->shaderRGBA[3] = 0xff;
le->color[3] = 1.0;
le->pos.trType = TR_LINEAR;
le->pos.trTime = cg.time;
VectorCopy( move, le->pos.trBase );
le->pos.trDelta[0] = crandom()*5;
le->pos.trDelta[1] = crandom()*5;
le->pos.trDelta[2] = crandom()*5 + 6;
VectorAdd (move, vec, move);
}
}
/*
=====================
CG_SmokePuff
Adds a smoke puff or blood trail localEntity.
=====================
*/
localEntity_t *CG_SmokePuff( const vec3_t p, const vec3_t vel,
float radius,
float r, float g, float b, float a,
float duration,
int startTime,
int fadeInTime,
int leFlags,
qhandle_t hShader ) {
static int seed = 0x92;
localEntity_t *le;
refEntity_t *re;
// int fadeInTime = startTime + duration / 2;
le = CG_AllocLocalEntity();
le->leFlags = leFlags;
le->radius = radius;
re = &le->refEntity;
re->rotation = Q_random( &seed ) * 360;
re->radius = radius;
re->shaderTime = startTime / 1000.0f;
le->leType = LE_MOVE_SCALE_FADE;
le->startTime = startTime;
le->fadeInTime = fadeInTime;
le->endTime = startTime + duration;
if ( fadeInTime > startTime ) {
le->lifeRate = 1.0 / ( le->endTime - le->fadeInTime );
}
else {
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
}
le->color[0] = r;
le->color[1] = g;
le->color[2] = b;
le->color[3] = a;
le->pos.trType = TR_LINEAR;
le->pos.trTime = startTime;
VectorCopy( vel, le->pos.trDelta );
VectorCopy( p, le->pos.trBase );
VectorCopy( p, re->origin );
re->customShader = hShader;
// rage pro can't alpha fade, so use a different shader
if ( cgs.glconfig.hardwareType == GLHW_RAGEPRO ) {
re->customShader = cgs.media.smokePuffRageProShader;
re->shaderRGBA[0] = 0xff;
re->shaderRGBA[1] = 0xff;
re->shaderRGBA[2] = 0xff;
re->shaderRGBA[3] = 0xff;
} else {
re->shaderRGBA[0] = le->color[0] * 0xff;
re->shaderRGBA[1] = le->color[1] * 0xff;
re->shaderRGBA[2] = le->color[2] * 0xff;
re->shaderRGBA[3] = 0xff;
}
re->reType = RT_SPRITE;
re->radius = le->radius;
return le;
}
/*
==================
CG_SpawnEffect
Player teleporting in or out
==================
*/
void CG_SpawnEffect( vec3_t org ) {
localEntity_t *le;
refEntity_t *re;
le = CG_AllocLocalEntity();
le->leFlags = 0;
le->leType = LE_FADE_RGB;
le->startTime = cg.time;
le->endTime = cg.time + 500;
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
le->color[0] = le->color[1] = le->color[2] = le->color[3] = 1.0;
re = &le->refEntity;
re->reType = RT_MODEL;
re->shaderTime = cg.time / 1000.0f;
#ifndef MISSIONPACK
re->customShader = cgs.media.teleportEffectShader;
#endif
re->hModel = cgs.media.teleportEffectModel;
AxisClear( re->axis );
VectorCopy( org, re->origin );
#ifdef MISSIONPACK
re->origin[2] += 16;
#else
re->origin[2] -= 24;
#endif
}
#ifdef MISSIONPACK
/*
===============
CG_LightningBoltBeam
===============
*/
void CG_LightningBoltBeam( vec3_t start, vec3_t end ) {
localEntity_t *le;
refEntity_t *beam;
le = CG_AllocLocalEntity();
le->leFlags = 0;
le->leType = LE_SHOWREFENTITY;
le->startTime = cg.time;
le->endTime = cg.time + 50;
beam = &le->refEntity;
VectorCopy( start, beam->origin );
// this is the end point
VectorCopy( end, beam->oldorigin );
beam->reType = RT_LIGHTNING;
beam->customShader = cgs.media.lightningShader;
}
/*
==================
CG_KamikazeEffect
==================
*/
void CG_KamikazeEffect( vec3_t org ) {
localEntity_t *le;
refEntity_t *re;
le = CG_AllocLocalEntity();
le->leFlags = 0;
le->leType = LE_KAMIKAZE;
le->startTime = cg.time;
le->endTime = cg.time + 3000;//2250;
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
le->color[0] = le->color[1] = le->color[2] = le->color[3] = 1.0;
VectorClear(le->angles.trBase);
re = &le->refEntity;
re->reType = RT_MODEL;
re->shaderTime = cg.time / 1000.0f;
re->hModel = cgs.media.kamikazeEffectModel;
VectorCopy( org, re->origin );
}
/*
==================
CG_ObeliskExplode
==================
*/
void CG_ObeliskExplode( vec3_t org, int entityNum ) {
localEntity_t *le;
vec3_t origin;
// create an explosion
VectorCopy( org, origin );
origin[2] += 64;
le = CG_MakeExplosion( origin, vec3_origin,
cgs.media.dishFlashModel,
cgs.media.rocketExplosionShader,
600, qtrue );
le->light = 300;
le->lightColor[0] = 1;
le->lightColor[1] = 0.75;
le->lightColor[2] = 0.0;
}
/*
==================
CG_ObeliskPain
==================
*/
void CG_ObeliskPain( vec3_t org ) {
float r;
sfxHandle_t sfx;
// hit sound
r = rand() & 3;
if ( r < 2 ) {
sfx = cgs.media.obeliskHitSound1;
} else if ( r == 2 ) {
sfx = cgs.media.obeliskHitSound2;
} else {
sfx = cgs.media.obeliskHitSound3;
}
trap_S_StartSound ( org, ENTITYNUM_NONE, CHAN_BODY, sfx );
}
/*
==================
CG_InvulnerabilityImpact
==================
*/
void CG_InvulnerabilityImpact( vec3_t org, vec3_t angles ) {
localEntity_t *le;
refEntity_t *re;
int r;
sfxHandle_t sfx;
le = CG_AllocLocalEntity();
le->leFlags = 0;
le->leType = LE_INVULIMPACT;
le->startTime = cg.time;
le->endTime = cg.time + 1000;
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
le->color[0] = le->color[1] = le->color[2] = le->color[3] = 1.0;
re = &le->refEntity;
re->reType = RT_MODEL;
re->shaderTime = cg.time / 1000.0f;
re->hModel = cgs.media.invulnerabilityImpactModel;
VectorCopy( org, re->origin );
AnglesToAxis( angles, re->axis );
r = rand() & 3;
if ( r < 2 ) {
sfx = cgs.media.invulnerabilityImpactSound1;
} else if ( r == 2 ) {
sfx = cgs.media.invulnerabilityImpactSound2;
} else {
sfx = cgs.media.invulnerabilityImpactSound3;
}
trap_S_StartSound (org, ENTITYNUM_NONE, CHAN_BODY, sfx );
}
/*
==================
CG_InvulnerabilityJuiced
==================
*/
void CG_InvulnerabilityJuiced( vec3_t org ) {
localEntity_t *le;
refEntity_t *re;
vec3_t angles;
le = CG_AllocLocalEntity();
le->leFlags = 0;
le->leType = LE_INVULJUICED;
le->startTime = cg.time;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -