//extern void G_Knockdown( gentity_t *victim ); //[/KnockdownSys] static void Howler_TryDamage( int damage, qboolean tongue, qboolean knockdown ) { vec3_t start, end, dir; trace_t tr; float dist; if ( tongue ) { G_GetBoltPosition( NPC, NPC->NPC->genericBolt1, start, 0 ); G_GetBoltPosition( NPC, NPC->NPC->genericBolt2, end, 0 ); VectorSubtract( end, start, dir ); dist = VectorNormalize( dir ); VectorMA( start, dist+16, dir, end ); } else { VectorCopy( NPC->r.currentOrigin, start ); AngleVectors( NPC->r.currentAngles, dir, NULL, NULL ); VectorMA( start, MIN_DISTANCE*2, dir, end ); } /* RACC - don't need this for now. #ifndef FINAL_BUILD if ( d_saberCombat.integer > 1 ) { G_DebugLine(start, end, 1000, 0x000000ff, qtrue); } #endif */ // Should probably trace from the mouth, but, ah well. trap_Trace( &tr, start, vec3_origin, vec3_origin, end, NPC->s.number, MASK_SHOT ); if ( tr.entityNum < ENTITYNUM_WORLD ) {//hit *something* gentity_t *victim = &g_entities[tr.entityNum]; if ( !victim->client || victim->client->NPC_class != CLASS_HOWLER ) {//not another howler if ( knockdown && victim->client ) {//only do damage if victim isn't knocked down. If he isn't, knock him down if ( PM_InKnockDown( &victim->client->ps ) ) { return; } } //FIXME: some sort of damage effect (claws and tongue are cutting you... blood?) G_Damage( victim, NPC, NPC, dir, tr.endpos, damage, DAMAGE_NO_KNOCKBACK, MOD_MELEE ); if ( knockdown && victim->health > 0 ) {//victim still alive //[KnockdownSys] G_Knockdown( victim, NPC, NPC->client->ps.velocity, 500, qfalse ); //G_Knockdown(victim); //[/KnockdownSys] } } } }
float NPC_EntRangeFromBolt( gentity_t *targEnt, int boltIndex ) { vec3_t org; if ( !targEnt ) { return Q3_INFINITE; } G_GetBoltPosition( NPC, boltIndex, org, 0 ); return (Distance( targEnt->r.currentOrigin, org )); }
int NPC_GetEntsNearBolt( int *radiusEnts, float radius, int boltIndex, vec3_t boltOrg ) { vec3_t mins, maxs; int i; //get my handRBolt's position vec3_t org; G_GetBoltPosition( NPC, boltIndex, org, 0 ); VectorCopy( org, boltOrg ); //Setup the bbox to search in for ( i = 0; i < 3; i++ ) { mins[i] = boltOrg[i] - radius; maxs[i] = boltOrg[i] + radius; } //Get the number of entities in a given space return (trap_EntitiesInBox( mins, maxs, radiusEnts, 128 )); }
void Rancor_Attack( float distance, qboolean doCharge ) { if ( !TIMER_Exists( NPCS.NPC, "attacking" ) ) { if ( NPCS.NPC->count == 2 && NPCS.NPC->activator ) { } else if ( NPCS.NPC->count == 1 && NPCS.NPC->activator ) {//holding enemy if ( NPCS.NPC->activator->health > 0 && Q_irand( 0, 1 ) ) {//quick bite NPC_SetAnim( NPCS.NPC, SETANIM_BOTH, BOTH_ATTACK1, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD ); TIMER_Set( NPCS.NPC, "attack_dmg", 450 ); } else {//full eat NPC_SetAnim( NPCS.NPC, SETANIM_BOTH, BOTH_ATTACK3, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD ); TIMER_Set( NPCS.NPC, "attack_dmg", 900 ); //Make victim scream in fright if ( NPCS.NPC->activator->health > 0 && NPCS.NPC->activator->client ) { G_AddEvent( NPCS.NPC->activator, Q_irand(EV_DEATH1, EV_DEATH3), 0 ); NPC_SetAnim( NPCS.NPC->activator, SETANIM_TORSO, BOTH_FALLDEATH1, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD ); if ( NPCS.NPC->activator->NPC ) {//no more thinking for you TossClientItems( NPCS.NPC ); NPCS.NPC->activator->NPC->nextBStateThink = Q3_INFINITE; } } } } else if ( NPCS.NPC->enemy->health > 0 && doCharge ) {//charge vec3_t fwd, yawAng; VectorSet( yawAng, 0, NPCS.NPC->client->ps.viewangles[YAW], 0 ); AngleVectors( yawAng, fwd, NULL, NULL ); VectorScale( fwd, distance*1.5f, NPCS.NPC->client->ps.velocity ); NPCS.NPC->client->ps.velocity[2] = 150; NPCS.NPC->client->ps.groundEntityNum = ENTITYNUM_NONE; NPC_SetAnim( NPCS.NPC, SETANIM_BOTH, BOTH_MELEE2, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD ); TIMER_Set( NPCS.NPC, "attack_dmg", 1250 ); } else if ( !Q_irand(0, 1) ) {//smash NPC_SetAnim( NPCS.NPC, SETANIM_BOTH, BOTH_MELEE1, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD ); TIMER_Set( NPCS.NPC, "attack_dmg", 1000 ); } else {//try to grab NPC_SetAnim( NPCS.NPC, SETANIM_BOTH, BOTH_ATTACK2, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD ); TIMER_Set( NPCS.NPC, "attack_dmg", 1000 ); } TIMER_Set( NPCS.NPC, "attacking", NPCS.NPC->client->ps.legsTimer + random() * 200 ); } // Need to do delayed damage since the attack animations encapsulate multiple mini-attacks if ( TIMER_Done2( NPCS.NPC, "attack_dmg", qtrue ) ) { vec3_t shakePos; switch ( NPCS.NPC->client->ps.legsAnim ) { case BOTH_MELEE1: Rancor_Smash(); G_GetBoltPosition( NPCS.NPC, NPCS.NPC->client->renderInfo.handLBolt, shakePos, 0 ); G_ScreenShake( shakePos, NULL, 4.0f, 1000, qfalse ); //CGCam_Shake( 1.0f*playerDist/128.0f, 1000 ); break; case BOTH_MELEE2: Rancor_Bite(); TIMER_Set( NPCS.NPC, "attack_dmg2", 450 ); break; case BOTH_ATTACK1: if ( NPCS.NPC->count == 1 && NPCS.NPC->activator ) { G_Damage( NPCS.NPC->activator, NPCS.NPC, NPCS.NPC, vec3_origin, NPCS.NPC->activator->r.currentOrigin, Q_irand( 25, 40 ), DAMAGE_NO_ARMOR|DAMAGE_NO_KNOCKBACK, MOD_MELEE ); if ( NPCS.NPC->activator->health <= 0 ) {//killed him //make it look like we bit his head off //NPC->activator->client->dismembered = qfalse; G_Dismember( NPCS.NPC->activator, NPCS.NPC, NPCS.NPC->activator->r.currentOrigin, G2_MODELPART_HEAD, 90, 0, NPCS.NPC->activator->client->ps.torsoAnim, qtrue); //G_DoDismemberment( NPC->activator, NPC->activator->r.currentOrigin, MOD_SABER, 1000, HL_HEAD, qtrue ); NPCS.NPC->activator->client->ps.forceHandExtend = HANDEXTEND_NONE; NPCS.NPC->activator->client->ps.forceHandExtendTime = 0; NPC_SetAnim( NPCS.NPC->activator, SETANIM_BOTH, BOTH_SWIM_IDLE1, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD ); } G_Sound( NPCS.NPC->activator, CHAN_AUTO, G_SoundIndex( "sound/chars/rancor/chomp.wav" ) ); } break; case BOTH_ATTACK2: //try to grab Rancor_Swing( qtrue ); break; case BOTH_ATTACK3: if ( NPCS.NPC->count == 1 && NPCS.NPC->activator ) { //cut in half if ( NPCS.NPC->activator->client ) { //NPC->activator->client->dismembered = qfalse; G_Dismember( NPCS.NPC->activator, NPCS.NPC, NPCS.NPC->activator->r.currentOrigin, G2_MODELPART_WAIST, 90, 0, NPCS.NPC->activator->client->ps.torsoAnim, qtrue); //G_DoDismemberment( NPC->activator, NPC->enemy->r.currentOrigin, MOD_SABER, 1000, HL_WAIST, qtrue ); } //KILL G_Damage( NPCS.NPC->activator, NPCS.NPC, NPCS.NPC, vec3_origin, NPCS.NPC->activator->r.currentOrigin, NPCS.NPC->enemy->health+10, DAMAGE_NO_PROTECTION|DAMAGE_NO_ARMOR|DAMAGE_NO_KNOCKBACK|DAMAGE_NO_HIT_LOC, MOD_MELEE );//, HL_NONE );// if ( NPCS.NPC->activator->client ) { NPCS.NPC->activator->client->ps.forceHandExtend = HANDEXTEND_NONE; NPCS.NPC->activator->client->ps.forceHandExtendTime = 0; NPC_SetAnim( NPCS.NPC->activator, SETANIM_BOTH, BOTH_SWIM_IDLE1, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD ); } TIMER_Set( NPCS.NPC, "attack_dmg2", 1350 ); G_Sound( NPCS.NPC->activator, CHAN_AUTO, G_SoundIndex( "sound/chars/rancor/swipehit.wav" ) ); G_AddEvent( NPCS.NPC->activator, EV_JUMP, NPCS.NPC->activator->health ); } break; } } else if ( TIMER_Done2( NPCS.NPC, "attack_dmg2", qtrue ) ) { switch ( NPCS.NPC->client->ps.legsAnim ) { case BOTH_MELEE1: break; case BOTH_MELEE2: Rancor_Bite(); break; case BOTH_ATTACK1: break; case BOTH_ATTACK2: break; case BOTH_ATTACK3: if ( NPCS.NPC->count == 1 && NPCS.NPC->activator ) {//swallow victim G_Sound( NPCS.NPC->activator, CHAN_AUTO, G_SoundIndex( "sound/chars/rancor/chomp.wav" ) ); //FIXME: sometimes end up with a live one in our mouths? //just make sure they're dead if ( NPCS.NPC->activator->health > 0 ) { //cut in half //NPC->activator->client->dismembered = qfalse; G_Dismember( NPCS.NPC->activator, NPCS.NPC, NPCS.NPC->activator->r.currentOrigin, G2_MODELPART_WAIST, 90, 0, NPCS.NPC->activator->client->ps.torsoAnim, qtrue); //G_DoDismemberment( NPC->activator, NPC->enemy->r.currentOrigin, MOD_SABER, 1000, HL_WAIST, qtrue ); //KILL G_Damage( NPCS.NPC->activator, NPCS.NPC, NPCS.NPC, vec3_origin, NPCS.NPC->activator->r.currentOrigin, NPCS.NPC->enemy->health+10, DAMAGE_NO_PROTECTION|DAMAGE_NO_ARMOR|DAMAGE_NO_KNOCKBACK|DAMAGE_NO_HIT_LOC, MOD_MELEE );//, HL_NONE ); NPCS.NPC->activator->client->ps.forceHandExtend = HANDEXTEND_NONE; NPCS.NPC->activator->client->ps.forceHandExtendTime = 0; NPC_SetAnim( NPCS.NPC->activator, SETANIM_BOTH, BOTH_SWIM_IDLE1, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD ); G_AddEvent( NPCS.NPC->activator, EV_JUMP, NPCS.NPC->activator->health ); } if ( NPCS.NPC->activator->client ) {//*sigh*, can't get tags right, just remove them? NPCS.NPC->activator->client->ps.eFlags |= EF_NODRAW; } NPCS.NPC->count = 2; TIMER_Set( NPCS.NPC, "clearGrabbed", 2600 ); } break; } } else if ( NPCS.NPC->client->ps.legsAnim == BOTH_ATTACK2 ) { if ( NPCS.NPC->client->ps.legsTimer >= 1200 && NPCS.NPC->client->ps.legsTimer <= 1350 ) { if ( Q_irand( 0, 2 ) ) { Rancor_Swing( qfalse ); } else { Rancor_Swing( qtrue ); } } else if ( NPCS.NPC->client->ps.legsTimer >= 1100 && NPCS.NPC->client->ps.legsTimer <= 1550 ) { Rancor_Swing( qtrue ); } } // Just using this to remove the attacking flag at the right time TIMER_Done2( NPCS.NPC, "attacking", qtrue ); }
static void Howler_Attack( float enemyDist, qboolean howl ) { int dmg = (NPCInfo->localState==LSTATE_BERZERK)?5:2; vec3_t boltOrg; vec3_t fwd; if ( !TIMER_Exists( NPC, "attacking" )) { int attackAnim = BOTH_GESTURE1; // Going to do an attack if ( NPC->enemy && NPC->enemy->client && PM_InKnockDown( &NPC->enemy->client->ps ) && enemyDist <= MIN_DISTANCE ) { attackAnim = BOTH_ATTACK2; } else if ( !Q_irand( 0, 4 ) || howl ) {//howl attack //G_SoundOnEnt( NPC, CHAN_VOICE, "sound/chars/howler/howl.mp3" ); } else if ( enemyDist > MIN_DISTANCE && Q_irand( 0, 1 ) ) {//lunge attack //jump foward vec3_t fwd, yawAng; VectorSet( yawAng, 0, NPC->client->ps.viewangles[YAW], 0 ); AngleVectors( yawAng, fwd, NULL, NULL ); VectorScale( fwd, (enemyDist*3.0f), NPC->client->ps.velocity ); NPC->client->ps.velocity[2] = 200; NPC->client->ps.groundEntityNum = ENTITYNUM_NONE; attackAnim = BOTH_ATTACK1; } else {//tongue attack attackAnim = BOTH_ATTACK2; } NPC_SetAnim( NPC, SETANIM_BOTH, attackAnim, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD | SETANIM_FLAG_RESTART ); if ( NPCInfo->localState == LSTATE_BERZERK ) {//attack again right away TIMER_Set( NPC, "attacking", NPC->client->ps.legsTimer ); } else { TIMER_Set( NPC, "attacking", NPC->client->ps.legsTimer + Q_irand( 0, 1500 ) );//FIXME: base on skill TIMER_Set( NPC, "standing", -level.time ); TIMER_Set( NPC, "walking", -level.time ); TIMER_Set( NPC, "running", NPC->client->ps.legsTimer + 5000 ); } TIMER_Set( NPC, "attack_dmg", 200 ); // level two damage } // Need to do delayed damage since the attack animations encapsulate multiple mini-attacks switch ( NPC->client->ps.legsAnim ) { case BOTH_ATTACK1: case BOTH_MELEE1: if ( NPC->client->ps.legsTimer > 650//more than 13 frames left && BG_AnimLength( NPC->localAnimIndex, (animNumber_t)NPC->client->ps.legsAnim ) - NPC->client->ps.legsTimer >= 800 )//at least 16 frames into anim { Howler_TryDamage( dmg, qfalse, qfalse ); } break; case BOTH_ATTACK2: case BOTH_MELEE2: if ( NPC->client->ps.legsTimer > 350//more than 7 frames left && BG_AnimLength( NPC->localAnimIndex, (animNumber_t)NPC->client->ps.legsAnim ) - NPC->client->ps.legsTimer >= 550 )//at least 11 frames into anim { Howler_TryDamage( dmg, qtrue, qfalse ); } break; case BOTH_GESTURE1: { if ( NPC->client->ps.legsTimer > 1800//more than 36 frames left && BG_AnimLength( NPC->localAnimIndex, (animNumber_t)NPC->client->ps.legsAnim ) - NPC->client->ps.legsTimer >= 950 )//at least 19 frames into anim { Howler_Howl(); if ( !NPC->count ) { //RAFIXME - this probably won't work correctly. G_GetBoltPosition(NPC, NPC->NPC->genericBolt1, boltOrg, 0); AngleVectors( NPC->client->ps.viewangles, fwd, NULL, NULL ); G_PlayEffectID( G_EffectIndex( "howler/sonic" ), boltOrg, fwd); //G_PlayEffect( G_EffectIndex( "howler/sonic" ), NPC->ghoul2, NPC->NPC->genericBolt1, NPC->s.number, NPC->currentOrigin, 4750, qtrue ); G_SoundOnEnt( NPC, CHAN_VOICE, "sound/chars/howler/howl.mp3" ); NPC->count = 1; } } } break; default: //anims seem to get reset after a load, so just stop attacking and it will restart as needed. TIMER_Remove( NPC, "attacking" ); break; } // Just using this to remove the attacking flag at the right time TIMER_Done2( NPC, "attacking", qtrue ); }
void G_KickSomeMofos(gentity_t *ent) { vec3_t kickDir, kickEnd, fwdAngs; float animLength = BG_AnimLength( ent->localAnimIndex, (animNumber_t)ent->client->ps.legsAnim ); float elapsedTime = (float)(animLength-ent->client->ps.legsTimer); float remainingTime = (animLength-elapsedTime); float kickDist = (ent->r.maxs[0]*1.5f)+STAFF_KICK_RANGE+8.0f;//fudge factor of 8 int kickDamage = Q_irand(10, 15);//Q_irand( 3, 8 ); //since it can only hit a guy once now int kickPush = flrand( 50.0f, 100.0f ); qboolean doKick = qfalse; renderInfo_t *ri = &ent->client->renderInfo; VectorSet(kickDir, 0.0f, 0.0f, 0.0f); VectorSet(kickEnd, 0.0f, 0.0f, 0.0f); VectorSet(fwdAngs, 0.0f, ent->client->ps.viewangles[YAW], 0.0f); //HMM... or maybe trace from origin to footRBolt/footLBolt? Which one? G2 trace? Will do hitLoc, if so... if ( ent->client->ps.torsoAnim == BOTH_A7_HILT ) { if ( elapsedTime >= 250 && remainingTime >= 250 ) {//front doKick = qtrue; if ( ri->handRBolt != -1 ) {//actually trace to a bolt G_GetBoltPosition( ent, ri->handRBolt, kickEnd, 0 ); VectorSubtract( kickEnd, ent->client->ps.origin, kickDir ); kickDir[2] = 0;//ah, flatten it, I guess... VectorNormalize( kickDir ); } else {//guess AngleVectors( fwdAngs, kickDir, NULL, NULL ); } } } else { switch ( ent->client->ps.legsAnim ) { case BOTH_GETUP_BROLL_B: case BOTH_GETUP_BROLL_F: case BOTH_GETUP_FROLL_B: case BOTH_GETUP_FROLL_F: if ( elapsedTime >= 250 && remainingTime >= 250 ) {//front doKick = qtrue; if ( ri->footRBolt != -1 ) {//actually trace to a bolt G_GetBoltPosition( ent, ri->footRBolt, kickEnd, 0 ); VectorSubtract( kickEnd, ent->client->ps.origin, kickDir ); kickDir[2] = 0;//ah, flatten it, I guess... VectorNormalize( kickDir ); } else {//guess AngleVectors( fwdAngs, kickDir, NULL, NULL ); } } break; case BOTH_A7_KICK_F_AIR: case BOTH_A7_KICK_B_AIR: case BOTH_A7_KICK_R_AIR: case BOTH_A7_KICK_L_AIR: if ( elapsedTime >= 100 && remainingTime >= 250 ) {//air doKick = qtrue; if ( ri->footRBolt != -1 ) {//actually trace to a bolt G_GetBoltPosition( ent, ri->footRBolt, kickEnd, 0 ); VectorSubtract( kickEnd, ent->r.currentOrigin, kickDir ); kickDir[2] = 0;//ah, flatten it, I guess... VectorNormalize( kickDir ); } else {//guess AngleVectors( fwdAngs, kickDir, NULL, NULL ); } } break; case BOTH_A7_KICK_F: //FIXME: push forward? if ( elapsedTime >= 250 && remainingTime >= 250 ) {//front doKick = qtrue; if ( ri->footRBolt != -1 ) {//actually trace to a bolt G_GetBoltPosition( ent, ri->footRBolt, kickEnd, 0 ); VectorSubtract( kickEnd, ent->r.currentOrigin, kickDir ); kickDir[2] = 0;//ah, flatten it, I guess... VectorNormalize( kickDir ); } else {//guess AngleVectors( fwdAngs, kickDir, NULL, NULL ); } } break; case BOTH_A7_KICK_B: //FIXME: push back? if ( elapsedTime >= 250 && remainingTime >= 250 ) {//back doKick = qtrue; if ( ri->footRBolt != -1 ) {//actually trace to a bolt G_GetBoltPosition( ent, ri->footRBolt, kickEnd, 0 ); VectorSubtract( kickEnd, ent->r.currentOrigin, kickDir ); kickDir[2] = 0;//ah, flatten it, I guess... VectorNormalize( kickDir ); } else {//guess AngleVectors( fwdAngs, kickDir, NULL, NULL ); VectorScale( kickDir, -1, kickDir ); } } break; case BOTH_A7_KICK_R: //FIXME: push right? if ( elapsedTime >= 250 && remainingTime >= 250 ) {//right doKick = qtrue; if ( ri->footRBolt != -1 ) {//actually trace to a bolt G_GetBoltPosition( ent, ri->footRBolt, kickEnd, 0 ); VectorSubtract( kickEnd, ent->r.currentOrigin, kickDir ); kickDir[2] = 0;//ah, flatten it, I guess... VectorNormalize( kickDir ); } else {//guess AngleVectors( fwdAngs, NULL, kickDir, NULL ); } } break; case BOTH_A7_KICK_L: //FIXME: push left? if ( elapsedTime >= 250 && remainingTime >= 250 ) {//left doKick = qtrue; if ( ri->footLBolt != -1 ) {//actually trace to a bolt G_GetBoltPosition( ent, ri->footLBolt, kickEnd, 0 ); VectorSubtract( kickEnd, ent->r.currentOrigin, kickDir ); kickDir[2] = 0;//ah, flatten it, I guess... VectorNormalize( kickDir ); } else {//guess AngleVectors( fwdAngs, NULL, kickDir, NULL ); VectorScale( kickDir, -1, kickDir ); } } break; case BOTH_A7_KICK_S: kickPush = flrand( 75.0f, 125.0f ); if ( ri->footRBolt != -1 ) {//actually trace to a bolt if ( elapsedTime >= 550 && elapsedTime <= 1050 ) { doKick = qtrue; G_GetBoltPosition( ent, ri->footRBolt, kickEnd, 0 ); VectorSubtract( kickEnd, ent->r.currentOrigin, kickDir ); kickDir[2] = 0;//ah, flatten it, I guess... VectorNormalize( kickDir ); //NOTE: have to fudge this a little because it's not getting enough range with the anim as-is VectorMA( kickEnd, 8.0f, kickDir, kickEnd ); } } else {//guess if ( elapsedTime >= 400 && elapsedTime < 500 ) {//front doKick = qtrue; AngleVectors( fwdAngs, kickDir, NULL, NULL ); } else if ( elapsedTime >= 500 && elapsedTime < 600 ) {//front-right? doKick = qtrue; fwdAngs[YAW] += 45; AngleVectors( fwdAngs, kickDir, NULL, NULL ); } else if ( elapsedTime >= 600 && elapsedTime < 700 ) {//right doKick = qtrue; AngleVectors( fwdAngs, NULL, kickDir, NULL ); } else if ( elapsedTime >= 700 && elapsedTime < 800 ) {//back-right? doKick = qtrue; fwdAngs[YAW] += 45; AngleVectors( fwdAngs, NULL, kickDir, NULL ); } else if ( elapsedTime >= 800 && elapsedTime < 900 ) {//back doKick = qtrue; AngleVectors( fwdAngs, kickDir, NULL, NULL ); VectorScale( kickDir, -1, kickDir ); } else if ( elapsedTime >= 900 && elapsedTime < 1000 ) {//back-left? doKick = qtrue; fwdAngs[YAW] += 45; AngleVectors( fwdAngs, kickDir, NULL, NULL ); } else if ( elapsedTime >= 1000 && elapsedTime < 1100 ) {//left doKick = qtrue; AngleVectors( fwdAngs, NULL, kickDir, NULL ); VectorScale( kickDir, -1, kickDir ); } else if ( elapsedTime >= 1100 && elapsedTime < 1200 ) {//front-left? doKick = qtrue; fwdAngs[YAW] += 45; AngleVectors( fwdAngs, NULL, kickDir, NULL ); VectorScale( kickDir, -1, kickDir ); } } break; case BOTH_A7_KICK_BF: kickPush = flrand( 75.0f, 125.0f ); kickDist += 20.0f; if ( elapsedTime < 1500 ) {//auto-aim! // overridAngles = PM_AdjustAnglesForBFKick( ent, ucmd, fwdAngs, qboolean(elapsedTime<850) )?qtrue:overridAngles; //FIXME: if we haven't done the back kick yet and there's no-one there to // kick anymore, go into some anim that returns us to our base stance } if ( ri->footRBolt != -1 ) {//actually trace to a bolt if ( ( elapsedTime >= 750 && elapsedTime < 850 ) || ( elapsedTime >= 1400 && elapsedTime < 1500 ) ) {//right, though either would do doKick = qtrue; G_GetBoltPosition( ent, ri->footRBolt, kickEnd, 0 ); VectorSubtract( kickEnd, ent->r.currentOrigin, kickDir ); kickDir[2] = 0;//ah, flatten it, I guess... VectorNormalize( kickDir ); //NOTE: have to fudge this a little because it's not getting enough range with the anim as-is VectorMA( kickEnd, 8, kickDir, kickEnd ); } } else {//guess if ( elapsedTime >= 250 && elapsedTime < 350 ) {//front doKick = qtrue; AngleVectors( fwdAngs, kickDir, NULL, NULL ); } else if ( elapsedTime >= 350 && elapsedTime < 450 ) {//back doKick = qtrue; AngleVectors( fwdAngs, kickDir, NULL, NULL ); VectorScale( kickDir, -1, kickDir ); } } break; case BOTH_A7_KICK_RL: kickPush = flrand( 75.0f, 125.0f ); kickDist += 10.0f; //ok, I'm tracing constantly on these things, they NEVER hit otherwise (in MP at least) //FIXME: auto aim at enemies on the side of us? //overridAngles = PM_AdjustAnglesForRLKick( ent, ucmd, fwdAngs, qboolean(elapsedTime<850) )?qtrue:overridAngles; //if ( elapsedTime >= 250 && elapsedTime < 350 ) if (level.framenum&1) {//right doKick = qtrue; if ( ri->footRBolt != -1 ) {//actually trace to a bolt G_GetBoltPosition( ent, ri->footRBolt, kickEnd, 0 ); VectorSubtract( kickEnd, ent->r.currentOrigin, kickDir ); kickDir[2] = 0;//ah, flatten it, I guess... VectorNormalize( kickDir ); //NOTE: have to fudge this a little because it's not getting enough range with the anim as-is VectorMA( kickEnd, 8, kickDir, kickEnd ); } else {//guess AngleVectors( fwdAngs, NULL, kickDir, NULL ); } } //else if ( elapsedTime >= 350 && elapsedTime < 450 ) else {//left doKick = qtrue; if ( ri->footLBolt != -1 ) {//actually trace to a bolt G_GetBoltPosition( ent, ri->footLBolt, kickEnd, 0 ); VectorSubtract( kickEnd, ent->r.currentOrigin, kickDir ); kickDir[2] = 0;//ah, flatten it, I guess... VectorNormalize( kickDir ); //NOTE: have to fudge this a little because it's not getting enough range with the anim as-is VectorMA( kickEnd, 8, kickDir, kickEnd ); } else {//guess AngleVectors( fwdAngs, NULL, kickDir, NULL ); VectorScale( kickDir, -1, kickDir ); } } break; } } if ( doKick ) { // G_KickTrace( ent, kickDir, kickDist, kickEnd, kickDamage, kickPush ); G_KickTrace( ent, kickDir, kickDist, NULL, kickDamage, kickPush ); } }