codemp/game/g_mover.c File Reference

#include "g_local.h"

Go to the source code of this file.

Data Structures

struct  pushed_t

Defines

#define MOVER_START_ON   1
#define MOVER_FORCE_ACTIVATE   2
#define MOVER_CRUSHER   4
#define MOVER_TOGGLE   8
#define MOVER_LOCKED   16
#define MOVER_GOODIE   32
#define MOVER_PLAYER_USE   64
#define MOVER_INACTIVE   128
#define TRAIN_START_ON   1
#define TRAIN_TOGGLE   2
#define TRAIN_BLOCK_STOPS   4
#define FUNC_WALL_OFF   1

Functions

void MatchTeam (gentity_t *teamLeader, int moverState, int time)
void G_PlayDoorLoopSound (gentity_t *ent)
void G_PlayDoorSound (gentity_t *ent, int type)
gentity_tG_TestEntityPosition (gentity_t *ent)
void G_CreateRotationMatrix (vec3_t angles, vec3_t matrix[3])
void G_TransposeMatrix (vec3_t matrix[3], vec3_t transpose[3])
void G_RotatePoint (vec3_t point, vec3_t matrix[3])
qboolean G_TryPushingEntity (gentity_t *check, gentity_t *pusher, vec3_t move, vec3_t amove)
void G_ExplodeMissile (gentity_t *ent)
qboolean G_MoverPush (gentity_t *pusher, vec3_t move, vec3_t amove, gentity_t **obstacle)
void G_MoverTeam (gentity_t *ent)
void G_RunMover (gentity_t *ent)
void CalcTeamDoorCenter (gentity_t *ent, vec3_t center)
void SetMoverState (gentity_t *ent, moverState_t moverState, int time)
void ReturnToPos1 (gentity_t *ent)
void Reached_BinaryMover (gentity_t *ent)
void Use_BinaryMover_Go (gentity_t *ent)
void UnLockDoors (gentity_t *const ent)
void LockDoors (gentity_t *const ent)
void Use_BinaryMover (gentity_t *ent, gentity_t *other, gentity_t *activator)
void InitMoverTrData (gentity_t *ent)
void InitMover (gentity_t *ent)
void Blocked_Door (gentity_t *ent, gentity_t *other)
void Touch_DoorTrigger (gentity_t *ent, gentity_t *other, trace_t *trace)
void Think_SpawnNewDoorTrigger (gentity_t *ent)
void Think_MatchTeam (gentity_t *ent)
qboolean G_EntIsDoor (int entityNum)
gentity_tG_FindDoorTrigger (gentity_t *ent)
qboolean G_EntIsUnlockedDoor (int entityNum)
void SP_func_door (gentity_t *ent)
void Touch_Plat (gentity_t *ent, gentity_t *other, trace_t *trace)
void Touch_PlatCenterTrigger (gentity_t *ent, gentity_t *other, trace_t *trace)
void SpawnPlatTrigger (gentity_t *ent)
void SP_func_plat (gentity_t *ent)
void Touch_Button (gentity_t *ent, gentity_t *other, trace_t *trace)
void SP_func_button (gentity_t *ent)
void Think_BeginMoving (gentity_t *ent)
void Reached_Train (gentity_t *ent)
void Think_SetupTrainTargets (gentity_t *ent)
void SP_path_corner (gentity_t *self)
void SP_func_train (gentity_t *self)
void func_static_use (gentity_t *self, gentity_t *other, gentity_t *activator)
void SP_func_static (gentity_t *ent)
void func_rotating_use (gentity_t *self, gentity_t *other, gentity_t *activator)
void SP_func_breakable (gentity_t *self)
void SP_func_rotating (gentity_t *ent)
void SP_func_bobbing (gentity_t *ent)
void SP_func_pendulum (gentity_t *ent)
void G_MiscModelExplosion (vec3_t mins, vec3_t maxs, int size, material_t chunkType)
void G_Chunks (int owner, vec3_t origin, const vec3_t normal, const vec3_t mins, const vec3_t maxs, float speed, int numChunks, material_t chunkType, int customChunk, float baseScale)
void funcBBrushDieGo (gentity_t *self)
void funcBBrushDie (gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int mod)
void funcBBrushUse (gentity_t *self, gentity_t *other, gentity_t *activator)
void funcBBrushPain (gentity_t *self, gentity_t *attacker, int damage)
void funcBBrushTouch (gentity_t *ent, gentity_t *other, trace_t *trace)
qboolean G_EntIsBreakable (int entityNum)
void GlassDie (gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int mod)
void GlassDie_Old (gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int mod)
void GlassPain (gentity_t *self, gentity_t *attacker, int damage)
void GlassUse (gentity_t *self, gentity_t *other, gentity_t *activator)
void SP_func_glass (gentity_t *ent)
void func_usable_use (gentity_t *self, gentity_t *other, gentity_t *activator)
void func_wait_return_solid (gentity_t *self)
void func_usable_think (gentity_t *self)
qboolean G_EntIsRemovableUsable (int entNum)
void func_usable_pain (gentity_t *self, gentity_t *attacker, int damage)
void func_usable_die (gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int mod)
void SP_func_usable (gentity_t *self)
void use_wall (gentity_t *ent, gentity_t *other, gentity_t *activator)
void SP_func_wall (gentity_t *ent)

Variables

pushed_t pushed [MAX_GENTITIES]
pushed_tpushed_p
int BMS_START = 0
int BMS_MID = 1
int BMS_END = 2


Define Documentation

#define FUNC_WALL_OFF   1
 

Definition at line 3229 of file g_mover.c.

Referenced by SP_func_wall().

#define MOVER_CRUSHER   4
 

Definition at line 28 of file g_mover.c.

Referenced by Blocked_Door().

#define MOVER_FORCE_ACTIVATE   2
 

Definition at line 27 of file g_mover.c.

Referenced by G_EntIsUnlockedDoor(), and SP_func_door().

#define MOVER_GOODIE   32
 

Definition at line 31 of file g_mover.c.

#define MOVER_INACTIVE   128
 

Definition at line 33 of file g_mover.c.

Referenced by InitMover().

#define MOVER_LOCKED   16
 

Definition at line 30 of file g_mover.c.

Referenced by G_EntIsUnlockedDoor(), LockDoors(), SP_func_door(), Touch_DoorTrigger(), UnLockDoors(), and Use_BinaryMover().

#define MOVER_PLAYER_USE   64
 

Definition at line 32 of file g_mover.c.

Referenced by G_EntIsUnlockedDoor(), InitMover(), and SP_func_door().

#define MOVER_START_ON   1
 

Definition at line 26 of file g_mover.c.

#define MOVER_TOGGLE   8
 

Definition at line 29 of file g_mover.c.

Referenced by UnLockDoors().

#define TRAIN_BLOCK_STOPS   4
 

Definition at line 1708 of file g_mover.c.

Referenced by SP_func_train().

#define TRAIN_START_ON   1
 

Definition at line 1706 of file g_mover.c.

#define TRAIN_TOGGLE   2
 

Definition at line 1707 of file g_mover.c.


Function Documentation

void Blocked_Door gentity_t ent,
gentity_t other
 

Definition at line 1008 of file g_mover.c.

References gentity_s::damage, G_Damage(), gentity_t, MOD_CRUSH, MOVER_CRUSHER, NULL, gentity_s::spawnflags, and Use_BinaryMover().

Referenced by SP_func_door(), and SP_func_plat().

01009 {
01010         if ( ent->damage ) {
01011                 G_Damage( other, ent, ent, NULL, NULL, ent->damage, 0, MOD_CRUSH );
01012         }
01013         if ( ent->spawnflags & MOVER_CRUSHER ) {
01014                 return;         // crushers don't reverse
01015         }
01016 
01017         // reverse direction
01018         Use_BinaryMover( ent, ent, other );
01019 }

void CalcTeamDoorCenter gentity_t ent,
vec3_t  center
 

Definition at line 501 of file g_mover.c.

References gentity_t, entityShared_t::maxs, entityShared_t::mins, gentity_s::r, gentity_s::teamchain, vec3_t, VectorAdd, and VectorScale.

Referenced by NAVNEW_ResolveEntityCollision(), Reached_BinaryMover(), and Use_BinaryMover_Go().

00502 {
00503         vec3_t          slavecenter;
00504         gentity_t       *slave;
00505 
00506         //Start with our center
00507         VectorAdd(ent->r.mins, ent->r.maxs, center);
00508         VectorScale(center, 0.5, center);
00509         for ( slave = ent->teamchain ; slave ; slave = slave->teamchain ) 
00510         {
00511                 //Find slave's center
00512                 VectorAdd(slave->r.mins, slave->r.maxs, slavecenter);
00513                 VectorScale(slavecenter, 0.5, slavecenter);
00514                 //Add that to our own, find middle
00515                 VectorAdd(center, slavecenter, center);
00516                 VectorScale(center, 0.5, center);
00517         }
00518 }

void func_rotating_use gentity_t self,
gentity_t other,
gentity_t activator
 

Definition at line 2028 of file g_mover.c.

References entityState_s::apos, BMS_END, BMS_MID, BMS_START, EV_BMODEL_SOUND, G_AddEvent(), G_SoundSetIndex(), gentity_t, entityState_s::loopIsSoundset, entityState_s::loopSound, qfalse, qtrue, gentity_s::s, gentity_s::soundSet, entityState_s::soundSetIndex, TR_LINEAR, TR_STATIONARY, and trajectory_t::trType.

02029 {
02030         if(     self->s.apos.trType == TR_LINEAR )
02031         {
02032                 self->s.apos.trType = TR_STATIONARY;
02033                 // stop the sound if it stops moving
02034                 self->s.loopSound = 0;
02035                 self->s.loopIsSoundset = qfalse;
02036                 // play stop sound too?
02037                 if ( self->soundSet && self->soundSet[0] )
02038                 {
02039                         self->s.soundSetIndex = G_SoundSetIndex(self->soundSet);
02040                         G_AddEvent( self, EV_BMODEL_SOUND, BMS_END );
02041                 }
02042         }
02043         else
02044         {
02045                 if ( self->soundSet && self->soundSet[0] )
02046                 {
02047                         self->s.soundSetIndex = G_SoundSetIndex(self->soundSet);
02048                         G_AddEvent( self, EV_BMODEL_SOUND, BMS_START );
02049                         self->s.loopSound = BMS_MID;
02050                         self->s.loopIsSoundset = qtrue;
02051                 }
02052                 self->s.apos.trType = TR_LINEAR;
02053         }
02054 }

void func_static_use gentity_t self,
gentity_t other,
gentity_t activator
 

Definition at line 2009 of file g_mover.c.

References BSET_USE, entityState_s::frame, G_ActivateBehavior(), G_UseTargets(), gentity_t, gentity_s::s, and gentity_s::spawnflags.

Referenced by SP_func_static().

02010 {
02011         G_ActivateBehavior( self, BSET_USE );
02012 
02013         if ( self->spawnflags & 4/*SWITCH_SHADER*/ )
02014         {
02015                 self->s.frame = self->s.frame ? 0 : 1;//toggle frame
02016         }
02017         G_UseTargets( self, activator );
02018 }

void func_usable_die gentity_t self,
gentity_t inflictor,
gentity_t attacker,
int  damage,
int  mod
 

Definition at line 3099 of file g_mover.c.

References gentity_t, GlobalUse(), qfalse, and gentity_s::takedamage.

Referenced by SP_func_usable().

03100 {
03101         self->takedamage = qfalse;
03102         GlobalUse(self, inflictor, attacker);
03103 }

void func_usable_pain gentity_t self,
gentity_t attacker,
int  damage
 

Definition at line 3094 of file g_mover.c.

References gentity_t, and GlobalUse().

Referenced by SP_func_usable().

03095 {
03096         GlobalUse(self, attacker, attacker);
03097 }

void func_usable_think gentity_t self  ) 
 

Definition at line 3013 of file g_mover.c.

References func_usable_use(), gentity_t, gentity_s::r, gentity_s::spawnflags, SVF_PLAYER_USABLE, entityShared_t::svFlags, gentity_s::think, and gentity_s::use.

Referenced by func_usable_use().

03014 {
03015         if ( self->spawnflags & 8 )
03016         {
03017                 self->r.svFlags |= SVF_PLAYER_USABLE;   //Replace the usable flag
03018                 self->use = func_usable_use;
03019                 self->think = 0;
03020         }
03021 }

void func_usable_use gentity_t self,
gentity_t other,
gentity_t activator
 

Definition at line 3036 of file g_mover.c.

References BSET_USE, gentity_s::clipmask, entityShared_t::contents, gentity_s::count, EF_NODRAW, EF_SHADER_ANIM, entityState_s::eFlags, entityState_s::frame, func_usable_think(), func_wait_return_solid(), G_ActivateBehavior(), G_UseTargets(), gentity_s::genericValue5, gentity_t, level, gentity_s::nextthink, gentity_s::r, gentity_s::s, entityState_s::solid, gentity_s::spawnflags, SVF_NOCLIENT, SVF_PLAYER_USABLE, entityShared_t::svFlags, gentity_s::target, gentity_s::think, level_locals_t::time, gentity_s::use, and gentity_s::wait.

Referenced by func_usable_think(), func_wait_return_solid(), and SP_func_usable().

03037 {//Toggle on and off
03038         G_ActivateBehavior( self, BSET_USE );
03039         if ( self->s.eFlags & EF_SHADER_ANIM )
03040         {//animate shader when used
03041                 self->s.frame++;//inc frame
03042                 if ( self->s.frame > self->genericValue5 )
03043                 {//wrap around
03044                         self->s.frame = 0;
03045                 }
03046                 if ( self->target && self->target[0] )
03047                 {
03048                         G_UseTargets( self, activator );
03049                 }
03050         }
03051         else if ( self->spawnflags & 8 )
03052         {//ALWAYS_ON
03053                 //Remove the ability to use the entity directly
03054                 self->r.svFlags &= ~SVF_PLAYER_USABLE;
03055                 //also remove ability to call any use func at all!
03056                 self->use = 0;
03057                 
03058                 if(self->target && self->target[0])
03059                 {
03060                         G_UseTargets(self, activator);
03061                 }
03062                 
03063                 if ( self->wait )
03064                 {
03065                         self->think = func_usable_think;
03066                         self->nextthink = level.time + ( self->wait * 1000 );
03067                 }
03068 
03069                 return;
03070         }
03071         else if ( !self->count )
03072         {//become solid again
03073                 self->count = 1;
03074                 func_wait_return_solid( self );
03075         }
03076         else
03077         {
03078                 self->s.solid = 0;
03079                 self->r.contents = 0;
03080                 self->clipmask = 0;
03081                 self->r.svFlags |= SVF_NOCLIENT;
03082                 self->s.eFlags |= EF_NODRAW;
03083                 self->count = 0;
03084 
03085                 if(self->target && self->target[0])
03086                 {
03087                         G_UseTargets(self, activator);
03088                 }
03089                 self->think = 0;
03090                 self->nextthink = -1;
03091         }
03092 }

void func_wait_return_solid gentity_t self  ) 
 

Definition at line 2981 of file g_mover.c.

References gentity_s::activator, gentity_s::clipmask, CONTENTS_BODY, entityShared_t::currentOrigin, EF_NODRAW, entityState_s::eFlags, FRAMETIME, func_usable_use(), func_wait_return_solid(), G_TestEntityPosition(), G_UseTargets2(), gentity_t, InitMover(), level, gentity_s::model, gentity_s::nextthink, NULL, entityState_s::origin, entityState_s::pos, gentity_s::r, gentity_s::s, gentity_s::spawnflags, SVF_NOCLIENT, entityShared_t::svFlags, gentity_s::target2, gentity_s::think, level_locals_t::time, trap_SetBrushModel(), trajectory_t::trBase, gentity_s::use, and VectorCopy.

Referenced by func_usable_use(), and func_wait_return_solid().

02982 {
02983         //once a frame, see if it's clear.
02984         self->clipmask = CONTENTS_BODY;
02985         if ( !(self->spawnflags&16) || G_TestEntityPosition( self ) == NULL )
02986         {
02987                 trap_SetBrushModel( self, self->model );
02988                 InitMover( self );
02989                 VectorCopy( self->s.origin, self->s.pos.trBase );
02990                 VectorCopy( self->s.origin, self->r.currentOrigin );
02991                 self->r.svFlags &= ~SVF_NOCLIENT;
02992                 self->s.eFlags &= ~EF_NODRAW;
02993                 self->use = func_usable_use;
02994                 self->clipmask = 0;
02995                 if ( self->target2 && self->target2[0] )
02996                 {
02997                         G_UseTargets2( self, self->activator, self->target2 );
02998                 }
02999                 //FIXME: Animations?
03000                 /*if ( self->s.eFlags & EF_ANIM_ONCE )
03001                 {//Start our anim
03002                         self->s.frame = 0;
03003                 }*/
03004         }
03005         else
03006         {
03007                 self->clipmask = 0;
03008                 self->think = func_wait_return_solid;
03009                 self->nextthink = level.time + FRAMETIME;
03010         }
03011 }

void funcBBrushDie gentity_t self,
gentity_t inflictor,
gentity_t attacker,
int  damage,
int  mod
 

Definition at line 2486 of file g_mover.c.

References gentity_s::delay, gentity_s::enemy, floor(), funcBBrushDieGo(), gentity_t, level, gentity_s::nextthink, qfalse, gentity_s::takedamage, gentity_s::think, and level_locals_t::time.

