📄 specialfx.cpp
字号:
This creates a beam effect from the origin to the target's origin. If no
target is specified, uses angles and projects beam out from there.
"model" Specifies the model to use as the beam
"overlap" Specifies the amount of overlap each beam link should have. Use this to fill
in the cracks when using electric on beams. (Default is 0)
"minoffset" Amount of electrical variation at the endpoints of beam (Default is 5)
"maxoffset" Amount of electrical variation in the middle of beam (Default is 25)
"color" Vector specifiying the red,green, and blue components. (Default is "1 1 1")
"alpha" Alpha of the beam (Default is 1.0)
"damage" Amount of damage the beam inflicts if beam hits someone (Default is 0)
"angles" Sets the angle of the beam if no target is specified.
"life" Deactivates the beam life seconds after the beam is activated. If not set, beam
will not be deactivated.
"beamstyle" Sets the style for this beam to cycle through. This applies only
to beams without models. sample styles (121 blood, 120 gunsmoke, 123 orangeglow, 124 blueyellow,
125 debris trail, 128 oil, 129 waterspray 130 blue-yellow-blue) See global0.scr for
more style numbers
START_ON - Starts the beam on
ANIMATE - Plays animation of the model
FAST - Plays the animation at 20 frames/sec
ROLL - Rolls the beam
RANDSTART - Starts each segment of the beam's animation on a different frame
ELECTRIC - Applies a random electric efffect to the beam
RANDALPHA - Randomly generate the alpha for the beam
If the model field is not set, then a straight beam will be created using the color
specified. color, minoffset, maxoffset ,ANIMATE, FAST, ROLL, RANDSTART,
ELECTRIC, and RANDALPHA are not applicable if the model is not set.
/*****************************************************************************/
FuncBeam::FuncBeam()
{
Vector color;
const char *target;
trace_t trace;
Vector endpoint, forward;
const char *model=0;
qboolean setangles;
setSolidType( SOLID_NOT );
setOrigin( origin );
end = NULL;
target = Target();
if ( target )
PostEvent( EV_FuncBeam_SetTarget, 0 );
else
// No target specified, so use angles to get direction and do a trace to get endpoint.
{
setangles = ( G_GetSpawnArg( "angle" ) || G_GetSpawnArg( "angles" ) );
if ( setangles )
{
float angle;
angle = G_GetFloatArg( "angle", 0 );
angles = G_GetVectorArg( "angles", Vector( 0, angle, 0 ) );
setAngles( angles );
angles.AngleVectors( &forward, NULL, NULL );
setAngles( angles );
endpoint = forward * 8192;
trace = G_Trace( origin, vec_zero, vec_zero, endpoint, this, MASK_SOLID, "FuncBeam" );
VectorCopy( trace.endpos, edict->s.old_origin );
}
else // Nothing specified. Remove this thing
{
gi.dprintf( "No target or angles set on FuncBeam.\n" );
PostEvent( EV_Remove, 0 );
return;
}
}
// Check for a model and use the beam models if it is set
model = G_GetSpawnArg( "model" );
if ( model && strlen( model ) )
{
setModel( model );
edict->s.effects |= EF_BEAMEFFECT;
edict->s.frame = G_GetFloatArg( "maxoffset", 25 );
edict->s.radius = G_GetFloatArg( "minoffset", 5 );
edict->s.lightofs = G_GetIntArg( "overlap", 0 );
// skinnum will hold the flags
edict->s.skinnum = 0;
if ( spawnflags & 0x0002 )
edict->s.skinnum |= BEAM_AUTO_ANIMATE;
if ( spawnflags & 0x0004 )
edict->s.skinnum |= BEAM_ANIMATE_FAST;
if ( spawnflags & 0x0008 )
edict->s.skinnum |= BEAM_ROLL;
if ( spawnflags & 0x0010 )
edict->s.skinnum |= BEAM_ANIMATE_RANDOM_START;
if ( spawnflags & 0x0020 )
edict->s.skinnum |= BEAM_LIGHTNING_EFFECT;
if ( spawnflags & 0x0040 )
edict->s.skinnum |= BEAM_RANDOM_ALPHA;
}
else // Otherwise do a Quake2 style beam
{
edict->s.renderfx |= RF_BEAM;
edict->s.frame = G_GetIntArg( "diameter", 4 );
edict->s.skinnum = G_GetIntArg( "beamstyle", 255 );;
color = G_GetVectorArg( "color", Vector( 1,1,1 ) );
edict->s.color_r = color.x;
edict->s.color_g = color.y;
edict->s.color_b = color.z;
edict->s.modelindex = 1; // must be non-zero
}
edict->s.alpha = G_GetFloatArg( "alpha", 1 );
damage = G_GetFloatArg( "damage", 0 );
life = G_GetFloatArg( "life", 0 );
if ( spawnflags & 0x0001 ) // Start On
{
PostEvent( EV_Activate, 0 );
}
else
{
hideModel();
}
}
CLASS_DECLARATION( Entity, Beam, NULL );
ResponseDef Beam::Responses[] =
{
{ NULL, NULL }
};
Beam::Beam()
{
hideModel();
edict->s.frame = 0;
edict->s.skinnum = 0;
setMoveType( MOVETYPE_NONE );
setSolidType( SOLID_NOT );
edict->s.renderfx |= RF_BEAM;
edict->s.modelindex = 1; // must be non-zero
}
void Beam::setBeam
(
Vector startpos,
Vector endpos,
int diameter,
float r,
float g,
float b,
float alpha,
float lifespan
)
{
showModel();
if ( lifespan )
{
PostEvent( EV_Remove, lifespan );
}
start = startpos;
end = endpos;
setOrigin( start );
edict->s.old_origin[ 0 ] = end[ 0 ];
edict->s.old_origin[ 1 ] = end[ 1 ];
edict->s.old_origin[ 2 ] = end[ 2 ];
edict->s.frame = diameter;
edict->s.skinnum = 255;
edict->s.color_r = r;
edict->s.color_g = g;
edict->s.color_b = b;
edict->s.alpha = alpha;
link();
}
CLASS_DECLARATION( Entity, Projectile, NULL );
ResponseDef Projectile::Responses[] =
{
{ NULL, NULL }
};
Projectile::Projectile()
{
flags |= FL_FATPROJECTILE;
}
void Projectile::Setup
(
Entity *owner,
Vector pos,
Vector dir
)
{
// This should never be called, but just in case.
assert( 0 );
PostEvent( EV_Remove, 0 );
}
/*****************************************************************************/
/*SINED fx_fire (0 .8 .5) (-8 -8 -8) (8 8 8) SINGLE STAR PARALLEL
This creates a fire sprite, it defaults to the cross shape
SINGLE - Only one sprite orientated
STAR - 4 sprites in a star shape
If you want flickering
Set style to the identifier contained in groupname in the surfaces to control.
"on_style" light style to set to when "on" (default is a flicker)
"off_style" light style to set to when "off" (default is "a")
/*****************************************************************************/
#define SINGLE (1<<0)
#define STAR (1<<1)
#define PARALLEL (1<<2)
CLASS_DECLARATION( Light, FireSprite, "fx_fire" )
ResponseDef FireSprite::Responses[] =
{
{ NULL, NULL }
};
FireSprite::FireSprite()
{
if ( on_style == str( "m" ) )
on_style = str( "kkllmmnnmmllkkonnmmkkllonnmmkkllnnoonnmmllkkonnnnmmllkko" );
ProcessEvent( EV_Light_TurnOn );
setMoveType( MOVETYPE_NONE );
setSolidType( SOLID_NOT );
showModel();
edict->svflags &= ~SVF_NOCLIENT;
edict->s.effects |= EF_AUTO_ANIMATE;
if ( spawnflags & SINGLE )
{
setModel( "sprites/fire.spr" );
}
else if ( spawnflags & STAR )
{
setModel( "sprites/fire_star.spr" );
}
else if ( spawnflags & PARALLEL )
{
setModel( "sprites/fire_single.spr" );
}
else
{
setModel( "sprites/fire_cross.spr" );
}
RandomGlobalEntitySound( "snd_fire" );
}
FireSprite::~FireSprite()
{
ProcessEvent( EV_Light_TurnOff );
detach();
//
// spawn an explosion
//
if ( world )
CreateExplosion( worldorigin, 100, edict->s.scale * 0.5f, true, this, this, this );
}
CLASS_DECLARATION( Trigger, Sprite, "fx_sprite" )
Event EV_Sprite_Activate( "activate" );
Event EV_Sprite_Deactivate( "deactivate" );
ResponseDef Sprite::Responses[] =
{
{ &EV_Activate, ( Response )FuncBeam::Activate },
{ &EV_Sprite_Activate, ( Response )FuncBeam::Activate },
{ &EV_Sprite_Deactivate, ( Response )FuncBeam::Deactivate },
{ NULL, NULL }
};
void Sprite::Activate
(
Event *ev
)
{
showModel();
}
void Sprite::Deactivate
(
Event *ev
)
{
hideModel();
}
Sprite::Sprite()
{
str model;
qboolean setangles;
Vector dir;
Vector color;
model = G_GetStringArg( "sprite", "" );
edict->s.frame = G_GetIntArg( "frame", 0 );
edict->s.scale = G_GetFloatArg( "scale", 1.0 );
edict->s.alpha = G_GetFloatArg( "alpha", 1.0 );
color = G_GetVectorArg("color",Vector(1,1,1));
edict->s.color_r = color.x;
edict->s.color_g = color.y;
edict->s.color_b = color.z;
if ( !model.length() )
{
gi.dprintf( "fx_sprite: sprite not defined, removing.\n" );
PostEvent( EV_Remove, 0 );
}
setModel( model.c_str() );
setMoveType( MOVETYPE_NONE );
setSolidType( SOLID_NOT );
showModel();
edict->svflags &= ~SVF_NOCLIENT;
if ( spawnflags & 1 )
edict->s.effects |= EF_AUTO_ANIMATE;
setangles = ( G_GetSpawnArg( "angle" ) || G_GetSpawnArg( "angles" ) );
if ( setangles )
{
float angle;
angle = G_GetFloatArg( "angle", 0 );
setAngles( G_GetVectorArg( "angles", Vector( 0, angle, 0 ) ) );
}
// If trace to surface, apply sprite and remove this.
if ( spawnflags & 2 )
{
Vector dir,end,norm;
trace_t trace;
Entity *splat;
dir = G_GetMovedir();
end = worldorigin + dir * 8192;
trace = G_Trace( worldorigin, vec_zero, vec_zero, end, this, MASK_SOLIDNONFENCE, "Sprite::Sprite" );
if ( HitSky( &trace ) || ( trace.ent->solid != SOLID_BSP ) )
{
PostEvent( EV_Remove, 0 );
return;
}
splat = new Entity;
splat->setMoveType( MOVETYPE_NONE );
splat->setSolidType( SOLID_NOT );
splat->setModel( model.c_str() );
splat->edict->s.frame = edict->s.frame;
splat->edict->s.scale = edict->s.scale;
splat->edict->s.alpha = edict->s.alpha;
splat->edict->s.color_r = edict->s.color_r;
splat->edict->s.color_g = edict->s.color_g;
splat->edict->s.color_b = edict->s.color_b;
if ( spawnflags & 1 )
splat->edict->s.effects |= EF_AUTO_ANIMATE;
norm = trace.plane.normal;
norm.x = -norm.x;
norm.y = -norm.y;
splat->angles = norm.toAngles();
splat->setAngles( splat->angles );
splat->setOrigin( Vector( trace.endpos ) + ( Vector( trace.plane.normal ) * 0.2 ) );
PostEvent( EV_Remove, 0.1f );
}
}
void ChangeMusic
(
const char *current,
const char *fallback,
qboolean force
)
{
int j;
edict_t *other;
if ( current || fallback )
{
for( j = 1; j <= game.maxclients; j++ )
{
other = &g_edicts[ j ];
if ( other->inuse && other->client )
{
Player * client;
client = ( Player * )other->entity;
client->ChangeMusic( current, fallback, force );
}
}
}
}
void ChangeSoundtrack
(
const char * soundtrack
)
{
gi.configstring( CS_SOUNDTRACK, soundtrack );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -