codemp/game/w_force.c File Reference

#include "b_local.h"
#include "w_saber.h"
#include "ai_main.h"
#include "../ghoul2/G2.h"
#include "../namespace_begin.h"
#include "../namespace_end.h"

Go to the source code of this file.

Defines

#define METROID_JUMP   1
#define FORCE_VELOCITY_DAMAGE   0

Functions

void NPC_PlayConfusionSound (gentity_t *self)
void NPC_Jedi_PlayConfusionSound (gentity_t *self)
void NPC_UseResponse (gentity_t *self, gentity_t *user, qboolean useWhenDone)
void Jedi_Decloak (gentity_t *self)
qboolean BG_FullBodyTauntAnim (int anim)
int ForceShootDrain (gentity_t *self)
gentity_tG_PreDefSound (vec3_t org, int pdSound)
void WP_InitForcePowers (gentity_t *ent)
void WP_SpawnInitForcePowers (gentity_t *ent)
qboolean BG_InKnockDown (int anim)
int ForcePowerUsableOn (gentity_t *attacker, gentity_t *other, forcePowers_t forcePower)
qboolean WP_ForcePowerAvailable (gentity_t *self, forcePowers_t forcePower, int overrideAmt)
qboolean WP_ForcePowerInUse (gentity_t *self, forcePowers_t forcePower)
qboolean WP_ForcePowerUsable (gentity_t *self, forcePowers_t forcePower)
int WP_AbsorbConversion (gentity_t *attacked, int atdAbsLevel, gentity_t *attacker, int atPower, int atPowerLevel, int atForceSpent)
void WP_ForcePowerRegenerate (gentity_t *self, int overrideAmt)
void WP_ForcePowerStart (gentity_t *self, forcePowers_t forcePower, int overrideAmt)
void ForceHeal (gentity_t *self)
void WP_AddToClientBitflags (gentity_t *ent, int entNum)
void ForceTeamHeal (gentity_t *self)
void ForceTeamForceReplenish (gentity_t *self)
void ForceGrip (gentity_t *self)
void ForceSpeed (gentity_t *self, int forceDuration)
void ForceSeeing (gentity_t *self)
void ForceProtect (gentity_t *self)
void ForceAbsorb (gentity_t *self)
void ForceRage (gentity_t *self)
void ForceLightning (gentity_t *self)
void ForceLightningDamage (gentity_t *self, gentity_t *traceEnt, vec3_t dir, vec3_t impactPoint)
void ForceShootLightning (gentity_t *self)
void ForceDrain (gentity_t *self)
void ForceDrainDamage (gentity_t *self, gentity_t *traceEnt, vec3_t dir, vec3_t impactPoint)
void ForceJumpCharge (gentity_t *self, usercmd_t *ucmd)
int WP_GetVelocityForForceJump (gentity_t *self, vec3_t jumpVel, usercmd_t *ucmd)
void ForceJump (gentity_t *self, usercmd_t *ucmd)
void WP_AddAsMindtricked (forcedata_t *fd, int entNum)
qboolean ForceTelepathyCheckDirectNPCTarget (gentity_t *self, trace_t *tr, qboolean *tookPower)
void ForceTelepathy (gentity_t *self)
void GEntity_UseFunc (gentity_t *self, gentity_t *other, gentity_t *activator)
qboolean CanCounterThrow (gentity_t *self, gentity_t *thrower, qboolean pull)
qboolean G_InGetUpAnim (playerState_t *ps)
void G_LetGoOfWall (gentity_t *ent)
void Touch_Button (gentity_t *ent, gentity_t *other, trace_t *trace)
void ForceThrow (gentity_t *self, qboolean pull)
void WP_ForcePowerStop (gentity_t *self, forcePowers_t forcePower)
void DoGripAction (gentity_t *self, forcePowers_t forcePower)
qboolean G_IsMindTricked (forcedata_t *fd, int client)
int WP_DoSpecificPower (gentity_t *self, usercmd_t *ucmd, forcePowers_t forcepower)
void FindGenericEnemyIndex (gentity_t *self)
void SeekerDroneUpdate (gentity_t *self)
void HolocronUpdate (gentity_t *self)
void JediMasterUpdate (gentity_t *self)
qboolean WP_HasForcePowers (const playerState_t *ps)
qboolean G_SpecialRollGetup (gentity_t *self)
void WP_ForcePowersUpdate (gentity_t *self, usercmd_t *ucmd)
qboolean Jedi_DodgeEvasion (gentity_t *self, gentity_t *shooter, trace_t *tr, int hitLoc)

Variables

vmCvar_t g_saberRestrictForce
bot_state_tbotstates [MAX_CLIENTS]
int speedLoopSound = 0
int rageLoopSound = 0
int protectLoopSound = 0
int absorbLoopSound = 0
int seeLoopSound = 0
int ysalamiriLoopSound = 0
const int forcePowerMinRank [NUM_FORCE_POWER_LEVELS][NUM_FORCE_POWERS]
const int mindTrickTime [NUM_FORCE_POWER_LEVELS]
float forcePushPullRadius [NUM_FORCE_POWER_LEVELS]
int g_LastFrameTime
int g_TimeSinceLastFrame


Define Documentation

#define FORCE_VELOCITY_DAMAGE   0
 

Definition at line 36 of file w_force.c.

#define METROID_JUMP   1
 

Definition at line 7 of file w_force.c.


Function Documentation

qboolean BG_FullBodyTauntAnim int  anim  ) 
 

Definition at line 1538 of file bg_panimate.c.

References BOTH_BOW, BOTH_DUAL_TAUNT, BOTH_GESTURE1, BOTH_MEDITATE, BOTH_SHOWOFF_DUAL, BOTH_SHOWOFF_FAST, BOTH_SHOWOFF_MEDIUM, BOTH_SHOWOFF_STAFF, BOTH_SHOWOFF_STRONG, BOTH_STAFF_TAUNT, BOTH_VICTORY_DUAL, BOTH_VICTORY_FAST, BOTH_VICTORY_MEDIUM, BOTH_VICTORY_STAFF, BOTH_VICTORY_STRONG, qboolean, qfalse, and qtrue.

Referenced by PmoveSingle(), and WP_ForcePowerStart().

01539 {
01540         switch ( anim )
01541         {
01542         case BOTH_GESTURE1:
01543         case BOTH_DUAL_TAUNT:
01544         case BOTH_STAFF_TAUNT:
01545         case BOTH_BOW:
01546         case BOTH_MEDITATE:
01547         case BOTH_SHOWOFF_FAST:
01548         case BOTH_SHOWOFF_MEDIUM:
01549         case BOTH_SHOWOFF_STRONG:
01550         case BOTH_SHOWOFF_DUAL:
01551         case BOTH_SHOWOFF_STAFF:
01552         case BOTH_VICTORY_FAST:
01553         case BOTH_VICTORY_MEDIUM:
01554         case BOTH_VICTORY_STRONG:
01555         case BOTH_VICTORY_DUAL:
01556         case BOTH_VICTORY_STAFF:
01557                 return qtrue;
01558                 break;
01559         }
01560         return qfalse;
01561 }

qboolean BG_InKnockDown int  anim  ) 
 

Definition at line 8526 of file bg_pmove.c.

08527 {
08528         switch ( (anim) )
08529         {
08530         case BOTH_KNOCKDOWN1:
08531         case BOTH_KNOCKDOWN2:
08532         case BOTH_KNOCKDOWN3:
08533         case BOTH_KNOCKDOWN4:
08534         case BOTH_KNOCKDOWN5:
08535                 return qtrue;
08536                 break;
08537         case BOTH_GETUP1:
08538         case BOTH_GETUP2:
08539         case BOTH_GETUP3:
08540         case BOTH_GETUP4:
08541         case BOTH_GETUP5:
08542         case BOTH_FORCE_GETUP_F1:
08543         case BOTH_FORCE_GETUP_F2:
08544         case BOTH_FORCE_GETUP_B1:
08545         case BOTH_FORCE_GETUP_B2:
08546         case BOTH_FORCE_GETUP_B3:
08547         case BOTH_FORCE_GETUP_B4:
08548         case BOTH_FORCE_GETUP_B5:
08549         case BOTH_GETUP_BROLL_B:
08550         case BOTH_GETUP_BROLL_F:
08551         case BOTH_GETUP_BROLL_L:
08552         case BOTH_GETUP_BROLL_R:
08553         case BOTH_GETUP_FROLL_B:
08554         case BOTH_GETUP_FROLL_F:
08555         case BOTH_GETUP_FROLL_L:
08556         case BOTH_GETUP_FROLL_R:
08557                 return qtrue;
08558                 break;
08559         }
08560         return qfalse;
08561 }

qboolean CanCounterThrow gentity_t self,
gentity_t thrower,
qboolean  pull
 

Definition at line 2900 of file w_force.c.

References AngleSubtract(), gentity_s::client, ENTITYNUM_NONE, playerState_s::forceHandExtend, FP_PULL, FP_PUSH, g_gametype, gentity_t, playerState_s::groundEntityNum, GT_SIEGE, HANDEXTEND_NONE, gentity_s::health, vmCvar_t::integer, level, playerState_s::origin, playerState_s::powerups, gclient_s::ps, PW_DISINT_4, qboolean, level_locals_t::time, vec3_t, vectoangles(), VectorSubtract, playerState_s::viewangles, WEAPON_CHARGING, WEAPON_CHARGING_ALT, playerState_s::weaponstate, playerState_s::weaponTime, WP_ForcePowerUsable(), and YAW.

Referenced by ForceThrow().

02901 {
02902         int powerUse = 0;
02903 
02904         if (self->client->ps.forceHandExtend != HANDEXTEND_NONE)
02905         {
02906                 return 0;
02907         }
02908 
02909         if (self->client->ps.weaponTime > 0)
02910         {
02911                 return 0;
02912         }
02913 
02914         if ( self->health <= 0 )
02915         {
02916                 return 0;
02917         }
02918 
02919         if ( self->client->ps.powerups[PW_DISINT_4] > level.time )
02920         {
02921                 return 0;
02922         }
02923 
02924         if (self->client->ps.weaponstate == WEAPON_CHARGING ||
02925                 self->client->ps.weaponstate == WEAPON_CHARGING_ALT)
02926         { //don't autodefend when charging a weapon
02927                 return 0;
02928         }
02929 
02930         if (g_gametype.integer == GT_SIEGE &&
02931                 pull &&
02932                 thrower && thrower->client)
02933         { //in siege, pull will affect people if they are not facing you, so they can't run away so much
02934                 vec3_t d;
02935                 float a;
02936 
02937         VectorSubtract(thrower->client->ps.origin, self->client->ps.origin, d);
02938                 vectoangles(d, d);
02939 
02940         a = AngleSubtract(d[YAW], self->client->ps.viewangles[YAW]);
02941 
02942                 if (a > 60.0f || a < -60.0f)
02943                 { //if facing more than 60 degrees away they cannot defend
02944                         return 0;
02945                 }
02946         }
02947 
02948         if (pull)
02949         {
02950                 powerUse = FP_PULL;
02951         }
02952         else
02953         {
02954                 powerUse = FP_PUSH;
02955         }
02956 
02957         if ( !WP_ForcePowerUsable( self, powerUse ) )
02958         {
02959                 return 0;
02960         }
02961 
02962         if (self->client->ps.groundEntityNum == ENTITYNUM_NONE)
02963         { //you cannot counter a push/pull if you're in the air
02964                 return 0;
02965         }
02966 
02967         return 1;
02968 }

void DoGripAction gentity_t self,
forcePowers_t  forcePower
 

Definition at line 3945 of file w_force.c.

References AngleVectors(), CHAN_VOICE, gentity_s::client, DAMAGE_NO_ARMOR, gclient_s::dangerTime, EF_INVULNERABLE, playerState_s::eFlags, trace_t::entityNum, ENTITYNUM_NONE, playerState_s::fd, FORCE_LEVEL_1, FORCE_LEVEL_2, FORCE_LEVEL_3, forcedata_s::forceGripBeingGripped, playerState_s::forceGripChangeMovetype, forcedata_s::forceGripDamageDebounceTime, forcedata_s::forceGripEntityNum, playerState_s::forceGripMoveInterval, forcedata_s::forceGripStarted, playerState_s::forceHandExtend, playerState_s::forceHandExtendTime, forcedata_s::forcePowerDebounce, forcedata_s::forcePowerLevel, forcePowerNeeded, forcePowers_t, forcedata_s::forcePowersActive, ForcePowerUsableOn(), FP_ABSORB, FP_GRIP, trace_t::fraction, G_Damage(), g_entities, G_EntitySound(), G_SoundIndex(), gentity_t, HANDEXTEND_CHOKE, gentity_s::health, InFront(), gentity_s::inuse, gclient_s::invulnerableTimer, Jetpack_Off(), level, MASK_PLAYERSOLID, MAX_GRIP_DISTANCE, MOD_FORCE_DARK, NULL, entityState_s::number, playerState_s::origin, playerState_s::otherKiller, playerState_s::otherKillerDebounceTime, playerState_s::otherKillerTime, PM_FLOAT, PM_NORMAL, gclient_s::ps, Q_irand(), gentity_s::s, level_locals_t::time, trap_Trace(), va(), vec3_t, VectorCopy, VectorNormalize(), VectorSubtract, playerState_s::velocity, playerState_s::viewangles, WP_AbsorbConversion(), and WP_ForcePowerStop().

03946 {
03947         gentity_t *gripEnt;
03948         int gripLevel = 0;
03949         trace_t tr;
03950         vec3_t a;
03951         vec3_t fwd, fwd_o, start_o, nvel;
03952 
03953         self->client->dangerTime = level.time;
03954         self->client->ps.eFlags &= ~EF_INVULNERABLE;
03955         self->client->invulnerableTimer = 0;
03956 
03957         gripEnt = &g_entities[self->client->ps.fd.forceGripEntityNum];
03958 
03959         if (!gripEnt || !gripEnt->client || !gripEnt->inuse || gripEnt->health < 1 || !ForcePowerUsableOn(self, gripEnt, FP_GRIP))
03960         {
03961                 WP_ForcePowerStop(self, forcePower);
03962                 self->client->ps.fd.forceGripEntityNum = ENTITYNUM_NONE;
03963 
03964                 if (gripEnt && gripEnt->client && gripEnt->inuse)
03965                 {
03966                         gripEnt->client->ps.forceGripChangeMovetype = PM_NORMAL;
03967                 }
03968                 return;
03969         }
03970 
03971         VectorSubtract(gripEnt->client->ps.origin, self->client->ps.origin, a);
03972         
03973         trap_Trace(&tr, self->client->ps.origin, NULL, NULL, gripEnt->client->ps.origin, self->s.number, MASK_PLAYERSOLID);
03974 
03975         gripLevel = WP_AbsorbConversion(gripEnt, gripEnt->client->ps.fd.forcePowerLevel[FP_ABSORB], self, FP_GRIP, self->client->ps.fd.forcePowerLevel[FP_GRIP], forcePowerNeeded[self->client->ps.fd.forcePowerLevel[FP_GRIP]][FP_GRIP]);
03976 
03977         if (gripLevel == -1)
03978         {
03979                 gripLevel = self->client->ps.fd.forcePowerLevel[FP_GRIP];
03980         }
03981 
03982         if (!gripLevel)
03983         {
03984                 WP_ForcePowerStop(self, forcePower);
03985                 return;
03986         }
03987 
03988         if (VectorLength(a) > MAX_GRIP_DISTANCE)
03989         {
03990                 WP_ForcePowerStop(self, forcePower);
03991                 return;
03992         }
03993 
03994         if ( !InFront( gripEnt->client->ps.origin, self->client->ps.origin, self->client->ps.viewangles, 0.9f ) &&
03995                 gripLevel < FORCE_LEVEL_3)
03996         {
03997                 WP_ForcePowerStop(self, forcePower);
03998                 return;
03999         }
04000 
04001         if (tr.fraction != 1.0f &&
04002                 tr.entityNum != gripEnt->s.number /*&&
04003                 gripLevel < FORCE_LEVEL_3*/)
04004         {
04005                 WP_ForcePowerStop(self, forcePower);
04006                 return;
04007         }
04008 
04009         if (self->client->ps.fd.forcePowerDebounce[FP_GRIP] < level.time)
04010         { //2 damage per second while choking, resulting in 10 damage total (not including The Squeeze<tm>)
04011                 self->client->ps.fd.forcePowerDebounce[FP_GRIP] = level.time + 1000;
04012                 G_Damage(gripEnt, self, self, NULL, NULL, 2, DAMAGE_NO_ARMOR, MOD_FORCE_DARK);
04013         }
04014 
04015         Jetpack_Off(gripEnt); //make sure the guy being gripped has his jetpack off.
04016 
04017         if (gripLevel == FORCE_LEVEL_1)
04018         {
04019                 gripEnt->client->ps.fd.forceGripBeingGripped = level.time + 1000;
04020                 
04021                 if ((level.time - gripEnt->client->ps.fd.forceGripStarted) > 5000)
04022                 {
04023                         WP_ForcePowerStop(self, forcePower);
04024                 }
04025                 return;
04026         }
04027 
04028         if (gripLevel == FORCE_LEVEL_2)
04029         {
04030                 gripEnt->client->ps.fd.forceGripBeingGripped = level.time + 1000;
04031 
04032                 if (gripEnt->client->ps.forceGripMoveInterval < level.time)
04033                 {
04034                         gripEnt->client->ps.velocity[2] = 30;
04035 
04036                         gripEnt->client->ps.forceGripMoveInterval = level.time + 300; //only update velocity every 300ms, so as to avoid heavy bandwidth usage
04037                 }
04038 
04039                 gripEnt->client->ps.otherKiller = self->s.number;
04040                 gripEnt->client->ps.otherKillerTime = level.time + 5000;
04041                 gripEnt->client->ps.otherKillerDebounceTime = level.time + 100;
04042 
04043                 gripEnt->client->ps.forceGripChangeMovetype = PM_FLOAT;
04044 
04045                 if ((level.time - gripEnt->client->ps.fd.forceGripStarted) > 3000 && !self->client->ps.fd.forceGripDamageDebounceTime)
04046                 { //if we managed to lift him into the air for 2 seconds, give him a crack
04047                         self->client->ps.fd.forceGripDamageDebounceTime = 1;
04048                         G_Damage(gripEnt, self, self, NULL, NULL, 20, DAMAGE_NO_ARMOR, MOD_FORCE_DARK);
04049 
04050                         //Must play custom sounds on the actual entity. Don't use G_Sound (it creates a temp entity for the sound)
04051                         G_EntitySound( gripEnt, CHAN_VOICE, G_SoundIndex(va( "*choke%d.wav", Q_irand( 1, 3 ) )) );
04052 
04053                         gripEnt->client->ps.forceHandExtend = HANDEXTEND_CHOKE;
04054                         gripEnt->client->ps.forceHandExtendTime = level.time + 2000;
04055 
04056                         if (gripEnt->client->ps.fd.forcePowersActive & (1 << FP_GRIP))
04057                         { //choking, so don't let him keep gripping himself
04058                                 WP_ForcePowerStop(gripEnt, FP_GRIP);
04059                         }
04060                 }
04061                 else if ((level.time - gripEnt->client->ps.fd.forceGripStarted) > 4000)
04062                 {
04063                         WP_ForcePowerStop(self, forcePower);
04064                 }
04065                 return;
04066         }
04067 
04068         if (gripLevel == FORCE_LEVEL_3)
04069         {
04070                 gripEnt->client->ps.fd.forceGripBeingGripped = level.time + 1000;
04071 
04072                 gripEnt->client->ps.otherKiller = self->s.number;
04073                 gripEnt->client->ps.otherKillerTime = level.time + 5000;
04074                 gripEnt->client->ps.otherKillerDebounceTime = level.time + 100;
04075 
04076                 gripEnt->client->ps.forceGripChangeMovetype = PM_FLOAT;
04077 
04078                 if (gripEnt->client->ps.forceGripMoveInterval < level.time)
04079                 {
04080                         float nvLen = 0;
04081 
04082                         VectorCopy(gripEnt->client->ps.origin, start_o);
04083                         AngleVectors(self->client->ps.viewangles, fwd, NULL, NULL);
04084                         fwd_o[0] = self->client->ps.origin[0] + fwd[0]*128;
04085                         fwd_o[1] = self->client->ps.origin[1] + fwd[1]*128;
04086                         fwd_o[2] = self->client->ps.origin[2] + fwd[2]*128;
04087                         fwd_o[2] += 16;
04088                         VectorSubtract(fwd_o, start_o, nvel);
04089 
04090                         nvLen = VectorLength(nvel);
04091 
04092                         if (nvLen < 16)
04093                         { //within x units of desired spot
04094                                 VectorNormalize(nvel);
04095                                 gripEnt->client->ps.velocity[0] = nvel[0]*8;
04096                                 gripEnt->client->ps.velocity[1] = nvel[1]*8;
04097                                 gripEnt->client->ps.velocity[2] = nvel[2]*8;
04098                         }
04099                         else if (nvLen < 64)
04100                         {
04101                                 VectorNormalize(nvel);
04102                                 gripEnt->client->ps.velocity[0] = nvel[0]*128;
04103                                 gripEnt->client->ps.velocity[1] = nvel[1]*128;
04104                                 gripEnt->client->ps.velocity[2] = nvel[2]*128;
04105                         }
04106                         else if (nvLen < 128)
04107                         {
04108                                 VectorNormalize(nvel);
04109                                 gripEnt->client->ps.velocity[0] = nvel[0]*256;
04110                                 gripEnt->client->ps.velocity[1] = nvel[1]*256;
04111                                 gripEnt->client->ps.velocity[2] = nvel[2]*256;
04112                         }
04113                         else if (nvLen < 200)
04114                         {
04115                                 VectorNormalize(nvel);
04116                                 gripEnt->client->ps.velocity[0] = nvel[0]*512;
04117                                 gripEnt->client->ps.velocity[1] = nvel[1]*512;
04118                                 gripEnt->client->ps.velocity[2] = nvel[2]*512;
04119                         }
04120                         else
04121                         {
04122                                 VectorNormalize(nvel);
04123                                 gripEnt->client->ps.velocity[0] = nvel[0]*700;
04124                                 gripEnt->client->ps.velocity[1] = nvel[1]*700;
04125                                 gripEnt->client->ps.velocity[2] = nvel[2]*700;
04126                         }
04127 
04128                         gripEnt->client->ps.forceGripMoveInterval = level.time + 300; //only update velocity every 300ms, so as to avoid heavy bandwidth usage
04129                 }
04130 
04131                 if ((level.time - gripEnt->client->ps.fd.forceGripStarted) > 3000 && !self->client->ps.fd.forceGripDamageDebounceTime)
04132                 { //if we managed to lift him into the air for 2 seconds, give him a crack
04133                         self->client->ps.fd.forceGripDamageDebounceTime = 1;
04134                         G_Damage(gripEnt, self, self, NULL, NULL, 40, DAMAGE_NO_ARMOR, MOD_FORCE_DARK);
04135 
04136                         //Must play custom sounds on the actual entity. Don't use G_Sound (it creates a temp entity for the sound)
04137                         G_EntitySound( gripEnt, CHAN_VOICE, G_SoundIndex(va( "*choke%d.wav", Q_irand( 1, 3 ) )) );
04138 
04139                         gripEnt->client->ps.forceHandExtend = HANDEXTEND_CHOKE;
04140                         gripEnt->client->ps.forceHandExtendTime = level.time + 2000;
04141 
04142                         if (gripEnt->client->ps.fd.forcePowersActive & (1 << FP_GRIP))
04143                         { //choking, so don't let him keep gripping himself
04144                                 WP_ForcePowerStop(gripEnt, FP_GRIP);
04145                         }
04146                 }
04147                 else if ((level.time - gripEnt->client->ps.fd.forceGripStarted) > 4000)
04148                 {
04149                         WP_ForcePowerStop(self, forcePower);
04150                 }
04151                 return;
04152         }
04153 }

void FindGenericEnemyIndex gentity_t self  ) 
 

Definition at line 4664 of file w_force.c.

References gentity_s::client, g_entities, playerState_s::genericEnemyIndex, gentity_t, gentity_s::health, InFront(), MAX_CLIENTS, NULL, entityState_s::number, OnSameTeam(), OrgVisible(), playerState_s::origin, PM_INTERMISSION, PM_SPECTATOR, playerState_s::pm_type, gclient_s::ps, gentity_s::s, vec3_t, VectorSubtract, and playerState_s::viewangles.

Referenced by SeekerDroneUpdate().

04665 { //Find another client that would be considered a threat.
04666         int i = 0;
04667         float tlen;
04668         gentity_t *ent;
04669         gentity_t *besten = NULL;
04670         float blen = 99999999;
04671         vec3_t a;
04672 
04673         while (i < MAX_CLIENTS)
04674         {
04675                 ent = &g_entities[i];
04676 
04677                 if (ent && ent->client && ent->s.number != self->s.number && ent->health > 0 && !OnSameTeam(self, ent) && ent->client->ps.pm_type != PM_INTERMISSION && ent->client->ps.pm_type != PM_SPECTATOR)
04678                 {
04679                         VectorSubtract(ent->client->ps.origin, self->client->ps.origin, a);
04680                         tlen = VectorLength(a);
04681 
04682                         if (tlen < blen &&
04683                                 InFront(ent->client->ps.origin, self->client->ps.origin, self->client->ps.viewangles, 0.8f ) &&
04684                                 OrgVisible(self->client->ps.origin, ent->client->ps.origin, self->s.number))
04685                         {
04686                                 blen = tlen;
04687                                 besten = ent;
04688                         }
04689                 }
04690 
04691                 i++;
04692         }
04693 
04694         if (!besten)
04695         {
04696                 return;
04697         }
04698 
04699         self->client->ps.genericEnemyIndex = besten->s.number;
04700 }

void ForceAbsorb gentity_t self  ) 
 

Definition at line 1694 of file w_force.c.

References absorbLoopSound, gentity_s::client, playerState_s::fd, playerState_s::forceAllowDeactivateTime, forcedata_s::forcePowersActive, FP_ABSORB, FP_PROTECT, FP_RAGE, G_PreDefSound(), G_Sound(), gentity_t, gentity_s::health, level, playerState_s::origin, PDSOUND_ABSORB, gclient_s::ps, level_locals_t::time, TRACK_CHANNEL_3, WP_ForcePowerStart(), WP_ForcePowerStop(), and WP_ForcePowerUsable().

Referenced by ClientThink_real(), and WP_DoSpecificPower().

01695 {
01696         if ( self->health <= 0 )
01697         {
01698                 return;
01699         }
01700 
01701         if (self->client->ps.forceAllowDeactivateTime < level.time &&
01702                 (self->client->ps.fd.forcePowersActive & (1 << FP_ABSORB)) )
01703         {
01704                 WP_ForcePowerStop( self, FP_ABSORB );
01705                 return;
01706         }
01707 
01708         if ( !WP_ForcePowerUsable( self, FP_ABSORB ) )
01709         {
01710                 return;
01711         }
01712 
01713         // Make sure to turn off Force Rage and Force Protection.
01714         if (self->client->ps.fd.forcePowersActive & (1 << FP_RAGE) )
01715         {
01716                 WP_ForcePowerStop( self, FP_RAGE );
01717         }
01718         if (self->client->ps.fd.forcePowersActive & (1 << FP_PROTECT) )
01719         {
01720                 WP_ForcePowerStop( self, FP_PROTECT );
01721         }
01722 
01723         self->client->ps.forceAllowDeactivateTime = level.time + 1500;
01724 
01725         WP_ForcePowerStart( self, FP_ABSORB, 0 );
01726         G_PreDefSound(self->client->ps.origin, PDSOUND_ABSORB);
01727         G_Sound( self, TRACK_CHANNEL_3, absorbLoopSound );
01728 }

void ForceDrain gentity_t self  ) 
 

Definition at line 2022 of file w_force.c.

References CHAN_BODY, gentity_s::client, playerState_s::fd, playerState_s::forceHandExtend, playerState_s::forceHandExtendTime, forcedata_s::forcePower, forcedata_s::forcePowerDebounce, FP_DRAIN, G_Sound(), G_SoundIndex(), gentity_t, HANDEXTEND_FORCE_HOLD, HANDEXTEND_NONE, gentity_s::health, level, gclient_s::ps, level_locals_t::time, playerState_s::weaponTime, WP_ForcePowerStart(), and WP_ForcePowerUsable().

Referenced by WP_DoSpecificPower().

02023 {
02024         if ( self->health <= 0 )
02025         {
02026                 return;
02027         }
02028 
02029         if (self->client->ps.forceHandExtend != HANDEXTEND_NONE)
02030         {
02031                 return;
02032         }
02033 
02034         if (self->client->ps.weaponTime > 0)
02035         {
02036                 return;
02037         }
02038 
02039         if ( self->client->ps.fd.forcePower < 25 || !WP_ForcePowerUsable( self, FP_DRAIN ) )
02040         {
02041                 return;
02042         }
02043         if ( self->client->ps.fd.forcePowerDebounce[FP_DRAIN] > level.time )
02044         {//stops it while using it and also after using it, up to 3 second delay
02045                 return;
02046         }
02047 
02048 //      self->client->ps.forceHandExtend = HANDEXTEND_FORCEPUSH;
02049 //      self->client->ps.forceHandExtendTime = level.time + 1000;
02050         self->client->ps.forceHandExtend = HANDEXTEND_FORCE_HOLD;
02051         self->client->ps.forceHandExtendTime = level.time + 20000;
02052 
02053         G_Sound( self, CHAN_BODY, G_SoundIndex("sound/weapons/force/drain.wav") );
02054         
02055         WP_ForcePowerStart( self, FP_DRAIN, 500 );
02056 }

void ForceDrainDamage gentity_t self,
gentity_t traceEnt,
vec3_t  dir,
vec3_t  impactPoint
 

Definition at line 2058 of file w_force.c.

References gentity_s::client, gclient_s::dangerTime, DirToByte(), EF_INVULNERABLE, playerState_s::eFlags, ET_NPC, entityState_s::eType, EV_FORCE_DRAINED, entityState_s::eventParm, playerState_s::fd, FORCE_LEVEL_1, FORCE_LEVEL_2, FORCE_LEVEL_3, forcedata_s::forceDrainTime, forcedata_s::forcePower, forcedata_s::forcePowerLevel, forcedata_s::forcePowerRegenDebounceTime, gclient_s::forcePowerSoundDebounce, ForcePowerUsableOn(), FP_ABSORB, FP_DRAIN, g_friendlyFire, G_TempEntity(), entityState_s::genericenemyindex, gentity_t, gentity_s::health, vmCvar_t::integer, gclient_s::invulnerableTimer, level, entityState_s::number, OnSameTeam(), entityState_s::owner, gclient_s::ps, gentity_s::s, STAT_HEALTH, STAT_MAX_HEALTH, playerState_s::stats, gentity_s::takedamage, level_locals_t::time, vec3_t, and WP_AbsorbConversion().

Referenced by ForceShootDrain().

02059 {
02060         gentity_t *tent;
02061 
02062         self->client->dangerTime = level.time;
02063         self->client->ps.eFlags &= ~EF_INVULNERABLE;
02064         self->client->invulnerableTimer = 0;
02065 
02066         if ( traceEnt && traceEnt->takedamage )
02067         {
02068                 if ( traceEnt->client && (!OnSameTeam(self, traceEnt) || g_friendlyFire.integer) && self->client->ps.fd.forceDrainTime < level.time && traceEnt->client->ps.fd.forcePower )
02069                 {//an enemy or object
02070                         if (!traceEnt->client && traceEnt->s.eType == ET_NPC)
02071                         { //g2animent
02072                                 if (traceEnt->s.genericenemyindex < level.time)
02073                                 {
02074                                         traceEnt->s.genericenemyindex = level.time + 2000;
02075                                 }
02076                         }
02077                         if (ForcePowerUsableOn(self, traceEnt, FP_DRAIN))
02078                         {
02079                                 int modPowerLevel = -1;
02080                                 int     dmg = 0; //Q_irand( 1, 3 );
02081                                 if (self->client->ps.fd.forcePowerLevel[FP_DRAIN] == FORCE_LEVEL_1)
02082                                 {
02083                                         dmg = 2; //because it's one-shot
02084                                 }
02085                                 else if (self->client->ps.fd.forcePowerLevel[FP_DRAIN] == FORCE_LEVEL_2)
02086                                 {
02087                                         dmg = 3;
02088                                 }
02089                                 else if (self->client->ps.fd.forcePowerLevel[FP_DRAIN] == FORCE_LEVEL_3)
02090                                 {
02091                                         dmg = 4;
02092                                 }
02093                         
02094                                 if (traceEnt->client)
02095                                 {
02096                                         modPowerLevel = WP_AbsorbConversion(traceEnt, traceEnt->client->ps.fd.forcePowerLevel[FP_ABSORB], self, FP_DRAIN, self->client->ps.fd.forcePowerLevel[FP_DRAIN], 1);
02097                                 }
02098 
02099                                 if (modPowerLevel != -1)
02100                                 {
02101                                         if (!modPowerLevel)
02102                                         {
02103                                                 dmg = 0;
02104                                         }
02105                                         else if (modPowerLevel == 1)
02106                                         {
02107                                                 dmg = 1;
02108                                         }
02109                                         else if (modPowerLevel == 2)
02110                                         {
02111                                                 dmg = 2;
02112                                         }
02113                                 }
02114                                 //G_Damage( traceEnt, self, self, dir, impactPoint, dmg, 0, MOD_FORCE_DARK );
02115 
02116                                 if (dmg)
02117                                 {
02118                                         traceEnt->client->ps.fd.forcePower -= (dmg);
02119                                 }
02120                                 if (traceEnt->client->ps.fd.forcePower < 0)
02121                                 {
02122                                         traceEnt->client->ps.fd.forcePower = 0;
02123                                 }
02124 
02125                                 if (self->client->ps.stats[STAT_HEALTH] < self->client->ps.stats[STAT_MAX_HEALTH] &&
02126                                         self->health > 0 && self->client->ps.stats[STAT_HEALTH] > 0)
02127                                 {
02128                                         self->health += dmg;
02129                                         if (self->health > self->client->ps.stats[STAT_MAX_HEALTH])
02130                                         {
02131                                                 self->health = self->client->ps.stats[STAT_MAX_HEALTH];
02132                                         }
02133                                         self->client->ps.stats[STAT_HEALTH] = self->health;
02134                                 }
02135 
02136                                 traceEnt->client->ps.fd.forcePowerRegenDebounceTime = level.time + 800; //don't let the client being drained get force power back right away
02137 
02138                                 //Drain the standard amount since we just drained someone else
02139 
02140                                 /*
02141                                 if (self->client->ps.fd.forcePowerLevel[FP_DRAIN] == FORCE_LEVEL_1)
02142                                 {
02143                                         BG_ForcePowerDrain( &self->client->ps, FP_DRAIN, 0 );
02144                                 }
02145                                 else
02146                                 {
02147                                         BG_ForcePowerDrain( &self->client->ps, FP_DRAIN, forcePowerNeeded[self->client->ps.fd.forcePowerLevel[FP_DRAIN]][FP_DRAIN]/5 );
02148                                 }
02149 
02150                                 if (self->client->ps.fd.forcePowerLevel[FP_DRAIN] == FORCE_LEVEL_1)
02151                                 {
02152                                         self->client->ps.fd.forceDrainTime = level.time + 100;
02153                                 }
02154                                 else
02155                                 {
02156                                         self->client->ps.fd.forceDrainTime = level.time + 20;
02157                                 }
02158 
02159                                 if ( traceEnt->client )
02160                                 {
02161                                         if ( !Q_irand( 0, 2 ) )
02162                                         {
02163                                                 //G_Sound( traceEnt, CHAN_BODY, G_SoundIndex( "sound/weapons/force/lightninghit.wav" ) );
02164                                         }
02165                                 //      traceEnt->s.powerups |= ( 1 << PW_DISINT_1 );
02166 
02167                                 //      traceEnt->client->ps.powerups[PW_DISINT_1] = level.time + 500;
02168                                 }
02169                                 */
02170 
02171                                 if (traceEnt->client->forcePowerSoundDebounce < level.time)
02172                                 {
02173                                         tent = G_TempEntity( impactPoint, EV_FORCE_DRAINED);
02174                                         tent->s.eventParm = DirToByte(dir);
02175                                         tent->s.owner = traceEnt->s.number;
02176 
02177                                         traceEnt->client->forcePowerSoundDebounce = level.time + 400;
02178                                 }
02179                         }
02180                 }
02181         }
02182 }

void ForceGrip gentity_t self  ) 
 

Definition at line 1523 of file w_force.c.

References AngleVectors(), bgEntity_t, gentity_s::client, vehicleInfo_t::Eject, trace_t::entityNum, ENTITYNUM_NONE, playerState_s::fd, forcedata_s::forceGripDamageDebounceTime, forcedata_s::forceGripEntityNum, forcedata_s::forceGripUseTime, playerState_s::forceHandExtend, playerState_s::forceHandExtendTime, ForcePowerUsableOn(), FP_GRIP, trace_t::fraction, g_entities, g_friendlyFire, gentity_t, HANDEXTEND_FORCE_HOLD, HANDEXTEND_NONE, gentity_s::health, vmCvar_t::integer, gentity_s::inuse, level, gentity_s::m_pVehicle, Vehicle_s::m_pVehicleInfo, MASK_PLAYERSOLID, MAX_CLIENTS, MAX_GRIP_DISTANCE, NULL, entityState_s::number, OnSameTeam(), playerState_s::origin, gclient_s::ps, qfalse, gentity_s::s, level_locals_t::time, trap_Trace(), vehicleInfo_t::type, vec3_t, VectorCopy, VH_ANIMAL, VH_SPEEDER, playerState_s::viewangles, playerState_s::viewheight, playerState_s::weaponTime, and WP_ForcePowerUsable().

Referenced by WP_DoSpecificPower().

01524 {
01525         trace_t tr;
01526         vec3_t tfrom, tto, fwd;
01527 
01528         if ( self->health <= 0 )
01529         {
01530                 return;
01531         }
01532 
01533         if (self->client->ps.forceHandExtend != HANDEXTEND_NONE)
01534         {
01535                 return;
01536         }
01537 
01538         if (self->client->ps.weaponTime > 0)
01539         {
01540                 return;
01541         }
01542 
01543         if (self->client->ps.fd.forceGripUseTime > level.time)
01544         {
01545                 return;
01546         }
01547 
01548         if ( !WP_ForcePowerUsable( self, FP_GRIP ) )
01549         {
01550                 return;
01551         }
01552 
01553         VectorCopy(self->client->ps.origin, tfrom);
01554         tfrom[2] += self->client->ps.viewheight;
01555         AngleVectors(self->client->ps.viewangles, fwd, NULL, NULL);
01556         tto[0] = tfrom[0] + fwd[0]*MAX_GRIP_DISTANCE;
01557         tto[1] = tfrom[1] + fwd[1]*MAX_GRIP_DISTANCE;
01558         tto[2] = tfrom[2] + fwd[2]*MAX_GRIP_DISTANCE;
01559 
01560         trap_Trace(&tr, tfrom, NULL, NULL, tto, self->s.number, MASK_PLAYERSOLID);
01561 
01562         if ( tr.fraction != 1.0 &&
01563                 tr.entityNum != ENTITYNUM_NONE &&
01564                 g_entities[tr.entityNum].client &&
01565                 !g_entities[tr.entityNum].client->ps.fd.forceGripCripple &&
01566                 g_entities[tr.entityNum].client->ps.fd.forceGripBeingGripped < level.time &&
01567                 ForcePowerUsableOn(self, &g_entities[tr.entityNum], FP_GRIP) &&
01568                 (g_friendlyFire.integer || !OnSameTeam(self, &g_entities[tr.entityNum])) ) //don't grip someone who's still crippled
01569         {
01570                 if (g_entities[tr.entityNum].s.number < MAX_CLIENTS && g_entities[tr.entityNum].client->ps.m_iVehicleNum)
01571                 { //a player on a vehicle
01572                         gentity_t *vehEnt = &g_entities[g_entities[tr.entityNum].client->ps.m_iVehicleNum];
01573                         if (vehEnt->inuse && vehEnt->client && vehEnt->m_pVehicle)
01574                         {
01575                                 if (vehEnt->m_pVehicle->m_pVehicleInfo->type == VH_SPEEDER ||
01576                                         vehEnt->m_pVehicle->m_pVehicleInfo->type == VH_ANIMAL)
01577                                 { //push the guy off
01578                                         vehEnt->m_pVehicle->m_pVehicleInfo->Eject(vehEnt->m_pVehicle, (bgEntity_t *)&g_entities[tr.entityNum], qfalse);
01579                                 }
01580                         }
01581                 }
01582                 self->client->ps.fd.forceGripEntityNum = tr.entityNum;
01583                 g_entities[tr.entityNum].client->ps.fd.forceGripStarted = level.time;
01584                 self->client->ps.fd.forceGripDamageDebounceTime = 0;
01585 
01586                 self->client->ps.forceHandExtend = HANDEXTEND_FORCE_HOLD;
01587                 self->client->ps.forceHandExtendTime = level.time + 5000;
01588         }
01589         else
01590         {
01591                 self->client->ps.fd.forceGripEntityNum = ENTITYNUM_NONE;
01592                 return;
01593         }
01594 }

void ForceHeal gentity_t self  ) 
 

Definition at line 1236 of file w_force.c.

References BG_ForcePowerDrain(), CHAN_ITEM, gentity_s::client, playerState_s::fd, FORCE_LEVEL_2, FORCE_LEVEL_3, forcedata_s::forcePowerLevel, FP_HEAL, G_Sound(), G_SoundIndex(), gentity_t, gentity_s::health, gclient_s::ps, STAT_MAX_HEALTH, playerState_s::stats, and WP_ForcePowerUsable().

Referenced by ClientThink_real(), and WP_DoSpecificPower().

01237 {
01238         if ( self->health <= 0 )
01239         {
01240                 return;
01241         }
01242 
01243         if ( !WP_ForcePowerUsable( self, FP_HEAL ) )
01244         {
01245                 return;
01246         }
01247 
01248         if ( self->health >= self->client->ps.stats[STAT_MAX_HEALTH])
01249         {
01250                 return;
01251         }
01252 
01253         if (self->client->ps.fd.forcePowerLevel[FP_HEAL] == FORCE_LEVEL_3)
01254         {
01255                 self->health += 25; //This was 50, but that angered the Balance God.
01256                 
01257                 if (self->health > self->client->ps.stats[STAT_MAX_HEALTH])
01258                 {
01259                         self->health = self->client->ps.stats[STAT_MAX_HEALTH];
01260                 }
01261                 BG_ForcePowerDrain( &self->client->ps, FP_HEAL, 0 );
01262         }
01263         else if (self->client->ps.fd.forcePowerLevel[FP_HEAL] == FORCE_LEVEL_2)
01264         {
01265                 self->health += 10;
01266                 
01267                 if (self->health > self->client->ps.stats[STAT_MAX_HEALTH])
01268                 {
01269                         self->health = self->client->ps.stats[STAT_MAX_HEALTH];
01270                 }
01271                 BG_ForcePowerDrain( &self->client->ps, FP_HEAL, 0 );
01272         }
01273         else
01274         {
01275                 self->health += 5;
01276                 
01277                 if (self->health > self->client->ps.stats[STAT_MAX_HEALTH])
01278                 {
01279                         self->health = self->client->ps.stats[STAT_MAX_HEALTH];
01280                 }
01281                 BG_ForcePowerDrain( &self->client->ps, FP_HEAL, 0 );
01282         }
01283         /*
01284         else
01285         {
01286                 WP_ForcePowerStart( self, FP_HEAL, 0 );
01287         }
01288         */
01289         //NOTE: Decided to make all levels instant.
01290 
01291         G_Sound( self, CHAN_ITEM, G_SoundIndex("sound/weapons/force/heal.wav") );
01292 }

void ForceJump gentity_t self,
usercmd_t ucmd
 

Definition at line 2462 of file w_force.c.

References gentity_s::client, ENTITYNUM_NONE, playerState_s::fd, gclient_s::fjDidJump, FORCE_JUMP_CHARGE_TIME, forcedata_s::forceJumpCharge, playerState_s::forceJumpFlip, forceJumpStrength, forcedata_s::forceJumpZStart, forcedata_s::forcePowerDuration, forcedata_s::forcePowerLevel, forcePowerNeeded, FP_LEVITATION, FRAMETIME, gentity_t, entityState_s::groundEntityNum, gentity_s::health, level, playerState_s::origin, gclient_s::ps, qtrue, gentity_s::s, level_locals_t::time, ucmd, usercmd_t, vec3_t, VectorCopy, playerState_s::velocity, WP_ForcePowerStart(), WP_ForcePowerUsable(), and WP_GetVelocityForForceJump().

Referenced by Boba_StopKnockdown(), and WP_DoSpecificPower().

02463 {
02464         float forceJumpChargeInterval;
02465         vec3_t  jumpVel;
02466 
02467         if ( self->client->ps.fd.forcePowerDuration[FP_LEVITATION] > level.time )
02468         {
02469                 return;
02470         }
02471         if ( !WP_ForcePowerUsable( self, FP_LEVITATION ) )
02472         {
02473                 return;
02474         }
02475         if ( self->s.groundEntityNum == ENTITYNUM_NONE )
02476         {
02477                 return;
02478         }
02479         if ( self->health <= 0 )
02480         {
02481                 return;
02482         }
02483 
02484         self->client->fjDidJump = qtrue;
02485 
02486         forceJumpChargeInterval = forceJumpStrength[self->client->ps.fd.forcePowerLevel[FP_LEVITATION]]/(FORCE_JUMP_CHARGE_TIME/FRAMETIME);
02487 
02488         WP_GetVelocityForForceJump( self, jumpVel, ucmd );
02489 
02490         //FIXME: sound effect
02491         self->client->ps.fd.forceJumpZStart = self->client->ps.origin[2];//remember this for when we land
02492         VectorCopy( jumpVel, self->client->ps.velocity );
02493         //wasn't allowing them to attack when jumping, but that was annoying
02494         //self->client->ps.weaponTime = self->client->ps.torsoAnimTimer;
02495 
02496         WP_ForcePowerStart( self, FP_LEVITATION, self->client->ps.fd.forceJumpCharge/forceJumpChargeInterval/(FORCE_JUMP_CHARGE_TIME/FRAMETIME)*forcePowerNeeded[self->client->ps.fd.forcePowerLevel[FP_LEVITATION]][FP_LEVITATION] );
02497         //self->client->ps.fd.forcePowerDuration[FP_LEVITATION] = level.time + self->client->ps.weaponTime;
02498         self->client->ps.fd.forceJumpCharge = 0;
02499         self->client->ps.forceJumpFlip = qtrue;
02500 }

void ForceJumpCharge gentity_t self,
usercmd_t ucmd
 

Definition at line 2317 of file w_force.c.

References CHAN_VOICE, gentity_s::client, ENTITYNUM_NONE, playerState_s::fd, FORCE_JUMP_CHARGE_TIME, forcedata_s::forceJumpAddTime, forcedata_s::forceJumpCharge, forceJumpStrength, forcedata_s::forcePower, forcedata_s::forcePowerLevel, forcePowerNeeded, FP_LEVITATION, FRAMETIME, G_MuteSound(), G_Sound(), G_SoundIndex(), gentity_t, playerState_s::groundEntityNum, gentity_s::health, forcedata_s::killSoundEntIndex, level, gclient_s::ps, level_locals_t::time, TRACK_CHANNEL_1, and usercmd_t.

Referenced by WP_ForcePowersUpdate().

02318 { //I guess this is unused now. Was used for the "charge" jump type.
02319         float forceJumpChargeInterval = forceJumpStrength[0] / (FORCE_JUMP_CHARGE_TIME/FRAMETIME);
02320 
02321         if ( self->health <= 0 )
02322         {
02323                 return;
02324         }
02325 
02326         if (!self->client->ps.fd.forceJumpCharge && self->client->ps.groundEntityNum == ENTITYNUM_NONE)
02327         {
02328                 return;
02329         }
02330 
02331         if (self->client->ps.fd.forcePower < forcePowerNeeded[self->client->ps.fd.forcePowerLevel[FP_LEVITATION]][FP_LEVITATION])
02332         {
02333                 G_MuteSound(self->client->ps.fd.killSoundEntIndex[TRACK_CHANNEL_1-50], CHAN_VOICE);
02334                 return;
02335         }
02336 
02337         if (!self->client->ps.fd.forceJumpCharge)
02338         {
02339                 self->client->ps.fd.forceJumpAddTime = 0;
02340         }
02341 
02342         if (self->client->ps.fd.forceJumpAddTime >= level.time)
02343         {
02344                 return;
02345         }
02346 
02347         //need to play sound
02348         if ( !self->client->ps.fd.forceJumpCharge )
02349         {
02350                 G_Sound( self, TRACK_CHANNEL_1, G_SoundIndex("sound/weapons/force/jumpbuild.wav") );
02351         }
02352 
02353         //Increment
02354         if (self->client->ps.fd.forceJumpAddTime < level.time)
02355         {
02356                 self->client->ps.fd.forceJumpCharge += forceJumpChargeInterval*50;
02357                 self->client->ps.fd.forceJumpAddTime = level.time + 500;
02358         }
02359 
02360         //clamp to max strength for current level
02361         if ( self->client->ps.fd.forceJumpCharge > forceJumpStrength[self->client->ps.fd.forcePowerLevel[FP_LEVITATION]] )
02362         {
02363                 self->client->ps.fd.forceJumpCharge = forceJumpStrength[self->client->ps.fd.forcePowerLevel[FP_LEVITATION]];
02364                 G_MuteSound(self->client->ps.fd.killSoundEntIndex[TRACK_CHANNEL_1-50], CHAN_VOICE);
02365         }
02366 
02367         //clamp to max available force power
02368         if ( self->client->ps.fd.forceJumpCharge/forceJumpChargeInterval/(FORCE_JUMP_CHARGE_TIME/FRAMETIME)*forcePowerNeeded[self->client->ps.fd.forcePowerLevel[FP_LEVITATION]][FP_LEVITATION] > self->client->ps.fd.forcePower )
02369         {//can't use more than you have
02370                 G_MuteSound(self->client->ps.fd.killSoundEntIndex[TRACK_CHANNEL_1-50], CHAN_VOICE);
02371                 self->client->ps.fd.forceJumpCharge = self->client->ps.fd.forcePower*forceJumpChargeInterval/(FORCE_JUMP_CHARGE_TIME/FRAMETIME);
02372         }
02373         
02374         //G_Printf("%f\n", self->client->ps.fd.forceJumpCharge);
02375 }

void ForceLightning gentity_t self  ) 
 

Definition at line 1777 of file w_force.c.

References CHAN_BODY, gentity_s::client, playerState_s::fd, playerState_s::forceHandExtend, playerState_s::forceHandExtendTime, forcedata_s::forcePower, forcedata_s::forcePowerDebounce, FP_LIGHTNING, G_Sound(), G_SoundIndex(), gentity_t, HANDEXTEND_FORCE_HOLD, HANDEXTEND_NONE, gentity_s::health, level, gclient_s::ps, level_locals_t::time, playerState_s::weaponTime, WP_ForcePowerStart(), and WP_ForcePowerUsable().

Referenced by WP_DoSpecificPower().

01778 {
01779         if ( self->health <= 0 )
01780         {
01781                 return;
01782         }
01783         if ( self->client->ps.fd.forcePower < 25 || !WP_ForcePowerUsable( self, FP_LIGHTNING ) )
01784         {
01785                 return;
01786         }
01787         if ( self->client->ps.fd.forcePowerDebounce[FP_LIGHTNING] > level.time )
01788         {//stops it while using it and also after using it, up to 3 second delay
01789                 return;
01790         }
01791 
01792         if (self->client->ps.forceHandExtend != HANDEXTEND_NONE)
01793         {
01794                 return;
01795         }
01796 
01797         if (self->client->ps.weaponTime > 0)
01798         {
01799                 return;
01800         }
01801 
01802         //Shoot lightning from hand
01803         //using grip anim now, to extend the burst time
01804         self->client->ps.forceHandExtend = HANDEXTEND_FORCE_HOLD;
01805         self->client->ps.forceHandExtendTime = level.time + 20000;
01806 
01807         G_Sound( self, CHAN_BODY, G_SoundIndex("sound/weapons/force/lightning") );
01808         
01809         WP_ForcePowerStart( self, FP_LIGHTNING, 500 );
01810 }

void ForceLightningDamage gentity_t self,
gentity_t traceEnt,
vec3_t  dir,
vec3_t  impactPoint
 

Definition at line 1812 of file w_force.c.

References CHAN_BODY, gentity_s::client, gclient_s::cloakToggleTime, gclient_s::dangerTime, EF_INVULNERABLE, playerState_s::eFlags, playerState_s::electrifyTime, ET_NPC, entityState_s::eType, playerState_s::fd, FORCE_LEVEL_2, forcedata_s::forcePower, forcedata_s::forcePowerLevel, ForcePowerUsableOn(), FP_ABSORB, FP_LIGHTNING, G_Damage(), G_Sound(), G_SoundIndex(), entityState_s::genericenemyindex, gentity_t, gclient_s::invulnerableTimer, Jedi_Decloak(), level, MOD_FORCE_DARK, gclient_s::noLightningTime, playerState_s::powerups, gclient_s::ps, PW_CLOAKED, Q_irand(), gentity_s::s, gentity_s::takedamage, level_locals_t::time, va(), vec3_t, playerState_s::weapon, WP_AbsorbConversion(), and WP_MELEE.

Referenced by ForceShootLightning().

01813 {
01814         self->client->dangerTime = level.time;
01815         self->client->ps.eFlags &= ~EF_INVULNERABLE;
01816         self->client->invulnerableTimer = 0;
01817 
01818         if ( traceEnt && traceEnt->takedamage )
01819         {
01820                 if (!traceEnt->client && traceEnt->s.eType == ET_NPC)
01821                 { //g2animent
01822                         if (traceEnt->s.genericenemyindex < level.time)
01823                         {
01824                                 traceEnt->s.genericenemyindex = level.time + 2000;
01825                         }
01826                 }
01827                 if ( traceEnt->client )
01828                 {//an enemy or object
01829                         if (traceEnt->client->noLightningTime >= level.time)
01830                         { //give them power and don't hurt them.
01831                                 traceEnt->client->ps.fd.forcePower++;
01832                                 if (traceEnt->client->ps.fd.forcePower > 100)
01833                                 {
01834                                         traceEnt->client->ps.fd.forcePower = 100;
01835                                 }
01836                                 return;
01837                         }
01838                         if (ForcePowerUsableOn(self, traceEnt, FP_LIGHTNING))
01839                         {
01840                                 int     dmg = Q_irand(1,2); //Q_irand( 1, 3 );
01841                                 
01842                                 int modPowerLevel = -1;
01843                                 
01844                                 if (traceEnt->client)
01845                                 {
01846                                         modPowerLevel = WP_AbsorbConversion(traceEnt, traceEnt->client->ps.fd.forcePowerLevel[FP_ABSORB], self, FP_LIGHTNING, self->client->ps.fd.forcePowerLevel[FP_LIGHTNING], 1);
01847                                 }
01848 
01849                                 if (modPowerLevel != -1)
01850                                 {
01851                                         if (!modPowerLevel)
01852                                         {
01853                                                 dmg = 0;
01854                                                 traceEnt->client->noLightningTime = level.time + 400;
01855                                         }
01856                                         else if (modPowerLevel == 1)
01857                                         {
01858                                                 dmg = 1;
01859                                                 traceEnt->client->noLightningTime = level.time + 300;
01860                                         }
01861                                         else if (modPowerLevel == 2)
01862                                         {
01863                                                 dmg = 1;
01864                                                 traceEnt->client->noLightningTime = level.time + 100;
01865                                         }
01866                                 }
01867 
01868                                 if ( self->client->ps.weapon == WP_MELEE
01869                                         && self->client->ps.fd.forcePowerLevel[FP_LIGHTNING] > FORCE_LEVEL_2 )
01870                                 {//2-handed lightning
01871                                         //jackin' 'em up, Palpatine-style
01872                                         dmg *= 2;
01873                                 }
01874 
01875                                 if (dmg)
01876                                 {
01877                                         //rww - Shields can now absorb lightning too.
01878                                         G_Damage( traceEnt, self, self, dir, impactPoint, dmg, 0, MOD_FORCE_DARK );
01879                                 }
01880                                 if ( traceEnt->client )
01881                                 {
01882                                         if ( !Q_irand( 0, 2 ) )
01883                                         {
01884                                                 G_Sound( traceEnt, CHAN_BODY, G_SoundIndex( va("sound/weapons/force/lightninghit%i", Q_irand(1, 3) )) );
01885                                         }
01886 
01887                                         if (traceEnt->client->ps.electrifyTime < (level.time + 400))
01888                                         { //only update every 400ms to reduce bandwidth usage (as it is passing a 32-bit time value)
01889                                                 traceEnt->client->ps.electrifyTime = level.time + 800;
01890                                         }
01891                                         if ( traceEnt->client->ps.powerups[PW_CLOAKED] )
01892                                         {//disable cloak temporarily
01893                                                 Jedi_Decloak( traceEnt );
01894                                                 traceEnt->client->cloakToggleTime = level.time + Q_irand( 3000, 10000 );
01895                                         }
01896                                 }
01897                         }
01898                 }
01899         }
01900 }

int ForcePowerUsableOn gentity_t attacker,
gentity_t other,
forcePowers_t  forcePower
 

Definition at line 697 of file w_force.c.

References BG_CanUseFPNow(), BG_HasYsalamiri(), BG_InKnockDown(), BG_SaberInSpecial(), CLASS_VEHICLE, gentity_s::client, playerState_s::duelInProgress, ET_NPC, entityState_s::eType, playerState_s::fd, forcePowers_t, forcedata_s::forcePowersActive, gclient_s::forcePowerSoundDebounce, FP_ABSORB, FP_GRIP, FP_LIGHTNING, FP_PULL, FP_PUSH, g_gametype, G_PreDefSound(), gentity_t, GT_SIEGE, vmCvar_t::integer, playerState_s::legsAnim, level, entityState_s::NPC_class, entityState_s::number, playerState_s::origin, PDSOUND_ABSORBHIT, gclient_s::ps, gentity_s::s, playerState_s::saberMove, level_locals_t::time, entityState_s::trickedentindex, playerState_s::weapon, and WP_SABER.

Referenced by DoGripAction(), ForceDrainDamage(), ForceGrip(), ForceLightningDamage(), ForceTeamForceReplenish(), ForceTeamHeal(), ForceTelepathy(), ForceThrow(), and StandardBotAI().

00698 {
00699         if (other && other->client && BG_HasYsalamiri(g_gametype.integer, &other->client->ps))
00700         {
00701                 return 0;
00702         }
00703 
00704         if (attacker && attacker->client && !BG_CanUseFPNow(g_gametype.integer, &attacker->client->ps, level.time, forcePower))
00705         {
00706                 return 0;
00707         }
00708 
00709         //Dueling fighters cannot use force powers on others, with the exception of force push when locked with each other
00710         if (attacker && attacker->client && attacker->client->ps.duelInProgress)
00711         {
00712                 return 0;
00713         }
00714 
00715         if (other && other->client && other->client->ps.duelInProgress)
00716         {
00717                 return 0;
00718         }
00719 
00720         if (forcePower == FP_GRIP)
00721         {
00722                 if (other && other->client &&
00723                         (other->client->ps.fd.forcePowersActive & (1<<FP_ABSORB)))
00724                 { //don't allow gripping to begin with if they are absorbing
00725                         //play sound indicating that attack was absorbed
00726                         if (other->client->forcePowerSoundDebounce < level.time)
00727                         {
00728                                 gentity_t *abSound = G_PreDefSound(other->client->ps.origin, PDSOUND_ABSORBHIT);
00729                                 abSound->s.trickedentindex = other->s.number;
00730                                 other->client->forcePowerSoundDebounce = level.time + 400;
00731                         }
00732                         return 0;
00733                 }
00734                 else if (other && other->client &&
00735                         other->client->ps.weapon == WP_SABER &&
00736                         BG_SaberInSpecial(other->client->ps.saberMove))
00737                 { //don't grip person while they are in a special or some really bad things can happen.
00738                         return 0;
00739                 }
00740         }
00741 
00742         if (other && other->client &&
00743                 (forcePower == FP_PUSH ||
00744                 forcePower == FP_PULL))
00745         {
00746                 if (BG_InKnockDown(other->client->ps.legsAnim))
00747                 {
00748                         return 0;
00749                 }
00750         }
00751 
00752         if (other && other->client && other->s.eType == ET_NPC &&
00753                 other->s.NPC_class == CLASS_VEHICLE)
00754         { //can't use the force on vehicles.. except lightning
00755                 if (forcePower == FP_LIGHTNING)
00756                 {
00757                         return 1;
00758                 }
00759                 else
00760                 {
00761                         return 0;
00762                 }
00763         }
00764 
00765         if (other && other->client && other->s.eType == ET_NPC &&
00766                 g_gametype.integer == GT_SIEGE)
00767         { //can't use powers at all on npc's normally in siege...
00768                 return 0;
00769         }
00770 
00771         return 1;
00772 }

void ForceProtect gentity_t self  ) 
 

Definition at line 1658 of file w_force.c.

References gentity_s::client, playerState_s::fd, playerState_s::forceAllowDeactivateTime, forcedata_s::forcePowersActive, FP_ABSORB, FP_PROTECT, FP_RAGE, G_PreDefSound(), G_Sound(), gentity_t, gentity_s::health, level, playerState_s::origin, PDSOUND_PROTECT, protectLoopSound, gclient_s::ps, level_locals_t::time, TRACK_CHANNEL_3, WP_ForcePowerStart(), WP_ForcePowerStop(), and WP_ForcePowerUsable().

Referenced by ClientThink_real(), and WP_DoSpecificPower().

01659 {
01660         if ( self->health <= 0 )
01661         {
01662                 return;
01663         }
01664 
01665         if (self->client->ps.forceAllowDeactivateTime < level.time &&
01666                 (self->client->ps.fd.forcePowersActive & (1 << FP_PROTECT)) )
01667         {
01668                 WP_ForcePowerStop( self, FP_PROTECT );
01669                 return;
01670         }
01671 
01672         if ( !WP_ForcePowerUsable( self, FP_PROTECT ) )
01673         {
01674                 return;
01675         }
01676 
01677         // Make sure to turn off Force Rage and Force Absorb.
01678         if (self->client->ps.fd.forcePowersActive & (1 << FP_RAGE) )
01679         {
01680                 WP_ForcePowerStop( self, FP_RAGE );
01681         }
01682         if (self->client->ps.fd.forcePowersActive & (1 << FP_ABSORB) )
01683         {
01684                 WP_ForcePowerStop( self, FP_ABSORB );
01685         }
01686 
01687         self->client->ps.forceAllowDeactivateTime = level.time + 1500;
01688 
01689         WP_ForcePowerStart( self, FP_PROTECT, 0 );
01690         G_PreDefSound(self->client->ps.origin, PDSOUND_PROTECT);
01691         G_Sound( self, TRACK_CHANNEL_3, protectLoopSound );
01692 }

void ForceRage gentity_t self  ) 
 

Definition at line 1730 of file w_force.c.

References gentity_s::client, playerState_s::fd, playerState_s::forceAllowDeactivateTime, forcedata_s::forcePowersActive, forcedata_s::forceRageRecoveryTime, FP_ABSORB, FP_PROTECT, FP_RAGE, G_Sound(), G_SoundIndex(), gentity_t, gentity_s::health, level, gclient_s::ps, rageLoopSound, level_locals_t::time, TRACK_CHANNEL_3, TRACK_CHANNEL_4, WP_ForcePowerStart(), WP_ForcePowerStop(), and WP_ForcePowerUsable().

Referenced by ClientThink_real(), and WP_DoSpecificPower().