Referenced by funcBBrushUse().

02487 {
02488         self->takedamage = qfalse;//stop chain reaction runaway loops
02489 
02490         self->enemy = attacker;
02491 
02492         if(self->delay)
02493         {
02494                 self->think = funcBBrushDieGo;
02495                 self->nextthink = level.time + floor(self->delay * 1000.0f);
02496                 return;
02497         }
02498 
02499         funcBBrushDieGo(self);
02500 }

void funcBBrushDieGo gentity_t self  ) 
 

Definition at line 2384 of file g_mover.c.

References entityShared_t::absmax, entityShared_t::absmin, gentity_s::client, gentity_s::clipmask, entityShared_t::contents, entityShared_t::currentOrigin, EF_MISSILE_STICK, entityState_s::eFlags, gentity_s::enemy, EV_GENERAL_SOUND, entityState_s::eventParm, G_Chunks(), G_Damage(), g_entities, G_FreeEntity(), G_MiscModelExplosion(), G_PlayEffectID(), G_RadiusDamage(), G_SoundIndex(), G_TempEntity(), G_UseTargets(), gentity_s::genericValue15, gentity_t, entityState_s::groundEntityNum, level, gentity_s::mass, gentity_s::material, material_t, MAX_GENTITIES, MOD_CRUSH, MOD_UNKNOWN, gentity_s::nextthink, NULL, entityState_s::number, qtrue, gentity_s::r, gentity_s::radius, random, gentity_s::s, entityState_s::solid, gentity_s::spawnflags, gentity_s::splashDamage, gentity_s::splashRadius, sqrt(), gentity_s::target, gentity_s::think, level_locals_t::time, trap_AdjustAreaPortalState(), trap_LinkEntity(), vec3_t, VectorAdd, VectorCopy, VectorMA, VectorNormalize(), VectorScale, VectorSet, and VectorSubtract.

Referenced by funcBBrushDie().

02385 {
02386         vec3_t          org, dir, up;
02387         gentity_t       *attacker = self->enemy;
02388         float           scale;
02389         int                     i, numChunks, size = 0;
02390         material_t      chunkType = self->material;
02391         
02392         // if a missile is stuck to us, blow it up so we don't look dumb
02393         for ( i = 0; i < MAX_GENTITIES; i++ )
02394         {
02395                 if ( g_entities[i].s.groundEntityNum == self->s.number && ( g_entities[i].s.eFlags & EF_MISSILE_STICK ))
02396                 {
02397                         G_Damage( &g_entities[i], self, self, NULL, NULL, 99999, 0, MOD_CRUSH ); //?? MOD?
02398                 }
02399         }
02400 
02401         //So chunks don't get stuck inside me
02402         self->s.solid = 0;
02403         self->r.contents = 0;
02404         self->clipmask = 0;
02405         trap_LinkEntity(self); 
02406 
02407         VectorSet(up, 0, 0, 1);
02408 
02409         if ( self->target && attacker != NULL )
02410         {
02411                 G_UseTargets(self, attacker);
02412         }
02413 
02414         VectorSubtract( self->r.absmax, self->r.absmin, org );// size
02415 
02416         numChunks = random() * 6 + 18;
02417 
02418         // This formula really has no logical basis other than the fact that it seemed to be the closest to yielding the results that I wanted.
02419         // Volume is length * width * height...then break that volume down based on how many chunks we have
02420         scale = sqrt( sqrt( org[0] * org[1] * org[2] )) * 1.75f;
02421 
02422         if ( scale > 48 )
02423         {
02424                 size = 2;
02425         }
02426         else if ( scale > 24 )
02427         {
02428                 size = 1;
02429         }
02430 
02431         scale = scale / numChunks;
02432 
02433         if ( self->radius > 0.0f )
02434         {
02435                 // designer wants to scale number of chunks, helpful because the above scale code is far from perfect
02436                 //      I do this after the scale calculation because it seems that the chunk size generally seems to be very close, it's just the number of chunks is a bit weak
02437                 numChunks *= self->radius;
02438         }
02439 
02440         VectorMA( self->r.absmin, 0.5, org, org );
02441         VectorAdd( self->r.absmin,self->r.absmax, org );
02442         VectorScale( org, 0.5f, org );
02443 
02444         if ( attacker != NULL && attacker->client )
02445         {
02446                 VectorSubtract( org, attacker->r.currentOrigin, dir );
02447                 VectorNormalize( dir );
02448         }
02449         else
02450         {
02451                 VectorCopy(up, dir);
02452         } 
02453 
02454         if ( !(self->spawnflags & 2048) ) // NO_EXPLOSION
02455         {
02456                 // we are allowed to explode
02457                 G_MiscModelExplosion( self->r.absmin, self->r.absmax, size, chunkType );
02458         }
02459 
02460         if (self->genericValue15)
02461         { //a custom effect to play
02462                 vec3_t ang;
02463                 VectorSet(ang, 0.0f, 1.0f, 0.0f);
02464                 G_PlayEffectID(self->genericValue15, org, ang);
02465         }
02466 
02467         if ( self->splashDamage > 0 && self->splashRadius > 0 )
02468         {
02469                 gentity_t *te;
02470                 //explode
02471                 G_RadiusDamage( org, self, self->splashDamage, self->splashRadius, self, NULL, MOD_UNKNOWN );
02472 
02473                 te = G_TempEntity( org, EV_GENERAL_SOUND );
02474                 te->s.eventParm = G_SoundIndex("sound/weapons/explosions/cargoexplode.wav");
02475         }
02476 
02477         //FIXME: base numChunks off size?
02478         G_Chunks( self->s.number, org, dir, self->r.absmin, self->r.absmax, 300, numChunks, chunkType, 0, (scale*self->mass) );
02479 
02480         trap_AdjustAreaPortalState( self, qtrue );
02481         self->think = G_FreeEntity;
02482         self->nextthink = level.time + 50;
02483         //G_FreeEntity( self );
02484 }

void funcBBrushPain gentity_t self,
gentity_t attacker,
int  damage
 

Definition at line 2518 of file g_mover.c.

References entityShared_t::absmax, entityShared_t::absmin, gentity_s::activator, BSET_PAIN, ceil(), gentity_s::client, entityShared_t::currentOrigin, G_ActivateBehavior(), G_Chunks(), G_UseTargets2(), gentity_t, gentity_s::inuse, level, gentity_s::mass, MAT_DRK_STONE, MAT_GREY_STONE, MAT_LT_STONE, MAT_SNOWY_ROCK, gentity_s::material, NULL, entityState_s::number, gentity_s::pain, gentity_s::painDebounceTime, gentity_s::paintarget, Q_irand(), gentity_s::r, gentity_s::radius, gentity_s::s, level_locals_t::time, vec3_t, VectorAdd, VectorMA, VectorNormalize(), VectorScale, VectorSet, VectorSubtract, and gentity_s::wait.

Referenced by SP_func_breakable().

02519 {
02520         if ( self->painDebounceTime > level.time )
02521         {
02522                 return;
02523         }
02524 
02525         if ( self->paintarget && self->paintarget[0] )
02526         {
02527                 if (!self->activator)
02528                 {
02529                         if (attacker && attacker->inuse && attacker->client)
02530                         {
02531                                 G_UseTargets2 (self, attacker, self->paintarget);
02532                         }
02533                 }
02534                 else
02535                 {
02536                         G_UseTargets2 (self, self->activator, self->paintarget);
02537                 }
02538         }
02539 
02540         G_ActivateBehavior( self, BSET_PAIN );
02541 
02542         if ( self->material == MAT_DRK_STONE
02543                 || self->material == MAT_LT_STONE
02544                 || self->material == MAT_GREY_STONE 
02545                 || self->material == MAT_SNOWY_ROCK )
02546         {
02547                 vec3_t  org, dir;
02548                 float   scale;
02549                 int             numChunks;
02550                 VectorSubtract( self->r.absmax, self->r.absmin, org );// size
02551                 // This formula really has no logical basis other than the fact that it seemed to be the closest to yielding the results that I wanted.
02552                 // Volume is length * width * height...then break that volume down based on how many chunks we have
02553                 scale = VectorLength( org ) / 100.0f;
02554                 VectorMA( self->r.absmin, 0.5, org, org );
02555                 VectorAdd( self->r.absmin,self->r.absmax, org );
02556                 VectorScale( org, 0.5f, org );
02557                 if ( attacker != NULL && attacker->client )
02558                 {
02559                         VectorSubtract( attacker->r.currentOrigin, org, dir );
02560                         VectorNormalize( dir );
02561                 }
02562                 else
02563                 {
02564                         VectorSet( dir, 0, 0, 1 );
02565                 } 
02566                 numChunks = Q_irand( 1, 3 );
02567                 if ( self->radius > 0.0f )
02568                 {
02569                         // designer wants to scale number of chunks, helpful because the above scale code is far from perfect
02570                         //      I do this after the scale calculation because it seems that the chunk size generally seems to be very close, it's just the number of chunks is a bit weak
02571                         numChunks = ceil(numChunks*self->radius);
02572                 }
02573                 G_Chunks( self->s.number, org, dir, self->r.absmin, self->r.absmax, 300, numChunks, self->material, 0, (scale*self->mass) );
02574         }
02575 
02576         if ( self->wait == -1 )
02577         {
02578                 self->pain = 0;
02579                 return;
02580         }
02581 
02582         self->painDebounceTime = level.time + self->wait;
02583 }

void funcBBrushTouch gentity_t ent,
gentity_t other,
trace_t trace
 

Definition at line 2649 of file g_mover.c.

References gentity_t.

Referenced by SP_func_breakable().

02650 {
02651 }

void funcBBrushUse gentity_t self,
gentity_t other,
gentity_t activator
 

Definition at line 2502 of file g_mover.c.

References BSET_USE, funcBBrushDie(), G_ActivateBehavior(), G_UseTargets(), gentity_t, gentity_s::health, MOD_UNKNOWN, gentity_s::spawnflags, and gentity_s::target.

Referenced by SP_func_breakable().

02503 {
02504         G_ActivateBehavior( self, BSET_USE );
02505         if(self->spawnflags & 64)
02506         {//Using it doesn't break it, makes it use it's targets
02507                 if(self->target && self->target[0])
02508                 {
02509                         G_UseTargets(self, activator);
02510                 }
02511         }
02512         else
02513         {
02514                 funcBBrushDie(self, other, activator, self->health, MOD_UNKNOWN);
02515         }
02516 }

void G_Chunks int  owner,
vec3_t  origin,
const vec3_t  normal,
const vec3_t  mins,
const vec3_t  maxs,
float  speed,
int  numChunks,
material_t  chunkType,
int  customChunk,
float  baseScale
 

Definition at line 2365 of file g_mover.c.

References entityState_s::angles, entityState_s::angles2, entityState_s::apos, EV_DEBRIS, entityState_s::eventParm, G_TempEntity(), gentity_t, material_t, entityState_s::modelindex, entityState_s::origin, entityState_s::origin2, entityState_s::owner, gentity_s::s, entityState_s::speed, trajectory_t::trBase, entityState_s::trickedentindex, vec3_t, and VectorCopy.

Referenced by funcBBrushDieGo(), and funcBBrushPain().

02367 {
02368         gentity_t *te = G_TempEntity( origin, EV_DEBRIS );
02369 
02370         //Now it's time to cram everything horribly into the entitystate of an event entity.
02371         te->s.owner = owner;
02372         VectorCopy(origin, te->s.origin);
02373         VectorCopy(normal, te->s.angles);
02374         VectorCopy(maxs, te->s.origin2);
02375         VectorCopy(mins, te->s.angles2);
02376         te->s.speed = speed;
02377         te->s.eventParm = numChunks;
02378         te->s.trickedentindex = chunkType;
02379         te->s.modelindex = customChunk;
02380         te->s.apos.trBase[0] = baseScale;
02381 }

void G_CreateRotationMatrix vec3_t  angles,
vec3_t  matrix[3]
 

Definition at line 118 of file g_mover.c.

References AngleVectors(), and vec3_t.

Referenced by G_TryPushingEntity().

00118                                                              {
00119         AngleVectors(angles, matrix[0], matrix[1], matrix[2]);
00120         VectorInverse(matrix[1]);
00121 }

qboolean G_EntIsBreakable int  entityNum  ) 
 

Definition at line 2817 of file g_mover.c.

References gentity_s::classname, ENTITYNUM_WORLD, g_entities, gentity_t, Q_stricmp(), qboolean, qfalse, qtrue, gentity_s::r, SVF_GLASS_BRUSH, and entityShared_t::svFlags.

Referenced by NAV_TestBestNode(), vmMain(), and WP_SaberRadiusDamage().

02818 {
02819         gentity_t *ent;
02820 
02821         if ( entityNum < 0 || entityNum >= ENTITYNUM_WORLD )
02822         {
02823                 return qfalse;
02824         }
02825 
02826         ent = &g_entities[entityNum];
02827         if ( (ent->r.svFlags & SVF_GLASS_BRUSH) )
02828         {
02829                 return qtrue;
02830         }
02831         /*
02832         if ( (ent->svFlags&SVF_BBRUSH) )
02833         {
02834                 return qtrue;
02835         }
02836         */
02837         if ( !Q_stricmp( "func_breakable", ent->classname ) )
02838         {
02839                 return qtrue;
02840         }
02841 
02842         if ( !Q_stricmp( "misc_model_breakable", ent->classname ) )
02843         {
02844                 return qtrue;
02845         }
02846         if ( !Q_stricmp( "misc_maglock", ent->classname ) )
02847         {
02848                 return qtrue;
02849         }
02850 
02851         return qfalse;
02852 }

qboolean G_EntIsDoor int  entityNum  ) 
 

Definition at line 1212 of file g_mover.c.

References gentity_s::classname, ENTITYNUM_WORLD, g_entities, gentity_t, Q_stricmp(), qboolean, qfalse, and qtrue.

Referenced by G_EntIsUnlockedDoor(), NAV_TestBestNode(), and vmMain().

01213 {
01214         gentity_t *ent;
01215 
01216         if ( entityNum < 0 || entityNum >= ENTITYNUM_WORLD )
01217         {
01218                 return qfalse;
01219         }
01220 
01221         ent = &g_entities[entityNum];
01222         if ( ent && !Q_stricmp( "func_door", ent->classname ) )
01223         {//blocked by a door
01224                 return qtrue;
01225         }
01226         return qfalse;
01227 }

qboolean G_EntIsRemovableUsable int  entNum  ) 
 

Definition at line 3023 of file g_mover.c.

References gentity_s::classname, EF_SHADER_ANIM, entityState_s::eFlags, g_entities, gentity_t, Q_stricmp(), qboolean, qfalse, qtrue, gentity_s::s, gentity_s::spawnflags, and gentity_s::targetname.

Referenced by NAV_TestBestNode(), and vmMain().

03024 {
03025         gentity_t *ent = &g_entities[entNum];
03026         if ( ent->classname && !Q_stricmp( "func_usable", ent->classname ) )
03027         {
03028                 if ( !(ent->s.eFlags&EF_SHADER_ANIM) && !(ent->spawnflags&8) && ent->targetname )
03029                 {//not just a shader-animator and not ALWAYS_ON, so it must be removable somehow
03030                         return qtrue;
03031                 }
03032         }
03033         return qfalse;
03034 }

qboolean G_EntIsUnlockedDoor int  entityNum  ) 
 

Definition at line 1272 of file g_mover.c.

References gentity_s::classname, ENTITYNUM_WORLD, FL_INACTIVE, FL_TEAMSLAVE, gentity_s::flags, FOFS, G_EntIsDoor(), g_entities, G_Find(), G_FindDoorTrigger(), gentity_t, gentity_s::health, MOVER_FORCE_ACTIVATE, MOVER_LOCKED, MOVER_PLAYER_USE, NULL, Q_stricmp(), qboolean, qfalse, qtrue, gentity_s::spawnflags, gentity_s::targetname, and gentity_s::teammaster.

Referenced by NAV_CheckAhead(), NAV_ResolveEntityCollision(), NAV_TestBestNode(), and vmMain().

