#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.
|
|
|
|
|
|
|
|
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 }
|
|
|
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 }
|
|
||||||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
||||||||||||||||||||
|
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 }
|
|
|
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
|
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 }
|
|
||||||||||||||||||||
|
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 }
|
|
||||||||||||||||
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
|
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 }
|
|
|
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 }
|
|
||||||||||||
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
||||||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
|
||||||||||||
|
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 }
|
|
|
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 }
|
|
||||||||||||
|
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 }
|
|
|
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 }
|
|
||||||||||||||||
|
Definition at line 2895 of file w_force.c. References gentity_t, and GlobalUse(). Referenced by ForceThrow().
02896 {
02897 GlobalUse(self, other, activator);
02898 }
|
|
|
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 }
|
|
|
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 }
|
|
||||||||||||||||||||
|
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 }
|
|
|
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. |