01731 {
01732         if ( self->health <= 0 )
01733         {
01734                 return;
01735         }
01736 
01737         if (self->client->ps.forceAllowDeactivateTime < level.time &&
01738                 (self->client->ps.fd.forcePowersActive & (1 << FP_RAGE)) )
01739         {
01740                 WP_ForcePowerStop( self, FP_RAGE );
01741                 return;
01742         }
01743 
01744         if ( !WP_ForcePowerUsable( self, FP_RAGE ) )
01745         {
01746                 return;
01747         }
01748 
01749         if (self->client->ps.fd.forceRageRecoveryTime >= level.time)
01750         {
01751                 return;
01752         }
01753 
01754         if (self->health < 10)
01755         {
01756                 return;
01757         }
01758 
01759         // Make sure to turn off Force Protection and Force Absorb.
01760         if (self->client->ps.fd.forcePowersActive & (1 << FP_PROTECT) )
01761         {
01762                 WP_ForcePowerStop( self, FP_PROTECT );
01763         }
01764         if (self->client->ps.fd.forcePowersActive & (1 << FP_ABSORB) )
01765         {
01766                 WP_ForcePowerStop( self, FP_ABSORB );
01767         }
01768 
01769         self->client->ps.forceAllowDeactivateTime = level.time + 1500;
01770 
01771         WP_ForcePowerStart( self, FP_RAGE, 0 );
01772 
01773         G_Sound( self, TRACK_CHANNEL_4, G_SoundIndex("sound/weapons/force/rage.wav") );
01774         G_Sound( self, TRACK_CHANNEL_3, rageLoopSound );
01775 }

void ForceSeeing gentity_t self  ) 
 

Definition at line 1631 of file w_force.c.

References CHAN_AUTO, gentity_s::client, playerState_s::fd, playerState_s::forceAllowDeactivateTime, forcedata_s::forcePowersActive, FP_SEE, G_Sound(), G_SoundIndex(), gentity_t, gentity_s::health, level, gclient_s::ps, seeLoopSound, level_locals_t::time, TRACK_CHANNEL_5, WP_ForcePowerStart(), WP_ForcePowerStop(), and WP_ForcePowerUsable().

Referenced by ClientThink_real(), and WP_DoSpecificPower().

01632 {
01633         if ( self->health <= 0 )
01634         {
01635                 return;
01636         }
01637 
01638         if (self->client->ps.forceAllowDeactivateTime < level.time &&
01639                 (self->client->ps.fd.forcePowersActive & (1 << FP_SEE)) )
01640         {
01641                 WP_ForcePowerStop( self, FP_SEE );
01642                 return;
01643         }
01644 
01645         if ( !WP_ForcePowerUsable( self, FP_SEE ) )
01646         {
01647                 return;
01648         }
01649 
01650         self->client->ps.forceAllowDeactivateTime = level.time + 1500;
01651 
01652         WP_ForcePowerStart( self, FP_SEE, 0 );
01653 
01654         G_Sound( self, CHAN_AUTO, G_SoundIndex("sound/weapons/force/see.wav") );
01655         G_Sound( self, TRACK_CHANNEL_5, seeLoopSound );
01656 }

int ForceShootDrain gentity_t self  ) 
 

Definition at line 2184 of file w_force.c.

References entityShared_t::absmax, entityShared_t::absmin, playerState_s::activeForcePass, trace_t::allsolid, AngleVectors(), BG_ForcePowerDrain(), entityShared_t::bmodel, gentity_s::client, DotProduct, trace_t::endpos, trace_t::entityNum, ENTITYNUM_NONE, playerState_s::fd, FORCE_LEVEL_2, FORCE_LEVEL_3, ForceDrainDamage(), forcedata_s::forcePower, forcedata_s::forcePowerLevel, forcedata_s::forcePowerRegenDebounceTime, FP_DRAIN, trace_t::fraction, g_entities, g_friendlyFire, gentity_t, gentity_s::health, vmCvar_t::integer, gentity_s::inuse, level, MASK_SHOT, MAX_DRAIN_DISTANCE, MAX_GENTITIES, NULL, entityState_s::number, OnSameTeam(), playerState_s::origin, gclient_s::ps, gentity_s::r, gentity_s::s, trace_t::startsolid, gentity_s::takedamage, level_locals_t::time, trap_EntitiesInBox(), trap_InPVS(), trap_Trace(), vec3_origin, vec3_t, VectorCopy, VectorMA, VectorNormalize(), VectorSubtract, and playerState_s::viewangles.

02185 {
02186         trace_t tr;
02187         vec3_t  end, forward;
02188         gentity_t       *traceEnt;
02189         int                     gotOneOrMore = 0;
02190 
02191         if ( self->health <= 0 )
02192         {
02193                 return 0;
02194         }
02195         AngleVectors( self->client->ps.viewangles, forward, NULL, NULL );
02196         VectorNormalize( forward );
02197 
02198         if ( self->client->ps.fd.forcePowerLevel[FP_DRAIN] > FORCE_LEVEL_2 )
02199         {//arc
02200                 vec3_t  center, mins, maxs, dir, ent_org, size, v;
02201                 float   radius = MAX_DRAIN_DISTANCE, dot, dist;
02202                 gentity_t       *entityList[MAX_GENTITIES];
02203                 int                     iEntityList[MAX_GENTITIES];
02204                 int             e, numListedEntities, i;
02205 
02206                 VectorCopy( self->client->ps.origin, center );
02207                 for ( i = 0 ; i < 3 ; i++ ) 
02208                 {
02209                         mins[i] = center[i] - radius;
02210                         maxs[i] = center[i] + radius;
02211                 }
02212                 numListedEntities = trap_EntitiesInBox( mins, maxs, iEntityList, MAX_GENTITIES );
02213 
02214                 i = 0;
02215                 while (i < numListedEntities)
02216                 {
02217                         entityList[i] = &g_entities[iEntityList[i]];
02218 
02219                         i++;
02220                 }
02221 
02222                 for ( e = 0 ; e < numListedEntities ; e++ ) 
02223                 {
02224                         traceEnt = entityList[e];
02225 
02226                         if ( !traceEnt )
02227                                 continue;
02228                         if ( traceEnt == self )
02229                                 continue;
02230                         if ( !traceEnt->inuse )
02231                                 continue;
02232                         if ( !traceEnt->takedamage )
02233                                 continue;
02234                         if ( traceEnt->health <= 0 )//no torturing corpses
02235                                 continue;
02236                         if ( !traceEnt->client )
02237                                 continue;
02238                         if ( !traceEnt->client->ps.fd.forcePower )
02239                                 continue;
02240                         if (OnSameTeam(self, traceEnt) && !g_friendlyFire.integer)
02241                                 continue;
02242                         //this is all to see if we need to start a saber attack, if it's in flight, this doesn't matter
02243                         // find the distance from the edge of the bounding box
02244                         for ( i = 0 ; i < 3 ; i++ ) 
02245                         {
02246                                 if ( center[i] < traceEnt->r.absmin[i] ) 
02247                                 {
02248                                         v[i] = traceEnt->r.absmin[i] - center[i];
02249                                 } else if ( center[i] > traceEnt->r.absmax[i] ) 
02250                                 {
02251                                         v[i] = center[i] - traceEnt->r.absmax[i];
02252                                 } else 
02253                                 {
02254                                         v[i] = 0;
02255                                 }
02256                         }
02257 
02258                         VectorSubtract( traceEnt->r.absmax, traceEnt->r.absmin, size );
02259                         VectorMA( traceEnt->r.absmin, 0.5, size, ent_org );
02260 
02261                         //see if they're in front of me
02262                         //must be within the forward cone
02263                         VectorSubtract( ent_org, center, dir );
02264                         VectorNormalize( dir );
02265                         if ( (dot = DotProduct( dir, forward )) < 0.5 )
02266                                 continue;
02267 
02268                         //must be close enough
02269                         dist = VectorLength( v );
02270                         if ( dist >= radius ) 
02271                         {
02272                                 continue;
02273                         }
02274                 
02275                         //in PVS?
02276                         if ( !traceEnt->r.bmodel && !trap_InPVS( ent_org, self->client->ps.origin ) )
02277                         {//must be in PVS
02278                                 continue;
02279                         }
02280 
02281                         //Now check and see if we can actually hit it
02282                         trap_Trace( &tr, self->client->ps.origin, vec3_origin, vec3_origin, ent_org, self->s.number, MASK_SHOT );
02283                         if ( tr.fraction < 1.0f && tr.entityNum != traceEnt->s.number )
02284                         {//must have clear LOS
02285                                 continue;
02286                         }
02287 
02288                         // ok, we are within the radius, add us to the incoming list
02289                         ForceDrainDamage( self, traceEnt, dir, ent_org );
02290                         gotOneOrMore = 1;
02291                 }
02292         }
02293         else
02294         {//trace-line
02295                 VectorMA( self->client->ps.origin, 2048, forward, end );
02296                 
02297                 trap_Trace( &tr, self->client->ps.origin, vec3_origin, vec3_origin, end, self->s.number, MASK_SHOT );
02298                 if ( tr.entityNum == ENTITYNUM_NONE || tr.fraction == 1.0 || tr.allsolid || tr.startsolid || !g_entities[tr.entityNum].client || !g_entities[tr.entityNum].inuse )
02299                 {
02300                         return 0;
02301                 }
02302                 
02303                 traceEnt = &g_entities[tr.entityNum];
02304                 ForceDrainDamage( self, traceEnt, forward, tr.endpos );
02305                 gotOneOrMore = 1;
02306         }
02307 
02308         self->client->ps.activeForcePass = self->client->ps.fd.forcePowerLevel[FP_DRAIN] + FORCE_LEVEL_3;
02309 
02310         BG_ForcePowerDrain( &self->client->ps, FP_DRAIN, 5 ); //used to be 1, but this did, too, anger the God of Balance.
02311 
02312         self->client->ps.fd.forcePowerRegenDebounceTime = level.time + 500;
02313 
02314         return gotOneOrMore;
02315 }

void ForceShootLightning gentity_t self  ) 
 

Definition at line 1902 of file w_force.c.

References entityShared_t::absmax, entityShared_t::absmin, trace_t::allsolid, AngleVectors(), entityShared_t::bmodel, gentity_s::client, DotProduct, trace_t::endpos, trace_t::entityNum, ENTITYNUM_NONE, playerState_s::fd, FORCE_LEVEL_2, FORCE_LIGHTNING_RADIUS, ForceLightningDamage(), forcedata_s::forcePowerLevel, FP_LIGHTNING, trace_t::fraction, g_entities, g_friendlyFire, gentity_t, gentity_s::health, vmCvar_t::integer, gentity_s::inuse, MASK_SHOT, MAX_GENTITIES, NULL, entityState_s::number, OnSameTeam(), playerState_s::origin, entityShared_t::ownerNum, gclient_s::ps, gentity_s::r, gentity_s::s, trace_t::startsolid, gentity_s::takedamage, trap_EntitiesInBox(), trap_InPVS(), trap_Trace(), vec3_origin, vec3_t, VectorCopy, VectorMA, VectorNormalize(), VectorSubtract, playerState_s::viewangles, entityState_s::weapon, and WP_THERMAL.

01903 {
01904         trace_t tr;
01905         vec3_t  end, forward;
01906         gentity_t       *traceEnt;
01907 
01908         if ( self->health <= 0 )
01909         {
01910                 return;
01911         }
01912         AngleVectors( self->client->ps.viewangles, forward, NULL, NULL );
01913         VectorNormalize( forward );
01914 
01915         if ( self->client->ps.fd.forcePowerLevel[FP_LIGHTNING] > FORCE_LEVEL_2 )
01916         {//arc
01917                 vec3_t  center, mins, maxs, dir, ent_org, size, v;
01918                 float   radius = FORCE_LIGHTNING_RADIUS, dot, dist;
01919                 gentity_t       *entityList[MAX_GENTITIES];
01920                 int                     iEntityList[MAX_GENTITIES];
01921                 int             e, numListedEntities, i;
01922 
01923                 VectorCopy( self->client->ps.origin, center );
01924                 for ( i = 0 ; i < 3 ; i++ ) 
01925                 {
01926                         mins[i] = center[i] - radius;
01927                         maxs[i] = center[i] + radius;
01928                 }
01929                 numListedEntities = trap_EntitiesInBox( mins, maxs, iEntityList, MAX_GENTITIES );
01930 
01931                 i = 0;
01932                 while (i < numListedEntities)
01933                 {
01934                         entityList[i] = &g_entities[iEntityList[i]];
01935 
01936                         i++;
01937                 }
01938 
01939                 for ( e = 0 ; e < numListedEntities ; e++ ) 
01940                 {
01941                         traceEnt = entityList[e];
01942 
01943                         if ( !traceEnt )
01944                                 continue;
01945                         if ( traceEnt == self )
01946                                 continue;
01947                         if ( traceEnt->r.ownerNum == self->s.number && traceEnt->s.weapon != WP_THERMAL )//can push your own thermals
01948                                 continue;
01949                         if ( !traceEnt->inuse )
01950                                 continue;
01951                         if ( !traceEnt->takedamage )
01952                                 continue;
01953                         if ( traceEnt->health <= 0 )//no torturing corpses
01954                                 continue;
01955                         if ( !g_friendlyFire.integer && OnSameTeam(self, traceEnt))
01956                                 continue;
01957                         //this is all to see if we need to start a saber attack, if it's in flight, this doesn't matter
01958                         // find the distance from the edge of the bounding box
01959                         for ( i = 0 ; i < 3 ; i++ ) 
01960                         {
01961                                 if ( center[i] < traceEnt->r.absmin[i] ) 
01962                                 {
01963                                         v[i] = traceEnt->r.absmin[i] - center[i];
01964                                 } else if ( center[i] > traceEnt->r.absmax[i] ) 
01965                                 {
01966                                         v[i] = center[i] - traceEnt->r.absmax[i];
01967                                 } else 
01968                                 {
01969                                         v[i] = 0;
01970                                 }
01971                         }
01972 
01973                         VectorSubtract( traceEnt->r.absmax, traceEnt->r.absmin, size );
01974                         VectorMA( traceEnt->r.absmin, 0.5, size, ent_org );
01975 
01976                         //see if they're in front of me
01977                         //must be within the forward cone
01978                         VectorSubtract( ent_org, center, dir );
01979                         VectorNormalize( dir );
01980                         if ( (dot = DotProduct( dir, forward )) < 0.5 )
01981                                 continue;
01982 
01983                         //must be close enough
01984                         dist = VectorLength( v );
01985                         if ( dist >= radius ) 
01986                         {
01987                                 continue;
01988                         }
01989                 
01990                         //in PVS?
01991                         if ( !traceEnt->r.bmodel && !trap_InPVS( ent_org, self->client->ps.origin ) )
01992                         {//must be in PVS
01993                                 continue;
01994                         }
01995 
01996                         //Now check and see if we can actually hit it
01997                         trap_Trace( &tr, self->client->ps.origin, vec3_origin, vec3_origin, ent_org, self->s.number, MASK_SHOT );
01998                         if ( tr.fraction < 1.0f && tr.entityNum != traceEnt->s.number )
01999                         {//must have clear LOS
02000                                 continue;
02001                         }
02002 
02003                         // ok, we are within the radius, add us to the incoming list
02004                         ForceLightningDamage( self, traceEnt, dir, ent_org );
02005                 }
02006         }
02007         else
02008         {//trace-line
02009                 VectorMA( self->client->ps.origin, 2048, forward, end );
02010                 
02011                 trap_Trace( &tr, self->client->ps.origin, vec3_origin, vec3_origin, end, self->s.number, MASK_SHOT );
02012                 if ( tr.entityNum == ENTITYNUM_NONE || tr.fraction == 1.0 || tr.allsolid || tr.startsolid )
02013                 {
02014                         return;
02015                 }
02016                 
02017                 traceEnt = &g_entities[tr.entityNum];
02018                 ForceLightningDamage( self, traceEnt, forward, tr.endpos );
02019         }
02020 }

void ForceSpeed gentity_t self,
int  forceDuration
 

Definition at line 1596 of file w_force.c.

References CHAN_BODY, gentity_s::client, ENTITYNUM_WORLD, playerState_s::fd, playerState_s::forceAllowDeactivateTime, forcedata_s::forcePowersActive, FP_SPEED, g_entities, G_Sound(), G_SoundIndex(), gentity_t, gentity_s::health, gclient_s::holdingObjectiveItem, level, MAX_CLIENTS, gclient_s::ps, speedLoopSound, level_locals_t::time, TRACK_CHANNEL_2, WP_ForcePowerStart(), WP_ForcePowerStop(), and WP_ForcePowerUsable().

Referenced by ClientThink_real(), Jedi_DodgeEvasion(), and WP_DoSpecificPower().

01597 {
01598         if ( self->health <= 0 )
01599         {
01600                 return;
01601         }
01602 
01603         if (self->client->ps.forceAllowDeactivateTime < level.time &&
01604                 (self->client->ps.fd.forcePowersActive & (1 << FP_SPEED)) )
01605         {
01606                 WP_ForcePowerStop( self, FP_SPEED );
01607                 return;
01608         }
01609 
01610         if ( !WP_ForcePowerUsable( self, FP_SPEED ) )
01611         {
01612                 return;
01613         }
01614 
01615         if ( self->client->holdingObjectiveItem >= MAX_CLIENTS  
01616                 && self->client->holdingObjectiveItem < ENTITYNUM_WORLD )
01617         {//holding Siege item
01618                 if ( g_entities[self->client->holdingObjectiveItem].genericValue15 )
01619                 {//disables force powers
01620                         return;
01621                 }
01622         }
01623 
01624         self->client->ps.forceAllowDeactivateTime = level.time + 1500;
01625 
01626         WP_ForcePowerStart( self, FP_SPEED, forceDuration );
01627         G_Sound( self, CHAN_BODY, G_SoundIndex("sound/weapons/force/speed.wav") );
01628         G_Sound( self, TRACK_CHANNEL_2, speedLoopSound );
01629 }

void ForceTeamForceReplenish gentity_t self  ) 
 

Definition at line 1424 of file w_force.c.

References BG_ForcePowerDrain(), gentity_s::client, EV_TEAM_POWER, entityState_s::eventParm, playerState_s::fd, FORCE_LEVEL_2, FORCE_LEVEL_3, forcedata_s::forcePower, forcedata_s::forcePowerDebounce, forcedata_s::forcePowerLevel, forcePowerNeeded, ForcePowerUsableOn(), FP_TEAM_FORCE, g_entities, G_TempEntity(), gentity_t, gentity_s::health, level, MAX_CLIENTS, NULL, OnSameTeam(), playerState_s::origin, gclient_s::ps, gentity_s::s, level_locals_t::time, trap_InPVS(), vec3_t, VectorSubtract, WP_AddToClientBitflags(), and WP_ForcePowerUsable().

Referenced by ClientThink_real(), and WP_DoSpecificPower().

01425 {
01426         float radius = 256;
01427         int i = 0;
01428         gentity_t *ent;
01429         vec3_t a;
01430         int numpl = 0;
01431         int pl[MAX_CLIENTS];
01432         int poweradd = 0;
01433         gentity_t *te = NULL;
01434 
01435         if ( self->health <= 0 )
01436         {
01437                 return;
01438         }
01439 
01440         if ( !WP_ForcePowerUsable( self, FP_TEAM_FORCE ) )
01441         {
01442                 return;
01443         }
01444 
01445         if (self->client->ps.fd.forcePowerDebounce[FP_TEAM_FORCE] >= level.time)
01446         {
01447                 return;
01448         }
01449 
01450         if (self->client->ps.fd.forcePowerLevel[FP_TEAM_FORCE] == FORCE_LEVEL_2)
01451         {
01452                 radius *= 1.5;
01453         }
01454         if (self->client->ps.fd.forcePowerLevel[FP_TEAM_FORCE] == FORCE_LEVEL_3)
01455         {
01456                 radius *= 2;
01457         }
01458 
01459         while (i < MAX_CLIENTS)
01460         {
01461                 ent = &g_entities[i];
01462 
01463                 if (ent && ent->client && self != ent && OnSameTeam(self, ent) && ent->client->ps.fd.forcePower < 100 && ForcePowerUsableOn(self, ent, FP_TEAM_FORCE) &&
01464                         trap_InPVS(self->client->ps.origin, ent->client->ps.origin))
01465                 {
01466                         VectorSubtract(self->client->ps.origin, ent->client->ps.origin, a);
01467 
01468                         if (VectorLength(a) <= radius)
01469                         {
01470                                 pl[numpl] = i;
01471                                 numpl++;
01472                         }
01473                 }
01474 
01475                 i++;
01476         }
01477 
01478         if (numpl < 1)
01479         {
01480                 return;
01481         }
01482 
01483         if (numpl == 1)
01484         {
01485                 poweradd = 50;
01486         }
01487         else if (numpl == 2)
01488         {
01489                 poweradd = 33;
01490         }
01491         else
01492         {
01493                 poweradd = 25;
01494         }
01495         self->client->ps.fd.forcePowerDebounce[FP_TEAM_FORCE] = level.time + 2000;
01496 
01497         BG_ForcePowerDrain( &self->client->ps, FP_TEAM_FORCE, forcePowerNeeded[self->client->ps.fd.forcePowerLevel[FP_TEAM_FORCE]][FP_TEAM_FORCE] );
01498 
01499         i = 0;
01500 
01501         while (i < numpl)
01502         {
01503                 g_entities[pl[i]].client->ps.fd.forcePower += poweradd;
01504                 if (g_entities[pl[i]].client->ps.fd.forcePower > 100)
01505                 {
01506                         g_entities[pl[i]].client->ps.fd.forcePower = 100;
01507                 }
01508 
01509                 //At this point we know we got one, so add him into the collective event client bitflag
01510                 if (!te)
01511                 {
01512                         te = G_TempEntity( self->client->ps.origin, EV_TEAM_POWER);
01513                         te->s.eventParm = 2; //eventParm 1 is heal, eventParm 2 is force regen
01514                 }
01515 
01516                 WP_AddToClientBitflags(te, pl[i]);
01517                 //Now cramming it all into one event.. doing this many g_sound events at once was a Bad Thing.
01518                 
01519                 i++;
01520         }
01521 }

