#include "b_local.h"#include "g_nav.h"Go to the source code of this file.
Defines | |
| #define | MIN_DISTANCE 48 |
| #define | MIN_DISTANCE_SQR ( MIN_DISTANCE * MIN_DISTANCE ) |
| #define | MAX_DISTANCE 1024 |
| #define | MAX_DISTANCE_SQR ( MAX_DISTANCE * MAX_DISTANCE ) |
| #define | LSTATE_CLEAR 0 |
| #define | LSTATE_WAITING 1 |
Functions | |
| void | Wampa_SetBolts (gentity_t *self) |
| void | NPC_Wampa_Precache (void) |
| void | Wampa_Idle (void) |
| qboolean | Wampa_CheckRoar (gentity_t *self) |
| void | Wampa_Patrol (void) |
| void | Wampa_Move (qboolean visible) |
| void | G_Knockdown (gentity_t *victim) |
| void | G_Dismember (gentity_t *ent, gentity_t *enemy, vec3_t point, int limbType, float limbRollBase, float limbPitchBase, int deathAnim, qboolean postDeath) |
| int | NPC_GetEntsNearBolt (int *radiusEnts, float radius, int boltIndex, vec3_t boltOrg) |
| void | Wampa_Slash (int boltIndex, qboolean backhand) |
| void | Wampa_Attack (float distance, qboolean doCharge) |
| void | Wampa_Combat (void) |
| void | NPC_Wampa_Pain (gentity_t *self, gentity_t *attacker, int damage) |
| void | NPC_BSWampa_Default (void) |
Variables | |
| float | enemyDist = 0 |
|
|
Definition at line 11 of file NPC_AI_Wampa.c. |
|
|
Definition at line 12 of file NPC_AI_Wampa.c. |
|
|
Definition at line 8 of file NPC_AI_Wampa.c. |
|
|
Definition at line 9 of file NPC_AI_Wampa.c. |
|
|
Definition at line 5 of file NPC_AI_Wampa.c. |
|
|
Definition at line 6 of file NPC_AI_Wampa.c. |
|
||||||||||||||||||||||||||||||||||||
|
Definition at line 3311 of file g_combat.c. References entityState_s::apos, BG_GetRootSurfNameWithVariant(), BG_InDeathAnim(), gentity_s::classname, gentity_s::client, gentity_s::clipmask, Com_sprintf(), entityShared_t::contents, CONTENTS_TRIGGER, entityShared_t::currentAngles, entityShared_t::currentOrigin, entityState_s::customRGBA, gentity_s::epGravFactor, gentity_s::epVelocity, ET_GENERAL, ET_NPC, entityState_s::eType, FRAMETIME, G2_MODEL_PART, G2_MODELPART_HEAD, G2_MODELPART_LARM, G2_MODELPART_LLEG, G2_MODELPART_RARM, G2_MODELPART_RHAND, G2_MODELPART_RLEG, G2_MODELPART_WAIST, entityState_s::g2radius, G_SetOrigin(), G_Spawn(), gentity_t, gentity_s::ghoul2, gclient_s::lastSaberBase_Always, gclient_s::lastSaberStorageTime, level, LimbThink(), LimbTouch(), MASK_SOLID, MAX_QPATH, entityShared_t::maxs, entityShared_t::mins, entityState_s::modelGhoul2, entityState_s::modelindex, gentity_s::nextthink, entityState_s::number, gclient_s::olderIsValid, gclient_s::olderSaberBase, entityState_s::otherEntityNum2, gentity_s::physicsObject, entityState_s::pos, gclient_s::ps, Q_irand(), Q_strncpyz(), qtrue, gentity_s::r, gentity_s::s, gentity_s::speed, SVF_USE_CURRENT_ORIGIN, entityShared_t::svFlags, gentity_s::think, level_locals_t::time, playerState_s::torsoAnim, playerState_s::torsoTimer, gentity_s::touch, trap_G2API_GetSurfaceRenderStatus(), trap_G2API_SetSurfaceOnOff(), trap_LinkEntity(), trajectory_t::trBase, trajectory_t::trDelta, vec3_t, VectorAdd, VectorClear, VectorCopy, VectorMA, VectorNormalize(), VectorScale, VectorSet, VectorSubtract, playerState_s::velocity, playerState_s::viewangles, playerState_s::weapon, entityState_s::weapon, and WP_SABER. Referenced by DismembermentByNum(), DismembermentTest(), G_CheckForDismemberment(), Rancor_Attack(), Rancor_Bite(), and Wampa_Slash().
03312 {
03313 vec3_t newPoint, dir, vel;
03314 gentity_t *limb;
03315 char limbName[MAX_QPATH];
03316 char stubName[MAX_QPATH];
03317 char stubCapName[MAX_QPATH];
03318
03319 if (limbType == G2_MODELPART_HEAD)
03320 {
03321 Q_strncpyz( limbName , "head", sizeof( limbName ) );
03322 Q_strncpyz( stubCapName, "torso_cap_head", sizeof( stubCapName ) );
03323 }
03324 else if (limbType == G2_MODELPART_WAIST)
03325 {
03326 Q_strncpyz( limbName, "torso", sizeof( limbName ) );
03327 Q_strncpyz( stubCapName, "hips_cap_torso", sizeof( stubCapName ) );
03328 }
03329 else if (limbType == G2_MODELPART_LARM)
03330 {
03331 BG_GetRootSurfNameWithVariant( ent->ghoul2, "l_arm", limbName, sizeof(limbName) );
03332 BG_GetRootSurfNameWithVariant( ent->ghoul2, "torso", stubName, sizeof(stubName) );
03333 Com_sprintf( stubCapName, sizeof( stubCapName), "%s_cap_l_arm", stubName );
03334 }
03335 else if (limbType == G2_MODELPART_RARM)
03336 {
03337 BG_GetRootSurfNameWithVariant( ent->ghoul2, "r_arm", limbName, sizeof(limbName) );
03338 BG_GetRootSurfNameWithVariant( ent->ghoul2, "torso", stubName, sizeof(stubName) );
03339 Com_sprintf( stubCapName, sizeof( stubCapName), "%s_cap_r_arm", stubName );
03340 }
03341 else if (limbType == G2_MODELPART_RHAND)
03342 {
03343 BG_GetRootSurfNameWithVariant( ent->ghoul2, "r_hand", limbName, sizeof(limbName) );
03344 BG_GetRootSurfNameWithVariant( ent->ghoul2, "r_arm", stubName, sizeof(stubName) );
03345 Com_sprintf( stubCapName, sizeof( stubCapName), "%s_cap_r_hand", stubName );
03346 }
03347 else if (limbType == G2_MODELPART_LLEG)
03348 {
03349 BG_GetRootSurfNameWithVariant( ent->ghoul2, "l_leg", limbName, sizeof(limbName) );
03350 BG_GetRootSurfNameWithVariant( ent->ghoul2, "hips", stubName, sizeof(stubName) );
03351 Com_sprintf( stubCapName, sizeof( stubCapName), "%s_cap_l_leg", stubName );
03352 }
03353 else if (limbType == G2_MODELPART_RLEG)
03354 {
03355 BG_GetRootSurfNameWithVariant( ent->ghoul2, "r_leg", limbName, sizeof(limbName) );
03356 BG_GetRootSurfNameWithVariant( ent->ghoul2, "hips", stubName, sizeof(stubName) );
03357 Com_sprintf( stubCapName, sizeof( stubCapName), "%s_cap_r_leg", stubName );
03358 }
03359 else
03360 {//umm... just default to the right leg, I guess (same as on client)
03361 BG_GetRootSurfNameWithVariant( ent->ghoul2, "r_leg", limbName, sizeof(limbName) );
03362 BG_GetRootSurfNameWithVariant( ent->ghoul2, "hips", stubName, sizeof(stubName) );
03363 Com_sprintf( stubCapName, sizeof( stubCapName), "%s_cap_r_leg", stubName );
03364 }
03365
03366 if (ent->ghoul2 && limbName && trap_G2API_GetSurfaceRenderStatus(ent->ghoul2, 0, limbName))
03367 { //is it already off? If so there's no reason to be doing it again, so get out of here.
03368 return;
03369 }
03370
03371 VectorCopy( point, newPoint );
03372 limb = G_Spawn();
03373 limb->classname = "playerlimb";
03374
03375 /*
03376 if (limbType == G2_MODELPART_WAIST)
03377 { //slight hack
03378 newPoint[2] += 1;
03379 }
03380 */
03381
03382 G_SetOrigin( limb, newPoint );
03383 VectorCopy( newPoint, limb->s.pos.trBase );
03384 limb->think = LimbThink;
03385 limb->touch = LimbTouch;
03386 limb->speed = level.time + Q_irand(8000, 16000);
03387 limb->nextthink = level.time + FRAMETIME;
03388
03389 limb->r.svFlags = SVF_USE_CURRENT_ORIGIN;
03390 limb->clipmask = MASK_SOLID;
03391 limb->r.contents = CONTENTS_TRIGGER;
03392 limb->physicsObject = qtrue;
03393 VectorSet( limb->r.mins, -6.0f, -6.0f, -3.0f );
03394 VectorSet( limb->r.maxs, 6.0f, 6.0f, 6.0f );
03395
03396 limb->s.g2radius = 200;
03397
03398 limb->s.eType = ET_GENERAL;
03399 limb->s.weapon = G2_MODEL_PART;
03400 limb->s.modelGhoul2 = limbType;
03401 limb->s.modelindex = ent->s.number;
03402 if (!ent->client)
03403 {
03404 limb->s.modelindex = -1;
03405 limb->s.otherEntityNum2 = ent->s.number;
03406 }
03407
03408 VectorClear(limb->s.apos.trDelta);
03409
03410 if (ent->client)
03411 {
03412 VectorCopy(ent->client->ps.viewangles, limb->r.currentAngles);
03413 VectorCopy(ent->client->ps.viewangles, limb->s.apos.trBase);
03414 }
03415 else
03416 {
03417 VectorCopy(ent->r.currentAngles, limb->r.currentAngles);
03418 VectorCopy(ent->r.currentAngles, limb->s.apos.trBase);
03419 }
03420
03421 //Set up the ExPhys values for the entity.
03422 limb->epGravFactor = 0;
03423 VectorClear(limb->epVelocity);
03424 VectorSubtract( point, ent->r.currentOrigin, dir );
03425 VectorNormalize( dir );
03426 if (ent->client)
03427 {
03428 VectorCopy(ent->client->ps.velocity, vel);
03429 }
03430 else
03431 {
03432 VectorCopy(ent->s.pos.trDelta, vel);
03433 }
03434 VectorMA( vel, 80, dir, limb->epVelocity );
03435
03436 //add some vertical velocity
03437 if (limbType == G2_MODELPART_HEAD ||
03438 limbType == G2_MODELPART_WAIST)
03439 {
03440 limb->epVelocity[2] += 10;
03441 }
03442
03443 if (enemy && enemy->client && ent && ent != enemy && ent->s.number != enemy->s.number &&
03444 enemy->client->ps.weapon == WP_SABER && enemy->client->olderIsValid &&
03445 (level.time - enemy->client->lastSaberStorageTime) < 200)
03446 { //The enemy has valid saber positions between this and last frame. Use them to factor in direction of the limb.
03447 vec3_t dif;
03448 float totalDistance;
03449 const float distScale = 1.2f;
03450
03451 //scale down the initial velocity first, which is based on the speed of the limb owner.
03452 //ExPhys object velocity operates on a slightly different scale than Q3-based physics velocity.
03453 VectorScale(limb->epVelocity, 0.4f, limb->epVelocity);
03454
03455 VectorSubtract(enemy->client->lastSaberBase_Always, enemy->client->olderSaberBase, dif);
03456 totalDistance = VectorNormalize(dif);
03457
03458 VectorScale(dif, totalDistance*distScale, dif);
03459 VectorAdd(limb->epVelocity, dif, limb->epVelocity);
03460
03461 if (ent->client && (ent->client->ps.torsoTimer > 0 || !BG_InDeathAnim(ent->client->ps.torsoAnim)))
03462 { //if he's done with his death anim we don't actually want the limbs going far
03463 vec3_t preVel;
03464
03465 VectorCopy(limb->epVelocity, preVel);
03466 preVel[2] = 0;
03467 totalDistance = VectorNormalize(preVel);
03468
03469 if (totalDistance < 40.0f)
03470 {
03471 float mAmt = 40.0f;//60.0f/totalDistance;
03472
03473 limb->epVelocity[0] = preVel[0]*mAmt;
03474 limb->epVelocity[1] = preVel[1]*mAmt;
03475 }
03476 }
03477 else if (ent->client)
03478 {
03479 VectorScale(limb->epVelocity, 0.3f, limb->epVelocity);
03480 }
03481 }
03482
03483 if (ent->s.eType == ET_NPC && ent->ghoul2 && limbName && stubCapName)
03484 { //if it's an npc remove these surfs on the server too. For players we don't even care cause there's no further dismemberment after death.
03485 trap_G2API_SetSurfaceOnOff(ent->ghoul2, limbName, 0x00000100);
03486 trap_G2API_SetSurfaceOnOff(ent->ghoul2, stubCapName, 0);
03487 }
03488
03489 limb->s.customRGBA[0] = ent->s.customRGBA[0];
03490 limb->s.customRGBA[1] = ent->s.customRGBA[1];
03491 limb->s.customRGBA[2] = ent->s.customRGBA[2];
03492 limb->s.customRGBA[3] = ent->s.customRGBA[3];
03493
03494 trap_LinkEntity( limb );
03495 }
|
|
|
Definition at line 4327 of file g_combat.c.
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 506 of file NPC_AI_Wampa.c. References BS_DEFAULT, BS_SEARCH, BS_WANDER, BUTTON_WALKING, usercmd_s::buttons, CHAN_AUTO, CHAN_VOICE, CLASS_WAMPA, gentity_s::client, gNPC_t::confusionTime, entityShared_t::currentOrigin, EF2_USE_ALT_ANIM, playerState_s::eFlags2, gentity_s::enemy, enemyDist, G_SetEnemy(), G_Sound(), G_SoundIndex(), gentity_t, gNPC_t::homeWp, gentity_s::inuse, gentity_s::lastEnemy, level, NPC, NPC_BSSearch(), NPC_BSSearchStart(), NPC_BSWander(), NPC_CheckEnemy(), NPC_CheckEnemyExt(), gclient_s::NPC_class, NPC_FaceEnemy(), NPC_UpdateAngles(), NPCInfo, NULL, gclient_s::ps, Q_irand(), qfalse, qtrue, gentity_s::r, gentity_s::s, SCF_LOOK_FOR_ENEMIES, gNPC_t::scriptFlags, gentity_s::spawnflags, gNPC_t::tempBehavior, entityState_s::time, level_locals_t::time, TIMER_Done(), TIMER_Remove(), TIMER_Set(), ucmd, va(), ValidEnemy(), Wampa_Attack(), Wampa_CheckRoar(), Wampa_Combat(), Wampa_Idle(), Wampa_Patrol(), gentity_s::waypoint, and WAYPOINT_NONE. Referenced by NPC_RunBehavior().
00507 {
00508 NPC->client->ps.eFlags2 &= ~EF2_USE_ALT_ANIM;
00509 //NORMAL ANIMS
00510 // stand1 = normal stand
00511 // walk1 = normal, non-angry walk
00512 // walk2 = injured
00513 // run1 = far away run
00514 // run2 = close run
00515 //VICTIM ANIMS
00516 // grabswipe = melee1 - sweep out and grab
00517 // stand2 attack = attack4 - while holding victim, swipe at him
00518 // walk3_drag = walk5 - walk with drag
00519 // stand2 = hold victim
00520 // stand2to1 = drop victim
00521 if ( !TIMER_Done( NPC, "rageTime" ) )
00522 {//do nothing but roar first time we see an enemy
00523 NPC_FaceEnemy( qtrue );
00524 return;
00525 }
00526 if ( NPC->enemy )
00527 {
00528 if ( !TIMER_Done(NPC,"attacking") )
00529 {//in middle of attack
00530 //face enemy
00531 NPC_FaceEnemy( qtrue );
00532 //continue attack logic
00533 enemyDist = Distance( NPC->r.currentOrigin, NPC->enemy->r.currentOrigin );
00534 Wampa_Attack( enemyDist, qfalse );
00535 return;
00536 }
00537 else
00538 {
00539 if ( TIMER_Done(NPC,"angrynoise") )
00540 {
00541 G_Sound( NPC, CHAN_VOICE, G_SoundIndex( va("sound/chars/wampa/misc/anger%d.wav", Q_irand(1, 2)) ) );
00542
00543 TIMER_Set( NPC, "angrynoise", Q_irand( 5000, 10000 ) );
00544 }
00545 //else, if he's in our hand, we eat, else if he's on the ground, we keep attacking his dead body for a while
00546 if( NPC->enemy->client && NPC->enemy->client->NPC_class == CLASS_WAMPA )
00547 {//got mad at another Wampa, look for a valid enemy
00548 if ( TIMER_Done( NPC, "wampaInfight" ) )
00549 {
00550 NPC_CheckEnemyExt( qtrue );
00551 }
00552 }
00553 else
00554 {
00555 if ( ValidEnemy( NPC->enemy ) == qfalse )
00556 {
00557 TIMER_Remove( NPC, "lookForNewEnemy" );//make them look again right now
00558 if ( !NPC->enemy->inuse || level.time - NPC->enemy->s.time > Q_irand( 10000, 15000 ) )
00559 {//it's been a while since the enemy died, or enemy is completely gone, get bored with him
00560 NPC->enemy = NULL;
00561 Wampa_Patrol();
00562 NPC_UpdateAngles( qtrue, qtrue );
00563 //just lost my enemy
00564 if ( (NPC->spawnflags&2) )
00565 {//search around me if I don't have an enemy
00566 NPC_BSSearchStart( NPC->waypoint, BS_SEARCH );
00567 NPCInfo->tempBehavior = BS_DEFAULT;
00568 }
00569 else if ( (NPC->spawnflags&1) )
00570 {//wander if I don't have an enemy
00571 NPC_BSSearchStart( NPC->waypoint, BS_WANDER );
00572 NPCInfo->tempBehavior = BS_DEFAULT;
00573 }
00574 return;
00575 }
00576 }
00577 if ( TIMER_Done( NPC, "lookForNewEnemy" ) )
00578 {
00579 gentity_t *newEnemy, *sav_enemy = NPC->enemy;//FIXME: what about NPC->lastEnemy?
00580 NPC->enemy = NULL;
00581 newEnemy = NPC_CheckEnemy( NPCInfo->confusionTime < level.time, qfalse, qfalse );
00582 NPC->enemy = sav_enemy;
00583 if ( newEnemy && newEnemy != sav_enemy )
00584 {//picked up a new enemy!
00585 NPC->lastEnemy = NPC->enemy;
00586 G_SetEnemy( NPC, newEnemy );
00587 //hold this one for at least 5-15 seconds
00588 TIMER_Set( NPC, "lookForNewEnemy", Q_irand( 5000, 15000 ) );
00589 }
00590 else
00591 {//look again in 2-5 secs
00592 TIMER_Set( NPC, "lookForNewEnemy", Q_irand( 2000, 5000 ) );
00593 }
00594 }
00595 }
00596 Wampa_Combat();
00597 return;
00598 }
00599 }
00600 else
00601 {
00602 if ( TIMER_Done(NPC,"idlenoise") )
00603 {
00604 G_Sound( NPC, CHAN_AUTO, G_SoundIndex( "sound/chars/wampa/misc/anger3.wav" ) );
00605
00606 TIMER_Set( NPC, "idlenoise", Q_irand( 2000, 4000 ) );
00607 }
00608 if ( (NPC->spawnflags&2) )
00609 {//search around me if I don't have an enemy
00610 if ( NPCInfo->homeWp == WAYPOINT_NONE )
00611 {//no homewap, initialize the search behavior
00612 NPC_BSSearchStart( WAYPOINT_NONE, BS_SEARCH );
00613 NPCInfo->tempBehavior = BS_DEFAULT;
00614 }
00615 ucmd.buttons |= BUTTON_WALKING;
00616 NPC_BSSearch();//this automatically looks for enemies
00617 }
00618 else if ( (NPC->spawnflags&1) )
00619 {//wander if I don't have an enemy
00620 if ( NPCInfo->homeWp == WAYPOINT_NONE )
00621 {//no homewap, initialize the wander behavior
00622 NPC_BSSearchStart( WAYPOINT_NONE, BS_WANDER );
00623 NPCInfo->tempBehavior = BS_DEFAULT;
00624 }
00625 ucmd.buttons |= BUTTON_WALKING;
00626 NPC_BSWander();
00627 if ( NPCInfo->scriptFlags & SCF_LOOK_FOR_ENEMIES )
00628 {
00629 if ( NPC_CheckEnemyExt( qtrue ) == qfalse )
00630 {
00631 Wampa_Idle();
00632 }
00633 else
00634 {
00635 Wampa_CheckRoar( NPC );
00636 TIMER_Set( NPC, "lookForNewEnemy", Q_irand( 5000, 15000 ) );
00637 }
00638 }
00639 }
00640 else
00641 {
00642 if ( NPCInfo->scriptFlags & SCF_LOOK_FOR_ENEMIES )
00643 {
00644 Wampa_Patrol();
00645 }
00646 else
00647 {
00648 Wampa_Idle();
00649 }
00650 }
00651 }
00652
00653 NPC_UpdateAngles( qtrue, qtrue );
00654 }
|
|
||||||||||||||||||||
|
Definition at line 1761 of file NPC_utils.c. References G_GetBoltPosition(), NPC, trap_EntitiesInBox(), vec3_t, and VectorCopy. Referenced by Rancor_Bite(), Rancor_Smash(), Rancor_Swing(), and Wampa_Slash().
01762 {
01763 vec3_t mins, maxs;
01764 int i;
01765
01766 //get my handRBolt's position
01767 vec3_t org;
01768
01769 G_GetBoltPosition( NPC, boltIndex, org, 0 );
01770
01771 VectorCopy( org, boltOrg );
01772
01773 //Setup the bbox to search in
01774 for ( i = 0; i < 3; i++ )
01775 {
01776 mins[i] = boltOrg[i] - radius;
01777 maxs[i] = boltOrg[i] + radius;
01778 }
01779
01780 //Get the number of entities in a given space
01781 return (trap_EntitiesInBox( mins, maxs, radiusEnts, 128 ));
01782 }
|
|
||||||||||||||||
|
Definition at line 433 of file NPC_AI_Wampa.c. References entityState_s::angles, BOTH_ATTACK1, BOTH_ATTACK2, BOTH_ATTACK3, BOTH_GESTURE1, BOTH_GESTURE2, BOTH_PAIN1, BOTH_PAIN2, CLASS_WAMPA, gentity_s::client, entityShared_t::currentOrigin, gentity_s::enemy, FL_NOTARGET, gentity_s::flags, G_SetEnemy(), gentity_t, gentity_s::health, gentity_s::inuse, gNPC_t::lastPathAngles, playerState_s::legsAnim, playerState_s::legsTimer, gNPC_t::localState, LSTATE_WAITING, gentity_s::NPC, gclient_s::NPC_class, NPC_SetAnim(), entityState_s::number, gclient_s::ps, Q_irand(), qboolean, qfalse, qtrue, gentity_s::r, gentity_s::s, SETANIM_BOTH, SETANIM_FLAG_HOLD, SETANIM_FLAG_OVERRIDE, TIMER_Done(), TIMER_Remove(), TIMER_Set(), VectorCopy, and Wampa_CheckRoar(). Referenced by NPC_PainFunc(), and NPC_SetMiscDefaultData().
00434 {
00435 qboolean hitByWampa = qfalse;
00436 if ( attacker&&attacker->client&&attacker->client->NPC_class==CLASS_WAMPA )
00437 {
00438 hitByWampa = qtrue;
00439 }
00440 if ( attacker
00441 && attacker->inuse
00442 && attacker != self->enemy
00443 && !(attacker->flags&FL_NOTARGET) )
00444 {
00445 if ( (!attacker->s.number&&!Q_irand(0,3))
00446 || !self->enemy
00447 || self->enemy->health == 0
00448 || (self->enemy->client&&self->enemy->client->NPC_class == CLASS_WAMPA)
00449 || (!Q_irand(0, 4 ) && DistanceSquared( attacker->r.currentOrigin, self->r.currentOrigin ) < DistanceSquared( self->enemy->r.currentOrigin, self->r.currentOrigin )) )
00450 {//if my enemy is dead (or attacked by player) and I'm not still holding/eating someone, turn on the attacker
00451 //FIXME: if can't nav to my enemy, take this guy if I can nav to him
00452 G_SetEnemy( self, attacker );
00453 TIMER_Set( self, "lookForNewEnemy", Q_irand( 5000, 15000 ) );
00454 if ( hitByWampa )
00455 {//stay mad at this Wampa for 2-5 secs before looking for attacker enemies
00456 TIMER_Set( self, "wampaInfight", Q_irand( 2000, 5000 ) );
00457 }
00458 }
00459 }
00460 if ( (hitByWampa|| Q_irand( 0, 100 ) < damage )//hit by wampa, hit while holding live victim, or took a lot of damage
00461 && self->client->ps.legsAnim != BOTH_GESTURE1
00462 && self->client->ps.legsAnim != BOTH_GESTURE2
00463 && TIMER_Done( self, "takingPain" ) )
00464 {
00465 if ( !Wampa_CheckRoar( self ) )
00466 {
00467 if ( self->client->ps.legsAnim != BOTH_ATTACK1
00468 && self->client->ps.legsAnim != BOTH_ATTACK2
00469 && self->client->ps.legsAnim != BOTH_ATTACK3 )
00470 {//cant interrupt one of the big attack anims
00471 if ( self->health > 100 || hitByWampa )
00472 {
00473 TIMER_Remove( self, "attacking" );
00474
00475 VectorCopy( self->NPC->lastPathAngles, self->s.angles );
00476
00477 if ( !Q_irand( 0, 1 ) )
00478 {
00479 NPC_SetAnim( self, SETANIM_BOTH, BOTH_PAIN2, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD );
00480 }
00481 else
00482 {
00483 NPC_SetAnim( self, SETANIM_BOTH, BOTH_PAIN1, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD );
00484 }
00485 TIMER_Set( self, "takingPain", self->client->ps.legsTimer+Q_irand(0, 500) );
00486 //allow us to re-evaluate our running speed/anim
00487 TIMER_Set( self, "runfar", -1 );
00488 TIMER_Set( self, "runclose", -1 );
00489 TIMER_Set( self, "walk", -1 );
00490
00491 if ( self->NPC )
00492 {
00493 self->NPC->localState = LSTATE_WAITING;
00494 }
00495 }
00496 }
00497 }
00498 }
00499 }
|
|
|
Definition at line 43 of file NPC_AI_Wampa.c. References G_SoundIndex(). Referenced by NPC_SpawnType(), and SP_NPC_Monster_Wampa().
00044 {
00045 /*
00046 int i;
00047 for ( i = 1; i < 4; i ++ )
00048 {
00049 G_SoundIndex( va("sound/chars/wampa/growl%d.wav", i) );
00050 }
00051 for ( i = 1; i < 3; i ++ )
00052 {
00053 G_SoundIndex( va("sound/chars/wampa/snort%d.wav", i) );
00054 }
00055 */
00056 G_SoundIndex( "sound/chars/rancor/swipehit.wav" );
00057 //G_SoundIndex( "sound/chars/wampa/chomp.wav" );
00058 }
|
|
||||||||||||
|
Definition at line 267 of file NPC_AI_Wampa.c. References AngleVectors(), BOTH_ATTACK1, BOTH_ATTACK2, BOTH_ATTACK3, BUTTON_WALKING, usercmd_s::buttons, gentity_s::client, ENTITYNUM_NONE, playerState_s::groundEntityNum, renderInfo_s::handLBolt, renderInfo_s::handRBolt, playerState_s::legsAnim, playerState_s::legsTimer, entityShared_t::maxs, MIN_DISTANCE, NPC, NPC_SetAnim(), NULL, gclient_s::ps, Q_irand(), qfalse, qtrue, gentity_s::r, random, gclient_s::renderInfo, SETANIM_BOTH, SETANIM_FLAG_HOLD, SETANIM_FLAG_OVERRIDE, TIMER_Done2(), TIMER_Exists(), TIMER_Set(), ucmd, vec3_t, VectorScale, VectorSet, playerState_s::velocity, playerState_s::viewangles, Wampa_Move(), Wampa_Slash(), and YAW. Referenced by NPC_BSWampa_Default(), and Wampa_Combat().
00268 {
00269 if ( !TIMER_Exists( NPC, "attacking" ) )
00270 {
00271 if ( Q_irand(0, 2) && !doCharge )
00272 {//double slash
00273 NPC_SetAnim( NPC, SETANIM_BOTH, BOTH_ATTACK1, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD );
00274 TIMER_Set( NPC, "attack_dmg", 750 );
00275 }
00276 else if ( doCharge || (distance > 270 && distance < 430 && !Q_irand(0, 1)) )
00277 {//leap
00278 vec3_t fwd, yawAng;
00279 VectorSet( yawAng, 0, NPC->client->ps.viewangles[YAW], 0 );
00280 NPC_SetAnim( NPC, SETANIM_BOTH, BOTH_ATTACK2, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD );
00281 TIMER_Set( NPC, "attack_dmg", 500 );
00282 AngleVectors( yawAng, fwd, NULL, NULL );
00283 VectorScale( fwd, distance*1.5f, NPC->client->ps.velocity );
00284 NPC->client->ps.velocity[2] = 150;
00285 NPC->client->ps.groundEntityNum = ENTITYNUM_NONE;
00286 }
00287 else
00288 {//backhand
00289 NPC_SetAnim( NPC, SETANIM_BOTH, BOTH_ATTACK3, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD );
00290 TIMER_Set( NPC, "attack_dmg", 250 );
00291 }
00292
00293 TIMER_Set( NPC, "attacking", NPC->client->ps.legsTimer + random() * 200 );
00294 //allow us to re-evaluate our running speed/anim
00295 TIMER_Set( NPC, "runfar", -1 );
00296 TIMER_Set( NPC, "runclose", -1 );
00297 TIMER_Set( NPC, "walk", -1 );
00298 }
00299
00300 // Need to do delayed damage since the attack animations encapsulate multiple mini-attacks
00301
00302 if ( TIMER_Done2( NPC, "attack_dmg", qtrue ) )
00303 {
00304 switch ( NPC->client->ps.legsAnim )
00305 {
00306 case BOTH_ATTACK1:
00307 Wampa_Slash( NPC->client->renderInfo.handRBolt, qfalse );
00308 //do second hit
00309 TIMER_Set( NPC, "attack_dmg2", 100 );
00310 break;
00311 case BOTH_ATTACK2:
00312 Wampa_Slash( NPC->client->renderInfo.handRBolt, qfalse );
00313 TIMER_Set( NPC, "attack_dmg2", 100 );
00314 break;
00315 case BOTH_ATTACK3:
00316 Wampa_Slash( NPC->client->renderInfo.handLBolt, qtrue );
00317 break;
00318 }
00319 }
00320 else if ( TIMER_Done2( NPC, "attack_dmg2", qtrue ) )
00321 {
00322 switch ( NPC->client->ps.legsAnim )
00323 {
00324 case BOTH_ATTACK1:
00325 Wampa_Slash( NPC->client->renderInfo.handLBolt, qfalse );
00326 break;
00327 case BOTH_ATTACK2:
00328 Wampa_Slash( NPC->client->renderInfo.handLBolt, qfalse );
00329 break;
00330 }
00331 }
00332
00333 // Just using this to remove the attacking flag at the right time
00334 TIMER_Done2( NPC, "attacking", qtrue );
00335
00336 if ( NPC->client->ps.legsAnim == BOTH_ATTACK1 && distance > (NPC->r.maxs[0]+MIN_DISTANCE) )
00337 {//okay to keep moving
00338 ucmd.buttons |= BUTTON_WALKING;
00339 Wampa_Move( 1 );
00340 }
00341 }
|
|
|
Definition at line 78 of file NPC_AI_Wampa.c. References BOTH_GESTURE1, BOTH_GESTURE2, gentity_s::client, gentity_t, playerState_s::legsTimer, level, NPC_SetAnim(), gclient_s::ps, Q_irand(), qboolean, qfalse, qtrue, SETANIM_BOTH, SETANIM_FLAG_HOLD, SETANIM_FLAG_OVERRIDE, level_locals_t::time, TIMER_Set(), and gentity_s::wait. Referenced by NPC_BSWampa_Default(), NPC_Wampa_Pain(), Wampa_Combat(), and Wampa_Patrol().
00079 {
00080 if ( self->wait < level.time )
00081 {
00082 self->wait = level.time + Q_irand( 5000, 20000 );
00083 NPC_SetAnim( self, SETANIM_BOTH, Q_irand(BOTH_GESTURE1,BOTH_GESTURE2), (SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD) );
00084 TIMER_Set( self, "rageTime", self->client->ps.legsTimer );
00085 return qtrue;
00086 }
00087 return qfalse;
00088 }
|
|
|
Definition at line 344 of file NPC_AI_Wampa.c. References gNPC_t::combatMove, entityShared_t::currentAngles, entityShared_t::currentOrigin, gentity_s::enemy, enemyDist, fabs(), gNPC_t::goalEntity, gNPC_t::goalRadius, gentity_s::health, InFOV3(), gNPC_t::localState, LSTATE_CLEAR, LSTATE_WAITING, MAX_DISTANCE, entityShared_t::maxs, MIN_DISTANCE, NPC, NPC_ClearLOS(), NPC_FaceEnemy(), NPCInfo, Q_irand(), qboolean, qfalse, qtrue, gentity_s::r, TIMER_Done(), TIMER_Done2(), UpdateGoal(), vec3_t, VectorSet, Wampa_Attack(), Wampa_CheckRoar(), Wampa_Move(), and YAW. Referenced by NPC_BSWampa_Default().
00345 {
00346 // If we cannot see our target or we have somewhere to go, then do that
00347 if ( !NPC_ClearLOS( NPC->r.currentOrigin, NPC->enemy->r.currentOrigin ) )
00348 {
00349 if ( !Q_irand( 0, 10 ) )
00350 {
00351 if ( Wampa_CheckRoar( NPC ) )
00352 {
00353 return;
00354 }
00355 }
00356 NPCInfo->combatMove = qtrue;
00357 NPCInfo->goalEntity = NPC->enemy;
00358 NPCInfo->goalRadius = MAX_DISTANCE; // just get us within combat range
00359
00360 Wampa_Move( 0 );
00361 return;
00362 }
00363 else if ( UpdateGoal() )
00364 {
00365 NPCInfo->combatMove = qtrue;
00366 NPCInfo->goalEntity = NPC->enemy;
00367 NPCInfo->goalRadius = MAX_DISTANCE; // just get us within combat range
00368
00369 Wampa_Move( 1 );
00370 return;
00371 }
00372 else
00373 {
00374 float distance = enemyDist = Distance( NPC->r.currentOrigin, NPC->enemy->r.currentOrigin );
00375 qboolean advance = (qboolean)( distance > (NPC->r.maxs[0]+MIN_DISTANCE) ? qtrue : qfalse );
00376 qboolean doCharge = qfalse;
00377
00378 // Sometimes I have problems with facing the enemy I'm attacking, so force the issue so I don't look dumb
00379 //FIXME: always seems to face off to the left or right?!!!!
00380 NPC_FaceEnemy( qtrue );
00381
00382
00383 if ( advance )
00384 {//have to get closer
00385 vec3_t yawOnlyAngles;
00386 VectorSet( yawOnlyAngles, 0, NPC->r.currentAngles[YAW], 0 );
00387 if ( NPC->enemy->health > 0//enemy still alive
00388 && fabs(distance-350) <= 80 //enemy anywhere from 270 to 430 away
00389 && InFOV3( NPC->enemy->r.currentOrigin, NPC->r.currentOrigin, yawOnlyAngles, 20, 20 ) )//enemy generally in front
00390 {//10% chance of doing charge anim
00391 if ( !Q_irand( 0, 9 ) )
00392 {//go for the charge
00393 doCharge = qtrue;
00394 advance = qfalse;
00395 }
00396 }
00397 }
00398
00399 if (( advance || NPCInfo->localState == LSTATE_WAITING ) && TIMER_Done( NPC, "attacking" )) // waiting monsters can't attack
00400 {
00401 if ( TIMER_Done2( NPC, "takingPain", qtrue ))
00402 {
00403 NPCInfo->localState = LSTATE_CLEAR;
00404 }
00405 else
00406 {
00407 Wampa_Move( 1 );
00408 }
00409 }
00410 else
00411 {
00412 if ( !Q_irand( 0, 20 ) )
00413 {//FIXME: only do this if we just damaged them or vice-versa?
00414 if ( Wampa_CheckRoar( NPC ) )
00415 {
00416 return;
00417 }
00418 }
00419 if ( !Q_irand( 0, 1 ) )
00420 {//FIXME: base on skill
00421 Wampa_Attack( distance, doCharge );
00422 }
00423 }
00424 }
00425 }
|
|
|
Definition at line 66 of file NPC_AI_Wampa.c. References BUTTON_WALKING, usercmd_s::buttons, gNPC_t::localState, LSTATE_CLEAR, NPC_MoveToGoal(), NPCInfo, qtrue, ucmd, and UpdateGoal(). Referenced by NPC_BSWampa_Default(), and Wampa_Patrol().
00067 {
00068 NPCInfo->localState = LSTATE_CLEAR;
00069
00070 //If we have somewhere to go, then do that
00071 if ( UpdateGoal() )
00072 {
00073 ucmd.buttons &= ~BUTTON_WALKING;
00074 NPC_MoveToGoal( qtrue );
00075 }
00076 }
|
|
|
Definition at line 126 of file NPC_AI_Wampa.c. References BUTTON_WALKING, usercmd_s::buttons, gentity_s::client, EF2_USE_ALT_ANIM, playerState_s::eFlags2, gentity_s::enemy, enemyDist, gNPC_t::goalEntity, gNPC_t::goalRadius, gNPC_t::localState, LSTATE_WAITING, MAX_DISTANCE, NPC, NPC_MoveToGoal(), NPCInfo, gclient_s::ps, Q_irand(), qtrue, gNPCstats_e::runSpeed, gNPC_t::stats, TIMER_Done(), TIMER_Set(), and ucmd. Referenced by Wampa_Attack(), and Wampa_Combat().
00127 {
00128 if ( NPCInfo->localState != LSTATE_WAITING )
00129 {
00130 NPCInfo->goalEntity = NPC->enemy;
00131
00132 if ( NPC->enemy )
00133 {//pick correct movement speed and anim
00134 //run by default
00135 ucmd.buttons &= ~BUTTON_WALKING;
00136 if ( !TIMER_Done( NPC, "runfar" )
00137 || !TIMER_Done( NPC, "runclose" ) )
00138 {//keep running with this anim & speed for a bit
00139 }
00140 else if ( !TIMER_Done( NPC, "walk" ) )
00141 {//keep walking for a bit
00142 ucmd.buttons |= BUTTON_WALKING;
00143 }
00144 else if ( visible && enemyDist > 384 && NPCInfo->stats.runSpeed == 180 )
00145 {//fast run, all fours
00146 NPCInfo->stats.runSpeed = 300;
00147 TIMER_Set( NPC, "runfar", Q_irand( 2000, 4000 ) );
00148 }
00149 else if ( enemyDist > 256 && NPCInfo->stats.runSpeed == 300 )
00150 {//slow run, upright
00151 NPCInfo->stats.runSpeed = 180;
00152 TIMER_Set( NPC, "runclose", Q_irand( 3000, 5000 ) );
00153 }
00154 else if ( enemyDist < 128 )
00155 {//walk
00156 NPCInfo->stats.runSpeed = 180;
00157 ucmd.buttons |= BUTTON_WALKING;
00158 TIMER_Set( NPC, "walk", Q_irand( 4000, 6000 ) );
00159 }
00160 }
00161
00162 if ( NPCInfo->stats.runSpeed == 300 )
00163 {//need to use the alternate run - hunched over on all fours
00164 NPC->client->ps.eFlags2 |= EF2_USE_ALT_ANIM;
00165 }
00166 NPC_MoveToGoal( qtrue );
00167 NPCInfo->goalRadius = MAX_DISTANCE; // just get us within combat range
00168 }
00169 }
|
|
|
Definition at line 94 of file NPC_AI_Wampa.c. References BUTTON_WALKING, usercmd_s::buttons, crandom, gNPC_t::localState, LSTATE_CLEAR, NPC, NPC_CheckEnemyExt(), NPC_MoveToGoal(), NPCInfo, Q_irand(), qfalse, qtrue, TIMER_Done(), TIMER_Set(), ucmd, UpdateGoal(), Wampa_CheckRoar(), and Wampa_Idle(). Referenced by NPC_BSWampa_Default().
00095 {
00096 NPCInfo->localState = LSTATE_CLEAR;
00097
00098 //If we have somewhere to go, then do that
00099 if ( UpdateGoal() )
00100 {
00101 ucmd.buttons |= BUTTON_WALKING;
00102 NPC_MoveToGoal( qtrue );
00103 }
00104 else
00105 {
00106 if ( TIMER_Done( NPC, "patrolTime" ))
00107 {
00108 TIMER_Set( NPC, "patrolTime", crandom() * 5000 + 5000 );
00109 }
00110 }
00111
00112 if ( NPC_CheckEnemyExt( qtrue ) == qfalse )
00113 {
00114 Wampa_Idle();
00115 return;
00116 }
00117 Wampa_CheckRoar( NPC );
00118 TIMER_Set( NPC, "lookForNewEnemy", Q_irand( 5000, 15000 ) );
00119 }
|
|
|
Definition at line 16 of file NPC_AI_Wampa.c. References gentity_s::client, renderInfo_s::crotchBolt, renderInfo_s::footLBolt, renderInfo_s::footRBolt, gentity_t, gentity_s::ghoul2, renderInfo_s::handLBolt, renderInfo_s::handRBolt, renderInfo_s::headBolt, gclient_s::renderInfo, renderInfo_t, renderInfo_s::torsoBolt, and trap_G2API_AddBolt(). Referenced by NPC_SetMiscDefaultData().
00017 {
00018 if ( self && self->client )
00019 {
00020 renderInfo_t *ri = &self->client->renderInfo;
00021 ri->headBolt = trap_G2API_AddBolt(self->ghoul2, 0, "*head_eyes");
00022 //ri->cervicalBolt = trap_G2API_AddBolt(self->ghoul2, 0, "neck_bone" );
00023 //ri->chestBolt = trap_G2API_AddBolt(self->ghoul2, 0, "upper_spine");
00024 //ri->gutBolt = trap_G2API_AddBolt(self->ghoul2, 0, "mid_spine");
00025 ri->torsoBolt = trap_G2API_AddBolt(self->ghoul2, 0, "lower_spine");
00026 ri->crotchBolt = trap_G2API_AddBolt(self->ghoul2, 0, "rear_bone");
00027 //ri->elbowLBolt = trap_G2API_AddBolt(self->ghoul2, 0, "*l_arm_elbow");
00028 //ri->elbowRBolt = trap_G2API_AddBolt(self->ghoul2, 0, "*r_arm_elbow");
00029 ri->handLBolt = trap_G2API_AddBolt(self->ghoul2, 0, "*l_hand");
00030 ri->handRBolt = trap_G2API_AddBolt(self->ghoul2, 0, "*r_hand");
00031 //ri->kneeLBolt = trap_G2API_AddBolt(self->ghoul2, 0, "*hips_l_knee");
00032 //ri->kneeRBolt = trap_G2API_AddBolt(self->ghoul2, 0, "*hips_r_knee");
00033 ri->footLBolt = trap_G2API_AddBolt(self->ghoul2, 0, "*l_leg_foot");
00034 ri->footRBolt = trap_G2API_AddBolt(self->ghoul2, 0, "*r_leg_foot");
00035 }
00036 }
|
|
||||||||||||
|
Definition at line 177 of file NPC_AI_Wampa.c. References AngleVectors(), BG_KnockDownable(), BOTH_DEATH17, BOTH_DEATHBACKWARD2, CHAN_WEAPON, CLASS_ATST, CLASS_RANCOR, CLASS_WAMPA, gentity_s::client, entityShared_t::currentOrigin, DAMAGE_NO_ARMOR, DAMAGE_NO_KNOCKBACK, flrand(), playerState_s::forceDodgeAnim, playerState_s::forceHandExtend, playerState_s::forceHandExtendTime, G2_MODELPART_HEAD, G2_MODELPART_RLEG, G2_MODELPART_WAIST, G_Damage(), G_Dismember(), g_entities, G_Knockdown(), G_Sound(), G_SoundIndex(), G_Throw(), gentity_t, HANDEXTEND_KNOCKDOWN, gentity_s::health, gentity_s::inuse, level, MOD_MELEE, NPC, gclient_s::NPC_class, NPC_GetEntsNearBolt(), NPC_SetAnim(), NULL, PITCH, gclient_s::ps, Q_irand(), qfalse, qtrue, playerState_s::quickerGetup, gentity_s::r, SETANIM_BOTH, SETANIM_FLAG_HOLD, SETANIM_FLAG_OVERRIDE, level_locals_t::time, playerState_s::torsoAnim, vec3_origin, vec3_t, VectorCopy, playerState_s::viewangles, and YAW. Referenced by Wampa_Attack().
00178 {
00179 int radiusEntNums[128];
00180 int numEnts;
00181 const float radius = 88;
00182 const float radiusSquared = (radius*radius);
00183 int i;
00184 vec3_t boltOrg;
00185 int damage = (backhand)?Q_irand(10,15):Q_irand(20,30);
00186
00187 numEnts = NPC_GetEntsNearBolt( radiusEntNums, radius, boltIndex, boltOrg );
00188
00189 for ( i = 0; i < numEnts; i++ )
00190 {
00191 gentity_t *radiusEnt = &g_entities[radiusEntNums[i]];
00192 if ( !radiusEnt->inuse )
00193 {
00194 continue;
00195 }
00196
00197 if ( radiusEnt == NPC )
00198 {//Skip the wampa ent
00199 continue;
00200 }
00201
00202 if ( radiusEnt->client == NULL )
00203 {//must be a client
00204 continue;
00205 }
00206
00207 if ( DistanceSquared( radiusEnt->r.currentOrigin, boltOrg ) <= radiusSquared )
00208 {
00209 //smack
00210 G_Damage( radiusEnt, NPC, NPC, vec3_origin, radiusEnt->r.currentOrigin, damage, ((backhand)?DAMAGE_NO_ARMOR:(DAMAGE_NO_ARMOR|DAMAGE_NO_KNOCKBACK)), MOD_MELEE );
00211 if ( backhand )
00212 {
00213 //actually push the enemy
00214 vec3_t pushDir;
00215 vec3_t angs;
00216 VectorCopy( NPC->client->ps.viewangles, angs );
00217 angs[YAW] += flrand( 25, 50 );
00218 angs[PITCH] = flrand( -25, -15 );
00219 AngleVectors( angs, pushDir, NULL, NULL );
00220 if ( radiusEnt->client->NPC_class != CLASS_WAMPA
00221 && radiusEnt->client->NPC_class != CLASS_RANCOR
00222 && radiusEnt->client->NPC_class != CLASS_ATST )
00223 {
00224 G_Throw( radiusEnt, pushDir, 65 );
00225 if ( BG_KnockDownable(&radiusEnt->client->ps) &&
00226 radiusEnt->health > 0 && Q_irand( 0, 1 ) )
00227 {//do pain on enemy
00228 radiusEnt->client->ps.forceHandExtend = HANDEXTEND_KNOCKDOWN;
00229 radiusEnt->client->ps.forceDodgeAnim = 0;
00230 radiusEnt->client->ps.forceHandExtendTime = level.time + 1100;
00231 radiusEnt->client->ps.quickerGetup = qfalse;
00232 }
00233 }
00234 }
00235 else if ( radiusEnt->health <= 0 && radiusEnt->client )
00236 {//killed them, chance of dismembering
00237 if ( !Q_irand( 0, 1 ) )
00238 {//bite something off
00239 int hitLoc = Q_irand( G2_MODELPART_HEAD, G2_MODELPART_RLEG );
00240 if ( hitLoc == G2_MODELPART_HEAD )
00241 {
00242 NPC_SetAnim( radiusEnt, SETANIM_BOTH, BOTH_DEATH17, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD );
00243 }
00244 else if ( hitLoc == G2_MODELPART_WAIST )
00245 {
00246 NPC_SetAnim( radiusEnt, SETANIM_BOTH, BOTH_DEATHBACKWARD2, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD );
00247 }
00248 G_Dismember( radiusEnt, NPC, radiusEnt->r.currentOrigin, hitLoc, 90, 0, radiusEnt->client->ps.torsoAnim, qtrue);
00249 }
00250 }
00251 else if ( !Q_irand( 0, 3 ) && radiusEnt->health > 0 )
00252 {//one out of every 4 normal hits does a knockdown, too
00253 vec3_t pushDir;
00254 vec3_t angs;
00255 VectorCopy( NPC->client->ps.viewangles, angs );
00256 angs[YAW] += flrand( 25, 50 );
00257 angs[PITCH] = flrand( -25, -15 );
00258 AngleVectors( angs, pushDir, NULL, NULL );
00259 G_Knockdown( radiusEnt );
00260 }
00261 G_Sound( radiusEnt, CHAN_WEAPON, G_SoundIndex( "sound/chars/rancor/swipehit.wav" ) );
00262 }
00263 }
00264 }
|
|
|
Definition at line 14 of file NPC_AI_Wampa.c. Referenced by Boba_FireDecide(), NPC_BSHuntAndKill(), NPC_BSWampa_Default(), turret_base_think(), turretG2_base_think(), VEH_TurretThink(), Wampa_Combat(), and Wampa_Move(). |