01273 {
01274         if ( entityNum < 0 || entityNum >= ENTITYNUM_WORLD )
01275         {
01276                 return qfalse;
01277         }
01278 
01279         if ( G_EntIsDoor( entityNum ) )
01280         {
01281                 gentity_t *ent = &g_entities[entityNum];
01282                 gentity_t *owner = NULL;
01283                 if ( ent->flags & FL_TEAMSLAVE )
01284                 {//not the master door, get the master door
01285                         while ( ent->teammaster && (ent->flags&FL_TEAMSLAVE))
01286                         {
01287                                 ent = ent->teammaster;
01288                         }
01289                 }
01290                 if ( ent->targetname )
01291                 {//find out what is targetting it
01292                         owner = NULL;
01293                         //FIXME: if ent->targetname, check what kind of trigger/ent is targetting it?  If a normal trigger (active, etc), then it's okay?
01294                         while ( (owner = G_Find( owner, FOFS( target ), ent->targetname )) != NULL )
01295                         {
01296                                 if ( !Q_stricmp( "trigger_multiple", owner->classname ) )//FIXME: other triggers okay too?
01297                                 {
01298                                         if ( !(owner->flags & FL_INACTIVE) )
01299                                         {
01300                                                 return qtrue;
01301                                         }
01302                                 }
01303                         }
01304                         owner = NULL;
01305                         while ( (owner = G_Find( owner, FOFS( target2 ), ent->targetname )) != NULL )
01306                         {
01307                                 if ( !Q_stricmp( "trigger_multiple", owner->classname ) )//FIXME: other triggers okay too?
01308                                 {
01309                                         if ( !(owner->flags & FL_INACTIVE) )
01310                                         {
01311                                                 return qtrue;
01312                                         }
01313                                 }
01314                         }
01315                         return qfalse;
01316                 }
01317                 else
01318                 {//check the door's auto-created trigger instead
01319                         owner = G_FindDoorTrigger( ent );
01320                         if ( owner && (owner->flags&FL_INACTIVE) )
01321                         {//owning auto-created trigger is inactive
01322                                 return qfalse;
01323                         }
01324                 }
01325                 if ( !(ent->flags & FL_INACTIVE) && //assumes that the reactivate trigger isn't right next to the door!
01326                         !ent->health &&
01327                         !(ent->spawnflags & MOVER_PLAYER_USE) &&
01328                         !(ent->spawnflags & MOVER_FORCE_ACTIVATE) &&
01329                         !(ent->spawnflags & MOVER_LOCKED))
01330                         //FIXME: what about MOVER_GOODIE?
01331                 {
01332                         return qtrue;
01333                 }
01334         }
01335         return qfalse;
01336 }

void G_ExplodeMissile gentity_t ent  ) 
 

Definition at line 215 of file g_missile.c.

00215                                         {
00216         vec3_t          dir;
00217         vec3_t          origin;
00218 
00219         BG_EvaluateTrajectory( &ent->s.pos, level.time, origin );
00220         SnapVector( origin );
00221         G_SetOrigin( ent, origin );
00222 
00223         // we don't have a valid direction, so just point straight up
00224         dir[0] = dir[1] = 0;
00225         dir[2] = 1;
00226 
00227         ent->s.eType = ET_GENERAL;
00228         G_AddEvent( ent, EV_MISSILE_MISS, DirToByte( dir ) );
00229 
00230         ent->freeAfterEvent = qtrue;
00231 
00232         ent->takedamage = qfalse;
00233         // splash damage
00234         if ( ent->splashDamage ) {
00235                 if( G_RadiusDamage( ent->r.currentOrigin, ent->parent, ent->splashDamage, ent->splashRadius, ent, 
00236                                 ent, ent->splashMethodOfDeath ) ) 
00237                 {
00238                         if (ent->parent)
00239                         {
00240                                 g_entities[ent->parent->s.number].client->accuracy_hits++;
00241                         }
00242                         else if (ent->activator)
00243                         {
00244                                 g_entities[ent->activator->s.number].client->accuracy_hits++;
00245                         }
00246                 }
00247         }
00248 
00249         trap_LinkEntity( ent );
00250 }

gentity_t* G_FindDoorTrigger gentity_t ent  ) 
 

Definition at line 1229 of file g_mover.c.

References entityShared_t::contents, CONTENTS_TRIGGER, FL_TEAMSLAVE, gentity_s::flags, FOFS, G_Find(), gentity_t, NULL, gentity_s::parent, gentity_s::r, gentity_s::targetname, and gentity_s::teammaster.

Referenced by G_EntIsUnlockedDoor(), and maglock_link().

01230 {
01231         gentity_t *owner = NULL;
01232         gentity_t *door = ent;
01233         if ( door->flags & FL_TEAMSLAVE )
01234         {//not the master door, get the master door
01235                 while ( door->teammaster && (door->flags&FL_TEAMSLAVE))
01236                 {
01237                         door = door->teammaster;
01238                 }
01239         }
01240         if ( door->targetname )
01241         {//find out what is targeting it
01242                 //FIXME: if ent->targetname, check what kind of trigger/ent is targetting it?  If a normal trigger (active, etc), then it's okay?
01243                 while ( (owner = G_Find( owner, FOFS( target ), door->targetname )) != NULL )
01244                 {
01245                         if ( owner && (owner->r.contents&CONTENTS_TRIGGER) )
01246                         {
01247                                 return owner;
01248                         }
01249                 }
01250                 owner = NULL;
01251                 while ( (owner = G_Find( owner, FOFS( target2 ), door->targetname )) != NULL )
01252                 {
01253                         if ( owner && (owner->r.contents&CONTENTS_TRIGGER) )
01254                         {
01255                                 return owner;
01256                         }
01257                 }
01258         }
01259 
01260         owner = NULL;
01261         while ( (owner = G_Find( owner, FOFS( classname ), "trigger_door" )) != NULL )
01262         {
01263                 if ( owner->parent == door )
01264                 {
01265                         return owner;
01266                 }
01267         }
01268 
01269         return NULL;
01270 }

void G_MiscModelExplosion vec3_t  mins,
vec3_t  maxs,
int  size,
material_t  chunkType
 

Definition at line 2349 of file g_mover.c.

References entityState_s::angles2, EV_MISC_MODEL_EXP, entityState_s::eventParm, G_TempEntity(), gentity_t, material_t, entityState_s::origin2, gentity_s::s, entityState_s::time, vec3_t, VectorAdd, VectorCopy, and VectorScale.

Referenced by funcBBrushDieGo().

02350 {
02351         gentity_t *te;
02352         vec3_t mid;
02353         
02354         VectorAdd( mins, maxs, mid );
02355         VectorScale( mid, 0.5f, mid );
02356 
02357         te = G_TempEntity( mid, EV_MISC_MODEL_EXP );
02358 
02359         VectorCopy(maxs, te->s.origin2);
02360         VectorCopy(mins, te->s.angles2);
02361         te->s.time = size;
02362         te->s.eventParm = chunkType;
02363 }

qboolean G_MoverPush gentity_t pusher,
vec3_t  move,
vec3_t  amove,
gentity_t **  obstacle
 

Definition at line 273 of file g_mover.c.

References entityShared_t::absmax, entityShared_t::absmin, pushed_t::angles, entityState_s::apos, gentity_s::client, entityShared_t::currentAngles, entityShared_t::currentOrigin, gentity_s::damage, playerState_s::delta_angles, pushed_t::deltayaw, pushed_t::ent, ET_BODY, ET_NPC, ET_PLAYER, entityState_s::eType, G_Damage(), g_entities, G_TestEntityPosition(), G_TryPushingEntity(), gentity_t, entityState_s::groundEntityNum, gentity_s::health, MAX_GENTITIES, entityShared_t::maxs, entityShared_t::mins, MOD_CRUSH, NULL, entityState_s::number, playerState_s::origin, pushed_t::origin, gentity_s::physicsObject, entityState_s::pos, gclient_s::ps, pushed, pushed_p, qboolean, qfalse, qtrue, gentity_s::r, RadiusFromBounds(), gentity_s::s, gentity_s::spawnflags, TR_SINE, trap_EntitiesInBox(), trap_LinkEntity(), trap_UnlinkEntity(), trajectory_t::trBase, trajectory_t::trType, vec3_t, VectorAdd, VectorCopy, and YAW.

Referenced by G_MoverTeam().

00273                                                                                            {
00274         int                     i, e;
00275         gentity_t       *check;
00276         vec3_t          mins, maxs;
00277         pushed_t        *p;
00278         int                     entityList[MAX_GENTITIES];
00279         int                     listedEntities;
00280         vec3_t          totalMins, totalMaxs;
00281 
00282         *obstacle = NULL;
00283 
00284 
00285         // mins/maxs are the bounds at the destination
00286         // totalMins / totalMaxs are the bounds for the entire move
00287         if ( pusher->r.currentAngles[0] || pusher->r.currentAngles[1] || pusher->r.currentAngles[2]
00288                 || amove[0] || amove[1] || amove[2] ) {
00289                 float           radius;
00290 
00291                 radius = RadiusFromBounds( pusher->r.mins, pusher->r.maxs );
00292                 for ( i = 0 ; i < 3 ; i++ ) {
00293                         mins[i] = pusher->r.currentOrigin[i] + move[i] - radius;
00294                         maxs[i] = pusher->r.currentOrigin[i] + move[i] + radius;
00295                         totalMins[i] = mins[i] - move[i];
00296                         totalMaxs[i] = maxs[i] - move[i];
00297                 }
00298         } else {
00299                 for (i=0 ; i<3 ; i++) {
00300                         mins[i] = pusher->r.absmin[i] + move[i];
00301                         maxs[i] = pusher->r.absmax[i] + move[i];
00302                 }
00303 
00304                 VectorCopy( pusher->r.absmin, totalMins );
00305                 VectorCopy( pusher->r.absmax, totalMaxs );
00306                 for (i=0 ; i<3 ; i++) {
00307                         if ( move[i] > 0 ) {
00308                                 totalMaxs[i] += move[i];
00309                         } else {
00310                                 totalMins[i] += move[i];
00311                         }
00312                 }
00313         }
00314 
00315         // unlink the pusher so we don't get it in the entityList
00316         trap_UnlinkEntity( pusher );
00317 
00318         listedEntities = trap_EntitiesInBox( totalMins, totalMaxs, entityList, MAX_GENTITIES );
00319 
00320         // move the pusher to it's final position
00321         VectorAdd( pusher->r.currentOrigin, move, pusher->r.currentOrigin );
00322         VectorAdd( pusher->r.currentAngles, amove, pusher->r.currentAngles );
00323         trap_LinkEntity( pusher );
00324 
00325         // see if any solid entities are inside the final position
00326         for ( e = 0 ; e < listedEntities ; e++ ) {
00327                 check = &g_entities[ entityList[ e ] ];
00328 
00329                 // only push items and players
00330                 if ( /*check->s.eType != ET_ITEM &&*/ check->s.eType != ET_PLAYER && check->s.eType != ET_NPC && !check->physicsObject ) {
00331                         continue;
00332                 }
00333 
00334                 // if the entity is standing on the pusher, it will definitely be moved
00335                 if ( check->s.groundEntityNum != pusher->s.number ) {
00336                         // see if the ent needs to be tested
00337                         if ( check->r.absmin[0] >= maxs[0]
00338                         || check->r.absmin[1] >= maxs[1]
00339                         || check->r.absmin[2] >= maxs[2]
00340                         || check->r.absmax[0] <= mins[0]
00341                         || check->r.absmax[1] <= mins[1]
00342                         || check->r.absmax[2] <= mins[2] ) {
00343                                 continue;
00344                         }
00345                         // see if the ent's bbox is inside the pusher's final position
00346                         // this does allow a fast moving object to pass through a thin entity...
00347                         if (!G_TestEntityPosition (check)) {
00348                                 continue;
00349                         }
00350                 }
00351 
00352                 // the entity needs to be pushed
00353                 if ( G_TryPushingEntity( check, pusher, move, amove ) ) {
00354                         continue;
00355                 }
00356 
00357                 if (pusher->damage && check->client && (pusher->spawnflags & 32))
00358                 {
00359                         G_Damage( check, pusher, pusher, NULL, NULL, pusher->damage, 0, MOD_CRUSH );
00360                         continue;
00361                 }
00362 
00363                 if (check->s.eType == ET_BODY ||
00364                         (check->s.eType == ET_PLAYER && check->health < 1))
00365                 { //whatever, just crush it
00366                         G_Damage( check, pusher, pusher, NULL, NULL, 999, 0, MOD_CRUSH );
00367                         continue;
00368                 }
00369 
00370                 // the move was blocked an entity
00371 
00372                 // bobbing entities are instant-kill and never get blocked
00373                 if ( pusher->s.pos.trType == TR_SINE || pusher->s.apos.trType == TR_SINE ) {
00374                         G_Damage( check, pusher, pusher, NULL, NULL, 99999, 0, MOD_CRUSH );
00375                         continue;
00376                 }
00377 
00378                 
00379                 // save off the obstacle so we can call the block function (crush, etc)
00380                 *obstacle = check;
00381 
00382                 // move back any entities we already moved
00383                 // go backwards, so if the same entity was pushed
00384                 // twice, it goes back to the original position
00385                 for ( p=pushed_p-1 ; p>=pushed ; p-- ) {
00386                         VectorCopy (p->origin, p->ent->s.pos.trBase);
00387                         VectorCopy (p->angles, p->ent->s.apos.trBase);
00388                         if ( p->ent->client ) {
00389                                 p->ent->client->ps.delta_angles[YAW] = p->deltayaw;
00390                                 VectorCopy (p->origin, p->ent->client->ps.origin);
00391                         }
00392                         trap_LinkEntity (p->ent);
00393                 }
00394                 return qfalse;
00395         }
00396 
00397         return qtrue;
00398 }

void G_MoverTeam gentity_t ent  ) 
 

Definition at line 406 of file g_mover.c.

References entityState_s::apos, BG_EvaluateTrajectory(), entityShared_t::currentAngles, entityShared_t::currentOrigin, G_MoverPush(), gentity_t, level, NULL, entityState_s::pos, level_locals_t::previousTime, pushed, pushed_p, gentity_s::r, gentity_s::reached, gentity_s::s, gentity_s::teamchain, level_locals_t::time, TR_LINEAR_STOP, TR_NONLINEAR_STOP, trap_LinkEntity(), trajectory_t::trDuration, trajectory_t::trTime, trajectory_t::trType, vec3_origin, vec3_t, and VectorSubtract.

Referenced by G_RunMover().

00406                                    {
00407         vec3_t          move, amove;
00408         gentity_t       *part, *obstacle;
00409         vec3_t          origin, angles;
00410 
00411         obstacle = NULL;
00412 
00413         // make sure all team slaves can move before commiting
00414         // any moves or calling any think functions
00415         // if the move is blocked, all moved objects will be backed out
00416         pushed_p = pushed;
00417         for (part = ent ; part ; part=part->teamchain) {
00418                 // get current position
00419                 BG_EvaluateTrajectory( &part->s.pos, level.time, origin );
00420                 BG_EvaluateTrajectory( &part->s.apos, level.time, angles );
00421                 VectorSubtract( origin, part->r.currentOrigin, move );
00422                 VectorSubtract( angles, part->r.currentAngles, amove );
00423                 if ( !VectorCompare( move, vec3_origin )
00424                         || !VectorCompare( amove, vec3_origin ) )
00425                 {//actually moved
00426                         if ( !G_MoverPush( part, move, amove, &obstacle ) ) {
00427                                 break;  // move was blocked
00428                         }
00429                 }
00430         }
00431 
00432         if (part) {
00433                 // go back to the previous position
00434                 for ( part = ent ; part ; part = part->teamchain ) {
00435                         part->s.pos.trTime += level.time - level.previousTime;
00436                         part->s.apos.trTime += level.time - level.previousTime;
00437                         BG_EvaluateTrajectory( &part->s.pos, level.time, part->r.currentOrigin );
00438                         BG_EvaluateTrajectory( &part->s.apos, level.time, part->r.currentAngles );
00439                         trap_LinkEntity( part );
00440                 }
00441 
00442                 // if the pusher has a "blocked" function, call it
00443                 if (ent->blocked) {
00444                         ent->blocked( ent, obstacle );
00445                 }
00446                 return;
00447         }
00448 
00449         // the move succeeded
00450         for ( part = ent ; part ; part = part->teamchain ) {
00451                 // call the reached function if time is at or past end point
00452                 if ( part->s.pos.trType == TR_LINEAR_STOP ||
00453                         part->s.pos.trType == TR_NONLINEAR_STOP) {
00454                         if ( level.time >= part->s.pos.trTime + part->s.pos.trDuration ) {
00455                                 if ( part->reached ) {
00456                                         part->reached( part );
00457                                 }
00458                         }
00459                 }
00460         }
00461 }

void G_PlayDoorLoopSound gentity_t ent  ) 
 

Definition at line 45 of file g_mover.c.

References BMS_MID, G_SoundSetIndex(), gentity_t, entityState_s::loopIsSoundset, entityState_s::loopSound, qtrue, gentity_s::s, gentity_s::soundSet, and entityState_s::soundSetIndex.

Referenced by Q3_Lerp2End(), Q3_Lerp2Origin(), Q3_Lerp2Pos(), Q3_Lerp2Start(), Reached_Train(), ReturnToPos1(), Think_BeginMoving(), and Use_BinaryMover_Go().

00046 {
00047         if (!ent->soundSet || !ent->soundSet[0])
00048         {
00049                 return;
00050         }
00051 
00052         ent->s.soundSetIndex = G_SoundSetIndex(ent->soundSet);
00053         ent->s.loopIsSoundset = qtrue;
00054         ent->s.loopSound = BMS_MID;
00055         /*
00056         ent->s.soundSetIndex = G_SoundSetIndex(ent->soundSet);
00057         ent->loopingOnClient = qtrue;
00058         G_AddEvent(ent, EV_PLAYDOORLOOPSOUND, 0);
00059         */
00060 }

void G_PlayDoorSound gentity_t ent,
int  type
 

Definition at line 68 of file g_mover.c.

References EV_PLAYDOORSOUND, G_AddEvent(), G_SoundSetIndex(), gentity_t, gentity_s::s, gentity_s::soundSet, and entityState_s::soundSetIndex.

Referenced by moverCallback(), Q3_Lerp2End(), Q3_Lerp2Origin(), Q3_Lerp2Pos(), Q3_Lerp2Start(), Reached_BinaryMover(), Reached_Train(), ReturnToPos1(), Think_BeginMoving(), and Use_BinaryMover_Go().