void ForceTeamHeal gentity_t self  ) 
 

Definition at line 1319 of file w_force.c.

References BG_ForcePowerDrain(), gentity_s::client, EV_TEAM_POWER, entityState_s::eventParm, playerState_s::fd, FORCE_LEVEL_2, FORCE_LEVEL_3, forcedata_s::forcePowerDebounce, forcedata_s::forcePowerLevel, forcePowerNeeded, ForcePowerUsableOn(), FP_TEAM_HEAL, g_entities, G_TempEntity(), gentity_t, gentity_s::health, level, MAX_CLIENTS, NULL, OnSameTeam(), playerState_s::origin, gclient_s::ps, gentity_s::s, STAT_HEALTH, STAT_MAX_HEALTH, playerState_s::stats, level_locals_t::time, trap_InPVS(), vec3_t, VectorSubtract, WP_AddToClientBitflags(), and WP_ForcePowerUsable().

Referenced by ClientThink_real(), and WP_DoSpecificPower().

01320 {
01321         float radius = 256;
01322         int i = 0;
01323         gentity_t *ent;
01324         vec3_t a;
01325         int numpl = 0;
01326         int pl[MAX_CLIENTS];
01327         int healthadd = 0;
01328         gentity_t *te = NULL;
01329 
01330         if ( self->health <= 0 )
01331         {
01332                 return;
01333         }
01334 
01335         if ( !WP_ForcePowerUsable( self, FP_TEAM_HEAL ) )
01336         {
01337                 return;
01338         }
01339 
01340         if (self->client->ps.fd.forcePowerDebounce[FP_TEAM_HEAL] >= level.time)
01341         {
01342                 return;
01343         }
01344 
01345         if (self->client->ps.fd.forcePowerLevel[FP_TEAM_HEAL] == FORCE_LEVEL_2)
01346         {
01347                 radius *= 1.5;
01348         }
01349         if (self->client->ps.fd.forcePowerLevel[FP_TEAM_HEAL] == FORCE_LEVEL_3)
01350         {
01351                 radius *= 2;
01352         }
01353 
01354         while (i < MAX_CLIENTS)
01355         {
01356                 ent = &g_entities[i];
01357 
01358                 if (ent && ent->client && self != ent && OnSameTeam(self, ent) && ent->client->ps.stats[STAT_HEALTH] < ent->client->ps.stats[STAT_MAX_HEALTH] && ent->client->ps.stats[STAT_HEALTH] > 0 && ForcePowerUsableOn(self, ent, FP_TEAM_HEAL) &&
01359                         trap_InPVS(self->client->ps.origin, ent->client->ps.origin))
01360                 {
01361                         VectorSubtract(self->client->ps.origin, ent->client->ps.origin, a);
01362 
01363                         if (VectorLength(a) <= radius)
01364                         {
01365                                 pl[numpl] = i;
01366                                 numpl++;
01367                         }
01368                 }
01369 
01370                 i++;
01371         }
01372 
01373         if (numpl < 1)
01374         {
01375                 return;
01376         }
01377 
01378         if (numpl == 1)
01379         {
01380                 healthadd = 50;
01381         }
01382         else if (numpl == 2)
01383         {
01384                 healthadd = 33;
01385         }
01386         else
01387         {
01388                 healthadd = 25;
01389         }
01390 
01391         self->client->ps.fd.forcePowerDebounce[FP_TEAM_HEAL] = level.time + 2000;
01392         i = 0;
01393 
01394         while (i < numpl)
01395         {
01396                 if (g_entities[pl[i]].client->ps.stats[STAT_HEALTH] > 0 &&
01397                         g_entities[pl[i]].health > 0)
01398                 {
01399                         g_entities[pl[i]].client->ps.stats[STAT_HEALTH] += healthadd;
01400                         if (g_entities[pl[i]].client->ps.stats[STAT_HEALTH] > g_entities[pl[i]].client->ps.stats[STAT_MAX_HEALTH])
01401                         {
01402                                 g_entities[pl[i]].client->ps.stats[STAT_HEALTH] = g_entities[pl[i]].client->ps.stats[STAT_MAX_HEALTH];
01403                         }
01404 
01405                         g_entities[pl[i]].health = g_entities[pl[i]].client->ps.stats[STAT_HEALTH];
01406 
01407                         //At this point we know we got one, so add him into the collective event client bitflag
01408                         if (!te)
01409                         {
01410                                 te = G_TempEntity( self->client->ps.origin, EV_TEAM_POWER);
01411                                 te->s.eventParm = 1; //eventParm 1 is heal, eventParm 2 is force regen
01412 
01413                                 //since we had an extra check above, do the drain now because we got at least one guy
01414                                 BG_ForcePowerDrain( &self->client->ps, FP_TEAM_HEAL, forcePowerNeeded[self->client->ps.fd.forcePowerLevel[FP_TEAM_HEAL]][FP_TEAM_HEAL] );
01415                         }
01416 
01417                         WP_AddToClientBitflags(te, pl[i]);
01418                         //Now cramming it all into one event.. doing this many g_sound events at once was a Bad Thing.
01419                 }
01420                 i++;
01421         }
01422 }

void ForceTelepathy gentity_t self  ) 
 

Definition at line 2723 of file w_force.c.

References AngleVectors(), CHAN_AUTO, gentity_s::client, trace_t::entityNum, ENTITYNUM_NONE, playerState_s::fd, FORCE_LEVEL_1, FORCE_LEVEL_2, FORCE_LEVEL_3, playerState_s::forceAllowDeactivateTime, playerState_s::forceHandExtend, playerState_s::forceHandExtendTime, forcedata_s::forcePowerLevel, forcedata_s::forcePowersActive, ForcePowerUsableOn(), ForceTelepathyCheckDirectNPCTarget(), FP_TELEPATHY, trace_t::fraction, g_entities, G_Sound(), G_SoundIndex(), gentity_t, HANDEXTEND_FORCEPUSH, HANDEXTEND_NONE, gentity_s::health, InFieldOfVision(), level, MAX_GENTITIES, MAX_TRICK_DISTANCE, NULL, entityState_s::number, OnSameTeam(), playerState_s::origin, entityState_s::pos, playerState_s::powerups, gclient_s::ps, PW_BLUEFLAG, PW_REDFLAG, qboolean, qfalse, qtrue, gentity_s::s, TEAM_SPECTATOR, level_locals_t::time, trap_EntitiesInBox(), trajectory_t::trBase, vec3_t, vectoangles(), VectorCopy, VectorSubtract, playerState_s::viewangles, playerState_s::viewheight, playerState_s::weaponTime, WP_AddAsMindtricked(), WP_ForcePowerStart(), WP_ForcePowerStop(), and WP_ForcePowerUsable().

Referenced by ClientThink_real(), and WP_DoSpecificPower().

02724 {
02725         trace_t tr;
02726         vec3_t tto, thispush_org, a;
02727         vec3_t mins, maxs, fwdangles, forward, right, center;
02728         int i;
02729         float visionArc = 0;
02730         float radius = MAX_TRICK_DISTANCE;
02731         qboolean        tookPower = qfalse;
02732 
02733         if ( self->health <= 0 )
02734         {
02735                 return;
02736         }
02737 
02738         if (self->client->ps.forceHandExtend != HANDEXTEND_NONE)
02739         {
02740                 return;
02741         }
02742 
02743         if (self->client->ps.weaponTime > 0)
02744         {
02745                 return;
02746         }
02747 
02748         if (self->client->ps.powerups[PW_REDFLAG] ||
02749                 self->client->ps.powerups[PW_BLUEFLAG])
02750         { //can't mindtrick while carrying the flag
02751                 return;
02752         }
02753 
02754         if (self->client->ps.forceAllowDeactivateTime < level.time &&
02755                 (self->client->ps.fd.forcePowersActive & (1 << FP_TELEPATHY)) )
02756         {
02757                 WP_ForcePowerStop( self, FP_TELEPATHY );
02758                 return;
02759         }
02760 
02761         if ( !WP_ForcePowerUsable( self, FP_TELEPATHY ) )
02762         {
02763                 return;
02764         }
02765 
02766         if ( ForceTelepathyCheckDirectNPCTarget( self, &tr, &tookPower ) )
02767         {//hit an NPC directly
02768                 self->client->ps.forceAllowDeactivateTime = level.time + 1500;
02769                 G_Sound( self, CHAN_AUTO, G_SoundIndex("sound/weapons/force/distract.wav") );
02770                 self->client->ps.forceHandExtend = HANDEXTEND_FORCEPUSH;
02771                 self->client->ps.forceHandExtendTime = level.time + 1000;
02772                 return;
02773         }
02774 
02775         if (self->client->ps.fd.forcePowerLevel[FP_TELEPATHY] == FORCE_LEVEL_2)
02776         {
02777                 visionArc = 180;
02778         }
02779         else if (self->client->ps.fd.forcePowerLevel[FP_TELEPATHY] == FORCE_LEVEL_3)
02780         {
02781                 visionArc = 360;
02782                 radius = MAX_TRICK_DISTANCE*2.0f;
02783         }
02784 
02785         VectorCopy( self->client->ps.viewangles, fwdangles );
02786         AngleVectors( fwdangles, forward, right, NULL );
02787         VectorCopy( self->client->ps.origin, center );
02788 
02789         for ( i = 0 ; i < 3 ; i++ ) 
02790         {
02791                 mins[i] = center[i] - radius;
02792                 maxs[i] = center[i] + radius;
02793         }
02794 
02795         if (self->client->ps.fd.forcePowerLevel[FP_TELEPATHY] == FORCE_LEVEL_1)
02796         {
02797                 if (tr.fraction != 1.0 &&
02798                         tr.entityNum != ENTITYNUM_NONE &&
02799                         g_entities[tr.entityNum].inuse &&
02800                         g_entities[tr.entityNum].client &&
02801                         g_entities[tr.entityNum].client->pers.connected &&
02802                         g_entities[tr.entityNum].client->sess.sessionTeam != TEAM_SPECTATOR)
02803                 {
02804                         WP_AddAsMindtricked(&self->client->ps.fd, tr.entityNum);
02805                         if ( !tookPower )
02806                         {
02807                                 WP_ForcePowerStart( self, FP_TELEPATHY, 0 );
02808                         }
02809 
02810                         G_Sound( self, CHAN_AUTO, G_SoundIndex("sound/weapons/force/distract.wav") );
02811 
02812                         self->client->ps.forceHandExtend = HANDEXTEND_FORCEPUSH;
02813                         self->client->ps.forceHandExtendTime = level.time + 1000;
02814 
02815                         return;
02816                 }
02817                 else
02818                 {
02819                         return;
02820                 }
02821         }
02822         else    //level 2 & 3
02823         {
02824                 gentity_t *ent;
02825                 int entityList[MAX_GENTITIES];
02826                 int numListedEntities;
02827                 int e = 0;
02828                 qboolean gotatleastone = qfalse;
02829 
02830                 numListedEntities = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );
02831 
02832                 while (e < numListedEntities)
02833                 {
02834                         ent = &g_entities[entityList[e]];
02835 
02836                         if (ent)
02837                         { //not in the arc, don't consider it
02838                                 if (ent->client)
02839                                 {
02840                                         VectorCopy(ent->client->ps.origin, thispush_org);
02841                                 }
02842                                 else
02843                                 {
02844                                         VectorCopy(ent->s.pos.trBase, thispush_org);
02845                                 }
02846                                 VectorCopy(self->client->ps.origin, tto);
02847                                 tto[2] += self->client->ps.viewheight;
02848                                 VectorSubtract(thispush_org, tto, a);
02849                                 vectoangles(a, a);
02850 
02851                                 if (!ent->client)
02852                                 {
02853                                         entityList[e] = ENTITYNUM_NONE;
02854                                 }
02855                                 else if (!InFieldOfVision(self->client->ps.viewangles, visionArc, a))
02856                                 { //only bother with arc rules if the victim is a client
02857                                         entityList[e] = ENTITYNUM_NONE;
02858                                 }
02859                                 else if (!ForcePowerUsableOn(self, ent, FP_TELEPATHY))
02860                                 {
02861                                         entityList[e] = ENTITYNUM_NONE;
02862                                 }
02863                                 else if (OnSameTeam(self, ent))
02864                                 {
02865                                         entityList[e] = ENTITYNUM_NONE;
02866                                 }
02867                         }
02868                         ent = &g_entities[entityList[e]];
02869                         if (ent && ent != self && ent->client)
02870                         {
02871                                 gotatleastone = qtrue;
02872                                 WP_AddAsMindtricked(&self->client->ps.fd, ent->s.number);
02873                         }
02874                         e++;
02875                 }
02876 
02877                 if (gotatleastone)
02878                 {
02879                         self->client->ps.forceAllowDeactivateTime = level.time + 1500;
02880 
02881                         if ( !tookPower )
02882                         {
02883                                 WP_ForcePowerStart( self, FP_TELEPATHY, 0 );
02884                         }
02885 
02886                         G_Sound( self, CHAN_AUTO, G_SoundIndex("sound/weapons/force/distract.wav") );
02887 
02888                         self->client->ps.forceHandExtend = HANDEXTEND_FORCEPUSH;
02889                         self->client->ps.forceHandExtendTime = level.time + 1000;
02890                 }
02891         }
02892 
02893 }

qboolean ForceTelepathyCheckDirectNPCTarget gentity_t self,
trace_t tr,
qboolean tookPower
 

Definition at line 2527 of file w_force.c.

References AddSightEvent(), AddSoundEvent(), AEL_SUSPICIOUS, trace_t::allsolid, AngleVectors(), BLOCKED_NONE, BSET_MINDTRICK, gNPC_t::charmedTime, CLASS_ATST, CLASS_BOBAFETT, CLASS_GALAKMECH, CLASS_GONK, CLASS_MARK1, CLASS_MARK2, CLASS_MOUSE, CLASS_PROBE, CLASS_PROTOCOL, CLASS_R2D2, CLASS_R5D2, CLASS_RANCOR, CLASS_REBORN, CLASS_REMOTE, CLASS_SEEKER, gentity_s::client, gNPC_t::confusionTime, trace_t::endpos, gentity_s::enemy, gclient_s::enemyTeam, trace_t::entityNum, ENTITYNUM_NONE, renderInfo_s::eyeAngles, renderInfo_s::eyePoint, playerState_s::fd, FORCE_LEVEL_1, FORCE_LEVEL_2, forcedata_s::forcePowerLevel, FP_TELEPATHY, trace_t::fraction, G_ActivateBehavior(), G_ClearEnemy(), G_EffectIndex(), g_entities, G_PlayEffectID(), gentity_s::genericValue1, gentity_s::genericValue2, gentity_s::genericValue3, gentity_t, gclient_s::leader, level, MASK_PLAYERSOLID, MAX_CLIENTS, MAX_TRICK_DISTANCE, mindTrickTime, cplane_s::normal, gentity_s::NPC, gclient_s::NPC_class, NPC_Jedi_PlayConfusionSound(), NPC_PlayConfusionSound(), NPC_UseResponse(), NPCTEAM_ENEMY, NPCTEAM_NEUTRAL, NPCTEAM_PLAYER, NULL, entityState_s::number, playerState_s::origin, trace_t::plane, gclient_s::playerTeam, PM_DEAD, playerState_s::pm_type, gclient_s::ps, qboolean, qfalse, qtrue, gclient_s::renderInfo, gentity_s::s, playerState_s::saberBlocked, SCF_NO_FORCE, SCF_NO_MIND_TRICK, SCF_NO_RESPONSE, gNPC_t::scriptFlags, gclient_s::sess, clientSession_t::sessionTeam, trace_t::startsolid, TEAM_BLUE, TEAM_RED, entityState_s::teamowner, level_locals_t::time, trap_Trace(), vec3_t, VectorCopy, VectorNormalize(), playerState_s::viewangles, playerState_s::viewheight, entityState_s::weapon, playerState_s::weaponTime, WP_ForcePowerStart(), WP_NONE, and WP_SABER.

Referenced by ForceTelepathy().

02528 {
02529         gentity_t       *traceEnt;
02530         qboolean        targetLive = qfalse, mindTrickDone = qfalse;
02531         vec3_t          tfrom, tto, fwd;
02532         float           radius = MAX_TRICK_DISTANCE;
02533 
02534         //Check for a direct usage on NPCs first
02535         VectorCopy(self->client->ps.origin, tfrom);
02536         tfrom[2] += self->client->ps.viewheight;
02537         AngleVectors(self->client->ps.viewangles, fwd, NULL, NULL);
02538         tto[0] = tfrom[0] + fwd[0]*radius/2;
02539         tto[1] = tfrom[1] + fwd[1]*radius/2;
02540         tto[2] = tfrom[2] + fwd[2]*radius/2;
02541 
02542         trap_Trace( tr, tfrom, NULL, NULL, tto, self->s.number, MASK_PLAYERSOLID );
02543         
02544         if ( tr->entityNum == ENTITYNUM_NONE 
02545                 || tr->fraction == 1.0f
02546                 || tr->allsolid 
02547                 || tr->startsolid )
02548         {
02549                 return qfalse;
02550         }
02551         
02552         traceEnt = &g_entities[tr->entityNum];
02553         
02554         if( traceEnt->NPC 
02555                 && traceEnt->NPC->scriptFlags & SCF_NO_FORCE )
02556         {
02557                 return qfalse;
02558         }
02559 
02560         if ( traceEnt && traceEnt->client  )
02561         {
02562                 switch ( traceEnt->client->NPC_class )
02563                 {
02564                 case CLASS_GALAKMECH://cant grip him, he's in armor
02565                 case CLASS_ATST://much too big to grip!
02566                 //no droids either
02567                 case CLASS_PROBE:
02568                 case CLASS_GONK:
02569                 case CLASS_R2D2:
02570                 case CLASS_R5D2:
02571                 case CLASS_MARK1:
02572                 case CLASS_MARK2:
02573                 case CLASS_MOUSE:
02574                 case CLASS_SEEKER:
02575                 case CLASS_REMOTE:
02576                 case CLASS_PROTOCOL:
02577                 case CLASS_BOBAFETT:
02578                 case CLASS_RANCOR:
02579                         break;
02580                 default:
02581                         targetLive = qtrue;
02582                         break;
02583                 }
02584         }
02585 
02586         if ( traceEnt->s.number < MAX_CLIENTS )
02587         {//a regular client
02588                 return qfalse;
02589         }
02590 
02591         if ( targetLive && traceEnt->NPC )
02592         {//hit an organic non-player
02593                 vec3_t  eyeDir;
02594                 if ( G_ActivateBehavior( traceEnt, BSET_MINDTRICK ) )
02595                 {//activated a script on him
02596                         //FIXME: do the visual sparkles effect on their heads, still?
02597                         WP_ForcePowerStart( self, FP_TELEPATHY, 0 );
02598                 }
02599                 else if ( (self->NPC && traceEnt->client->playerTeam != self->client->playerTeam)
02600                         || (!self->NPC && traceEnt->client->playerTeam != self->client->sess.sessionTeam) )
02601                 {//an enemy
02602                         int override = 0;
02603                         if ( (traceEnt->NPC->scriptFlags&SCF_NO_MIND_TRICK) )
02604                         {
02605                         }
02606                         else if ( traceEnt->s.weapon != WP_SABER 
02607                                 && traceEnt->client->NPC_class != CLASS_REBORN )
02608                         {//haha!  Jedi aren't easily confused!
02609                                 if ( self->client->ps.fd.forcePowerLevel[FP_TELEPATHY] > FORCE_LEVEL_2 )
02610                                 {//turn them to our side
02611                                         //if mind trick 3 and aiming at an enemy need more force power
02612                                         if ( traceEnt->s.weapon != WP_NONE )
02613                                         {//don't charm people who aren't capable of fighting... like ugnaughts and droids
02614                                                 int newPlayerTeam, newEnemyTeam;
02615 
02616                                                 if ( traceEnt->enemy )
02617                                                 {
02618                                                         G_ClearEnemy( traceEnt );
02619                                                 }
02620                                                 if ( traceEnt->NPC )
02621                                                 {
02622                                                         //traceEnt->NPC->tempBehavior = BS_FOLLOW_LEADER;
02623                                                         traceEnt->client->leader = self;
02624                                                 }
02625                                                 //FIXME: maybe pick an enemy right here?
02626                                                 if ( self->NPC )
02627                                                 {//NPC
02628                                                         newPlayerTeam = self->client->playerTeam;
02629                                                         newEnemyTeam = self->client->enemyTeam;
02630                                                 }
02631                                                 else
02632                                                 {//client/bot
02633                                                         if ( self->client->sess.sessionTeam == TEAM_BLUE )
02634                                                         {//rebel
02635                                                                 newPlayerTeam = NPCTEAM_PLAYER;
02636                                                                 newEnemyTeam = NPCTEAM_ENEMY;
02637                                                         }
02638                                                         else if ( self->client->sess.sessionTeam == TEAM_RED )
02639                                                         {//imperial
02640                                                                 newPlayerTeam = NPCTEAM_ENEMY;
02641                                                                 newEnemyTeam = NPCTEAM_PLAYER;
02642                                                         }
02643                                                         else
02644                                                         {//neutral - wan't attack anyone
02645                                                                 newPlayerTeam = NPCTEAM_NEUTRAL;
02646                                                                 newEnemyTeam = NPCTEAM_NEUTRAL;
02647                                                         }
02648                                                 }
02649                                                 //store these for retrieval later
02650                                                 traceEnt->genericValue1 = traceEnt->client->playerTeam;
02651                                                 traceEnt->genericValue2 = traceEnt->client->enemyTeam;
02652                                                 traceEnt->genericValue3 = traceEnt->s.teamowner;
02653                                                 //set the new values
02654                                                 traceEnt->client->playerTeam = newPlayerTeam;
02655                                                 traceEnt->client->enemyTeam = newEnemyTeam;
02656                                                 traceEnt->s.teamowner = newPlayerTeam;
02657                                                 //FIXME: need a *charmed* timer on this...?  Or do TEAM_PLAYERS assume that "confusion" means they should switch to team_enemy when done?
02658                                                 traceEnt->NPC->charmedTime = level.time + mindTrickTime[self->client->ps.fd.forcePowerLevel[FP_TELEPATHY]];
02659                                         }
02660                                 }
02661                                 else
02662                                 {//just confuse them
02663                                         //somehow confuse them?  Set don't fire to true for a while?  Drop their aggression?  Maybe just take their enemy away and don't let them pick one up for a while unless shot?
02664                                         traceEnt->NPC->confusionTime = level.time + mindTrickTime[self->client->ps.fd.forcePowerLevel[FP_TELEPATHY]];//confused for about 10 seconds
02665                                         NPC_PlayConfusionSound( traceEnt );
02666                                         if ( traceEnt->enemy )
02667                                         {
02668                                                 G_ClearEnemy( traceEnt );
02669                                         }
02670                                 }
02671                         }
02672                         else
02673                         {
02674                                 NPC_Jedi_PlayConfusionSound( traceEnt );
02675                         }
02676                         WP_ForcePowerStart( self, FP_TELEPATHY, override );
02677                 }
02678                 else if ( traceEnt->client->playerTeam == self->client->playerTeam )
02679                 {//an ally
02680                         //maybe just have him look at you?  Respond?  Take your enemy?
02681                         if ( traceEnt->client->ps.pm_type < PM_DEAD && traceEnt->NPC!=NULL && !(traceEnt->NPC->scriptFlags&SCF_NO_RESPONSE) )
02682                         {
02683                                 NPC_UseResponse( traceEnt, self, qfalse );
02684                                 WP_ForcePowerStart( self, FP_TELEPATHY, 1 );
02685                         }
02686                 }//NOTE: no effect on TEAM_NEUTRAL?
02687                 AngleVectors( traceEnt->client->renderInfo.eyeAngles, eyeDir, NULL, NULL );
02688                 VectorNormalize( eyeDir );
02689                 G_PlayEffectID( G_EffectIndex( "force/force_touch" ), traceEnt->client->renderInfo.eyePoint, eyeDir );
02690 
02691                 //make sure this plays and that you cannot press fire for about 1 second after this
02692                 //FIXME: BOTH_FORCEMINDTRICK or BOTH_FORCEDISTRACT
02693                 //NPC_SetAnim( self, SETANIM_TORSO, BOTH_MINDTRICK1, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_RESTART|SETANIM_FLAG_HOLD );
02694                 //FIXME: build-up or delay this until in proper part of anim
02695                 mindTrickDone = qtrue;
02696         }
02697         else 
02698         {
02699                 if ( self->client->ps.fd.forcePowerLevel[FP_TELEPATHY] > FORCE_LEVEL_1 && tr->fraction * 2048 > 64 )
02700                 {//don't create a diversion less than 64 from you of if at power level 1
02701                         //use distraction anim instead
02702                         G_PlayEffectID( G_EffectIndex( "force/force_touch" ), tr->endpos, tr->plane.normal );
02703                         //FIXME: these events don't seem to always be picked up...?
02704                         AddSoundEvent( self, tr->endpos, 512, AEL_SUSPICIOUS, qtrue );//, qtrue );
02705                         AddSightEvent( self, tr->endpos, 512, AEL_SUSPICIOUS, 50 );
02706                         WP_ForcePowerStart( self, FP_TELEPATHY, 0 );
02707                         *tookPower = qtrue;
02708                 }
02709                 //NPC_SetAnim( self, SETANIM_TORSO, BOTH_MINDTRICK2, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_RESTART|SETANIM_FLAG_HOLD );
02710         }
02711         //self->client->ps.saberMove = self->client->ps.saberBounceMove = LS_READY;//don't finish whatever saber anim you may have been in
02712         self->client->ps.saberBlocked = BLOCKED_NONE;
02713         self->client->ps.weaponTime = 1000;
02714         /*
02715         if ( self->client->ps.fd.forcePowersActive&(1<<FP_SPEED) )
02716         {
02717                 self->client->ps.weaponTime = floor( self->client->ps.weaponTime * g_timescale->value );
02718         }
02719         */
02720         return qtrue;
02721 }

