#include "g_local.h"#include "bg_local.h"#include "w_saber.h"#include "ai_main.h"#include "../ghoul2/G2.h"#include "../namespace_begin.h"#include "../namespace_end.h"Go to the source code of this file.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Definition at line 6335 of file w_saber.c. Referenced by DownedSaberThink(). |
|
|
Definition at line 5282 of file w_saber.c. Referenced by G_SPSaberDamageTraceLerped(). |
|
|
Definition at line 3501 of file w_saber.c. Referenced by WP_SaberClearDamage(), and WP_SaberDamageAdd(). |
|
|
|
|
|
|
|
|
Definition at line 282 of file w_saber.c. Referenced by SaberUpdateSelf(), and WP_SaberPositionUpdate(). |
|
|
|
|
|
Definition at line 2848 of file w_saber.c. Referenced by WP_SabersIntersect(). |
|
|
|
|
|
Definition at line 7113 of file w_saber.c. Referenced by saberFirstThrown(). |
|
|
Definition at line 2233 of file w_saber.c. Referenced by WP_SaberDoHit(). |
|
|
Definition at line 6508 of file w_saber.c. Referenced by saberKnockDown(). |
|
|
Definition at line 5887 of file w_saber.c. Referenced by saberKnockOutOfHand(), and WP_SaberPositionUpdate(). |
|
|
|
|
|
Definition at line 6585 of file w_saber.c. Referenced by saberCheckKnockdown_BrokenParry(), saberCheckKnockdown_DuelLoss(), saberCheckKnockdown_Smashed(), and saberCheckKnockdown_Thrown(). |
|
|
|
|
|
|
|
|
|
|
|
Definition at line 1073 of file w_saber.c.
01074 {
01075 LOCK_FIRST = 0,
01076 LOCK_TOP = LOCK_FIRST,
01077 LOCK_DIAG_TR,
01078 LOCK_DIAG_TL,
01079 LOCK_DIAG_BR,
01080 LOCK_DIAG_BL,
01081 LOCK_R,
01082 LOCK_L,
01083 LOCK_RANDOM
01084 } sabersLockMode_t;
|
|
||||||||||||
|
Definition at line 1339 of file bg_saber.c. References BOTH_LK_DL_DL_S_L_1, BOTH_LK_DL_DL_S_L_2, BOTH_LK_DL_DL_T_L_1, BOTH_LK_DL_DL_T_L_2, BOTH_LK_DL_S_S_L_1, BOTH_LK_DL_S_T_L_1, BOTH_LK_DL_ST_S_L_1, BOTH_LK_DL_ST_T_L_1, BOTH_LK_S_DL_S_L_1, BOTH_LK_S_DL_T_L_1, BOTH_LK_S_S_S_L_1, BOTH_LK_S_S_S_L_2, BOTH_LK_S_S_T_L_1, BOTH_LK_S_S_T_L_2, BOTH_LK_S_ST_S_L_1, BOTH_LK_S_ST_T_L_1, BOTH_LK_ST_DL_S_L_1, BOTH_LK_ST_DL_T_L_1, BOTH_LK_ST_S_S_L_1, BOTH_LK_ST_S_T_L_1, BOTH_LK_ST_ST_S_L_1, BOTH_LK_ST_ST_S_L_2, BOTH_LK_ST_ST_T_L_1, BOTH_LK_ST_ST_T_L_2, qboolean, qfalse, qtrue, and SABERLOCK_WIN. Referenced by PM_SaberLocked().
01340 {
01341 qboolean increment = qfalse;//???
01342 //RULE: if you are the first style in the lock anim, you advance from LOSING position to WINNING position
01343 // if you are the second style in the lock anim, you advance from WINNING position to LOSING position
01344 switch ( anim )
01345 {
01346 //increment to win:
01347 case BOTH_LK_DL_DL_S_L_1: //lock if I'm using dual vs. dual and I initiated
01348 case BOTH_LK_DL_DL_S_L_2: //lock if I'm using dual vs. dual and other initiated
01349 case BOTH_LK_DL_DL_T_L_1: //lock if I'm using dual vs. dual and I initiated
01350 case BOTH_LK_DL_DL_T_L_2: //lock if I'm using dual vs. dual and other initiated
01351 case BOTH_LK_DL_S_S_L_1: //lock if I'm using dual vs. a single
01352 case BOTH_LK_DL_S_T_L_1: //lock if I'm using dual vs. a single
01353 case BOTH_LK_DL_ST_S_L_1: //lock if I'm using dual vs. a staff
01354 case BOTH_LK_DL_ST_T_L_1: //lock if I'm using dual vs. a staff
01355 case BOTH_LK_S_S_S_L_1: //lock if I'm using single vs. a single and I initiated
01356 case BOTH_LK_S_S_T_L_2: //lock if I'm using single vs. a single and other initiated
01357 case BOTH_LK_ST_S_S_L_1: //lock if I'm using staff vs. a single
01358 case BOTH_LK_ST_S_T_L_1: //lock if I'm using staff vs. a single
01359 case BOTH_LK_ST_ST_T_L_1: //lock if I'm using staff vs. a staff and I initiated
01360 case BOTH_LK_ST_ST_T_L_2: //lock if I'm using staff vs. a staff and other initiated
01361 if ( winOrLose == SABERLOCK_WIN )
01362 {
01363 increment = qtrue;
01364 }
01365 else
01366 {
01367 increment = qfalse;
01368 }
01369 break;
01370
01371 //decrement to win:
01372 case BOTH_LK_S_DL_S_L_1: //lock if I'm using single vs. a dual
01373 case BOTH_LK_S_DL_T_L_1: //lock if I'm using single vs. a dual
01374 case BOTH_LK_S_S_S_L_2: //lock if I'm using single vs. a single and other intitiated
01375 case BOTH_LK_S_S_T_L_1: //lock if I'm using single vs. a single and I initiated
01376 case BOTH_LK_S_ST_S_L_1: //lock if I'm using single vs. a staff
01377 case BOTH_LK_S_ST_T_L_1: //lock if I'm using single vs. a staff
01378 case BOTH_LK_ST_DL_S_L_1: //lock if I'm using staff vs. dual
01379 case BOTH_LK_ST_DL_T_L_1: //lock if I'm using staff vs. dual
01380 case BOTH_LK_ST_ST_S_L_1: //lock if I'm using staff vs. a staff and I initiated
01381 case BOTH_LK_ST_ST_S_L_2: //lock if I'm using staff vs. a staff and other initiated
01382 if ( winOrLose == SABERLOCK_WIN )
01383 {
01384 increment = qfalse;
01385 }
01386 else
01387 {
01388 increment = qtrue;
01389 }
01390 break;
01391 default:
01392 break;
01393 }
01394 return increment;
01395 }
|
|
|
Definition at line 415 of file bg_panimate.c. References LS_A1_SPECIAL, LS_A2_SPECIAL, LS_A3_SPECIAL, LS_DUAL_SPIN_PROTECT, LS_JUMPATTACK_DUAL, LS_SPINATTACK, LS_SPINATTACK_DUAL, LS_STAFF_SOULCAL, qboolean, qfalse, and qtrue. Referenced by saberCheckKnockdown_Smashed().
00416 {
00417 switch ( move )
00418 {
00419 case LS_SPINATTACK_DUAL:
00420 case LS_SPINATTACK:
00421 case LS_DUAL_SPIN_PROTECT:
00422 case LS_STAFF_SOULCAL:
00423 case LS_A1_SPECIAL:
00424 case LS_A2_SPECIAL:
00425 case LS_A3_SPECIAL:
00426 case LS_JUMPATTACK_DUAL:
00427 return qtrue;
00428 break;
00429 }
00430 return qfalse;
00431 }
|
|
|
|
|
Definition at line 219 of file bg_panimate.c. References LS_A_T2B, LS_A_TL2BR, qboolean, qfalse, and qtrue.
00220 {
00221 if ( move >= LS_A_TL2BR && move <= LS_A_T2B )
00222 {
00223 return qtrue;
00224 }
00225 return qfalse;
00226 }
|
|
|
Definition at line 1202 of file bg_panimate.c. References PM_SaberInReturn(), and qboolean.
01203 {
01204 return PM_SaberInReturn( move );
01205 }
|
|
|
Definition at line 1619 of file bg_panimate.c. References PM_SaberInReturn(), PM_SaberInStart(), PM_SaberInTransition(), qboolean, qfalse, and qtrue. Referenced by PM_SaberAttackForMovement(), and WP_SaberStartMissileBlockCheck().
01620 {
01621 if ( PM_SaberInStart( move ) )
01622 {
01623 return qtrue;
01624 }
01625 else if ( PM_SaberInTransition( move ) )
01626 {
01627 return qtrue;
01628 }
01629 else if ( PM_SaberInReturn( move ) )
01630 {
01631 return qtrue;
01632 }
01633 return qfalse;
01634 }
|
|
|
Definition at line 201 of file bg_pmove.c. References playerState_s::fd, playerState_t, qboolean, qfalse, qtrue, forcedata_s::saberAnimLevelBase, playerState_s::saberHolstered, SS_DUAL, and SS_STAFF. Referenced by Jedi_SaberBlockGo(), NPC_BSGrenadier_Attack(), PM_GetSaberStance(), PM_VehicleWeaponAnimate(), PM_WeaponLightsaber(), SaberUpdateSelf(), WP_SaberCanBlock(), WP_SaberPositionUpdate(), WP_SabersIntersect(), and WP_SaberStartMissileBlockCheck().
00202 {
00203 if ( !ps->saberHolstered )
00204 {
00205 return qfalse;
00206 }
00207 if ( ps->fd.saberAnimLevelBase == SS_DUAL
00208 || ps->fd.saberAnimLevelBase == SS_STAFF )
00209 {
00210 if ( ps->saberHolstered < 2 )
00211 {
00212 return qfalse;
00213 }
00214 }
00215 return qtrue;
00216 }
|
|
|
Definition at line 1074 of file bg_panimate.c. References BOTH_STABDOWN, BOTH_STABDOWN_DUAL, BOTH_STABDOWN_STAFF, qboolean, qfalse, and qtrue.
01075 {
01076 switch ( anim )
01077 {
01078 case BOTH_STABDOWN:
01079 case BOTH_STABDOWN_STAFF:
01080 case BOTH_STABDOWN_DUAL:
01081 return qtrue;
01082 }
01083 return qfalse;
01084 }
|
|
|
|
|
Definition at line 6233 of file w_saber.c. References G_FreeEntity(), G_RunObject(), gentity_t, level, gentity_s::nextthink, gentity_s::speed, gentity_s::think, and level_locals_t::time. Referenced by MakeDeadSaber().
06234 {
06235 if (saberent->speed < level.time)
06236 {
06237 saberent->think = G_FreeEntity;
06238 saberent->nextthink = level.time;
06239 return;
06240 }
06241
06242 G_RunObject(saberent);
06243 }
|
|
|
Definition at line 6340 of file w_saber.c. References BUTTON_ATTACK, usercmd_s::buttons, CHAN_BODY, gentity_s::client, clientPersistant_t::cmd, entityShared_t::contents, CONTENTS_LIGHTSABER, ENTITYNUM_NONE, playerState_s::fd, forcedata_s::forcePowerLevel, FP_SABER_OFFENSE, g_entities, G_FreeEntity(), G_RunObject(), G_Sound(), G_SoundIndex(), gentity_s::genericValue5, gentity_t, gentity_s::health, gentity_s::inuse, level, entityState_s::loopIsSoundset, entityState_s::loopSound, MakeDeadSaber(), MAX_LEAVE_TIME, gentity_s::nextthink, NULL, entityState_s::number, entityShared_t::ownerNum, gclient_s::pers, playerState_s::pm_flags, PMF_FOLLOW, gclient_s::ps, qboolean, qfalse, qtrue, gentity_s::r, gentity_s::s, gclient_s::saber, saberBackToOwner(), playerState_s::saberCanThrow, playerState_s::saberEntityNum, playerState_s::saberEntityState, SaberGotHit(), playerState_s::saberInFlight, gclient_s::saberKnockedTime, saberReactivate(), gclient_s::saberStoredIndex, playerState_s::saberThrowDelay, SaberUpdateSelf(), gclient_s::sess, clientSession_t::sessionTeam, saberInfo_t::soundOn, gentity_s::speed, SVF_NOCLIENT, entityShared_t::svFlags, TEAM_SPECTATOR, gentity_s::think, level_locals_t::time, gentity_s::touch, and WP_SaberRemoveG2Model(). Referenced by saberKnockDown().
06341 {
06342 gentity_t *saberOwn = NULL;
06343 qboolean notDisowned = qfalse;
06344 qboolean pullBack = qfalse;
06345
06346 saberent->nextthink = level.time;
06347
06348 if (saberent->r.ownerNum == ENTITYNUM_NONE)
06349 {
06350 MakeDeadSaber(saberent);
06351
06352 saberent->think = G_FreeEntity;
06353 saberent->nextthink = level.time;
06354 return;
06355 }
06356
06357 saberOwn = &g_entities[saberent->r.ownerNum];
06358
06359 if (!saberOwn ||
06360 !saberOwn->inuse ||
06361 !saberOwn->client ||
06362 saberOwn->client->sess.sessionTeam == TEAM_SPECTATOR ||
06363 (saberOwn->client->ps.pm_flags & PMF_FOLLOW))
06364 {
06365 MakeDeadSaber(saberent);
06366
06367 saberent->think = G_FreeEntity;
06368 saberent->nextthink = level.time;
06369 return;
06370 }
06371
06372 if (saberOwn->client->ps.saberEntityNum)
06373 {
06374 if (saberOwn->client->ps.saberEntityNum == saberent->s.number)
06375 { //owner shouldn't have this set if we're thinking in here. Must've fallen off a cliff and instantly respawned or something.
06376 notDisowned = qtrue;
06377 }
06378 else
06379 { //This should never happen, but just in case..
06380 assert(!"ULTRA BAD THING");
06381 MakeDeadSaber(saberent);
06382
06383 saberent->think = G_FreeEntity;
06384 saberent->nextthink = level.time;
06385 return;
06386 }
06387 }
06388
06389 if (notDisowned || saberOwn->health < 1 || !saberOwn->client->ps.fd.forcePowerLevel[FP_SABER_OFFENSE])
06390 { //He's dead, just go back to our normal saber status
06391 saberOwn->client->ps.saberEntityNum = saberOwn->client->saberStoredIndex;
06392
06393 //MakeDeadSaber(saberent); //spawn a dead saber on top of where we are now. The "bodyqueue" method.
06394 //Actually this will get taken care of when the thrown saber func sees we're dead.
06395
06396 #ifdef _DEBUG
06397 if (saberOwn->client->saberStoredIndex != saberent->s.number)
06398 { //I'm paranoid.
06399 assert(!"Bad saber index!!!");
06400 }
06401 #endif
06402
06403 saberReactivate(saberent, saberOwn);
06404
06405 if (saberOwn->health < 1)
06406 {
06407 saberOwn->client->ps.saberInFlight = qfalse;
06408 MakeDeadSaber(saberent);
06409 }
06410
06411 saberent->touch = SaberGotHit;
06412 saberent->think = SaberUpdateSelf;
06413 saberent->genericValue5 = 0;
06414 saberent->nextthink = level.time;
06415
06416 saberent->r.svFlags |= (SVF_NOCLIENT);
06417 //saberent->r.contents = CONTENTS_LIGHTSABER;
06418 saberent->s.loopSound = 0;
06419 saberent->s.loopIsSoundset = qfalse;
06420
06421 if (saberOwn->health > 0)
06422 { //only set this if he's alive. If dead we want to reflect the lack of saber on the corpse, as he died with his saber out.
06423 saberOwn->client->ps.saberInFlight = qfalse;
06424 WP_SaberRemoveG2Model( saberent );
06425 }
06426 saberOwn->client->ps.saberEntityState = 0;
06427 saberOwn->client->ps.saberThrowDelay = level.time + 500;
06428 saberOwn->client->ps.saberCanThrow = qfalse;
06429
06430 return;
06431 }
06432
06433 if (saberOwn->client->saberKnockedTime < level.time && (saberOwn->client->pers.cmd.buttons & BUTTON_ATTACK))
06434 { //He wants us back
06435 pullBack = qtrue;
06436 }
06437 else if ((level.time - saberOwn->client->saberKnockedTime) > MAX_LEAVE_TIME)
06438 { //Been sitting around for too long, go back no matter what he wants.
06439 pullBack = qtrue;
06440 }
06441
06442 if (pullBack)
06443 { //Get going back to the owner.
06444 saberOwn->client->ps.saberEntityNum = saberOwn->client->saberStoredIndex;
06445
06446 #ifdef _DEBUG
06447 if (saberOwn->client->saberStoredIndex != saberent->s.number)
06448 { //I'm paranoid.
06449 assert(!"Bad saber index!!!");
06450 }
06451 #endif
06452 saberReactivate(saberent, saberOwn);
06453
06454 saberent->touch = SaberGotHit;
06455
06456 saberent->think = saberBackToOwner;
06457 saberent->speed = 0;
06458 saberent->genericValue5 = 0;
06459 saberent->nextthink = level.time;
06460
06461 saberent->r.contents = CONTENTS_LIGHTSABER;
06462
06463 G_Sound( saberOwn, CHAN_BODY, G_SoundIndex( "sound/weapons/force/pull.wav" ) );
06464 if (saberOwn->client->saber[0].soundOn)
06465 {
06466 G_Sound( saberent, CHAN_BODY, saberOwn->client->saber[0].soundOn );
06467 }
06468 if (saberOwn->client->saber[1].soundOn)
06469 {
06470 G_Sound( saberOwn, CHAN_BODY, saberOwn->client->saber[1].soundOn );
06471 }
06472
06473 return;
06474 }
06475
06476 G_RunObject(saberent);
06477 saberent->nextthink = level.time;
06478 }
|
|
||||||||||||
|
Definition at line 80 of file w_saber.c. References gentity_s::client, playerState_s::duelIndex, playerState_s::duelInProgress, g_friendlyFire, g_gametype, gentity_t, GT_TEAM, vmCvar_t::integer, gentity_s::inuse, entityState_s::number, OnSameTeam(), gclient_s::ps, qboolean, qfalse, qtrue, and gentity_s::s. Referenced by PM_VehicleImpact().
00081 {
00082 if (!self->inuse || !enemy->inuse || !self->client || !enemy->client)
00083 {
00084 return qfalse;
00085 }
00086
00087 if (self->client->ps.duelInProgress && self->client->ps.duelIndex != enemy->s.number)
00088 { //dueling but not with this person
00089 return qfalse;
00090 }
00091
00092 if (enemy->client->ps.duelInProgress && enemy->client->ps.duelIndex != self->s.number)
00093 { //other guy dueling but not with me
00094 return qfalse;
00095 }
00096
00097 if (g_gametype.integer < GT_TEAM)
00098 { //ok, sure
00099 return qtrue;
00100 }
00101
00102 if (g_friendlyFire.integer)
00103 { //if ff on then can inflict damage normally on teammates
00104 return qtrue;
00105 }
00106
00107 if (OnSameTeam(self, enemy))
00108 { //ff not on, don't hurt teammates
00109 return qfalse;
00110 }
00111
00112 return qtrue;
00113 }
|
|
||||||||||||||||
|
Definition at line 44 of file w_saber.c. References G_TestLine(), vec3_t, and VectorCopy. Referenced by SaberUpdateSelf().
00045 {
00046 vec3_t start;
00047 vec3_t end;
00048
00049 float x = maxs[0] - mins[0];
00050 float y = maxs[1] - mins[1];
00051
00052 // top of box
00053 VectorCopy(maxs, start);
00054 VectorCopy(maxs, end);
00055 start[0] -= x;
00056 G_TestLine(start, end, 0x00000ff, duration);
00057 end[0] = start[0];
00058 end[1] -= y;
00059 G_TestLine(start, end, 0x00000ff, duration);
00060 start[1] = end[1];
00061 start[0] += x;
00062 G_TestLine(start, end, 0x00000ff, duration);
00063 G_TestLine(start, maxs, 0x00000ff, duration);
00064 // bottom of box
00065 VectorCopy(mins, start);
00066 VectorCopy(mins, end);
00067 start[0] += x;
00068 G_TestLine(start, end, 0x00000ff, duration);
00069 end[0] = start[0];
00070 end[1] += y;
00071 G_TestLine(start, end, 0x00000ff, duration);
00072 start[1] = end[1];
00073 start[0] -= x;
00074 G_TestLine(start, end, 0x00000ff, duration);
00075 G_TestLine(start, mins, 0x00000ff, duration);
00076 }
|
|
|
Definition at line 2817 of file g_mover.c. References gentity_s::classname, ENTITYNUM_WORLD, g_entities, gentity_t, Q_stricmp(), qboolean, qfalse, qtrue, gentity_s::r, SVF_GLASS_BRUSH, and entityShared_t::svFlags. Referenced by NAV_TestBestNode(), vmMain(), and WP_SaberRadiusDamage().
02818 {
02819 gentity_t *ent;
02820
02821 if ( entityNum < 0 || entityNum >= ENTITYNUM_WORLD )
02822 {
02823 return qfalse;
02824 }
02825
02826 ent = &g_entities[entityNum];
02827 if ( (ent->r.svFlags & SVF_GLASS_BRUSH) )
02828 {
02829 return qtrue;
02830 }
02831 /*
02832 if ( (ent->svFlags&SVF_BBRUSH) )
02833 {
02834 return qtrue;
02835 }
02836 */
02837 if ( !Q_stricmp( "func_breakable", ent->classname ) )
02838 {
02839 return qtrue;
02840 }
02841
02842 if ( !Q_stricmp( "misc_model_breakable", ent->classname ) )
02843 {
02844 return qtrue;
02845 }
02846 if ( !Q_stricmp( "misc_maglock", ent->classname ) )
02847 {
02848 return qtrue;
02849 }
02850
02851 return qfalse;
02852 }
|
|
||||||||||||||||||||
|
Definition at line 1707 of file NPC_utils.c. References gentity_s::client, entityShared_t::currentAngles, entityShared_t::currentOrigin, gentity_t, gentity_s::ghoul2, gentity_s::inuse, level, gentity_s::modelScale, NULL, ORIGIN, gclient_s::ps, gentity_s::r, level_locals_t::time, trap_G2API_GetBoltMatrix(), vec3_t, VectorCopy, VectorSet, playerState_s::viewangles, and YAW. Referenced by NPC_EntRangeFromBolt(), NPC_GetEntsNearBolt(), and Rancor_Attack().
01708 {
01709 mdxaBone_t boltMatrix;
01710 vec3_t result, angles;
01711
01712 if (!self || !self->inuse)
01713 {
01714 return;
01715 }
01716
01717 if (self->client)
01718 { //clients don't actually even keep r.currentAngles maintained
01719 VectorSet(angles, 0, self->client->ps.viewangles[YAW], 0);
01720 }
01721 else
01722 {
01723 VectorSet(angles, 0, self->r.currentAngles[YAW], 0);
01724 }
01725
01726 if ( !self->ghoul2 )
01727 {
01728 return;
01729 }
01730
01731 trap_G2API_GetBoltMatrix( self->ghoul2, modelIndex,
01732 boltIndex,
01733 &boltMatrix, angles, self->r.currentOrigin, level.time,
01734 NULL, self->modelScale );
01735 if ( pos )
01736 {
01737 BG_GiveMeVectorFromMatrix( &boltMatrix, ORIGIN, result );
01738 VectorCopy( result, pos );
01739 }
01740 }
|
|
|
Definition at line 2208 of file w_saber.c. References LS_K1_BL, LS_K1_BR, LS_K1_T_, LS_K1_TL, LS_K1_TR, LS_PARRY_LL, LS_PARRY_LR, LS_PARRY_UL, LS_PARRY_UP, and LS_PARRY_UR.
02209 {
02210 //FIXME: need actual anims for this
02211 //FIXME: need to know which side of the saber was hit! For now, we presume the saber gets knocked away from the center
02212 switch ( move )
02213 {
02214 case LS_PARRY_UP:
02215 return LS_K1_T_;//push up
02216 break;
02217 case LS_PARRY_UR:
02218 default://case LS_READY:
02219 return LS_K1_TR;//push up, slightly to right
02220 break;
02221 case LS_PARRY_UL:
02222 return LS_K1_TL;//push up and to left
02223 break;
02224 case LS_PARRY_LR:
02225 return LS_K1_BR;//push down and to left
02226 break;
02227 case LS_PARRY_LL:
02228 return LS_K1_BL;//push down and to right
02229 break;
02230 }
02231 }
|
|
|
Definition at line 4327 of file g_combat.c. References BG_KnockDownable(), gentity_s::client, playerState_s::forceDodgeAnim, playerState_s::forceHandExtend, playerState_s::forceHandExtendTime, gentity_t, HANDEXTEND_KNOCKDOWN, level, gclient_s::ps, qfalse, playerState_s::quickerGetup, and level_locals_t::time.
04328 {
04329 if ( victim && victim->client && BG_KnockDownable(&victim->client->ps) )
04330 {
04331 victim->client->ps.forceHandExtend = HANDEXTEND_KNOCKDOWN;
04332 victim->client->ps.forceDodgeAnim = 0;
04333 victim->client->ps.forceHandExtendTime = level.time + 1100;
04334 victim->client->ps.quickerGetup = qfalse;
04335 }
04336 }
|
|
||||||||||||||||||||||||
|
Definition at line 1092 of file w_saber.c. References BOTH_LK_DL_DL_S_B_1_L, BOTH_LK_DL_DL_S_L_2, BOTH_LK_DL_DL_T_L_2, BOTH_LK_DL_S_S_B_1_L, BOTH_LK_DL_ST_S_B_1_L, BOTH_LK_S_DL_S_B_1_L, BOTH_LK_S_S_S_B_1_L, BOTH_LK_S_S_S_L_2, BOTH_LK_S_S_T_L_2, BOTH_LK_S_ST_S_B_1_L, BOTH_LK_ST_DL_S_B_1_L, BOTH_LK_ST_S_S_B_1_L, BOTH_LK_ST_ST_S_B_1_L, BOTH_LK_ST_ST_S_L_2, BOTH_LK_ST_ST_T_L_2, SABERLOCK_LOCK, SABERLOCK_LOSE, SABERLOCK_SUPERBREAK, SABERLOCK_TOP, SABERLOCK_WIN, SS_DUAL, SS_FAST, SS_STAFF, and SS_TAVION.
01093 {
01094 int baseAnim = -1;
01095 if ( lockOrBreakOrSuperBreak == SABERLOCK_LOCK )
01096 {//special case: if we're using the same style and locking
01097 if ( attackerSaberStyle == defenderSaberStyle
01098 || (attackerSaberStyle>=SS_FAST&&attackerSaberStyle<=SS_TAVION&&defenderSaberStyle>=SS_FAST&&defenderSaberStyle<=SS_TAVION) )
01099 {//using same style
01100 if ( winOrLose == SABERLOCK_LOSE )
01101 {//you want the defender's stance...
01102 switch ( defenderSaberStyle )
01103 {
01104 case SS_DUAL:
01105 if ( topOrSide == SABERLOCK_TOP )
01106 {
01107 baseAnim = BOTH_LK_DL_DL_T_L_2;
01108 }
01109 else
01110 {
01111 baseAnim = BOTH_LK_DL_DL_S_L_2;
01112 }
01113 break;
01114 case SS_STAFF:
01115 if ( topOrSide == SABERLOCK_TOP )
01116 {
01117 baseAnim = BOTH_LK_ST_ST_T_L_2;
01118 }
01119 else
01120 {
01121 baseAnim = BOTH_LK_ST_ST_S_L_2;
01122 }
01123 break;
01124 default:
01125 if ( topOrSide == SABERLOCK_TOP )
01126 {
01127 baseAnim = BOTH_LK_S_S_T_L_2;
01128 }
01129 else
01130 {
01131 baseAnim = BOTH_LK_S_S_S_L_2;
01132 }
01133 break;
01134 }
01135 }
01136 }
01137 }
01138 if ( baseAnim == -1 )
01139 {
01140 switch ( attackerSaberStyle )
01141 {
01142 case SS_DUAL:
01143 switch ( defenderSaberStyle )
01144 {
01145 case SS_DUAL:
01146 baseAnim = BOTH_LK_DL_DL_S_B_1_L;
01147 break;
01148 case SS_STAFF:
01149 baseAnim = BOTH_LK_DL_ST_S_B_1_L;
01150 break;
01151 default://single
01152 baseAnim = BOTH_LK_DL_S_S_B_1_L;
01153 break;
01154 }
01155 break;
01156 case SS_STAFF:
01157 switch ( defenderSaberStyle )
01158 {
01159 case SS_DUAL:
01160 baseAnim = BOTH_LK_ST_DL_S_B_1_L;
01161 break;
01162 case SS_STAFF:
01163 baseAnim = BOTH_LK_ST_ST_S_B_1_L;
01164 break;
01165 default://single
01166 baseAnim = BOTH_LK_ST_S_S_B_1_L;
01167 break;
01168 }
01169 break;
01170 default://single
01171 switch ( defenderSaberStyle )
01172 {
01173 case SS_DUAL:
01174 baseAnim = BOTH_LK_S_DL_S_B_1_L;
01175 break;
01176 case SS_STAFF:
01177 baseAnim = BOTH_LK_S_ST_S_B_1_L;
01178 break;
01179 default://single
01180 baseAnim = BOTH_LK_S_S_S_B_1_L;
01181 break;
01182 }
01183 break;
01184 }
01185 //side lock or top lock?
01186 if ( topOrSide == SABERLOCK_TOP )
01187 {
01188 baseAnim += 5;
01189 }
01190 //lock, break or superbreak?
01191 if ( lockOrBreakOrSuperBreak == SABERLOCK_LOCK )
01192 {
01193 baseAnim += 2;
01194 }
01195 else
01196 {//a break or superbreak
01197 if ( lockOrBreakOrSuperBreak == SABERLOCK_SUPERBREAK )
01198 {
01199 baseAnim += 3;
01200 }
01201 //winner or loser?
01202 if ( winOrLose == SABERLOCK_WIN )
01203 {
01204 baseAnim += 1;
01205 }
01206 }
01207 }
01208 return baseAnim;
01209 }
|
|
||||||||||||||||||||||||||||
|
Definition at line 5283 of file w_saber.c. References AngleVectors(), saberTrail_t::base, BG_InSpecialJump(), BG_SaberInAttack(), BG_SaberInSpecialAttack(), BG_SpinningSaberAnim(), saberInfo_t::blade, gentity_s::client, DotProduct, fabs(), gentity_t, saberTrail_t::lastTime, bladeInfo_t::lengthMax, LerpAngle(), level, MAX_SABER_SWING_INC, NULL, gclient_s::ps, qboolean, qfalse, qtrue, gclient_s::saber, playerState_s::saberMove, level_locals_t::time, saberTrail_t::tip, playerState_s::torsoAnim, bladeInfo_t::trail, vec3_t, vectoangles(), VectorCompare2(), VectorCopy, VectorMA, VectorNormalize(), and VectorSubtract. Referenced by WP_SaberPositionUpdate().
05284 {
05285 vec3_t baseOld, endOld;
05286 vec3_t mp1, mp2;
05287 vec3_t md1, md2;
05288
05289 if ( (level.time-self->client->saber[saberNum].blade[bladeNum].trail.lastTime) > 100 )
05290 {//no valid last pos, use current
05291 VectorCopy(baseNew, baseOld);
05292 VectorCopy(endNew, endOld);
05293 }
05294 else
05295 {//trace from last pos
05296 VectorCopy( self->client->saber[saberNum].blade[bladeNum].trail.base, baseOld );
05297 VectorCopy( self->client->saber[saberNum].blade[bladeNum].trail.tip, endOld );
05298 }
05299
05300 VectorCopy( baseOld, mp1 );
05301 VectorCopy( baseNew, mp2 );
05302 VectorSubtract( endOld, baseOld, md1 );
05303 VectorNormalize( md1 );
05304 VectorSubtract( endNew, baseNew, md2 );
05305 VectorNormalize( md2 );
05306
05307 saberHitWall = qfalse;
05308 saberHitSaber = qfalse;
05309 saberHitFraction = 1.0f;
05310 if ( VectorCompare2( baseOld, baseNew ) && VectorCompare2( endOld, endNew ) )
05311 {//no diff
05312 CheckSaberDamage( self, saberNum, bladeNum, baseNew, endNew, qfalse, clipmask, qfalse );
05313 }
05314 else
05315 {//saber moved, lerp
05316 float step = 8, stepsize = 8;//aveLength,
05317 vec3_t ma1, ma2, md2ang, curBase1, curBase2;
05318 int xx;
05319 vec3_t curMD1, curMD2;//, mdDiff, dirDiff;
05320 float dirInc, curDirFrac;
05321 vec3_t baseDiff, bladePointOld, bladePointNew;
05322 qboolean extrapolate = qtrue;
05323
05324 //do the trace at the base first
05325 VectorCopy( baseOld, bladePointOld );
05326 VectorCopy( baseNew, bladePointNew );
05327 CheckSaberDamage( self, saberNum, bladeNum, bladePointOld, bladePointNew, qfalse, clipmask, qtrue );
05328
05329 //if hit a saber, shorten rest of traces to match
05330 if ( saberHitFraction < 1.0f )
05331 {
05332 //adjust muzzleDir...
05333 vec3_t ma1, ma2;
05334 vectoangles( md1, ma1 );
05335 vectoangles( md2, ma2 );
05336 for ( xx = 0; xx < 3; xx++ )
05337 {
05338 md2ang[xx] = LerpAngle( ma1[xx], ma2[xx], saberHitFraction );
05339 }
05340 AngleVectors( md2ang, md2, NULL, NULL );
05341 //shorten the base pos
05342 VectorSubtract( mp2, mp1, baseDiff );
05343 VectorMA( mp1, saberHitFraction, baseDiff, baseNew );
05344 VectorMA( baseNew, self->client->saber[saberNum].blade[bladeNum].lengthMax, md2, endNew );
05345 }
05346
05347 //If the angle diff in the blade is high, need to do it in chunks of 33 to avoid flattening of the arc
05348 if ( BG_SaberInAttack( self->client->ps.saberMove )
05349 || BG_SaberInSpecialAttack( self->client->ps.torsoAnim )
05350 || BG_SpinningSaberAnim( self->client->ps.torsoAnim )
05351 || BG_InSpecialJump( self->client->ps.torsoAnim ) )
05352 //|| (g_timescale->value<1.0f&&BG_SaberInTransitionAny( ent->client->ps.saberMove )) )
05353 {
05354 curDirFrac = DotProduct( md1, md2 );
05355 }
05356 else
05357 {
05358 curDirFrac = 1.0f;
05359 }
05360 //NOTE: if saber spun at least 180 degrees since last damage trace, this is not reliable...!
05361 if ( fabs(curDirFrac) < 1.0f - MAX_SABER_SWING_INC )
05362 {//the saber blade spun more than 33 degrees since the last damage trace
05363 curDirFrac = dirInc = 1.0f/((1.0f - curDirFrac)/MAX_SABER_SWING_INC);
05364 }
05365 else
05366 {
05367 curDirFrac = 1.0f;
05368 dirInc = 0.0f;
05369 }
05370 //qboolean hit_saber = qfalse;
05371
05372 vectoangles( md1, ma1 );
05373 vectoangles( md2, ma2 );
05374
05375 //VectorSubtract( md2, md1, mdDiff );
05376 VectorCopy( md1, curMD2 );
05377 VectorCopy( baseOld, curBase2 );
05378
05379 while ( 1 )
05380 {
05381 VectorCopy( curMD2, curMD1 );
05382 VectorCopy( curBase2, curBase1 );
05383 if ( curDirFrac >= 1.0f )
05384 {
05385 VectorCopy( md2, curMD2 );
05386 VectorCopy( baseNew, curBase2 );
05387 }
05388 else
05389 {
05390 for ( xx = 0; xx < 3; xx++ )
05391 {
05392 md2ang[xx] = LerpAngle( ma1[xx], ma2[xx], curDirFrac );
05393 }
05394 AngleVectors( md2ang, curMD2, NULL, NULL );
05395 //VectorMA( md1, curDirFrac, mdDiff, curMD2 );
05396 VectorSubtract( baseNew, baseOld, baseDiff );
05397 VectorMA( baseOld, curDirFrac, baseDiff, curBase2 );
05398 }
05399 // Move up the blade in intervals of stepsize
05400 for ( step = stepsize; step <= self->client->saber[saberNum].blade[bladeNum].lengthMax /*&& step < self->client->saber[saberNum].blade[bladeNum].lengthOld*/; step += stepsize )
05401 {
05402 VectorMA( curBase1, step, curMD1, bladePointOld );
05403 VectorMA( curBase2, step, curMD2, bladePointNew );
05404
05405 if ( step+stepsize >= self->client->saber[saberNum].blade[bladeNum].lengthMax )
05406 {
05407 extrapolate = qfalse;
05408 }
05409 //do the damage trace
05410 CheckSaberDamage( self, saberNum, bladeNum, bladePointOld, bladePointNew, qfalse, clipmask, extrapolate );
05411 /*
05412 if ( WP_SaberDamageForTrace( ent->s.number, bladePointOld, bladePointNew, baseDamage, curMD2,
05413 qfalse, entPowerLevel, ent->client->ps.saber[saberNum].type, qtrue,
05414 saberNum, bladeNum ) )
05415 {
05416 hit_wall = qtrue;
05417 }
05418 */
05419
05420 //if hit a saber, shorten rest of traces to match
05421 if ( saberHitFraction < 1.0f )
05422 {
05423 vec3_t curMA1, curMA2;
05424 //adjust muzzle endpoint
05425 VectorSubtract( mp2, mp1, baseDiff );
05426 VectorMA( mp1, saberHitFraction, baseDiff, baseNew );
05427 VectorMA( baseNew, self->client->saber[saberNum].blade[bladeNum].lengthMax, curMD2, endNew );
05428 //adjust muzzleDir...
05429 vectoangles( curMD1, curMA1 );
05430 vectoangles( curMD2, curMA2 );
05431 for ( xx = 0; xx < 3; xx++ )
05432 {
05433 md2ang[xx] = LerpAngle( curMA1[xx], curMA2[xx], saberHitFraction );
05434 }
05435 AngleVectors( md2ang, curMD2, NULL, NULL );
05436 saberHitSaber = qtrue;
05437 }
05438 if (saberHitWall)
05439 {
05440 break;
05441 }
05442 }
05443 if ( saberHitWall || saberHitSaber )
05444 {
05445 break;
05446 }
05447 if ( curDirFrac >= 1.0f )
05448 {
05449 break;
05450 }
05451 else
05452 {
05453 curDirFrac += dirInc;
05454 if ( curDirFrac >= 1.0f )
05455 {
05456 curDirFrac = 1.0f;
05457 }
05458 }
05459 }
05460
05461 //do the trace at the end last
05462 //Special check- adjust for length of blade not being a multiple of 12
05463 /*
05464 aveLength = (ent->client->ps.saber[saberNum].blade[bladeNum].lengthOld + ent->client->ps.saber[saberNum].blade[bladeNum].length)/2;
05465 if ( step > aveLength )
05466 {//less dmg if the last interval was not stepsize
05467 tipDmgMod = (stepsize-(step-aveLength))/stepsize;
05468 }
05469 //NOTE: since this is the tip, we do not extrapolate the extra 16
05470 if ( WP_SaberDamageForTrace( ent->s.number, endOld, endNew, tipDmgMod*baseDamage, md2,
05471 qfalse, entPowerLevel, ent->client->ps.saber[saberNum].type, qfalse,
05472 saberNum, bladeNum ) )
05473 {
05474 hit_wall = qtrue;
05475 }
05476 */
05477 }
05478 }
|
|
||||||||||||||||||||
|
Definition at line 212 of file ai_wpnav.c. References EV_TESTLINE, G_TempEntity(), gentity_t, entityState_s::origin, entityState_s::origin2, gentity_s::r, gentity_s::s, SVF_BROADCAST, entityShared_t::svFlags, entityState_s::time2, vec3_t, VectorCopy, and entityState_s::weapon. Referenced by AI_RefreshGroup(), BotWaypointRender(), CTFTakesPriority(), G_DebugBoxLines(), UpdateClientRenderinfo(), and WP_SabersIntersect().
00213 {
00214 gentity_t *te;
00215
00216 te = G_TempEntity( start, EV_TESTLINE );
00217 VectorCopy(start, te->s.origin);
00218 VectorCopy(end, te->s.origin2);
00219 te->s.time2 = time;
00220 te->s.weapon = color;
00221 te->r.svFlags |= SVF_BROADCAST;
00222 }
|
|
|
Definition at line 9448 of file w_saber.c. References g_duelWeaponDisable, g_gametype, g_weaponDisable, GT_DUEL, GT_JEDIMASTER, GT_POWERDUEL, vmCvar_t::integer, qboolean, qfalse, qtrue, WP_NONE, WP_NUM_WEAPONS, and WP_SABER. Referenced by CalculateTactician(), ClientSpawn(), FinishSpawningItem(), HolocronUpdate(), SP_misc_holocron(), WP_InitForcePowers(), and WP_SpawnInitForcePowers().
09449 {
09450 int i = 0;
09451 int wDisable = 0;
09452
09453 if (g_gametype.integer == GT_JEDIMASTER)
09454 { //set to 0
09455 return qfalse;
09456 }
09457
09458 if (g_gametype.integer == GT_DUEL || g_gametype.integer == GT_POWERDUEL)
09459 {
09460 wDisable = g_duelWeaponDisable.integer;
09461 }
09462 else
09463 {
09464 wDisable = g_weaponDisable.integer;
09465 }
09466
09467 while (i < WP_NUM_WEAPONS)
09468 {
09469 if (!(wDisable & (1 << i)) &&
09470 i != WP_SABER && i != WP_NONE)
09471 {
09472 return qfalse;
09473 }
09474
09475 i++;
09476 }
09477
09478 return qtrue;
09479 }
|
|
||||||||||||||||||||||||
|
Definition at line 109 of file NPC_senses.c. References AngleDelta(), fabs(), PITCH, qboolean, qfalse, qtrue, vec3_t, vectoangles(), VectorSubtract, and YAW. Referenced by InFOV2(), NPC_BSGrenadier_Attack(), Rancor_Combat(), Wampa_Combat(), and WP_SaberStartMissileBlockCheck().
00110 {
00111 vec3_t deltaVector, angles, deltaAngles;
00112
00113 VectorSubtract ( spot, from, deltaVector );
00114 vectoangles ( deltaVector, angles );
00115
00116 deltaAngles[PITCH] = AngleDelta ( fromAngles[PITCH], angles[PITCH] );
00117 deltaAngles[YAW] = AngleDelta ( fromAngles[YAW], angles[YAW] );
00118
00119 if ( fabs ( deltaAngles[PITCH] ) <= vFOV && fabs ( deltaAngles[YAW] ) <= hFOV )
00120 {
00121 return qtrue;
00122 }
00123
00124 return qfalse;
00125 }
|
|
||||||||||||||||||||
|
Definition at line 82 of file NPC_senses.c. References AngleVectors(), DotProduct, NULL, qboolean, vec3_t, VectorCopy, VectorNormalize(), and VectorSubtract. Referenced by DoGripAction(), FindGenericEnemyIndex(), NPC_BSGM_Attack(), SeekerDroneUpdate(), WP_SaberCanBlock(), and WP_SabersCheckLock().
00083 {
00084 vec3_t dir, forward, angles;
00085 float dot;
00086
00087 VectorSubtract( spot, from, dir );
00088 dir[2] = 0;
00089 VectorNormalize( dir );
00090
00091 VectorCopy( fromAngles, angles );
00092 angles[0] = 0;
00093 AngleVectors( angles, forward, NULL, NULL );
00094
00095 dot = DotProduct( dir, forward );
00096
00097 return (dot > threshHold);
00098 }
|
|
|
||||||||||||||||||||||||||||
|
Definition at line 2485 of file NPC_AI_Jedi.c. References entityShared_t::absmin, AngleVectors(), BG_InRoll(), BG_SaberInAttack(), BG_SaberInSpecialAttack(), BG_SabersOff(), BG_SpinningSaberAnim(), BLOCKED_LOWER_LEFT, BLOCKED_LOWER_RIGHT, BLOCKED_TOP, BLOCKED_UPPER_LEFT, BLOCKED_UPPER_RIGHT, BOTH_BUTTERFLY_LEFT, BOTH_BUTTERFLY_RIGHT, BOTH_DODGE_BL, BOTH_DODGE_BR, BOTH_DODGE_FL, BOTH_DODGE_FR, BOTH_DODGE_L, BOTH_DODGE_R, CHAN_BODY, CLASS_BOBAFETT, CLASS_TAVION, gentity_s::client, Com_Printf(), entityShared_t::currentOrigin, d_JediAI, d_slowmodeath, DotProduct, gentity_s::enemy, ENTITYNUM_NONE, EV_JUMP, EVASION_CARTWHEEL, EVASION_DODGE, EVASION_DUCK, EVASION_DUCK_PARRY, EVASION_FJUMP, EVASION_JUMP, EVASION_JUMP_PARRY, EVASION_NONE, EVASION_PARRY, evasionType_t, renderInfo_s::eyePoint, fabs(), playerState_s::fd, forcedata_s::forceJumpCharge, forcedata_s::forceJumpZStart, forcedata_s::forcePowerDebounce, forcedata_s::forcePowersActive, forcedata_s::forceRageRecoveryTime, usercmd_s::forwardmove, FP_DRAIN, FP_GRIP, FP_RAGE, FP_SABER_DEFENSE, G_AddEvent(), G_Sound(), G_SoundIndex(), G_StartMatrixEffect(), gentity_t, playerState_s::groundEntityNum, vmCvar_t::integer, Jedi_CheckFlipEvasions(), Jedi_QuickReactions(), Jedi_ReCalcParryTime(), Jedi_SaberBusy(), JUMP_VELOCITY, playerState_s::legsAnim, level, NPC, gentity_s::NPC, gclient_s::NPC_class, NPC_SetAnim(), NULL, entityState_s::number, playerState_s::pm_flags, PM_InKnockDown(), PM_SaberInStart(), playerState_s::pm_time, PMF_DUCKED, PMF_TIME_KNOCKBACK, entityState_s::pos, gclient_s::ps, Q_irand(), qboolean, qfalse, qtrue, gentity_s::r, gNPC_t::rank, RANK_CREWMAN, RANK_LT_JG, gclient_s::renderInfo, usercmd_s::rightmove, gentity_s::s, playerState_s::saberBlocked, playerState_s::saberInFlight, playerState_s::saberMove, SCF_NO_ACROBATICS, gNPC_t::scriptFlags, SETANIM_BOTH, SETANIM_FLAG_HOLD, SETANIM_FLAG_OVERRIDE, level_locals_t::time, TIMER_Done(), TIMER_Set(), TIMER_Start(), playerState_s::torsoAnim, playerState_s::torsoTimer, trajectory_t::trDelta, usercmd_s::upmove, usercmd_t, vec3_t, VectorCopy, VectorNormalize2(), VectorSubtract, playerState_s::velocity, playerState_s::viewangles, entityState_s::weapon, playerState_s::weaponTime, WP_ForcePowerStop(), WP_MissileBlockForBlock(), and WP_SABER. Referenced by WP_SaberStartMissileBlockCheck().
02486 {
02487 vec3_t hitloc, hitdir, diff, fwdangles={0,0,0}, right;
02488 float rightdot;
02489 float zdiff;
02490 int duckChance = 0;
02491 int dodgeAnim = -1;
02492 qboolean saberBusy = qfalse, evaded = qfalse, doDodge = qfalse;
02493 evasionType_t evasionType = EVASION_NONE;
02494
02495 //FIXME: if we don't have our saber in hand, pick the force throw option or a jump or strafe!
02496 //FIXME: reborn don't block enough anymore
02497 if ( !incoming )
02498 {
02499 VectorCopy( pHitloc, hitloc );
02500 VectorCopy( phitDir, hitdir );
02501 //FIXME: maybe base this on rank some? And/or g_spskill?
02502 if ( self->client->ps.saberInFlight )
02503 {//DOH! do non-saber evasion!
02504 saberBusy = qtrue;
02505 }
02506 else if ( Jedi_QuickReactions( self ) )
02507 {//jedi trainer and tavion are must faster at parrying and can do it whenever they like
02508 //Also, on medium, all level 3 people can parry any time and on hard, all level 2 or 3 people can parry any time
02509 }
02510 else
02511 {
02512 saberBusy = Jedi_SaberBusy( self );
02513 }
02514 }
02515 else
02516 {
02517 if ( incoming->s.weapon == WP_SABER )
02518 {//flying lightsaber, face it!
02519 //FIXME: for this to actually work, we'd need to call update angles too?
02520 //Jedi_FaceEntity( self, incoming, qtrue );
02521 }
02522 VectorCopy( incoming->r.currentOrigin, hitloc );
02523 VectorNormalize2( incoming->s.pos.trDelta, hitdir );
02524 }
02525 if ( self->client && self->client->NPC_class == CLASS_BOBAFETT )
02526 {
02527 saberBusy = qtrue;
02528 }
02529
02530 VectorSubtract( hitloc, self->client->renderInfo.eyePoint, diff );
02531 diff[2] = 0;
02532 //VectorNormalize( diff );
02533 fwdangles[1] = self->client->ps.viewangles[1];
02534 // Ultimately we might care if the shot was ahead or behind, but for now, just quadrant is fine.
02535 AngleVectors( fwdangles, NULL, right, NULL );
02536
02537 rightdot = DotProduct(right, diff);// + flrand(-0.10f,0.10f);
02538 //totalHeight = self->client->renderInfo.eyePoint[2] - self->r.absmin[2];
02539 zdiff = hitloc[2] - self->client->renderInfo.eyePoint[2];// + Q_irand(-6,6);
02540
02541 //see if we can dodge if need-be
02542 if ( (dist>16&&(Q_irand( 0, 2 )||saberBusy))
02543 || self->client->ps.saberInFlight
02544 || BG_SabersOff( &self->client->ps )
02545 || self->client->NPC_class == CLASS_BOBAFETT )
02546 {//either it will miss by a bit (and 25% chance) OR our saber is not in-hand OR saber is off
02547 if ( self->NPC && (self->NPC->rank == RANK_CREWMAN || self->NPC->rank >= RANK_LT_JG) )
02548 {//acrobat or fencer or above
02549 if ( self->client->ps.groundEntityNum != ENTITYNUM_NONE &&//on the ground
02550 !(self->client->ps.pm_flags&PMF_DUCKED)&&cmd->upmove>=0&&TIMER_Done( self, "duck" )//not ducking
02551 && !BG_InRoll( &self->client->ps, self->client->ps.legsAnim )//not rolling
02552 && !PM_InKnockDown( &self->client->ps )//not knocked down
02553 && ( self->client->ps.saberInFlight ||
02554 self->client->NPC_class == CLASS_BOBAFETT ||
02555 (!BG_SaberInAttack( self->client->ps.saberMove )//not attacking
02556 && !PM_SaberInStart( self->client->ps.saberMove )//not starting an attack
02557 && !BG_SpinningSaberAnim( self->client->ps.torsoAnim )//not in a saber spin
02558 && !BG_SaberInSpecialAttack( self->client->ps.torsoAnim ))//not in a special attack
02559 )
02560 )
02561 {//need to check all these because it overrides both torso and legs with the dodge
02562 doDodge = qtrue;
02563 }
02564 }
02565 }
02566 // Figure out what quadrant the block was in.
02567 if ( d_JediAI.integer )
02568 {
02569 Com_Printf( "(%d) evading attack from height %4.2f, zdiff: %4.2f, rightdot: %4.2f\n", level.time, hitloc[2]-self->r.absmin[2],zdiff,rightdot);
02570 }
02571
02572 //UL = > -1//-6
02573 //UR = > -6//-9
02574 //TOP = > +6//+4
02575 //FIXME: take FP_SABER_DEFENSE into account here somehow?
02576 if ( zdiff >= -5 )//was 0
02577 {
02578 if ( incoming || !saberBusy )
02579 {
02580 if ( rightdot > 12
02581 || (rightdot > 3 && zdiff < 5)
02582 || (!incoming&&fabs(hitdir[2])<0.25f) )//was normalized, 0.3
02583 {//coming from right
02584 if ( doDodge )
02585 {
02586 if ( self->client->NPC_class == CLASS_BOBAFETT && !Q_irand( 0, 2 ) )
02587 {//roll!
02588 TIMER_Start( self, "duck", Q_irand( 500, 1500 ) );
02589 TIMER_Start( self, "strafeLeft", Q_irand( 500, 1500 ) );
02590 TIMER_Set( self, "strafeRight", 0 );
02591 evasionType = EVASION_DUCK;
02592 evaded = qtrue;
02593 }
02594 else if ( Q_irand( 0, 1 ) )
02595 {
02596 dodgeAnim = BOTH_DODGE_FL;
02597 }
02598 else
02599 {
02600 dodgeAnim = BOTH_DODGE_BL;
02601 }
02602 }
02603 else
02604 {
02605 self->client->ps.saberBlocked = BLOCKED_UPPER_RIGHT;
02606 evasionType = EVASION_PARRY;
02607 if ( self->client->ps.groundEntityNum != ENTITYNUM_NONE )
02608 {
02609 if ( zdiff > 5 )
02610 {
02611 TIMER_Start( self, "duck", Q_irand( 500, 1500 ) );
02612 evasionType = EVASION_DUCK_PARRY;
02613 evaded = qtrue;
02614 if ( d_JediAI.integer )
02615 {
02616 Com_Printf( "duck " );
02617 }
02618 }
02619 else
02620 {
02621 duckChance = 6;
02622 }
02623 }
02624 }
02625 if ( d_JediAI.integer )
02626 {
02627 Com_Printf( "UR block\n" );
02628 }
02629 }
02630 else if ( rightdot < -12
02631 || (rightdot < -3 && zdiff < 5)
02632 || (!incoming&&fabs(hitdir[2])<0.25f) )//was normalized, -0.3
02633 {//coming from left
02634 if ( doDodge )
02635 {
02636 if ( self->client->NPC_class == CLASS_BOBAFETT && !Q_irand( 0, 2 ) )
02637 {//roll!
02638 TIMER_Start( self, "duck", Q_irand( 500, 1500 ) );
02639 TIMER_Start( self, "strafeRight", Q_irand( 500, 1500 ) );
02640 TIMER_Set( self, "strafeLeft", 0 );
02641 evasionType = EVASION_DUCK;
02642 evaded = qtrue;
02643 }
02644 else if ( Q_irand( 0, 1 ) )
02645 {
02646 dodgeAnim = BOTH_DODGE_FR;
02647 }
02648 else
02649 {
02650 dodgeAnim = BOTH_DODGE_BR;
02651 }
02652 }
02653 else
02654 {
02655 self->client->ps.saberBlocked = BLOCKED_UPPER_LEFT;
02656 evasionType = EVASION_PARRY;
02657 if ( self->client->ps.groundEntityNum != ENTITYNUM_NONE )
02658 {
02659 if ( zdiff > 5 )
02660 {
02661 TIMER_Start( self, "duck", Q_irand( 500, 1500 ) );
02662 evasionType = EVASION_DUCK_PARRY;
02663 evaded = qtrue;
02664 if ( d_JediAI.integer )
02665 {
02666 Com_Printf( "duck " );
02667 }
02668 }
02669 else
02670 {
02671 duckChance = 6;
02672 }
02673 }
02674 }
02675 if ( d_JediAI.integer )
02676 {
02677 Com_Printf( "UL block\n" );
02678 }
02679 }
02680 else
02681 {
02682 self->client->ps.saberBlocked = BLOCKED_TOP;
02683 evasionType = EVASION_PARRY;
02684 if ( self->client->ps.groundEntityNum != ENTITYNUM_NONE )
02685 {
02686 duckChance = 4;
02687 }
02688 if ( d_JediAI.integer )
02689 {
02690 Com_Printf( "TOP block\n" );
02691 }
02692 }
02693 evaded = qtrue;
02694 }
02695 else
02696 {
02697 if ( self->client->ps.groundEntityNum != ENTITYNUM_NONE )
02698 {
02699 //duckChance = 2;
02700 TIMER_Start( self, "duck", Q_irand( 500, 1500 ) );
02701 evasionType = EVASION_DUCK;
02702 evaded = qtrue;
02703 if ( d_JediAI.integer )
02704 {
02705 Com_Printf( "duck " );
02706 }
02707 }
02708 }
02709 }
02710 //LL = -22//= -18 to -39
02711 //LR = -23//= -20 to -41
02712 else if ( zdiff > -22 )//was-15 )
02713 {
02714 if ( 1 )//zdiff < -10 )
02715 {//hmm, pretty low, but not low enough to use the low block, so we need to duck
02716 if ( self->client->ps.groundEntityNum != ENTITYNUM_NONE )
02717 {
02718 //duckChance = 2;
02719 TIMER_Start( self, "duck", Q_irand( 500, 1500 ) );
02720 evasionType = EVASION_DUCK;
02721 evaded = qtrue;
02722 if ( d_JediAI.integer )
02723 {
02724 Com_Printf( "duck " );
02725 }
02726 }
02727 else
02728 {//in air! Ducking does no good
02729 }
02730 }
02731 if ( incoming || !saberBusy )
02732 {
02733 if ( rightdot > 8 || (rightdot > 3 && zdiff < -11) )//was normalized, 0.2
02734 {
02735 if ( doDodge )
02736 {
02737 if ( self->client->NPC_class == CLASS_BOBAFETT && !Q_irand( 0, 2 ) )
02738 {//roll!
02739 TIMER_Start( self, "strafeLeft", Q_irand( 500, 1500 ) );
02740 TIMER_Set( self, "strafeRight", 0 );
02741 }
02742 else
02743 {
02744 dodgeAnim = BOTH_DODGE_L;
02745 }
02746 }
02747 else
02748 {
02749 self->client->ps.saberBlocked = BLOCKED_UPPER_RIGHT;
02750 if ( evasionType == EVASION_DUCK )
02751 {
02752 evasionType = EVASION_DUCK_PARRY;
02753 }
02754 else
02755 {
02756 evasionType = EVASION_PARRY;
02757 }
02758 }
02759 if ( d_JediAI.integer )
02760 {
02761 Com_Printf( "mid-UR block\n" );
02762 }
02763 }
02764 else if ( rightdot < -8 || (rightdot < -3 && zdiff < -11) )//was normalized, -0.2
02765 {
02766 if ( doDodge )
02767 {
02768 if ( self->client->NPC_class == CLASS_BOBAFETT && !Q_irand( 0, 2 ) )
02769 {//roll!
02770 TIMER_Start( self, "strafeLeft", Q_irand( 500, 1500 ) );
02771 TIMER_Set( self, "strafeRight", 0 );
02772 }
02773 else
02774 {
02775 dodgeAnim = BOTH_DODGE_R;
02776 }
02777 }
02778 else
02779 {
02780 self->client->ps.saberBlocked = BLOCKED_UPPER_LEFT;
02781 if ( evasionType == EVASION_DUCK )
02782 {
02783 evasionType = EVASION_DUCK_PARRY;
02784 }
02785 else
02786 {
02787 evasionType = EVASION_PARRY;
02788 }
02789 }
02790 if ( d_JediAI.integer )
02791 {
02792 Com_Printf( "mid-UL block\n" );
02793 }
02794 }
02795 else
02796 {
02797 self->client->ps.saberBlocked = BLOCKED_TOP;
02798 if ( evasionType == EVASION_DUCK )
02799 {
02800 evasionType = EVASION_DUCK_PARRY;
02801 }
02802 else
02803 {
02804 evasionType = EVASION_PARRY;
02805 }
02806 if ( d_JediAI.integer )
02807 {
02808 Com_Printf( "mid-TOP block\n" );
02809 }
02810 }
02811 evaded = qtrue;
02812 }
02813 }
02814 else if ( saberBusy || (zdiff < -36 && ( zdiff < -44 || !Q_irand( 0, 2 ) ) ) )//was -30 and -40//2nd one was -46
02815 {//jump!
02816 if ( self->client->ps.groundEntityNum == ENTITYNUM_NONE )
02817 {//already in air, duck to pull up legs
02818 TIMER_Start( self, "duck", Q_irand( 500, 1500 ) );
02819 evasionType = EVASION_DUCK;
02820 evaded = qtrue;
02821 if ( d_JediAI.integer )
02822 {
02823 Com_Printf( "legs up\n" );
02824 }
02825 if ( incoming || !saberBusy )
02826 {
02827 //since the jump may be cleared if not safe, set a lower block too
02828 if ( rightdot >= 0 )
02829 {
02830 self->client->ps.saberBlocked = BLOCKED_LOWER_RIGHT;
02831 evasionType = EVASION_DUCK_PARRY;
02832 if ( d_JediAI.integer )
02833 {
02834 Com_Printf( "LR block\n" );
02835 }
02836 }
02837 else
02838 {
02839 self->client->ps.saberBlocked = BLOCKED_LOWER_LEFT;
02840 evasionType = EVASION_DUCK_PARRY;
02841 if ( d_JediAI.integer )
02842 {
02843 Com_Printf( "LL block\n" );
02844 }
02845 }
02846 evaded = qtrue;
02847 }
02848 }
02849 else
02850 {//gotta jump!
02851 if ( self->NPC && (self->NPC->rank == RANK_CREWMAN || self->NPC->rank > RANK_LT_JG ) &&
02852 (!Q_irand( 0, 10 ) || (!Q_irand( 0, 2 ) && (cmd->forwardmove || cmd->rightmove))) )
02853 {//superjump
02854 //FIXME: check the jump, if can't, then block
02855 if ( self->NPC
02856 && !(self->NPC->scriptFlags&SCF_NO_ACROBATICS)
02857 && self->client->ps.fd.forceRageRecoveryTime < level.time
02858 && !(self->client->ps.fd.forcePowersActive&(1<<FP_RAGE))
02859 && !PM_InKnockDown( &self->client->ps ) )
02860 {
02861 self->client->ps.fd.forceJumpCharge = 320;//FIXME: calc this intelligently
02862 evasionType = EVASION_FJUMP;
02863 evaded = qtrue;
02864 if ( d_JediAI.integer )
02865 {
02866 Com_Printf( "force jump + " );
02867 }
02868 }
02869 }
02870 else
02871 {//normal jump
02872 //FIXME: check the jump, if can't, then block
02873 if ( self->NPC
02874 && !(self->NPC->scriptFlags&SCF_NO_ACROBATICS)
02875 && self->client->ps.fd.forceRageRecoveryTime < level.time
02876 && !(self->client->ps.fd.forcePowersActive&(1<<FP_RAGE)) )
02877 {
02878 if ( self->client->NPC_class == CLASS_BOBAFETT && !Q_irand( 0, 1 ) )
02879 {//roll!
02880 if ( rightdot > 0 )
02881 {
02882 TIMER_Start( self, "strafeLeft", Q_irand( 500, 1500 ) );
02883 TIMER_Set( self, "strafeRight", 0 );
02884 TIMER_Set( self, "walking", 0 );
02885 }
02886 else
02887 {
02888 TIMER_Start( self, "strafeRight", Q_irand( 500, 1500 ) );
02889 TIMER_Set( self, "strafeLeft", 0 );
02890 TIMER_Set( self, "walking", 0 );
02891 }
02892 }
02893 else
02894 {
02895 if ( self == NPC )
02896 {
02897 cmd->upmove = 127;
02898 }
02899 else
02900 {
02901 self->client->ps.velocity[2] = JUMP_VELOCITY;
02902 }
02903 }
02904 evasionType = EVASION_JUMP;
02905 evaded = qtrue;
02906 if ( d_JediAI.integer )
02907 {
02908 Com_Printf( "jump + " );
02909 }
02910 }
02911 if ( self->client->NPC_class == CLASS_TAVION )
02912 {
02913 if ( !incoming
02914 && self->client->ps.groundEntityNum < ENTITYNUM_NONE
02915 && !Q_irand( 0, 2 ) )
02916 {
02917 if ( !BG_SaberInAttack( self->client->ps.saberMove )
02918 && !PM_SaberInStart( self->client->ps.saberMove )
02919 && !BG_InRoll( &self->client->ps, self->client->ps.legsAnim )
02920 && !PM_InKnockDown( &self->client->ps )
02921 && !BG_SaberInSpecialAttack( self->client->ps.torsoAnim ) )
02922 {//do the butterfly!
02923 int butterflyAnim;
02924 if ( Q_irand( 0, 1 ) )
02925 {
02926 butterflyAnim = BOTH_BUTTERFLY_LEFT;
02927 }
02928 else
02929 {
02930 butterflyAnim = BOTH_BUTTERFLY_RIGHT;
02931 }
02932 evasionType = EVASION_CARTWHEEL;
02933 NPC_SetAnim( self, SETANIM_BOTH, butterflyAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD );
02934 self->client->ps.velocity[2] = 225;
02935 self->client->ps.fd.forceJumpZStart = self->r.currentOrigin[2];//so we don't take damage if we land at same height
02936 // self->client->ps.pm_flags |= PMF_JUMPING|PMF_SLOW_MO_FALL;
02937 // self->client->ps.SaberActivateTrail( 300 );//FIXME: reset this when done!
02938 //Ah well. No hacking from the server for now.
02939 if ( self->client->NPC_class == CLASS_BOBAFETT )
02940 {
02941 G_AddEvent( self, EV_JUMP, 0 );
02942 }
02943 else
02944 {
02945 G_Sound( self, CHAN_BODY, G_SoundIndex("sound/weapons/force/jump.wav") );
02946 }
02947 cmd->upmove = 0;
02948 saberBusy = qtrue;
02949 evaded = qtrue;
02950 }
02951 }
02952 }
02953 }
02954 if ( ((evasionType = Jedi_CheckFlipEvasions( self, rightdot, zdiff ))!=EVASION_NONE) )
02955 {
02956 if ( d_slowmodeath.integer > 5 && self->enemy && !self->enemy->s.number )
02957 {
02958 G_StartMatrixEffect( self );
02959 }
02960 saberBusy = qtrue;
02961 evaded = qtrue;
02962 }
02963 else if ( incoming || !saberBusy )
02964 {
02965 //since the jump may be cleared if not safe, set a lower block too
02966 if ( rightdot >= 0 )
02967 {
02968 self->client->ps.saberBlocked = BLOCKED_LOWER_RIGHT;
02969 if ( evasionType == EVASION_JUMP )
02970 {
02971 evasionType = EVASION_JUMP_PARRY;
02972 }
02973 else if ( evasionType == EVASION_NONE )
02974 {
02975 evasionType = EVASION_PARRY;
02976 }
02977 if ( d_JediAI.integer )
02978 {
02979 Com_Printf( "LR block\n" );
02980 }
02981 }
02982 else
02983 {
02984 self->client->ps.saberBlocked = BLOCKED_LOWER_LEFT;
02985 if ( evasionType == EVASION_JUMP )
02986 {
02987 evasionType = EVASION_JUMP_PARRY;
02988 }
02989 else if ( evasionType == EVASION_NONE )
02990 {
02991 evasionType = EVASION_PARRY;
02992 }
02993 if ( d_JediAI.integer )
02994 {
02995 Com_Printf( "LL block\n" );
02996 }
02997 }
02998 evaded = qtrue;
02999 }
03000 }
03001 }
03002 else
03003 {
03004 if ( incoming || !saberBusy )
03005 {
03006 if ( rightdot >= 0 )
03007 {
03008 self->client->ps.saberBlocked = BLOCKED_LOWER_RIGHT;
03009 evasionType = EVASION_PARRY;
03010 if ( d_JediAI.integer )
03011 {
03012 Com_Printf( "LR block\n" );
03013 }
03014 }
03015 else
03016 {
03017 self->client->ps.saberBlocked = BLOCKED_LOWER_LEFT;
03018 evasionType = EVASION_PARRY;
03019 if ( d_JediAI.integer )
03020 {
03021 Com_Printf( "LL block\n" );
03022 }
03023 }
03024 if ( incoming && incoming->s.weapon == WP_SABER )
03025 {//thrown saber!
03026 if ( self->NPC && (self->NPC->rank == RANK_CREWMAN || self->NPC->rank > RANK_LT_JG ) &&
03027 (!Q_irand( 0, 10 ) || (!Q_irand( 0, 2 ) && (cmd->forwardmove || cmd->rightmove))) )
03028 {//superjump
03029 //FIXME: check the jump, if can't, then block
03030 if ( self->NPC
03031 && !(self->NPC->scriptFlags&SCF_NO_ACROBATICS)
03032 && self->client->ps.fd.forceRageRecoveryTime < level.time
03033 && !(self->client->ps.fd.forcePowersActive&(1<<FP_RAGE))
03034 && !PM_InKnockDown( &self->client->ps ) )
03035 {
03036 self->client->ps.fd.forceJumpCharge = 320;//FIXME: calc this intelligently
03037 evasionType = EVASION_FJUMP;
03038 if ( d_JediAI.integer )
03039 {
03040 Com_Printf( "force jump + " );
03041 }
03042 }
03043 }
03044 else
03045 {//normal jump
03046 //FIXME: check the jump, if can't, then block
03047 if ( self->NPC
03048 && !(self->NPC->scriptFlags&SCF_NO_ACROBATICS)
03049 && self->client->ps.fd.forceRageRecoveryTime < level.time
03050 && !(self->client->ps.fd.forcePowersActive&(1<<FP_RAGE)))
03051 {
03052 if ( self == NPC )
03053 {
03054 cmd->upmove = 127;
03055 }
03056 else
03057 {
03058 self->client->ps.velocity[2] = JUMP_VELOCITY;
03059 }
03060 evasionType = EVASION_JUMP_PARRY;
03061 if ( d_JediAI.integer )
03062 {
03063 Com_Printf( "jump + " );
03064 }
03065 }
03066 }
03067 }
03068 evaded = qtrue;
03069 }
03070 }
03071
03072 if ( evasionType == EVASION_NONE )
03073 {
03074 return EVASION_NONE;
03075 }
03076 //stop taunting
03077 TIMER_Set( self, "taunting", 0 );
03078 //stop gripping
03079 TIMER_Set( self, "gripping", -level.time );
03080 WP_ForcePowerStop( self, FP_GRIP );
03081 //stop draining
03082 TIMER_Set( self, "draining", -level.time );
03083 WP_ForcePowerStop( self, FP_DRAIN );
03084
03085 if ( dodgeAnim != -1 )
03086 {//dodged
03087 evasionType = EVASION_DODGE;
03088 NPC_SetAnim( self, SETANIM_BOTH, dodgeAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD );
03089 self->client->ps.weaponTime = self->client->ps.torsoTimer;
03090 //force them to stop moving in this case
03091 self->client->ps.pm_time = self->client->ps.torsoTimer;
03092 //FIXME: maybe make a sound? Like a grunt? EV_JUMP?
03093 self->client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
03094 //dodged, not block
03095 if ( d_slowmodeath.integer > 5 && self->enemy && !self->enemy->s.number )
03096 {
03097 G_StartMatrixEffect( self );
03098 }
03099 }
03100 else
03101 {
03102 if ( duckChance )
03103 {
03104 if ( !Q_irand( 0, duckChance ) )
03105 {
03106 TIMER_Start( self, "duck", Q_irand( 500, 1500 ) );
03107 if ( evasionType == EVASION_PARRY )
03108 {
03109 evasionType = EVASION_DUCK_PARRY;
03110 }
03111 else
03112 {
03113 evasionType = EVASION_DUCK;
03114 }
03115 /*
03116 if ( d_JediAI.integer )
03117 {
03118 Com_Printf( "duck " );
03119 }
03120 */
03121 }
03122 }
03123
03124 if ( incoming )
03125 {
03126 self->client->ps.saberBlocked = WP_MissileBlockForBlock( self->client->ps.saberBlocked );
03127 }
03128
03129 }
03130 //if ( self->client->ps.saberBlocked != BLOCKED_NONE )
03131 {
03132 int parryReCalcTime = Jedi_ReCalcParryTime( self, evasionType );
03133 if ( self->client->ps.fd.forcePowerDebounce[FP_SABER_DEFENSE] < level.time + parryReCalcTime )
03134 {
03135 self->client->ps.fd.forcePowerDebounce[FP_SABER_DEFENSE] = level.time + parryReCalcTime;
03136 }
03137 }
03138 return evasionType;
03139 }
|
|
|
Referenced by NPC_BSJedi_Default(), NPC_Jedi_Pain(), NPC_Use(), player_die(), and WP_SaberStartMissileBlockCheck(). |
|
|
Definition at line 6245 of file w_saber.c. References entityState_s::angles, entityState_s::apos, gentity_s::bounceCount, gentity_s::classname, gentity_s::client, gentity_s::clipmask, entityShared_t::contents, CONTENTS_TRIGGER, entityShared_t::currentAngles, entityShared_t::currentOrigin, DeadSaberThink(), ENTITYNUM_WORLD, ET_MISSILE, entityState_s::eType, FL_BOUNCE_HALF, gentity_s::flags, entityState_s::g2radius, g_entities, G_FreeEntity(), g_gametype, G_Spawn(), gentity_t, GT_JEDIMASTER, vmCvar_t::integer, gentity_s::inuse, level, MASK_PLAYERSOLID, entityShared_t::maxs, entityShared_t::mins, saberInfo_t::model, entityState_s::modelGhoul2, gentity_s::nextthink, NULL, entityState_s::number, entityState_s::origin, entityShared_t::ownerNum, entityState_s::pos, Q_irand(), qtrue, gentity_s::r, gentity_s::s, gclient_s::saber, SaberBounceSound(), saberInfo_t::skin, gentity_s::speed, SVF_USE_CURRENT_ORIGIN, entityShared_t::svFlags, gentity_s::think, level_locals_t::time, gentity_s::touch, TR_GRAVITY, trap_LinkEntity(), trajectory_t::trBase, trajectory_t::trDelta, trajectory_t::trTime, trajectory_t::trType, vec3_t, VectorCopy, VectorSet, entityState_s::weapon, WP_SABER, and WP_SaberAddG2Model(). Referenced by DownedSaberThink(), saberBackToOwner(), and saberFirstThrown().
06246 { //spawn a "dead" saber entity here so it looks like the saber fell out of the air.
06247 //This entity will remove itself after a very short time period.
06248 vec3_t startorg;
06249 vec3_t startang;
06250 gentity_t *saberent;
06251 gentity_t *owner = NULL;
06252
06253 if (g_gametype.integer == GT_JEDIMASTER)
06254 { //never spawn a dead saber in JM, because the only saber on the level is really a world object
06255 //G_Sound(ent, CHAN_AUTO, saberOffSound);
06256 return;
06257 }
06258
06259 saberent = G_Spawn();
06260
06261 VectorCopy(ent->r.currentOrigin, startorg);
06262 VectorCopy(ent->r.currentAngles, startang);
06263
06264 saberent->classname = "deadsaber";
06265
06266 saberent->r.svFlags = SVF_USE_CURRENT_ORIGIN;
06267 saberent->r.ownerNum = ent->s.number;
06268
06269 saberent->clipmask = MASK_PLAYERSOLID;
06270 saberent->r.contents = CONTENTS_TRIGGER;//0;
06271
06272 VectorSet( saberent->r.mins, -3.0f, -3.0f, -1.5f );
06273 VectorSet( saberent->r.maxs, 3.0f, 3.0f, 1.5f );
06274
06275 saberent->touch = SaberBounceSound;
06276
06277 saberent->think = DeadSaberThink;
06278 saberent->nextthink = level.time;
06279
06280 VectorCopy(startorg, saberent->s.pos.trBase);
06281 VectorCopy(startang, saberent->s.apos.trBase);
06282
06283 VectorCopy(startorg, saberent->s.origin);
06284 VectorCopy(startang, saberent->s.angles);
06285
06286 VectorCopy(startorg, saberent->r.currentOrigin);
06287 VectorCopy(startang, saberent->r.currentAngles);
06288
06289 saberent->s.apos.trType = TR_GRAVITY;
06290 saberent->s.apos.trDelta[0] = Q_irand(200, 800);
06291 saberent->s.apos.trDelta[1] = Q_irand(200, 800);
06292 saberent->s.apos.trDelta[2] = Q_irand(200, 800);
06293 saberent->s.apos.trTime = level.time-50;
06294
06295 saberent->s.pos.trType = TR_GRAVITY;
06296 saberent->s.pos.trTime = level.time-50;
06297 saberent->flags = FL_BOUNCE_HALF;
06298 if (ent->r.ownerNum >= 0 && ent->r.ownerNum < ENTITYNUM_WORLD)
06299 {
06300 owner = &g_entities[ent->r.ownerNum];
06301
06302 if (owner->inuse && owner->client &&
06303 owner->client->saber[0].model[0])
06304 {
06305 WP_SaberAddG2Model( saberent, owner->client->saber[0].model, owner->client->saber[0].skin );
06306 }
06307 else
06308 {
06309 //WP_SaberAddG2Model( saberent, NULL, 0 );
06310 //argh!!!!
06311 G_FreeEntity(saberent);
06312 return;
06313 }
06314 }
06315
06316 saberent->s.modelGhoul2 = 1;
06317 saberent->s.g2radius = 20;
06318
06319 saberent->s.eType = ET_MISSILE;
06320 saberent->s.weapon = WP_SABER;
06321
06322 saberent->speed = level.time + 4000;
06323
06324 saberent->bounceCount = 12;
06325
06326 //fall off in the direction the real saber was headed
06327 VectorCopy(ent->s.pos.trDelta, saberent->s.pos.trDelta);
06328
06329 saberMoveBack(saberent, qtrue);
06330 saberent->s.pos.trType = TR_GRAVITY;
06331
06332 trap_LinkEntity(saberent);
06333 }
|
|
||||||||||||||||
|
Definition at line 906 of file NPC_utils.c. References BONE_ANGLES_POSTMULT, entityState_s::boneAngles1, entityState_s::boneAngles2, entityState_s::boneAngles3, entityState_s::boneAngles4, entityState_s::boneIndex1, entityState_s::boneIndex2, entityState_s::boneIndex3, entityState_s::boneIndex4, entityState_s::boneOrient, byte, Com_Printf(), G_BoneIndex(), gentity_t, gentity_s::ghoul2, level, NEGATIVE_Y, NEGATIVE_Z, NULL, POSITIVE_X, gentity_s::s, level_locals_t::time, trap_G2API_SetBoneAngles(), vec3_t, and VectorCopy. Referenced by Interrogator_PartsMove(), R2D2_PartsMove(), and VEH_TurretAim().
00907 {
00908 #ifdef _XBOX
00909 byte *thebone = &ent->s.boneIndex1;
00910 byte *firstFree = NULL;
00911 #else
00912 int *thebone = &ent->s.boneIndex1;
00913 int *firstFree = NULL;
00914 #endif
00915 int i = 0;
00916 int boneIndex = G_BoneIndex(bone);
00917 int flags, up, right, forward;
00918 vec3_t *boneVector = &ent->s.boneAngles1;
00919 vec3_t *freeBoneVec = NULL;
00920
00921 while (thebone)
00922 {
00923 if (!*thebone && !firstFree)
00924 { //if the value is 0 then this index is clear, we can use it if we don't find the bone we want already existing.
00925 firstFree = thebone;
00926 freeBoneVec = boneVector;
00927 }
00928 else if (*thebone)
00929 {
00930 if (*thebone == boneIndex)
00931 { //this is it
00932 break;
00933 }
00934 }
00935
00936 switch (i)
00937 {
00938 case 0:
00939 thebone = &ent->s.boneIndex2;
00940 boneVector = &ent->s.boneAngles2;
00941 break;
00942 case 1:
00943 thebone = &ent->s.boneIndex3;
00944 boneVector = &ent->s.boneAngles3;
00945 break;
00946 case 2:
00947 thebone = &ent->s.boneIndex4;
00948 boneVector = &ent->s.boneAngles4;
00949 break;
00950 default:
00951 thebone = NULL;
00952 boneVector = NULL;
00953 break;
00954 }
00955
00956 i++;
00957 }
00958
00959 if (!thebone)
00960 { //didn't find it, create it
00961 if (!firstFree)
00962 { //no free bones.. can't do a thing then.
00963 Com_Printf("WARNING: NPC has no free bone indexes\n");
00964 return;
00965 }
00966
00967 thebone = firstFree;
00968
00969 *thebone = boneIndex;
00970 boneVector = freeBoneVec;
00971 }
00972
00973 //If we got here then we have a vector and an index.
00974
00975 //Copy the angles over the vector in the entitystate, so we can use the corresponding index
00976 //to set the bone angles on the client.
00977 VectorCopy(angles, *boneVector);
00978
00979 //Now set the angles on our server instance if we have one.
00980
00981 if (!ent->ghoul2)
00982 {
00983 return;
00984 }
00985
00986 flags = BONE_ANGLES_POSTMULT;
00987 up = POSITIVE_X;
00988 right = NEGATIVE_Y;
00989 forward = NEGATIVE_Z;
00990
00991 //first 3 bits is forward, second 3 bits is right, third 3 bits is up
00992 ent->s.boneOrient = ((forward)|(right<<3)|(up<<6));
00993
00994 trap_G2API_SetBoneAngles(ent->ghoul2, 0, bone, angles, flags, up, right, forward, NULL, 100, level.time);
00995 }
|
|
||||||||||||||||
|
Definition at line 1632 of file NPC_utils.c. References gentity_s::client, EF2_HELD_BY_MONSTER, playerState_s::eFlags2, gentity_t, renderInfo_s::lookTarget, renderInfo_s::lookTargetClearTime, gclient_s::ps, and gclient_s::renderInfo. Referenced by Jedi_CheckAmbushPlayer(), NPC_ExecuteBState(), and NPC_TempLookTarget().
01633 {
01634 if ( !self->client )
01635 {
01636 return;
01637 }
01638
01639 if ( (self->client->ps.eFlags2&EF2_HELD_BY_MONSTER) )
01640 {//lookTarget is set by and to the monster that's holding you, no other operations can change that
01641 return;
01642 }
01643
01644 self->client->renderInfo.lookTarget = entNum;
01645 self->client->renderInfo.lookTargetClearTime = clearTime;
01646 }
|
|
|
Definition at line 1086 of file bg_panimate.c. References LS_B1__L, LS_B1__R, LS_B1_BL, LS_B1_BR, LS_B1_T_, LS_B1_TL, LS_B1_TR, LS_NONE, Q_B, Q_BL, Q_BR, Q_L, Q_R, Q_T, Q_TL, Q_TR, saberMoveData, and saberMoveData_t::startQuad. Referenced by PM_WeaponLightsaber().
01087 {
01088 switch ( saberMoveData[move].startQuad )
01089 {
01090 case Q_B:
01091 case Q_BR:
01092 return LS_B1_BR;
01093 break;
01094 case Q_R:
01095 return LS_B1__R;
01096 break;
01097 case Q_TR:
01098 return LS_B1_TR;
01099 break;
01100 case Q_T:
01101 return LS_B1_T_;
01102 break;
01103 case Q_TL:
01104 return LS_B1_TL;
01105 break;
01106 case Q_L:
01107 return LS_B1__L;
01108 break;
01109 case Q_BL:
01110 return LS_B1_BL;
01111 break;
01112 }
01113 return LS_NONE;
01114 }
|
|
|
Definition at line 1116 of file bg_panimate.c. References LS_D1__L, LS_D1__R, LS_D1_B_, LS_D1_BL, LS_D1_BR, LS_D1_T_, LS_D1_TL, LS_D1_TR, LS_NONE, Q_B, Q_BL, Q_BR, Q_L, Q_R, Q_T, Q_TL, and Q_TR.
01117 {
01118 switch ( quad )
01119 {
01120 case Q_B:
01121 return LS_D1_B_;
01122 break;
01123 case Q_BR:
01124 return LS_D1_BR;
01125 break;
01126 case Q_R:
01127 return LS_D1__R;
01128 break;
01129 case Q_TR:
01130 return LS_D1_TR;
01131 break;
01132 case Q_T:
01133 return LS_D1_T_;
01134 break;
01135 case Q_TL:
01136 return LS_D1_TL;
01137 break;
01138 case Q_L:
01139 return LS_D1__L;
01140 break;
01141 case Q_BL:
01142 return LS_D1_BL;
01143 break;
01144 }
01145 return LS_NONE;
01146 }
|
|
|
Definition at line 700 of file bg_saber.c. References LS_B1_BL, LS_B1_BR, LS_D1_BL, LS_D1_BR, qboolean, qfalse, and qtrue. Referenced by PM_SaberAttackForMovement(), and PM_WeaponLightsaber().
|
|
|
Definition at line 1580 of file bg_saber.c. References LS_H1_BL, LS_H1_T_, LS_V1_B_, LS_V1_BR, qboolean, qfalse, and qtrue. Referenced by Jedi_SaberBusy(), PM_SetSaberMove(), PM_WeaponLightsaber(), and WP_SaberCanBlock().
|
|
|
Definition at line 1148 of file bg_panimate.c. References LS_D1_B_, LS_D1_BR, qboolean, qfalse, and qtrue.
|
|
|
Definition at line 1610 of file bg_panimate.c. References LS_T1_BL__L, LS_T1_BR__R, qboolean, qfalse, and qtrue. Referenced by BG_AdjustClientSpeed(), BG_SaberInTransitionAny(), ClientThink_real(), PM_WeaponLightsaber(), and WP_SaberPositionUpdate().
01611 {
01612 if ( move >= LS_T1_BR__R && move <= LS_T1_BL__L )
01613 {
01614 return qtrue;
01615 }
01616 return qfalse;
01617 }
|
|
||||||||||||
|
Definition at line 39 of file w_saber.c. Referenced by G_DeflectMissile(), G_ReflectMissile(), and WP_SaberBlock().
|
|
|
Definition at line 6915 of file w_saber.c. References CHAN_AUTO, gentity_s::client, entityShared_t::contents, CONTENTS_LIGHTSABER, entityShared_t::currentOrigin, ENTITYNUM_NONE, playerState_s::fd, FORCE_LEVEL_3, forcedata_s::forcePowerLevel, FP_SABER_OFFENSE, FP_SABERTHROW, g_entities, G_FreeEntity(), G_Sound(), G_SoundIndex(), gentity_s::genericValue5, gentity_t, gentity_s::health, gentity_s::inuse, level, entityState_s::loopIsSoundset, entityState_s::loopSound, MakeDeadSaber(), gentity_s::nextthink, entityState_s::number, entityShared_t::ownerNum, entityState_s::pos, gentity_s::pos1, gclient_s::ps, qfalse, qtrue, gentity_s::r, gentity_s::s, gclient_s::saber, playerState_s::saberCanThrow, playerState_s::saberEntityNum, playerState_s::saberEntityState, saberInfo_t::saberFlags, SaberGotHit(), playerState_s::saberHolstered, entityState_s::saberInFlight, playerState_s::saberInFlight, gclient_s::saberStoredIndex, playerState_s::saberThrowDelay, SaberUpdateSelf(), gclient_s::sess, clientSession_t::sessionTeam, SFL_RETURN_DAMAGE, saberInfo_t::soundLoop, saberInfo_t::soundOff, gentity_s::speed, SVF_NOCLIENT, entityShared_t::svFlags, TEAM_SPECTATOR, gentity_s::think, level_locals_t::time, gentity_s::touch, trajectory_t::trBase, trajectory_t::trDelta, trajectory_t::trTime, vec3_t, VectorCopy, VectorNormalize(), VectorScale, VectorSubtract, and WP_SaberRemoveG2Model(). Referenced by DownedSaberThink(), and thrownSaberTouch().
06916 {
06917 gentity_t *saberOwner = &g_entities[saberent->r.ownerNum];
06918 vec3_t dir;
06919 float ownerLen;
06920
06921 if (saberent->r.ownerNum == ENTITYNUM_NONE)
06922 {
06923 MakeDeadSaber(saberent);
06924
06925 saberent->think = G_FreeEntity;
06926 saberent->nextthink = level.time;
06927 return;
06928 }
06929
06930 if (!saberOwner->inuse ||
06931 !saberOwner->client ||
06932 saberOwner->client->sess.sessionTeam == TEAM_SPECTATOR)
06933 {
06934 MakeDeadSaber(saberent);
06935
06936 saberent->think = G_FreeEntity;
06937 saberent->nextthink = level.time;
06938 return;
06939 }
06940
06941 if (saberOwner->health < 1 || !saberOwner->client->ps.fd.forcePowerLevel[FP_SABER_OFFENSE])
06942 { //He's dead, just go back to our normal saber status
06943 saberent->touch = SaberGotHit;
06944 saberent->think = SaberUpdateSelf;
06945 saberent->genericValue5 = 0;
06946 saberent->nextthink = level.time;
06947
06948 if (saberOwner->client &&
06949 saberOwner->client->saber[0].soundOff)
06950 {
06951 G_Sound(saberent, CHAN_AUTO, saberOwner->client->saber[0].soundOff);
06952 }
06953 MakeDeadSaber(saberent);
06954
06955 saberent->r.svFlags |= (SVF_NOCLIENT);
06956 saberent->r.contents = CONTENTS_LIGHTSABER;
06957 SetSaberBoxSize(saberent);
06958 saberent->s.loopSound = 0;
06959 saberent->s.loopIsSoundset = qfalse;
06960 WP_SaberRemoveG2Model( saberent );
06961
06962 saberOwner->client->ps.saberInFlight = qfalse;
06963 saberOwner->client->ps.saberEntityState = 0;
06964 saberOwner->client->ps.saberThrowDelay = level.time + 500;
06965 saberOwner->client->ps.saberCanThrow = qfalse;
06966
06967 return;
06968 }
06969
06970 //make sure this is set alright
06971 assert(saberOwner->client->ps.saberEntityNum == saberent->s.number ||
06972 saberOwner->client->saberStoredIndex == saberent->s.number);
06973 saberOwner->client->ps.saberEntityNum = saberent->s.number;
06974
06975 saberent->r.contents = CONTENTS_LIGHTSABER;
06976
06977 VectorSubtract(saberent->pos1, saberent->r.currentOrigin, dir);
06978
06979 ownerLen = VectorLength(dir);
06980
06981 if (saberent->speed < level.time)
06982 {
06983 float baseSpeed = 900;
06984
06985 VectorNormalize(dir);
06986
06987 saberMoveBack(saberent, qtrue);
06988 VectorCopy(saberent->r.currentOrigin, saberent->s.pos.trBase);
06989
06990 if (saberOwner->client->ps.fd.forcePowerLevel[FP_SABERTHROW] >= FORCE_LEVEL_3)
06991 { //allow players with high saber throw rank to control the return speed of the saber
06992 baseSpeed = 900;
06993
06994 saberent->speed = level.time;// + 200;
06995 }
06996 else
06997 {
06998 baseSpeed = 700;
06999 saberent->speed = level.time + 50;
07000 }
07001
07002 //Gradually slow down as it approaches, so it looks smoother coming into the hand.
07003 if (ownerLen < 64)
07004 {
07005 VectorScale(dir, baseSpeed-200, saberent->s.pos.trDelta );
07006 }
07007 else if (ownerLen < 128)
07008 {
07009 VectorScale(dir, baseSpeed-150, saberent->s.pos.trDelta );
07010 }
07011 else if (ownerLen < 256)
07012 {
07013 VectorScale(dir, baseSpeed-100, saberent->s.pos.trDelta );
07014 }
07015 else
07016 {
07017 VectorScale(dir, baseSpeed, saberent->s.pos.trDelta );
07018 }
07019
07020 saberent->s.pos.trTime = level.time;
07021 }
07022
07023 /*
07024 if (ownerLen <= 512)
07025 {
07026 saberent->s.saberInFlight = qfalse;
07027 saberent->s.loopSound = saberHumSound;
07028 saberent->s.loopIsSoundset = qfalse;
07029 }
07030 */
07031 //I'm just doing this now. I don't really like the spin on the way back. And it does weird stuff with the new saber-knocked-away code.
07032 if (saberOwner->client->ps.saberEntityNum == saberent->s.number)
07033 {
07034 if ( !(saberOwner->client->saber[0].saberFlags&SFL_RETURN_DAMAGE)
07035 || saberOwner->client->ps.saberHolstered )
07036 {
07037 saberent->s.saberInFlight = qfalse;
07038 }
07039 saberent->s.loopSound = saberOwner->client->saber[0].soundLoop;
07040 saberent->s.loopIsSoundset = qfalse;
07041
07042 if (ownerLen <= 32)
07043 {
07044 G_Sound( saberent, CHAN_AUTO, G_SoundIndex( "sound/weapons/saber/saber_catch.wav" ) );
07045
07046 saberOwner->client->ps.saberInFlight = qfalse;
07047 saberOwner->client->ps.saberEntityState = 0;
07048 saberOwner->client->ps.saberCanThrow = qfalse;
07049 saberOwner->client->ps.saberThrowDelay = level.time + 300;
07050
07051 saberent->touch = SaberGotHit;
07052
07053 saberent->think = SaberUpdateSelf;
07054 saberent->genericValue5 = 0;
07055 saberent->nextthink = level.time + 50;
07056 WP_SaberRemoveG2Model( saberent );
07057
07058 return;
07059 }
07060
07061 if (!saberent->s.saberInFlight)
07062 {
07063 saberCheckRadiusDamage(saberent, 1);
07064 }
07065 else
07066 {
07067 saberCheckRadiusDamage(saberent, 2);
07068 }
07069
07070 saberMoveBack(saberent, qtrue);
07071 }
07072
07073 saberent->nextthink = level.time;
07074 }
|
|
||||||||||||||||
|
Definition at line 6227 of file w_saber.c. References entityState_s::apos, entityShared_t::currentAngles, gentity_t, PITCH, gentity_s::r, gentity_s::s, trajectory_t::trBase, and VectorCopy. Referenced by MakeDeadSaber(), and saberKnockDown().
06228 {
06229 VectorCopy(self->r.currentAngles, self->s.apos.trBase);
06230 self->s.apos.trBase[PITCH] = 90;
06231 }
|
|
||||||||||||||||
|
Definition at line 6763 of file w_saber.c. References gentity_s::client, saberInfo_t::disarmBonus, gentity_t, gclient_s::lastSaberBase_Always, gclient_s::lastSaberStorageTime, level, saberInfo_t::model, gclient_s::olderIsValid, gclient_s::olderSaberBase, gclient_s::ps, Q_irand(), qboolean, qfalse, qtrue, gclient_s::saber, playerState_s::saberHolstered, SABERINVALID, saberKnockOutOfHand(), level_locals_t::time, vec3_t, VectorNormalize(), VectorScale, and VectorSubtract.
06764 {
06765 int myAttack;
06766 int otherAttack;
06767 qboolean doKnock = qfalse;
06768 int disarmChance = 1;
06769
06770 if (SABERINVALID)
06771 {
06772 return qfalse;
06773 }
06774
06775 //Neither gets an advantage based on attack state, when it comes to knocking
06776 //saber out of hand.
06777 myAttack = G_SaberAttackPower(saberOwner, qfalse);
06778 otherAttack = G_SaberAttackPower(other, qfalse);
06779
06780 if (!other->client->olderIsValid || (level.time - other->client->lastSaberStorageTime) >= 200)
06781 { //if we don't know which way to throw the saber based on momentum between saber positions, just don't throw it
06782 return qfalse;
06783 }
06784
06785 //only knock the saber out of the hand if they're in a stronger stance I suppose. Makes strong more advantageous.
06786 if (otherAttack > myAttack+1 && Q_irand(1, 10) <= 7)
06787 { //This would be, say, strong stance against light stance.
06788 doKnock = qtrue;
06789 }
06790 else if (otherAttack > myAttack && Q_irand(1, 10) <= 3)
06791 { //Strong vs. medium, medium vs. light
06792 doKnock = qtrue;
06793 }
06794
06795 if (doKnock)
06796 {
06797 vec3_t dif;
06798 float totalDistance;
06799 float distScale = 6.5f;
06800
06801 VectorSubtract(other->client->lastSaberBase_Always, other->client->olderSaberBase, dif);
06802 totalDistance = VectorNormalize(dif);
06803
06804 if (!totalDistance)
06805 { //fine, try our own
06806 if (!saberOwner->client->olderIsValid || (level.time - saberOwner->client->lastSaberStorageTime) >= 200)
06807 { //if we don't know which way to throw the saber based on momentum between saber positions, just don't throw it
06808 return qfalse;
06809 }
06810
06811 VectorSubtract(saberOwner->client->lastSaberBase_Always, saberOwner->client->olderSaberBase, dif);
06812 totalDistance = VectorNormalize(dif);
06813 }
06814
06815 if (!totalDistance)
06816 { //...forget it then.
06817 return qfalse;
06818 }
06819
06820 if (totalDistance < 20)
06821 {
06822 totalDistance = 20;
06823 }
06824 VectorScale(dif, totalDistance*distScale, dif);
06825
06826 if ( other && other->client )
06827 {
06828 disarmChance += other->client->saber[0].disarmBonus;
06829 if ( other->client->saber[1].model
06830 && other->client->saber[1].model[0]
06831 && !other->client->ps.saberHolstered )
06832 {
06833 other->client->saber[1].disarmBonus;
06834 }
06835 }
06836 if ( Q_irand( 0, disarmChance ) )
06837 {
06838 return saberKnockOutOfHand(saberent, saberOwner, dif);
06839 }
06840 }
06841
06842 return qfalse;
06843 }
|
|
||||||||||||||||
|
Definition at line 6679 of file w_saber.c. References BLOCKED_BOUNCE_MOVE, gentity_s::client, saberInfo_t::disarmBonus, gentity_t, gclient_s::lastSaberBase_Always, gclient_s::lastSaberStorageTime, level, LS_V1_BL, saberInfo_t::model, gclient_s::olderIsValid, gclient_s::olderSaberBase, gclient_s::ps, Q_irand(), qboolean, qfalse, qtrue, gclient_s::saber, playerState_s::saberBlocked, playerState_s::saberHolstered, SABERINVALID, saberKnockOutOfHand(), playerState_s::saberMove, level_locals_t::time, vec3_t, VectorClear, VectorNormalize(), VectorScale, and VectorSubtract. Referenced by ClientThink_real().
06680 {
06681 vec3_t dif;
06682 float totalDistance = 1;
06683 float distScale = 6.5f;
06684 qboolean validMomentum = qtrue;
06685 int disarmChance = 1;
06686
06687 if (SABERINVALID)
06688 {
06689 return qfalse;
06690 }
06691
06692 VectorClear(dif);
06693
06694 if (!other->client->olderIsValid || (level.time - other->client->lastSaberStorageTime) >= 200)
06695 { //see if the spots are valid
06696 validMomentum = qfalse;
06697 }
06698
06699 if (validMomentum)
06700 {
06701 //Get the difference
06702 VectorSubtract(other->client->lastSaberBase_Always, other->client->olderSaberBase, dif);
06703 totalDistance = VectorNormalize(dif);
06704
06705 if (!totalDistance)
06706 { //fine, try our own
06707 if (!saberOwner->client->olderIsValid || (level.time - saberOwner->client->lastSaberStorageTime) >= 200)
06708 {
06709 validMomentum = qfalse;
06710 }
06711
06712 if (validMomentum)
06713 {
06714 VectorSubtract(saberOwner->client->lastSaberBase_Always, saberOwner->client->olderSaberBase, dif);
06715 totalDistance = VectorNormalize(dif);
06716 }
06717 }
06718
06719 if (validMomentum)
06720 {
06721 if (!totalDistance)
06722 { //try the difference between the two blades
06723 VectorSubtract(saberOwner->client->lastSaberBase_Always, other->client->lastSaberBase_Always, dif);
06724 totalDistance = VectorNormalize(dif);
06725 }
06726
06727 if (totalDistance)
06728 { //if we still have no difference somehow, just let it fall to the ground when the time comes.
06729 if (totalDistance < 20)
06730 {
06731 totalDistance = 20;
06732 }
06733 VectorScale(dif, totalDistance*distScale, dif);
06734 }
06735 }
06736 }
06737
06738 saberOwner->client->ps.saberMove = LS_V1_BL; //rwwFIXMEFIXME: Ideally check which lock it was exactly and use the proper anim (same goes for the attacker)
06739 saberOwner->client->ps.saberBlocked = BLOCKED_BOUNCE_MOVE;
06740
06741 if ( other && other->client )
06742 {
06743 disarmChance += other->client->saber[0].disarmBonus;
06744 if ( other->client->saber[1].model
06745 && other->client->saber[1].model[0]
06746 && !other->client->ps.saberHolstered )
06747 {
06748 other->client->saber[1].disarmBonus;
06749 }
06750 }
06751 if ( Q_irand( 0, disarmChance ) )
06752 {
06753 return saberKnockOutOfHand(saberent, saberOwner, dif);
06754 }
06755 else
06756 {
06757 return qfalse;
06758 }
06759 }
|
|
||||||||||||||||||||
|
Definition at line 6850 of file w_saber.c. References BG_InExtraDefenseSaberMove(), gentity_s::client, gentity_t, gentity_s::inuse, gclient_s::ps, qboolean, qfalse, qtrue, playerState_s::saberInFlight, SABERINVALID, saberKnockDown(), and playerState_s::saberMove.
06851 {
06852 if (SABERINVALID)
06853 {
06854 return qfalse;
06855 }
06856
06857 if (!saberOwner->client->ps.saberInFlight)
06858 { //can only do this if the saber is already actually in flight
06859 return qfalse;
06860 }
06861
06862 if ( other
06863 && other->inuse
06864 && other->client
06865 && BG_InExtraDefenseSaberMove( other->client->ps.saberMove ) )
06866 { //make sure the blow was strong enough
06867 saberKnockDown(saberent, saberOwner, other);
06868 return qtrue;
06869 }
06870
06871 if (damage > 10)
06872 { //make sure the blow was strong enough
06873 saberKnockDown(saberent, saberOwner, other);
06874 return qtrue;
06875 }
06876
06877 return qfalse;
06878 }
|
|
||||||||||||||||
|
Definition at line 6882 of file w_saber.c. References gentity_s::client, playerState_s::fd, forcedata_s::forcePowerLevel, FP_SABER_DEFENSE, FP_SABERTHROW, gentity_t, gclient_s::ps, Q_irand(), qboolean, qfalse, qtrue, SABERINVALID, and saberKnockDown().
06883 {
06884 int throwLevel = 0;
06885 int defenLevel = 0;
06886 qboolean tossIt = qfalse;
06887
06888 if (SABERINVALID)
06889 {
06890 return qfalse;
06891 }
06892
06893 defenLevel = other->client->ps.fd.forcePowerLevel[FP_SABER_DEFENSE];
06894 throwLevel = saberOwner->client->ps.fd.forcePowerLevel[FP_SABERTHROW];
06895
06896 if (defenLevel > throwLevel)
06897 {
06898 tossIt = qtrue;
06899 }
06900 else if (defenLevel == throwLevel && Q_irand(1, 10) <= 4)
06901 {
06902 tossIt = qtrue;
06903 }
06904 //otherwise don't
06905
06906 if (tossIt)
06907 {
06908 saberKnockDown(saberent, saberOwner, other);
06909 return qtrue;
06910 }
06911
06912 return qfalse;
06913 }
|
|
|
Definition at line 7115 of file w_saber.c. References AngleVectors(), BG_CanUseFPNow(), BG_HasYsalamiri(), BUTTON_ALT_ATTACK, gclient_s::buttons, CHAN_AUTO, gentity_s::client, entityShared_t::contents, CONTENTS_LIGHTSABER, entityShared_t::currentOrigin, trace_t::endpos, ENTITYNUM_NONE, playerState_s::fd, FORCE_LEVEL_2, FORCE_LEVEL_3, forcedata_s::forcePowerLevel, FP_SABER_OFFENSE, FP_SABERTHROW, g_entities, G_FreeEntity(), g_gametype, G_RunObject(), G_Sound(), gentity_s::genericValue5, gentity_t, gentity_s::health, vmCvar_t::integer, gentity_s::inuse, level, entityState_s::loopIsSoundset, entityState_s::loopSound, MakeDeadSaber(), MASK_PLAYERSOLID, MASK_SOLID, gentity_s::nextthink, NULL, entityState_s::number, playerState_s::origin, entityShared_t::ownerNum, entityState_s::pos, gclient_s::ps, qfalse, gentity_s::r, gentity_s::s, gclient_s::saber, SABER_MAX_THROW_DISTANCE, playerState_s::saberCanThrow, playerState_s::saberDidThrowTime, playerState_s::saberEntityState, SaberGotHit(), playerState_s::saberInFlight, playerState_s::saberThrowDelay, SaberUpdateSelf(), gclient_s::sess, clientSession_t::sessionTeam, saberInfo_t::soundOff, gentity_s::speed, SVF_NOCLIENT, entityShared_t::svFlags, TEAM_SPECTATOR, gentity_s::think, thrownSaberTouch(), level_locals_t::time, gentity_s::touch, trap_Trace(), trajectory_t::trBase, trajectory_t::trDelta, trajectory_t::trTime, vec3_t, VectorCopy, VectorNormalize(), VectorScale, VectorSubtract, playerState_s::viewangles, playerState_s::viewheight, and WP_SaberRemoveG2Model(). Referenced by WP_SaberPositionUpdate().
07116 {
07117 vec3_t vSub;
07118 float vLen;
07119 gentity_t *saberOwn = &g_entities[saberent->r.ownerNum];
07120
07121 if (saberent->r.ownerNum == ENTITYNUM_NONE)
07122 {
07123 MakeDeadSaber(saberent);
07124
07125 saberent->think = G_FreeEntity;
07126 saberent->nextthink = level.time;
07127 return;
07128 }
07129
07130 if (!saberOwn ||
07131 !saberOwn->inuse ||
07132 !saberOwn->client ||
07133 saberOwn->client->sess.sessionTeam == TEAM_SPECTATOR)
07134 {
07135 MakeDeadSaber(saberent);
07136
07137 saberent->think = G_FreeEntity;
07138 saberent->nextthink = level.time;
07139 return;
07140 }
07141
07142 if (saberOwn->health < 1 || !saberOwn->client->ps.fd.forcePowerLevel[FP_SABER_OFFENSE])
07143 { //He's dead, just go back to our normal saber status
07144 saberent->touch = SaberGotHit;
07145 saberent->think = SaberUpdateSelf;
07146 saberent->genericValue5 = 0;
07147 saberent->nextthink = level.time;
07148
07149 if (saberOwn->client &&
07150 saberOwn->client->saber[0].soundOff)
07151 {
07152 G_Sound(saberent, CHAN_AUTO, saberOwn->client->saber[0].soundOff);
07153 }
07154 MakeDeadSaber(saberent);
07155
07156 saberent->r.svFlags |= (SVF_NOCLIENT);
07157 saberent->r.contents = CONTENTS_LIGHTSABER;
07158 SetSaberBoxSize(saberent);
07159 saberent->s.loopSound = 0;
07160 saberent->s.loopIsSoundset = qfalse;
07161 WP_SaberRemoveG2Model( saberent );
07162
07163 saberOwn->client->ps.saberInFlight = qfalse;
07164 saberOwn->client->ps.saberEntityState = 0;
07165 saberOwn->client->ps.saberThrowDelay = level.time + 500;
07166 saberOwn->client->ps.saberCanThrow = qfalse;
07167
07168 return;
07169 }
07170
07171 if ((level.time - saberOwn->client->ps.saberDidThrowTime) > 500)
07172 {
07173 if (!(saberOwn->client->buttons & BUTTON_ALT_ATTACK))
07174 { //If owner releases altattack 500ms or later after throwing saber, it autoreturns
07175 thrownSaberTouch(saberent, saberent, NULL);
07176 goto runMin;
07177 }
07178 else if ((level.time - saberOwn->client->ps.saberDidThrowTime) > 6000)
07179 { //if it's out longer than 6 seconds, return it
07180 thrownSaberTouch(saberent, saberent, NULL);
07181 goto runMin;
07182 }
07183 }
07184
07185 if (BG_HasYsalamiri(g_gametype.integer, &saberOwn->client->ps))
07186 {
07187 thrownSaberTouch(saberent, saberent, NULL);
07188 goto runMin;
07189 }
07190
07191 if (!BG_CanUseFPNow(g_gametype.integer, &saberOwn->client->ps, level.time, FP_SABERTHROW))
07192 {
07193 thrownSaberTouch(saberent, saberent, NULL);
07194 goto runMin;
07195 }
07196
07197 VectorSubtract(saberOwn->client->ps.origin, saberent->r.currentOrigin, vSub);
07198 vLen = VectorLength(vSub);
07199
07200 if (vLen >= (SABER_MAX_THROW_DISTANCE*saberOwn->client->ps.fd.forcePowerLevel[FP_SABERTHROW]))
07201 {
07202 thrownSaberTouch(saberent, saberent, NULL);
07203 goto runMin;
07204 }
07205
07206 if (saberOwn->client->ps.fd.forcePowerLevel[FP_SABERTHROW] >= FORCE_LEVEL_2 &&
07207 saberent->speed < level.time)
07208 { //if owner is rank 3 in saber throwing, the saber goes where he points
07209 vec3_t fwd, traceFrom, traceTo, dir;
07210 trace_t tr;
07211
07212 AngleVectors(saberOwn->client->ps.viewangles, fwd, 0, 0);
07213
07214 VectorCopy(saberOwn->client->ps.origin, traceFrom);
07215 traceFrom[2] += saberOwn->client->ps.viewheight;
07216
07217 VectorCopy(traceFrom, traceTo);
07218 traceTo[0] += fwd[0]*4096;
07219 traceTo[1] += fwd[1]*4096;
07220 traceTo[2] += fwd[2]*4096;
07221
07222 saberMoveBack(saberent, qfalse);
07223 VectorCopy(saberent->r.currentOrigin, saberent->s.pos.trBase);
07224
07225 if (saberOwn->client->ps.fd.forcePowerLevel[FP_SABERTHROW] >= FORCE_LEVEL_3)
07226 { //if highest saber throw rank, we can direct the saber toward players directly by looking at them
07227 trap_Trace(&tr, traceFrom, NULL, NULL, traceTo, saberOwn->s.number, MASK_PLAYERSOLID);
07228 }
07229 else
07230 {
07231 trap_Trace(&tr, traceFrom, NULL, NULL, traceTo, saberOwn->s.number, MASK_SOLID);
07232 }
07233
07234 VectorSubtract(tr.endpos, saberent->r.currentOrigin, dir);
07235
07236 VectorNormalize(dir);
07237
07238 VectorScale(dir, 500, saberent->s.pos.trDelta );
07239 saberent->s.pos.trTime = level.time;
07240
07241 if (saberOwn->client->ps.fd.forcePowerLevel[FP_SABERTHROW] >= FORCE_LEVEL_3)
07242 { //we'll treat them to a quicker update rate if their throw rank is high enough
07243 saberent->speed = level.time + 100;
07244 }
07245 else
07246 {
07247 saberent->speed = level.time + 400;
07248 }
07249 }
07250
07251 runMin:
07252
07253 saberCheckRadiusDamage(saberent, 0);
07254 G_RunObject(saberent);
07255 }
|
|
||||||||||||||||
|
Definition at line 358 of file w_saber.c. References gentity_s::client, g_entities, gentity_t, entityShared_t::ownerNum, and gentity_s::r. Referenced by DownedSaberThink(), saberBackToOwner(), saberFirstThrown(), and WP_SaberInitBladeData().
00359 {
00360 gentity_t *own = &g_entities[self->r.ownerNum];
00361
00362 if (!own || !own->client)
00363 {
00364 return;
00365 }
00366
00367 //Do something here..? Was handling projectiles here, but instead they're now handled in their own functions.
00368 }
|
|
||||||||||||||||
|
Definition at line 6510 of file w_saber.c. References AngleVectors(), entityState_s::apos, gentity_s::bounceCount, CHAN_BODY, gentity_s::client, gentity_s::clipmask, entityShared_t::contents, CONTENTS_TRIGGER, DownedSaberThink(), ET_MISSILE, entityState_s::eType, FL_BOUNCE_HALF, gentity_s::flags, entityState_s::g2radius, G_Sound(), gentity_t, gentity_s::inuse, level, entityState_s::loopIsSoundset, entityState_s::loopSound, MASK_SOLID, entityShared_t::maxs, entityShared_t::mins, saberInfo_t::model, entityState_s::modelGhoul2, gentity_s::nextthink, entityState_s::pos, gclient_s::ps, Q_irand(), qfalse, qtrue, gentity_s::r, gentity_s::s, gclient_s::saber, SABER_RETRIEVE_DELAY, SaberBounceSound(), playerState_s::saberEntityNum, gclient_s::saberKnockedTime, saberInfo_t::skin, saberInfo_t::soundOff, gentity_s::speed, SVF_NOCLIENT, entityShared_t::svFlags, gentity_s::think, level_locals_t::time, gentity_s::touch, TR_GRAVITY, trap_LinkEntity(), trajectory_t::trDelta, trajectory_t::trTime, trajectory_t::trType, vec3_t, VectorSet, playerState_s::viewangles, entityState_s::weapon, WP_SABER, and WP_SaberAddG2Model(). Referenced by Cmd_ToggleSaber_f(), saberCheckKnockdown_Smashed(), saberCheckKnockdown_Thrown(), and saberKnockOutOfHand().
06511 {
06512 saberOwner->client->ps.saberEntityNum = 0; //still stored in client->saberStoredIndex
06513 saberOwner->client->saberKnockedTime = level.time + SABER_RETRIEVE_DELAY;
06514
06515 saberent->clipmask = MASK_SOLID;
06516 saberent->r.contents = CONTENTS_TRIGGER;//0;
06517
06518 VectorSet( saberent->r.mins, -3.0f, -3.0f, -1.5f );
06519 VectorSet( saberent->r.maxs, 3.0f, 3.0f, 1.5f );
06520
06521 saberent->s.apos.trType = TR_GRAVITY;
06522 saberent->s.apos.trDelta[0] = Q_irand(200, 800);
06523 saberent->s.apos.trDelta[1] = Q_irand(200, 800);
06524 saberent->s.apos.trDelta[2] = Q_irand(200, 800);
06525 saberent->s.apos.trTime = level.time-50;
06526
06527 saberent->s.pos.trType = TR_GRAVITY;
06528 saberent->s.pos.trTime = level.time-50;
06529 saberent->flags |= FL_BOUNCE_HALF;
06530
06531 WP_SaberAddG2Model( saberent, saberOwner->client->saber[0].model, saberOwner->client->saber[0].skin );
06532
06533 saberent->s.modelGhoul2 = 1;
06534 saberent->s.g2radius = 20;
06535
06536 saberent->s.eType = ET_MISSILE;
06537 saberent->s.weapon = WP_SABER;
06538
06539 saberent->speed = level.time + 4000;
06540
06541 saberent->bounceCount = -5;//8;
06542
06543 saberMoveBack(saberent, qtrue);
06544 saberent->s.pos.trType = TR_GRAVITY;
06545
06546 saberent->s.loopSound = 0; //kill this in case it was spinning.
06547 saberent->s.loopIsSoundset = qfalse;
06548
06549 saberent->r.svFlags &= ~(SVF_NOCLIENT); //make sure the client is getting updates on where it is and such.
06550
06551 saberent->touch = SaberBounceSound;
06552 saberent->think = DownedSaberThink;
06553 saberent->nextthink = level.time;
06554
06555 if (saberOwner != other)
06556 { //if someone knocked it out of the air and it wasn't turned off, go in the direction they were facing.
06557 if (other->inuse && other->client)
06558 {
06559 vec3_t otherFwd;
06560 float deflectSpeed = 200;
06561
06562 AngleVectors(other->client->ps.viewangles, otherFwd, 0, 0);
06563
06564 saberent->s.pos.trDelta[0] = otherFwd[0]*deflectSpeed;
06565 saberent->s.pos.trDelta[1] = otherFwd[1]*deflectSpeed;
06566 saberent->s.pos.trDelta[2] = otherFwd[2]*deflectSpeed;
06567 }
06568 }
06569
06570 trap_LinkEntity(saberent);
06571
06572 if (saberOwner->client->saber[0].soundOff)
06573 {
06574 G_Sound( saberent, CHAN_BODY, saberOwner->client->saber[0].soundOff );
06575 }
06576
06577 if (saberOwner->client->saber[1].soundOff &&
06578 saberOwner->client->saber[1].model[0])
06579 {
06580 G_Sound( saberOwner, CHAN_BODY, saberOwner->client->saber[1].soundOff );
06581 }
06582 }
|
|
||||||||||||||||
|
||||||||||||
|
|
Definition at line 284 of file w_saber.c. References BG_SabersOff(), gentity_s::clipmask, entityShared_t::contents, CONTENTS_LIGHTSABER, entityShared_t::currentOrigin, ENTITYNUM_NONE, ET_NPC, FP_SABER_OFFENSE, G_DebugBoxLines(), g_entities, G_FreeEntity(), g_saberDebugBox, g_svfps, gentity_s::genericValue5, gentity_t, vmCvar_t::integer, level, MASK_PLAYERSOLID, entityShared_t::maxs, entityShared_t::mins, gentity_s::nextthink, entityShared_t::ownerNum, PMF_FOLLOW, PROPER_THROWN_VALUE, gentity_s::r, TEAM_SPECTATOR, gentity_s::think, level_locals_t::time, trap_LinkEntity(), vec3_t, VectorAdd, and WP_SABER. Referenced by DownedSaberThink(), saberBackToOwner(), saberFirstThrown(), WP_SaberInitBladeData(), and WP_SaberPositionUpdate().
00285 {
00286 if (ent->r.ownerNum == ENTITYNUM_NONE)
00287 {
00288 ent->think = G_FreeEntity;
00289 ent->nextthink = level.time;
00290 return;
00291 }
00292
00293 if (!g_entities[ent->r.ownerNum].inuse ||
00294 !g_entities[ent->r.ownerNum].client/* ||
00295 g_entities[ent->r.ownerNum].client->sess.sessionTeam == TEAM_SPECTATOR*/)
00296 {
00297 ent->think = G_FreeEntity;
00298 ent->nextthink = level.time;
00299 return;
00300 }
00301
00302 if (g_entities[ent->r.ownerNum].client->ps.saberInFlight && g_entities[ent->r.ownerNum].health > 0)
00303 { //let The Master take care of us now (we'll get treated like a missile until we return)
00304 ent->nextthink = level.time;
00305 ent->genericValue5 = PROPER_THROWN_VALUE;
00306 return;
00307 }
00308
00309 ent->genericValue5 = 0;
00310
00311 if (g_entities[ent->r.ownerNum].client->ps.weapon != WP_SABER ||
00312 (g_entities[ent->r.ownerNum].client->ps.pm_flags & PMF_FOLLOW) ||
00313 //RWW ADDED 7-19-03 BEGIN
00314 g_entities[ent->r.ownerNum].client->sess.sessionTeam == TEAM_SPECTATOR ||
00315 g_entities[ent->r.ownerNum].client->tempSpectate >= level.time ||
00316 //RWW ADDED 7-19-03 END
00317 g_entities[ent->r.ownerNum].health < 1 ||
00318 BG_SabersOff( &g_entities[ent->r.ownerNum].client->ps ) ||
00319 (!g_entities[ent->r.ownerNum].client->ps.fd.forcePowerLevel[FP_SABER_OFFENSE] && g_entities[ent->r.ownerNum].s.eType != ET_NPC))
00320 { //owner is not using saber, spectating, dead, saber holstered, or has no attack level
00321 ent->r.contents = 0;
00322 ent->clipmask = 0;
00323 }
00324 else
00325 { //Standard contents (saber is active)
00326 #ifdef DEBUG_SABER_BOX
00327 if (g_saberDebugBox.integer == 1|| g_saberDebugBox.integer == 4)
00328 {
00329 vec3_t dbgMins;
00330 vec3_t dbgMaxs;
00331
00332 VectorAdd( ent->r.currentOrigin, ent->r.mins, dbgMins );
00333 VectorAdd( ent->r.currentOrigin, ent->r.maxs, dbgMaxs );
00334
00335 G_DebugBoxLines(dbgMins, dbgMaxs, (10.0f/(float)g_svfps.integer)*100);
00336 }
00337 #endif
00338 if (ent->r.contents != CONTENTS_LIGHTSABER)
00339 {
00340 if ((level.time - g_entities[ent->r.ownerNum].client->lastSaberStorageTime) <= 200)
00341 { //Only go back to solid once we're sure our owner has updated recently
00342 ent->r.contents = CONTENTS_LIGHTSABER;
00343 ent->clipmask = MASK_PLAYERSOLID | CONTENTS_LIGHTSABER;
00344 }
00345 }
00346 else
00347 {
00348 ent->r.contents = CONTENTS_LIGHTSABER;
00349 ent->clipmask = MASK_PLAYERSOLID | CONTENTS_LIGHTSABER;
00350 }
00351 }
00352
00353 trap_LinkEntity(ent);
00354
00355 ent->nextthink = level.time;
00356 }
|
|
||||||||||||||||
|
Definition at line 7078 of file w_saber.c. References entityState_s::apos, entityShared_t::contents, CONTENTS_LIGHTSABER, entityShared_t::currentOrigin, g_entities, gentity_t, level, MAX_CLIENTS, gentity_s::nextthink, entityState_s::number, entityShared_t::ownerNum, entityState_s::pos, qtrue, gentity_s::r, gentity_s::s, saberBackToOwner(), gentity_s::speed, gentity_s::think, level_locals_t::time, TR_LINEAR, trajectory_t::trBase, trajectory_t::trDelta, trajectory_t::trTime, trajectory_t::trType, VectorClear, and VectorCopy. Referenced by saberFirstThrown(), saberReactivate(), and WP_SaberPositionUpdate().
07079 {
07080 gentity_t *hitEnt = other;
07081
07082 if (other && other->s.number == saberent->r.ownerNum)
07083 {
07084 return;
07085 }
07086 VectorClear(saberent->s.pos.trDelta);
07087 saberent->s.pos.trTime = level.time;
07088
07089 saberent->s.apos.trType = TR_LINEAR;
07090 saberent->s.apos.trDelta[0] = 0;
07091 saberent->s.apos.trDelta[1] = 800;
07092 saberent->s.apos.trDelta[2] = 0;
07093
07094 VectorCopy(saberent->r.currentOrigin, saberent->s.pos.trBase);
07095
07096 saberent->think = saberBackToOwner;
07097 saberent->nextthink = level.time;
07098
07099 if (other && other->r.ownerNum < MAX_CLIENTS &&
07100 (other->r.contents & CONTENTS_LIGHTSABER) &&
07101 g_entities[other->r.ownerNum].client &&
07102 g_entities[other->r.ownerNum].inuse)
07103 {
07104 hitEnt = &g_entities[other->r.ownerNum];
07105 }
07106
07107 //we'll skip the dist check, since we don't really care about that (we just hit it physically)
07108 CheckThrownSaberDamaged(saberent, &g_entities[saberent->r.ownerNum], hitEnt, 256, 0, qtrue);
07109
07110 saberent->speed = 0;
07111 }
|
|
||||||||||||||||||||||||||||
|
Definition at line 198 of file tri_coll_test.c. References COMPUTE_INTERVALS, CROSS, DOT, EPSILON, fabs(), qboolean, qfalse, qtrue, SORT, SUB, and vec3_t. Referenced by WP_SabersIntersect().
00200 {
00201 vec3_t E1,E2;
00202 vec3_t N1,N2;
00203 float d1,d2;
00204 float du0,du1,du2,dv0,dv1,dv2;
00205 vec3_t D;
00206 float isect1[2], isect2[2];
00207 float du0du1,du0du2,dv0dv1,dv0dv2;
00208 short index;
00209 float vp0,vp1,vp2;
00210 float up0,up1,up2;
00211 float b,c,max;
00212
00213 /* compute plane equation of triangle(V0,V1,V2) */
00214 SUB(E1,V1,V0);
00215 SUB(E2,V2,V0);
00216 CROSS(N1,E1,E2);
00217 d1=-DOT(N1,V0);
00218 /* plane equation 1: N1.X+d1=0 */
00219
00220 /* put U0,U1,U2 into plane equation 1 to compute signed distances to the plane*/
00221 du0=DOT(N1,U0)+d1;
00222 du1=DOT(N1,U1)+d1;
00223 du2=DOT(N1,U2)+d1;
00224
00225 /* coplanarity robustness check */
00226 #if USE_EPSILON_TEST
00227 if(fabs(du0)<EPSILON) du0=0.0;
00228 if(fabs(du1)<EPSILON) du1=0.0;
00229 if(fabs(du2)<EPSILON) du2=0.0;
00230 #endif
00231 du0du1=du0*du1;
00232 du0du2=du0*du2;
00233
00234 if(du0du1>0.0f && du0du2>0.0f) /* same sign on all of them + not equal 0 ? */
00235 return 0; /* no intersection occurs */
00236
00237 /* compute plane of triangle (U0,U1,U2) */
00238 SUB(E1,U1,U0);
00239 SUB(E2,U2,U0);
00240 CROSS(N2,E1,E2);
00241 d2=-DOT(N2,U0);
00242 /* plane equation 2: N2.X+d2=0 */
00243
00244 /* put V0,V1,V2 into plane equation 2 */
00245 dv0=DOT(N2,V0)+d2;
00246 dv1=DOT(N2,V1)+d2;
00247 dv2=DOT(N2,V2)+d2;
00248
00249 #if USE_EPSILON_TEST
00250 if(fabs(dv0)<EPSILON) dv0=0.0;
00251 if(fabs(dv1)<EPSILON) dv1=0.0;
00252 if(fabs(dv2)<EPSILON) dv2=0.0;
00253 #endif
00254
00255 dv0dv1=dv0*dv1;
00256 dv0dv2=dv0*dv2;
00257
00258 if(dv0dv1>0.0f && dv0dv2>0.0f) /* same sign on all of them + not equal 0 ? */
00259 return 0; /* no intersection occurs */
00260
00261 /* compute direction of intersection line */
00262 CROSS(D,N1,N2);
00263
00264 /* compute and index to the largest component of D */
00265 max=fabs(D[0]);
00266 index=0;
00267 b=fabs(D[1]);
00268 c=fabs(D[2]);
00269 if(b>max) max=b,index=1;
00270 if(c>max) max=c,index=2;
00271
00272 /* this is the simplified projection onto L*/
00273 vp0=V0[index];
00274 vp1=V1[index];
00275 vp2=V2[index];
00276
00277 up0=U0[index];
00278 up1=U1[index];
00279 up2=U2[index];
00280
00281 /* compute interval for triangle 1 */
00282 COMPUTE_INTERVALS(vp0,vp1,vp2,dv0,dv1,dv2,dv0dv1,dv0dv2,isect1[0],isect1[1]);
00283
00284 /* compute interval for triangle 2 */
00285 COMPUTE_INTERVALS(up0,up1,up2,du0,du1,du2,du0du1,du0du2,isect2[0],isect2[1]);
00286
00287 SORT(isect1[0],isect1[1]);
00288 SORT(isect2[0],isect2[1]);
00289
00290 if(isect1[1]<isect2[0] || isect2[1]<isect1[0]) return qtrue;
00291 return qfalse;
00292 } |
|
||||||||||||||||
|
Definition at line 7257 of file w_saber.c. References renderInfo_s::boltValidityTime, gentity_s::client, renderInfo_s::crotchBolt, renderInfo_s::crotchPoint, renderInfo_s::footLBolt, renderInfo_s::footLPoint, renderInfo_s::footRBolt, renderInfo_s::footRPoint, gentity_t, gentity_s::ghoul2, renderInfo_s::handLBolt, renderInfo_s::handLPoint, renderInfo_s::handRBolt, renderInfo_s::handRPoint, renderInfo_s::headBolt, renderInfo_s::headPoint, level, mdxaBone_t::matrix, gentity_s::modelScale, NULL, playerState_s::origin, gclient_s::ps, gclient_s::renderInfo, renderInfo_t, level_locals_t::time, renderInfo_s::torsoBolt, renderInfo_s::torsoPoint, trap_G2API_GetBoltMatrix(), vec3_t, and VectorCopy. Referenced by G_GetHitLocFromSurfName().
07258 {
07259 mdxaBone_t boltMatrix;
07260 renderInfo_t *ri = &self->client->renderInfo;
07261
07262 if (!self->ghoul2)
07263 {
07264 VectorCopy(self->client->ps.origin, ri->headPoint);
07265 VectorCopy(self->client->ps.origin, ri->handRPoint);
07266 VectorCopy(self->client->ps.origin, ri->handLPoint);
07267 VectorCopy(self->client->ps.origin, ri->torsoPoint);
07268 VectorCopy(self->client->ps.origin, ri->crotchPoint);
07269 VectorCopy(self->client->ps.origin, ri->footRPoint);
07270 VectorCopy(self->client->ps.origin, ri->footLPoint);
07271 }
07272 else
07273 {
07274 //head
07275 trap_G2API_GetBoltMatrix(self->ghoul2, 0, ri->headBolt, &boltMatrix, renderAngles, renderOrigin, level.time, NULL, self->modelScale);
07276 ri->headPoint[0] = boltMatrix.matrix[0][3];
07277 ri->headPoint[1] = boltMatrix.matrix[1][3];
07278 ri->headPoint[2] = boltMatrix.matrix[2][3];
07279
07280 //right hand
07281 trap_G2API_GetBoltMatrix(self->ghoul2, 0, ri->handRBolt, &boltMatrix, renderAngles, renderOrigin, level.time, NULL, self->modelScale);
07282 ri->handRPoint[0] = boltMatrix.matrix[0][3];
07283 ri->handRPoint[1] = boltMatrix.matrix[1][3];
07284 ri->handRPoint[2] = boltMatrix.matrix[2][3];
07285
07286 //left hand
07287 trap_G2API_GetBoltMatrix(self->ghoul2, 0, ri->handLBolt, &boltMatrix, renderAngles, renderOrigin, level.time, NULL, self->modelScale);
07288 ri->handLPoint[0] = boltMatrix.matrix[0][3];
07289 ri->handLPoint[1] = boltMatrix.matrix[1][3];
07290 ri->handLPoint[2] = boltMatrix.matrix[2][3];
07291
07292 //chest
07293 trap_G2API_GetBoltMatrix(self->ghoul2, 0, ri->torsoBolt, &boltMatrix, renderAngles, renderOrigin, level.time, NULL, self->modelScale);
07294 ri->torsoPoint[0] = boltMatrix.matrix[0][3];
07295 ri->torsoPoint[1] = boltMatrix.matrix[1][3];
07296 ri->torsoPoint[2] = boltMatrix.matrix[2][3];
07297
07298 //crotch
07299 trap_G2API_GetBoltMatrix(self->ghoul2, 0, ri->crotchBolt, &boltMatrix, renderAngles, renderOrigin, level.time, NULL, self->modelScale);
07300 ri->crotchPoint[0] = boltMatrix.matrix[0][3];
07301 ri->crotchPoint[1] = boltMatrix.matrix[1][3];
07302 ri->crotchPoint[2] = boltMatrix.matrix[2][3];
07303
07304 //right foot
07305 trap_G2API_GetBoltMatrix(self->ghoul2, 0, ri->footRBolt, &boltMatrix, renderAngles, renderOrigin, level.time, NULL, self->modelScale);
07306 ri->footRPoint[0] = boltMatrix.matrix[0][3];
07307 ri->footRPoint[1] = boltMatrix.matrix[1][3];
07308 ri->footRPoint[2] = boltMatrix.matrix[2][3];
07309
07310 //left foot
07311 trap_G2API_GetBoltMatrix(self->ghoul2, 0, ri->footLBolt, &boltMatrix, renderAngles, renderOrigin, level.time, NULL, self->modelScale);
07312 ri->footLPoint[0] = boltMatrix.matrix[0][3];
07313 ri->footLPoint[1] = boltMatrix.matrix[1][3];
07314 ri->footLPoint[2] = boltMatrix.matrix[2][3];
07315 }
07316
07317 self->client->renderInfo.boltValidityTime = level.time;
07318 }
|
|
||||||||||||||||
|
Definition at line 7320 of file w_saber.c. References AngleVectors(), bgAllAnims, gentity_s::client, renderInfo_s::crotchBolt, renderInfo_s::crotchPoint, renderInfo_s::customAlpha, renderInfo_s::customRGB, renderInfo_s::eyeAngles, renderInfo_s::eyePoint, renderInfo_s::footLBolt, renderInfo_s::footLPoint, renderInfo_s::footRBolt, renderInfo_s::footRPoint, g_debugServerSkel, G_TestLine(), gentity_t, gentity_s::ghoul2, renderInfo_s::handLBolt, renderInfo_s::handLPoint, renderInfo_s::handRBolt, renderInfo_s::handRPoint, renderInfo_s::headAngles, renderInfo_s::headBolt, renderInfo_s::headPitchRangeDown, renderInfo_s::headPitchRangeUp, renderInfo_s::headPoint, renderInfo_s::headYawRangeLeft, renderInfo_s::headYawRangeRight, vmCvar_t::integer, renderInfo_s::lastG2, playerState_s::legsAnim, renderInfo_s::legsFpsMod, renderInfo_s::legsFrame, renderInfo_s::legsYaw, level, gentity_s::localAnimIndex, renderInfo_s::lockYaw, mdxaBone_t::matrix, gentity_s::modelScale, renderInfo_s::motionBolt, renderInfo_s::mPCalcTime, renderInfo_s::muzzleDir, renderInfo_s::muzzleDirOld, renderInfo_s::muzzlePoint, renderInfo_s::muzzlePointOld, NULL, playerState_s::origin, gclient_s::ps, renderInfo_s::renderFlags, gclient_s::renderInfo, renderInfo_t, level_locals_t::time, renderInfo_s::torsoAngles, playerState_s::torsoAnim, renderInfo_s::torsoBolt, renderInfo_s::torsoFpsMod, renderInfo_s::torsoFrame, renderInfo_s::torsoPitchRangeDown, renderInfo_s::torsoPitchRangeUp, renderInfo_s::torsoPoint, renderInfo_s::torsoYawRangeLeft, renderInfo_s::torsoYawRangeRight, trap_G2API_AddBolt(), trap_G2API_GetBoltMatrix(), vec3_t, VectorClear, VectorCopy, playerState_s::viewangles, and playerState_s::viewheight. Referenced by WP_SaberPositionUpdate().
07321 {
07322 renderInfo_t *ri = &self->client->renderInfo;
07323 if ( ri->mPCalcTime < level.time )
07324 {
07325 //We're just going to give rough estimates on most of this stuff,
07326 //it's not like most of it matters.
07327
07328 #if 0 //#if 0'd since it's a waste setting all this to 0 each frame.
07329 //Should you wish to make any of this valid then feel free to do so.
07330 ri->headYawRangeLeft = ri->headYawRangeRight = ri->headPitchRangeUp = ri->headPitchRangeDown = 0;
07331 ri->torsoYawRangeLeft = ri->torsoYawRangeRight = ri->torsoPitchRangeUp = ri->torsoPitchRangeDown = 0;
07332
07333 ri->torsoFpsMod = ri->legsFpsMod = 0;
07334
07335 VectorClear(ri->customRGB);
07336 ri->customAlpha = 0;
07337 ri->renderFlags = 0;
07338 ri->lockYaw = 0;
07339
07340 VectorClear(ri->headAngles);
07341 VectorClear(ri->torsoAngles);
07342
07343 //VectorClear(ri->eyeAngles);
07344
07345 ri->legsYaw = 0;
07346 #endif
07347
07348 if (self->ghoul2 &&
07349 self->ghoul2 != ri->lastG2)
07350 { //the g2 instance changed, so update all the bolts.
07351 //rwwFIXMEFIXME: Base on skeleton used? Assuming humanoid currently.
07352 ri->lastG2 = self->ghoul2;
07353
07354 if (self->localAnimIndex <= 1)
07355 {
07356 ri->headBolt = trap_G2API_AddBolt(self->ghoul2, 0, "*head_eyes");
07357 ri->handRBolt = trap_G2API_AddBolt(self->ghoul2, 0, "*r_hand");
07358 ri->handLBolt = trap_G2API_AddBolt(self->ghoul2, 0, "*l_hand");
07359 ri->torsoBolt = trap_G2API_AddBolt(self->ghoul2, 0, "thoracic");
07360 ri->crotchBolt = trap_G2API_AddBolt(self->ghoul2, 0, "pelvis");
07361 ri->footRBolt = trap_G2API_AddBolt(self->ghoul2, 0, "*r_leg_foot");
07362 ri->footLBolt = trap_G2API_AddBolt(self->ghoul2, 0, "*l_leg_foot");
07363 ri->motionBolt = trap_G2API_AddBolt(self->ghoul2, 0, "Motion");
07364 }
07365 else
07366 {
07367 ri->headBolt = -1;
07368 ri->handRBolt = -1;
07369 ri->handLBolt = -1;
07370 ri->torsoBolt = -1;
07371 ri->crotchBolt = -1;
07372 ri->footRBolt = -1;
07373 ri->footLBolt = -1;
07374 ri->motionBolt = -1;
07375 }
07376
07377 ri->lastG2 = self->ghoul2;
07378 }
07379
07380 VectorCopy( self->client->ps.viewangles, self->client->renderInfo.eyeAngles );
07381
07382 //we'll just say the legs/torso are whatever the first frame of our current anim is.
07383 ri->torsoFrame = bgAllAnims[self->localAnimIndex].anims[self->client->ps.torsoAnim].firstFrame;
07384 ri->legsFrame = bgAllAnims[self->localAnimIndex].anims[self->client->ps.legsAnim].firstFrame;
07385 if (g_debugServerSkel.integer)
07386 { //Alright, I was doing this, but it's just too slow to do every frame.
07387 //From now on if we want this data to be valid we're going to have to make a verify call for it before
07388 //accessing it. I'm only doing this now if we want to debug the server skel by drawing lines from bolt
07389 //positions every frame.
07390 mdxaBone_t boltMatrix;
07391
07392 if (!self->ghoul2)
07393 {
07394 VectorCopy(self->client->ps.origin, ri->headPoint);
07395 VectorCopy(self->client->ps.origin, ri->handRPoint);
07396 VectorCopy(self->client->ps.origin, ri->handLPoint);
07397 VectorCopy(self->client->ps.origin, ri->torsoPoint);
07398 VectorCopy(self->client->ps.origin, ri->crotchPoint);
07399 VectorCopy(self->client->ps.origin, ri->footRPoint);
07400 VectorCopy(self->client->ps.origin, ri->footLPoint);
07401 }
07402 else
07403 {
07404 //head
07405 trap_G2API_GetBoltMatrix(self->ghoul2, 0, ri->headBolt, &boltMatrix, renderAngles, renderOrigin, level.time, NULL, self->modelScale);
07406 ri->headPoint[0] = boltMatrix.matrix[0][3];
07407 ri->headPoint[1] = boltMatrix.matrix[1][3];
07408 ri->headPoint[2] = boltMatrix.matrix[2][3];
07409
07410 //right hand
07411 trap_G2API_GetBoltMatrix(self->ghoul2, 0, ri->handRBolt, &boltMatrix, renderAngles, renderOrigin, level.time, NULL, self->modelScale);
07412 ri->handRPoint[0] = boltMatrix.matrix[0][3];
07413 ri->handRPoint[1] = boltMatrix.matrix[1][3];
07414 ri->handRPoint[2] = boltMatrix.matrix[2][3];
07415
07416 //left hand
07417 trap_G2API_GetBoltMatrix(self->ghoul2, 0, ri->handLBolt, &boltMatrix, renderAngles, renderOrigin, level.time, NULL, self->modelScale);
07418 ri->handLPoint[0] = boltMatrix.matrix[0][3];
07419 ri->handLPoint[1] = boltMatrix.matrix[1][3];
07420 ri->handLPoint[2] = boltMatrix.matrix[2][3];
07421
07422 //chest
07423 trap_G2API_GetBoltMatrix(self->ghoul2, 0, ri->torsoBolt, &boltMatrix, renderAngles, renderOrigin, level.time, NULL, self->modelScale);
07424 ri->torsoPoint[0] = boltMatrix.matrix[0][3];
07425 ri->torsoPoint[1] = boltMatrix.matrix[1][3];
07426 ri->torsoPoint[2] = boltMatrix.matrix[2][3];
07427
07428 //crotch
07429 trap_G2API_GetBoltMatrix(self->ghoul2, 0, ri->crotchBolt, &boltMatrix, renderAngles, renderOrigin, level.time, NULL, self->modelScale);
07430 ri->crotchPoint[0] = boltMatrix.matrix[0][3];
07431 ri->crotchPoint[1] = boltMatrix.matrix[1][3];
07432 ri->crotchPoint[2] = boltMatrix.matrix[2][3];
07433
07434 //right foot
07435 trap_G2API_GetBoltMatrix(self->ghoul2, 0, ri->footRBolt, &boltMatrix, renderAngles, renderOrigin, level.time, NULL, self->modelScale);
07436 ri->footRPoint[0] = boltMatrix.matrix[0][3];
07437 ri->footRPoint[1] = boltMatrix.matrix[1][3];
07438 ri->footRPoint[2] = boltMatrix.matrix[2][3];
07439
07440 //left foot
07441 trap_G2API_GetBoltMatrix(self->ghoul2, 0, ri->footLBolt, &boltMatrix, renderAngles, renderOrigin, level.time, NULL, self->modelScale);
07442 ri->footLPoint[0] = boltMatrix.matrix[0][3];
07443 ri->footLPoint[1] = boltMatrix.matrix[1][3];
07444 ri->footLPoint[2] = boltMatrix.matrix[2][3];
07445 }
07446
07447 //Now draw the skel for debug
07448 G_TestLine(ri->headPoint, ri->torsoPoint, 0x000000ff, 50);
07449 G_TestLine(ri->torsoPoint, ri->handRPoint, 0x000000ff, 50);
07450 G_TestLine(ri->torsoPoint, ri->handLPoint, 0x000000ff, 50);
07451 G_TestLine(ri->torsoPoint, ri->crotchPoint, 0x000000ff, 50);
07452 G_TestLine(ri->crotchPoint, ri->footRPoint, 0x000000ff, 50);
07453 G_TestLine(ri->crotchPoint, ri->footLPoint, 0x000000ff, 50);
07454 }
07455
07456 //muzzle point calc (we are going to be cheap here)
07457 VectorCopy(ri->muzzlePoint, ri->muzzlePointOld);
07458 VectorCopy(self->client->ps.origin, ri->muzzlePoint);
07459 VectorCopy(ri->muzzleDir, ri->muzzleDirOld);
07460 AngleVectors(self->client->ps.viewangles, ri->muzzleDir, 0, 0);
07461 ri->mPCalcTime = level.time;
07462
07463 VectorCopy(self->client->ps.origin, ri->eyePoint);
07464 ri->eyePoint[2] += self->client->ps.viewheight;
07465 }
07466 }
|
|
||||||||||||
|
Definition at line 5273 of file w_saber.c. References GAME_INLINE, and vec3_t. Referenced by G_SPSaberDamageTraceLerped().
05273 {
05274 if ( v1[0] > v2[0]+0.0001f || v1[0] < v2[0]-0.0001f
05275 || v1[1] > v2[1]+0.0001f || v1[1] < v2[1]-0.0001f
05276 || v1[2] > v2[2]+0.0001f || v1[2] < v2[2]-0.0001f ) {
05277 return 0;
05278 }
05279 return 1;
05280 }
|
|
|
Definition at line 248 of file w_saber.c. References CHAN_WEAPON, gentity_s::client, playerState_s::fd, forcedata_s::forceGripCripple, playerState_s::forceHandExtend, playerState_s::forceHandExtendTime, G_Sound(), gentity_t, HANDEXTEND_JEDITAUNT, HANDEXTEND_NONE, level, gentity_s::NPC, gclient_s::ps, gclient_s::saber, playerState_s::saberHolstered, saberInfo_t::soundOn, and level_locals_t::time. Referenced by Jedi_Ambush(), and WP_SaberStartMissileBlockCheck().
00249 {
00250 if ( !self || !self->client )
00251 {
00252 return;
00253 }
00254
00255 if (self->NPC &&
00256 self->client->ps.forceHandExtend == HANDEXTEND_JEDITAUNT &&
00257 (self->client->ps.forceHandExtendTime - level.time) > 200)
00258 { //if we're an NPC and in the middle of a taunt then stop it
00259 self->client->ps.forceHandExtend = HANDEXTEND_NONE;
00260 self->client->ps.forceHandExtendTime = 0;
00261 }
00262 else if (self->client->ps.fd.forceGripCripple)
00263 { //can't activate saber while being gripped
00264 return;
00265 }
00266
00267 if ( self->client->ps.saberHolstered )
00268 {
00269 self->client->ps.saberHolstered = 0;
00270 if (self->client->saber[0].soundOn)
00271 {
00272 G_Sound(self, CHAN_WEAPON, self->client->saber[0].soundOn);
00273 }
00274
00275 if (self->client->saber[1].soundOn)
00276 {
00277 G_Sound(self, CHAN_WEAPON, self->client->saber[1].soundOn);
00278 }
00279 }
00280 }
|
|
||||||||||||
|
Definition at line 217 of file w_saber.c. References CHAN_WEAPON, gentity_s::client, G_Sound(), gentity_t, saberInfo_t::model, gclient_s::ps, gclient_s::saber, playerState_s::saberHolstered, and saberInfo_t::soundOff.
00218 {
00219 if ( !self || !self->client )
00220 {
00221 return;
00222 }
00223 //keep my saber off!
00224 if ( !self->client->ps.saberHolstered )
00225 {
00226 self->client->ps.saberHolstered = 2;
00227 /*
00228 if ( clearLength )
00229 {
00230 self->client->ps.SetSaberLength( 0 );
00231 }
00232 */
00233 //Doens't matter ATM
00234 if (self->client->saber[0].soundOff)
00235 {
00236 G_Sound(self, CHAN_WEAPON, self->client->saber[0].soundOff);
00237 }
00238
00239 if (self->client->saber[1].soundOff &&
00240 self->client->saber[1].model[0])
00241 {
00242 G_Sound(self, CHAN_WEAPON, self->client->saber[1].soundOff);
00243 }
00244
00245 }
00246 }
|
|
||||||||||||
|
Definition at line 813 of file w_force.c. References BG_CanUseFPNow(), BG_HasYsalamiri(), gentity_s::client, EF_DEAD, playerState_s::eFlags, playerState_s::fd, gclient_s::fjDidJump, forcedata_s::forcePowerLevel, forcePowers_t, forcedata_s::forcePowersActive, forcedata_s::forcePowersKnown, saberInfo_t::forceRestrictions, FP_DRAIN, FP_GRIP, FP_LEVITATION, FP_LIGHTNING, FP_PULL, FP_PUSH, FP_SABER_DEFENSE, FP_SABER_OFFENSE, FP_SABERTHROW, FP_TELEPATHY, g_debugMelee, g_gametype, g_saberRestrictForce, gentity_t, gentity_s::health, vmCvar_t::integer, level, saberInfo_t::model, playerState_s::pm_flags, PMF_FOLLOW, PMF_STUCK_TO_WALL, gclient_s::ps, qboolean, qfalse, gclient_s::saber, saberInfo_t::saberFlags, playerState_s::saberHolstered, gclient_s::sess, clientSession_t::sessionTeam, SFL_TWO_HANDED, STAT_HEALTH, playerState_s::stats, TEAM_SPECTATOR, gclient_s::tempSpectate, level_locals_t::time, and WP_ForcePowerAvailable(). Referenced by CanCounterThrow(), ForceAbsorb(), ForceDrain(), ForceGrip(), ForceHeal(), ForceJump(), ForceLightning(), ForceProtect(), ForceRage(), ForceSeeing(), ForceSpeed(), ForceTeamForceReplenish(), ForceTeamHeal(), ForceTelepathy(), ForceThrow(), Jedi_DodgeEvasion(), and WP_SaberStartMissileBlockCheck().
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 { //specs can't use powers through people
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 {//don't know this power
00846 return qfalse;
00847 }
00848
00849 if ( (self->client->ps.fd.forcePowersActive & ( 1 << forcePower )) )
00850 {//already using this power
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 {//no offensive force powers when stuck to wall
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 {//this saber requires the use of two hands OR our other hand is using an active saber too
00908 if ( (self->client->saber[0].forceRestrictions&(1<<forcePower)) )
00909 {//this power is verboten when using this saber
00910 return qfalse;
00911 }
00912 }
00913
00914 if ( self->client->saber[0].model
00915 && self->client->saber[0].model[0] )
00916 {//both sabers on
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 {//this power is verboten when using this saber
00933 return qfalse;
00934 }
00935 }
00936 }
00937 return WP_ForcePowerAvailable( self, forcePower, 0 ); // OVERRIDEFIXME
00938 }
|
|
|
Definition at line 9099 of file w_saber.c. References BLOCKED_LOWER_LEFT, BLOCKED_LOWER_LEFT_PROJ, BLOCKED_LOWER_RIGHT, BLOCKED_LOWER_RIGHT_PROJ, BLOCKED_TOP, BLOCKED_TOP_PROJ, BLOCKED_UPPER_LEFT, BLOCKED_UPPER_LEFT_PROJ, BLOCKED_UPPER_RIGHT, and BLOCKED_UPPER_RIGHT_PROJ. Referenced by Jedi_SaberBlockGo(), WP_SaberBlock(), and WP_SaberBlockNonRandom().
09100 {
09101 switch( saberBlock )
09102 {
09103 case BLOCKED_UPPER_RIGHT:
09104 return BLOCKED_UPPER_RIGHT_PROJ;
09105 break;
09106 case BLOCKED_UPPER_LEFT:
09107 return BLOCKED_UPPER_LEFT_PROJ;
09108 break;
09109 case BLOCKED_LOWER_RIGHT:
09110 return BLOCKED_LOWER_RIGHT_PROJ;
09111 break;
09112 case BLOCKED_LOWER_LEFT:
09113 return BLOCKED_LOWER_LEFT_PROJ;
09114 break;
09115 case BLOCKED_TOP:
09116 return BLOCKED_TOP_PROJ;
09117 break;
09118 }
09119 return saberBlock;
09120 }
|
|
||||||||||||||||
|
Referenced by MakeDeadSaber(), saberKnockDown(), saberKnockOutOfHand(), ThrowSaberToAttacker(), and WP_SaberPositionUpdate(). |
|
|
Definition at line 3575 of file w_saber.c. References gentity_s::client, DAMAGE_NO_DISMEMBER, G_Damage(), g_entities, g_saberWallDamageScale, gentity_t, MOD_SABER, NULL, and vmCvar_t::value. Referenced by WP_SaberPositionUpdate().
03576 {
03577 int i;
03578 if ( !numVictims )
03579 {
03580 return;
03581 }
03582 for ( i = 0; i < numVictims; i++ )
03583 {
03584 gentity_t *victim = NULL;
03585 int dflags = 0;
03586
03587 victim = &g_entities[victimEntityNum[i]];
03588
03589 // nmckenzie: SABER_DAMAGE_WALLS
03590 if ( !victim->client )
03591 {
03592 totalDmg[i] *= g_saberWallDamageScale.value;
03593 }
03594
03595 if ( !dismemberDmg[i] )
03596 {//don't do dismemberment!
03597 dflags |= DAMAGE_NO_DISMEMBER;
03598 }
03599 dflags |= saberKnockbackFlags[i];
03600
03601 G_Damage( victim, self, self, dmgDir[i], dmgSpot[i], totalDmg[i], dflags, MOD_SABER );
03602 }
03603 }
|
|
||||||||||||
|
Definition at line 230 of file bg_saberLoad.c. References qboolean, qfalse, qtrue, saberInfo_t::saberFlags2, SFL2_TRANSITION_DAMAGE, SFL2_TRANSITION_DAMAGE2, and WP_SaberBladeUseSecondBladeStyle().
00231 {
00232 if ( !WP_SaberBladeUseSecondBladeStyle( saber, bladeNum )
00233 && (saber->saberFlags2&SFL2_TRANSITION_DAMAGE) )
00234 {//use first blade style for this blade
00235 return qtrue;
00236 }
00237 else if ( WP_SaberBladeUseSecondBladeStyle( saber, bladeNum )
00238 && (saber->saberFlags2&SFL2_TRANSITION_DAMAGE2) )
00239 {//use second blade style for this blade
00240 return qtrue;
00241 }
00242 return qfalse;
00243 }
|
|
|
Definition at line 2777 of file w_saber.c. References saberInfo_t::blade, bladeInfo_t::lengthMax, and saberInfo_t::numBlades. Referenced by WP_SaberLength().
|
|
||||||||||||
|
Definition at line 215 of file bg_saberLoad.c. References saberInfo_t::bladeStyle2Start, qboolean, qfalse, and qtrue. Referenced by CG_AddSaberBlade(), CG_EntityEvent(), CG_SaberCompWork(), WP_SaberBladeDoTransitionDamage(), WP_SaberBounceSound(), and WP_SaberDoHit().
00216 {
00217 if ( saber )
00218 {
00219 if ( saber->bladeStyle2Start > 0 )
00220 {
00221 if ( bladeNum >= saber->bladeStyle2Start )
00222 {
00223 return qtrue;
00224 }
00225 }
00226 }
00227 return qfalse;
00228 }
|
|
||||||||||||||||
|
Definition at line 9195 of file w_saber.c. References AngleVectors(), BLOCKED_LOWER_LEFT, BLOCKED_LOWER_RIGHT, BLOCKED_TOP, BLOCKED_UPPER_LEFT, BLOCKED_UPPER_RIGHT, gentity_s::client, DotProduct, gentity_t, NULL, playerState_s::origin, gclient_s::ps, Q_irand(), RandFloat(), playerState_s::saberBlocked, vec3_t, VectorNormalize(), VectorSubtract, playerState_s::viewangles, and WP_MissileBlockForBlock().
09196 {
09197 vec3_t diff, fwdangles={0,0,0}, right;
09198 float rightdot;
09199 float zdiff;
09200
09201 VectorSubtract(hitloc, playerent->client->ps.origin, diff);
09202 VectorNormalize(diff);
09203
09204 fwdangles[1] = playerent->client->ps.viewangles[1];
09205 // Ultimately we might care if the shot was ahead or behind, but for now, just quadrant is fine.
09206 AngleVectors( fwdangles, NULL, right, NULL );
09207
09208 rightdot = DotProduct(right, diff) + RandFloat(-0.2f,0.2f);
09209 zdiff = hitloc[2] - playerent->client->ps.origin[2] + Q_irand(-8,8);
09210
09211 // Figure out what quadrant the block was in.
09212 if (zdiff > 24)
09213 { // Attack from above
09214 if (Q_irand(0,1))
09215 {
09216 playerent->client->ps.saberBlocked = BLOCKED_TOP;
09217 }
09218 else
09219 {
09220 playerent->client->ps.saberBlocked = BLOCKED_UPPER_LEFT;
09221 }
09222 }
09223 else if (zdiff > 13)
09224 { // The upper half has three viable blocks...
09225 if (rightdot > 0.25)
09226 { // In the right quadrant...
09227 if (Q_irand(0,1))
09228 {
09229 playerent->client->ps.saberBlocked = BLOCKED_UPPER_LEFT;
09230 }
09231 else
09232 {
09233 playerent->client->ps.saberBlocked = BLOCKED_LOWER_LEFT;
09234 }
09235 }
09236 else
09237 {
09238 switch(Q_irand(0,3))
09239 {
09240 case 0:
09241 playerent->client->ps.saberBlocked = BLOCKED_UPPER_RIGHT;
09242 break;
09243 case 1:
09244 case 2:
09245 playerent->client->ps.saberBlocked = BLOCKED_LOWER_RIGHT;
09246 break;
09247 case 3:
09248 playerent->client->ps.saberBlocked = BLOCKED_TOP;
09249 break;
09250 }
09251 }
09252 }
09253 else
09254 { // The lower half is a bit iffy as far as block coverage. Pick one of the "low" ones at random.
09255 if (Q_irand(0,1))
09256 {
09257 playerent->client->ps.saberBlocked = BLOCKED_LOWER_RIGHT;
09258 }
09259 else
09260 {
09261 playerent->client->ps.saberBlocked = BLOCKED_LOWER_LEFT;
09262 }
09263 }
09264
09265 if ( missileBlock )
09266 {
09267 playerent->client->ps.saberBlocked = WP_MissileBlockForBlock( playerent->client->ps.saberBlocked );
09268 }
09269 }
|
|
||||||||||||||||
|
Referenced by G_MissileImpact(), WP_SaberCanBlock(), and WP_SaberStartMissileBlockCheck(). |
|
||||||||||||||||
|
Definition at line 3810 of file w_saber.c. References saberInfo_t::block2Sound, saberInfo_t::blockSound, saberInfo_t::bounce2Sound, saberInfo_t::bounceSound, CHAN_AUTO, gentity_s::client, G_Sound(), G_SoundIndex(), gentity_t, Q_irand(), gclient_s::saber, va(), and WP_SaberBladeUseSecondBladeStyle().
03811 {
03812 int index = 1;
03813 if ( !ent || !ent->client )
03814 {
03815 return;
03816 }
03817 index = Q_irand( 1, 9 );
03818 if ( !WP_SaberBladeUseSecondBladeStyle( &ent->client->saber[saberNum], bladeNum )
03819 && ent->client->saber[saberNum].bounceSound[0] )
03820 {
03821 G_Sound( ent, CHAN_AUTO, ent->client->saber[saberNum].bounceSound[Q_irand( 0, 2 )] );
03822 }
03823 else if ( WP_SaberBladeUseSecondBladeStyle( &ent->client->saber[saberNum], bladeNum )
03824 && ent->client->saber[saberNum].bounce2Sound[0] )
03825 {
03826 G_Sound( ent, CHAN_AUTO, ent->client->saber[saberNum].bounce2Sound[Q_irand( 0, 2 )] );
03827 }
03828 else if ( !WP_SaberBladeUseSecondBladeStyle( &ent->client->saber[saberNum], bladeNum )
03829 && ent->client->saber[saberNum].blockSound[0] )
03830 {
03831 G_Sound( ent, CHAN_AUTO, ent->client->saber[saberNum].blockSound[Q_irand( 0, 2 )] );
03832 }
03833 else if ( WP_SaberBladeUseSecondBladeStyle( &ent->client->saber[saberNum], bladeNum )
03834 && ent->client->saber[saberNum].block2Sound[0] )
03835 {
03836 G_Sound( ent, CHAN_AUTO, ent->client->saber[saberNum].block2Sound[Q_irand( 0, 2 )] );
03837 }
03838 else
03839 {
03840 G_Sound( ent, CHAN_AUTO, G_SoundIndex( va( "sound/weapons/saber/saberblock%d.wav", index ) ) );
03841 }
03842 }
|
|
||||||||||||||||||||||||||||
|
Definition at line 9271 of file w_saber.c. References BG_SaberInAttack(), BG_SabersOff(), BUTTON_ATTACK, usercmd_s::buttons, gentity_s::client, clientPersistant_t::cmd, d_saberGhoul2Collision, playerState_s::fd, FORCE_LEVEL_1, FORCE_LEVEL_2, FORCE_LEVEL_3, playerState_s::forceHandExtend, forcedata_s::forcePowerLevel, FP_SABER_DEFENSE, gentity_t, HANDEXTEND_NONE, InFront(), vmCvar_t::integer, level, LS_NONE, LS_PARRY_UP, LS_READY, LS_REFLECT_LL, playerState_s::origin, gclient_s::pers, PM_InSaberAnim(), PM_SaberInBrokenParry(), gclient_s::ps, qboolean, qfalse, qtrue, playerState_s::saberBlocked, playerState_s::saberBlocking, playerState_s::saberBlockTime, playerState_s::saberEntityNum, playerState_s::saberInFlight, playerState_s::saberMove, level_locals_t::time, playerState_s::torsoAnim, vec3_t, playerState_s::viewangles, playerState_s::weapon, WEAPON_RAISING, playerState_s::weaponstate, WP_SABER, and WP_SaberBlockNonRandom(). Referenced by G_MissileImpact(), and WP_DisruptorAltFire().
09272 {
09273 qboolean thrownSaber = qfalse;
09274 float blockFactor = 0;
09275
09276 if (!self || !self->client || !point)
09277 {
09278 return 0;
09279 }
09280
09281 if (attackStr == 999)
09282 {
09283 attackStr = 0;
09284 thrownSaber = qtrue;
09285 }
09286
09287 if (BG_SaberInAttack(self->client->ps.saberMove))
09288 {
09289 return 0;
09290 }
09291
09292 if (PM_InSaberAnim(self->client->ps.torsoAnim) && !self->client->ps.saberBlocked &&
09293 self->client->ps.saberMove != LS_READY && self->client->ps.saberMove != LS_NONE)
09294 {
09295 if ( self->client->ps.saberMove < LS_PARRY_UP || self->client->ps.saberMove > LS_REFLECT_LL )
09296 {
09297 return 0;
09298 }
09299 }
09300
09301 if (PM_SaberInBrokenParry(self->client->ps.saberMove))
09302 {
09303 return 0;
09304 }
09305
09306 if (!self->client->ps.saberEntityNum)
09307 { //saber is knocked away
09308 return 0;
09309 }
09310
09311 if (BG_SabersOff( &self->client->ps ))
09312 {
09313 return 0;
09314 }
09315
09316 if (self->client->ps.weapon != WP_SABER)
09317 {
09318 return 0;
09319 }
09320
09321 if (self->client->ps.weaponstate == WEAPON_RAISING)
09322 {
09323 return 0;
09324 }
09325
09326 if (self->client->ps.saberInFlight)
09327 {
09328 return 0;
09329 }
09330
09331 if ((self->client->pers.cmd.buttons & BUTTON_ATTACK)/* &&
09332 (projectile || attackStr == FORCE_LEVEL_3)*/)
09333 { //don't block when the player is trying to slash, if it's a projectile or he's doing a very strong attack
09334 return 0;
09335 }
09336
09337 //Removed this for now, the new broken parry stuff should handle it. This is how
09338 //blocks were decided before the 1.03 patch (as you can see, it was STUPID.. for the most part)
09339 /*
09340 if (attackStr == FORCE_LEVEL_3)
09341 {
09342 if (self->client->ps.fd.forcePowerLevel[FP_SABER_DEFENSE] >= FORCE_LEVEL_3)
09343 {
09344 if (Q_irand(1, 10) < 3)
09345 {
09346 return 0;
09347 }
09348 }
09349 else
09350 {
09351 return 0;
09352 }
09353 }
09354
09355 if (attackStr == FORCE_LEVEL_2 && Q_irand(1, 10) < 3)
09356 {
09357 if (self->client->ps.fd.forcePowerLevel[FP_SABER_DEFENSE] >= FORCE_LEVEL_3)
09358 {
09359 //do nothing for now
09360 }
09361 else if (self->client->ps.fd.forcePowerLevel[FP_SABER_DEFENSE] >= FORCE_LEVEL_2)
09362 {
09363 if (Q_irand(1, 10) < 5)
09364 {
09365 return 0;
09366 }
09367 }
09368 else
09369 {
09370 return 0;
09371 }
09372 }
09373
09374 if (attackStr == FORCE_LEVEL_1 && !self->client->ps.fd.forcePowerLevel[FP_SABER_DEFENSE] &&
09375 Q_irand(1, 40) < 3)
09376 { //if I have no defense level at all then I might be unable to block a level 1 attack (but very rarely)
09377 return 0;
09378 }
09379 */
09380
09381 if (SaberAttacking(self))
09382 { //attacking, can't block now
09383 return 0;
09384 }
09385
09386 if (self->client->ps.saberMove != LS_READY &&
09387 !self->client->ps.saberBlocking)
09388 {
09389 return 0;
09390 }
09391
09392 if (self->client->ps.saberBlockTime >= level.time)
09393 {
09394 return 0;
09395 }
09396
09397 if (self->client->ps.forceHandExtend != HANDEXTEND_NONE)
09398 {
09399 return 0;
09400 }
09401
09402 if (self->client->ps.fd.forcePowerLevel[FP_SABER_DEFENSE] == FORCE_LEVEL_3)
09403 {
09404 if (d_saberGhoul2Collision.integer)
09405 {
09406 blockFactor = 0.3f;
09407 }
09408 else
09409 {
09410 blockFactor = 0.05f;
09411 }
09412 }
09413 else if (self->client->ps.fd.forcePowerLevel[FP_SABER_DEFENSE] == FORCE_LEVEL_2)
09414 {
09415 blockFactor = 0.6f;
09416 }
09417 else if (self->client->ps.fd.forcePowerLevel[FP_SABER_DEFENSE] == FORCE_LEVEL_1)
09418 {
09419 blockFactor = 0.9f;
09420 }
09421 else
09422 { //for now we just don't get to autoblock with no def
09423 return 0;
09424 }
09425
09426 if (thrownSaber)
09427 {
09428 blockFactor -= 0.25f;
09429 }
09430
09431 if (attackStr)
09432 { //blocking a saber, not a projectile.
09433 blockFactor -= 0.25f;
09434 }
09435
09436 if (!InFront( point, self->client->ps.origin, self->client->ps.viewangles, blockFactor )) //orig 0.2f
09437 {
09438 return 0;
09439 }
09440
09441 if (projectile)
09442 {
09443 WP_SaberBlockNonRandom(self, point, projectile);
09444 }
09445 return 1;
09446 }
|
|
|
Definition at line 3510 of file w_saber.c. References ENTITYNUM_NONE, MAX_SABER_VICTIMS, and memset(). Referenced by WP_SaberPositionUpdate().
03511 {
03512 int ven;
03513 for ( ven = 0; ven < MAX_SABER_VICTIMS; ven++ )
03514 {
03515 victimEntityNum[ven] = ENTITYNUM_NONE;
03516 }
03517 memset( victimHitEffectDone, 0, sizeof( victimHitEffectDone ) );
03518 memset( totalDmg, 0, sizeof( totalDmg ) );
03519 memset( dmgDir, 0, sizeof( dmgDir ) );
03520 memset( dmgSpot, 0, sizeof( dmgSpot ) );
03521 memset( dismemberDmg, 0, sizeof( dismemberDmg ) );
03522 memset( saberKnockbackFlags, 0, sizeof( saberKnockbackFlags ) );
03523 numVictims = 0;
03524 }
|
|
||||||||||||||||||||||||||||
|
Definition at line 3526 of file w_saber.c. References ENTITYNUM_WORLD, MAX_SABER_VICTIMS, qtrue, vec3_origin, vec3_t, and VectorCopy.
03528 {
03529 if ( trVictimEntityNum < 0 || trVictimEntityNum >= ENTITYNUM_WORLD )
03530 {
03531 return;
03532 }
03533
03534 if ( trDmg )
03535 {//did some damage to something
03536 int curVictim = 0;
03537 int i;
03538
03539 for ( i = 0; i < numVictims; i++ )
03540 {
03541 if ( victimEntityNum[i] == trVictimEntityNum )
03542 {//already hit this guy before
03543 curVictim = i;
03544 break;
03545 }
03546 }
03547 if ( i == numVictims )
03548 {//haven't hit his guy before
03549 if ( numVictims + 1 >= MAX_SABER_VICTIMS )
03550 {//can't add another victim at this time
03551 return;
03552 }
03553 //add a new victim to the list
03554 curVictim = numVictims;
03555 victimEntityNum[numVictims++] = trVictimEntityNum;
03556 }
03557
03558 totalDmg[curVictim] += trDmg;
03559 if ( VectorCompare( dmgDir[curVictim], vec3_origin ) )
03560 {
03561 VectorCopy( trDmgDir, dmgDir[curVictim] );
03562 }
03563 if ( VectorCompare( dmgSpot[curVictim], vec3_origin ) )
03564 {
03565 VectorCopy( trDmgSpot, dmgSpot[curVictim] );
03566 }
03567 if ( doDismemberment )
03568 {
03569 dismemberDmg[curVictim] = qtrue;
03570 }
03571 saberKnockbackFlags[curVictim] |= knockBackFlags;
03572 }
03573 }
|
|
||||||||||||||||
|
Definition at line 3796 of file w_saber.c. References entityState_s::angles, EV_SABER_BLOCK, entityState_s::eventParm, G_TempEntity(), gentity_t, entityState_s::legsAnim, entityState_s::number, entityState_s::origin, entityState_s::otherEntityNum2, gentity_s::s, VectorCopy, and entityState_s::weapon. Referenced by WP_SaberPositionUpdate().
03797 {
03798 if ( saberDoClashEffect )
03799 {
03800 gentity_t *te = G_TempEntity( saberClashPos, EV_SABER_BLOCK );
03801 VectorCopy(saberClashPos, te->s.origin);
03802 VectorCopy(saberClashNorm, te->s.angles);
03803 te->s.eventParm = saberClashEventParm;
03804 te->s.otherEntityNum2 = self->s.number;
03805 te->s.weapon = saberNum;
03806 te->s.legsAnim = bladeNum;
03807 }
03808 }
|
|
||||||||||||||||
|
Definition at line 3606 of file w_saber.c. References entityState_s::angles, CLASS_ATST, CLASS_GONK, CLASS_INTERROGATOR, CLASS_MARK1, CLASS_MARK2, CLASS_MOUSE, CLASS_PROBE, CLASS_PROTOCOL, CLASS_R2D2, CLASS_R5D2, CLASS_REMOTE, CLASS_SEEKER, CLASS_SENTRY, class_t, gentity_s::client, ET_BODY, ET_NPC, entityState_s::eType, EV_SABER_CLASHFLARE, EV_SABER_HIT, entityState_s::eventParm, g_entities, G_TempEntity(), gentity_t, entityState_s::legsAnim, gclient_s::NPC_class, NULL, entityState_s::number, entityState_s::origin, entityState_s::otherEntityNum, entityState_s::otherEntityNum2, qboolean, qfalse, qtrue, gentity_s::s, gclient_s::saber, SABER_NONATTACK_DAMAGE, saberInfo_t::saberFlags2, SFL2_NO_CLASH_FLARE, SFL2_NO_CLASH_FLARE2, VectorCopy, VectorScale, entityState_s::weapon, and WP_SaberBladeUseSecondBladeStyle(). Referenced by WP_SaberPositionUpdate().
03607 {
03608 int i;
03609 if ( !numVictims )
03610 {
03611 return;
03612 }
03613 for ( i = 0; i < numVictims; i++ )
03614 {
03615 gentity_t *te = NULL, *victim = NULL;
03616 qboolean isDroid = qfalse;
03617
03618 if ( victimHitEffectDone[i] )
03619 {
03620 continue;
03621 }
03622
03623 victimHitEffectDone[i] = qtrue;
03624
03625 victim = &g_entities[victimEntityNum[i]];
03626
03627 if ( victim->client )
03628 {
03629 class_t npc_class = victim->client->NPC_class;
03630
03631 if ( npc_class == CLASS_SEEKER || npc_class == CLASS_PROBE || npc_class == CLASS_MOUSE || npc_class == CLASS_REMOTE ||
03632 npc_class == CLASS_GONK || npc_class == CLASS_R2D2 || npc_class == CLASS_R5D2 ||
03633 npc_class == CLASS_PROTOCOL || npc_class == CLASS_MARK1 || npc_class == CLASS_MARK2 ||
03634 npc_class == CLASS_INTERROGATOR || npc_class == CLASS_ATST || npc_class == CLASS_SENTRY )
03635 { //don't make "blood" sparks for droids.
03636 isDroid = qtrue;
03637 }
03638 }
03639
03640 te = G_TempEntity( dmgSpot[i], EV_SABER_HIT );
03641 if ( te )
03642 {
03643 te->s.otherEntityNum = victimEntityNum[i];
03644 te->s.otherEntityNum2 = self->s.number;
03645 te->s.weapon = saberNum;
03646 te->s.legsAnim = bladeNum;
03647
03648 VectorCopy(dmgSpot[i], te->s.origin);
03649 //VectorCopy(tr.plane.normal, te->s.angles);
03650 VectorScale( dmgDir[i], -1, te->s.angles);
03651
03652 if (!te->s.angles[0] && !te->s.angles[1] && !te->s.angles[2])
03653 { //don't let it play with no direction
03654 te->s.angles[1] = 1;
03655 }
03656
03657 if (!isDroid && (victim->client || victim->s.eType == ET_NPC ||
03658 victim->s.eType == ET_BODY))
03659 {
03660 if ( totalDmg[i] < 5 )
03661 {
03662 te->s.eventParm = 3;
03663 }
03664 else if (totalDmg[i] < 20 )
03665 {
03666 te->s.eventParm = 2;
03667 }
03668 else
03669 {
03670 te->s.eventParm = 1;
03671 }
03672 }
03673 else
03674 {
03675 if ( !WP_SaberBladeUseSecondBladeStyle( &self->client->saber[saberNum], bladeNum )
03676 && (self->client->saber[saberNum].saberFlags2&SFL2_NO_CLASH_FLARE) )
03677 {//don't do clash flare
03678 }
03679 else if ( WP_SaberBladeUseSecondBladeStyle( &self->client->saber[saberNum], bladeNum )
03680 && (self->client->saber[saberNum].saberFlags2&SFL2_NO_CLASH_FLARE2) )
03681 {//don't do clash flare
03682 }
03683 else
03684 {
03685 if (totalDmg[i] > SABER_NONATTACK_DAMAGE)
03686 { //I suppose I could tie this into the saberblock event, but I'm tired of adding flags to that thing.
03687 gentity_t *teS = G_TempEntity( te->s.origin, EV_SABER_CLASHFLARE );
03688 VectorCopy(te->s.origin, teS->s.origin);
03689 }
03690 te->s.eventParm = 0;
03691 }
03692 }
03693 }
03694 }
03695 }
|
|
|
Definition at line 564 of file w_saber.c. References gentity_s::classname, gentity_s::client, gentity_s::clipmask, entityShared_t::contents, CONTENTS_LIGHTSABER, EF_NODRAW, entityState_s::eFlags, g_entities, G_FreeEntity(), G_InitGentity(), G_SoundIndex(), G_Spawn(), gentity_s::genericValue5, gentity_t, gentity_s::inuse, level, MASK_PLAYERSOLID, gentity_s::mass, entityState_s::modelGhoul2, gentity_s::neverFree, gentity_s::nextthink, NULL, level_locals_t::num_entities, entityState_s::number, entityShared_t::ownerNum, gclient_s::ps, Q_stricmp(), qfalse, qtrue, gentity_s::r, gentity_s::s, playerState_s::saberEntityNum, SaberGotHit(), saberSpinSound, gclient_s::saberStoredIndex, SaberUpdateSelf(), SVF_NOCLIENT, SVF_USE_CURRENT_ORIGIN, entityShared_t::svFlags, gentity_s::think, level_locals_t::time, and gentity_s::touch. Referenced by ClientBegin(), and NPC_SetMiscDefaultData().
00565 {
00566 gentity_t *saberent = NULL;
00567 gentity_t *checkEnt;
00568 int i = 0;
00569
00570 while (i < level.num_entities)
00571 { //make sure there are no other saber entities floating around that think they belong to this client.
00572 checkEnt = &g_entities[i];
00573
00574 if (checkEnt->inuse && checkEnt->neverFree &&
00575 checkEnt->r.ownerNum == ent->s.number &&
00576 checkEnt->classname && checkEnt->classname[0] &&
00577 !Q_stricmp(checkEnt->classname, "lightsaber"))
00578 {
00579 if (saberent)
00580 { //already have one
00581 checkEnt->neverFree = qfalse;
00582 checkEnt->think = G_FreeEntity;
00583 checkEnt->nextthink = level.time;
00584 }
00585 else
00586 { //hmm.. well then, take it as my own.
00587 //free the bitch but don't issue a kg2 to avoid overflowing clients.
00588 checkEnt->s.modelGhoul2 = 0;
00589 G_FreeEntity(checkEnt);
00590
00591 //now init it manually and reuse this ent slot.
00592 G_InitGentity(checkEnt);
00593 saberent = checkEnt;
00594 }
00595 }
00596
00597 i++;
00598 }
00599
00600 //We do not want the client to have any real knowledge of the entity whatsoever. It will only
00601 //ever be used on the server.
00602 if (!saberent)
00603 { //ok, make one then
00604 saberent = G_Spawn();
00605 }
00606 ent->client->ps.saberEntityNum = ent->client->saberStoredIndex = saberent->s.number;
00607 saberent->classname = "lightsaber";
00608
00609 saberent->neverFree = qtrue; //the saber being removed would be a terrible thing.
00610
00611 saberent->r.svFlags = SVF_USE_CURRENT_ORIGIN;
00612 saberent->r.ownerNum = ent->s.number;
00613
00614 saberent->clipmask = MASK_PLAYERSOLID | CONTENTS_LIGHTSABER;
00615 saberent->r.contents = CONTENTS_LIGHTSABER;
00616
00617 SetSaberBoxSize(saberent);
00618
00619 saberent->mass = 10;
00620
00621 saberent->s.eFlags |= EF_NODRAW;
00622 saberent->r.svFlags |= SVF_NOCLIENT;
00623
00624 saberent->s.modelGhoul2 = 1;
00625 //should we happen to be removed (we belong to an NPC and he is removed) then
00626 //we want to attempt to remove our g2 instance on the client in case we had one.
00627
00628 saberent->touch = SaberGotHit;
00629
00630 saberent->think = SaberUpdateSelf;
00631 saberent->genericValue5 = 0;
00632 saberent->nextthink = level.time + 50;
00633
00634 saberSpinSound = G_SoundIndex("sound/weapons/saber/saberspin.wav");
00635 }
|
|
|
Definition at line 2791 of file w_saber.c. References gentity_s::client, gentity_t, MAX_SABERS, gclient_s::saber, and WP_SaberBladeLength().
02792 {//return largest length
02793 if ( !ent || !ent->client )
02794 {
02795 return 0.0f;
02796 }
02797 else
02798 {
02799 int i;
02800 float len, bestLen = 0.0f;
02801 for ( i = 0; i < MAX_SABERS; i++ )
02802 {
02803 len = WP_SaberBladeLength( &ent->client->saber[i] );
02804 if ( len > bestLen )
02805 {
02806 bestLen = len;
02807 }
02808 }
02809 return bestLen;
02810 }
02811 }
|
|
||||||||||||
|
Definition at line 8079 of file w_saber.c. References trace_t::allsolid, AngleDelta(), entityState_s::angles, AnglesToAxis(), AngleVectors(), entityState_s::apos, saberTrail_t::base, BG_EvaluateTrajectory(), BG_InGrappleMove(), BG_KickingAnim(), BG_SaberInAttack(), BG_SabersOff(), BG_SuperBreakWinAnim(), saberInfo_t::blade, BLOCKED_NONE, BOTH_DEADFLOP1, BOTH_KYLE_GRAB, BOTH_KYLE_MISS, BOTH_KYLE_PA_1, BOTH_KYLE_PA_2, BROKENLIMB_LARM, playerState_s::brokenLimbs, CHAN_AUTO, CHAN_VOICE, gentity_s::client, gentity_s::clipmask, clientPersistant_t::cmd, entityShared_t::contents, CONTENTS_BODY, CONTENTS_LIGHTSABER, entityShared_t::currentOrigin, d_saberInterpolate, d_saberSPStyleDamage, gentity_s::damage, gclient_s::dangerTime, playerState_s::duelInProgress, EF_INVULNERABLE, playerState_s::eFlags, entityState_s::eFlags, ET_GENERAL, entityState_s::eType, EV_SABER_BLOCK, entityState_s::eventParm, playerState_s::fd, playerState_s::forceHandExtend, playerState_s::forceHandExtendTime, forcedata_s::forcePowersActive, FP_RAGE, trace_t::fraction, FRAMETIME, g2SaberInstance, G_Damage(), g_entities, G_EntitySound(), g_gametype, g_saberTraceSaberFirst, G_SetAnim(), G_SetOrigin(), G_Sound(), G_SoundIndex(), G_SPSaberDamageTraceLerped(), g_svfps, G_TempEntity(), G_UpdateClientAnims(), entityState_s::genericenemyindex, gentity_s::genericValue5, gentity_t, gentity_s::ghoul2, gclient_s::grappleIndex, gclient_s::grappleState, GT_DUEL, GT_POWERDUEL, HANDEXTEND_KNOCKDOWN, gclient_s::hasCurrentPosition, gentity_s::health, vmCvar_t::integer, gentity_s::inuse, gclient_s::invulnerableTimer, gclient_s::lastSaberBase_Always, gclient_s::lastSaberDir_Always, gclient_s::lastSaberStorageTime, saberTrail_t::lastTime, entityState_s::legsAnim, playerState_s::legsAnim, playerState_s::legsTimer, bladeInfo_t::lengthMax, level, entityShared_t::linked, entityState_s::loopIsSoundset, entityState_s::loopSound, playerState_s::m_iVehicleNum, gentity_s::m_pVehicle, Vehicle_s::m_vOrientation, MASK_PLAYERSOLID, MASK_SHOT, MAX_CLIENTS, MAX_SABERS, entityShared_t::maxs, gentity_s::methodOfDeath, entityShared_t::mins, MOD_MELEE, MOD_SABER, saberInfo_t::model, entityState_s::modelGhoul2, gentity_s::modelScale, bladeInfo_t::muzzleDir, bladeInfo_t::muzzleDirOld, bladeInfo_t::muzzlePoint, bladeInfo_t::muzzlePointOld, NEGATIVE_Y, gentity_s::nextthink, NULL, entityState_s::number, saberInfo_t::numBlades, gclient_s::olderIsValid, gclient_s::olderSaberBase, entityState_s::origin, ORIGIN, playerState_s::origin, gentity_s::parent, gclient_s::pers, PM_SaberInTransition(), entityState_s::pos, gentity_s::pos1, PROPER_THROWN_VALUE, gclient_s::ps, Q_irand(), qboolean, qfalse, qtrue, gentity_s::r, gentity_s::s, gclient_s::saber, SABER_THROWN_HIT_DAMAGE, forcedata_s::saberAnimLevel, playerState_s::saberBlocked, playerState_s::saberCanThrow, gclient_s::saberCycleQueue, playerState_s::saberDidThrowTime, forcedata_s::saberDrawAnimLevel, playerState_s::saberEntityNum, playerState_s::saberEntityState, saberFirstThrown(), saberInfo_t::saberFlags, playerState_s::saberHolstered, playerState_s::saberIdleWound, entityState_s::saberInFlight, playerState_s::saberInFlight, playerState_s::saberLockTime, SABERMAXS_X, SABERMAXS_Y, SABERMAXS_Z, SABERMINS_X, SABERMINS_Y, SABERMINS_Z, playerState_s::saberMove, saberSpinSound, gclient_s::saberStoredIndex, playerState_s::saberThrowDelay, SaberUpdateSelf(), SETANIM_BOTH, SETANIM_FLAG_HOLD, SETANIM_FLAG_OVERRIDE, SetClientViewAngle(), SFL_NOT_THROWABLE, SFL_SINGLE_BLADE_THROWABLE, saberInfo_t::skin, entityState_s::solid, saberInfo_t::soundOff, saberInfo_t::spinSound, gentity_s::splashMethodOfDeath, trace_t::startsolid, bladeInfo_t::storageTime, SVF_NOCLIENT, entityShared_t::svFlags, gentity_s::think, thrownSaberTouch(), level_locals_t::time, saberTrail_t::tip, playerState_s::torsoAnim, playerState_s::torsoTimer, gentity_s::touch, TR_LINEAR, bladeInfo_t::trail, trap_G2API_GetBoltMatrix(), trap_G2API_OverrideServer(), trap_LinkEntity(), trap_Trace(), trajectory_t::trBase, trajectory_t::trDelta, trajectory_t::trTime, trajectory_t::trType, UpdateClientRenderinfo(), usercmd_t, vmCvar_t::value, vec3_t, vectoangles(), VectorAdd, VectorCopy, VectorMA, VectorNormalize(), VectorScale, VectorSet, VectorSubtract, playerState_s::velocity, playerState_s::viewangles, entityState_s::weapon, playerState_s::weapon, WEAPON_DROPPING, WEAPON_FIRING, WEAPON_RAISING, playerState_s::weaponstate, playerState_s::weaponTime, WP_SABER, WP_SaberAddG2Model(), WP_SaberApplyDamage(), WP_SaberClearDamage(), WP_SaberDoClash(), WP_SaberDoHit(), WP_SaberRemoveG2Model(), and YAW. Referenced by G_RunFrame().
08080 { //rww - keep the saber position as updated as possible on the server so that we can try to do realistic-looking contact stuff
08081 //Note that this function also does the majority of working in maintaining the server g2 client instance (updating angles/anims/etc)
08082 gentity_t *mySaber = NULL;
08083 mdxaBone_t boltMatrix;
08084 vec3_t properAngles, properOrigin;
08085 vec3_t boltAngles, boltOrigin;
08086 vec3_t end;
08087 vec3_t legAxis[3];
08088 vec3_t addVel;
08089 vec3_t rawAngles;
08090 float fVSpeed = 0;
08091 int returnAfterUpdate = 0;
08092 float animSpeedScale = 1.0f;
08093 int saberNum;
08094 qboolean clientOverride;
08095 gentity_t *vehEnt = NULL;
08096 int rSaberNum = 0;
08097 int rBladeNum = 0;
08098
08099 #ifdef _DEBUG
08100 if (g_disableServerG2.integer)
08101 {
08102 return;
08103 }
08104 #endif
08105
08106 if (self && self->inuse && self->client)
08107 {
08108 if (self->client->saberCycleQueue)
08109 {
08110 self->client->ps.fd.saberDrawAnimLevel = self->client->saberCycleQueue;
08111 }
08112 else
08113 {
08114 self->client->ps.fd.saberDrawAnimLevel = self->client->ps.fd.saberAnimLevel;
08115 }
08116 }
08117
08118 if (self &&
08119 self->inuse &&
08120 self->client &&
08121 self->client->saberCycleQueue &&
08122 (self->client->ps.weaponTime <= 0 || self->health < 1))
08123 { //we cycled attack levels while we were busy, so update now that we aren't (even if that means we're dead)
08124 self->client->ps.fd.saberAnimLevel = self->client->saberCycleQueue;
08125 self->client->saberCycleQueue = 0;
08126 }
08127
08128 if (!self ||
08129 !self->inuse ||
08130 !self->client ||
08131 !self->ghoul2 ||
08132 !g2SaberInstance)
08133 {
08134 return;
08135 }
08136
08137 if (BG_KickingAnim(self->client->ps.legsAnim))
08138 { //do some kick traces and stuff if we're in the appropriate anim
08139 G_KickSomeMofos(self);
08140 }
08141 else if (self->client->ps.torsoAnim == BOTH_KYLE_GRAB)
08142 { //try to grab someone
08143 G_GrabSomeMofos(self);
08144 }
08145 else if (self->client->grappleState)
08146 {
08147 gentity_t *grappler = &g_entities[self->client->grappleIndex];
08148
08149 if (!grappler->inuse || !grappler->client || grappler->client->grappleIndex != self->s.number ||
08150 !BG_InGrappleMove(grappler->client->ps.torsoAnim) || !BG_InGrappleMove(grappler->client->ps.legsAnim) ||
08151 !BG_InGrappleMove(self->client->ps.torsoAnim) || !BG_InGrappleMove(self->client->ps.legsAnim) ||
08152 !self->client->grappleState || !grappler->client->grappleState ||
08153 grappler->health < 1 || self->health < 1 ||
08154 !G_PrettyCloseIGuess(self->client->ps.origin[2], grappler->client->ps.origin[2], 4.0f))
08155 {
08156 self->client->grappleState = 0;
08157 if ((BG_InGrappleMove(self->client->ps.torsoAnim) && self->client->ps.torsoTimer > 100) ||
08158 (BG_InGrappleMove(self->client->ps.legsAnim) && self->client->ps.legsTimer > 100))
08159 { //if they're pretty far from finishing the anim then shove them into another anim
08160 G_SetAnim(self, &self->client->pers.cmd, SETANIM_BOTH, BOTH_KYLE_MISS, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0);
08161 if (self->client->ps.torsoAnim == BOTH_KYLE_MISS)
08162 { //providing the anim set succeeded..
08163 self->client->ps.weaponTime = self->client->ps.torsoTimer;
08164 }
08165 }
08166 }
08167 else
08168 {
08169 vec3_t grapAng;
08170
08171 VectorSubtract(grappler->client->ps.origin, self->client->ps.origin, grapAng);
08172
08173 if (VectorLength(grapAng) > 64.0f)
08174 { //too far away, break it off
08175 if ((BG_InGrappleMove(self->client->ps.torsoAnim) && self->client->ps.torsoTimer > 100) ||
08176 (BG_InGrappleMove(self->client->ps.legsAnim) && self->client->ps.legsTimer > 100))
08177 {
08178 self->client->grappleState = 0;
08179
08180 G_SetAnim(self, &self->client->pers.cmd, SETANIM_BOTH, BOTH_KYLE_MISS, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0);
08181 if (self->client->ps.torsoAnim == BOTH_KYLE_MISS)
08182 { //providing the anim set succeeded..
08183 self->client->ps.weaponTime = self->client->ps.torsoTimer;
08184 }
08185 }
08186 }
08187 else
08188 {
08189 vectoangles(grapAng, grapAng);
08190 SetClientViewAngle(self, grapAng);
08191
08192 if (self->client->grappleState >= 20)
08193 { //grapplee
08194 //try to position myself at the correct distance from my grappler
08195 float idealDist;
08196 vec3_t gFwd, idealSpot;
08197 trace_t trace;
08198
08199 if (grappler->client->ps.torsoAnim == BOTH_KYLE_PA_1)
08200 { //grab punch
08201 idealDist = 46.0f;
08202 }
08203 else
08204 { //knee-throw
08205 idealDist = 34.0f;
08206 }
08207
08208 AngleVectors(grappler->client->ps.viewangles, gFwd, 0, 0);
08209 VectorMA(grappler->client->ps.origin, idealDist, gFwd, idealSpot);
08210
08211 trap_Trace(&trace, self->client->ps.origin, self->r.mins, self->r.maxs, idealSpot, self->s.number, self->clipmask);
08212 if (!trace.startsolid && !trace.allsolid && trace.fraction == 1.0f)
08213 { //go there
08214 G_SetOrigin(self, idealSpot);
08215 VectorCopy(idealSpot, self->client->ps.origin);
08216 }
08217 }
08218 else if (self->client->grappleState >= 1)
08219 { //grappler
08220 if (grappler->client->ps.weapon == WP_SABER)
08221 { //make sure their saber is shut off
08222 if (!grappler->client->ps.saberHolstered)
08223 {
08224 grappler->client->ps.saberHolstered = 2;
08225 if (grappler->client->saber[0].soundOff)
08226 {
08227 G_Sound(grappler, CHAN_AUTO, grappler->client->saber[0].soundOff);
08228 }
08229 if (grappler->client->saber[1].soundOff &&
08230 grappler->client->saber[1].model[0])
08231 {
08232 G_Sound(grappler, CHAN_AUTO, grappler->client->saber[1].soundOff);
08233 }
08234 }
08235 }
08236
08237 //check for smashy events
08238 if (self->client->ps.torsoAnim == BOTH_KYLE_PA_1)
08239 { //grab punch
08240 if (self->client->grappleState == 1)
08241 { //smack
08242 if (self->client->ps.torsoTimer < 3400)
08243 {
08244 int grapplerAnim = grappler->client->ps.torsoAnim;
08245 int grapplerTime = grappler->client->ps.torsoTimer;
08246
08247 G_Damage(grappler, self, self, NULL, self->client->ps.origin, 10, 0, MOD_MELEE);
08248 //G_Sound( grappler, CHAN_AUTO, G_SoundIndex( va( "sound/weapons/melee/punch%d", Q_irand( 1, 4 ) ) ) );
08249
08250 //it might try to put them into a pain anim or something, so override it back again
08251 if (grappler->health > 0)
08252 {
08253 grappler->client->ps.torsoAnim = grapplerAnim;
08254 grappler->client->ps.torsoTimer = grapplerTime;
08255 grappler->client->ps.legsAnim = grapplerAnim;
08256 grappler->client->ps.legsTimer = grapplerTime;
08257 grappler->client->ps.weaponTime = grapplerTime;
08258 }
08259 self->client->grappleState++;
08260 }
08261 }
08262 else if (self->client->grappleState == 2)
08263 { //smack!
08264 if (self->client->ps.torsoTimer < 2550)
08265 {
08266 int grapplerAnim = grappler->client->ps.torsoAnim;
08267 int grapplerTime = grappler->client->ps.torsoTimer;
08268
08269 G_Damage(grappler, self, self, NULL, self->client->ps.origin, 10, 0, MOD_MELEE);
08270 //G_Sound( grappler, CHAN_AUTO, G_SoundIndex( va( "sound/weapons/melee/punch%d", Q_irand( 1, 4 ) ) ) );
08271
08272 //it might try to put them into a pain anim or something, so override it back again
08273 if (grappler->health > 0)
08274 {
08275 grappler->client->ps.torsoAnim = grapplerAnim;
08276 grappler->client->ps.torsoTimer = grapplerTime;
08277 grappler->client->ps.legsAnim = grapplerAnim;
08278 grappler->client->ps.legsTimer = grapplerTime;
08279 grappler->client->ps.weaponTime = grapplerTime;
08280 }
08281 self->client->grappleState++;
08282 }
08283 }
08284 else
08285 { //SMACK!
08286 if (self->client->ps.torsoTimer < 1300)
08287 {
08288 vec3_t tossDir;
08289
08290 G_Damage(grappler, self, self, NULL, self->client->ps.origin, 30, 0, MOD_MELEE);
08291 //G_Sound( grappler, CHAN_AUTO, G_SoundIndex( va( "sound/weapons/melee/punch%d", Q_irand( 1, 4 ) ) ) );
08292
08293 self->client->grappleState = 0;
08294
08295 VectorSubtract(grappler->client->ps.origin, self->client->ps.origin, tossDir);
08296 VectorNormalize(tossDir);
08297 VectorScale(tossDir, 500.0f, tossDir);
08298 tossDir[2] = 200.0f;
08299
08300 VectorAdd(grappler->client->ps.velocity, tossDir, grappler->client->ps.velocity);
08301
08302 if (grappler->health > 0)
08303 { //if still alive knock them down
08304 grappler->client->ps.forceHandExtend = HANDEXTEND_KNOCKDOWN;
08305 grappler->client->ps.forceHandExtendTime = level.time + 1300;
08306 }
08307 }
08308 }
08309 }
08310 else if (self->client->ps.torsoAnim == BOTH_KYLE_PA_2)
08311 { //knee throw
08312 if (self->client->grappleState == 1)
08313 { //knee to the face
08314 if (self->client->ps.torsoTimer < 3200)
08315 {
08316 int grapplerAnim = grappler->client->ps.torsoAnim;
08317 int grapplerTime = grappler->client->ps.torsoTimer;
08318
08319 G_Damage(grappler, self, self, NULL, self->client->ps.origin, 20, 0, MOD_MELEE);
08320 //G_Sound( grappler, CHAN_AUTO, G_SoundIndex( va( "sound/weapons/melee/punch%d", Q_irand( 1, 4 ) ) ) );
08321
08322 //it might try to put them into a pain anim or something, so override it back again
08323 if (grappler->health > 0)
08324 {
08325 grappler->client->ps.torsoAnim = grapplerAnim;
08326 grappler->client->ps.torsoTimer = grapplerTime;
08327 grappler->client->ps.legsAnim = grapplerAnim;
08328 grappler->client->ps.legsTimer = grapplerTime;
08329 grappler->client->ps.weaponTime = grapplerTime;
08330 }
08331 self->client->grappleState++;
08332 }
08333 }
08334 else if (self->client->grappleState == 2)
08335 { //smashed on the ground
08336 if (self->client->ps.torsoTimer < 2000)
08337 {
08338 //G_Damage(grappler, self, self, NULL, self->client->ps.origin, 10, 0, MOD_MELEE);
08339 //don't do damage on this one, it would look very freaky if they died
08340 G_EntitySound( grappler, CHAN_VOICE, G_SoundIndex("*pain100.wav") );
08341 //G_Sound( grappler, CHAN_AUTO, G_SoundIndex( va( "sound/weapons/melee/punch%d", Q_irand( 1, 4 ) ) ) );
08342 self->client->grappleState++;
08343 }
08344 }
08345 else
08346 { //and another smash
08347 if (self->client->ps.torsoTimer < 1000)
08348 {
08349 G_Damage(grappler, self, self, NULL, self->client->ps.origin, 30, 0, MOD_MELEE);
08350 //G_Sound( grappler, CHAN_AUTO, G_SoundIndex( va( "sound/weapons/melee/punch%d", Q_irand( 1, 4 ) ) ) );
08351
08352 //it might try to put them into a pain anim or something, so override it back again
08353 if (grappler->health > 0)
08354 {
08355 grappler->client->ps.torsoTimer = 1000;
08356 //G_SetAnim(grappler, &grappler->client->pers.cmd, SETANIM_BOTH, BOTH_GETUP3, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0);
08357 grappler->client->grappleState = 0;
08358 }
08359 else
08360 { //override death anim
08361 grappler->client->ps.torsoAnim = BOTH_DEADFLOP1;
08362 grappler->client->ps.legsAnim = BOTH_DEADFLOP1;
08363 }
08364
08365 self->client->grappleState = 0;
08366 }
08367 }
08368 }
08369 else
08370 { //?
08371 }
08372 }
08373 }
08374 }
08375 }
08376
08377 //If this is a listen server (client+server running on same machine),
08378 //then lets try to steal the skeleton/etc data off the client instance
08379 //for this entity to save us processing time.
08380 clientOverride = trap_G2API_OverrideServer(self->ghoul2);
08381
08382 saberNum = self->client->ps.saberEntityNum;
08383
08384 if (!saberNum)
08385 {
08386 saberNum = self->client->saberStoredIndex;
08387 }
08388
08389 if (!saberNum)
08390 {
08391 returnAfterUpdate = 1;
08392 goto nextStep;
08393 }
08394
08395 mySaber = &g_entities[saberNum];
08396
08397 if (self->health < 1)
08398 { //we don't want to waste precious CPU time calculating saber positions for corpses. But we want to avoid the saber ent position lagging on spawn, so..
08399 //I guess it's good to keep the position updated even when contents are 0
08400 if (mySaber && ((mySaber->r.contents & CONTENTS_LIGHTSABER) || mySaber->r.contents == 0) && !self->client->ps.saberInFlight)
08401 { //Since we haven't got a bolt position, place it on top of the player origin.
08402 VectorCopy(self->client->ps.origin, mySaber->r.currentOrigin);
08403 }
08404
08405 //I don't want to return now actually, I want to keep g2 instances for corpses up to
08406 //date because I'm doing better corpse hit detection/dismem (particularly for the
08407 //npc's)
08408 //return;
08409 }
08410
08411 if ( BG_SuperBreakWinAnim( self->client->ps.torsoAnim ) )
08412 {
08413 self->client->ps.weaponstate = WEAPON_FIRING;
08414 }
08415 if (self->client->ps.weapon != WP_SABER ||
08416 self->client->ps.weaponstate == WEAPON_RAISING ||
08417 self->client->ps.weaponstate == WEAPON_DROPPING ||
08418 self->health < 1)
08419 {
08420 if (!self->client->ps.saberInFlight)
08421 {
08422 returnAfterUpdate = 1;
08423 }
08424 }
08425
08426 if (self->client->ps.saberThrowDelay < level.time)
08427 {
08428 if ( (self->client->saber[0].saberFlags&SFL_NOT_THROWABLE) )
08429 {//cant throw it normally!
08430 if ( (self->client->saber[0].saberFlags&SFL_SINGLE_BLADE_THROWABLE) )
08431 {//but can throw it if only have 1 blade on
08432 if ( self->client->saber[0].numBlades > 1
08433 && self->client->ps.saberHolstered == 1 )
08434 {//have multiple blades and only one blade on
08435 self->client->ps.saberCanThrow = qtrue;//qfalse;
08436 //huh? want to be able to throw then right?
08437 }
08438 else
08439 {//multiple blades on, can't throw
08440 self->client->ps.saberCanThrow = qfalse;
08441 }
08442 }
08443 else
08444 {//never can throw it
08445 self->client->ps.saberCanThrow = qfalse;
08446 }
08447 }
08448 else
08449 {//can throw it!
08450 self->client->ps.saberCanThrow = qtrue;
08451 }
08452 }
08453 nextStep:
08454 if (self->client->ps.fd.forcePowersActive & (1 << FP_RAGE))
08455 {
08456 animSpeedScale = 2;
08457 }
08458
08459 VectorCopy(self->client->ps.origin, properOrigin);
08460
08461 //try to predict the origin based on velocity so it's more like what the client is seeing
08462 VectorCopy(self->client->ps.velocity, addVel);
08463 VectorNormalize(addVel);
08464
08465 if (self->client->ps.velocity[0] < 0)
08466 {
08467 fVSpeed += (-self->client->ps.velocity[0]);
08468 }
08469 else
08470 {
08471 fVSpeed += self->client->ps.velocity[0];
08472 }
08473 if (self->client->ps.velocity[1] < 0)
08474 {
08475 fVSpeed += (-self->client->ps.velocity[1]);
08476 }
08477 else
08478 {
08479 fVSpeed += self->client->ps.velocity[1];
08480 }
08481 if (self->client->ps.velocity[2] < 0)
08482 {
08483 fVSpeed += (-self->client->ps.velocity[2]);
08484 }
08485 else
08486 {
08487 fVSpeed += self->client->ps.velocity[2];
08488 }
08489
08490 //fVSpeed *= 0.08;
08491 fVSpeed *= 1.6f/g_svfps.value;
08492
08493 //Cap it off at reasonable values so the saber box doesn't go flying ahead of us or
08494 //something if we get a big speed boost from something.
08495 if (fVSpeed > 70)
08496 {
08497 fVSpeed = 70;
08498 }
08499 if (fVSpeed < -70)
08500 {
08501 fVSpeed = -70;
08502 }
08503
08504 properOrigin[0] += addVel[0]*fVSpeed;
08505 properOrigin[1] += addVel[1]*fVSpeed;
08506 properOrigin[2] += addVel[2]*fVSpeed;
08507
08508 properAngles[0] = 0;
08509 if (self->s.number < MAX_CLIENTS && self->client->ps.m_iVehicleNum)
08510 {
08511 vehEnt = &g_entities[self->client->ps.m_iVehicleNum];
08512 if (vehEnt->inuse && vehEnt->client && vehEnt->m_pVehicle)
08513 {
08514 properAngles[1] = vehEnt->m_pVehicle->m_vOrientation[YAW];
08515 }
08516 else
08517 {
08518 properAngles[1] = self->client->ps.viewangles[YAW];
08519 vehEnt = NULL;
08520 }
08521 }
08522 else
08523 {
08524 properAngles[1] = self->client->ps.viewangles[YAW];
08525 }
08526 properAngles[2] = 0;
08527
08528 AnglesToAxis( properAngles, legAxis );
08529
08530 UpdateClientRenderinfo(self, properOrigin, properAngles);
08531
08532 if (!clientOverride)
08533 { //if we get the client instance we don't need to do this
08534 G_G2PlayerAngles( self, legAxis, properAngles );
08535 }
08536
08537 if (vehEnt)
08538 {
08539 properAngles[1] = vehEnt->m_pVehicle->m_vOrientation[YAW];
08540 }
08541
08542 if (returnAfterUpdate && saberNum)
08543 { //We don't even need to do GetBoltMatrix if we're only in here to keep the g2 server instance in sync
08544 //but keep our saber entity in sync too, just copy it over our origin.
08545
08546 //I guess it's good to keep the position updated even when contents are 0
08547 if (mySaber && ((mySaber->r.contents & CONTENTS_LIGHTSABER) || mySaber->r.contents == 0) && !self->client->ps.saberInFlight)
08548 { //Since we haven't got a bolt position, place it on top of the player origin.
08549 VectorCopy(self->client->ps.origin, mySaber->r.currentOrigin);
08550 }
08551
08552 goto finalUpdate;
08553 }
08554
08555 if (returnAfterUpdate)
08556 {
08557 goto finalUpdate;
08558 }
08559
08560 //We'll get data for blade 0 first no matter what it is and stick them into
08561 //the constant ("_Always") values. Later we will handle going through each blade.
08562 trap_G2API_GetBoltMatrix(self->ghoul2, 1, 0, &boltMatrix, properAngles, properOrigin, level.time, NULL, self->modelScale);
08563 BG_GiveMeVectorFromMatrix(&boltMatrix, ORIGIN, boltOrigin);
08564 BG_GiveMeVectorFromMatrix(&boltMatrix, NEGATIVE_Y, boltAngles);
08565
08566 //immediately store these values so we don't have to recalculate this again
08567 if (self->client->lastSaberStorageTime && (level.time - self->client->lastSaberStorageTime) < 200)
08568 { //alright
08569 VectorCopy(self->client->lastSaberBase_Always, self->client->olderSaberBase);
08570 self->client->olderIsValid = qtrue;
08571 }
08572 else
08573 {
08574 self->client->olderIsValid = qfalse;
08575 }
08576
08577 VectorCopy(boltOrigin, self->client->lastSaberBase_Always);
08578 VectorCopy(boltAngles, self->client->lastSaberDir_Always);
08579 self->client->lastSaberStorageTime = level.time;
08580
08581 VectorCopy(boltAngles, rawAngles);
08582
08583 VectorMA( boltOrigin, self->client->saber[0].blade[0].lengthMax, boltAngles, end );
08584
08585 if (self->client->ps.saberEntityNum)
08586 {
08587 //I guess it's good to keep the position updated even when contents are 0
08588 if (mySaber && ((mySaber->r.contents & CONTENTS_LIGHTSABER) || mySaber->r.contents == 0) && !self->client->ps.saberInFlight)
08589 { //place it roughly in the middle of the saber..
08590 VectorMA( boltOrigin, self->client->saber[0].blade[0].lengthMax, boltAngles, mySaber->r.currentOrigin );
08591 }
08592 }
08593
08594 boltAngles[YAW] = self->client->ps.viewangles[YAW];
08595
08596 /* {
08597 static int lastDTime = 0;
08598 if (lastDTime < level.time)
08599 {
08600 G_TestLine(boltOrigin, end, 0x0000ff, 200);
08601 lastDTime = level.time + 200;
08602 }
08603 }
08604 */
08605 if (self->client->ps.saberInFlight)
08606 { //do the thrown-saber stuff
08607 gentity_t *saberent = &g_entities[saberNum];
08608
08609 if (saberent)
08610 {
08611 if (!self->client->ps.saberEntityState && self->client->ps.saberEntityNum)
08612 {
08613 vec3_t startorg, startang, dir;
08614
08615 VectorCopy(boltOrigin, saberent->r.currentOrigin);
08616
08617 VectorCopy(boltOrigin, startorg);
08618 VectorCopy(boltAngles, startang);
08619
08620 //startang[0] = 90;
08621 //Instead of this we'll sort of fake it and slowly tilt it down on the client via
08622 //a perframe method (which doesn't actually affect where or how the saber hits)
08623
08624 saberent->r.svFlags &= ~(SVF_NOCLIENT);
08625 VectorCopy(startorg, saberent->s.pos.trBase);
08626 VectorCopy(startang, saberent->s.apos.trBase);
08627
08628 VectorCopy(startorg, saberent->s.origin);
08629 VectorCopy(startang, saberent->s.angles);
08630
08631 saberent->s.saberInFlight = qtrue;
08632
08633 saberent->s.apos.trType = TR_LINEAR;
08634 saberent->s.apos.trDelta[0] = 0;
08635 saberent->s.apos.trDelta[1] = 800;
08636 saberent->s.apos.trDelta[2] = 0;
08637
08638 saberent->s.pos.trType = TR_LINEAR;
08639 saberent->s.eType = ET_GENERAL;
08640 saberent->s.eFlags = 0;
08641
08642 WP_SaberAddG2Model( saberent, self->client->saber[0].model, self->client->saber[0].skin );
08643
08644 saberent->s.modelGhoul2 = 127;
08645
08646 saberent->parent = self;
08647
08648 self->client->ps.saberEntityState = 1;
08649
08650 //Projectile stuff:
08651 AngleVectors(self->client->ps.viewangles, dir, NULL, NULL);
08652
08653 saberent->nextthink = level.time + FRAMETIME;
08654 saberent->think = saberFirstThrown;
08655
08656 saberent->damage = SABER_THROWN_HIT_DAMAGE;
08657 saberent->methodOfDeath = MOD_SABER;
08658 saberent->splashMethodOfDeath = MOD_SABER;
08659 saberent->s.solid = 2;
08660 saberent->r.contents = CONTENTS_LIGHTSABER;
08661
08662 saberent->genericValue5 = 0;
08663
08664 VectorSet( saberent->r.mins, SABERMINS_X, SABERMINS_Y, SABERMINS_Z );
08665 VectorSet( saberent->r.maxs, SABERMAXS_X, SABERMAXS_Y, SABERMAXS_Z );
08666
08667 saberent->s.genericenemyindex = self->s.number+1024;
08668
08669 saberent->touch = thrownSaberTouch;
08670
08671 saberent->s.weapon = WP_SABER;
08672
08673 VectorScale(dir, 400, saberent->s.pos.trDelta );
08674 saberent->s.pos.trTime = level.time;
08675
08676 if ( self->client->saber[0].spinSound )
08677 {
08678 saberent->s.loopSound = self->client->saber[0].spinSound;
08679 }
08680 else
08681 {
08682 saberent->s.loopSound = saberSpinSound;
08683 }
08684 saberent->s.loopIsSoundset = qfalse;
08685
08686 self->client->ps.saberDidThrowTime = level.time;
08687
08688 self->client->dangerTime = level.time;
08689 self->client->ps.eFlags &= ~EF_INVULNERABLE;
08690 self->client->invulnerableTimer = 0;
08691
08692 trap_LinkEntity(saberent);
08693 }
08694 else if (self->client->ps.saberEntityNum) //only do this stuff if your saber is active and has not been knocked out of the air.
08695 {
08696 VectorCopy(boltOrigin, saberent->pos1);
08697 trap_LinkEntity(saberent);
08698
08699 if (saberent->genericValue5 == PROPER_THROWN_VALUE)
08700 { //return to the owner now, this is a bad state to be in for here..
08701 saberent->genericValue5 = 0;
08702 saberent->think = SaberUpdateSelf;
08703 saberent->nextthink = level.time;
08704 WP_SaberRemoveG2Model( saberent );
08705
08706 self->client->ps.saberInFlight = qfalse;
08707 self->client->ps.saberEntityState = 0;
08708 self->client->ps.saberThrowDelay = level.time + 500;
08709 self->client->ps.saberCanThrow = qfalse;
08710 }
08711 }
08712 }
08713 }
08714
08715 /*
08716 if (self->client->ps.saberInFlight)
08717 { //if saber is thrown then only do the standard stuff for the left hand saber
08718 rSaberNum = 1;
08719 }
08720 */
08721
08722 if (!BG_SabersOff(&self->client->ps))
08723 {
08724 gentity_t *saberent = &g_entities[saberNum];
08725
08726 if (!self->client->ps.saberInFlight && saberent)
08727 {
08728 saberent->r.svFlags |= (SVF_NOCLIENT);
08729 saberent->r.contents = CONTENTS_LIGHTSABER;
08730 SetSaberBoxSize(saberent);
08731 saberent->s.loopSound = 0;
08732 saberent->s.loopIsSoundset = qfalse;
08733 }
08734
08735 if (self->client->ps.saberLockTime > level.time && self->client->ps.saberEntityNum)
08736 {
08737 if (self->client->ps.saberIdleWound < level.time)
08738 {
08739 gentity_t *te;
08740 vec3_t dir;
08741 te = G_TempEntity( g_entities[saberNum].r.currentOrigin, EV_SABER_BLOCK );
08742 VectorSet( dir, 0, 1, 0 );
08743 VectorCopy(g_entities[saberNum].r.currentOrigin, te->s.origin);
08744 VectorCopy(dir, te->s.angles);
08745 te->s.eventParm = 1;
08746 te->s.weapon = 0;//saberNum
08747 te->s.legsAnim = 0;//bladeNum
08748
08749 self->client->ps.saberIdleWound = level.time + Q_irand(400, 600);
08750 }
08751
08752 while (rSaberNum < MAX_SABERS)
08753 {
08754 rBladeNum = 0;
08755 while (rBladeNum < self->client->saber[rSaberNum].numBlades)
08756 { //Don't bother updating the bolt for each blade for this, it's just a very rough fallback method for during saberlocks
08757 VectorCopy(boltOrigin, self->client->saber[saberNum].blade[rBladeNum].trail.base);
08758 VectorCopy(end, self->client->saber[saberNum].blade[rBladeNum].trail.tip);
08759 self->client->saber[saberNum].blade[rBladeNum].trail.lastTime = level.time;
08760
08761 rBladeNum++;
08762 }
08763
08764 rSaberNum++;
08765 }
08766 self->client->hasCurrentPosition = qtrue;
08767
08768 self->client->ps.saberBlocked = BLOCKED_NONE;
08769
08770 goto finalUpdate;
08771 }
08772
08773 //reset it in case we used it for cycling before
08774 rSaberNum = rBladeNum = 0;
08775
08776 if (self->client->ps.saberInFlight)
08777 { //if saber is thrown then only do the standard stuff for the left hand saber
08778 if (!self->client->ps.saberEntityNum)
08779 { //however, if saber is not in flight but rather knocked away, our left saber is off, and thus we may do nothing.
08780 rSaberNum = 1;//was 2?
08781 }
08782 else
08783 {//thrown saber still in flight, so do damage
08784 rSaberNum = 0;//was 1?
08785 }
08786 }
08787
08788 WP_SaberClearDamage();
08789 saberDoClashEffect = qfalse;
08790
08791 //Now cycle through each saber and each blade on the saber and do damage traces.
08792 while (rSaberNum < MAX_SABERS)
08793 {
08794 if (!self->client->saber[rSaberNum].model[0])
08795 {
08796 rSaberNum++;
08797 continue;
08798 }
08799
08800 /*
08801 if (rSaberNum == 0 && (self->client->ps.brokenLimbs & (1 << BROKENLIMB_RARM)))
08802 { //don't do saber 0 is the right arm is broken
08803 rSaberNum++;
08804 continue;
08805 }
08806 */
08807 //for now I'm keeping a broken right arm swingable, it will just look and act damaged
08808 //but still be useable
08809
08810 if (rSaberNum == 1 && (self->client->ps.brokenLimbs & (1 << BROKENLIMB_LARM)))
08811 { //don't to saber 1 if the left arm is broken
08812 break;
08813 }
08814 if (rSaberNum > 0
08815 && self->client->saber[1].model
08816 && self->client->saber[1].model[0]
08817 && self->client->ps.saberHolstered == 1 )
08818 { //don't to saber 2 if it's off
08819 break;
08820 }
08821 rBladeNum = 0;
08822 while (rBladeNum < self->client->saber[rSaberNum].numBlades)
08823 {
08824 //update muzzle data for the blade
08825 VectorCopy(self->client->saber[rSaberNum].blade[rBladeNum].muzzlePoint, self->client->saber[rSaberNum].blade[rBladeNum].muzzlePointOld);
08826 VectorCopy(self->client->saber[rSaberNum].blade[rBladeNum].muzzleDir, self->client->saber[rSaberNum].blade[rBladeNum].muzzleDirOld);
08827
08828 if ( rBladeNum > 0 //more than one blade
08829 && (!self->client->saber[1].model||!self->client->saber[1].model[0])//not using dual blades
08830 && self->client->saber[rSaberNum].numBlades > 1//using a multi-bladed saber
08831 && self->client->ps.saberHolstered == 1 )//
08832 { //don't to extra blades if they're off
08833 break;
08834 }
08835 //get the new data
08836 //then update the bolt pos/dir. rBladeNum corresponds to the bolt index because blade bolts are added in order.
08837 if ( rSaberNum == 0 && self->client->ps.saberInFlight )
08838 {
08839 if ( !self->client->ps.saberEntityNum )
08840 {//dropped it... shouldn't get here, but...
08841 //assert(0);
08842 //FIXME: It's getting here a lot actually....
08843 rSaberNum++;
08844 rBladeNum = 0;
08845 continue;
08846 }
08847 else
08848 {
08849 gentity_t *saberEnt = &g_entities[self->client->ps.saberEntityNum];
08850 vec3_t saberOrg, saberAngles;
08851 if ( !saberEnt
08852 || !saberEnt->inuse
08853 || !saberEnt->ghoul2 )
08854 {//wtf?
08855 rSaberNum++;
08856 rBladeNum = 0;
08857 continue;
08858 }
08859 if ( saberent->s.saberInFlight )
08860 {//spinning
08861 BG_EvaluateTrajectory( &saberEnt->s.pos, level.time+50, saberOrg );
08862 BG_EvaluateTrajectory( &saberEnt->s.apos, level.time+50, saberAngles );
08863 }
08864 else
08865 {//coming right back
08866 vec3_t saberDir;
08867 BG_EvaluateTrajectory( &saberEnt->s.pos, level.time, saberOrg );
08868 VectorSubtract( self->r.currentOrigin, saberOrg, saberDir );
08869 vectoangles( saberDir, saberAngles );
08870 }
08871 trap_G2API_GetBoltMatrix(saberEnt->ghoul2, 0, rBladeNum, &boltMatrix, saberAngles, saberOrg, level.time, NULL, self->modelScale);
08872 BG_GiveMeVectorFromMatrix(&boltMatrix, ORIGIN, self->client->saber[rSaberNum].blade[rBladeNum].muzzlePoint);
08873 BG_GiveMeVectorFromMatrix(&boltMatrix, NEGATIVE_Y, self->client->saber[rSaberNum].blade[rBladeNum].muzzleDir);
08874 VectorCopy( self->client->saber[rSaberNum].blade[rBladeNum].muzzlePoint, boltOrigin );
08875 VectorMA( boltOrigin, self->client->saber[rSaberNum].blade[rBladeNum].lengthMax, self->client->saber[rSaberNum].blade[rBladeNum].muzzleDir, end );
08876 }
08877
08878 }
08879 else
08880 {
08881 trap_G2API_GetBoltMatrix(self->ghoul2, rSaberNum+1, rBladeNum, &boltMatrix, properAngles, properOrigin, level.time, NULL, self->modelScale);
08882 BG_GiveMeVectorFromMatrix(&boltMatrix, ORIGIN, self->client->saber[rSaberNum].blade[rBladeNum].muzzlePoint);
08883 BG_GiveMeVectorFromMatrix(&boltMatrix, NEGATIVE_Y, self->client->saber[rSaberNum].blade[rBladeNum].muzzleDir);
08884 VectorCopy( self->client->saber[rSaberNum].blade[rBladeNum].muzzlePoint, boltOrigin );
08885 VectorMA( boltOrigin, self->client->saber[rSaberNum].blade[rBladeNum].lengthMax, self->client->saber[rSaberNum].blade[rBladeNum].muzzleDir, end );
08886 }
08887
08888 self->client->saber[rSaberNum].blade[rBladeNum].storageTime = level.time;
08889
08890 if (self->client->hasCurrentPosition && d_saberInterpolate.integer)
08891 {
08892 if (self->client->ps.weaponTime <= 0)
08893 { //rww - 07/17/02 - don't bother doing the extra stuff unless actually attacking. This is in attempt to save CPU.
08894 CheckSaberDamage(self, rSaberNum, rBladeNum, boltOrigin, end, qfalse, (MASK_PLAYERSOLID|CONTENTS_LIGHTSABER|MASK_SHOT), qfalse);
08895 }
08896 else if (d_saberInterpolate.integer == 1)
08897 {
08898 int trMask = CONTENTS_LIGHTSABER|CONTENTS_BODY;
08899 int sN = 0;
08900 qboolean gotHit = qfalse;
08901 qboolean clientUnlinked[MAX_CLIENTS];
08902 qboolean skipSaberTrace = qfalse;
08903
08904 if (!g_saberTraceSaberFirst.integer)
08905 {
08906 skipSaberTrace = qtrue;
08907 }
08908 else if (g_saberTraceSaberFirst.integer >= 2 &&
08909 g_gametype.integer != GT_DUEL &&
08910 g_gametype.integer != GT_POWERDUEL &&
08911 !self->client->ps.duelInProgress)
08912 { //if value is >= 2, and not in a duel, skip
08913 skipSaberTrace = qtrue;
08914 }
08915
08916 if (skipSaberTrace)
08917 { //skip the saber-contents-only trace and get right to the full trace
08918 trMask = (MASK_PLAYERSOLID|CONTENTS_LIGHTSABER|MASK_SHOT);
08919 }
08920 else
08921 {
08922 while (sN < MAX_CLIENTS)
08923 {
08924 if (g_entities[sN].inuse && g_entities[sN].client && g_entities[sN].r.linked && g_entities[sN].health > 0 && (g_entities[sN].r.contents & CONTENTS_BODY))
08925 { //Take this mask off before the saber trace, because we want to hit the saber first
08926 g_entities[sN].r.contents &= ~CONTENTS_BODY;
08927 clientUnlinked[sN] = qtrue;
08928 }
08929 else
08930 {
08931 clientUnlinked[sN] = qfalse;
08932 }
08933 sN++;
08934 }
08935 }
08936
08937 while (!gotHit)
08938 {
08939 if (!CheckSaberDamage(self, rSaberNum, rBladeNum, boltOrigin, end, qfalse, trMask, qfalse))
08940 {
08941 if (!CheckSaberDamage(self, rSaberNum, rBladeNum, boltOrigin, end, qtrue, trMask, qfalse))
08942 {
08943 vec3_t oldSaberStart;
08944 vec3_t oldSaberEnd;
08945 vec3_t saberAngleNow;
08946 vec3_t saberAngleBefore;
08947 vec3_t saberMidDir;
08948 vec3_t saberMidAngle;
08949 vec3_t saberMidPoint;
08950 vec3_t saberMidEnd;
08951 vec3_t saberSubBase;
08952 float deltaX, deltaY, deltaZ;
08953
08954 if ( (level.time-self->client->saber[rSaberNum].blade[rBladeNum].trail.lastTime) > 100 )
08955 {//no valid last pos, use current
08956 VectorCopy(boltOrigin, oldSaberStart);
08957 VectorCopy(end, oldSaberEnd);
08958 }
08959 else
08960 {//trace from last pos
08961 VectorCopy(self->client->saber[rSaberNum].blade[rBladeNum].trail.base, oldSaberStart);
08962 VectorCopy(self->client->saber[rSaberNum].blade[rBladeNum].trail.tip, oldSaberEnd);
08963 }
08964
08965 VectorSubtract(oldSaberEnd, oldSaberStart, saberAngleBefore);
08966 vectoangles(saberAngleBefore, saberAngleBefore);
08967
08968 VectorSubtract(end, boltOrigin, saberAngleNow);
08969 vectoangles(saberAngleNow, saberAngleNow);
08970
08971 deltaX = AngleDelta(saberAngleBefore[0], saberAngleNow[0]);
08972 deltaY = AngleDelta(saberAngleBefore[1], saberAngleNow[1]);
08973 deltaZ = AngleDelta(saberAngleBefore[2], saberAngleNow[2]);
08974
08975 if ( (deltaX != 0 || deltaY != 0 || deltaZ != 0) && deltaX < 180 && deltaY < 180 && deltaZ < 180 && (BG_SaberInAttack(self->client->ps.saberMove) || PM_SaberInTransition(self->client->ps.saberMove)) )
08976 { //don't go beyond here if we aren't attacking/transitioning or the angle is too large.
08977 //and don't bother if the angle is the same
08978 saberMidAngle[0] = saberAngleBefore[0] + (deltaX/2);
08979 saberMidAngle[1] = saberAngleBefore[1] + (deltaY/2);
08980 saberMidAngle[2] = saberAngleBefore[2] + (deltaZ/2);
08981
08982 //Now that I have the angle, I'll just say the base for it is the difference between the two start
08983 //points (even though that's quite possibly completely false)
08984 VectorSubtract(boltOrigin, oldSaberStart, saberSubBase);
08985 saberMidPoint[0] = boltOrigin[0] + (saberSubBase[0]*0.5);
08986 saberMidPoint[1] = boltOrigin[1] + (saberSubBase[1]*0.5);
08987 saberMidPoint[2] = boltOrigin[2] + (saberSubBase[2]*0.5);
08988
08989 AngleVectors(saberMidAngle, saberMidDir, 0, 0);
08990 saberMidEnd[0] = saberMidPoint[0] + saberMidDir[0]*self->client->saber[rSaberNum].blade[rBladeNum].lengthMax;
08991 saberMidEnd[1] = saberMidPoint[1] + saberMidDir[1]*self->client->saber[rSaberNum].blade[rBladeNum].lengthMax;
08992 saberMidEnd[2] = saberMidPoint[2] + saberMidDir[2]*self->client->saber[rSaberNum].blade[rBladeNum].lengthMax;
08993
08994 //I'll just trace straight out and not even trace between positions to save speed.
08995 if (CheckSaberDamage(self, rSaberNum, rBladeNum, saberMidPoint, saberMidEnd, qfalse, trMask, qfalse))
08996 {
08997 gotHit = qtrue;
08998 }
08999 }
09000 }
09001 else
09002 {
09003 gotHit = qtrue;
09004 }
09005 }
09006 else
09007 {
09008 gotHit = qtrue;
09009 }
09010
09011 if (g_saberTraceSaberFirst.integer)
09012 {
09013 sN = 0;
09014 while (sN < MAX_CLIENTS)
09015 {
09016 if (clientUnlinked[sN])
09017 { //Make clients clip properly again.
09018 if (g_entities[sN].inuse && g_entities[sN].health > 0)
09019 {
09020 g_entities[sN].r.contents |= CONTENTS_BODY;
09021 }
09022 }
09023 sN++;
09024 }
09025 }
09026
09027 if (!gotHit)
09028 {
09029 if (trMask != (MASK_PLAYERSOLID|CONTENTS_LIGHTSABER|MASK_SHOT))
09030 {
09031 trMask = (MASK_PLAYERSOLID|CONTENTS_LIGHTSABER|MASK_SHOT);
09032 }
09033 else
09034 {
09035 gotHit = qtrue; //break out of the loop
09036 }
09037 }
09038 }
09039 }
09040 else if (d_saberInterpolate.integer) //anything but 0 or 1, use the old plain method.
09041 {
09042 if (!CheckSaberDamage(self, rSaberNum, rBladeNum, boltOrigin, end, qfalse, (MASK_PLAYERSOLID|CONTENTS_LIGHTSABER|MASK_SHOT), qfalse))
09043 {
09044 CheckSaberDamage(self, rSaberNum, rBladeNum, boltOrigin, end, qtrue, (MASK_PLAYERSOLID|CONTENTS_LIGHTSABER|MASK_SHOT), qfalse);
09045 }
09046 }
09047 }
09048 else if ( d_saberSPStyleDamage.integer )
09049 {
09050 G_SPSaberDamageTraceLerped( self, rSaberNum, rBladeNum, boltOrigin, end, (MASK_PLAYERSOLID|CONTENTS_LIGHTSABER|MASK_SHOT) );
09051 }
09052 else
09053 {
09054 CheckSaberDamage(self, rSaberNum, rBladeNum, boltOrigin, end, qfalse, (MASK_PLAYERSOLID|CONTENTS_LIGHTSABER|MASK_SHOT), qfalse);
09055 }
09056
09057 VectorCopy(boltOrigin, self->client->saber[rSaberNum].blade[rBladeNum].trail.base);
09058 VectorCopy(end, self->client->saber[rSaberNum].blade[rBladeNum].trail.tip);
09059 self->client->saber[rSaberNum].blade[rBladeNum].trail.lastTime = level.time;
09060 //VectorCopy(boltOrigin, self->client->lastSaberBase);
09061 //VectorCopy(end, self->client->lastSaberTip);
09062 self->client->hasCurrentPosition = qtrue;
09063
09064 //do hit effects
09065 WP_SaberDoHit( self, rSaberNum, rBladeNum );
09066 WP_SaberDoClash( self, rSaberNum, rBladeNum );
09067
09068 rBladeNum++;
09069 }
09070
09071 rSaberNum++;
09072 }
09073
09074 WP_SaberApplyDamage( self );
09075 //NOTE: doing one call like this after the 2 loops above is a bit cheaper, tempentity-wise... but won't use the correct saber and blade numbers...
09076 //now actually go through and apply all the damage we did
09077 //WP_SaberDoHit( self, 0, 0 );
09078 //WP_SaberDoClash( self, 0, 0 );
09079
09080 if (mySaber && mySaber->inuse)
09081 {
09082 trap_LinkEntity(mySaber);
09083 }
09084
09085 if (!self->client->ps.saberInFlight)
09086 {
09087 self->client->ps.saberEntityState = 0;
09088 }
09089 }
09090 finalUpdate:
09091 if (clientOverride)
09092 { //if we get the client instance we don't even need to bother setting anims and stuff
09093 return;
09094 }
09095
09096 G_UpdateClientAnims(self, animSpeedScale);
09097 }
|
|
||||||||||||||||||||||||
|
Definition at line 3699 of file w_saber.c. References ceil(), CLASS_ATST, CLASS_RANCOR, gentity_s::client, entityShared_t::currentOrigin, DAMAGE_NO_KNOCKBACK, EF2_HELD_BY_MONSTER, playerState_s::eFlags2, ENTITYNUM_NONE, FL_NO_KNOCKBACK, gentity_s::flags, G_Damage(), G_EntIsBreakable(), g_entities, G_Knockdown(), G_Throw(), gentity_t, playerState_s::groundEntityNum, gentity_s::health, gentity_s::inuse, MOD_MELEE, gclient_s::NPC_class, NULL, entityState_s::number, gclient_s::ps, gentity_s::r, gentity_s::s, trap_EntitiesInBox(), vec3_origin, vec3_t, VectorNormalize(), and VectorSubtract.
03700 {
03701 if ( !ent || !ent->client )
03702 {
03703 return;
03704 }
03705 else if ( radius <= 0.0f || (damage <= 0 && knockBack <= 0) )
03706 {
03707 return;
03708 }
03709 else
03710 {
03711 vec3_t mins, maxs, entDir;
03712 int radiusEnts[128];
03713 gentity_t *radiusEnt = NULL;
03714 int numEnts, i;
03715 float dist;
03716
03717 //Setup the bbox to search in
03718 for ( i = 0; i < 3; i++ )
03719 {
03720 mins[i] = point[i] - radius;
03721 maxs[i] = point[i] + radius;
03722 }
03723
03724 //Get the number of entities in a given space
03725 numEnts = trap_EntitiesInBox( mins, maxs, radiusEnts, 128 );
03726
03727 for ( i = 0; i < numEnts; i++ )
03728 {
03729 radiusEnt = &g_entities[radiusEnts[i]];
03730 if ( !radiusEnt->inuse )
03731 {
03732 continue;
03733 }
03734
03735 if ( radiusEnt == ent )
03736 {//Skip myself
03737 continue;
03738 }
03739
03740 if ( radiusEnt->client == NULL )
03741 {//must be a client
03742 if ( G_EntIsBreakable( radiusEnt->s.number ) )
03743 {//damage breakables within range, but not as much
03744 G_Damage( radiusEnt, ent, ent, vec3_origin, radiusEnt->r.currentOrigin, 10, 0, MOD_MELEE );
03745 }
03746 continue;
03747 }
03748
03749 if ( (radiusEnt->client->ps.eFlags2&EF2_HELD_BY_MONSTER) )
03750 {//can't be one being held
03751 continue;
03752 }
03753
03754 VectorSubtract( radiusEnt->r.currentOrigin, point, entDir );
03755 dist = VectorNormalize( entDir );
03756 if ( dist <= radius )
03757 {//in range
03758 if ( damage > 0 )
03759 {//do damage
03760 int points = ceil((float)damage*dist/radius);
03761 G_Damage( radiusEnt, ent, ent, vec3_origin, radiusEnt->r.currentOrigin, points, DAMAGE_NO_KNOCKBACK, MOD_MELEE );
03762 }
03763 if ( knockBack > 0 )
03764 {//do knockback
03765 if ( radiusEnt->client
03766 && radiusEnt->client->NPC_class != CLASS_RANCOR
03767 && radiusEnt->client->NPC_class != CLASS_ATST
03768 && !(radiusEnt->flags&FL_NO_KNOCKBACK) )//don't throw them back
03769 {
03770 float knockbackStr = knockBack*dist/radius;
03771 entDir[2] += 0.1f;
03772 VectorNormalize( entDir );
03773 G_Throw( radiusEnt, entDir, knockbackStr );
03774 if ( radiusEnt->health > 0 )
03775 {//still alive
03776 if ( knockbackStr > 50 )
03777 {//close enough and knockback high enough to possibly knock down
03778 if ( dist < (radius*0.5f)
03779 || radiusEnt->client->ps.groundEntityNum != ENTITYNUM_NONE )
03780 {//within range of my fist or within ground-shaking range and not in the air
03781 G_Knockdown( radiusEnt );//, ent, entDir, 500, qtrue );
03782 }
03783 }
03784 }
03785 }
03786 }
03787 }
03788 }
03789 }
03790 }
|
|
|
Referenced by DownedSaberThink(), saberBackToOwner(), saberFirstThrown(), WP_SaberAddG2Model(), and WP_SaberPositionUpdate(). |
|
||||||||||||
|
Definition at line 1460 of file w_saber.c. References BG_InRoll(), BG_InSpecialJump(), BLK_WIDE, BOTH_A1__L__R, BOTH_A1__R__L, BOTH_A1_BL_TR, BOTH_A1_BR_TL, BOTH_A1_T__B_, BOTH_A1_TL_BR, BOTH_A1_TR_BL, BOTH_A2__L__R, BOTH_A2__R__L, BOTH_A2_BL_TR, BOTH_A2_BR_TL, BOTH_A2_T__B_, BOTH_A2_TL_BR, BOTH_A2_TR_BL, BOTH_A3__L__R, BOTH_A3__R__L, BOTH_A3_BL_TR, BOTH_A3_BR_TL, BOTH_A3_T__B_, BOTH_A3_TL_BR, BOTH_A3_TR_BL, BOTH_A4__L__R, BOTH_A4__R__L, BOTH_A4_BL_TR, BOTH_A4_BR_TL, BOTH_A4_T__B_, BOTH_A4_TL_BR, BOTH_A4_TR_BL, BOTH_A5__L__R, BOTH_A5__R__L, BOTH_A5_BL_TR, BOTH_A5_BR_TL, BOTH_A5_T__B_, BOTH_A5_TL_BR, BOTH_A5_TR_BL, BOTH_A6__L__R, BOTH_A6__R__L, BOTH_A6_BL_TR, BOTH_A6_BR_TL, BOTH_A6_T__B_, BOTH_A6_TL_BR, BOTH_A6_TR_BL, BOTH_A7__L__R, BOTH_A7__R__L, BOTH_A7_BL_TR, BOTH_A7_BR_TL, BOTH_A7_T__B_, BOTH_A7_TL_BR, BOTH_A7_TR_BL, BOTH_P1_S1_BL, BOTH_P1_S1_BR, BOTH_P1_S1_TL, BOTH_P1_S1_TR, gentity_s::client, entityShared_t::currentOrigin, playerState_s::duelIndex, playerState_s::duelInProgress, ENTITYNUM_NONE, ET_NPC, entityState_s::eType, fabs(), playerState_s::forceHandExtend, g_debugSaberLocks, g_gametype, g_saberLocking, gentity_t, playerState_s::groundEntityNum, GT_DUEL, GT_POWERDUEL, HANDEXTEND_NONE, InFront(), vmCvar_t::integer, playerState_s::legsAnim, LOCK_DIAG_BL, LOCK_DIAG_BR, LOCK_DIAG_TL, LOCK_DIAG_TR, LOCK_L, LOCK_R, LOCK_RANDOM, LOCK_TOP, saberInfo_t::model, entityState_s::number, playerState_s::origin, gclient_s::playerTeam, playerState_s::pm_flags, PMF_DUCKED, gclient_s::ps, Q_irand(), qboolean, qfalse, qtrue, gentity_s::r, gentity_s::s, gclient_s::saber, playerState_s::saberBlocking, playerState_s::saberEntityNum, saberInfo_t::saberFlags, playerState_s::saberHolstered, playerState_s::saberInFlight, SFL_NOT_LOCKABLE, playerState_s::torsoAnim, playerState_s::viewangles, and playerState_s::weaponTime.
01461 {
01462 float dist;
01463 qboolean ent1BlockingPlayer = qfalse;
01464 qboolean ent2BlockingPlayer = qfalse;
01465
01466 if ( g_debugSaberLocks.integer )
01467 {
01468 WP_SabersCheckLock2( ent1, ent2, LOCK_RANDOM );
01469 return qtrue;
01470 }
01471 //for now.. it's not fair to the lone duelist.
01472 //we need dual saber lock animations.
01473 if (g_gametype.integer == GT_POWERDUEL)
01474 {
01475 return qfalse;
01476 }
01477
01478 if (!g_saberLocking.integer)
01479 {
01480 return qfalse;
01481 }
01482
01483 if (!ent1->client || !ent2->client)
01484 {
01485 return qfalse;
01486 }
01487
01488 if (ent1->s.eType == ET_NPC ||
01489 ent2->s.eType == ET_NPC)
01490 { //if either ents is NPC, then never let an NPC lock with someone on the same playerTeam
01491 if (ent1->client->playerTeam == ent2->client->playerTeam)
01492 {
01493 return qfalse;
01494 }
01495 }
01496
01497 if (!ent1->client->ps.saberEntityNum ||
01498 !ent2->client->ps.saberEntityNum ||
01499 ent1->client->ps.saberInFlight ||
01500 ent2->client->ps.saberInFlight)
01501 { //can't get in lock if one of them has had the saber knocked out of his hand
01502 return qfalse;
01503 }
01504
01505 if (ent1->s.eType != ET_NPC && ent2->s.eType != ET_NPC)
01506 { //can always get into locks with NPCs
01507 if (!ent1->client->ps.duelInProgress ||
01508 !ent2->client->ps.duelInProgress ||
01509 ent1->client->ps.duelIndex != ent2->s.number ||
01510 ent2->client->ps.duelIndex != ent1->s.number)
01511 { //only allow saber locking if two players are dueling with each other directly
01512 if (g_gametype.integer != GT_DUEL && g_gametype.integer != GT_POWERDUEL)
01513 {
01514 return qfalse;
01515 }
01516 }
01517 }
01518
01519 if ( fabs( ent1->r.currentOrigin[2]-ent2->r.currentOrigin[2] ) > 16 )
01520 {
01521 return qfalse;
01522 }
01523 if ( ent1->client->ps.groundEntityNum == ENTITYNUM_NONE ||
01524 ent2->client->ps.groundEntityNum == ENTITYNUM_NONE )
01525 {
01526 return qfalse;
01527 }
01528 dist = DistanceSquared(ent1->r.currentOrigin,ent2->r.currentOrigin);
01529 if ( dist < 64 || dist > 6400 )
01530 {//between 8 and 80 from each other
01531 return qfalse;
01532 }
01533
01534 if (BG_InSpecialJump(ent1->client->ps.legsAnim))
01535 {
01536 return qfalse;
01537 }
01538 if (BG_InSpecialJump(ent2->client->ps.legsAnim))
01539 {
01540 return qfalse;
01541 }
01542
01543 if (BG_InRoll(&ent1->client->ps, ent1->client->ps.legsAnim))
01544 {
01545 return qfalse;
01546 }
01547 if (BG_InRoll(&ent2->client->ps, ent2->client->ps.legsAnim))
01548 {
01549 return qfalse;
01550 }
01551
01552 if (ent1->client->ps.forceHandExtend != HANDEXTEND_NONE ||
01553 ent2->client->ps.forceHandExtend != HANDEXTEND_NONE)
01554 {
01555 return qfalse;
01556 }
01557
01558 if ((ent1->client->ps.pm_flags & PMF_DUCKED) ||
01559 (ent2->client->ps.pm_flags & PMF_DUCKED))
01560 {
01561 return qfalse;
01562 }
01563
01564 if ( (ent1->client->saber[0].saberFlags&SFL_NOT_LOCKABLE)
01565 || (ent2->client->saber[0].saberFlags&SFL_NOT_LOCKABLE) )
01566 {
01567 return qfalse;
01568 }
01569 if ( ent1->client->saber[1].model
01570 && ent1->client->saber[1].model[0]
01571 && !ent1->client->ps.saberHolstered
01572 && (ent1->client->saber[1].saberFlags&SFL_NOT_LOCKABLE) )
01573 {
01574 return qfalse;
01575 }
01576 if ( ent2->client->saber[1].model
01577 && ent2->client->saber[1].model[0]
01578 && !ent2->client->ps.saberHolstered
01579 && (ent2->client->saber[1].saberFlags&SFL_NOT_LOCKABLE) )
01580 {
01581 return qfalse;
01582 }
01583
01584 if (!InFront( ent1->client->ps.origin, ent2->client->ps.origin, ent2->client->ps.viewangles, 0.4f ))
01585 {
01586 return qfalse;
01587 }
01588 if (!InFront( ent2->client->ps.origin, ent1->client->ps.origin, ent1->client->ps.viewangles, 0.4f ))
01589 {
01590 return qfalse;
01591 }
01592
01593 //T to B lock
01594 if ( ent1->client->ps.torsoAnim == BOTH_A1_T__B_ ||
01595 ent1->client->ps.torsoAnim == BOTH_A2_T__B_ ||
01596 ent1->client->ps.torsoAnim == BOTH_A3_T__B_ ||
01597 ent1->client->ps.torsoAnim == BOTH_A4_T__B_ ||
01598 ent1->client->ps.torsoAnim == BOTH_A5_T__B_ ||
01599 ent1->client->ps.torsoAnim == BOTH_A6_T__B_ ||
01600 ent1->client->ps.torsoAnim == BOTH_A7_T__B_)
01601 {//ent1 is attacking top-down
01602 return WP_SabersCheckLock2( ent1, ent2, LOCK_TOP );
01603 }
01604
01605 if ( ent2->client->ps.torsoAnim == BOTH_A1_T__B_ ||
01606 ent2->client->ps.torsoAnim == BOTH_A2_T__B_ ||
01607 ent2->client->ps.torsoAnim == BOTH_A3_T__B_ ||
01608 ent2->client->ps.torsoAnim == BOTH_A4_T__B_ ||
01609 ent2->client->ps.torsoAnim == BOTH_A5_T__B_ ||
01610 ent2->client->ps.torsoAnim == BOTH_A6_T__B_ ||
01611 ent2->client->ps.torsoAnim == BOTH_A7_T__B_)
01612 {//ent2 is attacking top-down
01613 return WP_SabersCheckLock2( ent2, ent1, LOCK_TOP );
01614 }
01615
01616 if ( ent1->s.number == 0 &&
01617 ent1->client->ps.saberBlocking == BLK_WIDE && ent1->client->ps.weaponTime <= 0 )
01618 {
01619 ent1BlockingPlayer = qtrue;
01620 }
01621 if ( ent2->s.number == 0 &&
01622 ent2->client->ps.saberBlocking == BLK_WIDE && ent2->client->ps.weaponTime <= 0 )
01623 {
01624 ent2BlockingPlayer = qtrue;
01625 }
01626
01627 //TR to BL lock
01628 if ( ent1->client->ps.torsoAnim == BOTH_A1_TR_BL ||
01629 ent1->client->ps.torsoAnim == BOTH_A2_TR_BL ||
01630 ent1->client->ps.torsoAnim == BOTH_A3_TR_BL ||
01631 ent1->client->ps.torsoAnim == BOTH_A4_TR_BL ||
01632 ent1->client->ps.torsoAnim == BOTH_A5_TR_BL ||
01633 ent1->client->ps.torsoAnim == BOTH_A6_TR_BL ||
01634 ent1->client->ps.torsoAnim == BOTH_A7_TR_BL)
01635 {//ent1 is attacking diagonally
01636 if ( ent2BlockingPlayer )
01637 {//player will block this anyway
01638 return WP_SabersCheckLock2( ent1, ent2, LOCK_DIAG_TR );
01639 }
01640 if ( ent2->client->ps.torsoAnim == BOTH_A1_TR_BL ||
01641 ent2->client->ps.torsoAnim == BOTH_A2_TR_BL ||
01642 ent2->client->ps.torsoAnim == BOTH_A3_TR_BL ||
01643 ent2->client->ps.torsoAnim == BOTH_A4_TR_BL ||
01644 ent2->client->ps.torsoAnim == BOTH_A5_TR_BL ||
01645 ent2->client->ps.torsoAnim == BOTH_A6_TR_BL ||
01646 ent2->client->ps.torsoAnim == BOTH_A7_TR_BL ||
01647 ent2->client->ps.torsoAnim == BOTH_P1_S1_TL )
01648 {//ent2 is attacking in the opposite diagonal
01649 return WP_SabersCheckLock2( ent1, ent2, LOCK_DIAG_TR );
01650 }
01651 if ( ent2->client->ps.torsoAnim == BOTH_A1_BR_TL ||
01652 ent2->client->ps.torsoAnim == BOTH_A2_BR_TL ||
01653 ent2->client->ps.torsoAnim == BOTH_A3_BR_TL ||
01654 ent2->client->ps.torsoAnim == BOTH_A4_BR_TL ||
01655 ent2->client->ps.torsoAnim == BOTH_A5_BR_TL ||
01656 ent2->client->ps.torsoAnim == BOTH_A6_BR_TL ||
01657 ent2->client->ps.torsoAnim == BOTH_A7_BR_TL ||
01658 ent2->client->ps.torsoAnim == BOTH_P1_S1_BL )
01659 {//ent2 is attacking in the opposite diagonal
01660 return WP_SabersCheckLock2( ent1, ent2, LOCK_DIAG_BL );
01661 }
01662 return qfalse;
01663 }
01664
01665 if ( ent2->client->ps.torsoAnim == BOTH_A1_TR_BL ||
01666 ent2->client->ps.torsoAnim == BOTH_A2_TR_BL ||
01667 ent2->client->ps.torsoAnim == BOTH_A3_TR_BL ||
01668 ent2->client->ps.torsoAnim == BOTH_A4_TR_BL ||
01669 ent2->client->ps.torsoAnim == BOTH_A5_TR_BL ||
01670 ent2->client->ps.torsoAnim == BOTH_A6_TR_BL ||
01671 ent2->client->ps.torsoAnim == BOTH_A7_TR_BL)
01672 {//ent2 is attacking diagonally
01673 if ( ent1BlockingPlayer )
01674 {//player will block this anyway
01675 return WP_SabersCheckLock2( ent2, ent1, LOCK_DIAG_TR );
01676 }
01677 if ( ent1->client->ps.torsoAnim == BOTH_A1_TR_BL ||
01678 ent1->client->ps.torsoAnim == BOTH_A2_TR_BL ||
01679 ent1->client->ps.torsoAnim == BOTH_A3_TR_BL ||
01680 ent1->client->ps.torsoAnim == BOTH_A4_TR_BL ||
01681 ent1->client->ps.torsoAnim == BOTH_A5_TR_BL ||
01682 ent1->client->ps.torsoAnim == BOTH_A6_TR_BL ||
01683 ent1->client->ps.torsoAnim == BOTH_A7_TR_BL ||
01684 ent1->client->ps.torsoAnim == BOTH_P1_S1_TL )
01685 {//ent1 is attacking in the opposite diagonal
01686 return WP_SabersCheckLock2( ent2, ent1, LOCK_DIAG_TR );
01687 }
01688 if ( ent1->client->ps.torsoAnim == BOTH_A1_BR_TL ||
01689 ent1->client->ps.torsoAnim == BOTH_A2_BR_TL ||
01690 ent1->client->ps.torsoAnim == BOTH_A3_BR_TL ||
01691 ent1->client->ps.torsoAnim == BOTH_A4_BR_TL ||
01692 ent1->client->ps.torsoAnim == BOTH_A5_BR_TL ||
01693 ent1->client->ps.torsoAnim == BOTH_A6_BR_TL ||
01694 ent1->client->ps.torsoAnim == BOTH_A7_BR_TL ||
01695 ent1->client->ps.torsoAnim == BOTH_P1_S1_BL )
01696 {//ent1 is attacking in the opposite diagonal
01697 return WP_SabersCheckLock2( ent2, ent1, LOCK_DIAG_BL );
01698 }
01699 return qfalse;
01700 }
01701
01702 //TL to BR lock
01703 if ( ent1->client->ps.torsoAnim == BOTH_A1_TL_BR ||
01704 ent1->client->ps.torsoAnim == BOTH_A2_TL_BR ||
01705 ent1->client->ps.torsoAnim == BOTH_A3_TL_BR ||
01706 ent1->client->ps.torsoAnim == BOTH_A4_TL_BR ||
01707 ent1->client->ps.torsoAnim == BOTH_A5_TL_BR ||
01708 ent1->client->ps.torsoAnim == BOTH_A6_TL_BR ||
01709 ent1->client->ps.torsoAnim == BOTH_A7_TL_BR)
01710 {//ent1 is attacking diagonally
01711 if ( ent2BlockingPlayer )
01712 {//player will block this anyway
01713 return WP_SabersCheckLock2( ent1, ent2, LOCK_DIAG_TL );
01714 }
01715 if ( ent2->client->ps.torsoAnim == BOTH_A1_TL_BR ||
01716 ent2->client->ps.torsoAnim == BOTH_A2_TL_BR ||
01717 ent2->client->ps.torsoAnim == BOTH_A3_TL_BR ||
01718 ent2->client->ps.torsoAnim == BOTH_A4_TL_BR ||
01719 ent2->client->ps.torsoAnim == BOTH_A5_TL_BR ||
01720 ent2->client->ps.torsoAnim == BOTH_A6_TL_BR ||
01721 ent2->client->ps.torsoAnim == BOTH_A7_TL_BR ||
01722 ent2->client->ps.torsoAnim == BOTH_P1_S1_TR )
01723 {//ent2 is attacking in the opposite diagonal
01724 return WP_SabersCheckLock2( ent1, ent2, LOCK_DIAG_TL );
01725 }
01726 if ( ent2->client->ps.torsoAnim == BOTH_A1_BL_TR ||
01727 ent2->client->ps.torsoAnim == BOTH_A2_BL_TR ||
01728 ent2->client->ps.torsoAnim == BOTH_A3_BL_TR ||
01729 ent2->client->ps.torsoAnim == BOTH_A4_BL_TR ||
01730 ent2->client->ps.torsoAnim == BOTH_A5_BL_TR ||
01731 ent2->client->ps.torsoAnim == BOTH_A6_BL_TR ||
01732 ent2->client->ps.torsoAnim == BOTH_A7_BL_TR ||
01733 ent2->client->ps.torsoAnim == BOTH_P1_S1_BR )
01734 {//ent2 is attacking in the opposite diagonal
01735 return WP_SabersCheckLock2( ent1, ent2, LOCK_DIAG_BR );
01736 }
01737 return qfalse;
01738 }
01739
01740 if ( ent2->client->ps.torsoAnim == BOTH_A1_TL_BR ||
01741 ent2->client->ps.torsoAnim == BOTH_A2_TL_BR ||
01742 ent2->client->ps.torsoAnim == BOTH_A3_TL_BR ||
01743 ent2->client->ps.torsoAnim == BOTH_A4_TL_BR ||
01744 ent2->client->ps.torsoAnim == BOTH_A5_TL_BR ||
01745 ent2->client->ps.torsoAnim == BOTH_A6_TL_BR ||
01746 ent2->client->ps.torsoAnim == BOTH_A7_TL_BR)
01747 {//ent2 is attacking diagonally
01748 if ( ent1BlockingPlayer )
01749 {//player will block this anyway
01750 return WP_SabersCheckLock2( ent2, ent1, LOCK_DIAG_TL );
01751 }
01752 if ( ent1->client->ps.torsoAnim == BOTH_A1_TL_BR ||
01753 ent1->client->ps.torsoAnim == BOTH_A2_TL_BR ||
01754 ent1->client->ps.torsoAnim == BOTH_A3_TL_BR ||
01755 ent1->client->ps.torsoAnim == BOTH_A4_TL_BR ||
01756 ent1->client->ps.torsoAnim == BOTH_A5_TL_BR ||
01757 ent1->client->ps.torsoAnim == BOTH_A6_TL_BR ||
01758 ent1->client->ps.torsoAnim == BOTH_A7_TL_BR ||
01759 ent1->client->ps.torsoAnim == BOTH_P1_S1_TR )
01760 {//ent1 is attacking in the opposite diagonal
01761 return WP_SabersCheckLock2( ent2, ent1, LOCK_DIAG_TL );
01762 }
01763 if ( ent1->client->ps.torsoAnim == BOTH_A1_BL_TR ||
01764 ent1->client->ps.torsoAnim == BOTH_A2_BL_TR ||
01765 ent1->client->ps.torsoAnim == BOTH_A3_BL_TR ||
01766 ent1->client->ps.torsoAnim == BOTH_A4_BL_TR ||
01767 ent1->client->ps.torsoAnim == BOTH_A5_BL_TR ||
01768 ent1->client->ps.torsoAnim == BOTH_A6_BL_TR ||
01769 ent1->client->ps.torsoAnim == BOTH_A7_BL_TR ||
01770 ent1->client->ps.torsoAnim == BOTH_P1_S1_BR )
01771 {//ent1 is attacking in the opposite diagonal
01772 return WP_SabersCheckLock2( ent2, ent1, LOCK_DIAG_BR );
01773 }
01774 return qfalse;
01775 }
01776 //L to R lock
01777 if ( ent1->client->ps.torsoAnim == BOTH_A1__L__R ||
01778 ent1->client->ps.torsoAnim == BOTH_A2__L__R ||
01779 ent1->client->ps.torsoAnim == BOTH_A3__L__R ||
01780 ent1->client->ps.torsoAnim == BOTH_A4__L__R ||
01781 ent1->client->ps.torsoAnim == BOTH_A5__L__R ||
01782 ent1->client->ps.torsoAnim == BOTH_A6__L__R ||
01783 ent1->client->ps.torsoAnim == BOTH_A7__L__R)
01784 {//ent1 is attacking l to r
01785 if ( ent2BlockingPlayer )
01786 {//player will block this anyway
01787 return WP_SabersCheckLock2( ent1, ent2, LOCK_L );
01788 }
01789 if ( ent2->client->ps.torsoAnim == BOTH_A1_TL_BR ||
01790 ent2->client->ps.torsoAnim == BOTH_A2_TL_BR ||
01791 ent2->client->ps.torsoAnim == BOTH_A3_TL_BR ||
01792 ent2->client->ps.torsoAnim == BOTH_A4_TL_BR ||
01793 ent2->client->ps.torsoAnim == BOTH_A5_TL_BR ||
01794 ent2->client->ps.torsoAnim == BOTH_A6_TL_BR ||
01795 ent2->client->ps.torsoAnim == BOTH_A7_TL_BR ||
01796 ent2->client->ps.torsoAnim == BOTH_P1_S1_TR ||
01797 ent2->client->ps.torsoAnim == BOTH_P1_S1_BL )
01798 {//ent2 is attacking or blocking on the r
01799 return WP_SabersCheckLock2( ent1, ent2, LOCK_L );
01800 }
01801 return qfalse;
01802 }
01803 if ( ent2->client->ps.torsoAnim == BOTH_A1__L__R ||
01804 ent2->client->ps.torsoAnim == BOTH_A2__L__R ||
01805 ent2->client->ps.torsoAnim == BOTH_A3__L__R ||
01806 ent2->client->ps.torsoAnim == BOTH_A4__L__R ||
01807 ent2->client->ps.torsoAnim == BOTH_A5__L__R ||
01808 ent2->client->ps.torsoAnim == BOTH_A6__L__R ||
01809 ent2->client->ps.torsoAnim == BOTH_A7__L__R)
01810 {//ent2 is attacking l to r
01811 if ( ent1BlockingPlayer )
01812 {//player will block this anyway
01813 return WP_SabersCheckLock2( ent2, ent1, LOCK_L );
01814 }
01815 if ( ent1->client->ps.torsoAnim == BOTH_A1_TL_BR ||
01816 ent1->client->ps.torsoAnim == BOTH_A2_TL_BR ||
01817 ent1->client->ps.torsoAnim == BOTH_A3_TL_BR ||
01818 ent1->client->ps.torsoAnim == BOTH_A4_TL_BR ||
01819 ent1->client->ps.torsoAnim == BOTH_A5_TL_BR ||
01820 ent1->client->ps.torsoAnim == BOTH_A6_TL_BR ||
01821 ent1->client->ps.torsoAnim == BOTH_A7_TL_BR ||
01822 ent1->client->ps.torsoAnim == BOTH_P1_S1_TR ||
01823 ent1->client->ps.torsoAnim == BOTH_P1_S1_BL )
01824 {//ent1 is attacking or blocking on the r
01825 return WP_SabersCheckLock2( ent2, ent1, LOCK_L );
01826 }
01827 return qfalse;
01828 }
01829 //R to L lock
01830 if ( ent1->client->ps.torsoAnim == BOTH_A1__R__L ||
01831 ent1->client->ps.torsoAnim == BOTH_A2__R__L ||
01832 ent1->client->ps.torsoAnim == BOTH_A3__R__L ||
01833 ent1->client->ps.torsoAnim == BOTH_A4__R__L ||
01834 ent1->client->ps.torsoAnim == BOTH_A5__R__L ||
01835 ent1->client->ps.torsoAnim == BOTH_A6__R__L ||
01836 ent1->client->ps.torsoAnim == BOTH_A7__R__L)
01837 {//ent1 is attacking r to l
01838 if ( ent2BlockingPlayer )
01839 {//player will block this anyway
01840 return WP_SabersCheckLock2( ent1, ent2, LOCK_R );
01841 }
01842 if ( ent2->client->ps.torsoAnim == BOTH_A1_TR_BL ||
01843 ent2->client->ps.torsoAnim == BOTH_A2_TR_BL ||
01844 ent2->client->ps.torsoAnim == BOTH_A3_TR_BL ||
01845 ent2->client->ps.torsoAnim == BOTH_A4_TR_BL ||
01846 ent2->client->ps.torsoAnim == BOTH_A5_TR_BL ||
01847 ent2->client->ps.torsoAnim == BOTH_A6_TR_BL ||
01848 ent2->client->ps.torsoAnim == BOTH_A7_TR_BL ||
01849 ent2->client->ps.torsoAnim == BOTH_P1_S1_TL ||
01850 ent2->client->ps.torsoAnim == BOTH_P1_S1_BR )
01851 {//ent2 is attacking or blocking on the l
01852 return WP_SabersCheckLock2( ent1, ent2, LOCK_R );
01853 }
01854 return qfalse;
01855 }
01856 if ( ent2->client->ps.torsoAnim == BOTH_A1__R__L ||
01857 ent2->client->ps.torsoAnim == BOTH_A2__R__L ||
01858 ent2->client->ps.torsoAnim == BOTH_A3__R__L ||
01859 ent2->client->ps.torsoAnim == BOTH_A4__R__L ||
01860 ent2->client->ps.torsoAnim == BOTH_A5__R__L ||
01861 ent2->client->ps.torsoAnim == BOTH_A6__R__L ||
01862 ent2->client->ps.torsoAnim == BOTH_A7__R__L)
01863 {//ent2 is attacking r to l
01864 if ( ent1BlockingPlayer )
01865 {//player will block this anyway
01866 return WP_SabersCheckLock2( ent2, ent1, LOCK_R );
01867 }
01868 if ( ent1->client->ps.torsoAnim == BOTH_A1_TR_BL ||
01869 ent1->client->ps.torsoAnim == BOTH_A2_TR_BL ||
01870 ent1->client->ps.torsoAnim == BOTH_A3_TR_BL ||
01871 ent1->client->ps.torsoAnim == BOTH_A4_TR_BL ||
01872 ent1->client->ps.torsoAnim == BOTH_A5_TR_BL ||
01873 ent1->client->ps.torsoAnim == BOTH_A6_TR_BL ||
01874 ent1->client->ps.torsoAnim == BOTH_A7_TR_BL ||
01875 ent1->client->ps.torsoAnim == BOTH_P1_S1_TL ||
01876 ent1->client->ps.torsoAnim == BOTH_P1_S1_BR )
01877 {//ent1 is attacking or blocking on the l
01878 return WP_SabersCheckLock2( ent2, ent1, LOCK_R );
01879 }
01880 return qfalse;
01881 }
01882 if ( !Q_irand( 0, 10 ) )
01883 {
01884 return WP_SabersCheckLock2( ent1, ent2, LOCK_RANDOM );
01885 }
01886 return qfalse;
01887 }
|
|
||||||||||||||||||||||||
|
Definition at line 2849 of file w_saber.c. References BG_SabersOff(), saberInfo_t::blade, gentity_s::client, bladeInfo_t::color, DotProduct, g_saberDebugBox, G_TestLine(), gentity_t, vmCvar_t::integer, bladeInfo_t::lengthMax, MAX_SABERS, bladeInfo_t::muzzleDir, bladeInfo_t::muzzleDirOld, bladeInfo_t::muzzlePoint, bladeInfo_t::muzzlePointOld, saberInfo_t::numBlades, gclient_s::ps, qboolean, qfalse, qtrue, gclient_s::saber, SABER_EXTRAPOLATE_DIST, SABER_NONE, tri_tri_intersect(), saberInfo_t::type, vec3_t, VectorCopy, VectorMA, VectorNormalize(), and VectorSubtract.
02850 {
02851 vec3_t saberBase1, saberTip1, saberBaseNext1, saberTipNext1;
02852 vec3_t saberBase2, saberTip2, saberBaseNext2, saberTipNext2;
02853 int ent2SaberNum = 0, ent2BladeNum = 0;
02854 vec3_t dir;
02855
02856 if ( !ent1 || !ent2 )
02857 {
02858 return qfalse;
02859 }
02860 if ( !ent1->client || !ent2->client )
02861 {
02862 return qfalse;
02863 }
02864 if ( BG_SabersOff( &ent1->client->ps )
02865 || BG_SabersOff( &ent2->client->ps ) )
02866 {
02867 return qfalse;
02868 }
02869
02870 for ( ent2SaberNum = 0; ent2SaberNum < MAX_SABERS; ent2SaberNum++ )
02871 {
02872 if ( ent2->client->saber[ent2SaberNum].type != SABER_NONE )
02873 {
02874 for ( ent2BladeNum = 0; ent2BladeNum < ent2->client->saber[ent2SaberNum].numBlades; ent2BladeNum++ )
02875 {
02876 if ( ent2->client->saber[ent2SaberNum].blade[ent2BladeNum].lengthMax > 0 )
02877 {//valid saber and this blade is on
02878 //if ( ent1->client->saberInFlight )
02879 {
02880 VectorCopy( ent1->client->saber[ent1SaberNum].blade[ent1BladeNum].muzzlePointOld, saberBase1 );
02881 VectorCopy( ent1->client->saber[ent1SaberNum].blade[ent1BladeNum].muzzlePoint, saberBaseNext1 );
02882
02883 VectorSubtract( ent1->client->saber[ent1SaberNum].blade[ent1BladeNum].muzzlePoint, ent1->client->saber[ent1SaberNum].blade[ent1BladeNum].muzzlePointOld, dir );
02884 VectorNormalize( dir );
02885 VectorMA( saberBaseNext1, SABER_EXTRAPOLATE_DIST, dir, saberBaseNext1 );
02886
02887 VectorMA( saberBase1, ent1->client->saber[ent1SaberNum].blade[ent1BladeNum].lengthMax+SABER_EXTRAPOLATE_DIST, ent1->client->saber[ent1SaberNum].blade[ent1BladeNum].muzzleDirOld, saberTip1 );
02888 VectorMA( saberBaseNext1, ent1->client->saber[ent1SaberNum].blade[ent1BladeNum].lengthMax+SABER_EXTRAPOLATE_DIST, ent1->client->saber[ent1SaberNum].blade[ent1BladeNum].muzzleDir, saberTipNext1 );
02889
02890 VectorSubtract( saberTipNext1, saberTip1, dir );
02891 VectorNormalize( dir );
02892 VectorMA( saberTipNext1, SABER_EXTRAPOLATE_DIST, dir, saberTipNext1 );
02893 }
02894 /*
02895 else
02896 {
02897 VectorCopy( ent1->client->saber[ent1SaberNum].blade[ent1BladeNum].muzzlePoint, saberBase1 );
02898 VectorCopy( ent1->client->saber[ent1SaberNum].blade[ent1BladeNum].muzzlePointNext, saberBaseNext1 );
02899 VectorMA( saberBase1, ent1->client->saber[ent1SaberNum].blade[ent1BladeNum].lengthMax, ent1->client->saber[ent1SaberNum].blade[ent1BladeNum].muzzleDir, saberTip1 );
02900 VectorMA( saberBaseNext1, ent1->client->saber[ent1SaberNum].blade[ent1BladeNum].lengthMax, ent1->client->saber[ent1SaberNum].blade[ent1BladeNum].muzzleDirNext, saberTipNext1 );
02901 }
02902 */
02903
02904 //if ( ent2->client->saberInFlight )
02905 {
02906 VectorCopy( ent2->client->saber[ent2SaberNum].blade[ent2BladeNum].muzzlePointOld, saberBase2 );
02907 VectorCopy( ent2->client->saber[ent2SaberNum].blade[ent2BladeNum].muzzlePoint, saberBaseNext2 );
02908
02909 VectorSubtract( ent2->client->saber[ent2SaberNum].blade[ent2BladeNum].muzzlePoint, ent2->client->saber[ent2SaberNum].blade[ent2BladeNum].muzzlePointOld, dir );
02910 VectorNormalize( dir );
02911 VectorMA( saberBaseNext2, SABER_EXTRAPOLATE_DIST, dir, saberBaseNext2 );
02912
02913 VectorMA( saberBase2, ent2->client->saber[ent2SaberNum].blade[ent2BladeNum].lengthMax+SABER_EXTRAPOLATE_DIST, ent2->client->saber[ent2SaberNum].blade[ent2BladeNum].muzzleDirOld, saberTip2 );
02914 VectorMA( saberBaseNext2, ent2->client->saber[ent2SaberNum].blade[ent2BladeNum].lengthMax+SABER_EXTRAPOLATE_DIST, ent2->client->saber[ent2SaberNum].blade[ent2BladeNum].muzzleDir, saberTipNext2 );
02915
02916 VectorSubtract( saberTipNext2, saberTip2, dir );
02917 VectorNormalize( dir );
02918 VectorMA( saberTipNext2, SABER_EXTRAPOLATE_DIST, dir, saberTipNext2 );
02919 }
02920 /*
02921 else
02922 {
02923 VectorCopy( ent2->client->saber[ent2SaberNum].blade[ent2BladeNum].muzzlePoint, saberBase2 );
02924 VectorCopy( ent2->client->saber[ent2SaberNum].blade[ent2BladeNum].muzzlePointNext, saberBaseNext2 );
02925 VectorMA( saberBase2, ent2->client->saber[ent2SaberNum].blade[ent2BladeNum].lengthMax, ent2->client->saber[ent2SaberNum].blade[ent2BladeNum].muzzleDir, saberTip2 );
02926 VectorMA( saberBaseNext2, ent2->client->saber[ent2SaberNum].blade[ent2BladeNum].lengthMax, ent2->client->saber[ent2SaberNum].blade[ent2BladeNum].muzzleDirNext, saberTipNext2 );
02927 }
02928 */
02929 if ( checkDir )
02930 {//check the direction of the two swings to make sure the sabers are swinging towards each other
02931 vec3_t saberDir1, saberDir2;
02932 float dot = 0.0f;
02933
02934 VectorSubtract( saberTipNext1, saberTip1, saberDir1 );
02935 VectorSubtract( saberTipNext2, saberTip2, saberDir2 );
02936 VectorNormalize( saberDir1 );
02937 VectorNormalize( saberDir2 );
02938 if ( DotProduct( saberDir1, saberDir2 ) > 0.6f )
02939 {//sabers moving in same dir, probably didn't actually hit
02940 continue;
02941 }
02942 //now check orientation of sabers, make sure they're not parallel or close to it
02943 dot = DotProduct( ent1->client->saber[ent1SaberNum].blade[ent1BladeNum].muzzleDir, ent2->client->saber[ent2SaberNum].blade[ent2BladeNum].muzzleDir );
02944 if ( dot > 0.9f || dot < -0.9f )
02945 {//too parallel to really block effectively?
02946 continue;
02947 }
02948 }
02949
02950 #ifdef DEBUG_SABER_BOX
02951 if ( g_saberDebugBox.integer == 2 || g_saberDebugBox.integer == 4 )
02952 {
02953 G_TestLine(saberBase1, saberTip1, ent1->client->saber[ent1SaberNum].blade[ent1BladeNum].color, 500);
02954 G_TestLine(saberTip1, saberTipNext1, ent1->client->saber[ent1SaberNum].blade[ent1BladeNum].color, 500);
02955 G_TestLine(saberTipNext1, saberBase1, ent1->client->saber[ent1SaberNum].blade[ent1BladeNum].color, 500);
02956
02957 G_TestLine(saberBase2, saberTip2, ent2->client->saber[ent2SaberNum].blade[ent2BladeNum].color, 500);
02958 G_TestLine(saberTip2, saberTipNext2, ent2->client->saber[ent2SaberNum].blade[ent2BladeNum].color, 500);
02959 G_TestLine(saberTipNext2, saberBase2, ent2->client->saber[ent2SaberNum].blade[ent2BladeNum].color, 500);
02960 }
02961 #endif
02962 if ( tri_tri_intersect( saberBase1, saberTip1, saberBaseNext1, saberBase2, saberTip2, saberBaseNext2 ) )
02963 {
02964 return qtrue;
02965 }
02966 if ( tri_tri_intersect( saberBase1, saberTip1, saberBaseNext1, saberBase2, saberTip2, saberTipNext2 ) )
02967 {
02968 return qtrue;
02969 }
02970 if ( tri_tri_intersect( saberBase1, saberTip1, saberTipNext1, saberBase2, saberTip2, saberBaseNext2 ) )
02971 {
02972 return qtrue;
02973 }
02974 if ( tri_tri_intersect( saberBase1, saberTip1, saberTipNext1, saberBase2, saberTip2, saberTipNext2 ) )
02975 {
02976 return qtrue;
02977 }
02978 }
02979 }
02980 }
02981 }
02982 return qfalse;
02983 }
|
|
||||||||||||
|
Definition at line 5490 of file w_saber.c. References entityShared_t::absmax, trace_t::allsolid, AngleVectors(), BG_SaberInAttack(), BG_SaberInSpecialAttack(), BG_SaberInTransitionAny(), BG_SabersOff(), BUTTON_ATTACK, usercmd_s::buttons, CLASS_BOBAFETT, CLASS_VEHICLE, gentity_s::client, gentity_s::clipmask, gentity_s::count, entityShared_t::currentAngles, entityShared_t::currentOrigin, DotProduct, EF2_FLYING, EF2_HELD_BY_MONSTER, EF_MISSILE_STICK, entityState_s::eFlags, playerState_s::eFlags2, gentity_s::enemy, trace_t::entityNum, ENTITYNUM_NONE, ENTITYNUM_WORLD, ET_MISSILE, ET_NPC, ET_PLAYER, entityState_s::eType, EVASION_NONE, renderInfo_s::eyePoint, playerState_s::fd, FL_BOUNCE_HALF, gentity_s::flags, forcedata_s::forceJumpCharge, forcedata_s::forcePowerDebounce, forcedata_s::forcePowersActive, ForceThrow(), FP_DRAIN, FP_GRIP, FP_LIGHTNING, FP_PUSH, FP_SABER_DEFENSE, trace_t::fraction, G_ClearLOS4(), g_entities, G_SetEnemy(), gentity_t, playerState_s::groundEntityNum, playerState_s::hasLookTarget, gentity_s::health, InFOV3(), gentity_s::inuse, Jedi_Ambush(), Jedi_SaberBlockGo(), Jedi_WaitingAmbush(), gNPC_t::last_ucmd, level, gentity_s::localAnimIndex, playerState_s::lookTarget, renderInfo_s::lookTarget, MASK_PLAYERSOLID, MAX_GENTITIES, entityShared_t::maxs, gentity_s::methodOfDeath, entityShared_t::mins, MOD_ROCKET_HOMING, gentity_s::nextthink, gentity_s::NPC, entityState_s::NPC_class, gclient_s::NPC_class, NULL, entityState_s::number, OnSameTeam(), playerState_s::origin, entityShared_t::ownerNum, gclient_s::playerTeam, playerState_s::pm_flags, PM_InKnockDown(), PMF_FOLLOW, entityState_s::pos, gclient_s::ps, Q_irand(), qboolean, qfalse, qtrue, gentity_s::r, gclient_s::renderInfo, gentity_s::s, gclient_s::saber, SABER_REFLECT_MISSILE_CONE, playerState_s::saberEntityNum, saberInfo_t::saberFlags, playerState_s::saberInFlight, playerState_s::saberMove, gclient_s::sess, clientSession_t::sessionTeam, SFL_NOT_ACTIVE_BLOCKING, gentity_s::splashDamage, gentity_s::splashRadius, gNPC_t::standTime, trace_t::startsolid, TEAM_SPECTATOR, level_locals_t::time, TIMER_Set(), playerState_s::torsoAnim, TR_GRAVITY, TR_INTERPOLATE, TR_STATIONARY, trap_EntitiesInBox(), trap_Trace(), trajectory_t::trBase, trajectory_t::trDelta, trajectory_t::trTime, trajectory_t::trType, ucmd, usercmd_t, vec3_t, VectorCopy, VectorMA, VectorNormalize(), VectorNormalize2(), VectorScale, VectorSubtract, playerState_s::viewangles, playerState_s::viewheight, entityState_s::weapon, playerState_s::weapon, playerState_s::weaponTime, WP_ActivateSaber(), WP_ForcePowerUsable(), WP_SABER, WP_SaberBlockNonRandom(), and WP_THERMAL. Referenced by G_RunFrame().
05491 {
05492 float dist;
05493 gentity_t *ent, *incoming = NULL;
05494 int entityList[MAX_GENTITIES];
05495 int numListedEntities;
05496 vec3_t mins, maxs;
05497 int i, e;
05498 float closestDist, radius = 256;
05499 vec3_t forward, dir, missile_dir, fwdangles = {0};
05500 trace_t trace;
05501 vec3_t traceTo, entDir;
05502 float dot1, dot2;
05503 float lookTDist = -1;
05504 gentity_t *lookT = NULL;
05505 qboolean doFullRoutine = qtrue;
05506
05507 //keep this updated even if we don't get below
05508 if ( !(self->client->ps.eFlags2&EF2_HELD_BY_MONSTER) )
05509 {//lookTarget is set by and to the monster that's holding you, no other operations can change that
05510 self->client->ps.hasLookTarget = qfalse;
05511 }
05512
05513 if ( self->client->ps.weapon != WP_SABER && self->client->NPC_class != CLASS_BOBAFETT )
05514 {
05515 doFullRoutine = qfalse;
05516 }
05517 else if ( self->client->ps.saberInFlight )
05518 {
05519 doFullRoutine = qfalse;
05520 }
05521 else if ( self->client->ps.fd.forcePowersActive&(1<<FP_LIGHTNING) )
05522 {//can't block while zapping
05523 doFullRoutine = qfalse;
05524 }
05525 else if ( self->client->ps.fd.forcePowersActive&(1<<FP_DRAIN) )
05526 {//can't block while draining
05527 doFullRoutine = qfalse;
05528 }
05529 else if ( self->client->ps.fd.forcePowersActive&(1<<FP_PUSH) )
05530 {//can't block while shoving
05531 doFullRoutine = qfalse;
05532 }
05533 else if ( self->client->ps.fd.forcePowersActive&(1<<FP_GRIP) )
05534 {//can't block while gripping (FIXME: or should it break the grip? Pain should break the grip, I think...)
05535 doFullRoutine = qfalse;
05536 }
05537
05538 if (self->client->ps.weaponTime > 0)
05539 { //don't autoblock while busy with stuff
05540 return;
05541 }
05542
05543 if ( (self->client->saber[0].saberFlags&SFL_NOT_ACTIVE_BLOCKING) )
05544 {//can't actively block with this saber type
05545 return;
05546 }
05547
05548 if ( self->health <= 0 )
05549 {//dead don't try to block (NOTE: actual deflection happens in missile code)
05550 return;
05551 }
05552 if ( PM_InKnockDown( &self->client->ps ) )
05553 {//can't block when knocked down
05554 return;
05555 }
05556
05557 if ( BG_SabersOff( &self->client->ps ) && self->client->NPC_class != CLASS_BOBAFETT )
05558 {
05559 if ( self->s.eType != ET_NPC )
05560 {//player doesn't auto-activate
05561 doFullRoutine = qfalse;
05562 }
05563 }
05564
05565 if ( self->s.eType == ET_PLAYER )
05566 {//don't do this if already attacking!
05567 if ( ucmd->buttons & BUTTON_ATTACK
05568 || BG_SaberInAttack( self->client->ps.saberMove )
05569 || BG_SaberInSpecialAttack( self->client->ps.torsoAnim )
05570 || BG_SaberInTransitionAny( self->client->ps.saberMove ))
05571 {
05572 doFullRoutine = qfalse;
05573 }
05574 }
05575
05576 if ( self->client->ps.fd.forcePowerDebounce[FP_SABER_DEFENSE] > level.time )
05577 {//can't block while gripping (FIXME: or should it break the grip? Pain should break the grip, I think...)
05578 doFullRoutine = qfalse;
05579 }
05580
05581 fwdangles[1] = self->client->ps.viewangles[1];
05582 AngleVectors( fwdangles, forward, NULL, NULL );
05583
05584 for ( i = 0 ; i < 3 ; i++ )
05585 {
05586 mins[i] = self->r.currentOrigin[i] - radius;
05587 maxs[i] = self->r.currentOrigin[i] + radius;
05588 }
05589
05590 numListedEntities = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );
05591
05592 closestDist = radius;
05593
05594 for ( e = 0 ; e < numListedEntities ; e++ )
05595 {
05596 ent = &g_entities[entityList[ e ]];
05597
05598 if (ent == self)
05599 continue;
05600
05601 //as long as we're here I'm going to get a looktarget too, I guess. -rww
05602 if (self->s.eType == ET_PLAYER &&
05603 ent->client &&
05604 (ent->s.eType == ET_NPC || ent->s.eType == ET_PLAYER) &&
05605 !OnSameTeam(ent, self) &&
05606 ent->client->sess.sessionTeam != TEAM_SPECTATOR &&
05607 !(ent->client->ps.pm_flags & PMF_FOLLOW) &&
05608 (ent->s.eType != ET_NPC || ent->s.NPC_class != CLASS_VEHICLE) && //don't look at vehicle NPCs
05609 ent->health > 0)
05610 { //seems like a valid enemy to look at.
05611 vec3_t vecSub;
05612 float vecLen;
05613
05614 VectorSubtract(self->client->ps.origin, ent->client->ps.origin, vecSub);
05615 vecLen = VectorLength(vecSub);
05616
05617 if (lookTDist == -1 || vecLen < lookTDist)
05618 {
05619 trace_t tr;
05620 vec3_t myEyes;
05621
05622 VectorCopy(self->client->ps.origin, myEyes);
05623 myEyes[2] += self->client->ps.viewheight;
05624
05625 trap_Trace(&tr, myEyes, NULL, NULL, ent->client->ps.origin, self->s.number, MASK_PLAYERSOLID);
05626
05627 if (tr.fraction == 1.0f || tr.entityNum == ent->s.number)
05628 { //we have a clear line of sight to him, so it's all good.
05629 lookT = ent;
05630 lookTDist = vecLen;
05631 }
05632 }
05633 }
05634
05635 if (!doFullRoutine)
05636 { //don't care about the rest then
05637 continue;
05638 }
05639
05640 if (ent->r.ownerNum == self->s.number)
05641 continue;
05642 if ( !(ent->inuse) )
05643 continue;
05644 if ( ent->s.eType != ET_MISSILE && !(ent->s.eFlags&EF_MISSILE_STICK) )
05645 {//not a normal projectile
05646 gentity_t *pOwner;
05647
05648 if (ent->r.ownerNum < 0 || ent->r.ownerNum >= ENTITYNUM_WORLD)
05649 { //not going to be a client then.
05650 continue;
05651 }
05652
05653 pOwner = &g_entities[ent->r.ownerNum];
05654
05655 if (!pOwner->inuse || !pOwner->client)
05656 {
05657 continue; //not valid cl owner
05658 }
05659
05660 if (!pOwner->client->ps.saberEntityNum ||
05661 !pOwner->client->ps.saberInFlight ||
05662 pOwner->client->ps.saberEntityNum != ent->s.number)
05663 { //the saber is knocked away and/or not flying actively, or this ent is not the cl's saber ent at all
05664 continue;
05665 }
05666
05667 //If we get here then it's ok to be treated as a thrown saber, I guess.
05668 }
05669 else
05670 {
05671 if ( ent->s.pos.trType == TR_STATIONARY && self->s.eType == ET_PLAYER )
05672 {//nothing you can do with a stationary missile if you're the player
05673 continue;
05674 }
05675 }
05676
05677 //see if they're in front of me
05678 VectorSubtract( ent->r.currentOrigin, self->r.currentOrigin, dir );
05679 dist = VectorNormalize( dir );
05680 //FIXME: handle detpacks, proximity mines and tripmines
05681 if ( ent->s.weapon == WP_THERMAL )
05682 {//thermal detonator!
05683 if ( self->NPC && dist < ent->splashRadius )
05684 {
05685 if ( dist < ent->splashRadius &&
05686 ent->nextthink < level.time + 600 &&
05687 ent->count &&
05688 self->client->ps.groundEntityNum != ENTITYNUM_NONE &&
05689 (ent->s.pos.trType == TR_STATIONARY||
05690 ent->s.pos.trType == TR_INTERPOLATE||
05691 (dot1 = DotProduct( dir, forward )) < SABER_REFLECT_MISSILE_CONE||
05692 !WP_ForcePowerUsable( self, FP_PUSH )) )
05693 {//TD is close enough to hurt me, I'm on the ground and the thing is at rest or behind me and about to blow up, or I don't have force-push so force-jump!
05694 //FIXME: sometimes this might make me just jump into it...?
05695 self->client->ps.fd.forceJumpCharge = 480;
05696 }
05697 else if ( self->client->NPC_class != CLASS_BOBAFETT )
05698 {//FIXME: check forcePushRadius[NPC->client->ps.forcePowerLevel[FP_PUSH]]
05699 ForceThrow( self, qfalse );
05700 }
05701 }
05702 continue;
05703 }
05704 else if ( ent->splashDamage && ent->splashRadius )
05705 {//exploding missile
05706 //FIXME: handle tripmines and detpacks somehow...
05707 // maybe do a force-gesture that makes them explode?
05708 // But what if we're within it's splashradius?
05709 if ( self->s.eType == ET_PLAYER )
05710 {//players don't auto-handle these at all
05711 continue;
05712 }
05713 else
05714 {
05715 //if ( ent->s.pos.trType == TR_STATIONARY && (ent->s.eFlags&EF_MISSILE_STICK)
05716 // && self->client->NPC_class != CLASS_BOBAFETT )
05717 if (0) //Maybe handle this later?
05718 {//a placed explosive like a tripmine or detpack
05719 if ( InFOV3( ent->r.currentOrigin, self->client->renderInfo.eyePoint, self->client->ps.viewangles, 90, 90 ) )
05720 {//in front of me
05721 if ( G_ClearLOS4( self, ent ) )
05722 {//can see it
05723 vec3_t throwDir;
05724 //make the gesture
05725 ForceThrow( self, qfalse );
05726 //take it off the wall and toss it
05727 ent->s.pos.trType = TR_GRAVITY;
05728 ent->s.eType = ET_MISSILE;
05729 ent->s.eFlags &= ~EF_MISSILE_STICK;
05730 ent->flags |= FL_BOUNCE_HALF;
05731 AngleVectors( ent->r.currentAngles, throwDir, NULL, NULL );
05732 VectorMA( ent->r.currentOrigin, ent->r.maxs[0]+4, throwDir, ent->r.currentOrigin );
05733 VectorCopy( ent->r.currentOrigin, ent->s.pos.trBase );
05734 VectorScale( throwDir, 300, ent->s.pos.trDelta );
05735 ent->s.pos.trDelta[2] += 150;
05736 VectorMA( ent->s.pos.trDelta, 800, dir, ent->s.pos.trDelta );
05737 ent->s.pos.trTime = level.time; // move a bit on the very first frame
05738 VectorCopy( ent->r.currentOrigin, ent->s.pos.trBase );
05739 ent->r.ownerNum = self->s.number;
05740 // make it explode, but with less damage
05741 ent->splashDamage /= 3;
05742 ent->splashRadius /= 3;
05743 //ent->think = WP_Explode;
05744 ent->nextthink = level.time + Q_irand( 500, 3000 );
05745 }
05746 }
05747 }
05748 else if ( dist < ent->splashRadius &&
05749 self->client->ps.groundEntityNum != ENTITYNUM_NONE &&
05750 (DotProduct( dir, forward ) < SABER_REFLECT_MISSILE_CONE||
05751 !WP_ForcePowerUsable( self, FP_PUSH )) )
05752 {//NPCs try to evade it
05753 self->client->ps.fd.forceJumpCharge = 480;
05754 }
05755 else if ( self->client->NPC_class != CLASS_BOBAFETT )
05756 {//else, try to force-throw it away
05757 //FIXME: check forcePushRadius[NPC->client->ps.forcePowerLevel[FP_PUSH]]
05758 ForceThrow( self, qfalse );
05759 }
05760 }
05761 //otherwise, can't block it, so we're screwed
05762 continue;
05763 }
05764
05765 if ( ent->s.weapon != WP_SABER )
05766 {//only block shots coming from behind
05767 if ( (dot1 = DotProduct( dir, forward )) < SABER_REFLECT_MISSILE_CONE )
05768 continue;
05769 }
05770 else if ( self->s.eType == ET_PLAYER )
05771 {//player never auto-blocks thrown sabers
05772 continue;
05773 }//NPCs always try to block sabers coming from behind!
05774
05775 //see if they're heading towards me
05776 VectorCopy( ent->s.pos.trDelta, missile_dir );
05777 VectorNormalize( missile_dir );
05778 if ( (dot2 = DotProduct( dir, missile_dir )) > 0 )
05779 continue;
05780
05781 //FIXME: must have a clear trace to me, too...
05782 if ( dist < closestDist )
05783 {
05784 VectorCopy( self->r.currentOrigin, traceTo );
05785 traceTo[2] = self->r.absmax[2] - 4;
05786 trap_Trace( &trace, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, traceTo, ent->s.number, ent->clipmask );
05787 if ( trace.allsolid || trace.startsolid || (trace.fraction < 1.0f && trace.entityNum != self->s.number && trace.entityNum != self->client->ps.saberEntityNum) )
05788 {//okay, try one more check
05789 VectorNormalize2( ent->s.pos.trDelta, entDir );
05790 VectorMA( ent->r.currentOrigin, radius, entDir, traceTo );
05791 trap_Trace( &trace, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, traceTo, ent->s.number, ent->clipmask );
05792 if ( trace.allsolid || trace.startsolid || (trace.fraction < 1.0f && trace.entityNum != self->s.number && trace.entityNum != self->client->ps.saberEntityNum) )
05793 {//can't hit me, ignore it
05794 continue;
05795 }
05796 }
05797 if ( self->s.eType == ET_NPC )
05798 {//An NPC
05799 if ( self->NPC && !self->enemy && ent->r.ownerNum != ENTITYNUM_NONE )
05800 {
05801 gentity_t *owner = &g_entities[ent->r.ownerNum];
05802 if ( owner->health >= 0 && (!owner->client || owner->client->playerTeam != self->client->playerTeam) )
05803 {
05804 G_SetEnemy( self, owner );
05805 }
05806 }
05807 }
05808 //FIXME: if NPC, predict the intersection between my current velocity/path and the missile's, see if it intersects my bounding box (+/-saberLength?), don't try to deflect unless it does?
05809 closestDist = dist;
05810 incoming = ent;
05811 }
05812 }
05813
05814 if (self->s.eType == ET_NPC && self->localAnimIndex <= 1)
05815 { //humanoid NPCs don't set angles based on server angles for looking, unlike other NPCs
05816 if (self->client && self->client->renderInfo.lookTarget < ENTITYNUM_WORLD)
05817 {
05818 lookT = &g_entities[self->client->renderInfo.lookTarget];
05819 }
05820 }
05821
05822 if (lookT)
05823 { //we got a looktarget at some point so we'll assign it then.
05824 if ( !(self->client->ps.eFlags2&EF2_HELD_BY_MONSTER) )
05825 {//lookTarget is set by and to the monster that's holding you, no other operations can change that
05826 self->client->ps.hasLookTarget = qtrue;
05827 self->client->ps.lookTarget = lookT->s.number;
05828 }
05829 }
05830
05831 if (!doFullRoutine)
05832 { //then we're done now
05833 return;
05834 }
05835
05836 if ( incoming )
05837 {
05838 if ( self->NPC /*&& !G_ControlledByPlayer( self )*/ )
05839 {
05840 if ( Jedi_WaitingAmbush( self ) )
05841 {
05842 Jedi_Ambush( self );
05843 }
05844 if ( self->client->NPC_class == CLASS_BOBAFETT
05845 && (self->client->ps.eFlags2&EF2_FLYING)//moveType == MT_FLYSWIM
05846 && incoming->methodOfDeath != MOD_ROCKET_HOMING )
05847 {//a hovering Boba Fett, not a tracking rocket
05848 if ( !Q_irand( 0, 1 ) )
05849 {//strafe
05850 self->NPC->standTime = 0;
05851 self->client->ps.fd.forcePowerDebounce[FP_SABER_DEFENSE] = level.time + Q_irand( 1000, 2000 );
05852 }
05853 if ( !Q_irand( 0, 1 ) )
05854 {//go up/down
05855 TIMER_Set( self, "heightChange", Q_irand( 1000, 3000 ) );
05856 self->client->ps.fd.forcePowerDebounce[FP_SABER_DEFENSE] = level.time + Q_irand( 1000, 2000 );
05857 }
05858 }
05859 else if ( Jedi_SaberBlockGo( self, &self->NPC->last_ucmd, NULL, NULL, incoming, 0.0f ) != EVASION_NONE )
05860 {//make sure to turn on your saber if it's not on
05861 if ( self->client->NPC_class != CLASS_BOBAFETT )
05862 {
05863 //self->client->ps.SaberActivate();
05864 WP_ActivateSaber(self);
05865 }
05866 }
05867 }
05868 else//player
05869 {
05870 gentity_t *owner = &g_entities[incoming->r.ownerNum];
05871
05872 WP_SaberBlockNonRandom( self, incoming->r.currentOrigin, qtrue );
05873 if ( owner && owner->client && (!self->enemy || self->enemy->s.weapon != WP_SABER) )//keep enemy jedi over shooters
05874 {
05875 self->enemy = owner;
05876 //NPC_SetLookTarget( self, owner->s.number, level.time+1000 );
05877 //player looktargetting done differently
05878 }
05879 }
05880 }
05881 }
|
|
|
Definition at line 2812 of file w_saber.c. References SABER_BLUE, saber_colors_t, SABER_GREEN, SABER_ORANGE, SABER_PURPLE, SABER_RED, and SABER_YELLOW.
02813 {
02814 switch( (int)(saberColor) )
02815 {
02816 case SABER_RED:
02817 return 0x000000ff;
02818 break;
02819 case SABER_ORANGE:
02820 return 0x000088ff;
02821 break;
02822 case SABER_YELLOW:
02823 return 0x0000ffff;
02824 break;
02825 case SABER_GREEN:
02826 return 0x0000ff00;
02827 break;
02828 case SABER_BLUE:
02829 return 0x00ff0000;
02830 break;
02831 case SABER_PURPLE:
02832 return 0x00ff00ff;
02833 break;
02834 default:
02835 return 0x00ffffff;//white
02836 break;
02837 }
02838 }
|
|
|
|
|
|
|
Definition at line 13 of file w_saber.c. Referenced by WP_SaberPositionUpdate(). |
|
|
Definition at line 14 of file w_saber.c. Referenced by WP_SabersCheckLock(). |
|
|
Definition at line 12 of file w_saber.c. Referenced by CorpsePhysics(), and Jedi_ReCalcParryTime(). |
|
|
Definition at line 16 of file w_saber.c. Referenced by WP_SaberApplyDamage(). |
|
|
Definition at line 18 of file w_saber.c. Referenced by WP_SaberInitBladeData(), and WP_SaberPositionUpdate(). |