diff --git a/game/g_local.h b/game/g_local.h index b6d6e60..cdfa16a 100644 --- a/game/g_local.h +++ b/game/g_local.h @@ -908,8 +908,8 @@ void target_turbolift_start( gentity_t *ent ); qboolean LogAccuracyHit( gentity_t *target, gentity_t *attacker ); void CalcMuzzlePoint ( gentity_t *ent, vec3_t forward, vec3_t right, vec3_t up, vec3_t muzzlePoint, float projsize); void SnapVectorTowards( vec3_t v, vec3_t to ); -qboolean SeekerAcquiresTarget ( gentity_t *ent, vec3_t pos ); -void FireSeeker( gentity_t *owner, gentity_t *target, vec3_t origin); +//qboolean SeekerAcquiresTarget ( gentity_t *ent, vec3_t pos ); +//void FireSeeker( gentity_t *owner, gentity_t *target, vec3_t origin); // // g_client.c diff --git a/game/g_lua.c b/game/g_lua.c index 6f88b67..3172722 100644 --- a/game/g_lua.c +++ b/game/g_lua.c @@ -314,6 +314,7 @@ qboolean G_LuaStartVM(lvm_t * vm) Luaopen_Entity(vm->L); Luaopen_Cinematic(vm->L); Luaopen_Sound(vm->L); + Luaopen_Trace(vm->L); res = luaL_loadbuffer(vm->L, vm->code, vm->code_size, vm->filename); if(res == LUA_ERRSYNTAX) diff --git a/game/g_weapon.c b/game/g_weapon.c index 126d21f..daf5fef 100644 --- a/game/g_weapon.c +++ b/game/g_weapon.c @@ -377,327 +377,14 @@ void WP_FireCompressionRifle ( gentity_t *ent, qboolean alt_fire ) } } - -/* ----------------------------------------------- - IMOD ----------------------------------------------- -*/ - -#define MAXRANGE_IMOD 4096 -#define MAX_RAIL_HITS 4 - -void IMODHit(qboolean alt_fire, gentity_t *traceEnt, gentity_t *ent, vec3_t d_dir, vec3_t endpos, vec3_t normal, - qboolean render_impact) -{ - gentity_t *tent = NULL; - int damage = IMOD_ALT_DAMAGE*DMG_VAR; - - if ( alt_fire ) - { - // send beam impact - if ( traceEnt && traceEnt->takedamage ) - { - G_Damage( traceEnt, ent, ent, d_dir, endpos, damage, DAMAGE_NO_ARMOR | DAMAGE_NO_INVULNERABILITY, MOD_IMOD_ALT); - if (render_impact) - { - tent = G_TempEntity( endpos, EV_IMOD_ALTFIRE_HIT ); - } - // log hit - /*if (ent->client) - { - ent->client->ps.persistant[PERS_ACCURACY_HITS]++; - }*/ - } - } - else - { - // send beam impact - if ( traceEnt && traceEnt->takedamage && rpg_imoddmg.integer != 0) - { - G_Damage( traceEnt, ent, ent, d_dir, endpos, damage, DAMAGE_NO_ARMOR | DAMAGE_NO_INVULNERABILITY, MOD_IMOD); - if (render_impact) - { - tent = G_TempEntity( endpos, EV_IMOD_HIT ); - } - // log hit - /*if (ent->client) - { - ent->client->ps.persistant[PERS_ACCURACY_HITS]++; - }*/ - } - } - if (tent) - { - tent->s.eventParm = DirToByte( normal ); - tent->s.weapon = ent->s.weapon; - VectorCopy( muzzle, tent->s.origin2 ); - SnapVector(tent->s.origin2); - } -} - -//--------------------------------------------------------- -/*void WP_FireIMOD ( gentity_t *ent, qboolean alt_fire ) -//--------------------------------------------------------- -{ - int i = 0; - int hits = 0; - int unlinked = 0; - gentity_t *unlinkedEntities[MAX_RAIL_HITS]; - - trace_t tr; - vec3_t end, d_dir; - gentity_t *tent = 0; - gentity_t *traceEnt = NULL; - qboolean render_impact; - - VectorMA (muzzle, MAXRANGE_IMOD, forward, end); - - // trace only against the solids, so the railgun will go through people - do - { - trap_Trace (&tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT ); - traceEnt = &g_entities[ tr.entityNum ]; - if ( tr.surfaceFlags & SURF_NOIMPACT ) - { // If the beam hit the skybox, etc. it would look foolish to add in an explosion - render_impact = qfalse; - } else - { - render_impact = qtrue; - } - if ( traceEnt->takedamage ) - { - if( LogAccuracyHit( traceEnt, ent ) ) - { - hits++; - } - //For knockback - send them up in air - VectorCopy(forward, d_dir); - if(d_dir[2] < 0.30f) - { - d_dir[2] = 0.30f; - } - VectorNormalize(d_dir); - // do the damage and send an impact effect - IMODHit(alt_fire, traceEnt, ent, d_dir, tr.endpos, tr.plane.normal, qtrue); - - // give the shooter a reward sound if they have made two sniper hits in a row - // check for "impressive" reward sound - // Note that hitting two people in a line warrants an "impressive" as well... - if (traceEnt->client) - { - if (((g_gametype.integer >= GT_TEAM) && (ent->client->ps.persistant[PERS_TEAM] != traceEnt->client->ps.persistant[PERS_TEAM])) - || (g_gametype.integer < GT_TEAM)) - { - if (alt_fire) - { - ent->client->accurateCount++; - if ( ent->client->accurateCount >= 2 ) - { - ent->client->accurateCount -= 2; - ent->client->ps.persistant[PERS_REWARD_COUNT]++; - ent->client->ps.persistant[PERS_REWARD] = REWARD_IMPRESSIVE; - ent->client->ps.persistant[PERS_IMPRESSIVE_COUNT]++; - // add the sprite over the player's head - ent->client->ps.eFlags &= ~EF_AWARD_MASK; - ent->client->ps.eFlags |= EF_AWARD_IMPRESSIVE; - ent->client->rewardTime = level.time + REWARD_SPRITE_TIME; - } // End of brace - } - } - } - } - else - { // send an impact effect - IMODHit(alt_fire, traceEnt, ent, d_dir, tr.endpos, tr.plane.normal, render_impact); - } - if ( tr.contents & CONTENTS_SOLID ) - { - break; // we hit something solid enough to stop the beam - } - // unlink this entity, so the next trace will go past it - trap_UnlinkEntity( traceEnt ); - unlinkedEntities[unlinked] = traceEnt; - unlinked++; - } while ( unlinked < MAX_RAIL_HITS ); - - // link back in any entities we unlinked - for ( i = 0 ; i < unlinked ; i++ ) - { - trap_LinkEntity( unlinkedEntities[i] ); - } - - // With endcapping on, the beam is actually longer than what the length parm in FX_AddLine for this - // effect specifies..so move it out so it doesn't clip into the gun so much - if ( alt_fire ) - VectorMA (muzzle, 10, forward, muzzle); - else - VectorMA (muzzle, 2, forward, muzzle); - - // Create the events that will add in the necessary effects - if ( alt_fire ) - { - tent = G_TempEntity( tr.endpos, EV_IMOD_ALTFIRE ); - } - else - { - tent = G_TempEntity( tr.endpos, EV_IMOD ); - } - - // Stash origins, etc. so the effect can have access to them - VectorCopy( muzzle, tent->s.origin2 ); - SnapVector( tent->s.origin2 ); // save net bandwidth - if ( render_impact ) - { - tent->s.eventParm = DirToByte( tr.plane.normal ); - tent->s.weapon = ent->s.weapon; - } - - G_LogWeaponFire(ent->s.number, WP_1); - //G_LogWeaponFire(ent->s.number, WP_1); -}*/ - /* ---------------------------------------------- SCAVENGER ---------------------------------------------- */ - -#define SCAV_SPREAD 0.5 -#define SCAV_VELOCITY 1500 #define SCAV_SIZE 3 - -#define SCAV_ALT_VELOCITY 1000 -#define SCAV_ALT_UP_VELOCITY 100 #define SCAV_ALT_SIZE 6 -//TiM -//--------------------------------------------------------- -void FireScavengerBullet( gentity_t *ent, vec3_t start, vec3_t dir ) -//--------------------------------------------------------- -{ - gentity_t *bolt; - - bolt = G_Spawn(); - - bolt->classname = "scav_proj"; - bolt->nextthink = level.time + 10000; - bolt->think = G_FreeEntity; - bolt->s.eType = ET_MISSILE; - bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN; - //bolt->s.weapon = WP_4; - bolt->s.weapon = WP_10; //TiM - bolt->r.ownerNum = ent->s.number; - bolt->parent = ent; - -//fixme - remove - { - // Flags effect as being the full beefy version for the player - bolt->count = 0; - } - - bolt->damage = SCAV_DAMAGE*DMG_VAR*s_quadFactor; - bolt->splashDamage = 0; - bolt->splashRadius = 0; - bolt->methodOfDeath = MOD_SCAVENGER; - bolt->clipmask = MASK_SHOT; - - // Set the size of the missile up - VectorSet(bolt->r.maxs, SCAV_SIZE, SCAV_SIZE, SCAV_SIZE); - VectorSet(bolt->r.mins, -SCAV_SIZE, -SCAV_SIZE, -SCAV_SIZE); - - bolt->s.pos.trType = TR_LINEAR; - bolt->s.pos.trTime = level.time - 10; // move a bit on the very first frame - VectorCopy( start, bolt->s.pos.trBase ); - SnapVector( bolt->s.pos.trBase ); // save net bandwidth - VectorScale( dir, SCAV_VELOCITY, bolt->s.pos.trDelta ); - SnapVector( bolt->s.pos.trDelta ); // save net bandwidth - VectorCopy( start, bolt->r.currentOrigin); -} - -//TiM -// Alt-fire... -//--------------------------------------------------------- -/*void FireScavengerGrenade( gentity_t *ent, vec3_t start, vec3_t dir ) -//--------------------------------------------------------- -{ - gentity_t *grenade; - - grenade = G_Spawn(); - - grenade->classname = "scav_grenade"; - grenade->nextthink = level.time + 9000; - grenade->think = G_FreeEntity; - grenade->s.eType = ET_ALT_MISSILE; - grenade->s.weapon = WP_4; - grenade->r.ownerNum = ent->s.number; - grenade->parent = ent; - grenade->damage = SCAV_ALT_DAMAGE*DMG_VAR*s_quadFactor; - grenade->splashDamage = SCAV_ALT_SPLASH_DAM*s_quadFactor; - grenade->splashRadius = SCAV_ALT_SPLASH_RAD;// *s_quadFactor; - grenade->methodOfDeath = MOD_SCAVENGER_ALT; - grenade->splashMethodOfDeath = MOD_SCAVENGER_ALT_SPLASH; - grenade->clipmask = MASK_SHOT; - grenade->s.eFlags |= EF_ALT_FIRING; - - // Set the size of the missile up - VectorSet(grenade->r.maxs, SCAV_ALT_SIZE, SCAV_ALT_SIZE, SCAV_ALT_SIZE); - VectorSet(grenade->r.mins, -SCAV_ALT_SIZE, -SCAV_ALT_SIZE, -SCAV_ALT_SIZE); - - grenade->s.pos.trType = TR_GRAVITY; - grenade->s.pos.trTime = level.time; // move a bit on the very first frame - - VectorCopy( start, grenade->s.pos.trBase ); - SnapVector( grenade->s.pos.trBase ); // save net bandwidth - VectorScale( dir, random() * 100 + SCAV_ALT_VELOCITY, grenade->s.pos.trDelta ); - - // Add a tad of upwards velocity to the shot. - grenade->s.pos.trDelta[2] += SCAV_ALT_UP_VELOCITY; - - // Add in half the player's velocity to the shot. - VectorMA(grenade->s.pos.trDelta, 0.5, ent->s.pos.trDelta, grenade->s.pos.trDelta); - - SnapVector( grenade->s.pos.trDelta ); // save net bandwidth - VectorCopy (start, grenade->r.currentOrigin); - VectorCopy (start, grenade->pos1); - VectorCopy (start, grenade->s.origin2); - SnapVector( grenade->s.origin2 ); // save net bandwidth -}*/ - -//TiM -//--------------------------------------------------------- -/*void WP_FireScavenger( gentity_t *ent, qboolean alt_fire ) -//--------------------------------------------------------- -{ - vec3_t dir, angles, temp_ang, temp_org; - vec3_t start; - float offset; - - VectorCopy( forward, dir ); - VectorCopy( muzzle, start ); - - if ( alt_fire ) - { - FireScavengerGrenade( ent, start, dir ); - } - else - { - vectoangles( dir, angles ); - VectorSet( temp_ang, angles[0] + (crandom() * SCAV_SPREAD), angles[1] + (crandom() * SCAV_SPREAD), angles[2] ); - AngleVectors( temp_ang, dir, NULL, NULL ); - - // try to make the shot alternate between barrels - offset = irandom(0, 1) * 2 + 1; - - // FIXME: These offsets really don't work like they should - VectorMA( start, offset, right, temp_org ); - VectorMA( temp_org, offset, up, temp_org ); - FireScavengerBullet( ent, temp_org, dir ); - } - - G_LogWeaponFire(ent->s.number, WP_4); -}*/ - /* ---------------------------------------------- STASIS @@ -1395,163 +1082,8 @@ void WP_FireGrenade( gentity_t *ent, qboolean alt_fire ) ---------------------------------------------- */ -#define TETRION_SPREAD 275 -#define NUM_TETRION_SHOTS 3 - -#define TETRION_ALT_VELOCITY 500000 //RPG-X: J2J - increased velocity to 1/2 million units/second #define TETRION_ALT_SIZE 6 -#define MAXRANGE_TETRION 5000000 //RPG-X: J2J - increased range to 5 million units - -typedef struct tetrionHit_s -{ - gentity_t *ent; - vec3_t pos; -} tetrionHit_t; - -// provide the center of the circle, a normal out from it (normalized, please), and the radius. -//out will then become a random position on the radius of the circle. -void fxRandCircumferencePos(vec3_t center, vec3_t normal, float radius, vec3_t out) -{ - float rnd = flrandom(0, 2*M_PI); - float s = sin(rnd); - float c = cos(rnd); - vec3_t vTemp, radialX, radialY; - - vTemp[0]=0; - vTemp[1]=0; - vTemp[2]=-1; - CrossProduct(normal, vTemp, radialX); - CrossProduct(normal, radialX, radialY); - VectorScale(radialX, radius, radialX); - VectorScale(radialY, radius, radialY); - VectorMA(center, s, radialX, out); - VectorMA(out, c, radialY, out); -} -#define NUM_TETRION_BULLETS 3 -//--------------------------------------------------------- -void FireTetrionBullet( gentity_t *ent, vec3_t start, vec3_t dir ) -//--------------------------------------------------------- -{ - gentity_t *tent = NULL; - trace_t tr; - vec3_t end, lup = {0,0,1}, lright; // , zero = {0,0,0}; - int i = 0, j = 0; - qboolean bHitAlready = qfalse; - int numHits = 0; - tetrionHit_t hitEnts[NUM_TETRION_BULLETS]; - - - vec3_t new_start, radial, start2, spreadFwd; - float firingRadius = 6, minDeviation = 0.95, maxDeviation = 1.1; - - for (i = 0; i < NUM_TETRION_BULLETS; i++) - { - hitEnts[i].ent = NULL; - } - // create our message-entity with the firing position for an origin - tent = G_TempEntity(muzzle, EV_TETRION); - // stash our firing direction in the message also - VectorCopy(forward, tent->s.angles2); - VectorShort(tent->s.angles2); - - // now do the damage. we're going to fake three separate bullets here by doing three - //traces and splitting two or three hits worth of dmg between whatever the traces hit. - CrossProduct(forward, lup, lright); - CrossProduct(lright, forward, up); // get a "real" up - - for (i = 0; i < NUM_TETRION_BULLETS; i++) - { - // determine new firing position - fxRandCircumferencePos(start, forward, firingRadius, new_start); - VectorSubtract(new_start, start, radial); - VectorMA(start, 10, forward, start2); - VectorMA(start2, flrandom(minDeviation, maxDeviation), radial, start2); - VectorSubtract(start2, new_start, spreadFwd); - VectorNormalize(spreadFwd); - // determine new end position for this bullet. give the endpoint some spread, too. - VectorMA(new_start, MAXRANGE_TETRION, spreadFwd, end); - trap_Trace ( &tr, new_start, NULL, NULL, end, ent->s.number, MASK_SHOT); - if ((tr.entityNum < MAX_GENTITIES) && (tr.entityNum != ENTITYNUM_WORLD)) - { - bHitAlready = qfalse; - for (j = 0; j < numHits; j++) - { - if (hitEnts[j].ent == &g_entities[ tr.entityNum ]) - { - // already hit this ent - bHitAlready = qtrue; - break; - } - } - if (!bHitAlready) - { - hitEnts[numHits].ent = &g_entities[ tr.entityNum ]; - VectorCopy(tr.endpos, hitEnts[numHits].pos); - numHits++; - } - } - } - if (numHits) - { - // determine damage (2 or 3 bullets) - float totalDmg = (float)(irandom(2,3)*TETRION_DAMAGE*s_quadFactor), dmgPerHit = 0; - - dmgPerHit = (int)(totalDmg/(float)numHits); - for (i = 0; i < numHits; i++) - { - if (hitEnts[i].ent->takedamage) - { - G_Damage( hitEnts[i].ent, ent, ent, forward, hitEnts[i].pos, dmgPerHit, - DAMAGE_ARMOR_PIERCING|DAMAGE_NO_KNOCKBACK, MOD_TETRION ); - } - // log hit - /*if (ent->client) - { - ent->client->ps.persistant[PERS_ACCURACY_HITS]++; - }*/ - } - } -} - -//--------------------------------------------------------- -void FireTetrionProjectile( gentity_t *ent, vec3_t start, vec3_t dir ) -//--------------------------------------------------------- -{// Projectile that /*bouncesoff surfaces but does not have gravity - gentity_t *bolt; - - bolt = G_Spawn(); - bolt->classname = "tetrion_projectile"; - bolt->nextthink = level.time + 2000; - bolt->think = G_FreeEntity; - - bolt->s.eType = ET_ALT_MISSILE; - bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN; - //bolt->s.eFlags |= EF_BOUNCE; //RPG-X: J2J - Dont bounce anymore - //bolt->count = random() > 0.75f ? 3 : 4; //RPG-X: J2J - Number of bounces - - //RPG-X: J2J - Not sure about alt size, may need tweaking - VectorSet(bolt->r.mins, -TETRION_ALT_SIZE, -TETRION_ALT_SIZE, -TETRION_ALT_SIZE); - VectorSet(bolt->r.maxs, TETRION_ALT_SIZE, TETRION_ALT_SIZE, TETRION_ALT_SIZE); - - bolt->s.weapon = WP_7; - bolt->r.ownerNum = ent->s.number; - bolt->parent = ent; - bolt->damage = 300; //RPG-X: RedTechie - Use to be TETRION_ALT_DAMAGE*DMG_VAR*s_quadFactor; - bolt->splashDamage = 0; - bolt->splashRadius = 0; - bolt->methodOfDeath = MOD_TETRION_ALT; - bolt->clipmask = CONTENTS_BODY; //MASK_SHOT; MASK_ONLYPLAYER //RPG-X: J2J - Goes through all objects except players and corpses - - bolt->s.pos.trType = TR_LINEAR; - bolt->s.pos.trTime = level.time; // move a bit on the very first frame - VectorCopy( start, bolt->s.pos.trBase ); - SnapVector( bolt->s.pos.trBase ); // save net bandwidth - VectorScale( dir, TETRION_ALT_VELOCITY, bolt->s.pos.trDelta ); - SnapVector( bolt->s.pos.trDelta ); // save net bandwidth - VectorCopy (start, bolt->r.currentOrigin); -} - #define MAX_TR_116_DIST 8192 #define MAX_TRACES 24 //Number of traces thru walls we'll do before we give up lol @@ -1621,28 +1153,6 @@ void WP_FireTetrionDisruptor( gentity_t *ent, qboolean alt_fire ) WP_FireTR116Bullet( ent, start, dir ); - if ( alt_fire ) - { - //PM_AddEvent( EV_TR116_TRIS ); - //ent = G_TempEntity( muzzle, EV_HYPO_PUFF ); - //ent->s.eventParm = qfalse; - - //FireTetrionProjectile( ent, start, dir ); //Do nothing (server side) with alt fire now. - - //RPG-X: J2J - 3 second deley between each shot - //if((level.time - ent->last_tr116_fire) < 300) - // return; - //FireTetrionProjectile( ent, start, dir ); - } - else - { - //RPG-X: J2J - 3 second deley between each shot - //if((level.time - ent->last_tr116_fire) < 300) - // return; - //FireTetrionBullet( ent, start, dir ); //This now isnt used - //FireTetrionProjectile( ent, start, dir ); - } - G_LogWeaponFire(ent->s.number, WP_7); //ent->last_tr116_fire = level.time; //RPG-X: J2J update last fire time } @@ -1901,485 +1411,6 @@ void WP_FireQuantumBurst( gentity_t *ent, qboolean alt_fire ) } -/* ----------------------------------------------- - DREADNOUGHT ----------------------------------------------- -*/ - -#define MAXRANGE_DREADNOUGHT 2048 - -//--------------------------------------------------------- -void WP_FireDreadnoughtBeam( gentity_t *ent ) -//--------------------------------------------------------- -{ - trace_t tr; - vec3_t end; - gentity_t *traceEnt; - vec3_t start; - qboolean bHit = qfalse; - - // Trace once to the right... - VectorMA( muzzle, DREADNOUGHT_WIDTH, right, start); - VectorMA( start, MAXRANGE_DREADNOUGHT, forward, end ); - - // Find out who we've hit - trap_Trace( &tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT ); - traceEnt = &g_entities[ tr.entityNum ]; - - if ( traceEnt->takedamage) - { - G_Damage( traceEnt, ent, ent, forward, tr.endpos, DREADNOUGHT_DAMAGE*s_quadFactor, - DAMAGE_NOT_ARMOR_PIERCING, MOD_DREADNOUGHT); - bHit = qtrue; - } - - // Now trace once to the left... - VectorMA( muzzle, -DREADNOUGHT_WIDTH, right, start); - VectorMA( start, MAXRANGE_DREADNOUGHT, forward, end ); - - // Find out who we've hit - trap_Trace( &tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT ); - traceEnt = &g_entities[ tr.entityNum ]; - - if ( traceEnt->takedamage) - { - G_Damage( traceEnt, ent, ent, forward, tr.endpos, DREADNOUGHT_DAMAGE*s_quadFactor, - DAMAGE_NOT_ARMOR_PIERCING, MOD_DREADNOUGHT); - bHit = qtrue; - } - if (bHit) - { - // log hit - /*if (ent->client) - { - ent->client->ps.persistant[PERS_ACCURACY_HITS]++; - }*/ - } -} - - -//#define DN_SEARCH_DIST 512 -//#define DN_SIDE_DIST 64 -//#define DN_RAND_DEV 8 - -#define DN_SEARCH_DIST 256 -#define DN_SIDE_DIST 128 -#define DN_RAND_DEV 16 -#define DN_ALT_THINK_TIME 100 -#define DN_ALT_SIZE 12 -void DreadnoughtBurstThink(gentity_t *ent) -{ - vec3_t startpos, endpos, perp; - trace_t tr; - gentity_t *traceEnt, *tent; - int source; - vec3_t dest, mins={-DN_ALT_SIZE,-DN_ALT_SIZE,-1}, maxs={DN_ALT_SIZE,DN_ALT_SIZE,1}; - float dot; - static qboolean recursion=qfalse; - - VectorCopy(ent->s.origin, startpos); - - // Search in a 3-way arc in front of it. - VectorMA(startpos, DN_SEARCH_DIST, ent->movedir, endpos); - endpos[0] += flrandom(-DN_RAND_DEV, DN_RAND_DEV); - endpos[1] += flrandom(-DN_RAND_DEV, DN_RAND_DEV); - endpos[2] += flrandom(-DN_RAND_DEV*0.5, DN_RAND_DEV*0.5); - - // unlink this entity, so the next trace will go past it - trap_UnlinkEntity(ent); - - // link back in any entities we unlinked - if (ent->target_ent) - { - source = ent->target_ent->s.number; - } - else if (ent->r.ownerNum) - { - source = ent->r.ownerNum; - } - else - { - source = ent->s.number; - } - - trap_Trace (&tr, startpos, mins, maxs, endpos, source, MASK_SHOT ); - traceEnt = &g_entities[ tr.entityNum ]; - // did we hit the holdable shield? - if (traceEnt->classname && !Q_stricmp(traceEnt->classname, "holdable_shield")) - { - // Make sure you damage the surface first - G_Damage( traceEnt, ent, &g_entities[ent->r.ownerNum], forward, tr.endpos, ent->damage, - DAMAGE_NOT_ARMOR_PIERCING, MOD_DREADNOUGHT_ALT); - - VectorCopy(ent->s.origin, ent->s.origin2); - VectorCopy(endpos, ent->s.origin); - SnapVector(ent->s.origin); - SnapVector(ent->s.origin2); - - ent->nextthink = level.time + 100; - - // yes. We are done. - ent->think = G_FreeEntity; - - tent = G_TempEntity( tr.endpos, EV_DREADNOUGHT_MISS ); - // Stash origins, etc. so that the effects can have access to them - VectorCopy( startpos, tent->s.origin2 ); - SnapVector(tent->s.origin2); - tent->s.eventParm = DirToByte( tr.plane.normal ); - - return; - } - - if (traceEnt->takedamage) - { - ent->target_ent = traceEnt; - VectorCopy(ent->s.origin, ent->s.origin2); - SnapVector(ent->s.origin); - SnapVector(ent->s.origin2); - VectorCopy(traceEnt->r.currentOrigin, ent->s.origin); - trap_LinkEntity(ent); - VectorNormalize(ent->movedir); - ent->nextthink = level.time + DN_ALT_THINK_TIME; - G_Damage( traceEnt, ent, &g_entities[ent->r.ownerNum], forward, tr.endpos, ent->damage, - DAMAGE_NOT_ARMOR_PIERCING, MOD_DREADNOUGHT_ALT); - // log hit - /*if (ent->client) - { - ent->client->ps.persistant[PERS_ACCURACY_HITS]++; - }*/ - return; - } - else - { - if (tr.fraction < 0.02) - { // Hit a wall... - - dot = DotProduct(ent->movedir, tr.plane.normal); - if (dot < -0.6 || dot == 0.0) - { // Stop. - G_FreeEntity( ent ); - - tent = G_TempEntity( tr.endpos, EV_DREADNOUGHT_MISS ); - - // Stash origins, etc. so that the effects can have access to them - VectorCopy( startpos, tent->s.origin2 ); - SnapVector(tent->s.origin2); - tent->s.eventParm = DirToByte( tr.plane.normal ); - - return; - } - else - { - - // Bounce off the surface just a little - VectorMA(ent->movedir, -1.25*dot, tr.plane.normal, ent->movedir); - VectorNormalize(ent->movedir); - - // Make sure we store a next think time, else the effect could stick around forever... - ent->nextthink = level.time + DN_ALT_THINK_TIME; - - if (!recursion) - { // NOTE RECURSION HERE. - recursion=qtrue; - DreadnoughtBurstThink(ent); - recursion=qfalse; - } - - return; - } - - } - - VectorCopy(tr.endpos, dest); - } - - // Didn't hit anything forward. Try some side vectors. - - // Get the perp vector (okay, only in 2D) to find a right or left (random)-pointing perpendicular vector to the facing. - if (irandom(0,1)) - { // Right vector - perp[0] = ent->movedir[1]; - perp[1] = -ent->movedir[0]; - perp[2] = ent->movedir[2]; - } - else - { // Left vector - perp[0] = -ent->movedir[1]; - perp[1] = ent->movedir[0]; - perp[2] = ent->movedir[2]; - } - - // Search a random interval from the side arc - VectorMA(endpos, DN_SIDE_DIST, perp, endpos); - endpos[0] += flrandom(-DN_RAND_DEV, DN_RAND_DEV); - endpos[1] += flrandom(-DN_RAND_DEV, DN_RAND_DEV); - endpos[2] += flrandom(-DN_RAND_DEV*0.5, DN_RAND_DEV*0.5); - - trap_Trace (&tr, startpos, mins, maxs, endpos, source, MASK_SHOT ); - traceEnt = &g_entities[ tr.entityNum ]; - // did we hit the holdable shield? - if (traceEnt->classname && !Q_stricmp(traceEnt->classname, "holdable_shield")) - { - // yes. We are done. - VectorCopy(ent->s.origin, ent->s.origin2); - VectorCopy(endpos, ent->s.origin); - SnapVector(ent->s.origin); - SnapVector(ent->s.origin2); - - ent->nextthink = level.time + 100; - - ent->think = G_FreeEntity; - tent = G_TempEntity( tr.endpos, EV_DREADNOUGHT_MISS ); - // Stash origins, etc. so that the effects can have access to them - VectorCopy( startpos, tent->s.origin2 ); - SnapVector(tent->s.origin2); - tent->s.eventParm = DirToByte( tr.plane.normal ); - - return; - } - if (traceEnt->takedamage) - { - ent->target_ent = traceEnt; - VectorCopy(ent->s.origin, ent->s.origin2); - SnapVector(ent->s.origin); - SnapVector(ent->s.origin2); - VectorCopy(traceEnt->r.currentOrigin, ent->s.origin); - trap_LinkEntity(ent); - VectorNormalize(ent->movedir); - ent->nextthink = level.time + DN_ALT_THINK_TIME; - G_Damage( traceEnt, ent, &g_entities[ent->r.ownerNum], forward, tr.endpos, ent->damage, - DAMAGE_NOT_ARMOR_PIERCING, MOD_DREADNOUGHT_ALT); - - // log hit - /*if (ent->client) - { - ent->client->ps.persistant[PERS_ACCURACY_HITS]++; - }*/ - // NOTE Send this as a hit effect once we have one... - G_Sound( traceEnt, G_SoundIndex( SOUND_DIR "dreadnought/dn_althit.wav")); - - return; - } - - // Search a random interval in the opposite direction - VectorMA(endpos, -2.0*DN_SIDE_DIST, perp, endpos); - endpos[0] += flrandom(-DN_RAND_DEV, DN_RAND_DEV); - endpos[1] += flrandom(-DN_RAND_DEV, DN_RAND_DEV); - endpos[2] += flrandom(-DN_RAND_DEV*0.5, DN_RAND_DEV*0.5); - - trap_Trace (&tr, startpos, mins, maxs, endpos, source, MASK_SHOT ); - traceEnt = &g_entities[ tr.entityNum ]; - // did we hit the holdable shield? - if (traceEnt->classname && !Q_stricmp(traceEnt->classname, "holdable_shield")) - { - VectorCopy(ent->s.origin, ent->s.origin2); - VectorCopy(endpos, ent->s.origin); - SnapVector(ent->s.origin); - SnapVector(ent->s.origin2); - - ent->nextthink = level.time + 100; - - // yes. We are done. - ent->think = G_FreeEntity; - - tent = G_TempEntity( tr.endpos, EV_DREADNOUGHT_MISS ); - // Stash origins, etc. so that the effects can have access to them - VectorCopy( startpos, tent->s.origin2 ); - SnapVector(tent->s.origin2); - tent->s.eventParm = DirToByte( tr.plane.normal ); - - return; - } - if (traceEnt->takedamage) - { - ent->target_ent = traceEnt; - VectorCopy(ent->s.origin, ent->s.origin2); - SnapVector(ent->s.origin); - SnapVector(ent->s.origin2); - VectorCopy(traceEnt->r.currentOrigin, ent->s.origin); - trap_LinkEntity(ent); - VectorNormalize(ent->movedir); - ent->nextthink = level.time + DN_ALT_THINK_TIME; - G_Damage( traceEnt, ent, &g_entities[ent->r.ownerNum], forward, tr.endpos, ent->damage, - DAMAGE_NOT_ARMOR_PIERCING, MOD_DREADNOUGHT_ALT); - // log hit - /*if (ent->client) - { - ent->client->ps.persistant[PERS_ACCURACY_HITS]++; - }*/ - return; - } - - // We didn't find anything, so move the entity to the middle destination. - ent->target_ent = NULL; - VectorCopy(ent->s.origin, ent->s.origin2); - VectorCopy(dest, ent->s.origin); - VectorCopy(dest, ent->s.pos.trBase); - SnapVector(ent->s.origin2); - trap_LinkEntity(ent); - ent->nextthink = level.time + DN_ALT_THINK_TIME; - - return; -} - - -//--------------------------------------------------------- -void WP_FireDreadnoughtBurst( gentity_t *ent ) -//--------------------------------------------------------- -{ - gentity_t *bolt; - vec3_t dir, start; - - VectorCopy( forward, dir ); - VectorCopy( muzzle, start ); - - bolt = G_Spawn(); - bolt->classname = "dn_projectile"; - - bolt->nextthink = level.time + 200; - bolt->think = DreadnoughtBurstThink; - - bolt->s.eType = ET_ALT_MISSILE; - bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN; - bolt->s.weapon = WP_13; - bolt->r.ownerNum = ent->s.number; - bolt->parent = ent; - bolt->damage = DREADNOUGHT_ALTDAMAGE*DMG_VAR*s_quadFactor; - bolt->splashDamage = 0; - bolt->splashRadius = 0; - bolt->methodOfDeath = MOD_DREADNOUGHT_ALT; - bolt->clipmask = MASK_SHOT; - - bolt->s.pos.trType = TR_LINEAR; - bolt->s.pos.trTime = level.time; - VectorCopy( start, bolt->s.pos.trBase ); - VectorCopy( start, bolt->s.origin); - SnapVector(bolt->s.pos.trBase); - SnapVector(bolt->s.origin); - - VectorCopy( forward, bolt->movedir); - - SnapVector( bolt->s.pos.trDelta ); // save net bandwidth - VectorCopy( start, bolt->r.currentOrigin ); - VectorCopy( start, bolt->pos1 ); - VectorCopy( start, bolt->pos2 ); - - DreadnoughtBurstThink(bolt); -} - -//--------------------------------------------------------- -void WP_FireDreadnought( gentity_t *ent, qboolean alt_fire ) -//--------------------------------------------------------- -{ - // This was moved out of the FireWeapon switch statement below to keep things more consistent - if ( alt_fire ) - { - WP_FireDreadnoughtBurst( ent ); - } - else - { - WP_FireDreadnoughtBeam( ent ); - } - - G_LogWeaponFire(ent->s.number, WP_13); -} - - -//====================================================================== - -#define BORG_PROJECTILE_SIZE 8 -#define BORG_PROJ_VELOCITY 1000 - -void WP_FireBorgTaser( gentity_t *ent ) -{ - trace_t tr; - vec3_t end, d_dir; - gentity_t *tent = 0; - gentity_t *traceEnt = NULL; - - VectorMA (muzzle, MAXRANGE_IMOD, forward, end); - - trap_Trace (&tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT ); - traceEnt = &g_entities[ tr.entityNum ]; - - if ( traceEnt->takedamage ) - { - LogAccuracyHit( traceEnt, ent ); - - //For knockback - send them up in air - VectorCopy( forward, d_dir ); - if ( d_dir[2] < 0.30f ) - { - d_dir[2] = 0.30f; - } - VectorNormalize( d_dir ); - - G_Damage( traceEnt, ent, ent, forward, tr.endpos, BORG_TASER_DAMAGE * s_quadFactor, 0, MOD_BORG_ALT ); - } - - VectorMA (muzzle, 2, forward, muzzle); - tent = G_TempEntity( tr.endpos, EV_BORG_ALT_WEAPON ); - - // Stash origins, etc. so the effect can have access to them - VectorCopy( muzzle, tent->s.origin2 ); - SnapVector( tent->s.origin2 ); // save net bandwidth - tent->s.eventParm = DirToByte( tr.plane.normal ); - tent->s.weapon = ent->s.weapon; -} - - -void WP_FireBorgProjectile( gentity_t *ent, vec3_t start ) -//--------------------------------------------------------- -{ - gentity_t *bolt; - - bolt = G_Spawn(); - - bolt->classname = "borg_proj"; - bolt->nextthink = level.time + 10000; - bolt->think = G_FreeEntity; - bolt->s.eType = ET_MISSILE; - bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN; - bolt->s.weapon = WP_11; - bolt->r.ownerNum = ent->s.number; - bolt->parent = ent; - - bolt->damage = BORG_PROJ_DAMAGE * DMG_VAR * s_quadFactor; - bolt->splashDamage = 0; - bolt->splashRadius = 0; - bolt->methodOfDeath = MOD_BORG; - bolt->clipmask = MASK_SHOT; - - // Set the size of the missile up - VectorSet(bolt->r.maxs, BORG_PROJECTILE_SIZE, BORG_PROJECTILE_SIZE, BORG_PROJECTILE_SIZE); - VectorScale( bolt->r.maxs, -1, bolt->r.mins ); - - bolt->s.pos.trType = TR_LINEAR; - bolt->s.pos.trTime = level.time; // move a bit on the very first frame - VectorCopy( start, bolt->s.pos.trBase ); - SnapVector( bolt->s.pos.trBase ); // save net bandwidth - VectorScale( forward, BORG_PROJ_VELOCITY, bolt->s.pos.trDelta ); - SnapVector( bolt->s.pos.trDelta ); // save net bandwidth - VectorCopy( start, bolt->r.currentOrigin); -} - -void WP_FireBorgWeapon( gentity_t *ent, qboolean alt_fire ) -//--------------------------------------------------------- -{ - if ( alt_fire ) - { - WP_FireBorgTaser( ent ); - } - else - { - WP_FireBorgProjectile( ent, muzzle ); - } - - G_LogWeaponFire( ent->s.number, WP_11 ); -} - - /* =============== LogAccuracyHit @@ -2791,98 +1822,6 @@ void WP_SprayVoyagerHypo( gentity_t *ent, qboolean alt_fire ) } } -void WP_Assimilate( gentity_t *ent, qboolean alt_fire ) -{//MCG: hacked this in for now for testing the rules - gentity_t *tr_ent; - trace_t tr; - vec3_t end; - float range; - - if ( ent->s.number == borgQueenClientNum ) - { - range = 32; - } - else - { - range = 64; - } - VectorMA( muzzle, range, forward, end ); - - trap_Trace ( &tr, muzzle, vec3_origin, vec3_origin, end, ent->s.number, MASK_SHOT ); - - if ( tr.entityNum >= ENTITYNUM_WORLD ) - { - return; - } - - tr_ent = &g_entities[tr.entityNum]; - - if ( tr_ent && tr_ent->client && tr_ent->health > 0 && ent->client && ent->client->sess.sessionTeam != tr_ent->client->sess.sessionTeam ) - { - if ( ent->s.number == borgQueenClientNum ) - {//Borg queen assimilates with one hit - tr_ent->health = 0; - player_die( tr_ent, ent, ent, 100, MOD_ASSIMILATE ); - //G_Damage( tr_ent, ent, ent, forward, tr.endpos, 50, DAMAGE_NO_ARMOR|DAMAGE_NO_INVULNERABILITY, MOD_ASSIMILATE ); - } - else - { - G_Damage( tr_ent, ent, ent, forward, tr.endpos, 10, DAMAGE_NO_ARMOR|DAMAGE_NO_INVULNERABILITY, MOD_ASSIMILATE ); - } - } -} - -/* -=============== -RPG-X Fire Engineer Tool -By: RedTechie -=============== -*/ -/*void WP_NEUTRINO_PROBE( gentity_t *ent, qboolean alt_fire ){ - gentity_t *target; //Target entity - trace_t trace; //Used to trace target - vec3_t src, dest, vf; //Used to find target - - if(!ent){ - return; - } - //if(ent->parent->client->sess.sessionClass == PC_ADMIN){ - if(alt_fire){ - return; - }else{ - ////////////////////////////////////// - //All this code below finds the target entity - - VectorCopy( ent->r.currentOrigin, src ); - src[2] += ent->client->ps.viewheight; - - AngleVectors( ent->client->ps.viewangles, vf, NULL, NULL ); - - //extend to find end of use trace - VectorMA( src, -6, vf, src );//in case we're inside something? - VectorMA( src, 1340, vf, dest );//128+6 - - //Trace ahead to find a valid target - trap_Trace( &trace, src, vec3_origin, vec3_origin, dest, ent->s.number, CONTENTS_TRIGGER ); - - if ( trace.fraction == 1.0f || trace.entityNum < 0 ) - { - trap_SendConsoleCommand( EXEC_APPEND, va("echo No target in range to kick.") ); - return; - } - - target = &g_entities[trace.entityNum]; - - //////////////////////////////// - - //lets delete it - if(target){ - G_FreeEntity( target ); - } - } - //} -}*/ - /* =============== FireWeapon @@ -2895,43 +1834,10 @@ FireWeapon void FireWeapon( gentity_t *ent, qboolean alt_fire ) { float projsize; - int i = 0; - qboolean bFastWeapon = qfalse; - weapon_t fastWeapons[NUM_FAST_WEAPONS] = - { - WP_5, - //WP_7 - }; - /*if (ent->client->ps.powerups[PW_QUAD] ) { - s_quadFactor = 3; - } else {*/ - s_quadFactor = 1; - //} + s_quadFactor = 1; - // Unghost the player. - //RPG-X: RedTechie N00bs are to stupid to get unghosted by firing - //ent->client->ps.powerups[PW_GHOST] = 0; - - // track shots taken for accuracy tracking - for (i = 0; i < NUM_FAST_WEAPONS; i++) - { - if (fastWeapons[i] == ent->s.weapon) - { - bFastWeapon = qtrue; - break; - } - } - if (bFastWeapon && ((level.time - ent->client->pers.teamState.lastFireTime) < ACCURACY_TRACKING_DELAY)) - { - // using a weapon with a high rate of fire so try to be a little more forgiving with - //this whole accuracy thing - } - else - { - //ent->client->ps.persistant[PERS_ACCURACY_SHOTS]++; - ent->client->pers.teamState.lastFireTime = level.time; - } + ent->client->pers.teamState.lastFireTime = level.time; // set aiming directions AngleVectors (ent->client->ps.viewangles, forward, right, up); @@ -2958,13 +1864,10 @@ void FireWeapon( gentity_t *ent, qboolean alt_fire ) WP_FireCompressionRifle( ent, alt_fire ); break; case WP_1: - //WP_FireIMOD(ent, alt_fire); - //G_Printf( "BANG!\n" ); if ( IsAdmin( ent ) && alt_fire ) WP_FireGrenade( ent, qfalse ); break; case WP_4: - //WP_FireScavenger( ent, alt_fire ); break; case WP_10: WP_FireDisruptor( ent, alt_fire ); @@ -2977,7 +1880,6 @@ void FireWeapon( gentity_t *ent, qboolean alt_fire ) break; case WP_13: WP_SprayVoyagerHypo( ent, alt_fire ); -// WP_FireDreadnought( ent, alt_fire ); break; case WP_9: WP_FireQuantumBurst( ent, alt_fire ); @@ -2988,122 +1890,20 @@ void FireWeapon( gentity_t *ent, qboolean alt_fire ) case WP_3: break; case WP_15: - //RPG-X:RedTechie - TODO make the thing do something! - //WP_FxGun( ent, alt_fire ); - //WP_NEUTRINO_PROBE( ent, alt_fire ); WP_FireHyperspanner(ent, alt_fire); break; -// case WP_7: -// WP_FireCompressionRifle( ent, alt_fire ); -// WP_FireTR116( ent, alt_fire ); - break; case WP_12: WP_SprayVoyagerHypo( ent, alt_fire ); break; case WP_14: -// WP_Assimilate( ent, alt_fire ); break; case WP_11: -// WP_FireBorgWeapon( ent, alt_fire ); break; - default: -// FIXME G_Error( "Bad ent->s.weapon" ); break; } } -#define SEEKER_RADIUS 500 - -qboolean SeekerAcquiresTarget ( gentity_t *ent, vec3_t pos ) -{ - vec3_t seekerPos; - float angle; - int entityList[MAX_CLIENTS]; // targets within inital radius - int visibleTargets[MAX_CLIENTS]; // final filtered target list - int numListedEntities; - int i, e; - gentity_t *target; - vec3_t mins, maxs; - -// if (!irandom(0,2)) for now, it'll shoot every second it finds a target - { - angle = level.time/100.0f; - seekerPos[0] = ent->r.currentOrigin[0] + 18 * cos(angle); - seekerPos[1] = ent->r.currentOrigin[1] + 18 * sin(angle); - seekerPos[2] = ent->r.currentOrigin[2] + ent->client->ps.viewheight + 8 + (3*cos(level.time/150.0f)); - - for ( i = 0 ; i < 3 ; i++ ) - { - mins[i] = seekerPos[i] - SEEKER_RADIUS; - maxs[i] = seekerPos[i] + SEEKER_RADIUS; - } - - // get potential targets within radius - numListedEntities = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES ); - - i = 0; // reset counter - - for ( e = 0 ; e < numListedEntities ; e++ ) - { - target = &g_entities[entityList[ e ]]; - // seeker owner not a valid target - if (target == ent) - { - continue; - } - - // only players are valid targets - if (!target->classname || strcmp(target->classname, "player")) - { - continue; - } - - // teammates not valid targets - if (OnSameTeam(ent, target)) - { - continue; - } - - // don't shoot at dead things - if (target->health <= 0) - { - continue; - } - //RPG-X: RedTechie - Need to take this out causes bad crashes with entity shooter, shouldent be needed anyway with newer code - //target->beingfiredby = ent; - if( CanDamage (target, seekerPos) ) // visible target, so add it to the list - { - visibleTargets[i++] = entityList[e]; - } - } - - if (i) - { - // ok, now we know there are i visible targets. Pick one as the seeker's target - ent->enemy = &g_entities[visibleTargets[irandom(0,i-1)]]; - VectorCopy(seekerPos, pos); - return qtrue; - } - } - - return qfalse; -} - -void FireSeeker( gentity_t *owner, gentity_t *target, vec3_t origin) -{ - vec3_t dir; - - VectorSubtract( target->r.currentOrigin, origin, dir); - VectorNormalize(dir); - - // for now I'm just using the scavenger bullet. - FireScavengerBullet( owner, origin, dir ); -} - - - - /* ============ Laser Sight Stuff diff --git a/old_code/g_weapon.c b/old_code/g_weapon.c new file mode 100644 index 0000000..966ae44 --- /dev/null +++ b/old_code/g_weapon.c @@ -0,0 +1,1128 @@ +/* +---------------------------------------------- + DREADNOUGHT +---------------------------------------------- +*/ + +#define MAXRANGE_DREADNOUGHT 2048 + +//--------------------------------------------------------- +void WP_FireDreadnoughtBeam( gentity_t *ent ) +//--------------------------------------------------------- +{ + trace_t tr; + vec3_t end; + gentity_t *traceEnt; + vec3_t start; + qboolean bHit = qfalse; + + // Trace once to the right... + VectorMA( muzzle, DREADNOUGHT_WIDTH, right, start); + VectorMA( start, MAXRANGE_DREADNOUGHT, forward, end ); + + // Find out who we've hit + trap_Trace( &tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT ); + traceEnt = &g_entities[ tr.entityNum ]; + + if ( traceEnt->takedamage) + { + G_Damage( traceEnt, ent, ent, forward, tr.endpos, DREADNOUGHT_DAMAGE*s_quadFactor, + DAMAGE_NOT_ARMOR_PIERCING, MOD_DREADNOUGHT); + bHit = qtrue; + } + + // Now trace once to the left... + VectorMA( muzzle, -DREADNOUGHT_WIDTH, right, start); + VectorMA( start, MAXRANGE_DREADNOUGHT, forward, end ); + + // Find out who we've hit + trap_Trace( &tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT ); + traceEnt = &g_entities[ tr.entityNum ]; + + if ( traceEnt->takedamage) + { + G_Damage( traceEnt, ent, ent, forward, tr.endpos, DREADNOUGHT_DAMAGE*s_quadFactor, + DAMAGE_NOT_ARMOR_PIERCING, MOD_DREADNOUGHT); + bHit = qtrue; + } + if (bHit) + { + // log hit + /*if (ent->client) + { + ent->client->ps.persistant[PERS_ACCURACY_HITS]++; + }*/ + } +} + + +//#define DN_SEARCH_DIST 512 +//#define DN_SIDE_DIST 64 +//#define DN_RAND_DEV 8 + +#define DN_SEARCH_DIST 256 +#define DN_SIDE_DIST 128 +#define DN_RAND_DEV 16 +#define DN_ALT_THINK_TIME 100 +#define DN_ALT_SIZE 12 +void DreadnoughtBurstThink(gentity_t *ent) +{ + vec3_t startpos, endpos, perp; + trace_t tr; + gentity_t *traceEnt, *tent; + int source; + vec3_t dest, mins={-DN_ALT_SIZE,-DN_ALT_SIZE,-1}, maxs={DN_ALT_SIZE,DN_ALT_SIZE,1}; + float dot; + static qboolean recursion=qfalse; + + VectorCopy(ent->s.origin, startpos); + + // Search in a 3-way arc in front of it. + VectorMA(startpos, DN_SEARCH_DIST, ent->movedir, endpos); + endpos[0] += flrandom(-DN_RAND_DEV, DN_RAND_DEV); + endpos[1] += flrandom(-DN_RAND_DEV, DN_RAND_DEV); + endpos[2] += flrandom(-DN_RAND_DEV*0.5, DN_RAND_DEV*0.5); + + // unlink this entity, so the next trace will go past it + trap_UnlinkEntity(ent); + + // link back in any entities we unlinked + if (ent->target_ent) + { + source = ent->target_ent->s.number; + } + else if (ent->r.ownerNum) + { + source = ent->r.ownerNum; + } + else + { + source = ent->s.number; + } + + trap_Trace (&tr, startpos, mins, maxs, endpos, source, MASK_SHOT ); + traceEnt = &g_entities[ tr.entityNum ]; + // did we hit the holdable shield? + if (traceEnt->classname && !Q_stricmp(traceEnt->classname, "holdable_shield")) + { + // Make sure you damage the surface first + G_Damage( traceEnt, ent, &g_entities[ent->r.ownerNum], forward, tr.endpos, ent->damage, + DAMAGE_NOT_ARMOR_PIERCING, MOD_DREADNOUGHT_ALT); + + VectorCopy(ent->s.origin, ent->s.origin2); + VectorCopy(endpos, ent->s.origin); + SnapVector(ent->s.origin); + SnapVector(ent->s.origin2); + + ent->nextthink = level.time + 100; + + // yes. We are done. + ent->think = G_FreeEntity; + + tent = G_TempEntity( tr.endpos, EV_DREADNOUGHT_MISS ); + // Stash origins, etc. so that the effects can have access to them + VectorCopy( startpos, tent->s.origin2 ); + SnapVector(tent->s.origin2); + tent->s.eventParm = DirToByte( tr.plane.normal ); + + return; + } + + if (traceEnt->takedamage) + { + ent->target_ent = traceEnt; + VectorCopy(ent->s.origin, ent->s.origin2); + SnapVector(ent->s.origin); + SnapVector(ent->s.origin2); + VectorCopy(traceEnt->r.currentOrigin, ent->s.origin); + trap_LinkEntity(ent); + VectorNormalize(ent->movedir); + ent->nextthink = level.time + DN_ALT_THINK_TIME; + G_Damage( traceEnt, ent, &g_entities[ent->r.ownerNum], forward, tr.endpos, ent->damage, + DAMAGE_NOT_ARMOR_PIERCING, MOD_DREADNOUGHT_ALT); + // log hit + /*if (ent->client) + { + ent->client->ps.persistant[PERS_ACCURACY_HITS]++; + }*/ + return; + } + else + { + if (tr.fraction < 0.02) + { // Hit a wall... + + dot = DotProduct(ent->movedir, tr.plane.normal); + if (dot < -0.6 || dot == 0.0) + { // Stop. + G_FreeEntity( ent ); + + tent = G_TempEntity( tr.endpos, EV_DREADNOUGHT_MISS ); + + // Stash origins, etc. so that the effects can have access to them + VectorCopy( startpos, tent->s.origin2 ); + SnapVector(tent->s.origin2); + tent->s.eventParm = DirToByte( tr.plane.normal ); + + return; + } + else + { + + // Bounce off the surface just a little + VectorMA(ent->movedir, -1.25*dot, tr.plane.normal, ent->movedir); + VectorNormalize(ent->movedir); + + // Make sure we store a next think time, else the effect could stick around forever... + ent->nextthink = level.time + DN_ALT_THINK_TIME; + + if (!recursion) + { // NOTE RECURSION HERE. + recursion=qtrue; + DreadnoughtBurstThink(ent); + recursion=qfalse; + } + + return; + } + + } + + VectorCopy(tr.endpos, dest); + } + + // Didn't hit anything forward. Try some side vectors. + + // Get the perp vector (okay, only in 2D) to find a right or left (random)-pointing perpendicular vector to the facing. + if (irandom(0,1)) + { // Right vector + perp[0] = ent->movedir[1]; + perp[1] = -ent->movedir[0]; + perp[2] = ent->movedir[2]; + } + else + { // Left vector + perp[0] = -ent->movedir[1]; + perp[1] = ent->movedir[0]; + perp[2] = ent->movedir[2]; + } + + // Search a random interval from the side arc + VectorMA(endpos, DN_SIDE_DIST, perp, endpos); + endpos[0] += flrandom(-DN_RAND_DEV, DN_RAND_DEV); + endpos[1] += flrandom(-DN_RAND_DEV, DN_RAND_DEV); + endpos[2] += flrandom(-DN_RAND_DEV*0.5, DN_RAND_DEV*0.5); + + trap_Trace (&tr, startpos, mins, maxs, endpos, source, MASK_SHOT ); + traceEnt = &g_entities[ tr.entityNum ]; + // did we hit the holdable shield? + if (traceEnt->classname && !Q_stricmp(traceEnt->classname, "holdable_shield")) + { + // yes. We are done. + VectorCopy(ent->s.origin, ent->s.origin2); + VectorCopy(endpos, ent->s.origin); + SnapVector(ent->s.origin); + SnapVector(ent->s.origin2); + + ent->nextthink = level.time + 100; + + ent->think = G_FreeEntity; + tent = G_TempEntity( tr.endpos, EV_DREADNOUGHT_MISS ); + // Stash origins, etc. so that the effects can have access to them + VectorCopy( startpos, tent->s.origin2 ); + SnapVector(tent->s.origin2); + tent->s.eventParm = DirToByte( tr.plane.normal ); + + return; + } + if (traceEnt->takedamage) + { + ent->target_ent = traceEnt; + VectorCopy(ent->s.origin, ent->s.origin2); + SnapVector(ent->s.origin); + SnapVector(ent->s.origin2); + VectorCopy(traceEnt->r.currentOrigin, ent->s.origin); + trap_LinkEntity(ent); + VectorNormalize(ent->movedir); + ent->nextthink = level.time + DN_ALT_THINK_TIME; + G_Damage( traceEnt, ent, &g_entities[ent->r.ownerNum], forward, tr.endpos, ent->damage, + DAMAGE_NOT_ARMOR_PIERCING, MOD_DREADNOUGHT_ALT); + + // log hit + /*if (ent->client) + { + ent->client->ps.persistant[PERS_ACCURACY_HITS]++; + }*/ + // NOTE Send this as a hit effect once we have one... + G_Sound( traceEnt, G_SoundIndex( SOUND_DIR "dreadnought/dn_althit.wav")); + + return; + } + + // Search a random interval in the opposite direction + VectorMA(endpos, -2.0*DN_SIDE_DIST, perp, endpos); + endpos[0] += flrandom(-DN_RAND_DEV, DN_RAND_DEV); + endpos[1] += flrandom(-DN_RAND_DEV, DN_RAND_DEV); + endpos[2] += flrandom(-DN_RAND_DEV*0.5, DN_RAND_DEV*0.5); + + trap_Trace (&tr, startpos, mins, maxs, endpos, source, MASK_SHOT ); + traceEnt = &g_entities[ tr.entityNum ]; + // did we hit the holdable shield? + if (traceEnt->classname && !Q_stricmp(traceEnt->classname, "holdable_shield")) + { + VectorCopy(ent->s.origin, ent->s.origin2); + VectorCopy(endpos, ent->s.origin); + SnapVector(ent->s.origin); + SnapVector(ent->s.origin2); + + ent->nextthink = level.time + 100; + + // yes. We are done. + ent->think = G_FreeEntity; + + tent = G_TempEntity( tr.endpos, EV_DREADNOUGHT_MISS ); + // Stash origins, etc. so that the effects can have access to them + VectorCopy( startpos, tent->s.origin2 ); + SnapVector(tent->s.origin2); + tent->s.eventParm = DirToByte( tr.plane.normal ); + + return; + } + if (traceEnt->takedamage) + { + ent->target_ent = traceEnt; + VectorCopy(ent->s.origin, ent->s.origin2); + SnapVector(ent->s.origin); + SnapVector(ent->s.origin2); + VectorCopy(traceEnt->r.currentOrigin, ent->s.origin); + trap_LinkEntity(ent); + VectorNormalize(ent->movedir); + ent->nextthink = level.time + DN_ALT_THINK_TIME; + G_Damage( traceEnt, ent, &g_entities[ent->r.ownerNum], forward, tr.endpos, ent->damage, + DAMAGE_NOT_ARMOR_PIERCING, MOD_DREADNOUGHT_ALT); + // log hit + /*if (ent->client) + { + ent->client->ps.persistant[PERS_ACCURACY_HITS]++; + }*/ + return; + } + + // We didn't find anything, so move the entity to the middle destination. + ent->target_ent = NULL; + VectorCopy(ent->s.origin, ent->s.origin2); + VectorCopy(dest, ent->s.origin); + VectorCopy(dest, ent->s.pos.trBase); + SnapVector(ent->s.origin2); + trap_LinkEntity(ent); + ent->nextthink = level.time + DN_ALT_THINK_TIME; + + return; +} + + +//--------------------------------------------------------- +void WP_FireDreadnoughtBurst( gentity_t *ent ) +//--------------------------------------------------------- +{ + gentity_t *bolt; + vec3_t dir, start; + + VectorCopy( forward, dir ); + VectorCopy( muzzle, start ); + + bolt = G_Spawn(); + bolt->classname = "dn_projectile"; + + bolt->nextthink = level.time + 200; + bolt->think = DreadnoughtBurstThink; + + bolt->s.eType = ET_ALT_MISSILE; + bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN; + bolt->s.weapon = WP_13; + bolt->r.ownerNum = ent->s.number; + bolt->parent = ent; + bolt->damage = DREADNOUGHT_ALTDAMAGE*DMG_VAR*s_quadFactor; + bolt->splashDamage = 0; + bolt->splashRadius = 0; + bolt->methodOfDeath = MOD_DREADNOUGHT_ALT; + bolt->clipmask = MASK_SHOT; + + bolt->s.pos.trType = TR_LINEAR; + bolt->s.pos.trTime = level.time; + VectorCopy( start, bolt->s.pos.trBase ); + VectorCopy( start, bolt->s.origin); + SnapVector(bolt->s.pos.trBase); + SnapVector(bolt->s.origin); + + VectorCopy( forward, bolt->movedir); + + SnapVector( bolt->s.pos.trDelta ); // save net bandwidth + VectorCopy( start, bolt->r.currentOrigin ); + VectorCopy( start, bolt->pos1 ); + VectorCopy( start, bolt->pos2 ); + + DreadnoughtBurstThink(bolt); +} + +//--------------------------------------------------------- +void WP_FireDreadnought( gentity_t *ent, qboolean alt_fire ) +//--------------------------------------------------------- +{ + // This was moved out of the FireWeapon switch statement below to keep things more consistent + if ( alt_fire ) + { + WP_FireDreadnoughtBurst( ent ); + } + else + { + WP_FireDreadnoughtBeam( ent ); + } + + G_LogWeaponFire(ent->s.number, WP_13); +} + + +//====================================================================== + +#define BORG_PROJECTILE_SIZE 8 +#define BORG_PROJ_VELOCITY 1000 + +void WP_FireBorgTaser( gentity_t *ent ) +{ + trace_t tr; + vec3_t end, d_dir; + gentity_t *tent = 0; + gentity_t *traceEnt = NULL; + + VectorMA (muzzle, MAXRANGE_IMOD, forward, end); + + trap_Trace (&tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT ); + traceEnt = &g_entities[ tr.entityNum ]; + + if ( traceEnt->takedamage ) + { + LogAccuracyHit( traceEnt, ent ); + + //For knockback - send them up in air + VectorCopy( forward, d_dir ); + if ( d_dir[2] < 0.30f ) + { + d_dir[2] = 0.30f; + } + VectorNormalize( d_dir ); + + G_Damage( traceEnt, ent, ent, forward, tr.endpos, BORG_TASER_DAMAGE * s_quadFactor, 0, MOD_BORG_ALT ); + } + + VectorMA (muzzle, 2, forward, muzzle); + tent = G_TempEntity( tr.endpos, EV_BORG_ALT_WEAPON ); + + // Stash origins, etc. so the effect can have access to them + VectorCopy( muzzle, tent->s.origin2 ); + SnapVector( tent->s.origin2 ); // save net bandwidth + tent->s.eventParm = DirToByte( tr.plane.normal ); + tent->s.weapon = ent->s.weapon; +} + + +void WP_FireBorgProjectile( gentity_t *ent, vec3_t start ) +//--------------------------------------------------------- +{ + gentity_t *bolt; + + bolt = G_Spawn(); + + bolt->classname = "borg_proj"; + bolt->nextthink = level.time + 10000; + bolt->think = G_FreeEntity; + bolt->s.eType = ET_MISSILE; + bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN; + bolt->s.weapon = WP_11; + bolt->r.ownerNum = ent->s.number; + bolt->parent = ent; + + bolt->damage = BORG_PROJ_DAMAGE * DMG_VAR * s_quadFactor; + bolt->splashDamage = 0; + bolt->splashRadius = 0; + bolt->methodOfDeath = MOD_BORG; + bolt->clipmask = MASK_SHOT; + + // Set the size of the missile up + VectorSet(bolt->r.maxs, BORG_PROJECTILE_SIZE, BORG_PROJECTILE_SIZE, BORG_PROJECTILE_SIZE); + VectorScale( bolt->r.maxs, -1, bolt->r.mins ); + + bolt->s.pos.trType = TR_LINEAR; + bolt->s.pos.trTime = level.time; // move a bit on the very first frame + VectorCopy( start, bolt->s.pos.trBase ); + SnapVector( bolt->s.pos.trBase ); // save net bandwidth + VectorScale( forward, BORG_PROJ_VELOCITY, bolt->s.pos.trDelta ); + SnapVector( bolt->s.pos.trDelta ); // save net bandwidth + VectorCopy( start, bolt->r.currentOrigin); +} + +void WP_Assimilate( gentity_t *ent, qboolean alt_fire ) +{//MCG: hacked this in for now for testing the rules + gentity_t *tr_ent; + trace_t tr; + vec3_t end; + float range; + + if ( ent->s.number == borgQueenClientNum ) + { + range = 32; + } + else + { + range = 64; + } + VectorMA( muzzle, range, forward, end ); + + trap_Trace ( &tr, muzzle, vec3_origin, vec3_origin, end, ent->s.number, MASK_SHOT ); + + if ( tr.entityNum >= ENTITYNUM_WORLD ) + { + return; + } + + tr_ent = &g_entities[tr.entityNum]; + + if ( tr_ent && tr_ent->client && tr_ent->health > 0 && ent->client && ent->client->sess.sessionTeam != tr_ent->client->sess.sessionTeam ) + { + if ( ent->s.number == borgQueenClientNum ) + {//Borg queen assimilates with one hit + tr_ent->health = 0; + player_die( tr_ent, ent, ent, 100, MOD_ASSIMILATE ); + //G_Damage( tr_ent, ent, ent, forward, tr.endpos, 50, DAMAGE_NO_ARMOR|DAMAGE_NO_INVULNERABILITY, MOD_ASSIMILATE ); + } + else + { + G_Damage( tr_ent, ent, ent, forward, tr.endpos, 10, DAMAGE_NO_ARMOR|DAMAGE_NO_INVULNERABILITY, MOD_ASSIMILATE ); + } + } +} + +/* +=============== +RPG-X Fire Engineer Tool +By: RedTechie +=============== +*/ +/*void WP_NEUTRINO_PROBE( gentity_t *ent, qboolean alt_fire ){ + gentity_t *target; //Target entity + trace_t trace; //Used to trace target + vec3_t src, dest, vf; //Used to find target + + if(!ent){ + return; + } + //if(ent->parent->client->sess.sessionClass == PC_ADMIN){ + if(alt_fire){ + return; + }else{ + ////////////////////////////////////// + //All this code below finds the target entity + + VectorCopy( ent->r.currentOrigin, src ); + src[2] += ent->client->ps.viewheight; + + AngleVectors( ent->client->ps.viewangles, vf, NULL, NULL ); + + //extend to find end of use trace + VectorMA( src, -6, vf, src );//in case we're inside something? + VectorMA( src, 1340, vf, dest );//128+6 + + //Trace ahead to find a valid target + trap_Trace( &trace, src, vec3_origin, vec3_origin, dest, ent->s.number, CONTENTS_TRIGGER ); + + if ( trace.fraction == 1.0f || trace.entityNum < 0 ) + { + trap_SendConsoleCommand( EXEC_APPEND, va("echo No target in range to kick.") ); + return; + } + + target = &g_entities[trace.entityNum]; + + //////////////////////////////// + + //lets delete it + if(target){ + G_FreeEntity( target ); + } + } + //} +}*/ + +/* +---------------------------------------------- + TETRION +---------------------------------------------- +*/ + +#define TETRION_SPREAD 275 +#define NUM_TETRION_SHOTS 3 + +#define TETRION_ALT_VELOCITY 500000 //RPG-X: J2J - increased velocity to 1/2 million units/second +#define TETRION_ALT_SIZE 6 + +#define MAXRANGE_TETRION 5000000 //RPG-X: J2J - increased range to 5 million units + +typedef struct tetrionHit_s +{ + gentity_t *ent; + vec3_t pos; +} tetrionHit_t; + +// provide the center of the circle, a normal out from it (normalized, please), and the radius. +//out will then become a random position on the radius of the circle. +void fxRandCircumferencePos(vec3_t center, vec3_t normal, float radius, vec3_t out) +{ + float rnd = flrandom(0, 2*M_PI); + float s = sin(rnd); + float c = cos(rnd); + vec3_t vTemp, radialX, radialY; + + vTemp[0]=0; + vTemp[1]=0; + vTemp[2]=-1; + CrossProduct(normal, vTemp, radialX); + CrossProduct(normal, radialX, radialY); + VectorScale(radialX, radius, radialX); + VectorScale(radialY, radius, radialY); + VectorMA(center, s, radialX, out); + VectorMA(out, c, radialY, out); +} +#define NUM_TETRION_BULLETS 3 +//--------------------------------------------------------- +void FireTetrionBullet( gentity_t *ent, vec3_t start, vec3_t dir ) +//--------------------------------------------------------- +{ + gentity_t *tent = NULL; + trace_t tr; + vec3_t end, lup = {0,0,1}, lright; // , zero = {0,0,0}; + int i = 0, j = 0; + qboolean bHitAlready = qfalse; + int numHits = 0; + tetrionHit_t hitEnts[NUM_TETRION_BULLETS]; + + + vec3_t new_start, radial, start2, spreadFwd; + float firingRadius = 6, minDeviation = 0.95, maxDeviation = 1.1; + + for (i = 0; i < NUM_TETRION_BULLETS; i++) + { + hitEnts[i].ent = NULL; + } + // create our message-entity with the firing position for an origin + tent = G_TempEntity(muzzle, EV_TETRION); + // stash our firing direction in the message also + VectorCopy(forward, tent->s.angles2); + VectorShort(tent->s.angles2); + + // now do the damage. we're going to fake three separate bullets here by doing three + //traces and splitting two or three hits worth of dmg between whatever the traces hit. + CrossProduct(forward, lup, lright); + CrossProduct(lright, forward, up); // get a "real" up + + for (i = 0; i < NUM_TETRION_BULLETS; i++) + { + // determine new firing position + fxRandCircumferencePos(start, forward, firingRadius, new_start); + VectorSubtract(new_start, start, radial); + VectorMA(start, 10, forward, start2); + VectorMA(start2, flrandom(minDeviation, maxDeviation), radial, start2); + VectorSubtract(start2, new_start, spreadFwd); + VectorNormalize(spreadFwd); + // determine new end position for this bullet. give the endpoint some spread, too. + VectorMA(new_start, MAXRANGE_TETRION, spreadFwd, end); + trap_Trace ( &tr, new_start, NULL, NULL, end, ent->s.number, MASK_SHOT); + if ((tr.entityNum < MAX_GENTITIES) && (tr.entityNum != ENTITYNUM_WORLD)) + { + bHitAlready = qfalse; + for (j = 0; j < numHits; j++) + { + if (hitEnts[j].ent == &g_entities[ tr.entityNum ]) + { + // already hit this ent + bHitAlready = qtrue; + break; + } + } + if (!bHitAlready) + { + hitEnts[numHits].ent = &g_entities[ tr.entityNum ]; + VectorCopy(tr.endpos, hitEnts[numHits].pos); + numHits++; + } + } + } + if (numHits) + { + // determine damage (2 or 3 bullets) + float totalDmg = (float)(irandom(2,3)*TETRION_DAMAGE*s_quadFactor), dmgPerHit = 0; + + dmgPerHit = (int)(totalDmg/(float)numHits); + for (i = 0; i < numHits; i++) + { + if (hitEnts[i].ent->takedamage) + { + G_Damage( hitEnts[i].ent, ent, ent, forward, hitEnts[i].pos, dmgPerHit, + DAMAGE_ARMOR_PIERCING|DAMAGE_NO_KNOCKBACK, MOD_TETRION ); + } + // log hit + /*if (ent->client) + { + ent->client->ps.persistant[PERS_ACCURACY_HITS]++; + }*/ + } + } +} + +//--------------------------------------------------------- +void FireTetrionProjectile( gentity_t *ent, vec3_t start, vec3_t dir ) +//--------------------------------------------------------- +{// Projectile that /*bouncesoff surfaces but does not have gravity + gentity_t *bolt; + + bolt = G_Spawn(); + bolt->classname = "tetrion_projectile"; + bolt->nextthink = level.time + 2000; + bolt->think = G_FreeEntity; + + bolt->s.eType = ET_ALT_MISSILE; + bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN; + //bolt->s.eFlags |= EF_BOUNCE; //RPG-X: J2J - Dont bounce anymore + //bolt->count = random() > 0.75f ? 3 : 4; //RPG-X: J2J - Number of bounces + + //RPG-X: J2J - Not sure about alt size, may need tweaking + VectorSet(bolt->r.mins, -TETRION_ALT_SIZE, -TETRION_ALT_SIZE, -TETRION_ALT_SIZE); + VectorSet(bolt->r.maxs, TETRION_ALT_SIZE, TETRION_ALT_SIZE, TETRION_ALT_SIZE); + + bolt->s.weapon = WP_7; + bolt->r.ownerNum = ent->s.number; + bolt->parent = ent; + bolt->damage = 300; //RPG-X: RedTechie - Use to be TETRION_ALT_DAMAGE*DMG_VAR*s_quadFactor; + bolt->splashDamage = 0; + bolt->splashRadius = 0; + bolt->methodOfDeath = MOD_TETRION_ALT; + bolt->clipmask = CONTENTS_BODY; //MASK_SHOT; MASK_ONLYPLAYER //RPG-X: J2J - Goes through all objects except players and corpses + + bolt->s.pos.trType = TR_LINEAR; + bolt->s.pos.trTime = level.time; // move a bit on the very first frame + VectorCopy( start, bolt->s.pos.trBase ); + SnapVector( bolt->s.pos.trBase ); // save net bandwidth + VectorScale( dir, TETRION_ALT_VELOCITY, bolt->s.pos.trDelta ); + SnapVector( bolt->s.pos.trDelta ); // save net bandwidth + VectorCopy (start, bolt->r.currentOrigin); +} + + + + +void WP_FireBorgWeapon( gentity_t *ent, qboolean alt_fire ) +//--------------------------------------------------------- +{ + if ( alt_fire ) + { + WP_FireBorgTaser( ent ); + } + else + { + WP_FireBorgProjectile( ent, muzzle ); + } + + G_LogWeaponFire( ent->s.number, WP_11 ); +} + +//TiM +// Alt-fire... +//--------------------------------------------------------- +/*void FireScavengerGrenade( gentity_t *ent, vec3_t start, vec3_t dir ) +//--------------------------------------------------------- +{ + gentity_t *grenade; + + grenade = G_Spawn(); + + grenade->classname = "scav_grenade"; + grenade->nextthink = level.time + 9000; + grenade->think = G_FreeEntity; + grenade->s.eType = ET_ALT_MISSILE; + grenade->s.weapon = WP_4; + grenade->r.ownerNum = ent->s.number; + grenade->parent = ent; + grenade->damage = SCAV_ALT_DAMAGE*DMG_VAR*s_quadFactor; + grenade->splashDamage = SCAV_ALT_SPLASH_DAM*s_quadFactor; + grenade->splashRadius = SCAV_ALT_SPLASH_RAD;// *s_quadFactor; + grenade->methodOfDeath = MOD_SCAVENGER_ALT; + grenade->splashMethodOfDeath = MOD_SCAVENGER_ALT_SPLASH; + grenade->clipmask = MASK_SHOT; + grenade->s.eFlags |= EF_ALT_FIRING; + + // Set the size of the missile up + VectorSet(grenade->r.maxs, SCAV_ALT_SIZE, SCAV_ALT_SIZE, SCAV_ALT_SIZE); + VectorSet(grenade->r.mins, -SCAV_ALT_SIZE, -SCAV_ALT_SIZE, -SCAV_ALT_SIZE); + + grenade->s.pos.trType = TR_GRAVITY; + grenade->s.pos.trTime = level.time; // move a bit on the very first frame + + VectorCopy( start, grenade->s.pos.trBase ); + SnapVector( grenade->s.pos.trBase ); // save net bandwidth + VectorScale( dir, random() * 100 + SCAV_ALT_VELOCITY, grenade->s.pos.trDelta ); + + // Add a tad of upwards velocity to the shot. + grenade->s.pos.trDelta[2] += SCAV_ALT_UP_VELOCITY; + + // Add in half the player's velocity to the shot. + VectorMA(grenade->s.pos.trDelta, 0.5, ent->s.pos.trDelta, grenade->s.pos.trDelta); + + SnapVector( grenade->s.pos.trDelta ); // save net bandwidth + VectorCopy (start, grenade->r.currentOrigin); + VectorCopy (start, grenade->pos1); + VectorCopy (start, grenade->s.origin2); + SnapVector( grenade->s.origin2 ); // save net bandwidth +}*/ + +//TiM +//--------------------------------------------------------- +/*void WP_FireScavenger( gentity_t *ent, qboolean alt_fire ) +//--------------------------------------------------------- +{ + vec3_t dir, angles, temp_ang, temp_org; + vec3_t start; + float offset; + + VectorCopy( forward, dir ); + VectorCopy( muzzle, start ); + + if ( alt_fire ) + { + FireScavengerGrenade( ent, start, dir ); + } + else + { + vectoangles( dir, angles ); + VectorSet( temp_ang, angles[0] + (crandom() * SCAV_SPREAD), angles[1] + (crandom() * SCAV_SPREAD), angles[2] ); + AngleVectors( temp_ang, dir, NULL, NULL ); + + // try to make the shot alternate between barrels + offset = irandom(0, 1) * 2 + 1; + + // FIXME: These offsets really don't work like they should + VectorMA( start, offset, right, temp_org ); + VectorMA( temp_org, offset, up, temp_org ); + FireScavengerBullet( ent, temp_org, dir ); + } + + G_LogWeaponFire(ent->s.number, WP_4); +}*/ + +void FireSeeker( gentity_t *owner, gentity_t *target, vec3_t origin) +{ + vec3_t dir; + + VectorSubtract( target->r.currentOrigin, origin, dir); + VectorNormalize(dir); + + // for now I'm just using the scavenger bullet. + FireScavengerBullet( owner, origin, dir ); +} + +//TiM +//--------------------------------------------------------- +void FireScavengerBullet( gentity_t *ent, vec3_t start, vec3_t dir ) +//--------------------------------------------------------- +{ + gentity_t *bolt; + + bolt = G_Spawn(); + + bolt->classname = "scav_proj"; + bolt->nextthink = level.time + 10000; + bolt->think = G_FreeEntity; + bolt->s.eType = ET_MISSILE; + bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN; + //bolt->s.weapon = WP_4; + bolt->s.weapon = WP_10; //TiM + bolt->r.ownerNum = ent->s.number; + bolt->parent = ent; + +//fixme - remove + { + // Flags effect as being the full beefy version for the player + bolt->count = 0; + } + + bolt->damage = SCAV_DAMAGE*DMG_VAR*s_quadFactor; + bolt->splashDamage = 0; + bolt->splashRadius = 0; + bolt->methodOfDeath = MOD_SCAVENGER; + bolt->clipmask = MASK_SHOT; + + // Set the size of the missile up + VectorSet(bolt->r.maxs, SCAV_SIZE, SCAV_SIZE, SCAV_SIZE); + VectorSet(bolt->r.mins, -SCAV_SIZE, -SCAV_SIZE, -SCAV_SIZE); + + bolt->s.pos.trType = TR_LINEAR; + bolt->s.pos.trTime = level.time - 10; // move a bit on the very first frame + VectorCopy( start, bolt->s.pos.trBase ); + SnapVector( bolt->s.pos.trBase ); // save net bandwidth + VectorScale( dir, SCAV_VELOCITY, bolt->s.pos.trDelta ); + SnapVector( bolt->s.pos.trDelta ); // save net bandwidth + VectorCopy( start, bolt->r.currentOrigin); +} + +/* +---------------------------------------------- + IMOD +---------------------------------------------- +*/ + +#define MAXRANGE_IMOD 4096 +#define MAX_RAIL_HITS 4 + +void IMODHit(qboolean alt_fire, gentity_t *traceEnt, gentity_t *ent, vec3_t d_dir, vec3_t endpos, vec3_t normal, + qboolean render_impact) +{ + gentity_t *tent = NULL; + int damage = IMOD_ALT_DAMAGE*DMG_VAR; + + if ( alt_fire ) + { + // send beam impact + if ( traceEnt && traceEnt->takedamage ) + { + G_Damage( traceEnt, ent, ent, d_dir, endpos, damage, DAMAGE_NO_ARMOR | DAMAGE_NO_INVULNERABILITY, MOD_IMOD_ALT); + if (render_impact) + { + tent = G_TempEntity( endpos, EV_IMOD_ALTFIRE_HIT ); + } + // log hit + /*if (ent->client) + { + ent->client->ps.persistant[PERS_ACCURACY_HITS]++; + }*/ + } + } + else + { + // send beam impact + if ( traceEnt && traceEnt->takedamage && rpg_imoddmg.integer != 0) + { + G_Damage( traceEnt, ent, ent, d_dir, endpos, damage, DAMAGE_NO_ARMOR | DAMAGE_NO_INVULNERABILITY, MOD_IMOD); + if (render_impact) + { + tent = G_TempEntity( endpos, EV_IMOD_HIT ); + } + // log hit + /*if (ent->client) + { + ent->client->ps.persistant[PERS_ACCURACY_HITS]++; + }*/ + } + } + if (tent) + { + tent->s.eventParm = DirToByte( normal ); + tent->s.weapon = ent->s.weapon; + VectorCopy( muzzle, tent->s.origin2 ); + SnapVector(tent->s.origin2); + } +} + +//--------------------------------------------------------- +/*void WP_FireIMOD ( gentity_t *ent, qboolean alt_fire ) +//--------------------------------------------------------- +{ + int i = 0; + int hits = 0; + int unlinked = 0; + gentity_t *unlinkedEntities[MAX_RAIL_HITS]; + + trace_t tr; + vec3_t end, d_dir; + gentity_t *tent = 0; + gentity_t *traceEnt = NULL; + qboolean render_impact; + + VectorMA (muzzle, MAXRANGE_IMOD, forward, end); + + // trace only against the solids, so the railgun will go through people + do + { + trap_Trace (&tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT ); + traceEnt = &g_entities[ tr.entityNum ]; + if ( tr.surfaceFlags & SURF_NOIMPACT ) + { // If the beam hit the skybox, etc. it would look foolish to add in an explosion + render_impact = qfalse; + } else + { + render_impact = qtrue; + } + if ( traceEnt->takedamage ) + { + if( LogAccuracyHit( traceEnt, ent ) ) + { + hits++; + } + //For knockback - send them up in air + VectorCopy(forward, d_dir); + if(d_dir[2] < 0.30f) + { + d_dir[2] = 0.30f; + } + VectorNormalize(d_dir); + // do the damage and send an impact effect + IMODHit(alt_fire, traceEnt, ent, d_dir, tr.endpos, tr.plane.normal, qtrue); + + // give the shooter a reward sound if they have made two sniper hits in a row + // check for "impressive" reward sound + // Note that hitting two people in a line warrants an "impressive" as well... + if (traceEnt->client) + { + if (((g_gametype.integer >= GT_TEAM) && (ent->client->ps.persistant[PERS_TEAM] != traceEnt->client->ps.persistant[PERS_TEAM])) + || (g_gametype.integer < GT_TEAM)) + { + if (alt_fire) + { + ent->client->accurateCount++; + if ( ent->client->accurateCount >= 2 ) + { + ent->client->accurateCount -= 2; + ent->client->ps.persistant[PERS_REWARD_COUNT]++; + ent->client->ps.persistant[PERS_REWARD] = REWARD_IMPRESSIVE; + ent->client->ps.persistant[PERS_IMPRESSIVE_COUNT]++; + // add the sprite over the player's head + ent->client->ps.eFlags &= ~EF_AWARD_MASK; + ent->client->ps.eFlags |= EF_AWARD_IMPRESSIVE; + ent->client->rewardTime = level.time + REWARD_SPRITE_TIME; + } // End of brace + } + } + } + } + else + { // send an impact effect + IMODHit(alt_fire, traceEnt, ent, d_dir, tr.endpos, tr.plane.normal, render_impact); + } + if ( tr.contents & CONTENTS_SOLID ) + { + break; // we hit something solid enough to stop the beam + } + // unlink this entity, so the next trace will go past it + trap_UnlinkEntity( traceEnt ); + unlinkedEntities[unlinked] = traceEnt; + unlinked++; + } while ( unlinked < MAX_RAIL_HITS ); + + // link back in any entities we unlinked + for ( i = 0 ; i < unlinked ; i++ ) + { + trap_LinkEntity( unlinkedEntities[i] ); + } + + // With endcapping on, the beam is actually longer than what the length parm in FX_AddLine for this + // effect specifies..so move it out so it doesn't clip into the gun so much + if ( alt_fire ) + VectorMA (muzzle, 10, forward, muzzle); + else + VectorMA (muzzle, 2, forward, muzzle); + + // Create the events that will add in the necessary effects + if ( alt_fire ) + { + tent = G_TempEntity( tr.endpos, EV_IMOD_ALTFIRE ); + } + else + { + tent = G_TempEntity( tr.endpos, EV_IMOD ); + } + + // Stash origins, etc. so the effect can have access to them + VectorCopy( muzzle, tent->s.origin2 ); + SnapVector( tent->s.origin2 ); // save net bandwidth + if ( render_impact ) + { + tent->s.eventParm = DirToByte( tr.plane.normal ); + tent->s.weapon = ent->s.weapon; + } + + G_LogWeaponFire(ent->s.number, WP_1); + //G_LogWeaponFire(ent->s.number, WP_1); +}*/ + +#define SEEKER_RADIUS 500 +qboolean SeekerAcquiresTarget ( gentity_t *ent, vec3_t pos ) +{ + vec3_t seekerPos; + float angle; + int entityList[MAX_CLIENTS]; // targets within inital radius + int visibleTargets[MAX_CLIENTS]; // final filtered target list + int numListedEntities; + int i, e; + gentity_t *target; + vec3_t mins, maxs; + +// if (!irandom(0,2)) for now, it'll shoot every second it finds a target + { + angle = level.time/100.0f; + seekerPos[0] = ent->r.currentOrigin[0] + 18 * cos(angle); + seekerPos[1] = ent->r.currentOrigin[1] + 18 * sin(angle); + seekerPos[2] = ent->r.currentOrigin[2] + ent->client->ps.viewheight + 8 + (3*cos(level.time/150.0f)); + + for ( i = 0 ; i < 3 ; i++ ) + { + mins[i] = seekerPos[i] - SEEKER_RADIUS; + maxs[i] = seekerPos[i] + SEEKER_RADIUS; + } + + // get potential targets within radius + numListedEntities = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES ); + + i = 0; // reset counter + + for ( e = 0 ; e < numListedEntities ; e++ ) + { + target = &g_entities[entityList[ e ]]; + // seeker owner not a valid target + if (target == ent) + { + continue; + } + + // only players are valid targets + if (!target->classname || strcmp(target->classname, "player")) + { + continue; + } + + // teammates not valid targets + if (OnSameTeam(ent, target)) + { + continue; + } + + // don't shoot at dead things + if (target->health <= 0) + { + continue; + } + //RPG-X: RedTechie - Need to take this out causes bad crashes with entity shooter, shouldent be needed anyway with newer code + //target->beingfiredby = ent; + if( CanDamage (target, seekerPos) ) // visible target, so add it to the list + { + visibleTargets[i++] = entityList[e]; + } + } + + if (i) + { + // ok, now we know there are i visible targets. Pick one as the seeker's target + ent->enemy = &g_entities[visibleTargets[irandom(0,i-1)]]; + VectorCopy(seekerPos, pos); + return qtrue; + } + } + + return qfalse; +} diff --git a/stefgame.suo b/stefgame.suo index 6d75670..62be838 100644 Binary files a/stefgame.suo and b/stefgame.suo differ