void ForceThrow gentity_t self,
qboolean  pull
 

Definition at line 3054 of file w_force.c.

References entityShared_t::absmax, entityShared_t::absmin, trace_t::allsolid, AngleVectors(), BG_KnockDownable(), bgEntity_t, entityShared_t::bmodel, CanCounterThrow(), CHAN_BODY, CLASS_ATST, CLASS_GALAKMECH, CLASS_RANCOR, gentity_s::classname, client, gentity_s::client, gclient_s::dangerTime, DotProduct, EF_INVULNERABLE, EF_MISSILE_STICK, EF_NODRAW, playerState_s::eFlags, entityState_s::eFlags, vehicleInfo_t::Eject, trace_t::entityNum, ENTITYNUM_NONE, ET_ITEM, ET_MISSILE, ET_NPC, entityState_s::eType, playerState_s::fd, FORCE_LEVEL_1, FORCE_LEVEL_2, FORCE_LEVEL_3, playerState_s::forceDodgeAnim, forcedata_s::forceGripBeingGripped, playerState_s::forceHandExtend, playerState_s::forceHandExtendTime, forcedata_s::forcePowerLevel, forcePowerNeeded, ForcePowerUsableOn(), FP_ABSORB, FP_GRIP, FP_PULL, FP_PUSH, trace_t::fraction, g_debugMelee, g_entities, g_gametype, G_InGetUpAnim(), G_LetGoOfWall(), G_ReflectMissile(), G_Sound(), G_SoundIndex(), g_useWhileThrowing, entityState_s::genericenemyindex, gentity_t, GEntity_UseFunc(), GT_SIEGE, HANDEXTEND_FORCEPULL, HANDEXTEND_FORCEPUSH, HANDEXTEND_KNOCKDOWN, HANDEXTEND_NONE, gentity_s::health, InFieldOfVision(), vmCvar_t::integer, gentity_s::inuse, gclient_s::invulnerableTimer, level, playerState_s::m_iVehicleNum, gentity_s::m_pVehicle, Vehicle_s::m_pVehicleInfo, MASK_PLAYERSOLID, MASK_SHOT, MAX_CLIENTS, MAX_GENTITIES, MOVER_POS1, MOVER_POS2, gentity_s::moverState, gclient_s::NPC_class, NULL, entityState_s::number, OnSameTeam(), playerState_s::origin, PMF_STUCK_TO_WALL, entityState_s::pos, playerState_s::powerups, gclient_s::ps, PW_DISINT_4, PW_PULL, Q_irand(), Q_stricmp(), qboolean, qfalse, qtrue, gentity_s::r, gentity_s::s, playerState_s::saberInFlight, playerState_s::saberLockFrame, playerState_s::saberLockHits, playerState_s::saberLockTime, gentity_s::spawnflags, SPF_BUTTON_FPUSHABLE, trace_t::startsolid, level_locals_t::time, TossClientWeapon(), Touch_Button(), TR_INTERPOLATE, TR_STATIONARY, trap_EntitiesInBox(), trap_InPVS(), trap_Trace(), trajectory_t::trBase, trajectory_t::trType, vehicleInfo_t::type, vec3_origin, vec3_t, vectoangles(), VectorAdd, VectorCopy, VectorMA, VectorNormalize(), VectorSubtract, VH_ANIMAL, VH_SPEEDER, playerState_s::viewangles, playerState_s::viewheight, entityState_s::weapon, playerState_s::weapon, playerState_s::weaponTime, WP_AbsorbConversion(), WP_ForcePowerStart(), WP_ForcePowerStop(), WP_ForcePowerUsable(), WP_SABER, and WP_THERMAL.

Referenced by ClientThink_real(), WP_DoSpecificPower(), and WP_SaberStartMissileBlockCheck().

