mirror of
https://github.com/DrBeef/JKXR.git
synced 2024-11-23 12:32:26 +00:00
4597b03873
Opens in Android Studio but haven't even tried to build it yet (it won't.. I know that much!)
320 lines
No EOL
9 KiB
C++
320 lines
No EOL
9 KiB
C++
/*
|
|
===========================================================================
|
|
Copyright (C) 2000 - 2013, Raven Software, Inc.
|
|
Copyright (C) 2001 - 2013, Activision, Inc.
|
|
Copyright (C) 2013 - 2015, OpenJK contributors
|
|
|
|
This file is part of the OpenJK source code.
|
|
|
|
OpenJK is free software; you can redistribute it and/or modify it
|
|
under the terms of the GNU General Public License version 2 as
|
|
published by the Free Software Foundation.
|
|
|
|
This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
|
|
===========================================================================
|
|
*/
|
|
|
|
#include "g_local.h"
|
|
#include "b_local.h"
|
|
#include "g_functions.h"
|
|
#include "wp_saber.h"
|
|
#include "w_local.h"
|
|
|
|
//-----------------------
|
|
// Laser Trip Mine
|
|
//-----------------------
|
|
|
|
#define PROXIMITY_STYLE 1
|
|
#define TRIPWIRE_STYLE 2
|
|
|
|
//---------------------------------------------------------
|
|
void touchLaserTrap( gentity_t *ent, gentity_t *other, trace_t *trace )
|
|
//---------------------------------------------------------
|
|
{
|
|
ent->s.eType = ET_GENERAL;
|
|
|
|
// a tripwire so add draw line flag
|
|
VectorCopy( trace->plane.normal, ent->movedir );
|
|
|
|
// make it shootable
|
|
VectorSet( ent->mins, -4, -4, -4 );
|
|
VectorSet( ent->maxs, 4, 4, 4 );
|
|
|
|
ent->clipmask = MASK_SHOT;
|
|
ent->contents = CONTENTS_SHOTCLIP;
|
|
ent->takedamage = qtrue;
|
|
ent->health = 15;
|
|
|
|
ent->e_DieFunc = dieF_WP_ExplosiveDie;
|
|
ent->e_TouchFunc = touchF_NULL;
|
|
|
|
// so we can trip it too
|
|
ent->activator = ent->owner;
|
|
ent->owner = NULL;
|
|
|
|
WP_Stick( ent, trace );
|
|
|
|
if ( ent->count == TRIPWIRE_STYLE )
|
|
{
|
|
vec3_t mins = {-4,-4,-4}, maxs = {4,4,4};//FIXME: global these
|
|
trace_t tr;
|
|
VectorMA( ent->currentOrigin, 32, ent->movedir, ent->s.origin2 );
|
|
gi.trace( &tr, ent->s.origin2, mins, maxs, ent->currentOrigin, ent->s.number, MASK_SHOT, G2_RETURNONHIT, 0 );
|
|
VectorCopy( tr.endpos, ent->s.origin2 );
|
|
|
|
ent->e_ThinkFunc = thinkF_laserTrapThink;
|
|
}
|
|
else
|
|
{
|
|
ent->e_ThinkFunc = thinkF_WP_prox_mine_think;
|
|
}
|
|
|
|
ent->nextthink = level.time + LT_ACTIVATION_DELAY;
|
|
}
|
|
|
|
// copied from flechette prox above...which will not be used if this gets approved
|
|
//---------------------------------------------------------
|
|
void WP_prox_mine_think( gentity_t *ent )
|
|
//---------------------------------------------------------
|
|
{
|
|
int count;
|
|
qboolean blow = qfalse;
|
|
|
|
// first time through?
|
|
if ( ent->count )
|
|
{
|
|
// play activated warning
|
|
ent->count = 0;
|
|
ent->s.eFlags |= EF_PROX_TRIP;
|
|
G_Sound( ent, G_SoundIndex( "sound/weapons/laser_trap/warning.wav" ));
|
|
}
|
|
|
|
// if it isn't time to auto-explode, do a small proximity check
|
|
if ( ent->delay > level.time )
|
|
{
|
|
count = G_RadiusList( ent->currentOrigin, PROX_MINE_RADIUS_CHECK, ent, qtrue, ent_list );
|
|
|
|
for ( int i = 0; i < count; i++ )
|
|
{
|
|
if ( ent_list[i]->client && ent_list[i]->health > 0 && ent->activator && ent_list[i]->s.number != ent->activator->s.number )
|
|
{
|
|
blow = qtrue;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// well, we must die now
|
|
blow = qtrue;
|
|
}
|
|
|
|
if ( blow )
|
|
{
|
|
// G_Sound( ent, G_SoundIndex( "sound/weapons/flechette/warning.wav" ));
|
|
ent->e_ThinkFunc = thinkF_WP_Explode;
|
|
ent->nextthink = level.time + 200;
|
|
}
|
|
else
|
|
{
|
|
// we probably don't need to do this thinking logic very often...maybe this is fast enough?
|
|
ent->nextthink = level.time + 500;
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
void laserTrapThink( gentity_t *ent )
|
|
//---------------------------------------------------------
|
|
{
|
|
gentity_t *traceEnt;
|
|
vec3_t end, mins = {-4,-4,-4}, maxs = {4,4,4};
|
|
trace_t tr;
|
|
|
|
// turn on the beam effect
|
|
if ( !(ent->s.eFlags & EF_FIRING ))
|
|
{
|
|
// arm me
|
|
G_Sound( ent, G_SoundIndex( "sound/weapons/laser_trap/warning.wav" ));
|
|
ent->s.loopSound = G_SoundIndex( "sound/weapons/laser_trap/hum_loop.wav" );
|
|
ent->s.eFlags |= EF_FIRING;
|
|
}
|
|
|
|
ent->e_ThinkFunc = thinkF_laserTrapThink;
|
|
ent->nextthink = level.time + FRAMETIME;
|
|
|
|
// Find the main impact point
|
|
VectorMA( ent->s.pos.trBase, 2048, ent->movedir, end );
|
|
gi.trace( &tr, ent->s.origin2, mins, maxs, end, ent->s.number, MASK_SHOT, G2_RETURNONHIT, 0 );
|
|
|
|
traceEnt = &g_entities[ tr.entityNum ];
|
|
|
|
// Adjust this so that the effect has a relatively fresh endpoint
|
|
VectorCopy( tr.endpos, ent->pos4 );
|
|
|
|
if ( traceEnt->client || tr.startsolid )
|
|
{
|
|
// go boom
|
|
WP_Explode( ent );
|
|
ent->s.eFlags &= ~EF_FIRING; // don't draw beam if we are dead
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
// FIXME: they need to avoid the beam!
|
|
AddSoundEvent( ent->owner, ent->currentOrigin, ent->splashRadius*2, AEL_DANGER );
|
|
AddSightEvent( ent->owner, ent->currentOrigin, ent->splashRadius*2, AEL_DANGER, 50 );
|
|
*/
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
void CreateLaserTrap( gentity_t *laserTrap, vec3_t start, gentity_t *owner )
|
|
//---------------------------------------------------------
|
|
{
|
|
if ( !VALIDSTRING( laserTrap->classname ))
|
|
{
|
|
// since we may be coming from a map placed trip mine, we don't want to override that class name....
|
|
// That would be bad because the player drop code tries to limit number of placed items...so it would have removed map placed ones as well.
|
|
laserTrap->classname = "tripmine";
|
|
}
|
|
|
|
laserTrap->splashDamage = weaponData[WP_TRIP_MINE].splashDamage;
|
|
laserTrap->splashRadius = weaponData[WP_TRIP_MINE].splashRadius;
|
|
laserTrap->damage = weaponData[WP_TRIP_MINE].damage;
|
|
laserTrap->methodOfDeath = MOD_LASERTRIP;
|
|
laserTrap->splashMethodOfDeath = MOD_LASERTRIP;//? SPLASH;
|
|
|
|
laserTrap->s.eType = ET_MISSILE;
|
|
laserTrap->svFlags = SVF_USE_CURRENT_ORIGIN;
|
|
laserTrap->s.weapon = WP_TRIP_MINE;
|
|
|
|
laserTrap->owner = owner;
|
|
// VectorSet( laserTrap->mins, -LT_SIZE, -LT_SIZE, -LT_SIZE );
|
|
// VectorSet( laserTrap->maxs, LT_SIZE, LT_SIZE, LT_SIZE );
|
|
laserTrap->clipmask = (CONTENTS_SOLID|CONTENTS_BODY|CONTENTS_SHOTCLIP);//MASK_SHOT;
|
|
|
|
laserTrap->s.pos.trTime = level.time; // move a bit on the very first frame
|
|
VectorCopy( start, laserTrap->s.pos.trBase );
|
|
VectorCopy( start, laserTrap->currentOrigin);
|
|
|
|
VectorCopy( start, laserTrap->pos2 ); // ?? wtf ?
|
|
|
|
laserTrap->fxID = G_EffectIndex( "tripMine/explosion" );
|
|
|
|
laserTrap->e_TouchFunc = touchF_touchLaserTrap;
|
|
|
|
laserTrap->s.radius = 60;
|
|
VectorSet( laserTrap->s.modelScale, 1.0f, 1.0f, 1.0f );
|
|
gi.G2API_InitGhoul2Model( laserTrap->ghoul2, weaponData[WP_TRIP_MINE].missileMdl, G_ModelIndex( weaponData[WP_TRIP_MINE].missileMdl ),
|
|
NULL_HANDLE, NULL_HANDLE, 0, 0);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
static void WP_RemoveOldTraps( gentity_t *ent )
|
|
//---------------------------------------------------------
|
|
{
|
|
gentity_t *found = NULL;
|
|
int trapcount = 0, i;
|
|
int foundLaserTraps[MAX_GENTITIES] = {ENTITYNUM_NONE};
|
|
int trapcount_org, lowestTimeStamp;
|
|
int removeMe;
|
|
|
|
// see how many there are now
|
|
while (( found = G_Find( found, FOFS(classname), "tripmine" )) != NULL )
|
|
{
|
|
if ( found->activator != ent ) // activator is really the owner?
|
|
{
|
|
continue;
|
|
}
|
|
foundLaserTraps[trapcount++] = found->s.number;
|
|
}
|
|
|
|
// now remove first ones we find until there are only 9 left
|
|
found = NULL;
|
|
trapcount_org = trapcount;
|
|
lowestTimeStamp = level.time;
|
|
|
|
while ( trapcount > 9 )
|
|
{
|
|
removeMe = -1;
|
|
for ( i = 0; i < trapcount_org; i++ )
|
|
{
|
|
if ( foundLaserTraps[i] == ENTITYNUM_NONE )
|
|
{
|
|
continue;
|
|
}
|
|
found = &g_entities[foundLaserTraps[i]];
|
|
if ( found->setTime < lowestTimeStamp )
|
|
{
|
|
removeMe = i;
|
|
lowestTimeStamp = found->setTime;
|
|
}
|
|
}
|
|
if ( removeMe != -1 )
|
|
{
|
|
//remove it... or blow it?
|
|
if ( &g_entities[foundLaserTraps[removeMe]] == NULL )
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
G_FreeEntity( &g_entities[foundLaserTraps[removeMe]] );
|
|
}
|
|
foundLaserTraps[removeMe] = ENTITYNUM_NONE;
|
|
trapcount--;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
void WP_PlaceLaserTrap( gentity_t *ent, qboolean alt_fire )
|
|
//---------------------------------------------------------
|
|
{
|
|
vec3_t start;
|
|
gentity_t *laserTrap;
|
|
|
|
// limit to 10 placed at any one time
|
|
WP_RemoveOldTraps( ent );
|
|
|
|
//FIXME: surface must be within 64
|
|
laserTrap = G_Spawn();
|
|
|
|
if ( laserTrap )
|
|
{
|
|
// now make the new one
|
|
VectorCopy( muzzle, start );
|
|
WP_TraceSetStart( ent, start, vec3_origin, vec3_origin );//make sure our start point isn't on the other side of a wall
|
|
|
|
CreateLaserTrap( laserTrap, start, ent );
|
|
|
|
// set player-created-specific fields
|
|
laserTrap->setTime = level.time;//remember when we placed it
|
|
|
|
laserTrap->s.eFlags |= EF_MISSILE_STICK;
|
|
laserTrap->s.pos.trType = TR_GRAVITY;
|
|
VectorScale( forwardVec, LT_VELOCITY, laserTrap->s.pos.trDelta );
|
|
|
|
if ( alt_fire )
|
|
{
|
|
laserTrap->count = PROXIMITY_STYLE;
|
|
laserTrap->delay = level.time + 40000; // will auto-blow in 40 seconds.
|
|
laserTrap->methodOfDeath = MOD_LASERTRIP_ALT;
|
|
laserTrap->splashMethodOfDeath = MOD_LASERTRIP_ALT;//? SPLASH;
|
|
}
|
|
else
|
|
{
|
|
laserTrap->count = TRIPWIRE_STYLE;
|
|
}
|
|
}
|
|
} |