/game/w_force.c
C | 5792 lines | 4895 code | 676 blank | 221 comment | 1433 complexity | 9246377cd634bd52cdb23d9f264484b0 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- //#include "g_local.h"
- #include "b_local.h"
- #include "w_saber.h"
- #include "ai_main.h"
- #include "../ghoul2/G2.h"
- #define METROID_JUMP 1
- //NEEDED FOR MIND-TRICK on NPCS=========================================================
- extern void NPC_PlayConfusionSound( gentity_t *self );
- extern void NPC_Jedi_PlayConfusionSound( gentity_t *self );
- extern void NPC_UseResponse( gentity_t *self, gentity_t *user, qboolean useWhenDone );
- //NEEDED FOR MIND-TRICK on NPCS=========================================================
- extern void Jedi_Decloak( gentity_t *self );
- extern vmCvar_t g_saberRestrictForce;
- #include "../namespace_begin.h"
- extern qboolean BG_FullBodyTauntAnim( int anim );
- #include "../namespace_end.h"
- extern bot_state_t *botstates[MAX_CLIENTS];
- int speedLoopSound = 0;
-
- int rageLoopSound = 0;
- int protectLoopSound = 0;
- int absorbLoopSound = 0;
- int seeLoopSound = 0;
- int ysalamiriLoopSound = 0;
- #define FORCE_VELOCITY_DAMAGE 0
- int ForceShootDrain( gentity_t *self );
- gentity_t *G_PreDefSound(vec3_t org, int pdSound)
- {
- gentity_t *te;
- te = G_TempEntity( org, EV_PREDEFSOUND );
- te->s.eventParm = pdSound;
- VectorCopy(org, te->s.origin);
- return te;
- }
- const int forcePowerMinRank[NUM_FORCE_POWER_LEVELS][NUM_FORCE_POWERS] = //0 == neutral
- {
- {
- 999,//FP_HEAL,//instant
- 999,//FP_LEVITATION,//hold/duration
- 999,//FP_SPEED,//duration
- 999,//FP_PUSH,//hold/duration
- 999,//FP_PULL,//hold/duration
- 999,//FP_TELEPATHY,//instant
- 999,//FP_GRIP,//hold/duration
- 999,//FP_LIGHTNING,//hold/duration
- 999,//FP_RAGE,//duration
- 999,//FP_PROTECT,//duration
- 999,//FP_ABSORB,//duration
- 999,//FP_TEAM_HEAL,//instant
- 999,//FP_TEAM_FORCE,//instant
- 999,//FP_DRAIN,//hold/duration
- 999,//FP_SEE,//duration
- 999,//FP_SABER_OFFENSE,
- 999,//FP_SABER_DEFENSE,
- 999//FP_SABERTHROW,
- //NUM_FORCE_POWERS
- },
- {
- 10,//FP_HEAL,//instant
- 0,//FP_LEVITATION,//hold/duration
- 0,//FP_SPEED,//duration
- 0,//FP_PUSH,//hold/duration
- 0,//FP_PULL,//hold/duration
- 10,//FP_TELEPATHY,//instant
- 15,//FP_GRIP,//hold/duration
- 10,//FP_LIGHTNING,//hold/duration
- 15,//FP_RAGE,//duration
- 15,//FP_PROTECT,//duration
- 15,//FP_ABSORB,//duration
- 10,//FP_TEAM_HEAL,//instant
- 10,//FP_TEAM_FORCE,//instant
- 10,//FP_DRAIN,//hold/duration
- 5,//FP_SEE,//duration
- 0,//FP_SABER_OFFENSE,
- 0,//FP_SABER_DEFENSE,
- 0//FP_SABERTHROW,
- //NUM_FORCE_POWERS
- },
- {
- 10,//FP_HEAL,//instant
- 0,//FP_LEVITATION,//hold/duration
- 0,//FP_SPEED,//duration
- 0,//FP_PUSH,//hold/duration
- 0,//FP_PULL,//hold/duration
- 10,//FP_TELEPATHY,//instant
- 15,//FP_GRIP,//hold/duration
- 10,//FP_LIGHTNING,//hold/duration
- 15,//FP_RAGE,//duration
- 15,//FP_PROTECT,//duration
- 15,//FP_ABSORB,//duration
- 10,//FP_TEAM_HEAL,//instant
- 10,//FP_TEAM_FORCE,//instant
- 10,//FP_DRAIN,//hold/duration
- 5,//FP_SEE,//duration
- 5,//FP_SABER_OFFENSE,
- 5,//FP_SABER_DEFENSE,
- 5//FP_SABERTHROW,
- //NUM_FORCE_POWERS
- },
- {
- 10,//FP_HEAL,//instant
- 0,//FP_LEVITATION,//hold/duration
- 0,//FP_SPEED,//duration
- 0,//FP_PUSH,//hold/duration
- 0,//FP_PULL,//hold/duration
- 10,//FP_TELEPATHY,//instant
- 15,//FP_GRIP,//hold/duration
- 10,//FP_LIGHTNING,//hold/duration
- 15,//FP_RAGE,//duration
- 15,//FP_PROTECT,//duration
- 15,//FP_ABSORB,//duration
- 10,//FP_TEAM_HEAL,//instant
- 10,//FP_TEAM_FORCE,//instant
- 10,//FP_DRAIN,//hold/duration
- 5,//FP_SEE,//duration
- 10,//FP_SABER_OFFENSE,
- 10,//FP_SABER_DEFENSE,
- 10//FP_SABERTHROW,
- //NUM_FORCE_POWERS
- }
- };
- const int mindTrickTime[NUM_FORCE_POWER_LEVELS] =
- {
- 0,//none
- 5000,
- 10000,
- 15000
- };
- void WP_InitForcePowers( gentity_t *ent )
- {
- int i;
- int i_r;
- int maxRank = g_maxForceRank.integer;
- qboolean warnClient = qfalse;
- qboolean warnClientLimit = qfalse;
- char userinfo[MAX_INFO_STRING];
- char forcePowers[256];
- char readBuf[256];
- int lastFPKnown = -1;
- qboolean didEvent = qfalse;
- if (!maxRank)
- { //if server has no max rank, default to max (50)
- maxRank = FORCE_MASTERY_JEDI_MASTER;
- }
- else if (maxRank >= NUM_FORCE_MASTERY_LEVELS)
- {//ack, prevent user from being dumb
- maxRank = FORCE_MASTERY_JEDI_MASTER;
- trap_Cvar_Set( "g_maxForceRank", va("%i", maxRank) );
- }
- /*
- if (g_forcePowerDisable.integer)
- {
- maxRank = FORCE_MASTERY_UNINITIATED;
- }
- */
- //rww - don't do this
- if ( !ent || !ent->client )
- {
- return;
- }
- ent->client->ps.fd.saberAnimLevel = ent->client->sess.saberLevel;
- if (ent->client->ps.fd.saberAnimLevel < FORCE_LEVEL_1 ||
- ent->client->ps.fd.saberAnimLevel > FORCE_LEVEL_3)
- {
- ent->client->ps.fd.saberAnimLevel = FORCE_LEVEL_1;
- }
- if (!speedLoopSound)
- { //so that the client configstring is already modified with this when we need it
- speedLoopSound = G_SoundIndex("sound/weapons/force/speedloop.wav");
- }
- if (!rageLoopSound)
- {
- rageLoopSound = G_SoundIndex("sound/weapons/force/rageloop.wav");
- }
- if (!absorbLoopSound)
- {
- absorbLoopSound = G_SoundIndex("sound/weapons/force/absorbloop.wav");
- }
- if (!protectLoopSound)
- {
- protectLoopSound = G_SoundIndex("sound/weapons/force/protectloop.wav");
- }
- if (!seeLoopSound)
- {
- seeLoopSound = G_SoundIndex("sound/weapons/force/seeloop.wav");
- }
- if (!ysalamiriLoopSound)
- {
- ysalamiriLoopSound = G_SoundIndex("sound/player/nullifyloop.wav");
- }
- if (ent->s.eType == ET_NPC)
- { //just stop here then.
- return;
- }
- i = 0;
- while (i < NUM_FORCE_POWERS)
- {
- ent->client->ps.fd.forcePowerLevel[i] = 0;
- ent->client->ps.fd.forcePowersKnown &= ~(1 << i);
- i++;
- }
- ent->client->ps.fd.forcePowerSelected = -1;
- ent->client->ps.fd.forceSide = 0;
- if (g_gametype.integer == GT_SIEGE &&
- ent->client->siegeClass != -1)
- { //Then use the powers for this class, and skip all this nonsense.
- i = 0;
- while (i < NUM_FORCE_POWERS)
- {
- ent->client->ps.fd.forcePowerLevel[i] = bgSiegeClasses[ent->client->siegeClass].forcePowerLevels[i];
- if (!ent->client->ps.fd.forcePowerLevel[i])
- {
- ent->client->ps.fd.forcePowersKnown &= ~(1 << i);
- }
- else
- {
- ent->client->ps.fd.forcePowersKnown |= (1 << i);
- }
- i++;
- }
- if (!ent->client->sess.setForce)
- {
- //bring up the class selection menu
- trap_SendServerCommand(ent-g_entities, "scl");
- }
- ent->client->sess.setForce = qtrue;
- return;
- }
- if (ent->s.eType == ET_NPC && ent->s.number >= MAX_CLIENTS)
- { //rwwFIXMEFIXME: Temp
- strcpy(userinfo, "forcepowers\\7-1-333003000313003120");
- }
- else
- {
- trap_GetUserinfo( ent->s.number, userinfo, sizeof( userinfo ) );
- }
- Q_strncpyz( forcePowers, Info_ValueForKey (userinfo, "forcepowers"), sizeof( forcePowers ) );
- if ( (ent->r.svFlags & SVF_BOT) && botstates[ent->s.number] )
- { //if it's a bot just copy the info directly from its personality
- Com_sprintf(forcePowers, sizeof(forcePowers), "%s\0", botstates[ent->s.number]->forceinfo);
- }
- //rww - parse through the string manually and eat out all the appropriate data
- i = 0;
- if (g_forceBasedTeams.integer)
- {
- if (ent->client->sess.sessionTeam == TEAM_RED)
- {
- warnClient = !(BG_LegalizedForcePowers(forcePowers, maxRank, HasSetSaberOnly(), FORCE_DARKSIDE, g_gametype.integer, g_forcePowerDisable.integer));
- }
- else if (ent->client->sess.sessionTeam == TEAM_BLUE)
- {
- warnClient = !(BG_LegalizedForcePowers(forcePowers, maxRank, HasSetSaberOnly(), FORCE_LIGHTSIDE, g_gametype.integer, g_forcePowerDisable.integer));
- }
- else
- {
- warnClient = !(BG_LegalizedForcePowers(forcePowers, maxRank, HasSetSaberOnly(), 0, g_gametype.integer, g_forcePowerDisable.integer));
- }
- }
- else
- {
- warnClient = !(BG_LegalizedForcePowers(forcePowers, maxRank, HasSetSaberOnly(), 0, g_gametype.integer, g_forcePowerDisable.integer));
- }
- i_r = 0;
- while (forcePowers[i] && forcePowers[i] != '-')
- {
- readBuf[i_r] = forcePowers[i];
- i_r++;
- i++;
- }
- readBuf[i_r] = 0;
- //THE RANK
- ent->client->ps.fd.forceRank = atoi(readBuf);
- i++;
- i_r = 0;
- while (forcePowers[i] && forcePowers[i] != '-')
- {
- readBuf[i_r] = forcePowers[i];
- i_r++;
- i++;
- }
- readBuf[i_r] = 0;
- //THE SIDE
- ent->client->ps.fd.forceSide = atoi(readBuf);
- i++;
- if ( g_gametype.integer != GT_SIEGE && (ent->r.svFlags & SVF_BOT) && botstates[ent->s.number] )
- { //hmm..I'm going to cheat here.
- int oldI = i;
- i_r = 0;
- while (forcePowers[i] && forcePowers[i] != '\n' &&
- i_r < NUM_FORCE_POWERS)
- {
- if (ent->client->ps.fd.forceSide == FORCE_LIGHTSIDE)
- {
- if (i_r == FP_ABSORB)
- {
- forcePowers[i] = '3';
- }
- if (botstates[ent->s.number]->settings.skill >= 4)
- { //cheat and give them more stuff
- if (i_r == FP_HEAL)
- {
- forcePowers[i] = '3';
- }
- else if (i_r == FP_PROTECT)
- {
- forcePowers[i] = '3';
- }
- }
- }
- else if (ent->client->ps.fd.forceSide == FORCE_DARKSIDE)
- {
- if (botstates[ent->s.number]->settings.skill >= 4)
- {
- if (i_r == FP_GRIP)
- {
- forcePowers[i] = '3';
- }
- else if (i_r == FP_LIGHTNING)
- {
- forcePowers[i] = '3';
- }
- else if (i_r == FP_RAGE)
- {
- forcePowers[i] = '3';
- }
- else if (i_r == FP_DRAIN)
- {
- forcePowers[i] = '3';
- }
- }
- }
- if (i_r == FP_PUSH)
- {
- forcePowers[i] = '3';
- }
- else if (i_r == FP_PULL)
- {
- forcePowers[i] = '3';
- }
- i++;
- i_r++;
- }
- i = oldI;
- }
- i_r = 0;
- while (forcePowers[i] && forcePowers[i] != '\n' &&
- i_r < NUM_FORCE_POWERS)
- {
- readBuf[0] = forcePowers[i];
- readBuf[1] = 0;
- ent->client->ps.fd.forcePowerLevel[i_r] = atoi(readBuf);
- if (ent->client->ps.fd.forcePowerLevel[i_r])
- {
- ent->client->ps.fd.forcePowersKnown |= (1 << i_r);
- }
- else
- {
- ent->client->ps.fd.forcePowersKnown &= ~(1 << i_r);
- }
- i++;
- i_r++;
- }
- //THE POWERS
- if (ent->s.eType != ET_NPC)
- {
- if (HasSetSaberOnly())
- {
- gentity_t *te = G_TempEntity( vec3_origin, EV_SET_FREE_SABER );
- te->r.svFlags |= SVF_BROADCAST;
- te->s.eventParm = 1;
- }
- else
- {
- gentity_t *te = G_TempEntity( vec3_origin, EV_SET_FREE_SABER );
- te->r.svFlags |= SVF_BROADCAST;
- te->s.eventParm = 0;
- }
- if (g_forcePowerDisable.integer)
- {
- gentity_t *te = G_TempEntity( vec3_origin, EV_SET_FORCE_DISABLE );
- te->r.svFlags |= SVF_BROADCAST;
- te->s.eventParm = 1;
- }
- else
- {
- gentity_t *te = G_TempEntity( vec3_origin, EV_SET_FORCE_DISABLE );
- te->r.svFlags |= SVF_BROADCAST;
- te->s.eventParm = 0;
- }
- }
- //rww - It seems we currently want to always do this, even if the player isn't exceeding the max
- //rank, so..
- // if (g_gametype.integer == GT_DUEL || g_gametype.integer == GT_POWERDUEL)
- // { //totally messes duel up to force someone into spec mode, and besides, each "round" is
- //counted as a full restart
- // ent->client->sess.setForce = qtrue;
- // }
- if (ent->s.eType == ET_NPC)
- {
- ent->client->sess.setForce = qtrue;
- }
- else if (g_gametype.integer == GT_SIEGE)
- {
- if (!ent->client->sess.setForce)
- {
- ent->client->sess.setForce = qtrue;
- //bring up the class selection menu
- trap_SendServerCommand(ent-g_entities, "scl");
- }
- }
- else
- {
- if (warnClient || !ent->client->sess.setForce)
- { //the client's rank is too high for the server and has been autocapped, so tell them
- if (g_gametype.integer != GT_HOLOCRON && g_gametype.integer != GT_JEDIMASTER )
- {
- #ifdef EVENT_FORCE_RANK
- gentity_t *te = G_TempEntity( vec3_origin, EV_GIVE_NEW_RANK );
- te->r.svFlags |= SVF_BROADCAST;
- te->s.trickedentindex = ent->s.number;
- te->s.eventParm = maxRank;
- te->s.bolt1 = 0;
- #endif
- didEvent = qtrue;
- // if (!(ent->r.svFlags & SVF_BOT) && g_gametype.integer != GT_DUEL && g_gametype.integer != GT_POWERDUEL && ent->s.eType != ET_NPC)
- if (!(ent->r.svFlags & SVF_BOT) && ent->s.eType != ET_NPC)
- {
- if (!g_teamAutoJoin.integer)
- {
- //Make them a spectator so they can set their powerups up without being bothered.
- ent->client->sess.sessionTeam = TEAM_SPECTATOR;
- ent->client->sess.spectatorState = SPECTATOR_FREE;
- ent->client->sess.spectatorClient = 0;
- ent->client->pers.teamState.state = TEAM_BEGIN;
- trap_SendServerCommand(ent-g_entities, "spc"); // Fire up the profile menu
- }
- }
- #ifdef EVENT_FORCE_RANK
- te->s.bolt2 = ent->client->sess.sessionTeam;
- #else
- //Event isn't very reliable, I made it a string. This way I can send it to just one
- //client also, as opposed to making a broadcast event.
- trap_SendServerCommand(ent->s.number, va("nfr %i %i %i", maxRank, 1, ent->client->sess.sessionTeam));
- //Arg1 is new max rank, arg2 is non-0 if force menu should be shown, arg3 is the current team
- #endif
- }
- ent->client->sess.setForce = qtrue;
- }
- if (!didEvent )
- {
- #ifdef EVENT_FORCE_RANK
- gentity_t *te = G_TempEntity( vec3_origin, EV_GIVE_NEW_RANK );
- te->r.svFlags |= SVF_BROADCAST;
- te->s.trickedentindex = ent->s.number;
- te->s.eventParm = maxRank;
- te->s.bolt1 = 1;
- te->s.bolt2 = ent->client->sess.sessionTeam;
- #else
- trap_SendServerCommand(ent->s.number, va("nfr %i %i %i", maxRank, 0, ent->client->sess.sessionTeam));
- #endif
- }
- if (warnClientLimit)
- { //the server has one or more force powers disabled and the client is using them in his config
- //trap_SendServerCommand(ent-g_entities, va("print \"The server has one or more force powers that you have chosen disabled.\nYou will not be able to use the disable force power(s) while playing on this server.\n\""));
- }
- }
- i = 0;
- while (i < NUM_FORCE_POWERS)
- {
- if ((ent->client->ps.fd.forcePowersKnown & (1 << i)) &&
- !ent->client->ps.fd.forcePowerLevel[i])
- { //err..
- ent->client->ps.fd.forcePowersKnown &= ~(1 << i);
- }
- else
- {
- if (i != FP_LEVITATION && i != FP_SABER_OFFENSE && i != FP_SABER_DEFENSE && i != FP_SABERTHROW)
- {
- lastFPKnown = i;
- }
- }
- i++;
- }
- if (ent->client->ps.fd.forcePowersKnown & ent->client->sess.selectedFP)
- {
- ent->client->ps.fd.forcePowerSelected = ent->client->sess.selectedFP;
- }
- if (!(ent->client->ps.fd.forcePowersKnown & (1 << ent->client->ps.fd.forcePowerSelected)))
- {
- if (lastFPKnown != -1)
- {
- ent->client->ps.fd.forcePowerSelected = lastFPKnown;
- }
- else
- {
- ent->client->ps.fd.forcePowerSelected = 0;
- }
- }
- while (i < NUM_FORCE_POWERS)
- {
- ent->client->ps.fd.forcePowerBaseLevel[i] = ent->client->ps.fd.forcePowerLevel[i];
- i++;
- }
- ent->client->ps.fd.forceUsingAdded = 0;
- }
- void WP_SpawnInitForcePowers( gentity_t *ent )
- {
- int i = 0;
- ent->client->ps.saberAttackChainCount = 0;
- i = 0;
- while (i < NUM_FORCE_POWERS)
- {
- if (ent->client->ps.fd.forcePowersActive & (1 << i))
- {
- WP_ForcePowerStop(ent, i);
- }
- i++;
- }
- ent->client->ps.fd.forceDeactivateAll = 0;
- ent->client->ps.fd.forcePower = ent->client->ps.fd.forcePowerMax = FORCE_POWER_MAX;
- ent->client->ps.fd.forcePowerRegenDebounceTime = 0;
- ent->client->ps.fd.forceGripEntityNum = ENTITYNUM_NONE;
- ent->client->ps.fd.forceMindtrickTargetIndex = 0;
- ent->client->ps.fd.forceMindtrickTargetIndex2 = 0;
- ent->client->ps.fd.forceMindtrickTargetIndex3 = 0;
- ent->client->ps.fd.forceMindtrickTargetIndex4 = 0;
- ent->client->ps.holocronBits = 0;
- i = 0;
- while (i < NUM_FORCE_POWERS)
- {
- ent->client->ps.holocronsCarried[i] = 0;
- i++;
- }
- if (g_gametype.integer == GT_HOLOCRON)
- {
- i = 0;
- while (i < NUM_FORCE_POWERS)
- {
- ent->client->ps.fd.forcePowerLevel[i] = FORCE_LEVEL_0;
- i++;
- }
- if (HasSetSaberOnly())
- {
- if (ent->client->ps.fd.forcePowerLevel[FP_SABER_OFFENSE] < FORCE_LEVEL_1)
- {
- ent->client->ps.fd.forcePowerLevel[FP_SABER_OFFENSE] = FORCE_LEVEL_1;
- }
- if (ent->client->ps.fd.forcePowerLevel[FP_SABER_DEFENSE] < FORCE_LEVEL_1)
- {
- ent->client->ps.fd.forcePowerLevel[FP_SABER_DEFENSE] = FORCE_LEVEL_1;
- }
- }
- }
- i = 0;
- while (i < NUM_FORCE_POWERS)
- {
- ent->client->ps.fd.forcePowerDebounce[i] = 0;
- ent->client->ps.fd.forcePowerDuration[i] = 0;
- i++;
- }
- ent->client->ps.fd.forcePowerRegenDebounceTime = 0;
- ent->client->ps.fd.forceJumpZStart = 0;
- ent->client->ps.fd.forceJumpCharge = 0;
- ent->client->ps.fd.forceJumpSound = 0;
- ent->client->ps.fd.forceGripDamageDebounceTime = 0;
- ent->client->ps.fd.forceGripBeingGripped = 0;
- ent->client->ps.fd.forceGripCripple = 0;
- ent->client->ps.fd.forceGripUseTime = 0;
- ent->client->ps.fd.forceGripSoundTime = 0;
- ent->client->ps.fd.forceGripStarted = 0;
- ent->client->ps.fd.forceHealTime = 0;
- ent->client->ps.fd.forceHealAmount = 0;
- ent->client->ps.fd.forceRageRecoveryTime = 0;
- ent->client->ps.fd.forceDrainEntNum = ENTITYNUM_NONE;
- ent->client->ps.fd.forceDrainTime = 0;
- i = 0;
- while (i < NUM_FORCE_POWERS)
- {
- if ((ent->client->ps.fd.forcePowersKnown & (1 << i)) &&
- !ent->client->ps.fd.forcePowerLevel[i])
- { //make sure all known powers are cleared if we have level 0 in them
- ent->client->ps.fd.forcePowersKnown &= ~(1 << i);
- }
- i++;
- }
- if (g_gametype.integer == GT_SIEGE &&
- ent->client->siegeClass != -1)
- { //Then use the powers for this class.
- i = 0;
- while (i < NUM_FORCE_POWERS)
- {
- ent->client->ps.fd.forcePowerLevel[i] = bgSiegeClasses[ent->client->siegeClass].forcePowerLevels[i];
- if (!ent->client->ps.fd.forcePowerLevel[i])
- {
- ent->client->ps.fd.forcePowersKnown &= ~(1 << i);
- }
- else
- {
- ent->client->ps.fd.forcePowersKnown |= (1 << i);
- }
- i++;
- }
- }
- }
- #include "../namespace_begin.h"
- extern qboolean BG_InKnockDown( int anim ); //bg_pmove.c
- #include "../namespace_end.h"
- int ForcePowerUsableOn(gentity_t *attacker, gentity_t *other, forcePowers_t forcePower)
- {
- if (other && other->client && BG_HasYsalamiri(g_gametype.integer, &other->client->ps))
- {
- return 0;
- }
- if (attacker && attacker->client && !BG_CanUseFPNow(g_gametype.integer, &attacker->client->ps, level.time, forcePower))
- {
- return 0;
- }
- //Dueling fighters cannot use force powers on others, with the exception of force push when locked with each other
- if (attacker && attacker->client && attacker->client->ps.duelInProgress)
- {
- return 0;
- }
- if (other && other->client && other->client->ps.duelInProgress)
- {
- return 0;
- }
- if (forcePower == FP_GRIP)
- {
- if (other && other->client &&
- (other->client->ps.fd.forcePowersActive & (1<<FP_ABSORB)))
- { //don't allow gripping to begin with if they are absorbing
- //play sound indicating that attack was absorbed
- if (other->client->forcePowerSoundDebounce < level.time)
- {
- gentity_t *abSound = G_PreDefSound(other->client->ps.origin, PDSOUND_ABSORBHIT);
- abSound->s.trickedentindex = other->s.number;
- other->client->forcePowerSoundDebounce = level.time + 400;
- }
- return 0;
- }
- else if (other && other->client &&
- other->client->ps.weapon == WP_SABER &&
- BG_SaberInSpecial(other->client->ps.saberMove))
- { //don't grip person while they are in a special or some really bad things can happen.
- return 0;
- }
- }
- if (other && other->client &&
- (forcePower == FP_PUSH ||
- forcePower == FP_PULL))
- {
- if (BG_InKnockDown(other->client->ps.legsAnim))
- {
- return 0;
- }
- }
- if (other && other->client && other->s.eType == ET_NPC &&
- other->s.NPC_class == CLASS_VEHICLE)
- { //can't use the force on vehicles.. except lightning
- if (forcePower == FP_LIGHTNING)
- {
- return 1;
- }
- else
- {
- return 0;
- }
- }
- if (other && other->client && other->s.eType == ET_NPC &&
- g_gametype.integer == GT_SIEGE)
- { //can't use powers at all on npc's normally in siege...
- return 0;
- }
- return 1;
- }
- qboolean WP_ForcePowerAvailable( gentity_t *self, forcePowers_t forcePower, int overrideAmt )
- {
- int drain = overrideAmt ? overrideAmt :
- forcePowerNeeded[self->client->ps.fd.forcePowerLevel[forcePower]][forcePower];
- if (self->client->ps.fd.forcePowersActive & (1 << forcePower))
- { //we're probably going to deactivate it..
- return qtrue;
- }
- if ( forcePower == FP_LEVITATION )
- {
- return qtrue;
- }
- if ( !drain )
- {
- return qtrue;
- }
- if ((forcePower == FP_DRAIN || forcePower == FP_LIGHTNING) &&
- self->client->ps.fd.forcePower >= 25)
- { //it's ok then, drain/lightning are actually duration
- return qtrue;
- }
- if ( self->client->ps.fd.forcePower < drain )
- {
- return qfalse;
- }
- return qtrue;
- }
- qboolean WP_ForcePowerInUse( gentity_t *self, forcePowers_t forcePower )
- {
- if ( (self->client->ps.fd.forcePowersActive & ( 1 << forcePower )) )
- {//already using this power
- return qtrue;
- }
- return qfalse;
- }
- qboolean WP_ForcePowerUsable( gentity_t *self, forcePowers_t forcePower )
- {
- if (BG_HasYsalamiri(g_gametype.integer, &self->client->ps))
- {
- return qfalse;
- }
- if (self->health <= 0 || self->client->ps.stats[STAT_HEALTH] <= 0 ||
- (self->client->ps.eFlags & EF_DEAD))
- {
- return qfalse;
- }
- if (self->client->ps.pm_flags & PMF_FOLLOW)
- { //specs can't use powers through people
- return qfalse;
- }
- if (self->client->sess.sessionTeam == TEAM_SPECTATOR)
- {
- return qfalse;
- }
- if (self->client->tempSpectate >= level.time)
- {
- return qfalse;
- }
- if (!BG_CanUseFPNow(g_gametype.integer, &self->client->ps, level.time, forcePower))
- {
- return qfalse;
- }
- if ( !(self->client->ps.fd.forcePowersKnown & ( 1 << forcePower )) )
- {//don't know this power
- return qfalse;
- }
-
- if ( (self->client->ps.fd.forcePowersActive & ( 1 << forcePower )) )
- {//already using this power
- if (forcePower != FP_LEVITATION)
- {
- return qfalse;
- }
- }
- if (forcePower == FP_LEVITATION && self->client->fjDidJump)
- {
- return qfalse;
- }
- if (!self->client->ps.fd.forcePowerLevel[forcePower])
- {
- return qfalse;
- }
- if ( g_debugMelee.integer )
- {
- if ( (self->client->ps.pm_flags&PMF_STUCK_TO_WALL) )
- {//no offensive force powers when stuck to wall
- switch ( forcePower )
- {
- case FP_GRIP:
- case FP_LIGHTNING:
- case FP_DRAIN:
- case FP_SABER_OFFENSE:
- case FP_SABER_DEFENSE:
- case FP_SABERTHROW:
- return qfalse;
- break;
- }
- }
- }
- if ( !self->client->ps.saberHolstered )
- {
- if ( (self->client->saber[0].saberFlags&SFL_TWO_HANDED) )
- {
- if ( g_saberRestrictForce.integer )
- {
- switch ( forcePower )
- {
- case FP_PUSH:
- case FP_PULL:
- case FP_TELEPATHY:
- case FP_GRIP:
- case FP_LIGHTNING:
- case FP_DRAIN:
- return qfalse;
- break;
- }
- }
- }
- if ( (self->client->saber[0].saberFlags&SFL_TWO_HANDED)
- || (self->client->saber[0].model && self->client->saber[0].model[0]) )
- {//this saber requires the use of two hands OR our other hand is using an active saber too
- if ( (self->client->saber[0].forceRestrictions&(1<<forcePower)) )
- {//this power is verboten when using this saber
- return qfalse;
- }
- }
- if ( self->client->saber[0].model
- && self->client->saber[0].model[0] )
- {//both sabers on
- if ( g_saberRestrictForce.integer )
- {
- switch ( forcePower )
- {
- case FP_PUSH:
- case FP_PULL:
- case FP_TELEPATHY:
- case FP_GRIP:
- case FP_LIGHTNING:
- case FP_DRAIN:
- return qfalse;
- break;
- }
- }
- if ( (self->client->saber[1].forceRestrictions&(1<<forcePower)) )
- {//this power is verboten when using this saber
- return qfalse;
- }
- }
- }
- return WP_ForcePowerAvailable( self, forcePower, 0 ); // OVERRIDEFIXME
- }
- int WP_AbsorbConversion(gentity_t *attacked, int atdAbsLevel, gentity_t *attacker, int atPower, int atPowerLevel, int atForceSpent)
- {
- int getLevel = 0;
- int addTot = 0;
- gentity_t *abSound;
- if (atPower != FP_LIGHTNING &&
- atPower != FP_DRAIN &&
- atPower != FP_GRIP &&
- atPower != FP_PUSH &&
- atPower != FP_PULL)
- { //Only these powers can be absorbed
- return -1;
- }
- if (!atdAbsLevel)
- { //looks like attacker doesn't have any absorb power
- return -1;
- }
- if (!(attacked->client->ps.fd.forcePowersActive & (1 << FP_ABSORB)))
- { //absorb is not active
- return -1;
- }
- //Subtract absorb power level from the offensive force power
- getLevel = atPowerLevel;
- getLevel -= atdAbsLevel;
- if (getLevel < 0)
- {
- getLevel = 0;
- }
- //let the attacker absorb an amount of force used in this attack based on his level of absorb
- addTot = (atForceSpent/3)*attacked->client->ps.fd.forcePowerLevel[FP_ABSORB];
- if (addTot < 1 && atForceSpent >= 1)
- {
- addTot = 1;
- }
- attacked->client->ps.fd.forcePower += addTot;
- if (attacked->client->ps.fd.forcePower > 100)
- {
- attacked->client->ps.fd.forcePower = 100;
- }
- //play sound indicating that attack was absorbed
- if (attacked->client->forcePowerSoundDebounce < level.time)
- {
- abSound = G_PreDefSound(attacked->client->ps.origin, PDSOUND_ABSORBHIT);
- abSound->s.trickedentindex = attacked->s.number;
- attacked->client->forcePowerSoundDebounce = level.time + 400;
- }
- return getLevel;
- }
- void WP_ForcePowerRegenerate( gentity_t *self, int overrideAmt )
- { //called on a regular interval to regenerate force power.
- if ( !self->client )
- {
- return;
- }
- if ( overrideAmt )
- { //custom regen amount
- self->client->ps.fd.forcePower += overrideAmt;
- }
- else
- { //otherwise, just 1
- self->client->ps.fd.forcePower++;
- }
- if ( self->client->ps.fd.forcePower > self->client->ps.fd.forcePowerMax )
- { //cap it off at the max (default 100)
- self->client->ps.fd.forcePower = self->client->ps.fd.forcePowerMax;
- }
- }
- void WP_ForcePowerStart( gentity_t *self, forcePowers_t forcePower, int overrideAmt )
- { //activate the given force power
- int duration = 0;
- qboolean hearable = qfalse;
- float hearDist = 0;
- if (!WP_ForcePowerAvailable( self, forcePower, overrideAmt ))
- {
- return;
- }
- if ( BG_FullBodyTauntAnim( self->client->ps.legsAnim ) )
- {//stop taunt
- self->client->ps.legsTimer = 0;
- }
- if ( BG_FullBodyTauntAnim( self->client->ps.torsoAnim ) )
- {//stop taunt
- self->client->ps.torsoTimer = 0;
- }
- //hearable and hearDist are merely for the benefit of bots, and not related to if a sound is actually played.
- //If duration is set, the force power will assume to be timer-based.
- switch( (int)forcePower )
- {
- case FP_HEAL:
- hearable = qtrue;
- hearDist = 256;
- self->client->ps.fd.forcePowersActive |= ( 1 << forcePower );
- break;
- case FP_LEVITATION:
- hearable = qtrue;
- hearDist = 256;
- self->client->ps.fd.forcePowersActive |= ( 1 << forcePower );
- break;
- case FP_SPEED:
- hearable = qtrue;
- hearDist = 256;
- if (self->client->ps.fd.forcePowerLevel[FP_SPEED] == FORCE_LEVEL_1)
- {
- duration = 10000;
- }
- else if (self->client->ps.fd.forcePowerLevel[FP_SPEED] == FORCE_LEVEL_2)
- {
- duration = 15000;
- }
- else if (self->client->ps.fd.forcePowerLevel[FP_SPEED] == FORCE_LEVEL_3)
- {
- duration = 20000;
- }
- else //shouldn't get here
- {
- break;
- }
- if (overrideAmt)
- {
- duration = overrideAmt;
- }
- self->client->ps.fd.forcePowersActive |= ( 1 << forcePower );
- break;
- case FP_PUSH:
- hearable = qtrue;
- hearDist = 256;
- break;
- case FP_PULL:
- hearable = qtrue;
- hearDist = 256;
- break;
- case FP_TELEPATHY:
- hearable = qtrue;
- hearDist = 256;
- if (self->client->ps.fd.forcePowerLevel[FP_TELEPATHY] == FORCE_LEVEL_1)
- {
- duration = 20000;
- }
- else if (self->client->ps.fd.forcePowerLevel[FP_TELEPATHY] == FORCE_LEVEL_2)
- {
- duration = 25000;
- }
- else if (self->client->ps.fd.forcePowerLevel[FP_TELEPATHY] == FORCE_LEVEL_3)
- {
- duration = 30000;
- }
- else //shouldn't get here
- {
- break;
- }
- self->client->ps.fd.forcePowersActive |= ( 1 << forcePower );
- break;
- case FP_GRIP:
- hearable = qtrue;
- hearDist = 256;
- self->client->ps.fd.forcePowersActive |= ( 1 << forcePower );
- self->client->ps.powerups[PW_DISINT_4] = level.time + 60000;
- break;
- case FP_LIGHTNING:
- hearable = qtrue;
- hearDist = 512;
- duration = overrideAmt;
- overrideAmt = 0;
- self->client->ps.fd.forcePowersActive |= ( 1 << forcePower );
- self->client->ps.activeForcePass = self->client->ps.fd.forcePowerLevel[FP_LIGHTNING];
- break;
- case FP_RAGE:
- hearable = qtrue;
- hearDist = 256;
- if (self->client->ps.fd.forcePowerLevel[FP_RAGE] == FORCE_LEVEL_1)
- {
- duration = 8000;
- }
- else if (self->client->ps.fd.forcePowerLevel[FP_RAGE] == FORCE_LEVEL_2)
- {
- duration = 14000;
- }
- else if (self->client->ps.fd.forcePowerLevel[FP_RAGE] == FORCE_LEVEL_3)
- {
- duration = 20000;
- }
- else //shouldn't get here
- {
- break;
- }
- self->client->ps.fd.forcePowersActive |= ( 1 << forcePower );
- break;
- case FP_PROTECT:
- hearable = qtrue;
- hearDist = 256;
- duration = 20000;
- self->client->ps.fd.forcePowersActive |= ( 1 << forcePower );
- break;
- case FP_ABSORB:
- hearable = qtrue;
- hearDist = 256;
- duration = 20000;
- self->client->ps.fd.forcePowersActive |= ( 1 << forcePower );
- break;
- case FP_TEAM_HEAL:
- hearable = qtrue;
- hearDist = 256;
- self->client->ps.fd.forcePowersActive |= ( 1 << forcePower );
- break;
- case FP_TEAM_FORCE:
- hearable = qtrue;
- hearDist = 256;
- self->client->ps.fd.forcePowersActive |= ( 1 << forcePower );
- break;
- case FP_DRAIN:
- hearable = qtrue;
- hearDist = 256;
- duration = overrideAmt;
- overrideAmt = 0;
- self->client->ps.fd.forcePowersActive |= ( 1 << forcePower );
- //self->client->ps.activeForcePass = self->client->ps.fd.forcePowerLevel[FP_DRAIN];
- break;
- case FP_SEE:
- hearable = qtrue;
- hearDist = 256;
- if (self->client->ps.fd.forcePowerLevel[FP_SEE] == FORCE_LEVEL_1)
- {
- duration = 10000;
- }
- else if (self->client->ps.fd.forcePowerLevel[FP_SEE] == FORCE_LEVEL_2)
- {
- duration = 20000;
- }
- else if (self->client->ps.fd.forcePowerLevel[FP_SEE] == FORCE_LEVEL_3)
- {
- duration = 30000;
- }
- else //shouldn't get here
- {
- break;
- }
- self->client->ps.fd.forcePowersActive |= ( 1 << forcePower );
- break;
- case FP_SABER_OFFENSE:
- break;
- case FP_SABER_DEFENSE:
- break;
- case FP_SABERTHROW:
- break;
- default:
- break;
- }
- if ( duration )
- {
- self->client->ps.fd.forcePowerDuration[forcePower] = level.time + duration;
- }
- else
- {
- self->client->ps.fd.forcePowerDuration[forcePower] = 0;
- }
- if (hearable)
- {
- self->client->ps.otherSoundLen = hearDist;
- self->client->ps.otherSoundTime = level.time + 100;
- }
-
- self->client->ps.fd.forcePowerDebounce[forcePower] = 0;
- if ((int)forcePower == FP_SPEED && overrideAmt)
- {
- BG_ForcePowerDrain( &self->client->ps, forcePower, overrideAmt*0.025 );
- }
- else if ((int)forcePower != FP_GRIP && (int)forcePower != FP_DRAIN)
- { //grip and drain drain as damage is done
- BG_ForcePowerDrain( &self->client->ps, forcePower, overrideAmt );
- }
- }
- void ForceHeal( gentity_t *self )
- {
- if ( self->health <= 0 )
- {
- return;
- }
- if ( !WP_ForcePowerUsable( self, FP_HEAL ) )
- {
- return;
- }
- if ( self->health >= self->client->ps.stats[STAT_MAX_HEALTH])
- {
- return;
- }
- if (self->client->ps.fd.forcePowerLevel[FP_HEAL] == FORCE_LEVEL_3)
- {
- self->health += 25; //This was 50, but that angered the Balance God.
-
- if (self->health > self->client->ps.stats[STAT_MAX_HEALTH])
- {
- self->health = self->client->ps.stats[STAT_MAX_HEALTH];
- }
- BG_ForcePowerDrain( &self->client->ps, FP_HEAL, 0 );
- }
- else if (self->client->ps.fd.forcePowerLevel[FP_HEAL] == FORCE_LEVEL_2)
- {
- self->health += 10;
-
- if (self->health > self->client->ps.stats[STAT_MAX_HEALTH])
- {
- self->health = self->client->ps.stats[STAT_MAX_HEALTH];
- }
- BG_ForcePowerDrain( &self->client->ps, FP_HEAL, 0 );
- }
- else
- {
- self->health += 5;
-
- if (self->health > self->client->ps.stats[STAT_MAX_HEALTH])
- {
- self->health = self->client->ps.stats[STAT_MAX_HEALTH];
- }
- BG_ForcePowerDrain( &self->client->ps, FP_HEAL, 0 );
- }
- /*
- else
- {
- WP_ForcePowerStart( self, FP_HEAL, 0 );
- }
- */
- //NOTE: Decided to make all levels instant.
- G_Sound( self, CHAN_ITEM, G_SoundIndex("sound/weapons/force/heal.wav") );
- }
- void WP_AddToClientBitflags(gentity_t *ent, int entNum)
- {
- if (!ent)
- {
- return;
- }
- if (entNum > 47)
- {
- ent->s.trickedentindex4 |= (1 << (entNum-48));
- }
- else if (entNum > 31)
- {
- ent->s.trickedentindex3 |= (1 << (entNum-32));
- }
- else if (entNum > 15)
- {
- ent->s.trickedentindex2 |= (1 << (entNum-16));
- }
- else
- {
- ent->s.trickedentindex |= (1 << entNum);
- }
- }
- void ForceTeamHeal( gentity_t *self )
- {
- float radius = 256;
- int i = 0;
- gentity_t *ent;
- vec3_t a;
- int numpl = 0;
- int pl[MAX_CLIENTS];
- int healthadd = 0;
- gentity_t *te = NULL;
- if ( self->health <= 0 )
- {
- return;
- }
- if ( !WP_ForcePowerUsable( self, FP_TEAM_HEAL ) )
- {
- return;
- }
- if (self->client->ps.fd.forcePowerDebounce[FP_TEAM_HEAL] >= level.time)
- {
- return;
- }
- if (self->client->ps.fd.forcePowerLevel[FP_TEAM_HEAL] == FORCE_LEVEL_2)
- {
- radius *= 1.5;
- }
- if (self->client->ps.fd.forcePowerLevel[FP_TEAM_HEAL] == FORCE_LEVEL_3)
- {
- radius *= 2;
- }
- while (i < MAX_CLIENTS)
- {
- ent = &g_entities[i];
- 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) &&
- trap_InPVS(self->client->ps.origin, ent->client->ps.origin))
- {
- VectorSubtract(self->client->ps.origin, ent->client->ps.origin, a);
- if (VectorLength(a) <= radius)
- {
- pl[numpl] = i;
- numpl++;
- }
- }
- i++;
- }
- if (numpl < 1)
- {
- return;
- }
- if (numpl == 1)
- {
- healthadd = 50;
- }
- else if (numpl == 2)
- {
- healthadd = 33;
- }
- else
- {
- healthadd = 25;
- }
- self->client->ps.fd.forcePowerDebounce[FP_TEAM_HEAL] = level.time + 2000;
- i = 0;
- while (i < numpl)
- {
- if (g_entities[pl[i]].client->ps.stats[STAT_HEALTH] > 0 &&
- g_entities[pl[i]].health > 0)
- {
- g_entities[pl[i]].client->ps.stats[STAT_HEALTH] += healthadd;
- if (g_entities[pl[i]].client->ps.stats[STAT_HEALTH] > g_entities[pl[i]].client->ps.stats[STAT_MAX_HEALTH])
- {
- g_entities[pl[i]].client->ps.stats[STAT_HEALTH] = g_entities[pl[i]].client->ps.stats[STAT_MAX_HEALTH];
- }
- g_entities[pl[i]].health = g_entities[pl[i]].client->ps.stats[STAT_HEALTH];
- //At this point we know we got one, so add him into the collective event client bitflag
- if (!te)
- {
- te = G_TempEntity( self->client->ps.origin, EV_TEAM_POWER);
- te->s.eventParm = 1; //eventParm 1 is heal, eventParm 2 is force regen
- //since we had an extra check above, do the drain now because we got at least one guy
- BG_ForcePowerDrain( &self->client->ps, FP_TEAM_HEAL, forcePowerNeeded[self->client->ps.fd.forcePowerLevel[FP_TEAM_HEAL]][FP_TEAM_HEAL] );
- }
- WP_AddToClientBitflags(te, pl[i]);
- //Now cramming it all into one event.. doing this many g_sound events at once was a Bad Thing.
- }
- i++;
- }
- }
- void ForceTeamForceReplenish( gentity_t *self )
- {
- float radius = 256;
- int i = 0;
- gentity_t *ent;
- vec3_t a;
- int numpl = 0;
- int pl[MAX_CLIENTS];
- int poweradd = 0;
- gentity_t *te = NULL;
- if ( self->health <= 0 )
- {
- return;
- }
- if ( !WP_ForcePowerUsable( self, FP_TEAM_FORCE ) )
- {
- return;
- }
- if (self->client->ps.fd.forcePowerDebounce[FP_TEAM_FORCE] >= level.time)
- {
- return;
- }
- if (self->client->ps.fd.forcePowerLevel[FP_TEAM_FORCE] == FORCE_LEVEL_2)
- {
- radius *= 1.5;
- }
- if (self->client->ps.fd.forcePowerLevel[FP_TEAM_FORCE] == FORCE_LEVEL_3)
- {
- radius *= 2;
- }
- while (i < MAX_CLIENTS)
- {
- ent = &g_entities[i];
- if (ent && ent->client && self != ent && OnSameTeam(self, ent) && ent->client->ps.fd.forcePower < 100 && ForcePowerUsableOn(self, ent, FP_TEAM_FORCE) &&
- trap_InPVS(self->client->ps.origin, ent->client->ps.origin))
- {
- VectorSubtract(self->client->ps.origin, ent->client->ps.origin, a);
- if (VectorLength(a) <= radius)
- {
- pl[numpl] = i;
- numpl++;
- }
- }
- i++;
- }
- if (numpl < 1)
- {
- return;
- }
- if (numpl == 1)
- {
- poweradd = 50;
- }
- else if (numpl == 2)
- {
- poweradd = 33;
- }
- else
- {
- poweradd = 25;
- }
- self->client->ps.fd.forcePowerDebounce[FP_TEAM_FORCE] = level.time + 2000;
- BG_ForcePowerDrain( &self->client->ps, FP_TEAM_FORCE, forcePowerNeeded[self->client->ps.fd.forcePowerLevel[FP_TEAM_FORCE]][FP_TEAM_FORCE] );
- i = 0;
- while (i < numpl)
- {
- g_entities[pl[i]].client->ps.fd.forcePower += poweradd;
- if (g_entities[pl[i]].client->ps.fd.forcePower > 100)
- {
- g_entities[pl[i]].client->ps.fd.forcePower = 100;
- }
- //At this point we know we got one, so add him into the collective event client bitflag
- if (!te)
- {
- te = G_TempEntity( self->client->ps.origin, EV_TEAM_POWER);
- te->s.eventParm = 2; //eventParm 1 is heal, eventParm 2 is force regen
- }
- WP_AddToClientBitflags(te, pl[i]);
- //Now cramming it all into one event.. doing this many g_sound events at once was a Bad Thing.
-
- i++;
- }
- }
- void ForceGrip( gentity_t *self )
- {
- trace_t tr;
- vec3_t tfrom, tto, fwd;
- if ( self->health <= 0 )
- {
- return;
- }
- if (self->client->ps.forceHandExtend != HANDEXTEND_NONE)
- {
- return;
- }
- if (self->client->ps.weaponTime > 0)
- {
- return;
- }
- if (self->client->ps.fd.forceGripUseTime > level.time)
- {
- return;
- }
- if ( !WP_ForcePowerUsable( self, FP_GRIP ) )
- {
- return;
- }
- VectorCopy(self->client->ps.origin, tfrom);
- tfrom[2] += self->client->ps.viewheight;
- AngleVectors(self->client->ps.viewangles, fwd, NULL, NULL);
- tto[0] = tfrom[0] + fwd[0]*MAX_GRIP_DISTANCE;
- tto[1] = tfrom[1] + fwd[1]*MAX_GRIP_DISTANCE;
- tto[2] = tfrom[2] + fwd[2]*MAX_GRIP_DISTANCE;
- trap_Trace(&tr, tfrom, NULL, NULL, tto, self->s.number, MASK_PLAYERSOLID);
- if ( tr.fraction != 1.0 &&
- tr.entityNum != ENTITYNUM_NONE &&
- g_entities[tr.entityNum].client &&
- !g_entities[tr.entityNum].client->ps.fd.forceGripCripple &&
- g_entities[tr.entityNum].client->ps.fd.forceGripBeingGripped < level.time &&
- ForcePowerUsableOn(self, &g_entities[tr.entityNum], FP_GRIP) &&
- (g_friendlyFire.integer || !OnSameTeam(self, &g_entities[tr.entityNum])) ) //don't grip someone who's still crippled
- {
- if (g_entities[tr.entityNum].s.number < MAX_CLIENTS && g_entities[tr.entityNum].client->ps.m_iVehicleNum)
- { //a player on a vehicle
- gentity_t *vehEnt = &g_entities[g_entities[tr.entityNum].client->ps.m_iVehicleNum];
- if (vehEnt->inuse && vehEnt->client && vehEnt->m_pVehicle)
- {
- if (vehEnt->m_pVehicle->m_pVehicleInfo->type == VH_SPEEDER ||
- vehEnt->m_pVehicle->m_pVehicleInfo->type == VH_ANIMAL)
- { //push the guy off
- vehEnt->m_pVehicle->m_pVehicleInfo->Eject(vehEnt->m_pVehicle, (bgEntity_t *)&g_entities[tr.entityNum], qfalse);
- }
- }
- }
- self->client->ps.fd.forceGripEntityNum = tr.entityNum;
- g_entities[tr.entityNum].client->ps.fd.forceGripStarted = level.time;
- self->client->ps.fd.forceGripDamageDebounceTime = 0;
- self->client->ps.forceHandExtend = HANDEXTEND_FORCE_HOLD;
- self->client->ps.forceHandExtendTime = level.time + 5000;
- }
- else
- {
- self->client->ps.fd.forceGripEntityNum = ENTITYNUM_NONE;
- return;
- }
- }
- void ForceSpeed( gentity_t *self, int forceDuration )
- {
- if ( self->health <= 0 )
- {
- return;
- }
- if (self->client->ps.forceAllowDeactivateTime < level.time &&
- (self->client->ps.fd.forcePowersActive & (1 << FP_SPEED)) )
- {
- WP_ForcePowerStop( self, FP_SPEED );
- return;
- }
- if ( !WP_ForcePowerUsable( self, FP_SPEED ) )
- {
- return;
- }
- if ( self->client->holdingObjectiveItem >= MAX_CLIENTS
- && self->client->holdingObjectiveItem < ENTITYNUM_WORLD )
- {//holding Siege item
- if ( g_entities[self->client->holdingObjectiveItem].genericValue15 )
- {//disables force powers
- return;
- }
- }
- self->client->ps.forceAllowDeactivateTime = level.time + 1500;
- WP_ForcePowerStart( self, FP_SPEED, forceDuration );
- G_Sound( self, CHAN_BODY, G_SoundIndex("sound/weapons/force/speed.wav") );
- G_Sound( self, TRACK_CHANNEL_2, speedLoopSound );
- }
- void ForceSeeing( gentity_t *self )
- {
- if ( self->health <= 0 )
- {
- return;
- }
- if (self->client->ps.forceAllowDeactivateTime < level.time &&
- (self->client->ps.fd.forcePowersActive & (1 << FP_SEE)) )
- {
- WP_ForcePowerStop( self, FP_SEE );
- return;
- }
- if ( !WP_ForcePowerUsable( self, FP_SEE ) )
- {
- return;
- }
- self->client->ps.forceAllowDeactivateTime = level.time + 1500;
- WP_ForcePowerStart( self, FP_SEE, 0 );
- G_Sound( self, CHAN_AUTO, G_SoundIndex("sound/weapons/force/see.wav") );
- G_Sound( self, TRACK_CHANNEL_5, seeLoopSound );
- }
- void ForceProtect( gentity_t *self )
- {
- if ( self->health <= 0 )
- {
- return;
- }
- if (self->client->ps.forceAllowDeactivateTime < level.time &&
- (self->client->ps.fd.forcePowersActive & (1 << FP_PROTECT)) )
- {
- WP_ForcePowerStop( self, FP_PROTECT );
- return;
- }
- if ( !WP_ForcePowerUsable( self, FP_PROTECT ) )
- {
- return;
- }
- // Make sure to turn off Force Rage and Force Absorb.
- if (self->client->ps.fd.forcePowersActive & (1 << FP_RAGE) )
- {
- WP_ForcePowerStop( self, FP_RAGE );
- }
- if (self->client->ps.fd.forcePowersActive & (1 << FP_ABSORB) )
- {
- WP_ForcePowerStop( self, FP_ABSORB );
- }
- self->client->ps.forceAllowDeactivateTime = level.time + 1500;
- WP_ForcePowerStart( self, FP_PROTECT, 0 );
- G_PreDefSound(self->client->ps.origin, PDSOUND_PROTECT);
- G_Sound( self, TRACK_CHANNEL_3, protectLoopSound );
- }
- void ForceAbsorb( gentity_t *self )
- {
- if ( self->health <= 0 )
- {
- return;
- }
- if (self->client->ps.forceAllowDeactivateTime < level.time &&
- (self->client->ps.fd.forcePowersActive & (1 << FP_ABSORB)) )
- {
- WP_ForcePowerStop( self, FP_ABSORB );
- return;
- }
- if ( !WP_ForcePowerUsable( self, FP_ABSORB ) )
- {
- return;
- }
- // Make sure to turn off Force Rage and Force Protection.
- if (self->client->ps.fd.forcePowersActive & (1 << FP_RAGE) )
- {
- WP_ForcePowerStop( self, FP_RAGE );
- }
- if (self->client->ps.fd.forcePowersActive & (1 << FP_PROTECT) )
- {
- WP_ForcePowerStop( self, FP_PROTECT );
- }
- self->client->ps.forceAllowDeactivateTime = level.time + 1500;
- WP_ForcePowerStart( self, FP_ABSORB, 0 );
- G_PreDefSound(self->client->ps.origin, PDSOUND_ABSORB);
- G_Sound( self, TRACK_CHANNEL_3, absorbLoopSound );
- }
- void ForceRage( gentity_t *self )
- {
- if ( self->health <= 0 )
- {
- return;
- }
- if (self->client->ps.forceAllowDeactivateTime < level.time &&
- (self->client->ps.fd.forcePowersActive & (1 << FP_RAGE)) )
- {
- WP_ForcePowerStop( self, FP_RAGE );
- return;
- }
- if ( !WP_ForcePowerUsable( self, FP_RAGE ) )
- {
- return;
- }
- if (self->client->ps.fd.forceRageRecoveryTime >= level.time)
- {
- return;
- }
- if (self->health < 10)
- {
- return;
- }
- // Make sure to turn off Force Protection and Force Absorb.
- if (self->client->ps.fd.forcePowersActive & (1 << FP_PROTECT) )
- {
- WP_ForcePowerStop( self, FP_PROTECT );
- }
- if (self->client->ps.fd.forcePowersActive & (1 << FP_ABSORB) )
- {
- WP_ForcePowerStop( self, FP_ABSORB );
- }
- self->client->ps.forceAllowDeactivateTime = level.time + 1500;
- WP_ForcePowerStart( self, FP_RAGE, 0 );
- G_Sound( self, TRACK_CHANNEL_4, G_SoundIndex("sound/weapons/force/rage.wav") );
- G_Sound( self, TRACK_CHANNEL_3, rageLoopSound );
- }
- void ForceLightning( gentity_t *self )
- {
- if ( self->health <= 0 )
- {
- return;
- }
- if ( self->client->ps.fd.forcePower < 25 || !WP_ForcePowerUsable( self, FP_LIGHTNING ) )
- {
- return;
- }
- if ( self->client->ps.fd.forcePowerDebounce[FP_LIGHTNING] > level.time )
- {//stops it while using it and also after using it, up to 3 second delay
- return;
- }
- if (self->client->ps.forceHandExtend != HANDEXTEND_NONE)
- {
- return;
- }
- if (self->client->ps.weaponTime > 0)
- {
- return;
- }
- //Shoot lightning from hand
- //using grip anim now, to extend the burst time
- self->client->ps.forceHandExtend = HANDEXTEND_FORCE_HOLD;
- self->client->ps.forceHandExtendTime = level.time + 20000;
- G_Sound( self, CHAN_BODY, G_SoundIndex("sound/weapons/force/lightning") );
-
- WP_ForcePowerStart( self, FP_LIGHTNING, 500 );
- }
- void ForceLightningDamage( gentity_t *self, gentity_t *traceEnt, vec3_t dir, vec3_t impactPoint )
- {
- self->client->dangerTime = level.time;
- self->client->ps.eFlags &= ~EF_INVULNERABLE;
- self->client->invulnerableTimer = 0;
- if ( traceEnt && traceEnt->takedamage )
- {
- if (!traceEnt->client && traceEnt->s.eType == ET_NPC)
- { //g2animent
- if (traceEnt->s.genericenemyindex < level.time)
- {
- traceEnt->s.genericenemyindex = level.time + 2000;
- }
- }
- if ( traceEnt->client )
- {//an enemy or object
- if (traceEnt->client->noLightningTime >= level.time)
- { //give them power and don't hurt them.
- traceEnt->client->ps.fd.forcePower++;
- if (traceEnt->client->ps.fd.forcePower > 100)
- {
- traceEnt->client->ps.fd.forcePower = 100;
- }
- return;
- }
- if (ForcePowerUsableOn(self, traceEnt, FP_LIGHTNING))
- {
- int dmg = Q_irand(1,2); //Q_irand( 1, 3 );
-
- int modPowerLevel = -1;
-
- if (traceEnt->client)
- {
- modPowerLevel = WP_AbsorbConversion(traceEnt, traceEnt->client->ps.fd.forcePowerLevel[FP_ABSORB], self, FP_LIGHTNING, self->client->ps.fd.forcePowerLevel[FP_LIGHTNING], 1);
- }
- if (modPowerLevel != -1)
- {
- if (!modPowerLevel)
- {
- dmg = 0;
- traceEnt->client->noLightningTime = level.time + 400;
- }
- else if (modPowerLevel == 1)
- {
- dmg = 1;
- traceEnt->client->noLightningTime = level.time + 300;
- }
- else if (modPowerLevel == 2)
- {
- dmg = 1;
- traceEnt->client->noLightningTime = level.time + 100;
- }
- }
- if ( self->client->ps.weapon == WP_MELEE
- && self->client->ps.fd.forcePowerLevel[FP_LIGHTNING] > FORCE_LEVEL_2 )
- {//2-handed lightning
- //jackin' 'em up, Palpatine-style
- dmg *= 2;
- }
- if (dmg)
- {
- //rww - Shields can now absorb lightning too.
- G_Damage( traceEnt, self, self, dir, impactPoint, dmg, 0, MOD_FORCE_DARK );
- }
- if ( traceEnt->client )
- {
- if ( !Q_irand( 0, 2 ) )
- {
- G_Sound( traceEnt, CHAN_BODY, G_SoundIndex( va("sound/weapons/force/lightninghit%i", Q_irand(1, 3) )) );
- }
- if (traceEnt->client->ps.electrifyTime < (level.time + 400))
- { //only update every 400ms to reduce bandwidth usage (as it is passing a 32-bit time value)
- traceEnt->client->ps.electrifyTime = level.time + 800;
- }
- if ( traceEnt->client->ps.powerups[PW_CLOAKED] )
- {//disable cloak temporarily
- Jedi_Decloak( traceEnt );
- traceEnt->client->cloakToggleTime = level.time + Q_irand( 3000, 10000 );
- }
- }
- }
- }
- }
- }
- void ForceShootLightning( gentity_t *self )
- {
- trace_t tr;
- vec3_t end, forward;
- gentity_t *traceEnt;
- if ( self->health <= 0 )
- {
- return;
- }
- AngleVectors( self->client->ps.viewangles, forward, NULL, NULL );
- VectorNormalize( forward );
- if ( self->client->ps.fd.forcePowerLevel[FP_LIGHTNING] > FORCE_LEVEL_2 )
- {//arc
- vec3_t center, mins, maxs, dir, ent_org, size, v;
- float radius = FORCE_LIGHTNING_RADIUS, dot, dist;
- gentity_t *entityList[MAX_GENTITIES];
- int iEntityList[MAX_GENTITIES];
- int e, numListedEntities, i;
- VectorCopy( self->client->ps.origin, center );
- for ( i = 0 ; i < 3 ; i++ )
- {
- mins[i] = center[i] - radius;
- maxs[i] = center[i] + radius;
- }
- numListedEntities = trap_EntitiesInBox( mins, maxs, iEntityList, MAX_GENTITIES );
- i = 0;
- while (i < numListedEntities)
- {
- entityList[i] = &g_entities[iEntityList[i]];
- i++;
- }
- for ( e = 0 ; e < numListedEntities ; e++ )
- {
- traceEnt = entityList[e];
- if ( !traceEnt )
- continue;
- if ( traceEnt == self )
- continue;
- if ( traceEnt->r.ownerNum == self->s.number && traceEnt->s.weapon != WP_THERMAL )//can push your own thermals
- continue;
- if ( !traceEnt->inuse )
- continue;
- if ( !traceEnt->takedamage )
- continue;
- if ( traceEnt->health <= 0 )//no torturing corpses
- continue;
- if ( !g_friendlyFire.integer && OnSameTeam(self, traceEnt))
- continue;
- //this is all to see if we need to start a saber attack, if it's in flight, this doesn't matter
- // find the distance from the edge of the bounding box
- for ( i = 0 ; i < 3 ; i++ )
- {
- if ( center[i] < traceEnt->r.absmin[i] )
- {
- v[i] = traceEnt->r.absmin[i] - center[i];
- } else if ( center[i] > traceEnt->r.absmax[i] )
- {
- v[i] = center[i] - traceEnt->r.absmax[i];
- } else
- {
- v[i] = 0;
- }
- }
- VectorSubtract( traceEnt->r.absmax, traceEnt->r.absmin, size );
- VectorMA( traceEnt->r.absmin, 0.5, size, ent_org );
- //see if they're in front of me
- //must be within the forward cone
- VectorSubtract( ent_org, center, dir );
- VectorNormalize( dir );
- if ( (dot = DotProduct( dir, forward )) < 0.5 )
- continue;
- //must be close enough
- dist = VectorLength( v );
- if ( dist >= radius )
- {
- continue;
- }
-
- //in PVS?
- if ( !traceEnt->r.bmodel && !trap_InPVS( ent_org, self->client->ps.origin ) )
- {//must be in PVS
- continue;
- }
- //Now check and see if we can actually hit it
- trap_Trace( &tr, self->client->ps.origin, vec3_origin, vec3_origin, ent_org, self->s.number, MASK_SHOT );
- if ( tr.fraction < 1.0f && tr.entityNum != traceEnt->s.number )
- {//must have clear LOS
- continue;
- }
- // ok, we are within the radius, add us to the incoming list
- ForceLightningDamage( self, traceEnt, dir, ent_org );
- }
- }
- else
- {//trace-line
- VectorMA( self->client->ps.origin, 2048, forward, end );
-
- trap_Trace( &tr, self->client->ps.origin, vec3_origin, vec3_origin, end, self->s.number, MASK_SHOT );
- if ( tr.entityNum == ENTITYNUM_NONE || tr.fraction == 1.0 || tr.allsolid || tr.startsolid )
- {
- return;
- }
-
- traceEnt = &g_entities[tr.entityNum];
- ForceLightningDamage( self, traceEnt, forward, tr.endpos );
- }
- }
- void ForceDrain( gentity_t *self )
- {
- if ( self->health <= 0 )
- {
- return;
- }
- if (self->client->ps.forceHandExtend != HANDEXTEND_NONE)
- {
- return;
- }
- if (self->client->ps.weaponTime > 0)
- {
- return;
- }
- if ( self->client->ps.fd.forcePower < 25 || !WP_ForcePowerUsable( self, FP_DRAIN ) )
- {
- return;
- }
- if ( self->client->ps.fd.forcePowerDebounce[FP_DRAIN] > level.time )
- {//stops it while using it and also after using it, up to 3 second delay
- return;
- }
- // self->client->ps.forceHandExtend = HANDEXTEND_FORCEPUSH;
- // self->client->ps.forceHandExtendTime = level.time + 1000;
- self->client->ps.forceHandExtend = HANDEXTEND_FORCE_HOLD;
- self->client->ps.forceHandExtendTime = level.time + 20000;
- G_Sound( self, CHAN_BODY, G_SoundIndex("sound/weapons/force/drain.wav") );
-
- WP_ForcePowerStart( self, FP_DRAIN, 500 );
- }
- void ForceDrainDamage( gentity_t *self, gentity_t *traceEnt, vec3_t dir, vec3_t impactPoint )
- {
- gentity_t *tent;
- self->client->dangerTime = level.time;
- self->client->ps.eFlags &= ~EF_INVULNERABLE;
- self->client->invulnerableTimer = 0;
- if ( traceEnt && traceEnt->takedamage )
- {
- if ( traceEnt->client && (!OnSameTeam(self, tra…
Large files files are truncated, but you can click here to view the full file