03055 {
03056         //shove things in front of you away
03057         float           dist;
03058         gentity_t       *ent;
03059         int                     entityList[MAX_GENTITIES];
03060         gentity_t       *push_list[MAX_GENTITIES];
03061         int                     numListedEntities;
03062         vec3_t          mins, maxs;
03063         vec3_t          v;
03064         int                     i, e;
03065         int                     ent_count = 0;
03066         int                     radius = 1024; //since it's view-based now. //350;
03067         int                     powerLevel;
03068         int                     visionArc;
03069         int                     pushPower;
03070         int                     pushPowerMod;
03071         vec3_t          center, ent_org, size, forward, right, end, dir, fwdangles = {0};
03072         float           dot1;
03073         trace_t         tr;
03074         int                     x;
03075         vec3_t          pushDir;
03076         vec3_t          thispush_org;
03077         vec3_t          tfrom, tto, fwd, a;
03078         float           knockback = pull?0:200;
03079         int                     powerUse = 0;
03080 
03081         visionArc = 0;
03082 
03083         if (self->client->ps.forceHandExtend != HANDEXTEND_NONE && (self->client->ps.forceHandExtend != HANDEXTEND_KNOCKDOWN || !G_InGetUpAnim(&self->client->ps)))
03084         {
03085                 return;
03086         }
03087 
03088         if (!g_useWhileThrowing.integer && self->client->ps.saberInFlight)
03089         {
03090                 return;
03091         }
03092 
03093         if (self->client->ps.weaponTime > 0)
03094         {
03095                 return;
03096         }
03097 
03098         if ( self->health <= 0 )
03099         {
03100                 return;
03101         }
03102         if ( self->client->ps.powerups[PW_DISINT_4] > level.time )
03103         {
03104                 return;
03105         }
03106         if (pull)
03107         {
03108                 powerUse = FP_PULL;
03109         }
03110         else
03111         {
03112                 powerUse = FP_PUSH;
03113         }
03114 
03115         if ( !WP_ForcePowerUsable( self, powerUse ) )
03116         {
03117                 return;
03118         }
03119 
03120         if (!pull && self->client->ps.saberLockTime > level.time && self->client->ps.saberLockFrame)
03121         {
03122                 G_Sound( self, CHAN_BODY, G_SoundIndex( "sound/weapons/force/push.wav" ) );
03123                 self->client->ps.powerups[PW_DISINT_4] = level.time + 1500;
03124 
03125                 self->client->ps.saberLockHits += self->client->ps.fd.forcePowerLevel[FP_PUSH]*2;
03126 
03127                 WP_ForcePowerStart( self, FP_PUSH, 0 );
03128                 return;
03129         }
03130 
03131         WP_ForcePowerStart( self, powerUse, 0 );
03132 
03133         //make sure this plays and that you cannot press fire for about 1 second after this
03134         if ( pull )
03135         {
03136                 G_Sound( self, CHAN_BODY, G_SoundIndex( "sound/weapons/force/pull.wav" ) );
03137                 if (self->client->ps.forceHandExtend == HANDEXTEND_NONE)
03138                 {
03139                         self->client->ps.forceHandExtend = HANDEXTEND_FORCEPULL;
03140                         if ( g_gametype.integer == GT_SIEGE && self->client->ps.weapon == WP_SABER )
03141                         {//hold less so can attack right after a pull
03142                                 self->client->ps.forceHandExtendTime = level.time + 200;
03143                         }
03144                         else
03145                         {
03146                                 self->client->ps.forceHandExtendTime = level.time + 400;
03147                         }
03148                 }
03149                 self->client->ps.powerups[PW_DISINT_4] = self->client->ps.forceHandExtendTime + 200;
03150                 self->client->ps.powerups[PW_PULL] = self->client->ps.powerups[PW_DISINT_4];
03151         }
03152         else
03153         {
03154                 G_Sound( self, CHAN_BODY, G_SoundIndex( "sound/weapons/force/push.wav" ) );
03155                 if (self->client->ps.forceHandExtend == HANDEXTEND_NONE)
03156                 {
03157                         self->client->ps.forceHandExtend = HANDEXTEND_FORCEPUSH;
03158                         self->client->ps.forceHandExtendTime = level.time + 1000;
03159                 }
03160                 else if (self->client->ps.forceHandExtend == HANDEXTEND_KNOCKDOWN && G_InGetUpAnim(&self->client->ps))
03161                 {
03162                         if (self->client->ps.forceDodgeAnim > 4)
03163                         {
03164                                 self->client->ps.forceDodgeAnim -= 8;
03165                         }
03166                         self->client->ps.forceDodgeAnim += 8; //special case, play push on upper torso, but keep playing current knockdown anim on legs
03167                 }
03168                 self->client->ps.powerups[PW_DISINT_4] = level.time + 1100;
03169                 self->client->ps.powerups[PW_PULL] = 0;
03170         }
03171 
03172         VectorCopy( self->client->ps.viewangles, fwdangles );
03173         AngleVectors( fwdangles, forward, right, NULL );
03174         VectorCopy( self->client->ps.origin, center );
03175 
03176         for ( i = 0 ; i < 3 ; i++ ) 
03177         {
03178                 mins[i] = center[i] - radius;
03179                 maxs[i] = center[i] + radius;
03180         }
03181 
03182 
03183         if (pull)
03184         {
03185                 powerLevel = self->client->ps.fd.forcePowerLevel[FP_PULL];
03186                 pushPower = 256*self->client->ps.fd.forcePowerLevel[FP_PULL];
03187         }
03188         else
03189         {
03190                 powerLevel = self->client->ps.fd.forcePowerLevel[FP_PUSH];
03191                 pushPower = 256*self->client->ps.fd.forcePowerLevel[FP_PUSH];
03192         }
03193 
03194         if (!powerLevel)
03195         { //Shouldn't have made it here..
03196                 return;
03197         }
03198 
03199         if (powerLevel == FORCE_LEVEL_2)
03200         {
03201                 visionArc = 60;
03202         }
03203         else if (powerLevel == FORCE_LEVEL_3)
03204         {
03205                 visionArc = 180;
03206         }
03207 
03208         if (powerLevel == FORCE_LEVEL_1)
03209         { //can only push/pull targeted things at level 1
03210                 VectorCopy(self->client->ps.origin, tfrom);
03211                 tfrom[2] += self->client->ps.viewheight;
03212                 AngleVectors(self->client->ps.viewangles, fwd, NULL, NULL);
03213                 tto[0] = tfrom[0] + fwd[0]*radius/2;
03214                 tto[1] = tfrom[1] + fwd[1]*radius/2;
03215                 tto[2] = tfrom[2] + fwd[2]*radius/2;
03216 
03217                 trap_Trace(&tr, tfrom, NULL, NULL, tto, self->s.number, MASK_PLAYERSOLID);
03218 
03219                 if (tr.fraction != 1.0 &&
03220                         tr.entityNum != ENTITYNUM_NONE)
03221                 {
03222                         if (!g_entities[tr.entityNum].client && g_entities[tr.entityNum].s.eType == ET_NPC)
03223                         { //g2animent
03224                                 if (g_entities[tr.entityNum].s.genericenemyindex < level.time)
03225                                 {
03226                                         g_entities[tr.entityNum].s.genericenemyindex = level.time + 2000;
03227                                 }
03228                         }
03229 
03230                         numListedEntities = 0;
03231                         entityList[numListedEntities] = tr.entityNum;
03232 
03233                         if (pull)
03234                         {
03235                                 if (!ForcePowerUsableOn(self, &g_entities[tr.entityNum], FP_PULL))
03236                                 {
03237                                         return;
03238                                 }
03239                         }
03240                         else
03241                         {
03242                                 if (!ForcePowerUsableOn(self, &g_entities[tr.entityNum], FP_PUSH))
03243                                 {
03244                                         return;
03245                                 }
03246                         }
03247                         numListedEntities++;
03248                 }
03249                 else
03250                 {
03251                         //didn't get anything, so just
03252                         return;
03253                 }
03254         }
03255         else
03256         {
03257                 numListedEntities = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );
03258 
03259                 e = 0;
03260 
03261                 while (e < numListedEntities)
03262                 {
03263                         ent = &g_entities[entityList[e]];
03264 
03265                         if (!ent->client && ent->s.eType == ET_NPC)
03266                         { //g2animent
03267                                 if (ent->s.genericenemyindex < level.time)
03268                                 {
03269                                         ent->s.genericenemyindex = level.time + 2000;
03270                                 }
03271                         }
03272 
03273                         if (ent)
03274                         {
03275                                 if (ent->client)
03276                                 {
03277                                         VectorCopy(ent->client->ps.origin, thispush_org);
03278                                 }
03279                                 else
03280                                 {
03281                                         VectorCopy(ent->s.pos.trBase, thispush_org);
03282                                 }
03283                         }
03284 
03285                         if (ent)
03286                         { //not in the arc, don't consider it
03287                                 VectorCopy(self->client->ps.origin, tto);
03288                                 tto[2] += self->client->ps.viewheight;
03289                                 VectorSubtract(thispush_org, tto, a);
03290                                 vectoangles(a, a);
03291 
03292                                 if (ent->client && !InFieldOfVision(self->client->ps.viewangles, visionArc, a) &&
03293                                         ForcePowerUsableOn(self, ent, powerUse))
03294                                 { //only bother with arc rules if the victim is a client
03295                                         entityList[e] = ENTITYNUM_NONE;
03296                                 }
03297                                 else if (ent->client)
03298                                 {
03299                                         if (pull)
03300                                         {
03301                                                 if (!ForcePowerUsableOn(self, ent, FP_PULL))
03302                                                 {
03303                                                         entityList[e] = ENTITYNUM_NONE;
03304                                                 }
03305                                         }
03306                                         else
03307                                         {
03308                                                 if (!ForcePowerUsableOn(self, ent, FP_PUSH))
03309                                                 {
03310                                                         entityList[e] = ENTITYNUM_NONE;
03311                                                 }
03312                                         }
03313                                 }
03314                         }
03315                         e++;
03316                 }
03317         }
03318 
03319         for ( e = 0 ; e < numListedEntities ; e++ ) 
03320         {
03321                 if (entityList[e] != ENTITYNUM_NONE &&
03322                         entityList[e] >= 0 &&
03323                         entityList[e] < MAX_GENTITIES)
03324                 {
03325                         ent = &g_entities[entityList[e]];
03326                 }
03327                 else
03328                 {
03329                         ent = NULL;
03330                 }
03331 
03332                 if (!ent)
03333                         continue;
03334                 if (ent == self)
03335                         continue;
03336                 if (ent->client && OnSameTeam(ent, self))
03337                 {
03338                         continue;
03339                 }
03340                 if ( !(ent->inuse) )
03341                         continue;
03342                 if ( ent->s.eType != ET_MISSILE )
03343                 {
03344                         if ( ent->s.eType != ET_ITEM )
03345                         {
03346                                 //FIXME: need pushable objects
03347                                 if ( Q_stricmp( "func_button", ent->classname ) == 0 )
03348                                 {//we might push it
03349                                         if ( pull || !(ent->spawnflags&SPF_BUTTON_FPUSHABLE) )
03350                                         {//not force-pushable, never pullable
03351                                                 continue;
03352                                         }
03353                                 }
03354                                 else
03355                                 {
03356                                         if ( ent->s.eFlags & EF_NODRAW )
03357                                         {
03358                                                 continue;
03359                                         }
03360                                         if ( !ent->client )
03361                                         {
03362                                                 if ( Q_stricmp( "lightsaber", ent->classname ) != 0 )
03363                                                 {//not a lightsaber 
03364                                                         if ( Q_stricmp( "func_door", ent->classname ) != 0 || !(ent->spawnflags & 2/*MOVER_FORCE_ACTIVATE*/) )
03365                                                         {//not a force-usable door
03366                                                                 if ( Q_stricmp( "func_static", ent->classname ) != 0 || (!(ent->spawnflags&1/*F_PUSH*/)&&!(ent->spawnflags&2/*F_PULL*/)) )
03367                                                                 {//not a force-usable func_static
03368                                                                         if ( Q_stricmp( "limb", ent->classname ) )
03369                                                                         {//not a limb
03370                                                                                 continue;
03371                                                                         }
03372                                                                 }
03373                                                         }
03374                                                         else if ( ent->moverState != MOVER_POS1 && ent->moverState != MOVER_POS2 )
03375                                                         {//not at rest
03376                                                                 continue;
03377                                                         }
03378                                                 }
03379                                         }
03380                                         else if ( ent->client->NPC_class == CLASS_GALAKMECH 
03381                                                 || ent->client->NPC_class == CLASS_ATST
03382                                                 || ent->client->NPC_class == CLASS_RANCOR )
03383                                         {//can't push ATST or Galak or Rancor
03384                                                 continue;
03385                                         }
03386                                 }
03387                         }
03388                 }
03389                 else
03390                 {
03391                         if ( ent->s.pos.trType == TR_STATIONARY && (ent->s.eFlags&EF_MISSILE_STICK) )
03392                         {//can't force-push/pull stuck missiles (detpacks, tripmines)
03393                                 continue;
03394                         }
03395                         if ( ent->s.pos.trType == TR_STATIONARY && ent->s.weapon != WP_THERMAL )
03396                         {//only thermal detonators can be pushed once stopped
03397                                 continue;
03398                         }
03399                 }
03400 
03401                 //this is all to see if we need to start a saber attack, if it's in flight, this doesn't matter
03402                 // find the distance from the edge of the bounding box
03403                 for ( i = 0 ; i < 3 ; i++ ) 
03404                 {
03405                         if ( center[i] < ent->r.absmin[i] ) 
03406                         {
03407                                 v[i] = ent->r.absmin[i] - center[i];
03408                         } else if ( center[i] > ent->r.absmax[i] ) 
03409                         {
03410                                 v[i] = center[i] - ent->r.absmax[i];
03411                         } else 
03412                         {
03413                                 v[i] = 0;
03414                         }
03415                 }
03416 
03417                 VectorSubtract( ent->r.absmax, ent->r.absmin, size );
03418                 VectorMA( ent->r.absmin, 0.5, size, ent_org );
03419 
03420                 VectorSubtract( ent_org, center, dir );
03421                 VectorNormalize( dir );
03422                 if ( (dot1 = DotProduct( dir, forward )) < 0.6 )
03423                         continue;
03424 
03425                 dist = VectorLength( v );
03426 
03427                 //Now check and see if we can actually deflect it
03428                 //method1
03429                 //if within a certain range, deflect it
03430                 if ( dist >= radius ) 
03431                 {
03432                         continue;
03433                 }
03434         
03435                 //in PVS?
03436                 if ( !ent->r.bmodel && !trap_InPVS( ent_org, self->client->ps.origin ) )
03437                 {//must be in PVS
03438                         continue;
03439                 }
03440 
03441                 //really should have a clear LOS to this thing...
03442                 trap_Trace( &tr, self->client->ps.origin, vec3_origin, vec3_origin, ent_org, self->s.number, MASK_SHOT );
03443                 if ( tr.fraction < 1.0f && tr.entityNum != ent->s.number )
03444                 {//must have clear LOS
03445                         //try from eyes too before you give up
03446                         vec3_t eyePoint;
03447                         VectorCopy(self->client->ps.origin, eyePoint);
03448                         eyePoint[2] += self->client->ps.viewheight;
03449                         trap_Trace( &tr, eyePoint, vec3_origin, vec3_origin, ent_org, self->s.number, MASK_SHOT );
03450 
03451                         if ( tr.fraction < 1.0f && tr.entityNum != ent->s.number )
03452                         {
03453                                 continue;
03454                         }
03455                 }
03456 
03457                 // ok, we are within the radius, add us to the incoming list
03458                 push_list[ent_count] = ent;
03459                 ent_count++;
03460         }
03461 
03462         if ( ent_count )
03463         {
03464                 //method1:
03465                 for ( x = 0; x < ent_count; x++ )
03466                 {
03467                         int modPowerLevel = powerLevel;
03468 
03469         
03470                         if (push_list[x]->client)
03471                         {
03472                                 modPowerLevel = WP_AbsorbConversion(push_list[x], push_list[x]->client->ps.fd.forcePowerLevel[FP_ABSORB], self, powerUse, powerLevel, forcePowerNeeded[self->client->ps.fd.forcePowerLevel[powerUse]][powerUse]);
03473                                 if (modPowerLevel == -1)
03474                                 {
03475                                         modPowerLevel = powerLevel;
03476                                 }
03477                         }
03478 
03479                         pushPower = 256*modPowerLevel;
03480 
03481                         if (push_list[x]->client)
03482                         {
03483                                 VectorCopy(push_list[x]->client->ps.origin, thispush_org);
03484                         }
03485                         else
03486                         {
03487                                 VectorCopy(push_list[x]->s.origin, thispush_org);
03488                         }
03489 
03490                         if ( push_list[x]->client )
03491                         {//FIXME: make enemy jedi able to hunker down and resist this?
03492                                 int otherPushPower = push_list[x]->client->ps.fd.forcePowerLevel[powerUse];
03493                                 qboolean canPullWeapon = qtrue;
03494                                 float dirLen = 0;
03495 
03496                                 if ( g_debugMelee.integer )
03497                                 {
03498                                         if ( (push_list[x]->client->ps.pm_flags&PMF_STUCK_TO_WALL) )
03499                                         {//no resistance if stuck to wall
03500                                                 //push/pull them off the wall
03501                                                 otherPushPower = 0;
03502                                                 G_LetGoOfWall( push_list[x] );
03503                                         }
03504                                 }
03505 
03506                                 knockback = pull?0:200;
03507 
03508                                 pushPowerMod = pushPower;
03509 
03510                                 if (push_list[x]->client->pers.cmd.forwardmove ||
03511                                         push_list[x]->client->pers.cmd.rightmove)
03512                                 { //if you are moving, you get one less level of defense
03513                                         otherPushPower--;
03514 
03515                                         if (otherPushPower < 0)
03516                                         {
03517                                                 otherPushPower = 0;
03518                                         }
03519                                 }
03520 
03521                                 if (otherPushPower && CanCounterThrow(push_list[x], self, pull))
03522                                 {
03523                                         if ( pull )
03524                                         {
03525                                                 G_Sound( push_list[x], CHAN_BODY, G_SoundIndex( "sound/weapons/force/pull.wav" ) );
03526                                                 push_list[x]->client->ps.forceHandExtend = HANDEXTEND_FORCEPULL;
03527                                                 push_list[x]->client->ps.forceHandExtendTime = level.time + 400;
03528                                         }
03529                                         else
03530                                         {
03531                                                 G_Sound( push_list[x], CHAN_BODY, G_SoundIndex( "sound/weapons/force/push.wav" ) );
03532                                                 push_list[x]->client->ps.forceHandExtend = HANDEXTEND_FORCEPUSH;
03533                                                 push_list[x]->client->ps.forceHandExtendTime = level.time + 1000;
03534                                         }
03535                                         push_list[x]->client->ps.powerups[PW_DISINT_4] = push_list[x]->client->ps.forceHandExtendTime + 200;
03536 
03537                                         if (pull)
03538                                         {
03539                                                 push_list[x]->client->ps.powerups[PW_PULL] = push_list[x]->client->ps.powerups[PW_DISINT_4];
03540                                         }
03541                                         else
03542                                         {
03543                                                 push_list[x]->client->ps.powerups[PW_PULL] = 0;
03544                                         }
03545 
03546                                         //Make a counter-throw effect
03547 
03548                                         if (otherPushPower >= modPowerLevel)
03549                                         {
03550                                                 pushPowerMod = 0;
03551                                                 canPullWeapon = qfalse;
03552                                         }
03553                                         else
03554                                         {
03555                                                 int powerDif = (modPowerLevel - otherPushPower);
03556 
03557                                                 if (powerDif >= 3)
03558                                                 {
03559                                                         pushPowerMod -= pushPowerMod*0.2;
03560                                                 }
03561                                                 else if (powerDif == 2)
03562                                                 {
03563                                                         pushPowerMod -= pushPowerMod*0.4;
03564                                                 }
03565                                                 else if (powerDif == 1)
03566                                                 {
03567                                                         pushPowerMod -= pushPowerMod*0.8;
03568                                                 }
03569 
03570                                                 if (pushPowerMod < 0)
03571                                                 {
03572                                                         pushPowerMod = 0;
03573                                                 }
03574                                         }
03575                                 }
03576 
03577                                 //shove them
03578                                 if ( pull )
03579                                 {
03580                                         VectorSubtract( self->client->ps.origin, thispush_org, pushDir );
03581 
03582                                         if (push_list[x]->client && VectorLength(pushDir) <= 256)
03583                                         {
03584                                                 int randfact = 0;
03585 
03586                                                 if (modPowerLevel == FORCE_LEVEL_1)
03587                                                 {
03588                                                         randfact = 3;
03589                                                 }
03590                                                 else if (modPowerLevel == FORCE_LEVEL_2)
03591                                                 {
03592                                                         randfact = 7;
03593                                                 }
03594                                                 else if (modPowerLevel == FORCE_LEVEL_3)
03595                                                 {
03596                                                         randfact = 10;
03597                                                 }
03598 
03599                                                 if (!OnSameTeam(self, push_list[x]) && Q_irand(1, 10) <= randfact && canPullWeapon)
03600                                                 {
03601                                                         vec3_t uorg, vecnorm;
03602 
03603                                                         VectorCopy(self->client->ps.origin, uorg);
03604                                                         uorg[2] += 64;
03605 
03606                                                         VectorSubtract(uorg, thispush_org, vecnorm);
03607                                                         VectorNormalize(vecnorm);
03608 
03609                                                         TossClientWeapon(push_list[x], vecnorm, 500);
03610                                                 }
03611                                         }
03612                                 }
03613                                 else
03614                                 {
03615                                         VectorSubtract( thispush_org, self->client->ps.origin, pushDir );
03616                                 }
03617 
03618                                 if ((modPowerLevel > otherPushPower || push_list[x]->client->ps.m_iVehicleNum) && push_list[x]->client)
03619                                 {
03620                                         if (modPowerLevel == FORCE_LEVEL_3 &&
03621                                                 push_list[x]->client->ps.forceHandExtend != HANDEXTEND_KNOCKDOWN)
03622                                         {
03623                                                 dirLen = VectorLength(pushDir);
03624 
03625                                                 if (BG_KnockDownable(&push_list[x]->client->ps) &&
03626                                                         dirLen <= (64*((modPowerLevel - otherPushPower)-1)))
03627                                                 { //can only do a knockdown if fairly close
03628                                                         push_list[x]->client->ps.forceHandExtend = HANDEXTEND_KNOCKDOWN;
03629                                                         push_list[x]->client->ps.forceHandExtendTime = level.time + 700;
03630                                                         push_list[x]->client->ps.forceDodgeAnim = 0; //this toggles between 1 and 0, when it's 1 we should play the get up anim
03631                                                         push_list[x]->client->ps.quickerGetup = qtrue;
03632                                                 }
03633                                                 else if (push_list[x]->s.number < MAX_CLIENTS && push_list[x]->client->ps.m_iVehicleNum &&
03634                                                         dirLen <= 128.0f )
03635                                                 { //a player on a vehicle
03636                                                         gentity_t *vehEnt = &g_entities[push_list[x]->client->ps.m_iVehicleNum];
03637                                                         if (vehEnt->inuse && vehEnt->client && vehEnt->m_pVehicle)
03638                                                         {
03639                                                                 if (vehEnt->m_pVehicle->m_pVehicleInfo->type == VH_SPEEDER ||
03640                                                                         vehEnt->m_pVehicle->m_pVehicleInfo->type == VH_ANIMAL)
03641                                                                 { //push the guy off
03642                                                                         vehEnt->m_pVehicle->m_pVehicleInfo->Eject(vehEnt->m_pVehicle, (bgEntity_t *)push_list[x], qfalse);
03643                                                                 }
03644                                                         }
03645                                                 }
03646                                         }
03647                                 }
03648 
03649                                 if (!dirLen)
03650                                 {
03651                                         dirLen = VectorLength(pushDir);
03652                                 }
03653 
03654                                 VectorNormalize(pushDir);
03655 
03656                                 if (push_list[x]->client)
03657                                 {
03658                                         //escape a force grip if we're in one
03659                                         if (self->client->ps.fd.forceGripBeingGripped > level.time)
03660                                         { //force the enemy to stop gripping me if I managed to push him
03661                                                 if (push_list[x]->client->ps.fd.forceGripEntityNum == self->s.number)
03662                                                 {
03663                                                         if (modPowerLevel >= push_list[x]->client->ps.fd.forcePowerLevel[FP_GRIP])
03664                                                         { //only break the grip if our push/pull level is >= their grip level
03665                                                                 WP_ForcePowerStop(push_list[x], FP_GRIP);
03666                                                                 self->client->ps.fd.forceGripBeingGripped = 0;
03667                                                                 push_list[x]->client->ps.fd.forceGripUseTime = level.time + 1000; //since we just broke out of it..
03668                                                         }
03669                                                 }
03670                                         }
03671 
03672                                         push_list[x]->client->ps.otherKiller = self->s.number;
03673                                         push_list[x]->client->ps.otherKillerTime = level.time + 5000;
03674                                         push_list[x]->client->ps.otherKillerDebounceTime = level.time + 100;
03675 
03676                                         pushPowerMod -= (dirLen*0.7);
03677                                         if (pushPowerMod < 16)
03678                                         {
03679                                                 pushPowerMod = 16;
03680                                         }
03681 
03682                                         //fullbody push effect
03683                                         push_list[x]->client->pushEffectTime = level.time + 600;
03684 
03685                                         push_list[x]->client->ps.velocity[0] = pushDir[0]*pushPowerMod;
03686                                         push_list[x]->client->ps.velocity[1] = pushDir[1]*pushPowerMod;
03687 
03688                                         if ((int)push_list[x]->client->ps.velocity[2] == 0)
03689                                         { //if not going anywhere vertically, boost them up a bit
03690                                                 push_list[x]->client->ps.velocity[2] = pushDir[2]*pushPowerMod;
03691 
03692                                                 if (push_list[x]->client->ps.velocity[2] < 128)
03693                                                 {
03694                                                         push_list[x]->client->ps.velocity[2] = 128;
03695                                                 }
03696                                         }
03697                                         else
03698                                         {
03699                                                 push_list[x]->client->ps.velocity[2] = pushDir[2]*pushPowerMod;
03700                                         }
03701                                 }
03702                         }
03703                         else if ( push_list[x]->s.eType == ET_MISSILE && push_list[x]->s.pos.trType != TR_STATIONARY && (push_list[x]->s.pos.trType != TR_INTERPOLATE||push_list[x]->s.weapon != WP_THERMAL) )//rolling and stationary thermal detonators are dealt with below
03704                         {
03705                                 if ( pull )
03706                                 {//deflect rather than reflect?
03707                                 }
03708                                 else 
03709                                 {
03710                                         G_ReflectMissile( self, push_list[x], forward );
03711                                 }
03712                         }
03713                         else if ( !Q_stricmp( "func_static", push_list[x]->classname ) )
03714                         {//force-usable func_static
03715                                 if ( !pull && (push_list[x]->spawnflags&1/*F_PUSH*/) )
03716                                 {
03717                                         GEntity_UseFunc( push_list[x], self, self );
03718                                 }
03719                                 else if ( pull && (push_list[x]->spawnflags&2/*F_PULL*/) )
03720                                 {
03721                                         GEntity_UseFunc( push_list[x], self, self );
03722                                 }
03723                         }
03724                         else if ( !Q_stricmp( "func_door", push_list[x]->classname ) && (push_list[x]->spawnflags&2) )
03725                         {//push/pull the door
03726                                 vec3_t  pos1, pos2;
03727                                 vec3_t  trFrom;
03728 
03729                                 VectorCopy(self->client->ps.origin, trFrom);
03730                                 trFrom[2] += self->client->ps.viewheight;
03731 
03732                                 AngleVectors( self->client->ps.viewangles, forward, NULL, NULL );
03733                                 VectorNormalize( forward );
03734                                 VectorMA( trFrom, radius, forward, end );
03735                                 trap_Trace( &tr, trFrom, vec3_origin, vec3_origin, end, self->s.number, MASK_SHOT );
03736                                 if ( tr.entityNum != push_list[x]->s.number || tr.fraction == 1.0 || tr.allsolid || tr.startsolid )
03737                                 {//must be pointing right at it
03738                                         continue;
03739                                 }
03740 
03741                                 if ( VectorCompare( vec3_origin, push_list[x]->s.origin ) )
03742                                 {//does not have an origin brush, so pos1 & pos2 are relative to world origin, need to calc center
03743                                         VectorSubtract( push_list[x]->r.absmax, push_list[x]->r.absmin, size );
03744                                         VectorMA( push_list[x]->r.absmin, 0.5, size, center );
03745                                         if ( (push_list[x]->spawnflags&1) && push_list[x]->moverState == MOVER_POS1 )
03746                                         {//if at pos1 and started open, make sure we get the center where it *started* because we're going to add back in the relative values pos1 and pos2
03747                                                 VectorSubtract( center, push_list[x]->pos1, center );
03748                                         }
03749                                         else if ( !(push_list[x]->spawnflags&1) && push_list[x]->moverState == MOVER_POS2 )
03750                                         {//if at pos2, make sure we get the center where it *started* because we're going to add back in the relative values pos1 and pos2
03751                                                 VectorSubtract( center, push_list[x]->pos2, center );
03752                                         }
03753                                         VectorAdd( center, push_list[x]->pos1, pos1 );
03754                                         VectorAdd( center, push_list[x]->pos2, pos2 );
03755                                 }
03756                                 else
03757                                 {//actually has an origin, pos1 and pos2 are absolute
03758                                         VectorCopy( push_list[x]->r.currentOrigin, center );
03759                                         VectorCopy( push_list[x]->pos1, pos1 );
03760                                         VectorCopy( push_list[x]->pos2, pos2 );
03761                                 }
03762 
03763                                 if ( Distance( pos1, trFrom ) < Distance( pos2, trFrom ) )
03764                                 {//pos1 is closer
03765                                         if ( push_list[x]->moverState == MOVER_POS1 )
03766                                         {//at the closest pos
03767                                                 if ( pull )
03768                                                 {//trying to pull, but already at closest point, so screw it
03769                                                         continue;
03770                                                 }
03771                                         }
03772                                         else if ( push_list[x]->moverState == MOVER_POS2 )
03773                                         {//at farthest pos
03774                                                 if ( !pull )
03775                                                 {//trying to push, but already at farthest point, so screw it
03776                                                         continue;
03777                                                 }
03778                                         }
03779                                 }
03780                                 else
03781                                 {//pos2 is closer
03782                                         if ( push_list[x]->moverState == MOVER_POS1 )
03783                                         {//at the farthest pos
03784                                                 if ( !pull )
03785                                                 {//trying to push, but already at farthest point, so screw it
03786                                                         continue;
03787                                                 }
03788                                         }
03789                                         else if ( push_list[x]->moverState == MOVER_POS2 )
03790                                         {//at closest pos
03791                                                 if ( pull )
03792                                                 {//trying to pull, but already at closest point, so screw it
03793                                                         continue;
03794                                                 }
03795                                         }
03796                                 }
03797                                 GEntity_UseFunc( push_list[x], self, self );
03798                         }
03799                         else if ( Q_stricmp( "func_button", push_list[x]->classname ) == 0 )
03800                         {//pretend you pushed it
03801                                 Touch_Button( push_list[x], self, NULL );
03802                                 continue;
03803                         }
03804                 }
03805         }
03806 
03807         //attempt to break any leftover grips
03808         //if we're still in a current grip that wasn't broken by the push, it will still remain
03809         self->client->dangerTime = level.time;
03810         self->client->ps.eFlags &= ~EF_INVULNERABLE;
03811         self->client->invulnerableTimer = 0;
03812 
03813         if (self->client->ps.fd.forceGripBeingGripped > level.time)
03814         {
03815                 self->client->ps.fd.forceGripBeingGripped = 0;
03816         }
03817 }

qboolean G_InGetUpAnim playerState_t ps  ) 
 

Definition at line 2970 of file w_force.c.

References BOTH_FORCE_GETUP_B1, BOTH_FORCE_GETUP_B2, BOTH_FORCE_GETUP_B3, BOTH_FORCE_GETUP_B4, BOTH_FORCE_GETUP_B5, BOTH_FORCE_GETUP_F1, BOTH_FORCE_GETUP_F2, BOTH_GETUP1, BOTH_GETUP2, BOTH_GETUP3, BOTH_GETUP4, BOTH_GETUP5, BOTH_GETUP_BROLL_B, BOTH_GETUP_BROLL_F, BOTH_GETUP_BROLL_L, BOTH_GETUP_BROLL_R, BOTH_GETUP_FROLL_B, BOTH_GETUP_FROLL_F, BOTH_GETUP_FROLL_L, BOTH_GETUP_FROLL_R, playerState_s::legsAnim, playerState_t, qboolean, qfalse, qtrue, and playerState_s::torsoAnim.

Referenced by ForceThrow().

02971 {
02972         switch( (ps->legsAnim) )
02973         {
02974         case BOTH_GETUP1:
02975         case BOTH_GETUP2:
02976         case BOTH_GETUP3:
02977         case BOTH_GETUP4:
02978         case BOTH_GETUP5:
02979         case BOTH_FORCE_GETUP_F1:
02980         case BOTH_FORCE_GETUP_F2:
02981         case BOTH_FORCE_GETUP_B1:
02982         case BOTH_FORCE_GETUP_B2:
02983         case BOTH_FORCE_GETUP_B3:
02984         case BOTH_FORCE_GETUP_B4:
02985         case BOTH_FORCE_GETUP_B5:
02986         case BOTH_GETUP_BROLL_B:
02987         case BOTH_GETUP_BROLL_F:
02988         case BOTH_GETUP_BROLL_L:
02989         case BOTH_GETUP_BROLL_R:
02990         case BOTH_GETUP_FROLL_B:
02991         case BOTH_GETUP_FROLL_F:
02992         case BOTH_GETUP_FROLL_L:
02993         case BOTH_GETUP_FROLL_R:
02994                 return qtrue;
02995         }
02996 
02997         switch( (ps->torsoAnim) )
02998         {
02999         case BOTH_GETUP1:
03000         case BOTH_GETUP2:
03001         case BOTH_GETUP3:
03002         case BOTH_GETUP4:
03003         case BOTH_GETUP5:
03004         case BOTH_FORCE_GETUP_F1:
03005         case BOTH_FORCE_GETUP_F2:
03006         case BOTH_FORCE_GETUP_B1:
03007         case BOTH_FORCE_GETUP_B2:
03008         case BOTH_FORCE_GETUP_B3:
03009         case BOTH_FORCE_GETUP_B4:
03010         case BOTH_FORCE_GETUP_B5:
03011         case BOTH_GETUP_BROLL_B:
03012         case BOTH_GETUP_BROLL_F:
03013         case BOTH_GETUP_BROLL_L:
03014         case BOTH_GETUP_BROLL_R:
03015         case BOTH_GETUP_FROLL_B:
03016         case BOTH_GETUP_FROLL_F:
03017         case BOTH_GETUP_FROLL_L:
03018         case BOTH_GETUP_FROLL_R:
03019                 return qtrue;
03020         }
03021 
03022         return qfalse;
03023 }