00069 {
00070         if (!ent->soundSet || !ent->soundSet[0])
00071         {
00072                 return;
00073         }
00074 
00075         ent->s.soundSetIndex = G_SoundSetIndex(ent->soundSet);
00076 
00077         G_AddEvent(ent, EV_PLAYDOORSOUND, type);
00078 }

void G_RotatePoint vec3_t  point,
vec3_t  matrix[3]
 

Definition at line 142 of file g_mover.c.

References DotProduct, vec3_t, and VectorCopy.

Referenced by G_TryPushingEntity().

00142                                                    {
00143         vec3_t tvec;
00144 
00145         VectorCopy(point, tvec);
00146         point[0] = DotProduct(matrix[0], tvec);
00147         point[1] = DotProduct(matrix[1], tvec);
00148         point[2] = DotProduct(matrix[2], tvec);
00149 }

void G_RunMover gentity_t ent  ) 
 

Definition at line 469 of file g_mover.c.

References entityState_s::apos, FL_TEAMSLAVE, gentity_s::flags, G_MoverTeam(), G_RunThink(), gentity_t, entityState_s::pos, gentity_s::s, TR_STATIONARY, and trajectory_t::trType.

Referenced by G_RunFrame().

00469                                   {
00470         // if not a team captain, don't do anything, because
00471         // the captain will handle everything
00472         if ( ent->flags & FL_TEAMSLAVE ) {
00473                 return;
00474         }
00475 
00476         // if stationary at one of the positions, don't move anything
00477         if ( ent->s.pos.trType != TR_STATIONARY || ent->s.apos.trType != TR_STATIONARY ) {
00478                 G_MoverTeam( ent );
00479         }
00480 
00481         // check think function
00482         G_RunThink( ent );
00483 }

gentity_t * G_TestEntityPosition gentity_t ent  ) 
 

Definition at line 86 of file g_mover.c.

References gentity_s::client, gentity_s::clipmask, trace_t::entityNum, g_entities, gentity_t, MASK_SOLID, entityShared_t::maxs, entityShared_t::mins, NULL, entityState_s::number, playerState_s::origin, entityState_s::pos, gclient_s::ps, gentity_s::r, gentity_s::s, trace_t::startsolid, trap_Trace(), trajectory_t::trBase, vec3_t, and VectorCopy.

Referenced by func_wait_return_solid(), G_MoverPush(), and G_TryPushingEntity().

00086                                                         {
00087         trace_t tr;
00088         int             mask;
00089 
00090         if ( ent->clipmask ) {
00091                 mask = ent->clipmask;
00092         } else {
00093                 mask = MASK_SOLID;
00094         }
00095         if ( ent->client ) {
00096                 vec3_t vMax;
00097                 VectorCopy(ent->r.maxs, vMax);
00098                 if (vMax[2] < 1)
00099                 {
00100                         vMax[2] = 1;
00101                 }
00102                 trap_Trace( &tr, ent->client->ps.origin, ent->r.mins, vMax, ent->client->ps.origin, ent->s.number, mask );
00103         } else {
00104                 trap_Trace( &tr, ent->s.pos.trBase, ent->r.mins, ent->r.maxs, ent->s.pos.trBase, ent->s.number, mask );
00105         }
00106         
00107         if (tr.startsolid)
00108                 return &g_entities[ tr.entityNum ];
00109                 
00110         return NULL;
00111 }

void G_TransposeMatrix vec3_t  matrix[3],
vec3_t  transpose[3]
 

Definition at line 128 of file g_mover.c.

References vec3_t.

Referenced by G_TryPushingEntity().

00128                                                               {
00129         int i, j;
00130         for (i = 0; i < 3; i++) {
00131                 for (j = 0; j < 3; j++) {
00132                         transpose[i][j] = matrix[j][i];
00133                 }
00134         }
00135 }

qboolean G_TryPushingEntity gentity_t check,
gentity_t pusher,
vec3_t  move,
vec3_t  amove
 

Definition at line 158 of file g_mover.c.

References ANGLE2SHORT, pushed_t::angles, entityState_s::apos, gentity_s::classname, gentity_s::client, entityShared_t::currentOrigin, gentity_s::damage, DAMAGE_NO_KNOCKBACK, playerState_s::delta_angles, pushed_t::deltayaw, pushed_t::ent, ENTITYNUM_NONE, G_CreateRotationMatrix(), G_Damage(), G_Error(), G_RotatePoint(), G_TestEntityPosition(), G_TransposeMatrix(), gentity_t, entityState_s::groundEntityNum, gentity_s::health, MAX_CLIENTS, MAX_GENTITIES, MOD_CRUSH, MOD_UNKNOWN, NULL, entityState_s::number, playerState_s::origin, pushed_t::origin, entityShared_t::ownerNum, entityState_s::pos, gclient_s::ps, pushed, pushed_p, Q_stricmp(), qboolean, qfalse, qtrue, gentity_s::r, gentity_s::s, gentity_s::spawnflags, gentity_s::takedamage, TR_STATIONARY, trap_LinkEntity(), trajectory_t::trBase, trajectory_t::trType, vec3_origin, vec3_t, VectorAdd, VectorCopy, VectorSubtract, entityState_s::weapon, and YAW.

Referenced by G_MoverPush().

00158                                                                                                      {
00159         vec3_t          matrix[3], transpose[3];
00160         vec3_t          org, org2, move2;
00161         gentity_t       *block;
00162 
00163         //This was only serverside not to mention it was never set.
00164         /*
00165         // EF_MOVER_STOP will just stop when contacting another entity
00166         // instead of pushing it, but entities can still ride on top of it
00167         if ( ( pusher->s.eFlags & EF_MOVER_STOP ) && 
00168                 check->s.groundEntityNum != pusher->s.number ) {
00169                 return qfalse;
00170         }
00171         */
00172         if ( pusher->s.apos.trType != TR_STATIONARY//rotating
00173                 && (pusher->spawnflags&16) //IMPACT
00174                 && Q_stricmp( "func_rotating", pusher->classname ) == 0 )
00175         {//just blow the fuck out of them
00176                 G_Damage( check, pusher, pusher, NULL, NULL, pusher->damage, DAMAGE_NO_KNOCKBACK, MOD_CRUSH );
00177                 return qtrue;
00178         }
00179 
00180         // save off the old position
00181         if (pushed_p > &pushed[MAX_GENTITIES]) {
00182                 G_Error( "pushed_p > &pushed[MAX_GENTITIES]" );
00183         }
00184         pushed_p->ent = check;
00185         VectorCopy (check->s.pos.trBase, pushed_p->origin);
00186         VectorCopy (check->s.apos.trBase, pushed_p->angles);
00187         if ( check->client ) {
00188                 pushed_p->deltayaw = check->client->ps.delta_angles[YAW];
00189                 VectorCopy (check->client->ps.origin, pushed_p->origin);
00190         }
00191         pushed_p++;
00192 
00193         // try moving the contacted entity 
00194         // figure movement due to the pusher's amove
00195         G_CreateRotationMatrix( amove, transpose );
00196         G_TransposeMatrix( transpose, matrix );
00197         if ( check->client ) {
00198                 VectorSubtract (check->client->ps.origin, pusher->r.currentOrigin, org);
00199         }
00200         else {
00201                 VectorSubtract (check->s.pos.trBase, pusher->r.currentOrigin, org);
00202         }
00203         VectorCopy( org, org2 );
00204         G_RotatePoint( org2, matrix );
00205         VectorSubtract (org2, org, move2);
00206         // add movement
00207         VectorAdd (check->s.pos.trBase, move, check->s.pos.trBase);
00208         VectorAdd (check->s.pos.trBase, move2, check->s.pos.trBase);
00209         if ( check->client ) {
00210                 VectorAdd (check->client->ps.origin, move, check->client->ps.origin);
00211                 VectorAdd (check->client->ps.origin, move2, check->client->ps.origin);
00212                 // make sure the client's view rotates when on a rotating mover
00213                 check->client->ps.delta_angles[YAW] += ANGLE2SHORT(amove[YAW]);
00214         }
00215 
00216         // may have pushed them off an edge
00217         if ( check->s.groundEntityNum != pusher->s.number ) {
00218                 check->s.groundEntityNum = ENTITYNUM_NONE;//-1;
00219         }
00220 
00221         block = G_TestEntityPosition( check );
00222         if (!block) {
00223                 // pushed ok
00224                 if ( check->client ) {
00225                         VectorCopy( check->client->ps.origin, check->r.currentOrigin );
00226                 } else {
00227                         VectorCopy( check->s.pos.trBase, check->r.currentOrigin );
00228                 }
00229                 trap_LinkEntity (check);
00230                 return qtrue;
00231         }
00232 
00233         if (check->takedamage && !check->client && check->s.weapon && check->r.ownerNum < MAX_CLIENTS &&
00234                 check->health < 500)
00235         {
00236                 if (check->health > 0)
00237                 {
00238                         G_Damage(check, pusher, pusher, vec3_origin, check->r.currentOrigin, 999, 0, MOD_UNKNOWN);
00239                 }
00240                 return qfalse;
00241         }
00242         // if it is ok to leave in the old position, do it
00243         // this is only relevent for riding entities, not pushed
00244         // Sliding trapdoors can cause this.
00245         VectorCopy( (pushed_p-1)->origin, check->s.pos.trBase);
00246         if ( check->client ) {
00247                 VectorCopy( (pushed_p-1)->origin, check->client->ps.origin);
00248         }
00249         VectorCopy( (pushed_p-1)->angles, check->s.apos.trBase );
00250         block = G_TestEntityPosition (check);
00251         if ( !block ) {
00252                 check->s.groundEntityNum = -1;
00253                 pushed_p--;
00254                 return qtrue;
00255         }
00256 
00257         // blocked
00258         return qfalse;
00259 }

void GlassDie gentity_t self,
gentity_t inflictor,
gentity_t attacker,
int  damage,
int  mod
 

Definition at line 2861 of file g_mover.c.

References entityShared_t::absmax, entityShared_t::absmin, entityState_s::angles, EV_GLASS_SHATTER, G_FreeEntity(), G_TempEntity(), G_UseTargets(), entityState_s::genericenemyindex, gentity_s::genericValue3, gentity_s::genericValue5, gentity_t, entityState_s::number, entityState_s::origin, entityState_s::pos, gentity_s::pos1, gentity_s::pos2, gentity_s::r, gentity_s::s, gentity_s::splashRadius, entityState_s::trickedentindex, trajectory_t::trTime, vec3_t, and VectorCopy.

Referenced by GlassUse(), and SP_func_glass().

02862 {
02863         gentity_t *te;
02864         vec3_t dif;
02865 
02866         if (self->genericValue5)
02867         { //was already destroyed, do not retrigger it
02868                 return;
02869         }
02870 
02871         self->genericValue5 = 1;
02872 
02873         dif[0] = (self->r.absmax[0]+self->r.absmin[0])/2;
02874         dif[1] = (self->r.absmax[1]+self->r.absmin[1])/2;
02875         dif[2] = (self->r.absmax[2]+self->r.absmin[2])/2;
02876 
02877         G_UseTargets(self, attacker);
02878 
02879         self->splashRadius = 40; // ?? some random number, maybe it's ok?
02880 
02881         te = G_TempEntity( dif, EV_GLASS_SHATTER );
02882         te->s.genericenemyindex = self->s.number;
02883         VectorCopy(self->pos1, te->s.origin);
02884         VectorCopy(self->pos2, te->s.angles);
02885         te->s.trickedentindex = (int)self->splashRadius;
02886         te->s.pos.trTime = (int)self->genericValue3;
02887 
02888         G_FreeEntity(self);
02889 }

void GlassDie_Old gentity_t self,
gentity_t inflictor,
gentity_t attacker,
int  damage,
int  mod
 

Definition at line 2891 of file g_mover.c.

References entityShared_t::absmax, entityShared_t::absmin, entityState_s::angles, EV_GLASS_SHATTER, G_FreeEntity(), G_TempEntity(), G_UseTargets(), entityState_s::genericenemyindex, gentity_t, entityShared_t::maxs, entityShared_t::mins, entityState_s::number, entityState_s::origin, gentity_s::r, gentity_s::s, vec3_t, and VectorCopy.

02892 {
02893         gentity_t *te;
02894         vec3_t dif;
02895 
02896         dif[0] = (self->r.absmax[0]+self->r.absmin[0])/2;
02897         dif[1] = (self->r.absmax[1]+self->r.absmin[1])/2;
02898         dif[2] = (self->r.absmax[2]+self->r.absmin[2])/2;
02899 
02900         G_UseTargets(self, attacker);
02901 
02902         te = G_TempEntity( dif, EV_GLASS_SHATTER );
02903         te->s.genericenemyindex = self->s.number;
02904         VectorCopy(self->r.maxs, te->s.origin);
02905         VectorCopy(self->r.mins, te->s.angles);
02906 
02907         G_FreeEntity(self);
02908 }

void GlassPain gentity_t self,
gentity_t attacker,
int  damage
 

Definition at line 2910 of file g_mover.c.

References gentity_t.

Referenced by SP_func_glass().

02911 {
02912         //G_Printf("Mr. Glass says: PLZ NO IT HURTS\n");
02913         //Make "cracking" sound?
02914 }

void GlassUse gentity_t self,
gentity_t other,
gentity_t activator
 

Definition at line 2916 of file g_mover.c.

References gentity_t, GlassDie(), entityShared_t::maxs, entityShared_t::mins, MOD_UNKNOWN, gentity_s::pos1, gentity_s::pos2, gentity_s::r, vec3_t, VectorAdd, VectorCopy, VectorNormalize(), VectorScale, and VectorSubtract.

Referenced by SP_func_glass().

02917 {
02918         vec3_t temp1, temp2;
02919 
02920         //no direct object to blame for the break, so fill the values with whatever
02921         VectorAdd( self->r.mins, self->r.maxs, temp1 );
02922         VectorScale( temp1, 0.5f, temp1 );
02923 
02924         VectorAdd( other->r.mins, other->r.maxs, temp2 );
02925         VectorScale( temp2, 0.5f, temp2 );
02926 
02927         VectorSubtract( temp1, temp2, self->pos2 );
02928         VectorCopy( temp1, self->pos1 );
02929 
02930         VectorNormalize( self->pos2 );
02931         VectorScale( self->pos2, 390, self->pos2 );
02932 
02933         GlassDie(self, other, activator, 100, MOD_UNKNOWN);
02934 }

void InitMover gentity_t ent  ) 
 

Definition at line 926 of file g_mover.c.

References entityState_s::constantLight, entityShared_t::currentOrigin, ET_MOVER, entityState_s::eType, FL_INACTIVE, gentity_s::flags, G_ModelIndex(), G_SpawnFloat(), G_SpawnVector(), gentity_t, InitMoverTrData(), gentity_s::model2, entityState_s::modelindex2, MOVER_INACTIVE, MOVER_PLAYER_USE, MOVER_POS1, gentity_s::moverState, gentity_s::pos1, qboolean, gentity_s::r, gentity_s::reached, Reached_BinaryMover(), gentity_s::s, gentity_s::spawnflags, strstr(), SVF_PLAYER_USABLE, SVF_USE_CURRENT_ORIGIN, entityShared_t::svFlags, trap_LinkEntity(), gentity_s::use, Use_BinaryMover(), vec3_t, and VectorCopy.

Referenced by func_wait_return_solid(), SP_func_bobbing(), SP_func_button(), SP_func_door(), SP_func_glass(), SP_func_pendulum(), SP_func_plat(), SP_func_rotating(), SP_func_static(), SP_func_train(), SP_func_usable(), and SP_func_wall().

00927 {
00928         float           light;
00929         vec3_t          color;
00930         qboolean        lightSet, colorSet;
00931 
00932         // if the "model2" key is set, use a seperate model
00933         // for drawing, but clip against the brushes
00934         if ( ent->model2 ) 
00935         {
00936                 if ( strstr( ent->model2, ".glm" ))
00937                 { //for now, not supported in MP.
00938                         ent->s.modelindex2 = 0;
00939                 }
00940                 else
00941                 {
00942                         ent->s.modelindex2 = G_ModelIndex( ent->model2 );
00943                 }
00944         }
00945 
00946         // if the "color" or "light" keys are set, setup constantLight
00947         lightSet = G_SpawnFloat( "light", "100", &light );
00948         colorSet = G_SpawnVector( "color", "1 1 1", color );
00949         if ( lightSet || colorSet ) {
00950                 int             r, g, b, i;
00951 
00952                 r = color[0] * 255;
00953                 if ( r > 255 ) {
00954                         r = 255;
00955                 }
00956                 g = color[1] * 255;
00957                 if ( g > 255 ) {
00958                         g = 255;
00959                 }
00960                 b = color[2] * 255;
00961                 if ( b > 255 ) {
00962                         b = 255;
00963                 }
00964                 i = light / 4;
00965                 if ( i > 255 ) {
00966                         i = 255;
00967                 }
00968                 ent->s.constantLight = r | ( g << 8 ) | ( b << 16 ) | ( i << 24 );
00969         }
00970 
00971         ent->use = Use_BinaryMover;
00972         ent->reached = Reached_BinaryMover;
00973 
00974         ent->moverState = MOVER_POS1;
00975         ent->r.svFlags = SVF_USE_CURRENT_ORIGIN;
00976         if ( ent->spawnflags & MOVER_INACTIVE )
00977         {// Make it inactive
00978                 ent->flags |= FL_INACTIVE;      
00979         }
00980         if(ent->spawnflags & MOVER_PLAYER_USE)
00981         {//Can be used by the player's BUTTON_USE
00982                 ent->r.svFlags |= SVF_PLAYER_USABLE;
00983         }
00984         ent->s.eType = ET_MOVER;
00985         VectorCopy( ent->pos1, ent->r.currentOrigin );
00986         trap_LinkEntity( ent );
00987 
00988         InitMoverTrData( ent );
00989 }

void InitMoverTrData gentity_t ent  ) 
 

Definition at line 903 of file g_mover.c.

References gentity_t, entityState_s::pos, gentity_s::pos1, gentity_s::pos2, gentity_s::s, gentity_s::speed, TR_STATIONARY, trajectory_t::trBase, trajectory_t::trDelta, trajectory_t::trDuration, trajectory_t::trType, vec3_t, VectorCopy, VectorScale, and VectorSubtract.

Referenced by InitMover(), Q3_Lerp2Origin(), and Q3_Lerp2Pos().

00904 {
00905         vec3_t          move;
00906         float           distance;
00907 
00908         ent->s.pos.trType = TR_STATIONARY;
00909         VectorCopy( ent->pos1, ent->s.pos.trBase );
00910 
00911         // calculate time to reach second position from speed
00912         VectorSubtract( ent->pos2, ent->pos1, move );
00913         distance = VectorLength( move );
00914         if ( ! ent->speed ) 
00915         {
00916                 ent->speed = 100;
00917         }
00918         VectorScale( move, ent->speed, ent->s.pos.trDelta );
00919         ent->s.pos.trDuration = distance * 1000 / ent->speed;
00920         if ( ent->s.pos.trDuration <= 0 ) 
00921         {
00922                 ent->s.pos.trDuration = 1;
00923         }
00924 }

void LockDoors gentity_t *const  ent  ) 
 

Definition at line 836 of file g_mover.c.

References entityState_s::frame, gentity_t, MOVER_LOCKED, gentity_s::s, gentity_s::spawnflags, and gentity_s::teamchain.

Referenced by Q3_Set().

00837 {
00838         //noise?
00839         //go through and lock the door and all the slaves
00840         gentity_t       *slave = ent;
00841         do 
00842         {
00843                 slave->spawnflags |= MOVER_LOCKED;
00844                 slave->s.frame = 0;//first stage of anim
00845                 slave = slave->teamchain;
00846         } while  ( slave );
00847 }

void MatchTeam gentity_t teamLeader,
int  moverState,
int  time
 

Referenced by moverCallback(), Q3_Lerp2Origin(), Q3_Lerp2Pos(), ReturnToPos1(), Think_MatchTeam(), Think_SpawnNewDoorTrigger(), and Use_BinaryMover_Go().

void Reached_BinaryMover gentity_t ent  ) 
 

Definition at line 624 of file g_mover.c.

References gentity_s::activator, BMS_END, CalcTeamDoorCenter(), gentity_s::closetarget, G_Error(), G_PlayDoorSound(), G_UseTargets2(), gentity_t, level, entityState_s::loopIsSoundset, entityState_s::loopSound, MOVER_1TO2, MOVER_2TO1, MOVER_POS1, MOVER_POS2, gentity_s::moverState, gentity_s::nextthink, gentity_s::opentarget, qfalse, ReturnToPos1(), gentity_s::s, SetMoverState(), gentity_s::spawnflags, gentity_s::teammaster, gentity_s::think, level_locals_t::time, trap_AdjustAreaPortalState(), gentity_s::use, vec3_t, and gentity_s::wait.

Referenced by InitMover().

00625 {
00626         // stop the looping sound
00627         ent->s.loopSound = 0;
00628         ent->s.loopIsSoundset = qfalse;
00629 
00630         if ( ent->moverState == MOVER_1TO2 ) 
00631         {//reached open
00632                 vec3_t  doorcenter;
00633 
00634                 // reached pos2
00635                 SetMoverState( ent, MOVER_POS2, level.time );
00636 
00637                 CalcTeamDoorCenter( ent, doorcenter );
00638 
00639                 // play sound
00640                 G_PlayDoorSound( ent, BMS_END );
00641 
00642                 if ( ent->wait < 0 )
00643                 {//Done for good
00644                         ent->think = 0;
00645                         ent->nextthink = 0;
00646                         ent->use = 0;
00647                 }
00648                 else
00649                 {
00650                         // return to pos1 after a delay
00651                         ent->think = ReturnToPos1;
00652                         if(ent->spawnflags & 8)
00653                         {//Toggle, keep think, wait for next use?
00654                                 ent->nextthink = -1;
00655                         }
00656                         else
00657                         {
00658                                 ent->nextthink = level.time + ent->wait;
00659                         }
00660                 }
00661 
00662                 // fire targets
00663                 if ( !ent->activator ) 
00664                 {
00665                         ent->activator = ent;
00666                 }
00667                 G_UseTargets2( ent, ent->activator, ent->opentarget );
00668         } 
00669         else if ( ent->moverState == MOVER_2TO1 ) 
00670         {//closed
00671                 vec3_t  doorcenter;
00672 
00673                 // reached pos1
00674                 SetMoverState( ent, MOVER_POS1, level.time );
00675 
00676                 CalcTeamDoorCenter( ent, doorcenter );
00677 
00678                 // play sound
00679                 G_PlayDoorSound( ent, BMS_END );
00680 
00681                 // close areaportals
00682                 if ( ent->teammaster == ent || !ent->teammaster ) 
00683                 {
00684                         trap_AdjustAreaPortalState( ent, qfalse );
00685                 }
00686                 G_UseTargets2( ent, ent->activator, ent->closetarget );
00687         } 
00688         else 
00689         {
00690                 G_Error( "Reached_BinaryMover: bad moverState" );
00691         }
00692 }

void Reached_Train gentity_t ent  ) 
 

Definition at line 1729 of file g_mover.c.

References BMS_END, G_PlayDoorLoopSound(), G_PlayDoorSound(), G_UseTargets(), gentity_t, level, entityState_s::loopIsSoundset, entityState_s::loopSound, MOVER_1TO2, gentity_s::nextthink, gentity_s::nextTrain, NULL, entityState_s::origin, entityState_s::pos, gentity_s::pos1, gentity_s::pos2, qfalse, gentity_s::s, SetMoverState(), gentity_s::speed, gentity_s::think, Think_BeginMoving(), level_locals_t::time, TR_STATIONARY, trajectory_t::trDuration, trajectory_t::trType, vec3_t, VectorCopy, VectorSubtract, and gentity_s::wait.

Referenced by SP_func_train(), and Think_SetupTrainTargets().

01729                                      {
01730         gentity_t               *next;
01731         float                   speed;
01732         vec3_t                  move;
01733         float                   length;
01734 
01735         // copy the apropriate values
01736         next = ent->nextTrain;
01737         if ( !next || !next->nextTrain ) {
01738                 return;         // just stop
01739         }
01740 
01741         // fire all other targets
01742         G_UseTargets( next, NULL );
01743 
01744         // set the new trajectory
01745         ent->nextTrain = next->nextTrain;
01746         VectorCopy( next->s.origin, ent->pos1 );
01747         VectorCopy( next->nextTrain->s.origin, ent->pos2 );
01748 
01749         // if the path_corner has a speed, use that
01750         if ( next->speed ) {
01751                 speed = next->speed;
01752         } else {
01753                 // otherwise use the train's speed
01754                 speed = ent->speed;
01755         }
01756         if ( speed < 1 ) {
01757                 speed = 1;
01758         }
01759 
01760         // calculate duration
01761         VectorSubtract( ent->pos2, ent->pos1, move );
01762         length = VectorLength( move );
01763 
01764         ent->s.pos.trDuration = length * 1000 / speed;
01765 
01766         // start it going
01767         SetMoverState( ent, MOVER_1TO2, level.time );
01768 
01769         G_PlayDoorSound( ent, BMS_END );
01770 
01771         // if there is a "wait" value on the target, don't start moving yet
01772         if ( next->wait ) {
01773                 ent->s.loopSound = 0;
01774                 ent->s.loopIsSoundset = qfalse;
01775                 ent->nextthink = level.time + next->wait * 1000;
01776                 ent->think = Think_BeginMoving;
01777                 ent->s.pos.trType = TR_STATIONARY;
01778         }
01779         else
01780         {
01781                 G_PlayDoorLoopSound( ent );
01782         }
01783 }

void ReturnToPos1 gentity_t ent  ) 
 

Definition at line 605 of file g_mover.c.

References BMS_START, G_PlayDoorLoopSound(), G_PlayDoorSound(), gentity_t, level, MatchTeam(), MOVER_2TO1, gentity_s::nextthink, gentity_s::s, gentity_s::think, level_locals_t::time, and entityState_s::time.

Referenced by Reached_BinaryMover(), and Use_BinaryMover_Go().

00605                                     {
00606         ent->think = 0;
00607         ent->nextthink = 0;
00608         ent->s.time = level.time;
00609 
00610         MatchTeam( ent, MOVER_2TO1, level.time );
00611 
00612         // starting sound
00613         G_PlayDoorLoopSound( ent );
00614         G_PlayDoorSound( ent, BMS_START );      //??
00615 }

void SetMoverState gentity_t ent,
moverState_t  moverState,
int  time
 

Definition at line 525 of file g_mover.c.

References gentity_s::alt_fire, BG_EvaluateTrajectory(), entityShared_t::currentOrigin, gentity_t, level, MOVER_1TO2, MOVER_2TO1, MOVER_POS1, MOVER_POS2, gentity_s::moverState, entityState_s::pos, gentity_s::pos1, gentity_s::pos2, gentity_s::r, gentity_s::s, level_locals_t::time, TR_LINEAR_STOP, TR_NONLINEAR_STOP, TR_STATIONARY, trap_LinkEntity(), trajectory_t::trBase, trajectory_t::trDelta, trajectory_t::trDuration, trajectory_t::trTime, trajectory_t::trType, vec3_t, VectorCopy, VectorScale, and VectorSubtract.

Referenced by MatchTeam(), Reached_BinaryMover(), and Reached_Train().

00525                                                                         {
00526         vec3_t                  delta;
00527         float                   f;
00528 
00529         ent->moverState = moverState;
00530 
00531         ent->s.pos.trTime = time;
00532 
00533         if ( ent->s.pos.trDuration <= 0 )
00534         {//Don't allow divide by zero!
00535                 ent->s.pos.trDuration = 1;
00536         }
00537 
00538         switch( moverState ) {
00539         case MOVER_POS1:
00540                 VectorCopy( ent->pos1, ent->s.pos.trBase );
00541                 ent->s.pos.trType = TR_STATIONARY;
00542                 break;
00543         case MOVER_POS2:
00544                 VectorCopy( ent->pos2, ent->s.pos.trBase );
00545                 ent->s.pos.trType = TR_STATIONARY;
00546                 break;
00547         case MOVER_1TO2:
00548                 VectorCopy( ent->pos1, ent->s.pos.trBase );
00549                 VectorSubtract( ent->pos2, ent->pos1, delta );
00550                 f = 1000.0 / ent->s.pos.trDuration;
00551                 VectorScale( delta, f, ent->s.pos.trDelta );
00552                 if ( ent->alt_fire )
00553                 {
00554                         ent->s.pos.trType = TR_LINEAR_STOP;
00555                 }
00556                 else
00557                 {
00558                         ent->s.pos.trType = TR_NONLINEAR_STOP;
00559                 }
00560                 //ent->s.eFlags &= ~EF_BLOCKED_MOVER;
00561                 break;
00562         case MOVER_2TO1:
00563                 VectorCopy( ent->pos2, ent->s.pos.trBase );
00564                 VectorSubtract( ent->pos1, ent->pos2, delta );
00565                 f = 1000.0 / ent->s.pos.trDuration;
00566                 VectorScale( delta, f, ent->s.pos.trDelta );
00567                 if ( ent->alt_fire )
00568                 {
00569                         ent->s.pos.trType = TR_LINEAR_STOP;
00570                 }
00571                 else
00572                 {
00573                         ent->s.pos.trType = TR_NONLINEAR_STOP;
00574                 }
00575                 //ent->s.eFlags &= ~EF_BLOCKED_MOVER;
00576                 break;
00577         }
00578         BG_EvaluateTrajectory( &ent->s.pos, level.time, ent->r.currentOrigin ); 
00579         trap_LinkEntity( ent );
00580 }

void SP_func_bobbing gentity_t ent  ) 
 

Definition at line 2217 of file g_mover.c.

References entityShared_t::currentOrigin, gentity_s::damage, G_SpawnFloat(), G_SpawnInt(), gentity_t, InitMover(), gentity_s::model, entityState_s::origin, entityState_s::pos, gentity_s::r, gentity_s::s, gentity_s::spawnflags, gentity_s::speed, TR_SINE, trap_SetBrushModel(), trajectory_t::trBase, trajectory_t::trDelta, trajectory_t::trDuration, trajectory_t::trTime, trajectory_t::trType, and VectorCopy.

02217                                       {
02218         float           height;
02219         float           phase;
02220 
02221         G_SpawnFloat( "speed", "4", &ent->speed );
02222         G_SpawnFloat( "height", "32", &height );
02223         G_SpawnInt( "dmg", "2", &ent->damage );
02224         G_SpawnFloat( "phase", "0", &phase );
02225 
02226         trap_SetBrushModel( ent, ent->model );
02227         InitMover( ent );
02228 
02229         VectorCopy( ent->s.origin, ent->s.pos.trBase );
02230         VectorCopy( ent->s.origin, ent->r.currentOrigin );
02231 
02232         ent->s.pos.trDuration = ent->speed * 1000;
02233         ent->s.pos.trTime = ent->s.pos.trDuration * phase;
02234         ent->s.pos.trType = TR_SINE;
02235 
02236         // set the axis of bobbing
02237         if ( ent->spawnflags & 1 ) {
02238                 ent->s.pos.trDelta[0] = height;
02239         } else if ( ent->spawnflags & 2 ) {
02240                 ent->s.pos.trDelta[1] = height;
02241         } else {
02242                 ent->s.pos.trDelta[2] = height;
02243         }
02244 }

void SP_func_breakable gentity_t self  ) 
 

Definition at line 2717 of file g_mover.c.

References atoi(), FL_DMG_BY_HEAVY_WEAP_ONLY, FL_DMG_BY_SABER_ONLY, gentity_s::flags, funcBBrushPain(), funcBBrushTouch(), funcBBrushUse(), G_EffectIndex(), G_Error(), g_gametype, G_ScaleNetHealth(), G_SoundIndex(), G_SpawnFloat(), G_SpawnInt(), G_SpawnString(), gentity_s::genericValue15, gentity_s::genericValue4, gentity_t, GT_SIEGE, gentity_s::health, vmCvar_t::integer, gentity_s::mass, gentity_s::material, gentity_s::maxHealth, gentity_s::model, NULL, gentity_s::pain, qtrue, gentity_s::radius, gentity_s::spawnflags, gentity_s::splashDamage, gentity_s::splashRadius, gentity_s::takedamage, gentity_s::team, gentity_s::teamnodmg, gentity_s::touch, and gentity_s::use.

02718 {
02719         int t;
02720         char *s = NULL;
02721 
02722         G_SpawnString("playfx", "", &s);
02723 
02724         if (s && s[0])
02725         { //should we play a special death effect?
02726                 self->genericValue15 = G_EffectIndex(s);
02727         }
02728         else
02729         {
02730                 self->genericValue15 = 0;
02731         }
02732 
02733         if(!(self->spawnflags & 1))
02734         {
02735                 if(!self->health)
02736                 {
02737                         self->health = 10;
02738                 }
02739         }
02740 
02741         G_SpawnInt( "showhealth", "0", &t );
02742 
02743         if (t)
02744         { //a non-0 maxhealth value will mean we want to show the health on the hud
02745                 self->maxHealth = self->health;
02746                 G_ScaleNetHealth(self);
02747         }
02748 
02749         //NOTE: g_spawn.c does this automatically now
02750         //G_SpawnInt( "teamowner", "0", &t );
02751         //self->s.teamowner = t;
02752 
02753         if ( self->spawnflags & 16 ) // saber only
02754         {
02755                 self->flags |= FL_DMG_BY_SABER_ONLY;
02756         }
02757         else if ( self->spawnflags & 32 ) // heavy weap
02758         {
02759                 self->flags |= FL_DMG_BY_HEAVY_WEAP_ONLY;
02760         }
02761 
02762         if (self->health) 
02763         {
02764                 self->takedamage = qtrue;
02765         }
02766 
02767         G_SoundIndex("sound/weapons/explosions/cargoexplode.wav");//precaching
02768         G_SpawnFloat( "radius", "1", &self->radius ); // used to scale chunk code if desired by a designer
02769         G_SpawnInt( "material", "0", (int*)&self->material );
02770 
02771         G_SpawnInt( "splashDamage", "0", &self->splashDamage );
02772         G_SpawnInt( "splashRadius", "0", &self->splashRadius );
02773 
02774         CacheChunkEffects( self->material );
02775 
02776         self->use = funcBBrushUse;
02777 
02778         //if ( self->paintarget )
02779         {
02780                 self->pain = funcBBrushPain;
02781         }
02782 
02783         self->touch = funcBBrushTouch;
02784 
02785         /*
02786         if ( self->team && self->team[0] )
02787         {
02788                 self->alliedTeam = TranslateTeamName( self->team );
02789                 if(self->alliedTeam == TEAM_FREE)
02790                 {
02791                         G_Error("team name %s not recognized\n", self->team);
02792                 }
02793         }
02794         */
02795         if ( self->team && self->team[0] && g_gametype.integer == GT_SIEGE &&
02796                 !self->teamnodmg)
02797         {
02798                 self->teamnodmg = atoi(self->team);
02799         }
02800         self->team = NULL;
02801         if (!self->model) {
02802                 G_Error("func_breakable with NULL model\n");
02803         }
02804         InitBBrush( self );
02805 
02806         if ( !self->radius )
02807         {//numchunks multiplier
02808                 self->radius = 1.0f;
02809         }
02810         if ( !self->mass )
02811         {//chunksize multiplier
02812                 self->mass = 1.0f;
02813         }
02814         self->genericValue4 = 1; //so damage sys knows it's a bbrush
02815 }

void SP_func_button gentity_t ent  ) 
 

Definition at line 1650 of file g_mover.c.

References entityState_s::angles, fabs(), G_SetMovedir(), G_SpawnFloat(), gentity_t, gentity_s::health, InitMover(), entityShared_t::maxs, entityShared_t::mins, gentity_s::model, gentity_s::movedir, entityState_s::origin, gentity_s::pos1, gentity_s::pos2, qtrue, gentity_s::r, gentity_s::s, gentity_s::speed, gentity_s::takedamage, gentity_s::touch, Touch_Button(), trap_SetBrushModel(), vec3_t, VectorCopy, VectorMA, VectorSubtract, and gentity_s::wait.

01650                                       {
01651         vec3_t          abs_movedir;
01652         float           distance;
01653         vec3_t          size;
01654         float           lip;
01655 
01656 //      ent->sound1to2 = G_SoundIndex("sound/movers/switches/butn2.wav");
01657         
01658         if ( !ent->speed ) {
01659                 ent->speed = 40;
01660         }
01661 
01662         if ( !ent->wait ) {
01663                 ent->wait = 1;
01664         }
01665         ent->wait *= 1000;
01666 
01667         // first position
01668         VectorCopy( ent->s.origin, ent->pos1 );
01669 
01670         // calculate second position
01671         trap_SetBrushModel( ent, ent->model );
01672 
01673         G_SpawnFloat( "lip", "4", &lip );
01674 
01675         G_SetMovedir( ent->s.angles, ent->movedir );
01676         abs_movedir[0] = fabs(ent->movedir[0]);
01677         abs_movedir[1] = fabs(ent->movedir[1]);
01678         abs_movedir[2] = fabs(ent->movedir[2]);
01679         VectorSubtract( ent->r.maxs, ent->r.mins, size );
01680         distance = abs_movedir[0] * size[0] + abs_movedir[1] * size[1] + abs_movedir[2] * size[2] - lip;
01681         VectorMA (ent->pos1, distance, ent->movedir, ent->pos2);
01682 
01683         if (ent->health) {
01684                 // shootable button
01685                 ent->takedamage = qtrue;
01686         } else {
01687                 // touchable button
01688                 ent->touch = Touch_Button;
01689         }
01690 
01691         InitMover( ent );
01692 }

void SP_func_door gentity_t ent  ) 
 

Definition at line 1370 of file g_mover.c.

References gentity_s::alliedTeam, entityState_s::angles, gentity_s::blocked, Blocked_Door(), entityState_s::bolt1, gentity_s::damage, gentity_s::delay, DotProduct, EF_SHADER_ANIM, entityState_s::eFlags, fabs(), FL_TEAMSLAVE, gentity_s::flags, entityState_s::frame, FRAMETIME, G_SetMovedir(), G_SpawnFloat(), G_SpawnInt(), gentity_s::genericValue14, gentity_t, InitMover(), level, entityShared_t::maxs, entityShared_t::mins, gentity_s::model, gentity_s::movedir, MOVER_FORCE_ACTIVATE, MOVER_LOCKED, MOVER_PLAYER_USE, gentity_s::nextthink, entityState_s::origin, gentity_s::pos1, gentity_s::pos2, qtrue, gentity_s::r, gentity_s::s, gentity_s::spawnflags, gentity_s::speed, gentity_s::takedamage, gentity_s::targetname, gentity_s::think, Think_MatchTeam(), Think_SpawnNewDoorTrigger(), level_locals_t::time, trap_SetBrushModel(), vec3_t, VectorCopy, VectorMA, VectorSubtract, and gentity_s::wait.

01371 {
01372         vec3_t  abs_movedir;
01373         float   distance;
01374         vec3_t  size;
01375         float   lip;
01376 
01377         G_SpawnInt("vehopen", "0", &ent->genericValue14);
01378 
01379         ent->blocked = Blocked_Door;
01380 
01381         // default speed of 400
01382         if (!ent->speed)
01383                 ent->speed = 400;
01384 
01385         // default wait of 2 seconds
01386         if (!ent->wait)
01387                 ent->wait = 2;
01388         ent->wait *= 1000;
01389 
01390         ent->delay *= 1000;
01391 
01392         // default lip of 8 units
01393         G_SpawnFloat( "lip", "8", &lip );
01394 
01395         // default damage of 2 points
01396         G_SpawnInt( "dmg", "2", &ent->damage );
01397         if ( ent->damage < 0 )
01398         {
01399                 ent->damage = 0;
01400         }
01401 
01402         G_SpawnInt( "teamallow", "0", &ent->alliedTeam );
01403 
01404         // first position at start
01405         VectorCopy( ent->s.origin, ent->pos1 );
01406 
01407         // calculate second position
01408         trap_SetBrushModel( ent, ent->model );
01409         G_SetMovedir( ent->s.angles, ent->movedir );
01410         abs_movedir[0] = fabs( ent->movedir[0] );
01411         abs_movedir[1] = fabs( ent->movedir[1] );
01412         abs_movedir[2] = fabs( ent->movedir[2] );
01413         VectorSubtract( ent->r.maxs, ent->r.mins, size );
01414         distance = DotProduct( abs_movedir, size ) - lip;
01415         VectorMA( ent->pos1, distance, ent->movedir, ent->pos2 );
01416 
01417         // if "start_open", reverse position 1 and 2
01418         if ( ent->spawnflags & 1 ) 
01419         {
01420                 vec3_t  temp;
01421 
01422                 VectorCopy( ent->pos2, temp );
01423                 VectorCopy( ent->s.origin, ent->pos2 );
01424                 VectorCopy( temp, ent->pos1 );
01425         }
01426 
01427         if ( ent->spawnflags & MOVER_LOCKED )
01428         {//a locked door, set up as locked until used directly
01429                 ent->s.eFlags |= EF_SHADER_ANIM;//use frame-controlled shader anim
01430                 ent->s.frame = 0;//first stage of anim
01431         }
01432         InitMover( ent );
01433 
01434         ent->nextthink = level.time + FRAMETIME;
01435 
01436         if ( !(ent->flags&FL_TEAMSLAVE) ) 
01437         {
01438                 int health;
01439 
01440                 G_SpawnInt( "health", "0", &health );
01441                 
01442                 if ( health ) 
01443                 {
01444                         ent->takedamage = qtrue;
01445                 }
01446                 
01447                 if ( !(ent->spawnflags&MOVER_LOCKED) && (ent->targetname || health || ent->spawnflags & MOVER_PLAYER_USE || ent->spawnflags & MOVER_FORCE_ACTIVATE) )
01448                 {
01449                         // non touch/shoot doors
01450                         ent->think = Think_MatchTeam;
01451 
01452                         if (ent->spawnflags & MOVER_FORCE_ACTIVATE)
01453                         { //so we know it's push/pullable on the client
01454                                 ent->s.bolt1 = 1;
01455                         }
01456                 } 
01457                 else 
01458                 {//locked doors still spawn a trigger
01459                         ent->think = Think_SpawnNewDoorTrigger;
01460                 }
01461         }
01462 }

void SP_func_glass gentity_t ent  ) 
 

Definition at line 2943 of file g_mover.c.

References entityShared_t::currentOrigin, gentity_s::die, G_SpawnInt(), gentity_s::genericValue1, gentity_s::genericValue3, gentity_s::genericValue4, gentity_t, GlassDie(), GlassPain(), GlassUse(), gentity_s::health, InitMover(), gentity_s::model, MOVER_POS1, gentity_s::moverState, entityState_s::origin, gentity_s::pain, entityState_s::pos, qfalse, qtrue, gentity_s::r, gentity_s::s, gentity_s::spawnflags, SVF_GLASS_BRUSH, entityShared_t::svFlags, gentity_s::takedamage, trap_SetBrushModel(), trajectory_t::trBase, gentity_s::use, and VectorCopy.

02943                                      {
02944         trap_SetBrushModel( ent, ent->model );
02945         InitMover( ent );
02946 
02947         ent->r.svFlags = SVF_GLASS_BRUSH;
02948 
02949         VectorCopy( ent->s.origin, ent->s.pos.trBase );
02950         VectorCopy( ent->s.origin, ent->r.currentOrigin );
02951         if (!ent->health)
02952         {
02953                 ent->health = 1;
02954         }
02955 
02956         G_SpawnInt("maxshards", "0", &ent->genericValue3);
02957 
02958         ent->genericValue1 = 0;
02959 
02960         ent->genericValue4 = 1;
02961 
02962         ent->moverState = MOVER_POS1;
02963 
02964         if (ent->spawnflags & 1)
02965         {
02966                 ent->takedamage = qfalse;
02967         }
02968         else
02969         {
02970                 ent->takedamage = qtrue;
02971         }
02972 
02973         ent->die = GlassDie;
02974         ent->use = GlassUse;
02975         ent->pain = GlassPain;
02976 }

void SP_func_pendulum gentity_t ent  ) 
 

Definition at line 2266 of file g_mover.c.

References entityState_s::angles, entityState_s::apos, entityShared_t::currentOrigin, gentity_s::damage, fabs(), g_gravity, G_SpawnFloat(), G_SpawnInt(), gentity_t, InitMover(), M_PI, entityShared_t::mins, gentity_s::model, entityState_s::origin, entityState_s::pos, gentity_s::r, gentity_s::s, sqrt(), TR_SINE, trap_SetBrushModel(), trajectory_t::trBase, trajectory_t::trDelta, trajectory_t::trDuration, trajectory_t::trTime, trajectory_t::trType, vmCvar_t::value, and VectorCopy.

02266                                       {
02267         float           freq;
02268         float           length;
02269         float           phase;
02270         float           speed;
02271 
02272         G_SpawnFloat( "speed", "30", &speed );
02273         G_SpawnInt( "dmg", "2", &ent->damage );
02274         G_SpawnFloat( "phase", "0", &phase );
02275 
02276         trap_SetBrushModel( ent, ent->model );
02277 
02278         // find pendulum length
02279         length = fabs( ent->r.mins[2] );
02280         if ( length < 8 ) {
02281                 length = 8;
02282         }
02283 
02284         freq = 1 / ( M_PI * 2 ) * sqrt( g_gravity.value / ( 3 * length ) );
02285 
02286         ent->s.pos.trDuration = ( 1000 / freq );
02287 
02288         InitMover( ent );
02289 
02290         VectorCopy( ent->s.origin, ent->s.pos.trBase );
02291         VectorCopy( ent->s.origin, ent->r.currentOrigin );
02292 
02293         VectorCopy( ent->s.angles, ent->s.apos.trBase );
02294 
02295         ent->s.apos.trDuration = 1000 / freq;
02296         ent->s.apos.trTime = ent->s.apos.trDuration * phase;
02297         ent->s.apos.trType = TR_SINE;
02298         ent->s.apos.trDelta[2] = speed;
02299 }

void SP_func_plat gentity_t ent  ) 
 

Definition at line 1566 of file g_mover.c.

References entityState_s::angles, gentity_s::blocked, Blocked_Door(), gentity_s::damage, G_SpawnFloat(), G_SpawnInt(), gentity_t, InitMover(), entityShared_t::maxs, entityShared_t::mins, gentity_s::model, entityState_s::origin, gentity_s::parent, gentity_s::pos1, gentity_s::pos2, gentity_s::r, gentity_s::s, SpawnPlatTrigger(), gentity_s::speed, gentity_s::targetname, gentity_s::touch, Touch_Plat(), trap_SetBrushModel(), VectorClear, VectorCopy, and gentity_s::wait.

01566                                    {
01567         float           lip, height;
01568 
01569 //      ent->sound1to2 = ent->sound2to1 = G_SoundIndex("sound/movers/plats/pt1_strt.wav");
01570 //      ent->soundPos1 = ent->soundPos2 = G_SoundIndex("sound/movers/plats/pt1_end.wav");
01571 
01572         VectorClear (ent->s.angles);
01573 
01574         G_SpawnFloat( "speed", "200", &ent->speed );
01575         G_SpawnInt( "dmg", "2", &ent->damage );
01576         G_SpawnFloat( "wait", "1", &ent->wait );
01577         G_SpawnFloat( "lip", "8", &lip );
01578 
01579         ent->wait = 1000;
01580 
01581         // create second position
01582         trap_SetBrushModel( ent, ent->model );
01583 
01584         if ( !G_SpawnFloat( "height", "0", &height ) ) {
01585                 height = (ent->r.maxs[2] - ent->r.mins[2]) - lip;
01586         }
01587 
01588         // pos1 is the rest (bottom) position, pos2 is the top
01589         VectorCopy( ent->s.origin, ent->pos2 );
01590         VectorCopy( ent->pos2, ent->pos1 );
01591         ent->pos1[2] -= height;
01592 
01593         InitMover( ent );
01594 
01595         // touch function keeps the plat from returning while
01596         // a live player is standing on it
01597         ent->touch = Touch_Plat;
01598 
01599         ent->blocked = Blocked_Door;
01600 
01601         ent->parent = ent;      // so it can be treated as a door
01602 
01603         // spawn the trigger if one hasn't been custom made
01604         if ( !ent->targetname ) {
01605                 SpawnPlatTrigger(ent);
01606         }
01607 }

void SP_func_rotating gentity_t ent  ) 
 

Definition at line 2121 of file g_mover.c.

References entityShared_t::absmax, entityShared_t::absmin, entityState_s::apos, entityShared_t::currentAngles, entityShared_t::currentOrigin, gentity_s::damage, EF_RADAROBJECT, entityState_s::eFlags, G_SpawnInt(), G_SpawnVector(), gentity_t, gentity_s::health, entityState_s::iModelScale, InitMover(), gentity_s::model, entityState_s::origin, entityState_s::pos, gentity_s::r, gentity_s::s, SP_func_breakable(), gentity_s::spawnflags, gentity_s::speed, entityState_s::speed, TR_LINEAR, trap_LinkEntity(), trap_SetBrushModel(), trajectory_t::trBase, trajectory_t::trDelta, trajectory_t::trType, vec3_t, and VectorCopy.

Referenced by asteroid_field_think().

02121                                        {
02122         vec3_t spinangles;
02123         if ( ent->health )
02124         {
02125                 int sav_spawnflags = ent->spawnflags;
02126                 ent->spawnflags = 0;
02127                 SP_func_breakable( ent );
02128                 ent->spawnflags = sav_spawnflags;
02129         }
02130         else
02131         {
02132                 trap_SetBrushModel( ent, ent->model );
02133                 InitMover( ent );
02134 
02135                 VectorCopy( ent->s.origin, ent->s.pos.trBase );
02136                 VectorCopy( ent->s.pos.trBase, ent->r.currentOrigin );
02137                 VectorCopy( ent->s.apos.trBase, ent->r.currentAngles );
02138 
02139                 trap_LinkEntity( ent );
02140         }
02141 
02142 #ifdef _XBOX
02143         int     tempModelScale;
02144         G_SpawnInt("model2scale", "0", &tempModelScale);
02145         ent->s.iModelScale = tempModelScale;
02146 #else
02147         G_SpawnInt("model2scale", "0", &ent->s.iModelScale);
02148 #endif
02149         if (ent->s.iModelScale < 0)
02150         {
02151                 ent->s.iModelScale = 0;
02152         }
02153         else if (ent->s.iModelScale > 1023)
02154         {
02155                 ent->s.iModelScale = 1023;
02156         }
02157 
02158         if ( G_SpawnVector( "spinangles", "0 0 0", spinangles ) )
02159         {
02160                 ent->speed = VectorLength( spinangles );
02161                 // set the axis of rotation
02162                 VectorCopy( spinangles, ent->s.apos.trDelta );
02163         }
02164         else
02165         {
02166                 if ( !ent->speed ) {
02167                         ent->speed = 100;
02168                 }
02169                 // set the axis of rotation
02170                 if ( ent->spawnflags & 4 ) {
02171                         ent->s.apos.trDelta[2] = ent->speed;
02172                 } else if ( ent->spawnflags & 8 ) {
02173                         ent->s.apos.trDelta[0] = ent->speed;
02174                 } else {
02175                         ent->s.apos.trDelta[1] = ent->speed;
02176                 }
02177         }
02178         ent->s.apos.trType = TR_LINEAR;
02179 
02180         if (!ent->damage) {
02181                 if ( (ent->spawnflags&16) )//IMPACT
02182                 {
02183                         ent->damage = 10000;
02184                 }
02185                 else
02186                 {
02187                         ent->damage = 2;
02188                 }
02189         }
02190         if ( (ent->spawnflags&2) )//RADAR
02191         {//show up on Radar at close range and play impact sound when close...?  Range based on my size
02192                 ent->s.speed = Distance( ent->r.absmin, ent->r.absmax )*0.5f;
02193                 ent->s.eFlags |= EF_RADAROBJECT;
02194         }
02195 }

void SP_func_static gentity_t ent  ) 
 

Definition at line 1946 of file g_mover.c.

References entityState_s::angles, entityState_s::bolt1, EF2_HYPERSPACE, EF_PERMANENT, EF_SHADER_ANIM, entityState_s::eFlags, entityState_s::eFlags2, entityState_s::frame, func_static_use(), G_SetAngles(), G_SetOrigin(), G_SpawnInt(), gentity_t, entityState_s::iModelScale, InitMover(), level, level_locals_t::mBSPInstanceDepth, gentity_s::model, entityState_s::origin, gentity_s::pos1, gentity_s::pos2, gentity_s::r, gentity_s::reached, gentity_s::s, gentity_s::spawnflags, SVF_BROADCAST, entityShared_t::svFlags, trap_LinkEntity(), trap_SetBrushModel(), gentity_s::use, and VectorCopy.

01947 {
01948         int             test;
01949         trap_SetBrushModel( ent, ent->model );
01950 
01951         VectorCopy( ent->s.origin, ent->pos1 );
01952         VectorCopy( ent->s.origin, ent->pos2 );
01953 
01954         InitMover( ent );
01955 
01956         ent->use = func_static_use;
01957         ent->reached = 0;
01958 
01959         G_SetOrigin( ent, ent->s.origin );
01960         G_SetAngles( ent, ent->s.angles );
01961 
01962         if( ent->spawnflags & 2048 )
01963         {                                                                  // yes this is very very evil, but for now (pre-alpha) it's a solution
01964                 ent->r.svFlags |= SVF_BROADCAST; // I need to rotate something that is huge and it's touching too many area portals...
01965         }
01966 
01967         if ( ent->spawnflags & 4/*SWITCH_SHADER*/ )
01968         {
01969                 ent->s.eFlags |= EF_SHADER_ANIM;//use frame-controlled shader anim
01970                 ent->s.frame = 0;//first stage of anim
01971         }
01972 
01973         if ((ent->spawnflags & 1) || (ent->spawnflags & 2))
01974         { //so we know it's push/pullable on the client
01975                 ent->s.bolt1 = 1;
01976         }
01977 
01978 #ifdef _XBOX
01979         int     tempModelScale;
01980         G_SpawnInt("model2scale", "0", &tempModelScale);
01981         ent->s.iModelScale = tempModelScale;
01982 #else
01983         G_SpawnInt("model2scale", "0", &ent->s.iModelScale);
01984 #endif
01985         if (ent->s.iModelScale < 0)
01986         {
01987                 ent->s.iModelScale = 0;
01988         }
01989         else if (ent->s.iModelScale > 1023)
01990         {
01991                 ent->s.iModelScale = 1023;
01992         }
01993 
01994         G_SpawnInt( "hyperspace", "0", &test );
01995         if ( test )
01996         {
01997                 ent->r.svFlags |= SVF_BROADCAST; // I need to rotate something that is huge and it's touching too many area portals...
01998                 ent->s.eFlags2 |= EF2_HYPERSPACE;
01999         }
02000 
02001         trap_LinkEntity( ent );
02002 
02003         if (level.mBSPInstanceDepth)
02004         {       // this means that this guy will never be updated, moved, changed, etc.
02005                 ent->s.eFlags = EF_PERMANENT;
02006         }
02007 }

void SP_func_train gentity_t self  ) 
 

Definition at line 1887 of file g_mover.c.

References entityShared_t::absmin, entityState_s::angles, gentity_s::damage, FRAMETIME, G_FreeEntity(), G_Printf(), gentity_t, InitMover(), level, gentity_s::model, gentity_s::nextthink, gentity_s::r, gentity_s::reached, Reached_Train(), gentity_s::s, gentity_s::spawnflags, gentity_s::speed, gentity_s::target, gentity_s::think, Think_SetupTrainTargets(), level_locals_t::time, TRAIN_BLOCK_STOPS, trap_SetBrushModel(), VectorClear, and vtos().

01887                                      {
01888         VectorClear (self->s.angles);
01889 
01890         if (self->spawnflags & TRAIN_BLOCK_STOPS) {
01891                 self->damage = 0;
01892         } else {
01893                 if (!self->damage) {
01894                         self->damage = 2;
01895                 }
01896         }
01897 
01898         if ( !self->speed ) {
01899                 self->speed = 100;
01900         }
01901 
01902         if ( !self->target ) {
01903                 G_Printf ("func_train without a target at %s\n", vtos(self->r.absmin));
01904                 G_FreeEntity( self );
01905                 return;
01906         }
01907 
01908         trap_SetBrushModel( self, self->model );
01909         InitMover( self );
01910 
01911         self->reached = Reached_Train;
01912 
01913         // start trains on the second frame, to make sure their targets have had
01914         // a chance to spawn
01915         self->nextthink = level.time + FRAMETIME;
01916         self->think = Think_SetupTrainTargets;
01917 }

void SP_func_usable gentity_t self  ) 
 

Definition at line 3126 of file g_mover.c.

References gentity_s::clipmask, entityShared_t::contents, gentity_s::count, entityShared_t::currentOrigin, gentity_s::die, EF_NODRAW, EF_SHADER_ANIM, entityState_s::eFlags, entityState_s::frame, func_usable_die(), func_usable_pain(), func_usable_use(), G_ModelIndex(), G_SpawnInt(), gentity_s::genericValue5, gentity_t, gentity_s::health, InitMover(), gentity_s::model, gentity_s::model2, entityState_s::modelindex2, entityState_s::origin, gentity_s::pain, entityState_s::pos, gentity_s::pos1, qtrue, gentity_s::r, gentity_s::s, entityState_s::solid, gentity_s::spawnflags, strstr(), SVF_NOCLIENT, entityShared_t::svFlags, gentity_s::takedamage, entityState_s::time, trap_LinkEntity(), trap_SetBrushModel(), trajectory_t::trBase, gentity_s::use, and VectorCopy.

03127 {
03128         trap_SetBrushModel( self, self->model );
03129         InitMover( self );
03130         VectorCopy( self->s.origin, self->s.pos.trBase );
03131         VectorCopy( self->s.origin, self->r.currentOrigin );
03132         VectorCopy( self->s.origin, self->pos1 );
03133 
03134         G_SpawnInt("endframe", "0", &self->genericValue5);
03135 
03136         if ( self->model2 && self->model2[0] ) 
03137         {
03138                 if ( strstr( self->model2, ".glm" ))
03139                 { //for now, not supported in MP.
03140                         self->s.modelindex2 = 0;
03141                 }
03142                 else
03143                 {
03144                         self->s.modelindex2 = G_ModelIndex( self->model2 );
03145                 }
03146         }
03147 
03148         self->count = 1;
03149         if (self->spawnflags & 1)
03150         {
03151                 self->s.solid = 0;
03152                 self->r.contents = 0;
03153                 self->clipmask = 0;
03154                 self->r.svFlags |= SVF_NOCLIENT;
03155                 self->s.eFlags |= EF_NODRAW;
03156                 self->count = 0;
03157         }
03158 
03159         //FIXME: Animation?
03160         /*
03161         if (self->spawnflags & 2)
03162         {
03163                 self->s.eFlags |= EF_ANIM_ALLFAST;
03164         }
03165 
03166         if (self->spawnflags & 4)
03167         {//FIXME: need to be able to do change to something when it's done?  Or not be usable until it's done?
03168                 self->s.eFlags |= EF_ANIM_ONCE;
03169         }
03170         */
03171 
03172         self->use = func_usable_use;
03173 
03174         if ( self->health )
03175         {
03176                 self->takedamage = qtrue;
03177                 self->die = func_usable_die;
03178                 self->pain = func_usable_pain;
03179         }
03180 
03181         if ( self->genericValue5 > 0 )
03182         {
03183                 self->s.frame = 0;
03184                 self->s.eFlags |= EF_SHADER_ANIM;
03185                 self->s.time = self->genericValue5 + 1;
03186         }
03187 
03188         trap_LinkEntity (self);
03189 }

void SP_func_wall gentity_t ent  ) 
 

Definition at line 3242 of file g_mover.c.

References entityShared_t::contents, entityShared_t::currentOrigin, EF_NODRAW, entityState_s::eFlags, FUNC_WALL_OFF, gentity_t, InitMover(), gentity_s::model, entityState_s::origin, entityState_s::pos, gentity_s::pos1, gentity_s::pos2, gentity_s::r, gentity_s::s, gentity_s::spawnflags, SVF_NOCLIENT, entityShared_t::svFlags, trap_LinkEntity(), trap_SetBrushModel(), trajectory_t::trBase, gentity_s::use, use_wall(), and VectorCopy.

03243 {
03244         trap_SetBrushModel( ent, ent->model );
03245 
03246         VectorCopy( ent->s.origin, ent->pos1 );
03247         VectorCopy( ent->s.origin, ent->pos2 );
03248 
03249         InitMover( ent );
03250         VectorCopy( ent->s.origin, ent->s.pos.trBase );
03251         VectorCopy( ent->s.origin, ent->r.currentOrigin );
03252 
03253         // it must be START_OFF
03254         if (ent->spawnflags & FUNC_WALL_OFF)
03255         {
03256                 ent->r.contents = 0;
03257                 ent->r.svFlags |= SVF_NOCLIENT;
03258                 ent->s.eFlags |= EF_NODRAW;
03259         }
03260 
03261         ent->use = use_wall;
03262 
03263         trap_LinkEntity (ent);
03264 
03265 }

void SP_path_corner gentity_t self  ) 
 

Definition at line 1863 of file g_mover.c.

References G_FreeEntity(), G_Printf(), gentity_t, entityState_s::origin, gentity_s::s, gentity_s::targetname, and vtos().

01863                                        {
01864         if ( !self->targetname ) {
01865                 G_Printf ("path_corner with no targetname at %s\n", vtos(self->s.origin));
01866                 G_FreeEntity( self );
01867                 return;
01868         }
01869         // path corners don't need to be linked in
01870 }

void SpawnPlatTrigger gentity_t ent  ) 
 

Definition at line 1517 of file g_mover.c.

References entityShared_t::contents, CONTENTS_TRIGGER, G_Spawn(), gentity_t, entityShared_t::maxs, entityShared_t::mins, gentity_s::parent, gentity_s::pos1, gentity_s::r, gentity_s::touch, Touch_PlatCenterTrigger(), trap_LinkEntity(), vec3_t, and VectorCopy.

Referenced by SP_func_plat().

01517                                         {
01518         gentity_t       *trigger;
01519         vec3_t  tmin, tmax;
01520 
01521         // the middle trigger will be a thin trigger just
01522         // above the starting position
01523         trigger = G_Spawn();
01524         trigger->touch = Touch_PlatCenterTrigger;
01525         trigger->r.contents = CONTENTS_TRIGGER;
01526         trigger->parent = ent;
01527         
01528         tmin[0] = ent->pos1[0] + ent->r.mins[0] + 33;
01529         tmin[1] = ent->pos1[1] + ent->r.mins[1] + 33;
01530         tmin[2] = ent->pos1[2] + ent->r.mins[2];
01531 
01532         tmax[0] = ent->pos1[0] + ent->r.maxs[0] - 33;
01533         tmax[1] = ent->pos1[1] + ent->r.maxs[1] - 33;
01534         tmax[2] = ent->pos1[2] + ent->r.maxs[2] + 8;
01535 
01536         if ( tmax[0] <= tmin[0] ) {
01537                 tmin[0] = ent->pos1[0] + (ent->r.mins[0] + ent->r.maxs[0]) *0.5;
01538                 tmax[0] = tmin[0] + 1;
01539         }
01540         if ( tmax[1] <= tmin[1] ) {
01541                 tmin[1] = ent->pos1[1] + (ent->r.mins[1] + ent->r.maxs[1]) *0.5;
01542                 tmax[1] = tmin[1] + 1;
01543         }
01544         
01545         VectorCopy (tmin, trigger->r.mins);
01546         VectorCopy (tmax, trigger->r.maxs);
01547 
01548         trap_LinkEntity (trigger);
01549 }

void Think_BeginMoving gentity_t ent  ) 
 

Definition at line 1717 of file g_mover.c.

References BMS_START, G_PlayDoorLoopSound(), G_PlayDoorSound(), gentity_t, level, entityState_s::pos, gentity_s::s, level_locals_t::time, TR_LINEAR_STOP, trajectory_t::trTime, and trajectory_t::trType.

Referenced by Reached_Train().

01717                                          {
01718         G_PlayDoorSound( ent, BMS_START );
01719         G_PlayDoorLoopSound( ent );
01720         ent->s.pos.trTime = level.time;
01721         ent->s.pos.trType = TR_LINEAR_STOP;
01722 }

void Think_MatchTeam gentity_t ent  ) 
 

Definition at line 1207 of file g_mover.c.

References gentity_t, level, MatchTeam(), gentity_s::moverState, and level_locals_t::time.

Referenced by SP_func_door().

01208 {
01209         MatchTeam( ent, ent->moverState, level.time );
01210 }

void Think_SetupTrainTargets gentity_t ent  ) 
 

Definition at line 1792 of file g_mover.c.

References entityShared_t::absmin, gentity_s::classname, Com_Printf(), FOFS, G_Find(), G_SetOrigin(), gentity_t, gentity_s::nextTrain, NULL, entityState_s::origin, gentity_s::r, Reached_Train(), gentity_s::s, gentity_s::spawnflags, strcmp(), gentity_s::target, gentity_s::targetname, and vtos().

Referenced by SP_func_train().

01792                                                {
01793         gentity_t               *path, *next, *start;
01794 
01795         ent->nextTrain = G_Find( NULL, FOFS(targetname), ent->target );
01796         if ( !ent->nextTrain ) {
01797                 Com_Printf( "func_train at %s with an unfound target\n",
01798                         vtos(ent->r.absmin) );
01799                 //Free me?`
01800                 return;
01801         }
01802 
01803         //FIXME: this can go into an infinite loop if last path_corner doesn't link to first
01804         //path_corner, like so:
01805         // t1---->t2---->t3
01806         //         ^      |
01807         //          \_____|
01808         start = NULL;
01809         for ( path = ent->nextTrain ; path != start ; path = next ) {
01810                 if ( !start ) {
01811                         start = path;
01812                 }
01813 
01814                 if ( !path->target ) {
01815 //                      gi.Printf( "Train corner at %s without a target\n",
01816 //                              vtos(path->s.origin) );
01817                         //end of path
01818                         break;
01819                 }
01820 
01821                 // find a path_corner among the targets
01822                 // there may also be other targets that get fired when the corner
01823                 // is reached
01824                 next = NULL;
01825                 do {
01826                         next = G_Find( next, FOFS(targetname), path->target );
01827                         if ( !next ) {
01828 //                              gi.Printf( "Train corner at %s without a target path_corner\n",
01829 //                                      vtos(path->s.origin) );
01830                                 //end of path
01831                                 break;
01832                         }
01833                 } while ( strcmp( next->classname, "path_corner" ) );
01834 
01835                 if ( next )
01836                 {
01837                         path->nextTrain = next;
01838                 }
01839                 else
01840                 {
01841                         break;
01842                 }
01843         }
01844 
01845         if ( !ent->targetname || (ent->spawnflags&1) /*start on*/)
01846         {
01847                 // start the train moving from the first corner
01848                 Reached_Train( ent );
01849         }
01850         else
01851         {
01852                 G_SetOrigin( ent, ent->s.origin );
01853         }
01854 }

void Think_SpawnNewDoorTrigger gentity_t ent  ) 
 

Definition at line 1158 of file g_mover.c.

References entityShared_t::absmax, entityShared_t::absmin, AddPointToBounds(), gentity_s::classname, entityShared_t::contents, CONTENTS_TRIGGER, gentity_s::count, G_Spawn(), gentity_t, level, MatchTeam(), entityShared_t::maxs, entityShared_t::mins, gentity_s::moverState, gentity_s::parent, qtrue, gentity_s::r, gentity_s::takedamage, gentity_s::teamchain, level_locals_t::time, gentity_s::touch, Touch_DoorTrigger(), trap_LinkEntity(), vec3_t, and VectorCopy.

Referenced by SP_func_door().

01159 {
01160         gentity_t               *other;
01161         vec3_t          mins, maxs;
01162         int                     i, best;
01163 
01164         // set all of the slaves as shootable
01165         if ( ent->takedamage ) 
01166         {
01167                 for ( other = ent ; other ; other = other->teamchain ) 
01168                 {
01169                         other->takedamage = qtrue;
01170                 }
01171         }
01172 
01173         // find the bounds of everything on the team
01174         VectorCopy (ent->r.absmin, mins);
01175         VectorCopy (ent->r.absmax, maxs);
01176 
01177         for (other = ent->teamchain ; other ; other=other->teamchain) {
01178                 AddPointToBounds (other->r.absmin, mins, maxs);
01179                 AddPointToBounds (other->r.absmax, mins, maxs);
01180         }
01181 
01182         // find the thinnest axis, which will be the one we expand
01183         best = 0;
01184         for ( i = 1 ; i < 3 ; i++ ) {
01185                 if ( maxs[i] - mins[i] < maxs[best] - mins[best] ) {
01186                         best = i;
01187                 }
01188         }
01189         maxs[best] += 120;
01190         mins[best] -= 120;
01191 
01192         // create a trigger with this size
01193         other = G_Spawn ();
01194         VectorCopy (mins, other->r.mins);
01195         VectorCopy (maxs, other->r.maxs);
01196         other->parent = ent;
01197         other->r.contents = CONTENTS_TRIGGER;
01198         other->touch = Touch_DoorTrigger;
01199         trap_LinkEntity (other);
01200         other->classname = "trigger_door";
01201         // remember the thinnest axis
01202         other->count = best;
01203 
01204         MatchTeam( ent, ent->moverState, level.time );
01205 }

void Touch_Button gentity_t ent,
gentity_t other,
trace_t trace
 

Definition at line 1623 of file g_mover.c.

References gentity_s::client, gentity_t, MOVER_POS1, gentity_s::moverState, and Use_BinaryMover().

Referenced by ForceThrow(), SP_func_button(), and TryUse().

01623                                                                      {
01624         if ( !other->client ) {
01625                 return;
01626         }
01627 
01628         if ( ent->moverState == MOVER_POS1 ) {
01629                 Use_BinaryMover( ent, other, other );
01630         }
01631 }

void Touch_DoorTrigger gentity_t ent,
gentity_t other,
trace_t trace
 

Definition at line 1068 of file g_mover.c.

References gentity_s::alliedTeam, CLASS_VEHICLE, gentity_s::client, ET_NPC, entityState_s::eType, FL_INACTIVE, FL_TEAMSLAVE, gentity_s::flags, gentity_s::genericValue14, gentity_t, playerState_s::m_iVehicleNum, MAX_CLIENTS, MOVER_1TO2, MOVER_LOCKED, MOVER_POS2, gentity_s::moverState, entityState_s::NPC_class, NULL, entityState_s::number, gentity_s::parent, gclient_s::ps, gentity_s::s, gclient_s::sess, clientSession_t::sessionTeam, gentity_s::spawnflags, TEAM_SPECTATOR, gentity_s::teammaster, and Use_BinaryMover().

Referenced by G_TouchTriggers(), and Think_SpawnNewDoorTrigger().

01069 {
01070         gentity_t *relockEnt = NULL;
01071 
01072         if ( other->client && other->client->sess.sessionTeam == TEAM_SPECTATOR ) 
01073         {
01074                 // if the door is not open and not opening
01075                 if ( ent->parent->moverState != MOVER_1TO2 &&
01076                         ent->parent->moverState != MOVER_POS2 ) 
01077                 {
01078                         Touch_DoorTriggerSpectator( ent, other, trace );
01079                 }
01080                 return;
01081         }
01082 
01083         if (!ent->genericValue14 &&
01084                 (!ent->parent || !ent->parent->genericValue14))
01085         {
01086                 if (other->client && other->s.number >= MAX_CLIENTS &&
01087                         other->s.eType == ET_NPC && other->s.NPC_class == CLASS_VEHICLE)
01088                 { //doors don't open for vehicles
01089                         return;
01090                 }
01091 
01092                 if (other->client && other->s.number < MAX_CLIENTS &&
01093                         other->client->ps.m_iVehicleNum)
01094                 { //can't open a door while on a vehicle
01095                         return;
01096                 }
01097         }
01098 
01099         if ( ent->flags & FL_INACTIVE )
01100         {
01101                 return;
01102         }
01103 
01104         if ( ent->parent->spawnflags & MOVER_LOCKED )
01105         {//don't even try to use the door if it's locked 
01106                 if ( !ent->parent->alliedTeam //we don't have a "teamallow" team
01107                         || !other->client //we do have a "teamallow" team, but this isn't a client
01108                         || other->client->sess.sessionTeam != ent->parent->alliedTeam )//it is a client, but it's not on the right team
01109                 {
01110                         return;
01111                 }
01112                 else
01113                 {//temporarily unlock us while we call Use_BinaryMover (so it doesn't unlock all the doors in this team)
01114                         if ( ent->parent->flags & FL_TEAMSLAVE ) 
01115                         {
01116                                 relockEnt = ent->parent->teammaster;
01117                         }
01118                         else
01119                         {
01120                                 relockEnt = ent->parent;
01121                         }
01122                         if ( relockEnt != NULL )
01123                         {
01124                                 relockEnt->spawnflags &= ~MOVER_LOCKED;
01125                         }
01126                 }
01127         }
01128 
01129         if ( ent->parent->moverState != MOVER_1TO2 ) 
01130         {//Door is not already opening
01131                 //if ( ent->parent->moverState == MOVER_POS1 || ent->parent->moverState == MOVER_2TO1 )
01132                 //{//only check these if closed or closing
01133 
01134                 //If door is closed, opening or open, check this
01135                 Use_BinaryMover( ent->parent, ent, other );
01136         }
01137         if ( relockEnt != NULL )
01138         {//re-lock us
01139                 relockEnt->spawnflags |= MOVER_LOCKED;
01140         }
01141 
01142         /*
01143         //Old style
01144         if ( ent->parent->moverState != MOVER_1TO2 ) {
01145                 Use_BinaryMover( ent->parent, ent, other );
01146         }
01147         */
01148 }

void Touch_Plat gentity_t ent,
gentity_t other,
trace_t trace
 

Definition at line 1479 of file g_mover.c.

References gentity_s::client, gentity_t, level, MOVER_POS2, gentity_s::moverState, gentity_s::nextthink, gclient_s::ps, STAT_HEALTH, playerState_s::stats, and level_locals_t::time.

Referenced by SP_func_plat().

01479                                                                     {
01480         if ( !other->client || other->client->ps.stats[STAT_HEALTH] <= 0 ) {
01481                 return;
01482         }
01483 
01484         // delay return-to-pos1 by one second
01485         if ( ent->moverState == MOVER_POS2 ) {
01486                 ent->nextthink = level.time + 1000;
01487         }
01488 }

void Touch_PlatCenterTrigger gentity_t ent,
gentity_t other,
trace_t trace
 

Definition at line 1497 of file g_mover.c.

References gentity_s::client, gentity_t, MOVER_POS1, gentity_s::moverState, gentity_s::parent, and Use_BinaryMover().

Referenced by SpawnPlatTrigger().

01497                                                                                 {
01498         if ( !other->client ) {
01499                 return;
01500         }
01501 
01502         if ( ent->parent->moverState == MOVER_POS1 ) {
01503                 Use_BinaryMover( ent->parent, ent, other );
01504         }
01505 }

void UnLockDoors gentity_t *const  ent  ) 
 

Definition at line 820 of file g_mover.c.

References entityState_s::frame, gentity_t, MOVER_LOCKED, MOVER_TOGGLE, NULL, gentity_s::s, gentity_s::spawnflags, gentity_s::targetname, and gentity_s::teamchain.

Referenced by Q3_Set(), and Use_BinaryMover().

00821 {
00822         //noise?
00823         //go through and unlock the door and all the slaves
00824         gentity_t       *slave = ent;
00825         do 
00826         {       // want to allow locked toggle doors, so keep the targetname
00827                 if( !(slave->spawnflags & MOVER_TOGGLE) )
00828                 {
00829                         slave->targetname = NULL;//not usable ever again
00830                 }
00831                 slave->spawnflags &= ~MOVER_LOCKED;
00832                 slave->s.frame = 1;//second stage of anim
00833                 slave = slave->teamchain;
00834         } while  ( slave );
00835 }

void Use_BinaryMover gentity_t ent,
gentity_t other,
gentity_t activator
 

Definition at line 853 of file g_mover.c.

References gentity_s::activator, BSET_USE, gentity_s::delay, gentity_s::enemy, FL_INACTIVE, FL_TEAMSLAVE, gentity_s::flags, G_ActivateBehavior(), gentity_t, level, MOVER_LOCKED, gentity_s::nextthink, gentity_s::spawnflags, gentity_s::teammaster, gentity_s::think, level_locals_t::time, UnLockDoors(), gentity_s::use, and Use_BinaryMover_Go().

Referenced by Blocked_Door(), InitMover(), Touch_Button(), Touch_DoorTrigger(), and Touch_PlatCenterTrigger().

00854 {
00855         if ( !ent->use )
00856         {//I cannot be used anymore, must be a door with a wait of -1 that's opened.
00857                 return;
00858         }
00859 
00860         // only the master should be used
00861         if ( ent->flags & FL_TEAMSLAVE ) 
00862         {
00863                 Use_BinaryMover( ent->teammaster, other, activator );
00864                 return;
00865         }
00866 
00867         if ( ent->flags & FL_INACTIVE )
00868         {
00869                 return;
00870         }
00871 
00872         if ( ent->spawnflags & MOVER_LOCKED )
00873         {//a locked door, unlock it
00874                 UnLockDoors(ent);
00875                 return;
00876         }
00877 
00878         G_ActivateBehavior(ent,BSET_USE);
00879 
00880         ent->enemy = other;
00881         ent->activator = activator;
00882         if(ent->delay)
00883         {
00884                 ent->think = Use_BinaryMover_Go;
00885                 ent->nextthink = level.time + ent->delay;
00886         }
00887         else
00888         {
00889                 Use_BinaryMover_Go(ent);
00890         }
00891 }

void Use_BinaryMover_Go gentity_t ent  ) 
 

Definition at line 700 of file g_mover.c.

References acos(), gentity_s::activator, BMS_START, CalcTeamDoorCenter(), entityShared_t::currentOrigin, floor(), FRAMETIME, G_PlayDoorLoopSound(), G_PlayDoorSound(), G_UseTargets(), G_UseTargets2(), gentity_t, level, MatchTeam(), MOVER_1TO2, MOVER_2TO1, MOVER_POS1, MOVER_POS2, gentity_s::moverState, gentity_s::nextthink, entityState_s::pos, gentity_s::pos1, gentity_s::pos2, qtrue, gentity_s::r, RAD2DEG, ReturnToPos1(), gentity_s::s, gentity_s::spawnflags, gentity_s::target2, gentity_s::teammaster, gentity_s::think, entityState_s::time, level_locals_t::time, TR_NONLINEAR_STOP, trap_AdjustAreaPortalState(), trajectory_t::trDelta, trajectory_t::trDuration, trajectory_t::trTime, trajectory_t::trType, vec3_t, VectorScale, VectorSubtract, and gentity_s::wait.

Referenced by Use_BinaryMover().

00701 {
00702         int             total;
00703         int             partial;
00704 //      gentity_t       *other = ent->enemy;
00705         gentity_t       *activator = ent->activator; 
00706 
00707         ent->activator = activator;
00708 
00709         if ( ent->moverState == MOVER_POS1 ) 
00710         {
00711                 vec3_t  doorcenter;
00712 
00713                 // start moving 50 msec later, becase if this was player
00714                 // triggered, level.time hasn't been advanced yet
00715                 MatchTeam( ent, MOVER_1TO2, level.time + 50 );
00716 
00717                 CalcTeamDoorCenter( ent, doorcenter );
00718 
00719                 // starting sound
00720                 G_PlayDoorLoopSound( ent );
00721                 G_PlayDoorSound( ent, BMS_START );
00722                 ent->s.time = level.time;
00723 
00724                 // open areaportal
00725                 if ( ent->teammaster == ent || !ent->teammaster ) {
00726                         trap_AdjustAreaPortalState( ent, qtrue );
00727                 }
00728                 G_UseTargets( ent, ent->activator );
00729                 return;
00730         }
00731 
00732         // if all the way up, just delay before coming down
00733         if ( ent->moverState == MOVER_POS2 ) {
00734                 //have to do this because the delay sets our think to Use_BinaryMover_Go
00735                 ent->think = ReturnToPos1;
00736                 if ( ent->spawnflags & 8 )
00737                 {//TOGGLE doors don't use wait!
00738                         ent->nextthink = level.time + FRAMETIME;
00739                 }
00740                 else
00741                 {
00742                         ent->nextthink = level.time + ent->wait;
00743                 }
00744                 G_UseTargets2( ent, ent->activator, ent->target2 );
00745                 return;
00746         }
00747 
00748         // only partway down before reversing
00749         if ( ent->moverState == MOVER_2TO1 ) 
00750         {
00751                 if ( ent->s.pos.trType == TR_NONLINEAR_STOP )
00752                 {
00753                         vec3_t curDelta;
00754                         float fPartial;
00755                         total = ent->s.pos.trDuration-50;
00756                         VectorSubtract( ent->r.currentOrigin, ent->pos1, curDelta );
00757                         fPartial = VectorLength( curDelta )/VectorLength( ent->s.pos.trDelta );
00758                         VectorScale( ent->s.pos.trDelta, fPartial, curDelta );
00759                         fPartial /= ent->s.pos.trDuration;
00760                         fPartial /= 0.001f;
00761                         fPartial = acos( fPartial );
00762                         fPartial = RAD2DEG( fPartial );
00763                         fPartial = (90.0f - fPartial)/90.0f*ent->s.pos.trDuration;
00764                         partial = total - floor( fPartial );
00765                 }
00766                 else
00767                 {
00768                         total = ent->s.pos.trDuration;
00769                         partial = level.time - ent->s.pos.trTime;
00770                 }
00771 
00772                 if ( partial > total ) {
00773                         partial = total;
00774                 }
00775                 ent->s.pos.trTime = level.time - ( total - partial );//ent->s.time;
00776 
00777                 MatchTeam( ent, MOVER_1TO2, ent->s.pos.trTime );
00778 
00779                 G_PlayDoorSound( ent, BMS_START );
00780 
00781                 return;
00782         }
00783 
00784         // only partway up before reversing
00785         if ( ent->moverState == MOVER_1TO2 ) 
00786         {
00787                 if ( ent->s.pos.trType == TR_NONLINEAR_STOP )
00788                 {
00789                         vec3_t curDelta;
00790                         float fPartial;
00791                         total = ent->s.pos.trDuration-50;
00792                         VectorSubtract( ent->r.currentOrigin, ent->pos2, curDelta );
00793                         fPartial = VectorLength( curDelta )/VectorLength( ent->s.pos.trDelta );
00794                         VectorScale( ent->s.pos.trDelta, fPartial, curDelta );
00795                         fPartial /= ent->s.pos.trDuration;
00796                         fPartial /= 0.001f;
00797                         fPartial = acos( fPartial );
00798                         fPartial = RAD2DEG( fPartial );
00799                         fPartial = (90.0f - fPartial)/90.0f*ent->s.pos.trDuration;
00800                         partial = total - floor( fPartial );
00801                 }
00802                 else
00803                 {
00804                         total = ent->s.pos.trDuration;
00805                         partial = level.time - ent->s.pos.trTime;
00806                 }
00807                 if ( partial > total ) {
00808                         partial = total;
00809                 }
00810 
00811                 ent->s.pos.trTime = level.time - ( total - partial );//ent->s.time;
00812                 MatchTeam( ent, MOVER_2TO1, ent->s.pos.trTime );
00813 
00814                 G_PlayDoorSound( ent, BMS_START );
00815 
00816                 return;
00817         }
00818 }

void use_wall gentity_t ent,
gentity_t other,
gentity_t activator
 

Definition at line 3201 of file g_mover.c.

References BSET_USE, entityShared_t::contents, CONTENTS_SOLID, EF_NODRAW, entityState_s::eFlags, G_ActivateBehavior(), gentity_t, qfalse, qtrue, gentity_s::r, gentity_s::s, gentity_s::spawnflags, SVF_NOCLIENT, entityShared_t::svFlags, and trap_AdjustAreaPortalState().

Referenced by SP_func_wall().

03202 {
03203         G_ActivateBehavior(ent,BSET_USE);
03204 
03205         // Not there so make it there
03206         if (!(ent->r.contents & CONTENTS_SOLID))
03207         {
03208                 ent->r.svFlags &= ~SVF_NOCLIENT;
03209                 ent->s.eFlags &= ~EF_NODRAW;
03210                 ent->r.contents = CONTENTS_SOLID;
03211                 if ( !(ent->spawnflags&1) )
03212                 {//START_OFF doesn't effect area portals
03213                         trap_AdjustAreaPortalState( ent, qfalse );
03214                 }
03215         }
03216         // Make it go away
03217         else
03218         {
03219                 ent->r.contents = 0;
03220                 ent->r.svFlags |= SVF_NOCLIENT;
03221                 ent->s.eFlags |= EF_NODRAW;
03222                 if ( !(ent->spawnflags&1) )
03223                 {//START_OFF doesn't effect area portals
03224                         trap_AdjustAreaPortalState( ent, qtrue );
03225                 }
03226         }
03227 }


Variable Documentation

int BMS_END = 2
 

Definition at line 37 of file g_mover.c.

int BMS_MID = 1
 

Definition at line 36 of file g_mover.c.

int BMS_START = 0
 

Definition at line 35 of file g_mover.c.

pushed_t pushed[MAX_GENTITIES]
 

Definition at line 24 of file g_mover.c.

Referenced by G_MoverPush(), G_MoverTeam(), and G_TryPushingEntity().

pushed_t * pushed_p
 

Definition at line 24 of file g_mover.c.

Referenced by G_MoverPush(), G_MoverTeam(), and G_TryPushingEntity().