00001
00002 #include "b_local.h"
00003 #include "w_saber.h"
00004 #include "ai_main.h"
00005 #include "../ghoul2/G2.h"
00006
00007 #define METROID_JUMP 1
00008
00009
00010 extern void NPC_PlayConfusionSound( gentity_t *self );
00011 extern void NPC_Jedi_PlayConfusionSound( gentity_t *self );
00012 extern void NPC_UseResponse( gentity_t *self, gentity_t *user, qboolean useWhenDone );
00013
00014 extern void Jedi_Decloak( gentity_t *self );
00015
00016 extern vmCvar_t g_saberRestrictForce;
00017
00018 #include "../namespace_begin.h"
00019 extern qboolean BG_FullBodyTauntAnim( int anim );
00020 #include "../namespace_end.h"
00021
00022 extern bot_state_t *botstates[MAX_CLIENTS];
00023
00024 int speedLoopSound = 0;
00025
00026 int rageLoopSound = 0;
00027
00028 int protectLoopSound = 0;
00029
00030 int absorbLoopSound = 0;
00031
00032 int seeLoopSound = 0;
00033
00034 int ysalamiriLoopSound = 0;
00035
00036 #define FORCE_VELOCITY_DAMAGE 0
00037
00038 int ForceShootDrain( gentity_t *self );
00039
00040 gentity_t *G_PreDefSound(vec3_t org, int pdSound)
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 }
00050
00051 const int forcePowerMinRank[NUM_FORCE_POWER_LEVELS][NUM_FORCE_POWERS] =
00052 {
00053 {
00054 999,
00055 999,
00056 999,
00057 999,
00058 999,
00059 999,
00060 999,
00061 999,
00062 999,
00063 999,
00064 999,
00065 999,
00066 999,
00067 999,
00068 999,
00069 999,
00070 999,
00071 999
00072
00073 },
00074 {
00075 10,
00076 0,
00077 0,
00078 0,
00079 0,
00080 10,
00081 15,
00082 10,
00083 15,
00084 15,
00085 15,
00086 10,
00087 10,
00088 10,
00089 5,
00090 0,
00091 0,
00092 0
00093
00094 },
00095 {
00096 10,
00097 0,
00098 0,
00099 0,
00100 0,
00101 10,
00102 15,
00103 10,
00104 15,
00105 15,
00106 15,
00107 10,
00108 10,
00109 10,
00110 5,
00111 5,
00112 5,
00113 5
00114
00115 },
00116 {
00117 10,
00118 0,
00119 0,
00120 0,
00121 0,
00122 10,
00123 15,
00124 10,
00125 15,
00126 15,
00127 15,
00128 10,
00129 10,
00130 10,
00131 5,
00132 10,
00133 10,
00134 10
00135
00136 }
00137 };
00138
00139 const int mindTrickTime[NUM_FORCE_POWER_LEVELS] =
00140 {
00141 0,
00142 5000,
00143 10000,
00144 15000
00145 };
00146
00147 void WP_InitForcePowers( gentity_t *ent )
00148 {
00149 int i;
00150 int i_r;
00151 int maxRank = g_maxForceRank.integer;
00152 qboolean warnClient = qfalse;
00153 qboolean warnClientLimit = qfalse;
00154 char userinfo[MAX_INFO_STRING];
00155 char forcePowers[256];
00156 char readBuf[256];
00157 int lastFPKnown = -1;
00158 qboolean didEvent = qfalse;
00159
00160 if (!maxRank)
00161 {
00162 maxRank = FORCE_MASTERY_JEDI_MASTER;
00163 }
00164 else if (maxRank >= NUM_FORCE_MASTERY_LEVELS)
00165 {
00166 maxRank = FORCE_MASTERY_JEDI_MASTER;
00167 trap_Cvar_Set( "g_maxForceRank", va("%i", maxRank) );
00168 }
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178 if ( !ent || !ent->client )
00179 {
00180 return;
00181 }
00182
00183 ent->client->ps.fd.saberAnimLevel = ent->client->sess.saberLevel;
00184
00185 if (ent->client->ps.fd.saberAnimLevel < FORCE_LEVEL_1 ||
00186 ent->client->ps.fd.saberAnimLevel > FORCE_LEVEL_3)
00187 {
00188 ent->client->ps.fd.saberAnimLevel = FORCE_LEVEL_1;
00189 }
00190
00191 if (!speedLoopSound)
00192 {
00193 speedLoopSound = G_SoundIndex("sound/weapons/force/speedloop.wav");
00194 }
00195
00196 if (!rageLoopSound)
00197 {
00198 rageLoopSound = G_SoundIndex("sound/weapons/force/rageloop.wav");
00199 }
00200
00201 if (!absorbLoopSound)
00202 {
00203 absorbLoopSound = G_SoundIndex("sound/weapons/force/absorbloop.wav");
00204 }
00205
00206 if (!protectLoopSound)
00207 {
00208 protectLoopSound = G_SoundIndex("sound/weapons/force/protectloop.wav");
00209 }
00210
00211 if (!seeLoopSound)
00212 {
00213 seeLoopSound = G_SoundIndex("sound/weapons/force/seeloop.wav");
00214 }
00215
00216 if (!ysalamiriLoopSound)
00217 {
00218 ysalamiriLoopSound = G_SoundIndex("sound/player/nullifyloop.wav");
00219 }
00220
00221 if (ent->s.eType == ET_NPC)
00222 {
00223 return;
00224 }
00225
00226 i = 0;
00227 while (i < NUM_FORCE_POWERS)
00228 {
00229 ent->client->ps.fd.forcePowerLevel[i] = 0;
00230 ent->client->ps.fd.forcePowersKnown &= ~(1 << i);
00231 i++;
00232 }
00233
00234 ent->client->ps.fd.forcePowerSelected = -1;
00235
00236 ent->client->ps.fd.forceSide = 0;
00237
00238 if (g_gametype.integer == GT_SIEGE &&
00239 ent->client->siegeClass != -1)
00240 {
00241 i = 0;
00242
00243 while (i < NUM_FORCE_POWERS)
00244 {
00245 ent->client->ps.fd.forcePowerLevel[i] = bgSiegeClasses[ent->client->siegeClass].forcePowerLevels[i];
00246
00247 if (!ent->client->ps.fd.forcePowerLevel[i])
00248 {
00249 ent->client->ps.fd.forcePowersKnown &= ~(1 << i);
00250 }
00251 else
00252 {
00253 ent->client->ps.fd.forcePowersKnown |= (1 << i);
00254 }
00255 i++;
00256 }
00257
00258 if (!ent->client->sess.setForce)
00259 {
00260
00261 trap_SendServerCommand(ent-g_entities, "scl");
00262 }
00263 ent->client->sess.setForce = qtrue;
00264
00265 return;
00266 }
00267
00268 if (ent->s.eType == ET_NPC && ent->s.number >= MAX_CLIENTS)
00269 {
00270 strcpy(userinfo, "forcepowers\\7-1-333003000313003120");
00271 }
00272 else
00273 {
00274 trap_GetUserinfo( ent->s.number, userinfo, sizeof( userinfo ) );
00275 }
00276
00277 Q_strncpyz( forcePowers, Info_ValueForKey (userinfo, "forcepowers"), sizeof( forcePowers ) );
00278
00279 if ( (ent->r.svFlags & SVF_BOT) && botstates[ent->s.number] )
00280 {
00281 Com_sprintf(forcePowers, sizeof(forcePowers), "%s\0", botstates[ent->s.number]->forceinfo);
00282 }
00283
00284
00285 i = 0;
00286
00287 if (g_forceBasedTeams.integer)
00288 {
00289 if (ent->client->sess.sessionTeam == TEAM_RED)
00290 {
00291 warnClient = !(BG_LegalizedForcePowers(forcePowers, maxRank, HasSetSaberOnly(), FORCE_DARKSIDE, g_gametype.integer, g_forcePowerDisable.integer));
00292 }
00293 else if (ent->client->sess.sessionTeam == TEAM_BLUE)
00294 {
00295 warnClient = !(BG_LegalizedForcePowers(forcePowers, maxRank, HasSetSaberOnly(), FORCE_LIGHTSIDE, g_gametype.integer, g_forcePowerDisable.integer));
00296 }
00297 else
00298 {
00299 warnClient = !(BG_LegalizedForcePowers(forcePowers, maxRank, HasSetSaberOnly(), 0, g_gametype.integer, g_forcePowerDisable.integer));
00300 }
00301 }
00302 else
00303 {
00304 warnClient = !(BG_LegalizedForcePowers(forcePowers, maxRank, HasSetSaberOnly(), 0, g_gametype.integer, g_forcePowerDisable.integer));
00305 }
00306
00307 i_r = 0;
00308 while (forcePowers[i] && forcePowers[i] != '-')
00309 {
00310 readBuf[i_r] = forcePowers[i];
00311 i_r++;
00312 i++;
00313 }
00314 readBuf[i_r] = 0;
00315
00316 ent->client->ps.fd.forceRank = atoi(readBuf);
00317 i++;
00318
00319 i_r = 0;
00320 while (forcePowers[i] && forcePowers[i] != '-')
00321 {
00322 readBuf[i_r] = forcePowers[i];
00323 i_r++;
00324 i++;
00325 }
00326 readBuf[i_r] = 0;
00327
00328 ent->client->ps.fd.forceSide = atoi(readBuf);
00329 i++;
00330
00331
00332 if ( g_gametype.integer != GT_SIEGE && (ent->r.svFlags & SVF_BOT) && botstates[ent->s.number] )
00333 {
00334 int oldI = i;
00335 i_r = 0;
00336 while (forcePowers[i] && forcePowers[i] != '\n' &&
00337 i_r < NUM_FORCE_POWERS)
00338 {
00339 if (ent->client->ps.fd.forceSide == FORCE_LIGHTSIDE)
00340 {
00341 if (i_r == FP_ABSORB)
00342 {
00343 forcePowers[i] = '3';
00344 }
00345 if (botstates[ent->s.number]->settings.skill >= 4)
00346 {
00347 if (i_r == FP_HEAL)
00348 {
00349 forcePowers[i] = '3';
00350 }
00351 else if (i_r == FP_PROTECT)
00352 {
00353 forcePowers[i] = '3';
00354 }
00355 }
00356 }
00357 else if (ent->client->ps.fd.forceSide == FORCE_DARKSIDE)
00358 {
00359 if (botstates[ent->s.number]->settings.skill >= 4)
00360 {
00361 if (i_r == FP_GRIP)
00362 {
00363 forcePowers[i] = '3';
00364 }
00365 else if (i_r == FP_LIGHTNING)
00366 {
00367 forcePowers[i] = '3';
00368 }
00369 else if (i_r == FP_RAGE)
00370 {
00371 forcePowers[i] = '3';
00372 }
00373 else if (i_r == FP_DRAIN)
00374 {
00375 forcePowers[i] = '3';
00376 }
00377 }
00378 }
00379
00380 if (i_r == FP_PUSH)
00381 {
00382 forcePowers[i] = '3';
00383 }
00384 else if (i_r == FP_PULL)
00385 {
00386 forcePowers[i] = '3';
00387 }
00388
00389 i++;
00390 i_r++;
00391 }
00392 i = oldI;
00393 }
00394
00395 i_r = 0;
00396 while (forcePowers[i] && forcePowers[i] != '\n' &&
00397 i_r < NUM_FORCE_POWERS)
00398 {
00399 readBuf[0] = forcePowers[i];
00400 readBuf[1] = 0;
00401
00402 ent->client->ps.fd.forcePowerLevel[i_r] = atoi(readBuf);
00403 if (ent->client->ps.fd.forcePowerLevel[i_r])
00404 {
00405 ent->client->ps.fd.forcePowersKnown |= (1 << i_r);
00406 }
00407 else
00408 {
00409 ent->client->ps.fd.forcePowersKnown &= ~(1 << i_r);
00410 }
00411 i++;
00412 i_r++;
00413 }
00414
00415
00416 if (ent->s.eType != ET_NPC)
00417 {
00418 if (HasSetSaberOnly())
00419 {
00420 gentity_t *te = G_TempEntity( vec3_origin, EV_SET_FREE_SABER );
00421 te->r.svFlags |= SVF_BROADCAST;
00422 te->s.eventParm = 1;
00423 }
00424 else
00425 {
00426 gentity_t *te = G_TempEntity( vec3_origin, EV_SET_FREE_SABER );
00427 te->r.svFlags |= SVF_BROADCAST;
00428 te->s.eventParm = 0;
00429 }
00430
00431 if (g_forcePowerDisable.integer)
00432 {
00433 gentity_t *te = G_TempEntity( vec3_origin, EV_SET_FORCE_DISABLE );
00434 te->r.svFlags |= SVF_BROADCAST;
00435 te->s.eventParm = 1;
00436 }
00437 else
00438 {
00439 gentity_t *te = G_TempEntity( vec3_origin, EV_SET_FORCE_DISABLE );
00440 te->r.svFlags |= SVF_BROADCAST;
00441 te->s.eventParm = 0;
00442 }
00443 }
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453 if (ent->s.eType == ET_NPC)
00454 {
00455 ent->client->sess.setForce = qtrue;
00456 }
00457 else if (g_gametype.integer == GT_SIEGE)
00458 {
00459 if (!ent->client->sess.setForce)
00460 {
00461 ent->client->sess.setForce = qtrue;
00462
00463 trap_SendServerCommand(ent-g_entities, "scl");
00464 }
00465 }
00466 else
00467 {
00468 if (warnClient || !ent->client->sess.setForce)
00469 {
00470 if (g_gametype.integer != GT_HOLOCRON && g_gametype.integer != GT_JEDIMASTER )
00471 {
00472 #ifdef EVENT_FORCE_RANK
00473 gentity_t *te = G_TempEntity( vec3_origin, EV_GIVE_NEW_RANK );
00474
00475 te->r.svFlags |= SVF_BROADCAST;
00476 te->s.trickedentindex = ent->s.number;
00477 te->s.eventParm = maxRank;
00478 te->s.bolt1 = 0;
00479 #endif
00480 didEvent = qtrue;
00481
00482
00483 if (!(ent->r.svFlags & SVF_BOT) && ent->s.eType != ET_NPC)
00484 {
00485 if (!g_teamAutoJoin.integer)
00486 {
00487
00488 ent->client->sess.sessionTeam = TEAM_SPECTATOR;
00489 ent->client->sess.spectatorState = SPECTATOR_FREE;
00490 ent->client->sess.spectatorClient = 0;
00491
00492 ent->client->pers.teamState.state = TEAM_BEGIN;
00493 trap_SendServerCommand(ent-g_entities, "spc");
00494 }
00495 }
00496
00497 #ifdef EVENT_FORCE_RANK
00498 te->s.bolt2 = ent->client->sess.sessionTeam;
00499 #else
00500
00501
00502 trap_SendServerCommand(ent->s.number, va("nfr %i %i %i", maxRank, 1, ent->client->sess.sessionTeam));
00503
00504 #endif
00505 }
00506 ent->client->sess.setForce = qtrue;
00507 }
00508
00509 if (!didEvent )
00510 {
00511 #ifdef EVENT_FORCE_RANK
00512 gentity_t *te = G_TempEntity( vec3_origin, EV_GIVE_NEW_RANK );
00513
00514 te->r.svFlags |= SVF_BROADCAST;
00515 te->s.trickedentindex = ent->s.number;
00516 te->s.eventParm = maxRank;
00517 te->s.bolt1 = 1;
00518 te->s.bolt2 = ent->client->sess.sessionTeam;
00519 #else
00520 trap_SendServerCommand(ent->s.number, va("nfr %i %i %i", maxRank, 0, ent->client->sess.sessionTeam));
00521 #endif
00522 }
00523
00524 if (warnClientLimit)
00525 {
00526
00527 }
00528 }
00529
00530 i = 0;
00531 while (i < NUM_FORCE_POWERS)
00532 {
00533 if ((ent->client->ps.fd.forcePowersKnown & (1 << i)) &&
00534 !ent->client->ps.fd.forcePowerLevel[i])
00535 {
00536 ent->client->ps.fd.forcePowersKnown &= ~(1 << i);
00537 }
00538 else
00539 {
00540 if (i != FP_LEVITATION && i != FP_SABER_OFFENSE && i != FP_SABER_DEFENSE && i != FP_SABERTHROW)
00541 {
00542 lastFPKnown = i;
00543 }
00544 }
00545
00546 i++;
00547 }
00548
00549 if (ent->client->ps.fd.forcePowersKnown & ent->client->sess.selectedFP)
00550 {
00551 ent->client->ps.fd.forcePowerSelected = ent->client->sess.selectedFP;
00552 }
00553
00554 if (!(ent->client->ps.fd.forcePowersKnown & (1 << ent->client->ps.fd.forcePowerSelected)))
00555 {
00556 if (lastFPKnown != -1)
00557 {
00558 ent->client->ps.fd.forcePowerSelected = lastFPKnown;
00559 }
00560 else
00561 {
00562 ent->client->ps.fd.forcePowerSelected = 0;
00563 }
00564 }
00565
00566 while (i < NUM_FORCE_POWERS)
00567 {
00568 ent->client->ps.fd.forcePowerBaseLevel[i] = ent->client->ps.fd.forcePowerLevel[i];
00569 i++;
00570 }
00571 ent->client->ps.fd.forceUsingAdded = 0;
00572 }
00573
00574 void WP_SpawnInitForcePowers( gentity_t *ent )
00575 {
00576 int i = 0;
00577
00578 ent->client->ps.saberAttackChainCount = 0;
00579
00580 i = 0;
00581
00582 while (i < NUM_FORCE_POWERS)
00583 {
00584 if (ent->client->ps.fd.forcePowersActive & (1 << i))
00585 {
00586 WP_ForcePowerStop(ent, i);
00587 }
00588
00589 i++;
00590 }
00591
00592 ent->client->ps.fd.forceDeactivateAll = 0;
00593
00594 ent->client->ps.fd.forcePower = ent->client->ps.fd.forcePowerMax = FORCE_POWER_MAX;
00595 ent->client->ps.fd.forcePowerRegenDebounceTime = 0;
00596 ent->client->ps.fd.forceGripEntityNum = ENTITYNUM_NONE;
00597 ent->client->ps.fd.forceMindtrickTargetIndex = 0;
00598 ent->client->ps.fd.forceMindtrickTargetIndex2 = 0;
00599 ent->client->ps.fd.forceMindtrickTargetIndex3 = 0;
00600 ent->client->ps.fd.forceMindtrickTargetIndex4 = 0;
00601
00602 ent->client->ps.holocronBits = 0;
00603
00604 i = 0;
00605 while (i < NUM_FORCE_POWERS)
00606 {
00607 ent->client->ps.holocronsCarried[i] = 0;
00608 i++;
00609 }
00610
00611 if (g_gametype.integer == GT_HOLOCRON)
00612 {
00613 i = 0;
00614 while (i < NUM_FORCE_POWERS)
00615 {
00616 ent->client->ps.fd.forcePowerLevel[i] = FORCE_LEVEL_0;
00617 i++;
00618 }
00619
00620 if (HasSetSaberOnly())
00621 {
00622 if (ent->client->ps.fd.forcePowerLevel[FP_SABER_OFFENSE] < FORCE_LEVEL_1)
00623 {
00624 ent->client->ps.fd.forcePowerLevel[FP_SABER_OFFENSE] = FORCE_LEVEL_1;
00625 }
00626 if (ent->client->ps.fd.forcePowerLevel[FP_SABER_DEFENSE] < FORCE_LEVEL_1)
00627 {
00628 ent->client->ps.fd.forcePowerLevel[FP_SABER_DEFENSE] = FORCE_LEVEL_1;
00629 }
00630 }
00631 }
00632
00633 i = 0;
00634
00635 while (i < NUM_FORCE_POWERS)
00636 {
00637 ent->client->ps.fd.forcePowerDebounce[i] = 0;
00638 ent->client->ps.fd.forcePowerDuration[i] = 0;
00639
00640 i++;
00641 }
00642
00643 ent->client->ps.fd.forcePowerRegenDebounceTime = 0;
00644 ent->client->ps.fd.forceJumpZStart = 0;
00645 ent->client->ps.fd.forceJumpCharge = 0;
00646 ent->client->ps.fd.forceJumpSound = 0;
00647 ent->client->ps.fd.forceGripDamageDebounceTime = 0;
00648 ent->client->ps.fd.forceGripBeingGripped = 0;
00649 ent->client->ps.fd.forceGripCripple = 0;
00650 ent->client->ps.fd.forceGripUseTime = 0;
00651 ent->client->ps.fd.forceGripSoundTime = 0;
00652 ent->client->ps.fd.forceGripStarted = 0;
00653 ent->client->ps.fd.forceHealTime = 0;
00654 ent->client->ps.fd.forceHealAmount = 0;
00655 ent->client->ps.fd.forceRageRecoveryTime = 0;
00656 ent->client->ps.fd.forceDrainEntNum = ENTITYNUM_NONE;
00657 ent->client->ps.fd.forceDrainTime = 0;
00658
00659 i = 0;
00660 while (i < NUM_FORCE_POWERS)
00661 {
00662 if ((ent->client->ps.fd.forcePowersKnown & (1 << i)) &&
00663 !ent->client->ps.fd.forcePowerLevel[i])
00664 {
00665 ent->client->ps.fd.forcePowersKnown &= ~(1 << i);
00666 }
00667
00668 i++;
00669 }
00670
00671 if (g_gametype.integer == GT_SIEGE &&
00672 ent->client->siegeClass != -1)
00673 {
00674 i = 0;
00675
00676 while (i < NUM_FORCE_POWERS)
00677 {
00678 ent->client->ps.fd.forcePowerLevel[i] = bgSiegeClasses[ent->client->siegeClass].forcePowerLevels[i];
00679
00680 if (!ent->client->ps.fd.forcePowerLevel[i])
00681 {
00682 ent->client->ps.fd.forcePowersKnown &= ~(1 << i);
00683 }
00684 else
00685 {
00686 ent->client->ps.fd.forcePowersKnown |= (1 << i);
00687 }
00688 i++;
00689 }
00690 }
00691 }
00692
00693 #include "../namespace_begin.h"
00694 extern qboolean BG_InKnockDown( int anim );
00695 #include "../namespace_end.h"
00696
00697 int ForcePowerUsableOn(gentity_t *attacker, gentity_t *other, forcePowers_t forcePower)
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
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 {
00725
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 {
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 {
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 {
00768 return 0;
00769 }
00770
00771 return 1;
00772 }
00773
00774 qboolean WP_ForcePowerAvailable( gentity_t *self, forcePowers_t forcePower, int overrideAmt )
00775 {
00776 int drain = overrideAmt ? overrideAmt :
00777 forcePowerNeeded[self->client->ps.fd.forcePowerLevel[forcePower]][forcePower];
00778
00779 if (self->client->ps.fd.forcePowersActive & (1 << forcePower))
00780 {
00781 return qtrue;
00782 }
00783 if ( forcePower == FP_LEVITATION )
00784 {
00785 return qtrue;
00786 }
00787 if ( !drain )
00788 {
00789 return qtrue;
00790 }
00791 if ((forcePower == FP_DRAIN || forcePower == FP_LIGHTNING) &&
00792 self->client->ps.fd.forcePower >= 25)
00793 {
00794 return qtrue;
00795 }
00796 if ( self->client->ps.fd.forcePower < drain )
00797 {
00798 return qfalse;
00799 }
00800 return qtrue;
00801 }
00802
00803 qboolean WP_ForcePowerInUse( gentity_t *self, forcePowers_t forcePower )
00804 {
00805 if ( (self->client->ps.fd.forcePowersActive & ( 1 << forcePower )) )
00806 {
00807 return qtrue;
00808 }
00809
00810 return qfalse;
00811 }
00812
00813 qboolean WP_ForcePowerUsable( gentity_t *self, forcePowers_t forcePower )
00814 {
00815 if (BG_HasYsalamiri(g_gametype.integer, &self->client->ps))
00816 {
00817 return qfalse;
00818 }
00819
00820 if (self->health <= 0 || self->client->ps.stats[STAT_HEALTH] <= 0 ||
00821 (self->client->ps.eFlags & EF_DEAD))
00822 {
00823 return qfalse;
00824 }
00825
00826 if (self->client->ps.pm_flags & PMF_FOLLOW)
00827 {
00828 return qfalse;
00829 }
00830 if (self->client->sess.sessionTeam == TEAM_SPECTATOR)
00831 {
00832 return qfalse;
00833 }
00834 if (self->client->tempSpectate >= level.time)
00835 {
00836 return qfalse;
00837 }
00838
00839 if (!BG_CanUseFPNow(g_gametype.integer, &self->client->ps, level.time, forcePower))
00840 {
00841 return qfalse;
00842 }
00843
00844 if ( !(self->client->ps.fd.forcePowersKnown & ( 1 << forcePower )) )
00845 {
00846 return qfalse;
00847 }
00848
00849 if ( (self->client->ps.fd.forcePowersActive & ( 1 << forcePower )) )
00850 {
00851 if (forcePower != FP_LEVITATION)
00852 {
00853 return qfalse;
00854 }
00855 }
00856
00857 if (forcePower == FP_LEVITATION && self->client->fjDidJump)
00858 {
00859 return qfalse;
00860 }
00861
00862 if (!self->client->ps.fd.forcePowerLevel[forcePower])
00863 {
00864 return qfalse;
00865 }
00866
00867 if ( g_debugMelee.integer )
00868 {
00869 if ( (self->client->ps.pm_flags&PMF_STUCK_TO_WALL) )
00870 {
00871 switch ( forcePower )
00872 {
00873 case FP_GRIP:
00874 case FP_LIGHTNING:
00875 case FP_DRAIN:
00876 case FP_SABER_OFFENSE:
00877 case FP_SABER_DEFENSE:
00878 case FP_SABERTHROW:
00879 return qfalse;
00880 break;
00881 }
00882 }
00883 }
00884
00885 if ( !self->client->ps.saberHolstered )
00886 {
00887 if ( (self->client->saber[0].saberFlags&SFL_TWO_HANDED) )
00888 {
00889 if ( g_saberRestrictForce.integer )
00890 {
00891 switch ( forcePower )
00892 {
00893 case FP_PUSH:
00894 case FP_PULL:
00895 case FP_TELEPATHY:
00896 case FP_GRIP:
00897 case FP_LIGHTNING:
00898 case FP_DRAIN:
00899 return qfalse;
00900 break;
00901 }
00902 }
00903 }
00904
00905 if ( (self->client->saber[0].saberFlags&SFL_TWO_HANDED)
00906 || (self->client->saber[0].model && self->client->saber[0].model[0]) )
00907 {
00908 if ( (self->client->saber[0].forceRestrictions&(1<<forcePower)) )
00909 {
00910 return qfalse;
00911 }
00912 }
00913
00914 if ( self->client->saber[0].model
00915 && self->client->saber[0].model[0] )
00916 {
00917 if ( g_saberRestrictForce.integer )
00918 {
00919 switch ( forcePower )
00920 {
00921 case FP_PUSH:
00922 case FP_PULL:
00923 case FP_TELEPATHY:
00924 case FP_GRIP:
00925 case FP_LIGHTNING:
00926 case FP_DRAIN:
00927 return qfalse;
00928 break;
00929 }
00930 }
00931 if ( (self->client->saber[1].forceRestrictions&(1<<forcePower)) )
00932 {
00933 return qfalse;
00934 }
00935 }
00936 }
00937 return WP_ForcePowerAvailable( self, forcePower, 0 );
00938 }
00939
00940 int WP_AbsorbConversion(gentity_t *attacked, int atdAbsLevel, gentity_t *attacker, int atPower, int atPowerLevel, int atForceSpent)
00941 {
00942 int getLevel = 0;
00943 int addTot = 0;
00944 gentity_t *abSound;
00945
00946 if (atPower != FP_LIGHTNING &&
00947 atPower != FP_DRAIN &&
00948 atPower != FP_GRIP &&
00949 atPower != FP_PUSH &&
00950 atPower != FP_PULL)
00951 {
00952 return -1;
00953 }
00954
00955 if (!atdAbsLevel)
00956 {
00957 return -1;
00958 }
00959
00960 if (!(attacked->client->ps.fd.forcePowersActive & (1 << FP_ABSORB)))
00961 {
00962 return -1;
00963 }
00964
00965
00966 getLevel = atPowerLevel;
00967 getLevel -= atdAbsLevel;
00968
00969 if (getLevel < 0)
00970 {
00971 getLevel = 0;
00972 }
00973
00974
00975 addTot = (atForceSpent/3)*attacked->client->ps.fd.forcePowerLevel[FP_ABSORB];
00976
00977 if (addTot < 1 && atForceSpent >= 1)
00978 {
00979 addTot = 1;
00980 }
00981 attacked->client->ps.fd.forcePower += addTot;
00982 if (attacked->client->ps.fd.forcePower > 100)
00983 {
00984 attacked->client->ps.fd.forcePower = 100;
00985 }
00986
00987
00988 if (attacked->client->forcePowerSoundDebounce < level.time)
00989 {
00990 abSound = G_PreDefSound(attacked->client->ps.origin, PDSOUND_ABSORBHIT);
00991 abSound->s.trickedentindex = attacked->s.number;
00992
00993 attacked->client->forcePowerSoundDebounce = level.time + 400;
00994 }
00995
00996 return getLevel;
00997 }
00998
00999 void WP_ForcePowerRegenerate( gentity_t *self, int overrideAmt )
01000 {
01001 if ( !self->client )
01002 {
01003 return;
01004 }
01005
01006 if ( overrideAmt )
01007 {
01008 self->client->ps.fd.forcePower += overrideAmt;
01009 }
01010 else
01011 {
01012 self->client->ps.fd.forcePower++;
01013 }
01014
01015 if ( self->client->ps.fd.forcePower > self->client->ps.fd.forcePowerMax )
01016 {
01017 self->client->ps.fd.forcePower = self->client->ps.fd.forcePowerMax;
01018 }
01019 }
01020
01021 void WP_ForcePowerStart( gentity_t *self, forcePowers_t forcePower, int overrideAmt )
01022 {
01023 int duration = 0;
01024 qboolean hearable = qfalse;
01025 float hearDist = 0;
01026
01027 if (!WP_ForcePowerAvailable( self, forcePower, overrideAmt ))
01028 {
01029 return;
01030 }
01031
01032 if ( BG_FullBodyTauntAnim( self->client->ps.legsAnim ) )
01033 {
01034 self->client->ps.legsTimer = 0;
01035 }
01036 if ( BG_FullBodyTauntAnim( self->client->ps.torsoAnim ) )
01037 {
01038 self->client->ps.torsoTimer = 0;
01039 }
01040
01041
01042 switch( (int)forcePower )
01043 {
01044 case FP_HEAL:
01045 hearable = qtrue;
01046 hearDist = 256;
01047 self->client->ps.fd.forcePowersActive |= ( 1 << forcePower );
01048 break;
01049 case FP_LEVITATION:
01050 hearable = qtrue;
01051 hearDist = 256;
01052 self->client->ps.fd.forcePowersActive |= ( 1 << forcePower );
01053 break;
01054 case FP_SPEED:
01055 hearable = qtrue;
01056 hearDist = 256;
01057 if (self->client->ps.fd.forcePowerLevel[FP_SPEED] == FORCE_LEVEL_1)
01058 {
01059 duration = 10000;
01060 }
01061 else if (self->client->ps.fd.forcePowerLevel[FP_SPEED] == FORCE_LEVEL_2)
01062 {
01063 duration = 15000;
01064 }
01065 else if (self->client->ps.fd.forcePowerLevel[FP_SPEED] == FORCE_LEVEL_3)
01066 {
01067 duration = 20000;
01068 }
01069 else
01070 {
01071 break;
01072 }
01073
01074 if (overrideAmt)
01075 {
01076 duration = overrideAmt;
01077 }
01078
01079 self->client->ps.fd.forcePowersActive |= ( 1 << forcePower );
01080 break;
01081 case FP_PUSH:
01082 hearable = qtrue;
01083 hearDist = 256;
01084 break;
01085 case FP_PULL:
01086 hearable = qtrue;
01087 hearDist = 256;
01088 break;
01089 case FP_TELEPATHY:
01090 hearable = qtrue;
01091 hearDist = 256;
01092 if (self->client->ps.fd.forcePowerLevel[FP_TELEPATHY] == FORCE_LEVEL_1)
01093 {
01094 duration = 20000;
01095 }
01096 else if (self->client->ps.fd.forcePowerLevel[FP_TELEPATHY] == FORCE_LEVEL_2)
01097 {
01098 duration = 25000;
01099 }
01100 else if (self->client->ps.fd.forcePowerLevel[FP_TELEPATHY] == FORCE_LEVEL_3)
01101 {
01102 duration = 30000;
01103 }
01104 else
01105 {
01106 break;
01107 }
01108
01109 self->client->ps.fd.forcePowersActive |= ( 1 << forcePower );
01110 break;
01111 case FP_GRIP:
01112 hearable = qtrue;
01113 hearDist = 256;
01114 self->client->ps.fd.forcePowersActive |= ( 1 << forcePower );
01115 self->client->ps.powerups[PW_DISINT_4] = level.time + 60000;
01116 break;
01117 case FP_LIGHTNING:
01118 hearable = qtrue;
01119 hearDist = 512;
01120 duration = overrideAmt;
01121 overrideAmt = 0;
01122 self->client->ps.fd.forcePowersActive |= ( 1 << forcePower );
01123 self->client->ps.activeForcePass = self->client->ps.fd.forcePowerLevel[FP_LIGHTNING];
01124 break;
01125 case FP_RAGE:
01126 hearable = qtrue;
01127 hearDist = 256;
01128 if (self->client->ps.fd.forcePowerLevel[FP_RAGE] == FORCE_LEVEL_1)
01129 {
01130 duration = 8000;
01131 }
01132 else if (self->client->ps.fd.forcePowerLevel[FP_RAGE] == FORCE_LEVEL_2)
01133 {
01134 duration = 14000;
01135 }
01136 else if (self->client->ps.fd.forcePowerLevel[FP_RAGE] == FORCE_LEVEL_3)
01137 {
01138 duration = 20000;
01139 }
01140 else
01141 {
01142 break;
01143 }
01144
01145 self->client->ps.fd.forcePowersActive |= ( 1 << forcePower );
01146 break;
01147 case FP_PROTECT:
01148 hearable = qtrue;
01149 hearDist = 256;
01150 duration = 20000;
01151 self->client->ps.fd.forcePowersActive |= ( 1 << forcePower );
01152 break;
01153 case FP_ABSORB:
01154 hearable = qtrue;
01155 hearDist = 256;
01156 duration = 20000;
01157 self->client->ps.fd.forcePowersActive |= ( 1 << forcePower );
01158 break;
01159 case FP_TEAM_HEAL:
01160 hearable = qtrue;
01161 hearDist = 256;
01162 self->client->ps.fd.forcePowersActive |= ( 1 << forcePower );
01163 break;
01164 case FP_TEAM_FORCE:
01165 hearable = qtrue;
01166 hearDist = 256;
01167 self->client->ps.fd.forcePowersActive |= ( 1 << forcePower );
01168 break;
01169 case FP_DRAIN:
01170 hearable = qtrue;
01171 hearDist = 256;
01172 duration = overrideAmt;
01173 overrideAmt = 0;
01174 self->client->ps.fd.forcePowersActive |= ( 1 << forcePower );
01175
01176 break;
01177 case FP_SEE:
01178 hearable = qtrue;
01179 hearDist = 256;
01180 if (self->client->ps.fd.forcePowerLevel[FP_SEE] == FORCE_LEVEL_1)
01181 {
01182 duration = 10000;
01183 }
01184 else if (self->client->ps.fd.forcePowerLevel[FP_SEE] == FORCE_LEVEL_2)
01185 {
01186 duration = 20000;
01187 }
01188 else if (self->client->ps.fd.forcePowerLevel[FP_SEE] == FORCE_LEVEL_3)
01189 {
01190 duration = 30000;
01191 }
01192 else
01193 {
01194 break;
01195 }
01196
01197 self->client->ps.fd.forcePowersActive |= ( 1 << forcePower );
01198 break;
01199 case FP_SABER_OFFENSE:
01200 break;
01201 case FP_SABER_DEFENSE:
01202 break;
01203 case FP_SABERTHROW:
01204 break;
01205 default:
01206 break;
01207 }
01208
01209 if ( duration )
01210 {
01211 self->client->ps.fd.forcePowerDuration[forcePower] = level.time + duration;
01212 }
01213 else
01214 {
01215 self->client->ps.fd.forcePowerDuration[forcePower] = 0;
01216 }
01217
01218 if (hearable)
01219 {
01220 self->client->ps.otherSoundLen = hearDist;
01221 self->client->ps.otherSoundTime = level.time + 100;
01222 }
01223
01224 self->client->ps.fd.forcePowerDebounce[forcePower] = 0;
01225
01226 if ((int)forcePower == FP_SPEED && overrideAmt)
01227 {
01228 BG_ForcePowerDrain( &self->client->ps, forcePower, overrideAmt*0.025 );
01229 }
01230 else if ((int)forcePower != FP_GRIP && (int)forcePower != FP_DRAIN)
01231 {
01232 BG_ForcePowerDrain( &self->client->ps, forcePower, overrideAmt );
01233 }
01234 }
01235
01236 void ForceHeal( gentity_t *self )
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;
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
01285
01286
01287
01288
01289
01290
01291 G_Sound( self, CHAN_ITEM, G_SoundIndex("sound/weapons/force/heal.wav") );
01292 }
01293
01294 void WP_AddToClientBitflags(gentity_t *ent, int entNum)
01295 {
01296 if (!ent)
01297 {
01298 return;
01299 }
01300
01301 if (entNum > 47)
01302 {
01303 ent->s.trickedentindex4 |= (1 << (entNum-48));
01304 }
01305 else if (entNum > 31)
01306 {
01307 ent->s.trickedentindex3 |= (1 << (entNum-32));
01308 }
01309 else if (entNum > 15)
01310 {
01311 ent->s.trickedentindex2 |= (1 << (entNum-16));
01312 }
01313 else
01314 {
01315 ent->s.trickedentindex |= (1 << entNum);
01316 }
01317 }
01318
01319 void ForceTeamHeal( gentity_t *self )
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
01408 if (!te)
01409 {
01410 te = G_TempEntity( self->client->ps.origin, EV_TEAM_POWER);
01411 te->s.eventParm = 1;
01412
01413
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
01419 }
01420 i++;
01421 }
01422 }
01423
01424 void ForceTeamForceReplenish( gentity_t *self )
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
01510 if (!te)
01511 {
01512 te = G_TempEntity( self->client->ps.origin, EV_TEAM_POWER);
01513 te->s.eventParm = 2;
01514 }
01515
01516 WP_AddToClientBitflags(te, pl[i]);
01517
01518
01519 i++;
01520 }
01521 }
01522
01523 void ForceGrip( gentity_t *self )
01524 {
01525 trace_t tr;
01526 vec3_t tfrom, tto, fwd;
01527
01528 if ( self->health <= 0 )
01529 {
01530 return;
01531 }
01532
01533 if (self->client->ps.forceHandExtend != HANDEXTEND_NONE)
01534 {
01535 return;
01536 }
01537
01538 if (self->client->ps.weaponTime > 0)
01539 {
01540 return;
01541 }
01542
01543 if (self->client->ps.fd.forceGripUseTime > level.time)
01544 {
01545 return;
01546 }
01547
01548 if ( !WP_ForcePowerUsable( self, FP_GRIP ) )
01549 {
01550 return;
01551 }
01552
01553 VectorCopy(self->client->ps.origin, tfrom);
01554 tfrom[2] += self->client->ps.viewheight;
01555 AngleVectors(self->client->ps.viewangles, fwd, NULL, NULL);
01556 tto[0] = tfrom[0] + fwd[0]*MAX_GRIP_DISTANCE;
01557 tto[1] = tfrom[1] + fwd[1]*MAX_GRIP_DISTANCE;
01558 tto[2] = tfrom[2] + fwd[2]*MAX_GRIP_DISTANCE;
01559
01560 trap_Trace(&tr, tfrom, NULL, NULL, tto, self->s.number, MASK_PLAYERSOLID);
01561
01562 if ( tr.fraction != 1.0 &&
01563 tr.entityNum != ENTITYNUM_NONE &&
01564 g_entities[tr.entityNum].client &&
01565 !g_entities[tr.entityNum].client->ps.fd.forceGripCripple &&
01566 g_entities[tr.entityNum].client->ps.fd.forceGripBeingGripped < level.time &&
01567 ForcePowerUsableOn(self, &g_entities[tr.entityNum], FP_GRIP) &&
01568 (g_friendlyFire.integer || !OnSameTeam(self, &g_entities[tr.entityNum])) )
01569 {
01570 if (g_entities[tr.entityNum].s.number < MAX_CLIENTS && g_entities[tr.entityNum].client->ps.m_iVehicleNum)
01571 {
01572 gentity_t *vehEnt = &g_entities[g_entities[tr.entityNum].client->ps.m_iVehicleNum];
01573 if (vehEnt->inuse && vehEnt->client && vehEnt->m_pVehicle)
01574 {
01575 if (vehEnt->m_pVehicle->m_pVehicleInfo->type == VH_SPEEDER ||
01576 vehEnt->m_pVehicle->m_pVehicleInfo->type == VH_ANIMAL)
01577 {
01578 vehEnt->m_pVehicle->m_pVehicleInfo->Eject(vehEnt->m_pVehicle, (bgEntity_t *)&g_entities[tr.entityNum], qfalse);
01579 }
01580 }
01581 }
01582 self->client->ps.fd.forceGripEntityNum = tr.entityNum;
01583 g_entities[tr.entityNum].client->ps.fd.forceGripStarted = level.time;
01584 self->client->ps.fd.forceGripDamageDebounceTime = 0;
01585
01586 self->client->ps.forceHandExtend = HANDEXTEND_FORCE_HOLD;
01587 self->client->ps.forceHandExtendTime = level.time + 5000;
01588 }
01589 else
01590 {
01591 self->client->ps.fd.forceGripEntityNum = ENTITYNUM_NONE;
01592 return;
01593 }
01594 }
01595
01596 void ForceSpeed( gentity_t *self, int forceDuration )
01597 {
01598 if ( self->health <= 0 )
01599 {
01600 return;
01601 }
01602
01603 if (self->client->ps.forceAllowDeactivateTime < level.time &&
01604 (self->client->ps.fd.forcePowersActive & (1 << FP_SPEED)) )
01605 {
01606 WP_ForcePowerStop( self, FP_SPEED );
01607 return;
01608 }
01609
01610 if ( !WP_ForcePowerUsable( self, FP_SPEED ) )
01611 {
01612 return;
01613 }
01614
01615 if ( self->client->holdingObjectiveItem >= MAX_CLIENTS
01616 && self->client->holdingObjectiveItem < ENTITYNUM_WORLD )
01617 {
01618 if ( g_entities[self->client->holdingObjectiveItem].genericValue15 )
01619 {
01620 return;
01621 }
01622 }
01623
01624 self->client->ps.forceAllowDeactivateTime = level.time + 1500;
01625
01626 WP_ForcePowerStart( self, FP_SPEED, forceDuration );
01627 G_Sound( self, CHAN_BODY, G_SoundIndex("sound/weapons/force/speed.wav") );
01628 G_Sound( self, TRACK_CHANNEL_2, speedLoopSound );
01629 }
01630
01631 void ForceSeeing( gentity_t *self )
01632 {
01633 if ( self->health <= 0 )
01634 {
01635 return;
01636 }
01637
01638 if (self->client->ps.forceAllowDeactivateTime < level.time &&
01639 (self->client->ps.fd.forcePowersActive & (1 << FP_SEE)) )
01640 {
01641 WP_ForcePowerStop( self, FP_SEE );
01642 return;
01643 }
01644
01645 if ( !WP_ForcePowerUsable( self, FP_SEE ) )
01646 {
01647 return;
01648 }
01649
01650 self->client->ps.forceAllowDeactivateTime = level.time + 1500;
01651
01652 WP_ForcePowerStart( self, FP_SEE, 0 );
01653
01654 G_Sound( self, CHAN_AUTO, G_SoundIndex("sound/weapons/force/see.wav") );
01655 G_Sound( self, TRACK_CHANNEL_5, seeLoopSound );
01656 }
01657
01658 void ForceProtect( gentity_t *self )
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
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 }
01693
01694 void ForceAbsorb( gentity_t *self )
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
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 }
01729
01730 void ForceRage( gentity_t *self )
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
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 }
01776
01777 void ForceLightning( gentity_t *self )
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 {
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
01803
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 }
01811
01812 void ForceLightningDamage( gentity_t *self, gentity_t *traceEnt, vec3_t dir, vec3_t impactPoint )
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 {
01822 if (traceEnt->s.genericenemyindex < level.time)
01823 {
01824 traceEnt->s.genericenemyindex = level.time + 2000;
01825 }
01826 }
01827 if ( traceEnt->client )
01828 {
01829 if (traceEnt->client->noLightningTime >= level.time)
01830 {
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);
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 {
01871
01872 dmg *= 2;
01873 }
01874
01875 if (dmg)
01876 {
01877
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 {
01889 traceEnt->client->ps.electrifyTime = level.time + 800;
01890 }
01891 if ( traceEnt->client->ps.powerups[PW_CLOAKED] )
01892 {
01893 Jedi_Decloak( traceEnt );
01894 traceEnt->client->cloakToggleTime = level.time + Q_irand( 3000, 10000 );
01895 }
01896 }
01897 }
01898 }
01899 }
01900 }
01901
01902 void ForceShootLightning( gentity_t *self )
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 {
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 )
01948 continue;
01949 if ( !traceEnt->inuse )
01950 continue;
01951 if ( !traceEnt->takedamage )
01952 continue;
01953 if ( traceEnt->health <= 0 )
01954 continue;
01955 if ( !g_friendlyFire.integer && OnSameTeam(self, traceEnt))
01956 continue;
01957
01958
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
01977
01978 VectorSubtract( ent_org, center, dir );
01979 VectorNormalize( dir );
01980 if ( (dot = DotProduct( dir, forward )) < 0.5 )
01981 continue;
01982
01983
01984 dist = VectorLength( v );
01985 if ( dist >= radius )
01986 {
01987 continue;
01988 }
01989
01990
01991 if ( !traceEnt->r.bmodel && !trap_InPVS( ent_org, self->client->ps.origin ) )
01992 {
01993 continue;
01994 }
01995
01996
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 {
02000 continue;
02001 }
02002
02003
02004 ForceLightningDamage( self, traceEnt, dir, ent_org );
02005 }
02006 }
02007 else
02008 {
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 }
02021
02022 void ForceDrain( gentity_t *self )
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 {
02045 return;
02046 }
02047
02048
02049
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 }
02057
02058 void ForceDrainDamage( gentity_t *self, gentity_t *traceEnt, vec3_t dir, vec3_t impactPoint )
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 {
02070 if (!traceEnt->client && traceEnt->s.eType == ET_NPC)
02071 {
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;
02081 if (self->client->ps.fd.forcePowerLevel[FP_DRAIN] == FORCE_LEVEL_1)
02082 {
02083 dmg = 2;
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
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;
02137
02138
02139
02140
02141
02142
02143
02144
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162
02163
02164
02165
02166
02167
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 }
02183
02184 int ForceShootDrain( gentity_t *self )
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 {
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 )
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
02243
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
02262
02263 VectorSubtract( ent_org, center, dir );
02264 VectorNormalize( dir );
02265 if ( (dot = DotProduct( dir, forward )) < 0.5 )
02266 continue;
02267
02268
02269 dist = VectorLength( v );
02270 if ( dist >= radius )
02271 {
02272 continue;
02273 }
02274
02275
02276 if ( !traceEnt->r.bmodel && !trap_InPVS( ent_org, self->client->ps.origin ) )
02277 {
02278 continue;
02279 }
02280
02281
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 {
02285 continue;
02286 }
02287
02288
02289 ForceDrainDamage( self, traceEnt, dir, ent_org );
02290 gotOneOrMore = 1;
02291 }
02292 }
02293 else
02294 {
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 );
02311
02312 self->client->ps.fd.forcePowerRegenDebounceTime = level.time + 500;
02313
02314 return gotOneOrMore;
02315 }
02316
02317 void ForceJumpCharge( gentity_t *self, usercmd_t *ucmd )
02318 {
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
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
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
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
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 {
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
02375 }
02376
02377 int WP_GetVelocityForForceJump( gentity_t *self, vec3_t jumpVel, usercmd_t *ucmd )
02378 {
02379 float pushFwd = 0, pushRt = 0;
02380 vec3_t view, forward, right;
02381 VectorCopy( self->client->ps.viewangles, view );
02382 view[0] = 0;
02383 AngleVectors( view, forward, right, NULL );
02384 if ( ucmd->forwardmove && ucmd->rightmove )
02385 {
02386 if ( ucmd->forwardmove > 0 )
02387 {
02388 pushFwd = 50;
02389 }
02390 else
02391 {
02392 pushFwd = -50;
02393 }
02394 if ( ucmd->rightmove > 0 )
02395 {
02396 pushRt = 50;
02397 }
02398 else
02399 {
02400 pushRt = -50;
02401 }
02402 }
02403 else if ( ucmd->forwardmove || ucmd->rightmove )
02404 {
02405 if ( ucmd->forwardmove > 0 )
02406 {
02407 pushFwd = 100;
02408 }
02409 else if ( ucmd->forwardmove < 0 )
02410 {
02411 pushFwd = -100;
02412 }
02413 else if ( ucmd->rightmove > 0 )
02414 {
02415 pushRt = 100;
02416 }
02417 else if ( ucmd->rightmove < 0 )
02418 {
02419 pushRt = -100;
02420 }
02421 }
02422
02423 G_MuteSound(self->client->ps.fd.killSoundEntIndex[TRACK_CHANNEL_1-50], CHAN_VOICE);
02424
02425 G_PreDefSound(self->client->ps.origin, PDSOUND_FORCEJUMP);
02426
02427 if (self->client->ps.fd.forceJumpCharge < JUMP_VELOCITY+40)
02428 {
02429 self->client->ps.fd.forceJumpCharge = JUMP_VELOCITY+400;
02430 }
02431
02432 if (self->client->ps.velocity[2] < -30)
02433 {
02434 self->client->ps.velocity[2] = -30;
02435 }
02436
02437 VectorMA( self->client->ps.velocity, pushFwd, forward, jumpVel );
02438 VectorMA( self->client->ps.velocity, pushRt, right, jumpVel );
02439 jumpVel[2] += self->client->ps.fd.forceJumpCharge;
02440 if ( pushFwd > 0 && self->client->ps.fd.forceJumpCharge > 200 )
02441 {
02442 return FJ_FORWARD;
02443 }
02444 else if ( pushFwd < 0 && self->client->ps.fd.forceJumpCharge > 200 )
02445 {
02446 return FJ_BACKWARD;
02447 }
02448 else if ( pushRt > 0 && self->client->ps.fd.forceJumpCharge > 200 )
02449 {
02450 return FJ_RIGHT;
02451 }
02452 else if ( pushRt < 0 && self->client->ps.fd.forceJumpCharge > 200 )
02453 {
02454 return FJ_LEFT;
02455 }
02456 else
02457 {
02458 return FJ_UP;
02459 }
02460 }
02461
02462 void ForceJump( gentity_t *self, usercmd_t *ucmd )
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
02491 self->client->ps.fd.forceJumpZStart = self->client->ps.origin[2];
02492 VectorCopy( jumpVel, self->client->ps.velocity );
02493
02494
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
02498 self->client->ps.fd.forceJumpCharge = 0;
02499 self->client->ps.forceJumpFlip = qtrue;
02500 }
02501
02502 void WP_AddAsMindtricked(forcedata_t *fd, int entNum)
02503 {
02504 if (!fd)
02505 {
02506 return;
02507 }
02508
02509 if (entNum > 47)
02510 {
02511 fd->forceMindtrickTargetIndex4 |= (1 << (entNum-48));
02512 }
02513 else if (entNum > 31)
02514 {
02515 fd->forceMindtrickTargetIndex3 |= (1 << (entNum-32));
02516 }
02517 else if (entNum > 15)
02518 {
02519 fd->forceMindtrickTargetIndex2 |= (1 << (entNum-16));
02520 }
02521 else
02522 {
02523 fd->forceMindtrickTargetIndex |= (1 << entNum);
02524 }
02525 }
02526
02527 qboolean ForceTelepathyCheckDirectNPCTarget( gentity_t *self, trace_t *tr, qboolean *tookPower )
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
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:
02565 case CLASS_ATST:
02566
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 {
02588 return qfalse;
02589 }
02590
02591 if ( targetLive && traceEnt->NPC )
02592 {
02593 vec3_t eyeDir;
02594 if ( G_ActivateBehavior( traceEnt, BSET_MINDTRICK ) )
02595 {
02596
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 {
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 {
02609 if ( self->client->ps.fd.forcePowerLevel[FP_TELEPATHY] > FORCE_LEVEL_2 )
02610 {
02611
02612 if ( traceEnt->s.weapon != WP_NONE )
02613 {
02614 int newPlayerTeam, newEnemyTeam;
02615
02616 if ( traceEnt->enemy )
02617 {
02618 G_ClearEnemy( traceEnt );
02619 }
02620 if ( traceEnt->NPC )
02621 {
02622
02623 traceEnt->client->leader = self;
02624 }
02625
02626 if ( self->NPC )
02627 {
02628 newPlayerTeam = self->client->playerTeam;
02629 newEnemyTeam = self->client->enemyTeam;
02630 }
02631 else
02632 {
02633 if ( self->client->sess.sessionTeam == TEAM_BLUE )
02634 {
02635 newPlayerTeam = NPCTEAM_PLAYER;
02636 newEnemyTeam = NPCTEAM_ENEMY;
02637 }
02638 else if ( self->client->sess.sessionTeam == TEAM_RED )
02639 {
02640 newPlayerTeam = NPCTEAM_ENEMY;
02641 newEnemyTeam = NPCTEAM_PLAYER;
02642 }
02643 else
02644 {
02645 newPlayerTeam = NPCTEAM_NEUTRAL;
02646 newEnemyTeam = NPCTEAM_NEUTRAL;
02647 }
02648 }
02649
02650 traceEnt->genericValue1 = traceEnt->client->playerTeam;
02651 traceEnt->genericValue2 = traceEnt->client->enemyTeam;
02652 traceEnt->genericValue3 = traceEnt->s.teamowner;
02653
02654 traceEnt->client->playerTeam = newPlayerTeam;
02655 traceEnt->client->enemyTeam = newEnemyTeam;
02656 traceEnt->s.teamowner = newPlayerTeam;
02657
02658 traceEnt->NPC->charmedTime = level.time + mindTrickTime[self->client->ps.fd.forcePowerLevel[FP_TELEPATHY]];
02659 }
02660 }
02661 else
02662 {
02663
02664 traceEnt->NPC->confusionTime = level.time + mindTrickTime[self->client->ps.fd.forcePowerLevel[FP_TELEPATHY]];
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 {
02680
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 }
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
02692
02693
02694
02695 mindTrickDone = qtrue;
02696 }
02697 else
02698 {
02699 if ( self->client->ps.fd.forcePowerLevel[FP_TELEPATHY] > FORCE_LEVEL_1 && tr->fraction * 2048 > 64 )
02700 {
02701
02702 G_PlayEffectID( G_EffectIndex( "force/force_touch" ), tr->endpos, tr->plane.normal );
02703
02704 AddSoundEvent( self, tr->endpos, 512, AEL_SUSPICIOUS, qtrue );
02705 AddSightEvent( self, tr->endpos, 512, AEL_SUSPICIOUS, 50 );
02706 WP_ForcePowerStart( self, FP_TELEPATHY, 0 );
02707 *tookPower = qtrue;
02708 }
02709
02710 }
02711
02712 self->client->ps.saberBlocked = BLOCKED_NONE;
02713 self->client->ps.weaponTime = 1000;
02714
02715
02716
02717
02718
02719
02720 return qtrue;
02721 }
02722
02723 void ForceTelepathy(gentity_t *self)
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 {
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 {
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
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 {
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 {
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 }
02894
02895 void GEntity_UseFunc( gentity_t *self, gentity_t *other, gentity_t *activator )
02896 {
02897 GlobalUse(self, other, activator);
02898 }
02899
02900 qboolean CanCounterThrow(gentity_t *self, gentity_t *thrower, qboolean pull)
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 {
02927 return 0;
02928 }
02929
02930 if (g_gametype.integer == GT_SIEGE &&
02931 pull &&
02932 thrower && thrower->client)
02933 {
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 {
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 {
02964 return 0;
02965 }
02966
02967 return 1;
02968 }
02969
02970 qboolean G_InGetUpAnim(playerState_t *ps)
02971 {
02972 switch( (ps->legsAnim) )
02973 {
02974 case BOTH_GETUP1:
02975 case BOTH_GETUP2:
02976 case BOTH_GETUP3:
02977 case BOTH_GETUP4:
02978 case BOTH_GETUP5:
02979 case BOTH_FORCE_GETUP_F1:
02980 case BOTH_FORCE_GETUP_F2:
02981 case BOTH_FORCE_GETUP_B1:
02982 case BOTH_FORCE_GETUP_B2:
02983 case BOTH_FORCE_GETUP_B3:
02984 case BOTH_FORCE_GETUP_B4:
02985 case BOTH_FORCE_GETUP_B5:
02986 case BOTH_GETUP_BROLL_B:
02987 case BOTH_GETUP_BROLL_F:
02988 case BOTH_GETUP_BROLL_L:
02989 case BOTH_GETUP_BROLL_R:
02990 case BOTH_GETUP_FROLL_B:
02991 case BOTH_GETUP_FROLL_F:
02992 case BOTH_GETUP_FROLL_L:
02993 case BOTH_GETUP_FROLL_R:
02994 return qtrue;
02995 }
02996
02997 switch( (ps->torsoAnim) )
02998 {
02999 case BOTH_GETUP1:
03000 case BOTH_GETUP2:
03001 case BOTH_GETUP3:
03002 case BOTH_GETUP4:
03003 case BOTH_GETUP5:
03004 case BOTH_FORCE_GETUP_F1:
03005 case BOTH_FORCE_GETUP_F2:
03006 case BOTH_FORCE_GETUP_B1:
03007 case BOTH_FORCE_GETUP_B2:
03008 case BOTH_FORCE_GETUP_B3:
03009 case BOTH_FORCE_GETUP_B4:
03010 case BOTH_FORCE_GETUP_B5:
03011 case BOTH_GETUP_BROLL_B:
03012 case BOTH_GETUP_BROLL_F:
03013 case BOTH_GETUP_BROLL_L:
03014 case BOTH_GETUP_BROLL_R:
03015 case BOTH_GETUP_FROLL_B:
03016 case BOTH_GETUP_FROLL_F:
03017 case BOTH_GETUP_FROLL_L:
03018 case BOTH_GETUP_FROLL_R:
03019 return qtrue;
03020 }
03021
03022 return qfalse;
03023 }
03024
03025 void G_LetGoOfWall( gentity_t *ent )
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 }
03043
03044 float forcePushPullRadius[NUM_FORCE_POWER_LEVELS] =
03045 {
03046 0,
03047 384,
03048 448,
03049 512
03050 };
03051
03052
03053 extern void Touch_Button(gentity_t *ent, gentity_t *other, trace_t *trace );
03054 void ForceThrow( gentity_t *self, qboolean pull )
03055 {
03056
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;
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
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 {
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;
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 {
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 {
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 {
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
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 {
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 {
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 {
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
03347 if ( Q_stricmp( "func_button", ent->classname ) == 0 )
03348 {
03349 if ( pull || !(ent->spawnflags&SPF_BUTTON_FPUSHABLE) )
03350 {
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 {
03364 if ( Q_stricmp( "func_door", ent->classname ) != 0 || !(ent->spawnflags & 2) )
03365 {
03366 if ( Q_stricmp( "func_static", ent->classname ) != 0 || (!(ent->spawnflags&1)&&!(ent->spawnflags&2)) )
03367 {
03368 if ( Q_stricmp( "limb", ent->classname ) )
03369 {
03370 continue;
03371 }
03372 }
03373 }
03374 else if ( ent->moverState != MOVER_POS1 && ent->moverState != MOVER_POS2 )
03375 {
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 {
03384 continue;
03385 }
03386 }
03387 }
03388 }
03389 else
03390 {
03391 if ( ent->s.pos.trType == TR_STATIONARY && (ent->s.eFlags&EF_MISSILE_STICK) )
03392 {
03393 continue;
03394 }
03395 if ( ent->s.pos.trType == TR_STATIONARY && ent->s.weapon != WP_THERMAL )
03396 {
03397 continue;
03398 }
03399 }
03400
03401
03402
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
03428
03429
03430 if ( dist >= radius )
03431 {
03432 continue;
03433 }
03434
03435
03436 if ( !ent->r.bmodel && !trap_InPVS( ent_org, self->client->ps.origin ) )
03437 {
03438 continue;
03439 }
03440
03441
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 {
03445
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
03458 push_list[ent_count] = ent;
03459 ent_count++;
03460 }
03461
03462 if ( ent_count )
03463 {
03464
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 {
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 {
03500
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 {
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
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
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 {
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;
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 {
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 {
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
03659 if (self->client->ps.fd.forceGripBeingGripped > level.time)
03660 {
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 {
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;
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
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 {
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) )
03704 {
03705 if ( pull )
03706 {
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 {
03715 if ( !pull && (push_list[x]->spawnflags&1) )
03716 {
03717 GEntity_UseFunc( push_list[x], self, self );
03718 }
03719 else if ( pull && (push_list[x]->spawnflags&2) )
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 {
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 {
03738 continue;
03739 }
03740
03741 if ( VectorCompare( vec3_origin, push_list[x]->s.origin ) )
03742 {
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 {
03747 VectorSubtract( center, push_list[x]->pos1, center );
03748 }
03749 else if ( !(push_list[x]->spawnflags&1) && push_list[x]->moverState == MOVER_POS2 )
03750 {
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 {
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 {
03765 if ( push_list[x]->moverState == MOVER_POS1 )
03766 {
03767 if ( pull )
03768 {
03769 continue;
03770 }
03771 }
03772 else if ( push_list[x]->moverState == MOVER_POS2 )
03773 {
03774 if ( !pull )
03775 {
03776 continue;
03777 }
03778 }
03779 }
03780 else
03781 {
03782 if ( push_list[x]->moverState == MOVER_POS1 )
03783 {
03784 if ( !pull )
03785 {
03786 continue;
03787 }
03788 }
03789 else if ( push_list[x]->moverState == MOVER_POS2 )
03790 {
03791 if ( pull )
03792 {
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 {
03801 Touch_Button( push_list[x], self, NULL );
03802 continue;
03803 }
03804 }
03805 }
03806
03807
03808
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 }
03818
03819 void WP_ForcePowerStop( gentity_t *self, forcePowers_t forcePower )
03820 {
03821 int wasActive = self->client->ps.fd.forcePowersActive;
03822
03823 self->client->ps.fd.forcePowersActive &= ~( 1 << forcePower );
03824
03825 switch( (int)forcePower )
03826 {
03827 case FP_HEAL:
03828 self->client->ps.fd.forceHealAmount = 0;
03829 self->client->ps.fd.forceHealTime = 0;
03830 break;
03831 case FP_LEVITATION:
03832 break;
03833 case FP_SPEED:
03834 if (wasActive & (1 << FP_SPEED))
03835 {
03836 G_MuteSound(self->client->ps.fd.killSoundEntIndex[TRACK_CHANNEL_2-50], CHAN_VOICE);
03837 }
03838 break;
03839 case FP_PUSH:
03840 break;
03841 case FP_PULL:
03842 break;
03843 case FP_TELEPATHY:
03844 if (wasActive & (1 << FP_TELEPATHY))
03845 {
03846 G_Sound( self, CHAN_AUTO, G_SoundIndex("sound/weapons/force/distractstop.wav") );
03847 }
03848 self->client->ps.fd.forceMindtrickTargetIndex = 0;
03849 self->client->ps.fd.forceMindtrickTargetIndex2 = 0;
03850 self->client->ps.fd.forceMindtrickTargetIndex3 = 0;
03851 self->client->ps.fd.forceMindtrickTargetIndex4 = 0;
03852 break;
03853 case FP_SEE:
03854 if (wasActive & (1 << FP_SEE))
03855 {
03856 G_MuteSound(self->client->ps.fd.killSoundEntIndex[TRACK_CHANNEL_5-50], CHAN_VOICE);
03857 }
03858 break;
03859 case FP_GRIP:
03860 self->client->ps.fd.forceGripUseTime = level.time + 3000;
03861 if (self->client->ps.fd.forcePowerLevel[FP_GRIP] > FORCE_LEVEL_1 &&
03862 g_entities[self->client->ps.fd.forceGripEntityNum].client &&
03863 g_entities[self->client->ps.fd.forceGripEntityNum].health > 0 &&
03864 g_entities[self->client->ps.fd.forceGripEntityNum].inuse &&
03865 (level.time - g_entities[self->client->ps.fd.forceGripEntityNum].client->ps.fd.forceGripStarted) > 500)
03866 {
03867 if (wasActive & (1 << FP_GRIP))
03868 {
03869 G_EntitySound( &g_entities[self->client->ps.fd.forceGripEntityNum], CHAN_VOICE, G_SoundIndex("*gasp.wav") );
03870 }
03871 }
03872
03873 if (g_entities[self->client->ps.fd.forceGripEntityNum].client &&
03874 g_entities[self->client->ps.fd.forceGripEntityNum].inuse)
03875 {
03876
03877 g_entities[self->client->ps.fd.forceGripEntityNum].client->ps.forceGripChangeMovetype = PM_NORMAL;
03878 }
03879
03880 if (self->client->ps.forceHandExtend == HANDEXTEND_FORCE_HOLD)
03881 {
03882 self->client->ps.forceHandExtendTime = 0;
03883 }
03884
03885 self->client->ps.fd.forceGripEntityNum = ENTITYNUM_NONE;
03886
03887 self->client->ps.powerups[PW_DISINT_4] = 0;
03888 break;
03889 case FP_LIGHTNING:
03890 if ( self->client->ps.fd.forcePowerLevel[FP_LIGHTNING] < FORCE_LEVEL_2 )
03891 {
03892 self->client->ps.fd.forcePowerDebounce[FP_LIGHTNING] = level.time + 3000;
03893 }
03894 else
03895 {
03896 self->client->ps.fd.forcePowerDebounce[FP_LIGHTNING] = level.time + 1500;
03897 }
03898 if (self->client->ps.forceHandExtend == HANDEXTEND_FORCE_HOLD)
03899 {
03900 self->client->ps.forceHandExtendTime = 0;
03901 }
03902
03903 self->client->ps.activeForcePass = 0;
03904 break;
03905 case FP_RAGE:
03906 self->client->ps.fd.forceRageRecoveryTime = level.time + 10000;
03907 if (wasActive & (1 << FP_RAGE))
03908 {
03909 G_MuteSound(self->client->ps.fd.killSoundEntIndex[TRACK_CHANNEL_3-50], CHAN_VOICE);
03910 }
03911 break;
03912 case FP_ABSORB:
03913 if (wasActive & (1 << FP_ABSORB))
03914 {
03915 G_MuteSound(self->client->ps.fd.killSoundEntIndex[TRACK_CHANNEL_3-50], CHAN_VOICE);
03916 }
03917 break;
03918 case FP_PROTECT:
03919 if (wasActive & (1 << FP_PROTECT))
03920 {
03921 G_MuteSound(self->client->ps.fd.killSoundEntIndex[TRACK_CHANNEL_3-50], CHAN_VOICE);
03922 }
03923 break;
03924 case FP_DRAIN:
03925 if ( self->client->ps.fd.forcePowerLevel[FP_DRAIN] < FORCE_LEVEL_2 )
03926 {
03927 self->client->ps.fd.forcePowerDebounce[FP_DRAIN] = level.time + 3000;
03928 }
03929 else
03930 {
03931 self->client->ps.fd.forcePowerDebounce[FP_DRAIN] = level.time + 1500;
03932 }
03933
03934 if (self->client->ps.forceHandExtend == HANDEXTEND_FORCE_HOLD)
03935 {
03936 self->client->ps.forceHandExtendTime = 0;
03937 }
03938
03939 self->client->ps.activeForcePass = 0;
03940 default:
03941 break;
03942 }
03943 }
03944
03945 void DoGripAction(gentity_t *self, forcePowers_t forcePower)
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 )
04004 {
04005 WP_ForcePowerStop(self, forcePower);
04006 return;
04007 }
04008
04009 if (self->client->ps.fd.forcePowerDebounce[FP_GRIP] < level.time)
04010 {
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);
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;
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 {
04047 self->client->ps.fd.forceGripDamageDebounceTime = 1;
04048 G_Damage(gripEnt, self, self, NULL, NULL, 20, DAMAGE_NO_ARMOR, MOD_FORCE_DARK);
04049
04050
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 {
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 {
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;
04129 }
04130
04131 if ((level.time - gripEnt->client->ps.fd.forceGripStarted) > 3000 && !self->client->ps.fd.forceGripDamageDebounceTime)
04132 {
04133 self->client->ps.fd.forceGripDamageDebounceTime = 1;
04134 G_Damage(gripEnt, self, self, NULL, NULL, 40, DAMAGE_NO_ARMOR, MOD_FORCE_DARK);
04135
04136
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 {
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 }
04154
04155 qboolean G_IsMindTricked(forcedata_t *fd, int client)
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 }
04198
04199 static void RemoveTrickedEnt(forcedata_t *fd, int client)
04200 {
04201 if (!fd)
04202 {
04203 return;
04204 }
04205
04206 if (client > 47)
04207 {
04208 fd->forceMindtrickTargetIndex4 &= ~(1 << (client-48));
04209 }
04210 else if (client > 31)
04211 {
04212 fd->forceMindtrickTargetIndex3 &= ~(1 << (client-32));
04213 }
04214 else if (client > 15)
04215 {
04216 fd->forceMindtrickTargetIndex2 &= ~(1 << (client-16));
04217 }
04218 else
04219 {
04220 fd->forceMindtrickTargetIndex &= ~(1 << client);
04221 }
04222 }
04223
04224 extern int g_LastFrameTime;
04225 extern int g_TimeSinceLastFrame;
04226
04227 static void WP_UpdateMindtrickEnts(gentity_t *self)
04228 {
04229 int i = 0;
04230
04231 while (i < MAX_CLIENTS)
04232 {
04233 if (G_IsMindTricked(&self->client->ps.fd, i))
04234 {
04235 gentity_t *ent = &g_entities[i];
04236
04237 if ( !ent || !ent->client || !ent->inuse || ent->health < 1 ||
04238 (ent->client->ps.fd.forcePowersActive & (1 << FP_SEE)) )
04239 {
04240 RemoveTrickedEnt(&self->client->ps.fd, i);
04241 }
04242 else if ((level.time - self->client->dangerTime) < g_TimeSinceLastFrame*4)
04243 {
04244 if (trap_InPVS(ent->client->ps.origin, self->client->ps.origin) &&
04245 OrgVisible(ent->client->ps.origin, self->client->ps.origin, ent->s.number))
04246 {
04247 RemoveTrickedEnt(&self->client->ps.fd, i);
04248 }
04249 }
04250 else if (BG_HasYsalamiri(g_gametype.integer, &ent->client->ps))
04251 {
04252 RemoveTrickedEnt(&self->client->ps.fd, i);
04253 }
04254 }
04255
04256 i++;
04257 }
04258
04259 if (!self->client->ps.fd.forceMindtrickTargetIndex &&
04260 !self->client->ps.fd.forceMindtrickTargetIndex2 &&
04261 !self->client->ps.fd.forceMindtrickTargetIndex3 &&
04262 !self->client->ps.fd.forceMindtrickTargetIndex4)
04263 {
04264 WP_ForcePowerStop(self, FP_TELEPATHY);
04265 }
04266 else if (self->client->ps.powerups[PW_REDFLAG] ||
04267 self->client->ps.powerups[PW_BLUEFLAG])
04268 {
04269 WP_ForcePowerStop(self, FP_TELEPATHY);
04270 }
04271 }
04272
04273 static void WP_ForcePowerRun( gentity_t *self, forcePowers_t forcePower, usercmd_t *cmd )
04274 {
04275 extern usercmd_t ucmd;
04276
04277 switch( (int)forcePower )
04278 {
04279 case FP_HEAL:
04280 if (self->client->ps.fd.forcePowerLevel[FP_HEAL] == FORCE_LEVEL_1)
04281 {
04282 if (self->client->ps.velocity[0] || self->client->ps.velocity[1] || self->client->ps.velocity[2])
04283 {
04284 WP_ForcePowerStop( self, forcePower );
04285 break;
04286 }
04287 }
04288
04289 if (self->health < 1 || self->client->ps.stats[STAT_HEALTH] < 1)
04290 {
04291 WP_ForcePowerStop( self, forcePower );
04292 break;
04293 }
04294
04295 if (self->client->ps.fd.forceHealTime > level.time)
04296 {
04297 break;
04298 }
04299 if ( self->health > self->client->ps.stats[STAT_MAX_HEALTH])
04300 {
04301 WP_ForcePowerStop( self, forcePower );
04302 break;
04303 }
04304 self->client->ps.fd.forceHealTime = level.time + 1000;
04305 self->health++;
04306 self->client->ps.fd.forceHealAmount++;
04307
04308 if ( self->health > self->client->ps.stats[STAT_MAX_HEALTH])
04309 {
04310 self->health = self->client->ps.stats[STAT_MAX_HEALTH];
04311 WP_ForcePowerStop( self, forcePower );
04312 }
04313
04314 if ( (self->client->ps.fd.forcePowerLevel[FP_HEAL] == FORCE_LEVEL_1 && self->client->ps.fd.forceHealAmount >= 25) ||
04315 (self->client->ps.fd.forcePowerLevel[FP_HEAL] == FORCE_LEVEL_2 && self->client->ps.fd.forceHealAmount >= 33))
04316 {
04317 WP_ForcePowerStop( self, forcePower );
04318 }
04319 break;
04320 case FP_SPEED:
04321
04322 if ( self->client->holdingObjectiveItem >= MAX_CLIENTS
04323 && self->client->holdingObjectiveItem < ENTITYNUM_WORLD )
04324 {
04325 if ( g_entities[self->client->holdingObjectiveItem].genericValue15 )
04326 {
04327 WP_ForcePowerStop( self, forcePower );
04328 }
04329 }
04330
04331
04332
04333
04334
04335
04336
04337
04338 break;
04339 case FP_GRIP:
04340 if (self->client->ps.forceHandExtend != HANDEXTEND_FORCE_HOLD)
04341 {
04342 WP_ForcePowerStop(self, FP_GRIP);
04343 break;
04344 }
04345
04346 if (self->client->ps.fd.forcePowerDebounce[FP_PULL] < level.time)
04347 {
04348 BG_ForcePowerDrain( &self->client->ps, forcePower, 1 );
04349 self->client->ps.fd.forcePowerDebounce[FP_PULL] = level.time + 100;
04350 }
04351
04352 if (self->client->ps.fd.forcePower < 1)
04353 {
04354 WP_ForcePowerStop(self, FP_GRIP);
04355 break;
04356 }
04357
04358 DoGripAction(self, forcePower);
04359 break;
04360 case FP_LEVITATION:
04361 if ( self->client->ps.groundEntityNum != ENTITYNUM_NONE && !self->client->ps.fd.forceJumpZStart )
04362 {
04363 WP_ForcePowerStop( self, forcePower );
04364 }
04365 break;
04366 case FP_RAGE:
04367 if (self->health < 1)
04368 {
04369 WP_ForcePowerStop(self, forcePower);
04370 break;
04371 }
04372 if (self->client->ps.forceRageDrainTime < level.time)
04373 {
04374 int addTime = 400;
04375
04376 self->health -= 2;
04377
04378 if (self->client->ps.fd.forcePowerLevel[FP_RAGE] == FORCE_LEVEL_1)
04379 {
04380 addTime = 150;
04381 }
04382 else if (self->client->ps.fd.forcePowerLevel[FP_RAGE] == FORCE_LEVEL_2)
04383 {
04384 addTime = 300;
04385 }
04386 else if (self->client->ps.fd.forcePowerLevel[FP_RAGE] == FORCE_LEVEL_3)
04387 {
04388 addTime = 450;
04389 }
04390 self->client->ps.forceRageDrainTime = level.time + addTime;
04391 }
04392
04393 if (self->health < 1)
04394 {
04395 self->health = 1;
04396 WP_ForcePowerStop(self, forcePower);
04397 }
04398
04399 self->client->ps.stats[STAT_HEALTH] = self->health;
04400 break;
04401 case FP_DRAIN:
04402 if (self->client->ps.forceHandExtend != HANDEXTEND_FORCE_HOLD)
04403 {
04404 WP_ForcePowerStop(self, forcePower);
04405 break;
04406 }
04407
04408 if ( self->client->ps.fd.forcePowerLevel[FP_DRAIN] > FORCE_LEVEL_1 )
04409 {
04410 if ( (cmd->buttons & BUTTON_FORCE_DRAIN) || ((cmd->buttons & BUTTON_FORCEPOWER) && self->client->ps.fd.forcePowerSelected == FP_DRAIN) )
04411 {
04412 self->client->ps.fd.forcePowerDuration[FP_DRAIN] = level.time + 500;
04413 }
04414 }
04415
04416 if ( !WP_ForcePowerAvailable( self, forcePower, 0 ) || self->client->ps.fd.forcePowerDuration[FP_DRAIN] < level.time ||
04417 self->client->ps.fd.forcePower < 25)
04418 {
04419 WP_ForcePowerStop( self, forcePower );
04420 }
04421 else
04422 {
04423 ForceShootDrain( self );
04424 }
04425 break;
04426 case FP_LIGHTNING:
04427 if (self->client->ps.forceHandExtend != HANDEXTEND_FORCE_HOLD)
04428 {
04429 WP_ForcePowerStop(self, forcePower);
04430 break;
04431 }
04432
04433 if ( self->client->ps.fd.forcePowerLevel[FP_LIGHTNING] > FORCE_LEVEL_1 )
04434 {
04435 if ( (cmd->buttons & BUTTON_FORCE_LIGHTNING) || ((cmd->buttons & BUTTON_FORCEPOWER) && self->client->ps.fd.forcePowerSelected == FP_LIGHTNING) )
04436 {
04437 self->client->ps.fd.forcePowerDuration[FP_LIGHTNING] = level.time + 500;
04438 }
04439 }
04440
04441 if ( !WP_ForcePowerAvailable( self, forcePower, 0 ) || self->client->ps.fd.forcePowerDuration[FP_LIGHTNING] < level.time ||
04442 self->client->ps.fd.forcePower < 25)
04443 {
04444 WP_ForcePowerStop( self, forcePower );
04445 }
04446 else
04447 {
04448 ForceShootLightning( self );
04449 BG_ForcePowerDrain( &self->client->ps, forcePower, 0 );
04450 }
04451 break;
04452 case FP_TELEPATHY:
04453 if ( self->client->holdingObjectiveItem >= MAX_CLIENTS
04454 && self->client->holdingObjectiveItem < ENTITYNUM_WORLD
04455 && g_entities[self->client->holdingObjectiveItem].genericValue15 )
04456 {
04457 WP_ForcePowerStop( self, FP_TELEPATHY );
04458 }
04459 else
04460 {
04461 WP_UpdateMindtrickEnts(self);
04462 }
04463 break;
04464 case FP_SABER_OFFENSE:
04465 break;
04466 case FP_SABER_DEFENSE:
04467 break;
04468 case FP_SABERTHROW:
04469 break;
04470 case FP_PROTECT:
04471 if (self->client->ps.fd.forcePowerDebounce[forcePower] < level.time)
04472 {
04473 BG_ForcePowerDrain( &self->client->ps, forcePower, 1 );
04474 if (self->client->ps.fd.forcePower < 1)
04475 {
04476 WP_ForcePowerStop(self, forcePower);
04477 }
04478
04479 self->client->ps.fd.forcePowerDebounce[forcePower] = level.time + 300;
04480 }
04481 break;
04482 case FP_ABSORB:
04483 if (self->client->ps.fd.forcePowerDebounce[forcePower] < level.time)
04484 {
04485 BG_ForcePowerDrain( &self->client->ps, forcePower, 1 );
04486 if (self->client->ps.fd.forcePower < 1)
04487 {
04488 WP_ForcePowerStop(self, forcePower);
04489 }
04490
04491 self->client->ps.fd.forcePowerDebounce[forcePower] = level.time + 600;
04492 }
04493 break;
04494 default:
04495 break;
04496 }
04497 }
04498
04499 int WP_DoSpecificPower( gentity_t *self, usercmd_t *ucmd, forcePowers_t forcepower)
04500 {
04501 int powerSucceeded;
04502
04503 powerSucceeded = 1;
04504
04505
04506 if ( !WP_ForcePowerAvailable( self, forcepower, 0 ) )
04507 {
04508 return 0;
04509 }
04510
04511 switch(forcepower)
04512 {
04513 case FP_HEAL:
04514 powerSucceeded = 0;
04515 if (self->client->ps.fd.forceButtonNeedRelease)
04516 {
04517 break;
04518 }
04519 ForceHeal(self);
04520 self->client->ps.fd.forceButtonNeedRelease = 1;
04521 break;
04522 case FP_LEVITATION:
04523
04524
04525 if ( self->client->ps.groundEntityNum == ENTITYNUM_NONE )
04526 {
04527 self->client->ps.fd.forceJumpCharge = 0;
04528 G_MuteSound( self->client->ps.fd.killSoundEntIndex[TRACK_CHANNEL_1-50], CHAN_VOICE );
04529
04530 }
04531 else
04532 {
04533 ForceJump( self, ucmd );
04534 }
04535 break;
04536 case FP_SPEED:
04537 powerSucceeded = 0;
04538 if (self->client->ps.fd.forceButtonNeedRelease)
04539 {
04540 break;
04541 }
04542 ForceSpeed(self, 0);
04543 self->client->ps.fd.forceButtonNeedRelease = 1;
04544 break;
04545 case FP_GRIP:
04546 if (self->client->ps.fd.forceGripEntityNum == ENTITYNUM_NONE)
04547 {
04548 ForceGrip( self );
04549 }
04550
04551 if (self->client->ps.fd.forceGripEntityNum != ENTITYNUM_NONE)
04552 {
04553 if (!(self->client->ps.fd.forcePowersActive & (1 << FP_GRIP)))
04554 {
04555 WP_ForcePowerStart( self, FP_GRIP, 0 );
04556 BG_ForcePowerDrain( &self->client->ps, FP_GRIP, GRIP_DRAIN_AMOUNT );
04557 }
04558 }
04559 else
04560 {
04561 powerSucceeded = 0;
04562 }
04563 break;
04564 case FP_LIGHTNING:
04565 ForceLightning(self);
04566 break;
04567 case FP_PUSH:
04568 powerSucceeded = 0;
04569 if (self->client->ps.fd.forceButtonNeedRelease && !(self->r.svFlags & SVF_BOT))
04570 {
04571 break;
04572 }
04573 ForceThrow(self, qfalse);
04574 self->client->ps.fd.forceButtonNeedRelease = 1;
04575 break;
04576 case FP_PULL:
04577 powerSucceeded = 0;
04578 if (self->client->ps.fd.forceButtonNeedRelease)
04579 {
04580 break;
04581 }
04582 ForceThrow(self, qtrue);
04583 self->client->ps.fd.forceButtonNeedRelease = 1;
04584 break;
04585 case FP_TELEPATHY:
04586 powerSucceeded = 0;
04587 if (self->client->ps.fd.forceButtonNeedRelease)
04588 {
04589 break;
04590 }
04591 ForceTelepathy(self);
04592 self->client->ps.fd.forceButtonNeedRelease = 1;
04593 break;
04594 case FP_RAGE:
04595 powerSucceeded = 0;
04596 if (self->client->ps.fd.forceButtonNeedRelease)
04597 {
04598 break;
04599 }
04600 ForceRage(self);
04601 self->client->ps.fd.forceButtonNeedRelease = 1;
04602 break;
04603 case FP_PROTECT:
04604 powerSucceeded = 0;
04605 if (self->client->ps.fd.forceButtonNeedRelease)
04606 {
04607 break;
04608 }
04609 ForceProtect(self);
04610 self->client->ps.fd.forceButtonNeedRelease = 1;
04611 break;
04612 case FP_ABSORB:
04613 powerSucceeded = 0;
04614 if (self->client->ps.fd.forceButtonNeedRelease)
04615 {
04616 break;
04617 }
04618 ForceAbsorb(self);
04619 self->client->ps.fd.forceButtonNeedRelease = 1;
04620 break;
04621 case FP_TEAM_HEAL:
04622 powerSucceeded = 0;
04623 if (self->client->ps.fd.forceButtonNeedRelease)
04624 {
04625 break;
04626 }
04627 ForceTeamHeal(self);
04628 self->client->ps.fd.forceButtonNeedRelease = 1;
04629 break;
04630 case FP_TEAM_FORCE:
04631 powerSucceeded = 0;
04632 if (self->client->ps.fd.forceButtonNeedRelease)
04633 {
04634 break;
04635 }
04636 ForceTeamForceReplenish(self);
04637 self->client->ps.fd.forceButtonNeedRelease = 1;
04638 break;
04639 case FP_DRAIN:
04640 ForceDrain(self);
04641 break;
04642 case FP_SEE:
04643 powerSucceeded = 0;
04644 if (self->client->ps.fd.forceButtonNeedRelease)
04645 {
04646 break;
04647 }
04648 ForceSeeing(self);
04649 self->client->ps.fd.forceButtonNeedRelease = 1;
04650 break;
04651 case FP_SABER_OFFENSE:
04652 break;
04653 case FP_SABER_DEFENSE:
04654 break;
04655 case FP_SABERTHROW:
04656 break;
04657 default:
04658 break;
04659 }
04660
04661 return powerSucceeded;
04662 }
04663
04664 void FindGenericEnemyIndex(gentity_t *self)
04665 {
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 }
04701
04702 void SeekerDroneUpdate(gentity_t *self)
04703 {
04704 vec3_t org, elevated, dir, a, endir;
04705 gentity_t *en;
04706 float angle;
04707 float prefig = 0;
04708 trace_t tr;
04709
04710 if (!(self->client->ps.eFlags & EF_SEEKERDRONE))
04711 {
04712 self->client->ps.genericEnemyIndex = -1;
04713 return;
04714 }
04715
04716 if (self->health < 1)
04717 {
04718 VectorCopy(self->client->ps.origin, elevated);
04719 elevated[2] += 40;
04720
04721 angle = ((level.time / 12) & 255) * (M_PI * 2) / 255;
04722 dir[0] = cos(angle) * 20;
04723 dir[1] = sin(angle) * 20;
04724 dir[2] = cos(angle) * 5;
04725 VectorAdd(elevated, dir, org);
04726
04727 a[ROLL] = 0;
04728 a[YAW] = 0;
04729 a[PITCH] = 1;
04730
04731 G_PlayEffect(EFFECT_SPARK_EXPLOSION, org, a);
04732
04733 self->client->ps.eFlags -= EF_SEEKERDRONE;
04734 self->client->ps.genericEnemyIndex = -1;
04735
04736 return;
04737 }
04738
04739 if (self->client->ps.droneExistTime >= level.time &&
04740 self->client->ps.droneExistTime < (level.time+5000))
04741 {
04742 self->client->ps.genericEnemyIndex = 1024+self->client->ps.droneExistTime;
04743 if (self->client->ps.droneFireTime < level.time)
04744 {
04745 G_Sound( self, CHAN_BODY, G_SoundIndex("sound/weapons/laser_trap/warning.wav") );
04746 self->client->ps.droneFireTime = level.time + 100;
04747 }
04748 return;
04749 }
04750 else if (self->client->ps.droneExistTime < level.time)
04751 {
04752 VectorCopy(self->client->ps.origin, elevated);
04753 elevated[2] += 40;
04754
04755 prefig = (self->client->ps.droneExistTime-level.time)/80;
04756
04757 if (prefig > 55)
04758 {
04759 prefig = 55;
04760 }
04761 else if (prefig < 1)
04762 {
04763 prefig = 1;
04764 }
04765
04766 elevated[2] -= 55-prefig;
04767
04768 angle = ((level.time / 12) & 255) * (M_PI * 2) / 255;
04769 dir[0] = cos(angle) * 20;
04770 dir[1] = sin(angle) * 20;
04771 dir[2] = cos(angle) * 5;
04772 VectorAdd(elevated, dir, org);
04773
04774 a[ROLL] = 0;
04775 a[YAW] = 0;
04776 a[PITCH] = 1;
04777
04778 G_PlayEffect(EFFECT_SPARK_EXPLOSION, org, a);
04779
04780 self->client->ps.eFlags -= EF_SEEKERDRONE;
04781 self->client->ps.genericEnemyIndex = -1;
04782
04783 return;
04784 }
04785
04786 if (self->client->ps.genericEnemyIndex == -1)
04787 {
04788 self->client->ps.genericEnemyIndex = ENTITYNUM_NONE;
04789 }
04790
04791 if (self->client->ps.genericEnemyIndex != ENTITYNUM_NONE && self->client->ps.genericEnemyIndex != -1)
04792 {
04793 en = &g_entities[self->client->ps.genericEnemyIndex];
04794
04795 if (!en || !en->client)
04796 {
04797 self->client->ps.genericEnemyIndex = ENTITYNUM_NONE;
04798 }
04799 else if (en->s.number == self->s.number)
04800 {
04801 self->client->ps.genericEnemyIndex = ENTITYNUM_NONE;
04802 }
04803 else if (en->health < 1)
04804 {
04805 self->client->ps.genericEnemyIndex = ENTITYNUM_NONE;
04806 }
04807 else if (OnSameTeam(self, en))
04808 {
04809 self->client->ps.genericEnemyIndex = ENTITYNUM_NONE;
04810 }
04811 else
04812 {
04813 if (!InFront(en->client->ps.origin, self->client->ps.origin, self->client->ps.viewangles, 0.8f ))
04814 {
04815 self->client->ps.genericEnemyIndex = ENTITYNUM_NONE;
04816 }
04817 else if (!OrgVisible(self->client->ps.origin, en->client->ps.origin, self->s.number))
04818 {
04819 self->client->ps.genericEnemyIndex = ENTITYNUM_NONE;
04820 }
04821 }
04822 }
04823
04824 if (self->client->ps.genericEnemyIndex == ENTITYNUM_NONE || self->client->ps.genericEnemyIndex == -1)
04825 {
04826 FindGenericEnemyIndex(self);
04827 }
04828
04829 if (self->client->ps.genericEnemyIndex != ENTITYNUM_NONE && self->client->ps.genericEnemyIndex != -1)
04830 {
04831 en = &g_entities[self->client->ps.genericEnemyIndex];
04832
04833 VectorCopy(self->client->ps.origin, elevated);
04834 elevated[2] += 40;
04835
04836 angle = ((level.time / 12) & 255) * (M_PI * 2) / 255;
04837 dir[0] = cos(angle) * 20;
04838 dir[1] = sin(angle) * 20;
04839 dir[2] = cos(angle) * 5;
04840 VectorAdd(elevated, dir, org);
04841
04842
04843 if (self->client->ps.droneFireTime < level.time)
04844 {
04845 trap_Trace(&tr, org, NULL, NULL, en->client->ps.origin, -1, MASK_SOLID);
04846
04847 if (tr.fraction == 1 && !tr.startsolid && !tr.allsolid)
04848 {
04849 VectorSubtract(en->client->ps.origin, org, endir);
04850 VectorNormalize(endir);
04851
04852 WP_FireGenericBlasterMissile(self, org, endir, 0, 15, 2000, MOD_BLASTER);
04853 G_SoundAtLoc( org, CHAN_WEAPON, G_SoundIndex("sound/weapons/bryar/fire.wav") );
04854
04855 self->client->ps.droneFireTime = level.time + Q_irand(400, 700);
04856 }
04857 }
04858 }
04859 }
04860
04861 void HolocronUpdate(gentity_t *self)
04862 {
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 {
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 {
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 {
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 }
04948
04949 void JediMasterUpdate(gentity_t *self)
04950 {
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 {
04965
04966
04967 self->client->ps.fd.forcePowersKnown &= ~(1 << i);
04968 self->client->ps.fd.forcePowerLevel[i] = 0;
04969 }
04970
04971 if (i == FP_TELEPATHY)
04972 {
04973
04974
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.forcePowerLevel[i] = FORCE_LEVEL_0;
04997 }
04998 }
04999
05000 i++;
05001 }
05002 }
05003
05004 qboolean WP_HasForcePowers( const playerState_t *ps )
05005 {
05006 int i;
05007 if ( ps )
05008 {
05009 for ( i = 0; i < NUM_FORCE_POWERS; i++ )
05010 {
05011 if ( i == FP_LEVITATION )
05012 {
05013 if ( ps->fd.forcePowerLevel[i] > FORCE_LEVEL_1 )
05014 {
05015 return qtrue;
05016 }
05017 }
05018 else if ( ps->fd.forcePowerLevel[i] > FORCE_LEVEL_0 )
05019 {
05020 return qtrue;
05021 }
05022 }
05023 }
05024 return qfalse;
05025 }
05026
05027
05028 qboolean G_SpecialRollGetup(gentity_t *self)
05029 {
05030 qboolean rolled = qfalse;
05031
05032
05033
05034
05035
05036
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 (
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 (
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
05075 }
05076
05077 if (rolled)
05078 {
05079 G_EntitySound( self, CHAN_VOICE, G_SoundIndex("*jump1.wav") );
05080 }
05081
05082 return rolled;
05083 }
05084
05085 void WP_ForcePowersUpdate( gentity_t *self, usercmd_t *ucmd )
05086 {
05087 qboolean usingForce = qfalse;
05088 int i, holo, holoregen;
05089 int prepower = 0;
05090
05091 if ( !self )
05092 {
05093 return;
05094 }
05095
05096 if ( !self->client )
05097 {
05098 return;
05099 }
05100
05101 if (self->client->ps.pm_flags & PMF_FOLLOW)
05102 {
05103 return;
05104 }
05105 if (self->client->sess.sessionTeam == TEAM_SPECTATOR)
05106 {
05107 return;
05108 }
05109
05110
05111
05112
05113
05114
05115
05116
05117
05118
05119
05120
05121 if (!self->client->ps.fd.saberAnimLevel)
05122 {
05123 self->client->ps.fd.saberAnimLevel = FORCE_LEVEL_1;
05124 }
05125
05126 if (g_gametype.integer != GT_SIEGE)
05127 {
05128 if (!(self->client->ps.fd.forcePowersKnown & (1 << FP_LEVITATION)))
05129 {
05130 self->client->ps.fd.forcePowersKnown |= (1 << FP_LEVITATION);
05131 }
05132
05133 if (self->client->ps.fd.forcePowerLevel[FP_LEVITATION] < FORCE_LEVEL_1)
05134 {
05135 self->client->ps.fd.forcePowerLevel[FP_LEVITATION] = FORCE_LEVEL_1;
05136 }
05137 }
05138
05139 if (self->client->ps.fd.forcePowerSelected < 0)
05140 {
05141 self->client->ps.fd.forcePowerSelected = 0;
05142 }
05143
05144 if ( ((self->client->sess.selectedFP != self->client->ps.fd.forcePowerSelected) ||
05145 (self->client->sess.saberLevel != self->client->ps.fd.saberAnimLevel)) &&
05146 !(self->r.svFlags & SVF_BOT) )
05147 {
05148 if (self->client->sess.updateUITime < level.time)
05149 {
05150
05151
05152 self->client->sess.selectedFP = self->client->ps.fd.forcePowerSelected;
05153 self->client->sess.saberLevel = self->client->ps.fd.saberAnimLevel;
05154 }
05155 }
05156
05157 if (!g_LastFrameTime)
05158 {
05159 g_LastFrameTime = level.time;
05160 }
05161
05162 if (self->client->ps.forceHandExtend == HANDEXTEND_KNOCKDOWN)
05163 {
05164 self->client->ps.zoomFov = 0;
05165 self->client->ps.zoomMode = 0;
05166 self->client->ps.zoomLocked = qfalse;
05167 self->client->ps.zoomTime = 0;
05168 }
05169
05170 if (self->client->ps.forceHandExtend == HANDEXTEND_KNOCKDOWN &&
05171 self->client->ps.forceHandExtendTime >= level.time)
05172 {
05173 self->client->ps.saberMove = 0;
05174 self->client->ps.saberBlocking = 0;
05175 self->client->ps.saberBlocked = 0;
05176 self->client->ps.weaponTime = 0;
05177 self->client->ps.weaponstate = WEAPON_READY;
05178 }
05179 else if (self->client->ps.forceHandExtend != HANDEXTEND_NONE &&
05180 self->client->ps.forceHandExtendTime < level.time)
05181 {
05182 if (self->client->ps.forceHandExtend == HANDEXTEND_KNOCKDOWN &&
05183 !self->client->ps.forceDodgeAnim)
05184 {
05185 if (self->health < 1 || (self->client->ps.eFlags & EF_DEAD))
05186 {
05187 self->client->ps.forceHandExtend = HANDEXTEND_NONE;
05188 }
05189 else if (G_SpecialRollGetup(self))
05190 {
05191 self->client->ps.forceHandExtend = HANDEXTEND_NONE;
05192 }
05193 else
05194 {
05195 if ((level.time-self->client->ps.forceHandExtendTime) > 4000)
05196 {
05197 if (self->client->pers.cmd.upmove &&
05198 self->client->ps.fd.forcePowerLevel[FP_LEVITATION] > FORCE_LEVEL_1)
05199 {
05200 G_PreDefSound(self->client->ps.origin, PDSOUND_FORCEJUMP);
05201 self->client->ps.forceDodgeAnim = 2;
05202 self->client->ps.forceHandExtendTime = level.time + 500;
05203
05204
05205 }
05206 else if (self->client->ps.quickerGetup)
05207 {
05208 G_EntitySound( self, CHAN_VOICE, G_SoundIndex("*jump1.wav") );
05209 self->client->ps.forceDodgeAnim = 3;
05210 self->client->ps.forceHandExtendTime = level.time + 500;
05211 self->client->ps.velocity[2] = 300;
05212 }
05213 else
05214 {
05215 self->client->ps.forceDodgeAnim = 1;
05216 self->client->ps.forceHandExtendTime = level.time + 1000;
05217 }
05218 }
05219 }
05220 self->client->ps.quickerGetup = qfalse;
05221 }
05222 else if (self->client->ps.forceHandExtend == HANDEXTEND_POSTTHROWN)
05223 {
05224 if (self->health < 1 || (self->client->ps.eFlags & EF_DEAD))
05225 {
05226 self->client->ps.forceHandExtend = HANDEXTEND_NONE;
05227 }
05228 else if (self->client->ps.groundEntityNum != ENTITYNUM_NONE && !self->client->ps.forceDodgeAnim)
05229 {
05230 self->client->ps.forceDodgeAnim = 1;
05231 self->client->ps.forceHandExtendTime = level.time + 1000;
05232 G_EntitySound( self, CHAN_VOICE, G_SoundIndex("*jump1.wav") );
05233 self->client->ps.velocity[2] = 100;
05234 }
05235 else if (!self->client->ps.forceDodgeAnim)
05236 {
05237 self->client->ps.forceHandExtendTime = level.time + 100;
05238 }
05239 else
05240 {
05241 self->client->ps.forceHandExtend = HANDEXTEND_WEAPONREADY;
05242 }
05243 }
05244 else
05245 {
05246 self->client->ps.forceHandExtend = HANDEXTEND_WEAPONREADY;
05247 }
05248 }
05249
05250 if (g_gametype.integer == GT_HOLOCRON)
05251 {
05252 HolocronUpdate(self);
05253 }
05254 if (g_gametype.integer == GT_JEDIMASTER)
05255 {
05256 JediMasterUpdate(self);
05257 }
05258
05259 SeekerDroneUpdate(self);
05260
05261 if (self->client->ps.powerups[PW_FORCE_BOON])
05262 {
05263 prepower = self->client->ps.fd.forcePower;
05264 }
05265
05266 if (self && self->client && (BG_HasYsalamiri(g_gametype.integer, &self->client->ps) ||
05267 self->client->ps.fd.forceDeactivateAll || self->client->tempSpectate >= level.time))
05268 {
05269 i = 0;
05270
05271 while (i < NUM_FORCE_POWERS)
05272 {
05273 if ((self->client->ps.fd.forcePowersActive & (1 << i)) && i != FP_LEVITATION)
05274 {
05275 WP_ForcePowerStop(self, i);
05276 }
05277
05278 i++;
05279 }
05280
05281 if (self->client->tempSpectate >= level.time)
05282 {
05283 self->client->ps.fd.forcePower = 100;
05284 self->client->ps.fd.forceRageRecoveryTime = 0;
05285 }
05286
05287 self->client->ps.fd.forceDeactivateAll = 0;
05288
05289 if (self->client->ps.fd.forceJumpCharge)
05290 {
05291 G_MuteSound(self->client->ps.fd.killSoundEntIndex[TRACK_CHANNEL_1-50], CHAN_VOICE);
05292 self->client->ps.fd.forceJumpCharge = 0;
05293 }
05294 }
05295 else
05296 {
05297 i = 0;
05298
05299 while (i < NUM_FORCE_POWERS)
05300 {
05301 if ((self->client->ps.fd.forcePowersActive & (1 << i)) && i != FP_LEVITATION &&
05302 !BG_CanUseFPNow(g_gametype.integer, &self->client->ps, level.time, i))
05303 {
05304 WP_ForcePowerStop(self, i);
05305 }
05306
05307 i++;
05308 }
05309 }
05310
05311 i = 0;
05312
05313 if (self->client->ps.powerups[PW_FORCE_ENLIGHTENED_LIGHT] || self->client->ps.powerups[PW_FORCE_ENLIGHTENED_DARK])
05314 {
05315 if (!self->client->ps.fd.forceUsingAdded)
05316 {
05317 i = 0;
05318
05319 while (i < NUM_FORCE_POWERS)
05320 {
05321 self->client->ps.fd.forcePowerBaseLevel[i] = self->client->ps.fd.forcePowerLevel[i];
05322
05323 if (!forcePowerDarkLight[i] ||
05324 self->client->ps.fd.forceSide == forcePowerDarkLight[i])
05325 {
05326 self->client->ps.fd.forcePowerLevel[i] = FORCE_LEVEL_3;
05327 self->client->ps.fd.forcePowersKnown |= (1 << i);
05328 }
05329
05330 i++;
05331 }
05332
05333 self->client->ps.fd.forceUsingAdded = 1;
05334 }
05335 }
05336 else if (self->client->ps.fd.forceUsingAdded)
05337 {
05338 i = 0;
05339
05340 while (i < NUM_FORCE_POWERS)
05341 {
05342 self->client->ps.fd.forcePowerLevel[i] = self->client->ps.fd.forcePowerBaseLevel[i];
05343 if (!self->client->ps.fd.forcePowerLevel[i])
05344 {
05345 if (self->client->ps.fd.forcePowersActive & (1 << i))
05346 {
05347 WP_ForcePowerStop(self, i);
05348 }
05349 self->client->ps.fd.forcePowersKnown &= ~(1 << i);
05350 }
05351
05352 i++;
05353 }
05354
05355 self->client->ps.fd.forceUsingAdded = 0;
05356 }
05357
05358 i = 0;
05359
05360 if (!(self->client->ps.fd.forcePowersActive & (1 << FP_TELEPATHY)))
05361 {
05362 self->client->ps.fd.forceMindtrickTargetIndex = 0;
05363 self->client->ps.fd.forceMindtrickTargetIndex2 = 0;
05364 self->client->ps.fd.forceMindtrickTargetIndex3 = 0;
05365 self->client->ps.fd.forceMindtrickTargetIndex4 = 0;
05366 }
05367
05368 if (self->health < 1)
05369 {
05370 self->client->ps.fd.forceGripBeingGripped = 0;
05371 }
05372
05373 if (self->client->ps.fd.forceGripBeingGripped > level.time)
05374 {
05375 self->client->ps.fd.forceGripCripple = 1;
05376
05377
05378 if (self->client->ps.weapon == WP_SABER && !self->client->ps.saberHolstered)
05379 {
05380 Cmd_ToggleSaber_f(self);
05381 }
05382 }
05383 else
05384 {
05385 self->client->ps.fd.forceGripCripple = 0;
05386 }
05387
05388 if (self->client->ps.fd.forceJumpSound)
05389 {
05390 G_PreDefSound(self->client->ps.origin, PDSOUND_FORCEJUMP);
05391 self->client->ps.fd.forceJumpSound = 0;
05392 }
05393
05394 if (self->client->ps.fd.forceGripCripple)
05395 {
05396 if (self->client->ps.fd.forceGripSoundTime < level.time)
05397 {
05398 G_PreDefSound(self->client->ps.origin, PDSOUND_FORCEGRIP);
05399 self->client->ps.fd.forceGripSoundTime = level.time + 1000;
05400 }
05401 }
05402
05403 if (self->client->ps.fd.forcePowersActive & (1 << FP_SPEED))
05404 {
05405 self->client->ps.powerups[PW_SPEED] = level.time + 100;
05406 }
05407
05408 if ( self->health <= 0 )
05409 {
05410 for ( i = 0; i < NUM_FORCE_POWERS; i++ )
05411 {
05412 if ( self->client->ps.fd.forcePowerDuration[i] || (self->client->ps.fd.forcePowersActive&( 1 << i )) )
05413 {
05414 WP_ForcePowerStop( self, (forcePowers_t)i );
05415 self->client->ps.fd.forcePowerDuration[i] = 0;
05416 }
05417 }
05418 goto powersetcheck;
05419 }
05420
05421 if (self->client->ps.groundEntityNum != ENTITYNUM_NONE)
05422 {
05423 self->client->fjDidJump = qfalse;
05424 }
05425
05426 if (self->client->ps.fd.forceJumpCharge && self->client->ps.groundEntityNum == ENTITYNUM_NONE && self->client->fjDidJump)
05427 {
05428 if (ucmd->upmove < 10 && (!(ucmd->buttons & BUTTON_FORCEPOWER) || self->client->ps.fd.forcePowerSelected != FP_LEVITATION))
05429 {
05430 G_MuteSound(self->client->ps.fd.killSoundEntIndex[TRACK_CHANNEL_1-50], CHAN_VOICE);
05431 self->client->ps.fd.forceJumpCharge = 0;
05432 }
05433 }
05434
05435 #ifndef METROID_JUMP
05436 else if ( (ucmd->upmove > 10) && (self->client->ps.pm_flags & PMF_JUMP_HELD) && self->client->ps.groundTime && (level.time - self->client->ps.groundTime) > 150 && !BG_HasYsalamiri(g_gametype.integer, &self->client->ps) && BG_CanUseFPNow(g_gametype.integer, &self->client->ps, level.time, FP_LEVITATION) )
05437 {
05438 ForceJumpCharge( self, ucmd );
05439 usingForce = qtrue;
05440 }
05441 else if (ucmd->upmove < 10 && self->client->ps.groundEntityNum == ENTITYNUM_NONE && self->client->ps.fd.forceJumpCharge)
05442 {
05443 self->client->ps.pm_flags &= ~(PMF_JUMP_HELD);
05444 }
05445 #endif
05446
05447 if (!(self->client->ps.pm_flags & PMF_JUMP_HELD) && self->client->ps.fd.forceJumpCharge)
05448 {
05449 if (!(ucmd->buttons & BUTTON_FORCEPOWER) ||
05450 self->client->ps.fd.forcePowerSelected != FP_LEVITATION)
05451 {
05452 if (WP_DoSpecificPower( self, ucmd, FP_LEVITATION ))
05453 {
05454 usingForce = qtrue;
05455 }
05456 }
05457 }
05458
05459 if ( ucmd->buttons & BUTTON_FORCEGRIP )
05460 {
05461 if (WP_DoSpecificPower( self, ucmd, FP_GRIP ))
05462 {
05463 usingForce = qtrue;
05464 }
05465 else
05466 {
05467 usingForce = qtrue;
05468 }
05469 }
05470 else
05471 {
05472 if (self->client->ps.fd.forcePowersActive & (1 << FP_GRIP))
05473 {
05474 if (!(ucmd->buttons & BUTTON_FORCEPOWER) || self->client->ps.fd.forcePowerSelected != FP_GRIP)
05475 {
05476 WP_ForcePowerStop(self, FP_GRIP);
05477 }
05478 }
05479 }
05480
05481 if ( ucmd->buttons & BUTTON_FORCE_LIGHTNING )
05482 {
05483 WP_DoSpecificPower(self, ucmd, FP_LIGHTNING);
05484 usingForce = qtrue;
05485 }
05486 else
05487 {
05488 if (self->client->ps.fd.forcePowersActive & (1 << FP_LIGHTNING))
05489 {
05490 if (!(ucmd->buttons & BUTTON_FORCEPOWER) || self->client->ps.fd.forcePowerSelected != FP_LIGHTNING)
05491 {
05492 WP_ForcePowerStop(self, FP_LIGHTNING);
05493 }
05494 }
05495 }
05496
05497 if ( ucmd->buttons & BUTTON_FORCE_DRAIN )
05498 {
05499 WP_DoSpecificPower(self, ucmd, FP_DRAIN);
05500 usingForce = qtrue;
05501 }
05502 else
05503 {
05504 if (self->client->ps.fd.forcePowersActive & (1 << FP_DRAIN))
05505 {
05506 if (!(ucmd->buttons & BUTTON_FORCEPOWER) || self->client->ps.fd.forcePowerSelected != FP_DRAIN)
05507 {
05508 WP_ForcePowerStop(self, FP_DRAIN);
05509 }
05510 }
05511 }
05512
05513 if ( (ucmd->buttons & BUTTON_FORCEPOWER) &&
05514 BG_CanUseFPNow(g_gametype.integer, &self->client->ps, level.time, self->client->ps.fd.forcePowerSelected))
05515 {
05516 if (self->client->ps.fd.forcePowerSelected == FP_LEVITATION)
05517 {
05518 ForceJumpCharge( self, ucmd );
05519 usingForce = qtrue;
05520 }
05521 else if (WP_DoSpecificPower( self, ucmd, self->client->ps.fd.forcePowerSelected ))
05522 {
05523 usingForce = qtrue;
05524 }
05525 else if (self->client->ps.fd.forcePowerSelected == FP_GRIP)
05526 {
05527 usingForce = qtrue;
05528 }
05529 }
05530 else
05531 {
05532 self->client->ps.fd.forceButtonNeedRelease = 0;
05533 }
05534
05535 for ( i = 0; i < NUM_FORCE_POWERS; i++ )
05536 {
05537 if ( self->client->ps.fd.forcePowerDuration[i] )
05538 {
05539 if ( self->client->ps.fd.forcePowerDuration[i] < level.time )
05540 {
05541 if ( (self->client->ps.fd.forcePowersActive&( 1 << i )) )
05542 {
05543 WP_ForcePowerStop( self, (forcePowers_t)i );
05544 }
05545 self->client->ps.fd.forcePowerDuration[i] = 0;
05546 }
05547 }
05548 if ( (self->client->ps.fd.forcePowersActive&( 1 << i )) )
05549 {
05550 usingForce = qtrue;
05551 WP_ForcePowerRun( self, (forcePowers_t)i, ucmd );
05552 }
05553 }
05554 if ( self->client->ps.saberInFlight && self->client->ps.saberEntityNum )
05555 {
05556 if ( self->client->ps.saberEntityNum < ENTITYNUM_NONE && self->client->ps.saberEntityNum > 0 )
05557 {
05558 if ( &g_entities[self->client->ps.saberEntityNum] != NULL && g_entities[self->client->ps.saberEntityNum].s.pos.trType == TR_LINEAR )
05559 {
05560 usingForce = qtrue;
05561 }
05562 }
05563 }
05564 if ( !self->client->ps.fd.forcePowersActive || self->client->ps.fd.forcePowersActive == (1 << FP_DRAIN) )
05565 {
05566 if ( !self->client->ps.saberInFlight && self->client->ps.fd.forcePowerRegenDebounceTime < level.time &&
05567 (self->client->ps.weapon != WP_SABER || !BG_SaberInSpecial(self->client->ps.saberMove)) )
05568 {
05569 if (g_gametype.integer != GT_HOLOCRON || g_MaxHolocronCarry.value)
05570 {
05571
05572
05573 {
05574 if (self->client->ps.powerups[PW_FORCE_BOON])
05575 {
05576 WP_ForcePowerRegenerate( self, 6 );
05577 }
05578 else if (self->client->ps.isJediMaster && g_gametype.integer == GT_JEDIMASTER)
05579 {
05580 WP_ForcePowerRegenerate( self, 4 );
05581 }
05582 else
05583 {
05584 WP_ForcePowerRegenerate( self, 0 );
05585 }
05586 }
05587
05588
05589
05590
05591
05592
05593 }
05594 else
05595 {
05596 holoregen = 0;
05597 holo = 0;
05598 while (holo < NUM_FORCE_POWERS)
05599 {
05600 if (self->client->ps.holocronsCarried[holo])
05601 {
05602 holoregen++;
05603 }
05604 holo++;
05605 }
05606
05607 WP_ForcePowerRegenerate(self, holoregen);
05608 }
05609
05610 if (g_gametype.integer == GT_SIEGE)
05611 {
05612 if (self->client->holdingObjectiveItem &&
05613 g_entities[self->client->holdingObjectiveItem].inuse &&
05614 g_entities[self->client->holdingObjectiveItem].genericValue15)
05615 {
05616 self->client->ps.fd.forcePowerRegenDebounceTime = level.time + 7000;
05617 }
05618 else if (self->client->siegeClass != -1 &&
05619 (bgSiegeClasses[self->client->siegeClass].classflags & (1<<CFL_FASTFORCEREGEN)))
05620 {
05621 self->client->ps.fd.forcePowerRegenDebounceTime = level.time + (g_forceRegenTime.integer*0.2);
05622 }
05623 else
05624 {
05625 self->client->ps.fd.forcePowerRegenDebounceTime = level.time + g_forceRegenTime.integer;
05626 }
05627 }
05628 else
05629 {
05630 if ( g_gametype.integer == GT_POWERDUEL && self->client->sess.duelTeam == DUELTEAM_LONE )
05631 {
05632 if ( g_duel_fraglimit.integer )
05633 {
05634 self->client->ps.fd.forcePowerRegenDebounceTime = level.time + (g_forceRegenTime.integer*
05635 (0.6 + (.3 * (float)self->client->sess.wins / (float)g_duel_fraglimit.integer)));
05636 }
05637 else
05638 {
05639 self->client->ps.fd.forcePowerRegenDebounceTime = level.time + (g_forceRegenTime.integer*0.7);
05640 }
05641 }
05642 else
05643 {
05644 self->client->ps.fd.forcePowerRegenDebounceTime = level.time + g_forceRegenTime.integer;
05645 }
05646 }
05647 }
05648 }
05649
05650 powersetcheck:
05651
05652 if (prepower && self->client->ps.fd.forcePower < prepower)
05653 {
05654 int dif = ((prepower - self->client->ps.fd.forcePower)/2);
05655 if (dif < 1)
05656 {
05657 dif = 1;
05658 }
05659
05660 self->client->ps.fd.forcePower = (prepower-dif);
05661 }
05662 }
05663
05664 qboolean Jedi_DodgeEvasion( gentity_t *self, gentity_t *shooter, trace_t *tr, int hitLoc )
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 {
05688 return qfalse;
05689 }
05690
05691 if ( self->client->ps.weaponTime > 0 || self->client->ps.forceHandExtend != HANDEXTEND_NONE )
05692 {
05693 return qfalse;
05694 }
05695
05696 if (g_forceDodge.integer == 2)
05697 {
05698 if (self->client->ps.fd.forcePowersActive)
05699 {
05700 return qfalse;
05701 }
05702 }
05703
05704 if (g_forceDodge.integer == 2)
05705 {
05706 if ( !WP_ForcePowerUsable( self, FP_SPEED ) )
05707 {
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 {
05716 return qfalse;
05717 }
05718 }
05719 else
05720 {
05721
05722 if (self->client->ps.fd.forcePowerLevel[FP_SEE] < FORCE_LEVEL_3)
05723 {
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
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 }