qboolean G_IsMindTricked forcedata_t fd,
int  client
 

Definition at line 4155 of file w_force.c.

References client, forcedata_t, forcedata_s::forceMindtrickTargetIndex, forcedata_s::forceMindtrickTargetIndex2, forcedata_s::forceMindtrickTargetIndex3, forcedata_s::forceMindtrickTargetIndex4, qboolean, qfalse, and qtrue.

04156 {
04157         int checkIn;
04158         int trickIndex1, trickIndex2, trickIndex3, trickIndex4;
04159         int sub = 0;
04160 
04161         if (!fd)
04162         {
04163                 return qfalse;
04164         }
04165 
04166         trickIndex1 = fd->forceMindtrickTargetIndex;
04167         trickIndex2 = fd->forceMindtrickTargetIndex2;
04168         trickIndex3 = fd->forceMindtrickTargetIndex3;
04169         trickIndex4 = fd->forceMindtrickTargetIndex4;
04170 
04171         if (client > 47)
04172         {
04173                 checkIn = trickIndex4;
04174                 sub = 48;
04175         }
04176         else if (client > 31)
04177         {
04178                 checkIn = trickIndex3;
04179                 sub = 32;
04180         }
04181         else if (client > 15)
04182         {
04183                 checkIn = trickIndex2;
04184                 sub = 16;
04185         }
04186         else
04187         {
04188                 checkIn = trickIndex1;
04189         }
04190 
04191         if (checkIn & (1 << (client-sub)))
04192         {
04193                 return qtrue;
04194         }
04195         
04196         return qfalse;
04197 }

void G_LetGoOfWall gentity_t ent  ) 
 

Definition at line 3025 of file w_force.c.

References BG_InReboundHold(), BG_InReboundJump(), gentity_s::client, gentity_t, playerState_s::legsAnim, playerState_s::legsTimer, playerState_s::pm_flags, PMF_STUCK_TO_WALL, gclient_s::ps, playerState_s::torsoAnim, and playerState_s::torsoTimer.

Referenced by ForceThrow(), and G_Damage().

03026 {
03027         if ( !ent || !ent->client )
03028         {
03029                 return;
03030         }
03031         ent->client->ps.pm_flags &= ~PMF_STUCK_TO_WALL;
03032         if ( BG_InReboundJump( ent->client->ps.legsAnim ) 
03033                 || BG_InReboundHold( ent->client->ps.legsAnim ) )
03034         {
03035                 ent->client->ps.legsTimer = 0;
03036         }
03037         if ( BG_InReboundJump( ent->client->ps.torsoAnim ) 
03038                 || BG_InReboundHold( ent->client->ps.torsoAnim ) )
03039         {
03040                 ent->client->ps.torsoTimer = 0;
03041         }
03042 }

gentity_t* G_PreDefSound vec3_t  org,
int  pdSound
 

Definition at line 40 of file w_force.c.

References EV_PREDEFSOUND, entityState_s::eventParm, G_TempEntity(), gentity_t, entityState_s::origin, gentity_s::s, vec3_t, and VectorCopy.

Referenced by ClientThink_real(), ForceAbsorb(), ForcePowerUsableOn(), ForceProtect(), G_Damage(), G_SpecialRollGetup(), WP_AbsorbConversion(), WP_ForcePowersUpdate(), and WP_GetVelocityForForceJump().

00041 {
00042         gentity_t       *te;
00043 
00044         te = G_TempEntity( org, EV_PREDEFSOUND );
00045         te->s.eventParm = pdSound;
00046         VectorCopy(org, te->s.origin);
00047 
00048         return te;
00049 }

qboolean G_SpecialRollGetup gentity_t self  ) 
 

Definition at line 5028 of file w_force.c.

References BOTH_GETUP_BROLL_B, BOTH_GETUP_BROLL_F, BOTH_GETUP_BROLL_L, BOTH_GETUP_BROLL_R, CHAN_VOICE, gentity_s::client, clientPersistant_t::cmd, playerState_s::forceDodgeAnim, playerState_s::forceHandExtendTime, usercmd_s::forwardmove, G_EntitySound(), G_PreDefSound(), G_SetAnim(), G_SoundIndex(), gentity_t, level, playerState_s::origin, PDSOUND_FORCEJUMP, gclient_s::pers, gclient_s::ps, qboolean, qfalse, qtrue, usercmd_s::rightmove, SETANIM_BOTH, SETANIM_FLAG_HOLD, SETANIM_FLAG_OVERRIDE, level_locals_t::time, and usercmd_s::upmove.

Referenced by WP_ForcePowersUpdate().

05029 { //fixme: currently no knockdown will actually land you on your front... so froll's are pretty useless at the moment.
05030         qboolean rolled = qfalse;
05031 
05032         /*
05033         if (self->client->ps.weapon != WP_SABER &&
05034                 self->client->ps.weapon != WP_MELEE)
05035         { //can't do acrobatics without saber selected
05036                 return qfalse;
05037         }
05038         */
05039 
05040         if (
05041                 self->client->pers.cmd.rightmove > 0 &&
05042                 !self->client->pers.cmd.forwardmove)
05043         {
05044                 G_SetAnim(self, &self->client->pers.cmd, SETANIM_BOTH, BOTH_GETUP_BROLL_R, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD, 0);
05045                 rolled = qtrue;
05046         }
05047         else if (
05048                 self->client->pers.cmd.rightmove < 0 &&
05049                 !self->client->pers.cmd.forwardmove)
05050         {
05051                 G_SetAnim(self, &self->client->pers.cmd, SETANIM_BOTH, BOTH_GETUP_BROLL_L, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD, 0);
05052                 rolled = qtrue;
05053         }
05054         else if (/*self->client->pers.cmd.upmove > 0 &&*/
05055                 !self->client->pers.cmd.rightmove &&
05056                 self->client->pers.cmd.forwardmove > 0)
05057         {
05058                 G_SetAnim(self, &self->client->pers.cmd, SETANIM_BOTH, BOTH_GETUP_BROLL_F, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD, 0);
05059                 rolled = qtrue;
05060         }
05061         else if (/*self->client->pers.cmd.upmove > 0 &&*/
05062                 !self->client->pers.cmd.rightmove &&
05063                 self->client->pers.cmd.forwardmove < 0)
05064         {
05065                 G_SetAnim(self, &self->client->pers.cmd, SETANIM_BOTH, BOTH_GETUP_BROLL_B, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD, 0);
05066                 rolled = qtrue;
05067         }
05068         else if (self->client->pers.cmd.upmove)
05069         {
05070                 G_PreDefSound(self->client->ps.origin, PDSOUND_FORCEJUMP);
05071                 self->client->ps.forceDodgeAnim = 2;
05072                 self->client->ps.forceHandExtendTime = level.time + 500;
05073 
05074                 //self->client->ps.velocity[2] = 300;
05075         }
05076 
05077         if (rolled)
05078         {
05079                 G_EntitySound( self, CHAN_VOICE, G_SoundIndex("*jump1.wav") );
05080         }
05081 
05082         return rolled;
05083 }

void GEntity_UseFunc gentity_t self,
gentity_t other,
gentity_t activator
 

Definition at line 2895 of file w_force.c.

References gentity_t, and GlobalUse().

Referenced by ForceThrow().

02896 {
02897         GlobalUse(self, other, activator);
02898 }

void HolocronUpdate gentity_t self  ) 
 

Definition at line 4861 of file w_force.c.

References gentity_s::client, playerState_s::fd, FORCE_LEVEL_0, FORCE_LEVEL_1, FORCE_LEVEL_3, forcedata_s::forcePowerLevel, forcedata_s::forcePowersActive, forcedata_s::forcePowersKnown, FP_LEVITATION, FP_SABER_DEFENSE, FP_SABER_OFFENSE, g_MaxHolocronCarry, gentity_t, HasSetSaberOnly(), playerState_s::holocronBits, playerState_s::holocronsCarried, NUM_FORCE_POWERS, gclient_s::ps, trap_Cvar_Update(), and WP_ForcePowerStop().

Referenced by WP_ForcePowersUpdate().

04862 { //keep holocron status updated in holocron mode
04863         int i = 0;
04864         int noHRank = 0;
04865 
04866         if (noHRank < FORCE_LEVEL_0)
04867         {
04868                 noHRank = FORCE_LEVEL_0;
04869         }
04870         if (noHRank > FORCE_LEVEL_3)
04871         {
04872                 noHRank = FORCE_LEVEL_3;
04873         }
04874 
04875         trap_Cvar_Update(&g_MaxHolocronCarry);
04876 
04877         while (i < NUM_FORCE_POWERS)
04878         {
04879                 if (self->client->ps.holocronsCarried[i])
04880                 { //carrying it, make sure we have the power
04881                         self->client->ps.holocronBits |= (1 << i);
04882                         self->client->ps.fd.forcePowersKnown |= (1 << i);
04883                         self->client->ps.fd.forcePowerLevel[i] = FORCE_LEVEL_3;
04884                 }
04885                 else
04886                 { //otherwise, make sure the power is cleared from us
04887                         self->client->ps.fd.forcePowerLevel[i] = 0;
04888                         if (self->client->ps.holocronBits & (1 << i))
04889                         {
04890                                 self->client->ps.holocronBits -= (1 << i);
04891                         }
04892 
04893                         if ((self->client->ps.fd.forcePowersKnown & (1 << i)) && i != FP_LEVITATION && i != FP_SABER_OFFENSE)
04894                         {
04895                                 self->client->ps.fd.forcePowersKnown -= (1 << i);
04896                         }
04897 
04898                         if ((self->client->ps.fd.forcePowersActive & (1 << i)) && i != FP_LEVITATION && i != FP_SABER_OFFENSE)
04899                         {
04900                                 WP_ForcePowerStop(self, i);
04901                         }
04902 
04903                         if (i == FP_LEVITATION)
04904                         {
04905                                 if (noHRank >= FORCE_LEVEL_1)
04906                                 {
04907                                         self->client->ps.fd.forcePowerLevel[i] = noHRank;
04908                                 }
04909                                 else
04910                                 {
04911                                         self->client->ps.fd.forcePowerLevel[i] = FORCE_LEVEL_1;
04912                                 }
04913                         }
04914                         else if (i == FP_SABER_OFFENSE)
04915                         {
04916                                 self->client->ps.fd.forcePowersKnown |= (1 << i);
04917 
04918                                 if (noHRank >= FORCE_LEVEL_1)
04919                                 {
04920                                         self->client->ps.fd.forcePowerLevel[i] = noHRank;
04921                                 }
04922                                 else
04923                                 {
04924                                         self->client->ps.fd.forcePowerLevel[i] = FORCE_LEVEL_1;
04925                                 }
04926                         }
04927                         else
04928                         {
04929                                 self->client->ps.fd.forcePowerLevel[i] = FORCE_LEVEL_0;
04930                         }
04931                 }
04932 
04933                 i++;
04934         }
04935 
04936         if (HasSetSaberOnly())
04937         { //if saberonly, we get these powers no matter what (still need the holocrons for level 3)
04938                 if (self->client->ps.fd.forcePowerLevel[FP_SABER_OFFENSE] < FORCE_LEVEL_1)
04939                 {
04940                         self->client->ps.fd.forcePowerLevel[FP_SABER_OFFENSE] = FORCE_LEVEL_1;
04941                 }
04942                 if (self->client->ps.fd.forcePowerLevel[FP_SABER_DEFENSE] < FORCE_LEVEL_1)
04943                 {
04944                         self->client->ps.fd.forcePowerLevel[FP_SABER_DEFENSE] = FORCE_LEVEL_1;
04945                 }
04946         }
04947 }

void Jedi_Decloak gentity_t self  ) 
 

Definition at line 818 of file NPC_AI_Jedi.c.

References CHAN_ITEM, gentity_s::client, FL_NOTARGET, gentity_s::flags, G_Sound(), G_SoundIndex(), gentity_t, playerState_s::powerups, gclient_s::ps, and PW_CLOAKED.

Referenced by ClientThink_real(), DEMP2_AltRadiusDamage(), ForceLightningDamage(), G_MissileImpact(), G_RunFrame(), ItemUse_UseCloak(), Jedi_Ambush(), and Jedi_CheckCloak().

00819 {
00820         if ( self )
00821         {
00822                 self->flags &= ~FL_NOTARGET;
00823                 if ( self->client )
00824                 {
00825                         if ( self->client->ps.powerups[PW_CLOAKED] )
00826                         {//Uncloak
00827                                 self->client->ps.powerups[PW_CLOAKED] = 0;
00828 
00829                                 G_Sound( self, CHAN_ITEM, G_SoundIndex("sound/chars/shadowtrooper/decloak.wav") );
00830                         }
00831                 }
00832         }
00833 }

qboolean Jedi_DodgeEvasion gentity_t self,
gentity_t shooter,
trace_t tr,
int  hitLoc
 

Definition at line 5664 of file w_force.c.

References BOTH_DODGE_FL, BOTH_DODGE_FR, BOTH_DODGE_L, BOTH_DODGE_R, CHAN_BODY, gentity_s::client, ENTITYNUM_NONE, playerState_s::fd, FORCE_LEVEL_3, playerState_s::forceDodgeAnim, playerState_s::forceHandExtend, playerState_s::forceHandExtendTime, forcedata_s::forcePowerLevel, forcedata_s::forcePowersActive, ForceSpeed(), FP_SEE, FP_SPEED, g_forceDodge, G_Sound(), G_SoundIndex(), gentity_t, playerState_s::groundEntityNum, HANDEXTEND_DODGE, HANDEXTEND_NONE, gentity_s::health, HL_ARM_LT, HL_ARM_RT, HL_BACK, HL_BACK_LT, HL_BACK_RT, HL_CHEST, HL_CHEST_LT, HL_CHEST_RT, HL_FOOT_LT, HL_FOOT_RT, HL_HAND_LT, HL_HAND_RT, HL_HEAD, HL_LEG_LT, HL_LEG_RT, HL_NONE, HL_WAIST, vmCvar_t::integer, level, playerState_s::powerups, gclient_s::ps, PW_SPEEDBURST, Q_irand(), qboolean, qfalse, qtrue, level_locals_t::time, playerState_s::weaponTime, and WP_ForcePowerUsable().

Referenced by WP_DisruptorAltFire().

05665 {
05666         int     dodgeAnim = -1;
05667 
05668         if ( !self || !self->client || self->health <= 0 )
05669         {
05670                 return qfalse;
05671         }
05672 
05673         if (!g_forceDodge.integer)
05674         {
05675                 return qfalse;
05676         }
05677 
05678         if (g_forceDodge.integer != 2)
05679         {
05680                 if (!(self->client->ps.fd.forcePowersActive & (1 << FP_SEE)))
05681                 {
05682                         return qfalse;
05683                 }
05684         }
05685 
05686         if ( self->client->ps.groundEntityNum == ENTITYNUM_NONE )
05687         {//can't dodge in mid-air
05688                 return qfalse;
05689         }
05690 
05691         if ( self->client->ps.weaponTime > 0 || self->client->ps.forceHandExtend != HANDEXTEND_NONE )
05692         {//in some effect that stops me from moving on my own
05693                 return qfalse;
05694         }
05695 
05696         if (g_forceDodge.integer == 2)
05697         {
05698                 if (self->client->ps.fd.forcePowersActive)
05699                 { //for now just don't let us dodge if we're using a force power at all
05700                         return qfalse;
05701                 }
05702         }
05703 
05704         if (g_forceDodge.integer == 2)
05705         {
05706                 if ( !WP_ForcePowerUsable( self, FP_SPEED ) )
05707                 {//make sure we have it and have enough force power
05708                         return qfalse;
05709                 }
05710         }
05711 
05712         if (g_forceDodge.integer == 2)
05713         {
05714                 if ( Q_irand( 1, 7 ) > self->client->ps.fd.forcePowerLevel[FP_SPEED] )
05715                 {//more likely to fail on lower force speed level
05716                         return qfalse;
05717                 }
05718         }
05719         else
05720         {
05721                 //We now dodge all the time, but only on level 3
05722                 if (self->client->ps.fd.forcePowerLevel[FP_SEE] < FORCE_LEVEL_3)
05723                 {//more likely to fail on lower force sight level
05724                         return qfalse;
05725                 }
05726         }
05727 
05728         switch( hitLoc )
05729         {
05730         case HL_NONE:
05731                 return qfalse;
05732                 break;
05733 
05734         case HL_FOOT_RT:
05735         case HL_FOOT_LT:
05736         case HL_LEG_RT:
05737         case HL_LEG_LT:
05738                 return qfalse;
05739 
05740         case HL_BACK_RT:
05741                 dodgeAnim = BOTH_DODGE_FL;
05742                 break;
05743         case HL_CHEST_RT:
05744                 dodgeAnim = BOTH_DODGE_FR;
05745                 break;
05746         case HL_BACK_LT:
05747                 dodgeAnim = BOTH_DODGE_FR;
05748                 break;
05749         case HL_CHEST_LT:
05750                 dodgeAnim = BOTH_DODGE_FR;
05751                 break;
05752         case HL_BACK:
05753         case HL_CHEST:
05754         case HL_WAIST:
05755                 dodgeAnim = BOTH_DODGE_FL;
05756                 break;
05757         case HL_ARM_RT:
05758         case HL_HAND_RT:
05759                 dodgeAnim = BOTH_DODGE_L;
05760                 break;
05761         case HL_ARM_LT:
05762         case HL_HAND_LT:
05763                 dodgeAnim = BOTH_DODGE_R;
05764                 break;
05765         case HL_HEAD:
05766                 dodgeAnim = BOTH_DODGE_FL;
05767                 break;
05768         default:
05769                 return qfalse;
05770         }
05771 
05772         if ( dodgeAnim != -1 )
05773         {
05774                 //Our own happy way of forcing an anim:
05775                 self->client->ps.forceHandExtend = HANDEXTEND_DODGE;
05776                 self->client->ps.forceDodgeAnim = dodgeAnim;
05777                 self->client->ps.forceHandExtendTime = level.time + 300;
05778 
05779                 self->client->ps.powerups[PW_SPEEDBURST] = level.time + 100;
05780 
05781                 if (g_forceDodge.integer == 2)
05782                 {
05783                         ForceSpeed( self, 500 );
05784                 }
05785                 else
05786                 {
05787                         G_Sound( self, CHAN_BODY, G_SoundIndex("sound/weapons/force/speed.wav") );
05788                 }
05789                 return qtrue;
05790         }
05791         return qfalse;
05792 }

void JediMasterUpdate gentity_t self  ) 
 

Definition at line 4949 of file w_force.c.

References gentity_s::client, playerState_s::fd, FORCE_LEVEL_0, FORCE_LEVEL_1, FORCE_LEVEL_2, FORCE_LEVEL_3, forcedata_s::forcePowerLevel, forcedata_s::forcePowersActive, forcedata_s::forcePowersKnown, FP_ABSORB, FP_DRAIN, FP_LEVITATION, FP_TEAM_FORCE, FP_TEAM_HEAL, FP_TELEPATHY, g_MaxHolocronCarry, gentity_t, playerState_s::isJediMaster, NUM_FORCE_POWERS, gclient_s::ps, trap_Cvar_Update(), and WP_ForcePowerStop().

Referenced by WP_ForcePowersUpdate().

04950 { //keep jedi master status updated for JM gametype
04951         int i = 0;
04952 
04953         trap_Cvar_Update(&g_MaxHolocronCarry);
04954 
04955         while (i < NUM_FORCE_POWERS)
04956         {
04957                 if (self->client->ps.isJediMaster)
04958                 {
04959                         self->client->ps.fd.forcePowersKnown |= (1 << i);
04960                         self->client->ps.fd.forcePowerLevel[i] = FORCE_LEVEL_3;
04961 
04962                         if (i == FP_TEAM_HEAL || i == FP_TEAM_FORCE ||
04963                                 i == FP_DRAIN || i == FP_ABSORB)
04964                         { //team powers are useless in JM, absorb is too because no one else has powers to absorb. Drain is just
04965                           //relatively useless in comparison, because its main intent is not to heal, but rather to cripple others
04966                           //by draining their force at the same time. And no one needs force in JM except the JM himself.
04967                                 self->client->ps.fd.forcePowersKnown &= ~(1 << i);
04968                                 self->client->ps.fd.forcePowerLevel[i] = 0;
04969                         }
04970 
04971                         if (i == FP_TELEPATHY)
04972                         { //this decision was made because level 3 mindtrick allows the JM to just hide too much, and no one else has force
04973                           //sight to counteract it. Since the JM himself is the focus of gameplay in this mode, having him hidden for large
04974                           //durations is indeed a bad thing.
04975                                 self->client->ps.fd.forcePowerLevel[i] = FORCE_LEVEL_2;
04976                         }
04977                 }
04978                 else
04979                 {
04980                         if ((self->client->ps.fd.forcePowersKnown & (1 << i)) && i != FP_LEVITATION)
04981                         {
04982                                 self->client->ps.fd.forcePowersKnown -= (1 << i);
04983                         }
04984 
04985                         if ((self->client->ps.fd.forcePowersActive & (1 << i)) && i != FP_LEVITATION)
04986                         {
04987                                 WP_ForcePowerStop(self, i);
04988                         }
04989 
04990                         if (i == FP_LEVITATION)
04991                         {
04992                                 self->client->ps.fd.forcePowerLevel[i] = FORCE_LEVEL_1;
04993                         }
04994                         else
04995                         {
04996                                 self->client->ps.fd.