?? misc.cpp
字號:
"land_radius" The distance of the ground the piece\
should be when on the ground ( default 0 )
"anglespeed" Speed at which pieces rotate ( default 100 ) \
if RANDOMANGLES ( default is 600 )
"key" The item needed to activate this. (default nothing)
IF RANDOMANGLES is set, object randomly spins while in the air.
IF LANDSHATTER is set, object shatters when it hits the ground.
IF TWOSTAGE is set, object can be shattered once it lands on the ground.
IF ACCUMALATIVE is set, damage is accumlative not threshold
IF INVISIBLE is set, these are invisible and not solid until triggered
If NOT_PLAYERS is set, the trigger does not respond to players
If MONSTERS is set, the trigger will respond to monsters
If PROJECTILES is set, the trigger will respond to projectiles (rockets, grenades, etc.)
/*****************************************************************************/
#define RANDOMANGLES ( 1 << 0 )
#define LANDSHATTER ( 1 << 1 )
#define INVISIBLE ( 1 << 5 )
#define ACCUMULATIVE ( 1 << 6 )
#define TWOSTAGE ( 1 << 7 )
CLASS_DECLARATION( Trigger, ExplodingWall, "func_explodingwall" );
Event EV_ExplodingWall_StopRotating( "stoprotating" );
Event EV_ExplodingWall_OnGround( "checkonground" );
ResponseDef ExplodingWall::Responses[] =
{
{ &EV_Trigger_Effect, ( Response )Explode },
{ &EV_Damage, ( Response )DamageEvent },
{ &EV_Touch, ( Response )TouchFunc },
{ &EV_ExplodingWall_StopRotating, ( Response )StopRotating },
{ &EV_ExplodingWall_OnGround, ( Response )CheckOnGround },
{ NULL, NULL }
};
void ExplodingWall::Explode
(
Event *ev
)
{
Entity *other;
Vector pos;
Vector mins, maxs;
int i;
if ( spawnflags & INVISIBLE )
{
showModel();
setSolidType( SOLID_BSP );
takedamage = DAMAGE_YES;
}
if ( takedamage == DAMAGE_NO )
{
return;
}
other = ev->GetEntity( 1 );
health = 0;
takedamage = DAMAGE_NO;
// Create explosions
for( i = 0; i < explosions; i++ )
{
pos[ 0 ] = absmin[ 0 ] + G_Random( size[ 0 ] );
pos[ 1 ] = absmin[ 1 ] + G_Random( size[ 1 ] );
pos[ 2 ] = absmin[ 2 ] + G_Random( size[ 2 ] );
CreateExplosion( pos, dmg, 1.0f, true, this, other, this );
}
// throw itself
state = 1;
on_ground = false;
PostEvent( EV_ExplodingWall_OnGround, 0.1f );
velocity[ 0 ] = G_CRandom( 70 );
velocity[ 1 ] = G_CRandom( 70 );
velocity[ 2 ] = 140 + G_Random( 70 );
setMoveType( MOVETYPE_BOUNCE );
setSolidType( SOLID_BBOX );
if ( spawnflags & RANDOMANGLES )
{
avelocity[ 0 ] = G_Random( angle_speed );
avelocity[ 1 ] = G_Random( angle_speed );
avelocity[ 2 ] = G_Random( angle_speed );
}
else
{
Vector delta;
float most;
float time;
int t;
delta = land_angles - worldangles;
if ( delta[ 0 ] > 180 )
delta[ 0 ] -= 360;
if ( delta[ 0 ] < -180 )
delta[ 0 ] += 360;
if ( delta[ 1 ] > 180 )
delta[ 1 ] -= 360;
if ( delta[ 1 ] < -180 )
delta[ 1 ] += 360;
if ( delta[ 2 ] > 180 )
delta[ 2 ] -= 360;
if ( delta[ 2 ] < -180 )
delta[ 2 ] += 360;
most = MaxValue( delta );
if ( !angle_speed )
angle_speed = 1;
t = 10 * most / angle_speed;
time = (float)t / 10;
delta = delta * (1.0/time);
avelocity = delta;
PostEvent( EV_ExplodingWall_StopRotating, time );
state = 2;
}
ActivateTargets( ev );
if ( land_radius > 0 )
{
mins[0] = mins[1] = mins[2] = -land_radius;
maxs[0] = maxs[1] = maxs[2] = land_radius;
setSize( mins, maxs );
}
attack_finished = 0;
}
void ExplodingWall::DamageEvent
(
Event *ev
)
{
Event *event;
Entity *inflictor;
Entity *attacker;
int damage;
if ( takedamage == DAMAGE_NO )
{
return;
}
if ( on_ground )
{
GroundDamage( ev );
return;
}
damage = ev->GetInteger( 1 );
inflictor = ev->GetEntity( 2 );
attacker = ev->GetEntity( 3 );
if ( spawnflags & ACCUMULATIVE )
{
health -= damage;
if ( health > 0 )
return;
}
else
{
if ( damage < health )
{
return;
}
}
event = new Event( EV_Activate );
event->AddEntity( attacker );
ProcessEvent( event );
}
void ExplodingWall::GroundDamage
(
Event *ev
)
{
Vector dir;
Entity *inflictor;
Entity *attacker;
Vector pos;
int damage;
if ( takedamage == DAMAGE_NO )
{
return;
}
damage = ev->GetInteger( 1 );
inflictor = ev->GetEntity( 2 );
attacker = ev->GetEntity( 3 );
if ( spawnflags & ACCUMULATIVE )
{
health -= damage;
if ( health > 0 )
return;
}
else
{
if ( damage < health )
{
return;
}
}
if ( explosions )
{
pos[ 0 ] = absmin[ 0 ] + G_Random( size[ 0 ] );
pos[ 1 ] = absmin[ 1 ] + G_Random( size[ 1 ] );
pos[ 2 ] = absmin[ 2 ] + G_Random( size[ 2 ] );
CreateExplosion( pos, damage, 1.0f, true, this, attacker, this );
}
takedamage = DAMAGE_NO;
hideModel();
dir = worldorigin - attacker->worldorigin;
TesselateModel
(
this,
tess_min_size,
tess_max_size,
dir,
damage,
tess_percentage,
tess_thickness,
vec3_origin
);
ProcessEvent( EV_BreakingSound );
PostEvent( EV_Remove, 0 );
}
void ExplodingWall::SetupSecondStage
(
void
)
{
health = max_health;
takedamage = DAMAGE_YES;
}
void ExplodingWall::StopRotating
(
Event *ev
)
{
avelocity = vec_zero;
setAngles( land_angles );
if ( spawnflags & TWOSTAGE )
SetupSecondStage();
}
void ExplodingWall::CheckOnGround
(
Event *ev
)
{
if ( ( velocity == vec_zero ) && groundentity )
{
Vector delta;
float most;
float time;
int t;
delta = land_angles - worldangles;
if ( delta.length() > 1 )
{
if ( delta[ 0 ] > 180 )
delta[ 0 ] -= 360;
if ( delta[ 0 ] < -180 )
delta[ 0 ] += 360;
if ( delta[ 1 ] > 180 )
delta[ 1 ] -= 360;
if ( delta[ 1 ] < -180 )
delta[ 1 ] += 360;
if ( delta[ 2 ] > 180 )
delta[ 2 ] -= 360;
if ( delta[ 2 ] < -180 )
delta[ 2 ] += 360;
most = MaxValue( delta );
if ( angle_speed > 3 )
t = 10.0f * most / ( angle_speed / 3 );
else
t = 10.0f * most;
time = (float)t / 10;
delta = delta * (1.0/time);
avelocity = delta;
PostEvent( EV_ExplodingWall_StopRotating, time );
}
state = 2;
setSize( orig_mins, orig_maxs );
on_ground = true;
}
else
PostEvent( ev, 0.1f );
}
void ExplodingWall::TouchFunc
(
Event *ev
)
{
Entity *other;
if ( ( velocity == vec_zero ) || ( level.time < attack_finished ) )
{
return;
}
other = ev->GetEntity( 1 );
if ( ( spawnflags & LANDSHATTER ) && ( other == world ) )
{
Vector pos;
takedamage = DAMAGE_NO;
if ( explosions )
{
pos[ 0 ] = absmin[ 0 ] + G_Random( size[ 0 ] );
pos[ 1 ] = absmin[ 1 ] + G_Random( size[ 1 ] );
pos[ 2 ] = absmin[ 2 ] + G_Random( size[ 2 ] );
CreateExplosion( pos, dmg, 1.0f, true, this, other, this );
}
hideModel();
TesselateModel
(
this,
tess_min_size,
tess_max_size,
vec_zero,
100,
tess_percentage,
tess_thickness,
vec3_origin
);
ProcessEvent( EV_BreakingSound );
PostEvent( EV_Remove, 0 );
return;
}
if ( other->takedamage )
{
other->Damage( this, activator, dmg, worldorigin, vec_zero, vec_zero, 20, 0, MOD_EXPLODEWALL, -1, -1, 1.0f );
RandomGlobalSound( "debris_generic", 1, CHAN_WEAPON, ATTN_NORM );
attack_finished = level.time + 0.1;
}
}
ExplodingWall::ExplodingWall()
{
if ( spawnflags & INVISIBLE )
{
if ( Targeted() )
takedamage = DAMAGE_YES;
else
takedamage = DAMAGE_NO;
hideModel();
setSolidType( SOLID_NOT );
}
else
{
showModel();
setSolidType( SOLID_BSP );
takedamage = DAMAGE_YES;
}
setMoveType( MOVETYPE_PUSH );
setOrigin( origin );
health = G_GetFloatArg( "health", 60 );
max_health = health;
on_ground = false;
state = 0;
if ( spawnflags & RANDOMANGLES )
angle_speed = G_GetFloatArg( "anglespeed", 600 );
else
angle_speed = G_GetFloatArg( "anglespeed", 100 );
land_radius = G_GetFloatArg( "land_radius", 0 );
land_angles = G_GetVectorArg( "land_angles" );
dmg = G_GetIntArg( "dmg", 10 );
explosions = G_GetIntArg( "explosions", 1 );
orig_mins = mins;
orig_maxs = maxs;
respondto = spawnflags ^ TRIGGER_PLAYERS;
}
/*****************************************************************************/
/*SINED detail (0.5 0 1.0) ?
Used to fake details before the Quake 2 merge.
/*****************************************************************************/
CLASS_DECLARATION( Entity, Detail, "detail" );
ResponseDef Detail::Responses[] =
{
{ NULL, NULL }
};
Detail::Detail()
{
// Be an asshole to the level designers so that they make the change asap.
gi.dprintf( "Detail brushes are no longer needed. Use Surface attributes.\n" );
if ( !G_GetSpawnArg( "model" ) )
{
gi.dprintf( "Detail brush with NULL model removed!!!\n" );
ProcessEvent( EV_Remove );
}
else
{
ProcessEvent( EV_Remove );
}
}
/*****************************************************************************/
/*SINED misc_oxygen (1 0 0) ? VISIBLE
Touching this entity will reset the drowning time - only
responds to players.
"key" The item needed to activate this. (default nothing)
/*****************************************************************************/
CLASS_DECLARATION( Trigger, Oxygenator, "misc_oxygen" );
ResponseDef Oxygenator::Responses[] =
{
{ &EV_Trigger_Effect, ( Response )Oxygenator::Oxygenate },
{ NULL, NULL }
};
Oxygenator::Oxygenator()
{
if ( spawnflags & 1 )
{
showModel();
}
time = 20;
respondto = TRIGGER_PLAYERS;
}
EXPORT_FROM_DLL void Oxygenator::Oxygenate
(
Event *ev
)
{
Entity *other;
Player *player;
other = ev->GetEntity( 1 );
if ( !other )
return;
player = ( Player * )( Sentient * )other;
player->GiveOxygen( time );
}
/*****************************************************************************/
/*SINED misc_teleporter (1 0 0) ? VISIBLE x NOT_PLAYERS NOT_MONSTERS NOT_PROJECTILES
Touching this entity will teleport players to the targeted object.
"key" The item needed to activate this. (default nothing)
If NOT_PLAYERS is set, the teleporter does not teleport players
If NOT_MONSTERS is set, the teleporter does not teleport monsters
If NOT_PROJECTILES is set, the teleporter does not teleport projectiles (rockets, grenades, etc.)
/*****************************************************************************/
CLASS_DECLARATION( Trigger, Teleporter, "misc_teleporter" );
ResponseDef Teleporter::Responses[] =
{
{ &EV_Trigger_Effect, ( Response )Teleporter::Teleport },
{ NULL, NULL }
};
EXPORT_FROM_DLL void Teleporter::Teleport
(
Event *ev
)
{
gclient_t *client;
Entity *dest;
int num;
int i;
Entity *other;
Vector mid;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -