diff options
Diffstat (limited to 'src/game/g_misc.c')
-rw-r--r-- | src/game/g_misc.c | 436 |
1 files changed, 436 insertions, 0 deletions
diff --git a/src/game/g_misc.c b/src/game/g_misc.c new file mode 100644 index 0000000..b0d6077 --- /dev/null +++ b/src/game/g_misc.c @@ -0,0 +1,436 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. +Copyright (C) 2000-2006 Tim Angus + +This file is part of Tremulous. + +Tremulous is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Tremulous is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Tremulous; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "g_local.h" + + +/*QUAKED func_group (0 0 0) ? +Used to group brushes together just for editor convenience. They are turned into normal brushes by the utilities. +*/ + + +/*QUAKED info_null (0 0.5 0) (-4 -4 -4) (4 4 4) +Used as a positional target for calculations in the utilities (spotlights, etc), but removed during gameplay. +*/ +void SP_info_null( gentity_t *self ) +{ + G_FreeEntity( self ); +} + + +/*QUAKED info_notnull (0 0.5 0) (-4 -4 -4) (4 4 4) +Used as a positional target for in-game calculation, like jumppad targets. +target_position does the same thing +*/ +void SP_info_notnull( gentity_t *self ) +{ + G_SetOrigin( self, self->s.origin ); +} + + +/*QUAKED light (0 1 0) (-8 -8 -8) (8 8 8) linear +Non-displayed light. +"light" overrides the default 300 intensity. +Linear checbox gives linear falloff instead of inverse square +Lights pointed at a target will be spotlights. +"radius" overrides the default 64 unit radius of a spotlight at the target point. +*/ +void SP_light( gentity_t *self ) +{ + G_FreeEntity( self ); +} + + + +/* +================================================================================= + +TELEPORTERS + +================================================================================= +*/ + +void TeleportPlayer( gentity_t *player, vec3_t origin, vec3_t angles ) +{ + // unlink to make sure it can't possibly interfere with G_KillBox + trap_UnlinkEntity( player ); + + VectorCopy( origin, player->client->ps.origin ); + player->client->ps.origin[ 2 ] += 1; + + // spit the player out + AngleVectors( angles, player->client->ps.velocity, NULL, NULL ); + VectorScale( player->client->ps.velocity, 400, player->client->ps.velocity ); + player->client->ps.pm_time = 160; // hold time + player->client->ps.pm_flags |= PMF_TIME_KNOCKBACK; + + // toggle the teleport bit so the client knows to not lerp + player->client->ps.eFlags ^= EF_TELEPORT_BIT; + G_UnlaggedClear( player ); + + // set angles + G_SetClientViewAngle( player, angles ); + + // kill anything at the destination + if( player->client->sess.sessionTeam != TEAM_SPECTATOR ) + G_KillBox( player ); + + // save results of pmove + BG_PlayerStateToEntityState( &player->client->ps, &player->s, qtrue ); + + // use the precise origin for linking + VectorCopy( player->client->ps.origin, player->r.currentOrigin ); + + if( player->client->sess.sessionTeam != TEAM_SPECTATOR ) + trap_LinkEntity (player); +} + + +/*QUAKED misc_teleporter_dest (1 0 0) (-32 -32 -24) (32 32 -16) +Point teleporters at these. +Now that we don't have teleport destination pads, this is just +an info_notnull +*/ +void SP_misc_teleporter_dest( gentity_t *ent ) +{ +} + + +//=========================================================== + +/*QUAKED misc_model (1 0 0) (-16 -16 -16) (16 16 16) +"model" arbitrary .md3 file to display +*/ +void SP_misc_model( gentity_t *ent ) +{ +#if 0 + ent->s.modelindex = G_ModelIndex( ent->model ); + VectorSet (ent->mins, -16, -16, -16); + VectorSet (ent->maxs, 16, 16, 16); + trap_LinkEntity (ent); + + G_SetOrigin( ent, ent->s.origin ); + VectorCopy( ent->s.angles, ent->s.apos.trBase ); +#else + G_FreeEntity( ent ); +#endif +} + +//=========================================================== + +void locateCamera( gentity_t *ent ) +{ + vec3_t dir; + gentity_t *target; + gentity_t *owner; + + owner = G_PickTarget( ent->target ); + if( !owner ) + { + G_Printf( "Couldn't find target for misc_portal_surface\n" ); + G_FreeEntity( ent ); + return; + } + ent->r.ownerNum = owner->s.number; + + // frame holds the rotate speed + if( owner->spawnflags & 1 ) + ent->s.frame = 25; + else if( owner->spawnflags & 2 ) + ent->s.frame = 75; + + // swing camera ? + if( owner->spawnflags & 4 ) + { + // set to 0 for no rotation at all + ent->s.powerups = 0; + } + else + ent->s.powerups = 1; + + // clientNum holds the rotate offset + ent->s.clientNum = owner->s.clientNum; + + VectorCopy( owner->s.origin, ent->s.origin2 ); + + // see if the portal_camera has a target + target = G_PickTarget( owner->target ); + if( target ) + { + VectorSubtract( target->s.origin, owner->s.origin, dir ); + VectorNormalize( dir ); + } + else + G_SetMovedir( owner->s.angles, dir ); + + ent->s.eventParm = DirToByte( dir ); +} + +/*QUAKED misc_portal_surface (0 0 1) (-8 -8 -8) (8 8 8) +The portal surface nearest this entity will show a view from the targeted misc_portal_camera, or a mirror view if untargeted. +This must be within 64 world units of the surface! +*/ +void SP_misc_portal_surface( gentity_t *ent ) +{ + VectorClear( ent->r.mins ); + VectorClear( ent->r.maxs ); + trap_LinkEntity( ent ); + + ent->r.svFlags = SVF_PORTAL; + ent->s.eType = ET_PORTAL; + + if( !ent->target ) + { + VectorCopy( ent->s.origin, ent->s.origin2 ); + } + else + { + ent->think = locateCamera; + ent->nextthink = level.time + 100; + } +} + +/*QUAKED misc_portal_camera (0 0 1) (-8 -8 -8) (8 8 8) slowrotate fastrotate noswing + +The target for a misc_portal_director. You can set either angles or target another entity to determine the direction of view. +"roll" an angle modifier to orient the camera around the target vector; +*/ +void SP_misc_portal_camera( gentity_t *ent ) +{ + float roll; + + VectorClear( ent->r.mins ); + VectorClear( ent->r.maxs ); + trap_LinkEntity( ent ); + + G_SpawnFloat( "roll", "0", &roll ); + + ent->s.clientNum = roll / 360.0f * 256; +} + +/* +====================================================================== + + NEAT EFFECTS AND STUFF FOR TREMULOUS + +====================================================================== +*/ + +void SP_toggle_particle_system( gentity_t *self ) +{ + //toggle EF_NODRAW + self->s.eFlags ^= EF_NODRAW; + + self->nextthink = 0; +} + +/* +=============== +SP_use_particle_system + +Use function for particle_system +=============== +*/ +void SP_use_particle_system( gentity_t *self, gentity_t *other, gentity_t *activator ) +{ + SP_toggle_particle_system( self ); + + if( self->wait > 0.0f ) + { + self->think = SP_toggle_particle_system; + self->nextthink = level.time + (int)( self->wait * 1000 ); + } +} + +/* +=============== +SP_spawn_particle_system + +Spawn function for particle system +=============== +*/ +void SP_misc_particle_system( gentity_t *self ) +{ + char *s; + + G_SetOrigin( self, self->s.origin ); + + G_SpawnString( "psName", "", &s ); + G_SpawnFloat( "wait", "0", &self->wait ); + + //add the particle system to the client precache list + self->s.modelindex = G_ParticleSystemIndex( s ); + + if( self->spawnflags & 1 ) + self->s.eFlags |= EF_NODRAW; + + self->use = SP_use_particle_system; + self->s.eType = ET_PARTICLE_SYSTEM; + trap_LinkEntity( self ); +} + +/* +=============== +SP_use_anim_model + +Use function for anim model +=============== +*/ +void SP_use_anim_model( gentity_t *self, gentity_t *other, gentity_t *activator ) +{ + if( self->spawnflags & 1 ) + { + //if spawnflag 1 is set + //toggle EF_NODRAW + if( self->s.eFlags & EF_NODRAW ) + self->s.eFlags &= ~EF_NODRAW; + else + self->s.eFlags |= EF_NODRAW; + } + else + { + //if the animation loops then toggle the animation + //toggle EF_MOVER_STOP + if( self->s.eFlags & EF_MOVER_STOP ) + self->s.eFlags &= ~EF_MOVER_STOP; + else + self->s.eFlags |= EF_MOVER_STOP; + } +} + +/* +=============== +SP_misc_anim_model + +Spawn function for anim model +=============== +*/ +void SP_misc_anim_model( gentity_t *self ) +{ + self->s.powerups = (int)self->animation[ 0 ]; + self->s.weapon = (int)self->animation[ 1 ]; + self->s.torsoAnim = (int)self->animation[ 2 ]; + self->s.legsAnim = (int)self->animation[ 3 ]; + + self->s.angles2[ 0 ] = self->pos2[ 0 ]; + + //add the model to the client precache list + self->s.modelindex = G_ModelIndex( self->model ); + + self->use = SP_use_anim_model; + + self->s.eType = ET_ANIMMAPOBJ; + + // spawn with animation stopped + if( self->spawnflags & 2 ) + self->s.eFlags |= EF_MOVER_STOP; + + trap_LinkEntity( self ); +} + +/* +=============== +SP_use_light_flare + +Use function for light flare +=============== +*/ +void SP_use_light_flare( gentity_t *self, gentity_t *other, gentity_t *activator ) +{ + self->s.eFlags ^= EF_NODRAW; +} + +/* +=============== +findEmptySpot + +Finds an empty spot radius units from origin +============== +*/ +static void findEmptySpot( vec3_t origin, float radius, vec3_t spot ) +{ + int i, j, k; + vec3_t delta, test, total; + trace_t tr; + + VectorClear( total ); + + //54(!) traces to test for empty spots + for( i = -1; i <= 1; i++ ) + { + for( j = -1; j <= 1; j++ ) + { + for( k = -1; k <= 1; k++ ) + { + VectorSet( delta, ( i * radius ), + ( j * radius ), + ( k * radius ) ); + + VectorAdd( origin, delta, test ); + + trap_Trace( &tr, test, NULL, NULL, test, -1, MASK_SOLID ); + + if( !tr.allsolid ) + { + trap_Trace( &tr, test, NULL, NULL, origin, -1, MASK_SOLID ); + VectorScale( delta, tr.fraction, delta ); + VectorAdd( total, delta, total ); + } + } + } + } + + VectorNormalize( total ); + VectorScale( total, radius, total ); + VectorAdd( origin, total, spot ); +} + +/* +=============== +SP_misc_light_flare + +Spawn function for light flare +=============== +*/ +void SP_misc_light_flare( gentity_t *self ) +{ + self->s.eType = ET_LIGHTFLARE; + self->s.modelindex = G_ShaderIndex( self->targetShaderName ); + VectorCopy( self->pos2, self->s.origin2 ); + + //try to find a spot near to the flare which is empty. This + //is used to facilitate visibility testing + findEmptySpot( self->s.origin, 8.0f, self->s.angles2 ); + + self->use = SP_use_light_flare; + + G_SpawnFloat( "speed", "200", &self->speed ); + self->s.time = self->speed; + + G_SpawnInt( "mindist", "0", &self->s.generic1 ); + + if( self->spawnflags & 1 ) + self->s.eFlags |= EF_NODRAW; + + trap_LinkEntity( self ); +} |