//--------------------------------------------------------- void MineMonster_TryDamage( gentity_t *enemy, int damage ) { vec3_t end, dir; trace_t tr; if ( !enemy ) { return; } AngleVectors( NPC->client->ps.viewangles, dir, NULL, NULL ); VectorMA( NPC->currentOrigin, MIN_DISTANCE, dir, end ); // Should probably trace from the mouth, but, ah well. gi.trace( &tr, NPC->currentOrigin, vec3_origin, vec3_origin, end, NPC->s.number, MASK_SHOT, (EG2_Collision)0, 0 ); if ( tr.entityNum >= 0 && tr.entityNum < ENTITYNUM_NONE ) { G_Damage( &g_entities[tr.entityNum], NPC, NPC, dir, tr.endpos, damage, DAMAGE_NO_KNOCKBACK, MOD_MELEE ); G_SoundOnEnt( NPC, CHAN_VOICE_ATTEN, va("sound/chars/mine/misc/bite%i.wav", Q_irand(1,4))); } else { G_SoundOnEnt( NPC, CHAN_VOICE_ATTEN, va("sound/chars/mine/misc/miss%i.wav", Q_irand(1,4))); } }
void G_DroidSounds( gentity_t *self ) { if ( self->client ) {//make the noises if ( TIMER_Done( self, "patrolNoise" ) && !Q_irand( 0, 20 ) ) { switch( self->client->NPC_class ) { case CLASS_R2D2: // droid G_SoundOnEnt(self, CHAN_AUTO, va("sound/chars/r2d2/misc/r2d2talk0%d.wav",Q_irand(1, 3)) ); break; case CLASS_R5D2: // droid G_SoundOnEnt(self, CHAN_AUTO, va("sound/chars/r5d2/misc/r5talk%d.wav",Q_irand(1, 4)) ); break; case CLASS_PROBE: // droid G_SoundOnEnt(self, CHAN_AUTO, va("sound/chars/probe/misc/probetalk%d.wav",Q_irand(1, 3)) ); break; case CLASS_MOUSE: // droid G_SoundOnEnt(self, CHAN_AUTO, va("sound/chars/mouse/misc/mousego%d.wav",Q_irand(1, 3)) ); break; case CLASS_GONK: // droid G_SoundOnEnt(self, CHAN_AUTO, va("sound/chars/gonk/misc/gonktalk%d.wav",Q_irand(1, 2)) ); break; default: break; } TIMER_Set( self, "patrolNoise", Q_irand( 2000, 4000 ) ); } } }
void ImperialProbe_Patrol( void ) { ImperialProbe_MaintainHeight(); if ( NPC_CheckPlayerTeamStealth() ) { NPC_UpdateAngles( qtrue, qtrue ); return; } //If we have somewhere to go, then do that if ( !NPC->enemy ) { NPC_SetAnim( NPC, SETANIM_BOTH, BOTH_RUN1, SETANIM_FLAG_NORMAL ); if ( UpdateGoal() ) { //start loop sound once we move NPC->s.loopSound = G_SoundIndex( "sound/chars/probe/misc/probedroidloop" ); ucmd.buttons |= BUTTON_WALKING; NPC_MoveToGoal( qtrue ); } //randomly talk if ( TIMER_Done( NPC, "patrolNoise" ) ) { G_SoundOnEnt( NPC, CHAN_AUTO, va( "sound/chars/probe/misc/probetalk%d", Q_irand( 1, 3 ) ) ); TIMER_Set( NPC, "patrolNoise", Q_irand( 2000, 4000 ) ); } } else // He's got an enemy. Make him angry. { G_SoundOnEnt( NPC, CHAN_AUTO, "sound/chars/probe/misc/anger1" ); TIMER_Set( NPC, "angerNoise", Q_irand( 2000, 4000 ) ); //NPCInfo->behaviorState = BS_HUNT_AND_KILL; } NPC_UpdateAngles( qtrue, qtrue ); }
void Droid_Patrol( void ) { NPC->pos1.yaw = AngleNormalize360( NPC->pos1.yaw ); if ( NPC->client && NPC->client->NPC_class != CLASS_GONK ) { if ( NPC->client->NPC_class != CLASS_R5D2 ) { //he doesn't have an eye. R2D2_PartsMove(); // Get his eye moving. } R2D2_TurnAnims(); } //If we have somewhere to go, then do that if ( UpdateGoal() ) { ucmd.buttons |= BUTTON_WALKING; NPC_MoveToGoal( qtrue ); if ( NPC->client && NPC->client->NPC_class == CLASS_MOUSE ) { NPCInfo->desiredYaw += sinf( level.time*.5f ) * 25; // Weaves side to side a little if ( TIMER_Done( NPC, "patrolNoise" ) ) { G_SoundOnEnt( NPC, CHAN_AUTO, va( "sound/chars/mouse/misc/mousego%d.wav", Q_irand( 1, 3 ) ) ); TIMER_Set( NPC, "patrolNoise", Q_irand( 2000, 4000 ) ); } } else if ( NPC->client && NPC->client->NPC_class == CLASS_R2D2 ) { if ( TIMER_Done( NPC, "patrolNoise" ) ) { G_SoundOnEnt( NPC, CHAN_AUTO, va( "sound/chars/r2d2/misc/r2d2talk0%d.wav", Q_irand( 1, 3 ) ) ); TIMER_Set( NPC, "patrolNoise", Q_irand( 2000, 4000 ) ); } } else if ( NPC->client && NPC->client->NPC_class == CLASS_R5D2 ) { if ( TIMER_Done( NPC, "patrolNoise" ) ) { G_SoundOnEnt( NPC, CHAN_AUTO, va( "sound/chars/r5d2/misc/r5talk%d.wav", Q_irand( 1, 4 ) ) ); TIMER_Set( NPC, "patrolNoise", Q_irand( 2000, 4000 ) ); } } if ( NPC->client && NPC->client->NPC_class == CLASS_GONK ) { if ( TIMER_Done( NPC, "patrolNoise" ) ) { G_SoundOnEnt( NPC, CHAN_AUTO, va( "sound/chars/gonk/misc/gonktalk%d.wav", Q_irand( 1, 2 ) ) ); TIMER_Set( NPC, "patrolNoise", Q_irand( 2000, 4000 ) ); } } // else // { // R5D2_LookAround(); // } } NPC_UpdateAngles( qtrue, qtrue ); }
void G_ATSTCheckPain( gentity_t *self, gentity_t *other, int damage ) { //int newBolt; //int hitLoc = gPainHitLoc; if ( rand() & 1 ) { G_SoundOnEnt( self, CHAN_LESS_ATTEN, "sound/chars/atst/atst_damaged1" ); } else { G_SoundOnEnt( self, CHAN_LESS_ATTEN, "sound/chars/atst/atst_damaged2" ); } }
void G_ATSTCheckPain( gentity_t *self, gentity_t *other, int damage ) { //int newBolt; //int hitLoc = gPainHitLoc; if ( rand() & 1 ) { G_SoundOnEnt( self, CHAN_LESS_ATTEN, "sound/chars/atst/atst_damaged1" ); } else { G_SoundOnEnt( self, CHAN_LESS_ATTEN, "sound/chars/atst/atst_damaged2" ); } /* if ((hitLoc==HL_ARM_LT) && (self->locationDamage[HL_ARM_LT] > LEFT_ARM_HEALTH)) { if (self->locationDamage[hitLoc] >= LEFT_ARM_HEALTH) // Blow it up? { newBolt = trap_G2API_AddBolt( self->ghoul2, 0, "*flash3" ); if ( newBolt != -1 ) { // G_PlayEffect( "small_chunks", self->playerModel, self->genericBolt1, self->s.number); ATST_PlayEffect( self, trap_G2API_AddBolt(self->ghoul2, 0, "*flash3"), "env/med_explode2" ); //G_PlayEffectID( G_EffectIndex("blaster/smoke_bolton"), self->playerModel, newBolt, self->s.number); //Maybe bother with this some other time. } NPC_SetSurfaceOnOff( self, "head_light_blaster_cann", TURN_OFF ); } } else if ((hitLoc==HL_ARM_RT) && (self->locationDamage[HL_ARM_RT] > RIGHT_ARM_HEALTH)) // Blow it up? { if (self->locationDamage[hitLoc] >= RIGHT_ARM_HEALTH) { newBolt = trap_G2API_AddBolt( self->ghoul2, 0, "*flash4" ); if ( newBolt != -1 ) { // G_PlayEffect( "small_chunks", self->playerModel, self->genericBolt2, self->s.number); ATST_PlayEffect( self, trap_G2API_AddBolt(self->ghoul2, 0, "*flash4"), "env/med_explode2" ); //G_PlayEffect( "blaster/smoke_bolton", self->playerModel, newBolt, self->s.number); } NPC_SetSurfaceOnOff( self, "head_concussion_charger", TURN_OFF ); } } */ }
void RT_FlyStop( gentity_t *self ) { self->client->ps.gravity = g_gravity->value; self->svFlags &= ~SVF_CUSTOM_GRAVITY; self->client->moveType = MT_RUNJUMP; //Stop the effect self->client->jetPackTime = 0; if ( self->genericBolt1 != -1 ) { G_StopEffect("rockettrooper/flameNEW", self->playerModel, self->genericBolt1, self->s.number ); } if ( self->genericBolt2 != -1 ) { G_StopEffect("rockettrooper/flameNEW", self->playerModel, self->genericBolt2, self->s.number ); } //stop jet loop sound self->s.loopSound = 0; G_SoundOnEnt( self, CHAN_ITEM, "sound/chars/boba/bf_land.wav" ); if ( self->NPC ) { self->count = 0; // SEEKER shot ammo count TIMER_Set( self, "jetRecharge", Q_irand( 1000, 5000 ) ); TIMER_Set( self, "jumpChaseDebounce", Q_irand( 500, 2000 ) ); } }
/* ------------------------- NPC_Sentry_Patrol ------------------------- */ void NPC_Sentry_Patrol( void ) { Sentry_MaintainHeight(); //If we have somewhere to go, then do that if ( !NPC->enemy ) { if ( NPC_CheckPlayerTeamStealth() ) { //NPC_AngerSound(); NPC_UpdateAngles( qtrue, qtrue ); return; } if ( UpdateGoal() ) { //start loop sound once we move ucmd.buttons |= BUTTON_WALKING; NPC_MoveToGoal( qtrue ); } //randomly talk if ( TIMER_Done( NPC, "patrolNoise" ) ) { G_SoundOnEnt( NPC, CHAN_AUTO, va( "sound/chars/sentry/misc/talk%d", Q_irand( 1, 3 ) ) ); TIMER_Set( NPC, "patrolNoise", Q_irand( 2000, 4000 ) ); } } NPC_UpdateAngles( qtrue, qtrue ); }
void Boba_FlyStart( gentity_t *self ) {//switch to seeker AI for a while if ( TIMER_Done( self, "jetRecharge" ) && !Boba_Flying( self ) ) { self->client->ps.gravity = 0; self->svFlags |= SVF_CUSTOM_GRAVITY; self->client->moveType = MT_FLYSWIM; //start jet effect self->client->jetPackTime = level.time + Q_irand( 3000, 10000 ); if ( self->genericBolt1 != -1 ) { G_PlayEffect( G_EffectIndex( "boba/jetSP" ), self->playerModel, self->genericBolt1, self->s.number, self->currentOrigin, qtrue, qtrue ); } if ( self->genericBolt2 != -1 ) { G_PlayEffect( G_EffectIndex( "boba/jetSP" ), self->playerModel, self->genericBolt2, self->s.number, self->currentOrigin, qtrue, qtrue ); } //take-off sound G_SoundOnEnt( self, CHAN_ITEM, "sound/chars/boba/bf_blast-off.wav" ); //jet loop sound self->s.loopSound = G_SoundIndex( "sound/chars/boba/bf_jetpack_lp.wav" ); if ( self->NPC ) { self->count = Q3_INFINITE; // SEEKER shot ammo count } } }
void RT_FlyStart( gentity_t *self ) {//switch to seeker AI for a while if ( TIMER_Done( self, "jetRecharge" ) && !RT_Flying( self ) ) { self->client->ps.gravity = 0; self->svFlags |= SVF_CUSTOM_GRAVITY; self->client->moveType = MT_FLYSWIM; //Inform NPC_HandleAIFlags we want to fly self->NPC->aiFlags |= NPCAI_FLY; self->lastInAirTime = level.time; //start jet effect self->client->jetPackTime = Q3_INFINITE; if ( self->genericBolt1 != -1 ) { G_PlayEffect( G_EffectIndex( "rockettrooper/flameNEW" ), self->playerModel, self->genericBolt1, self->s.number, self->currentOrigin, qtrue, qtrue ); } if ( self->genericBolt2 != -1 ) { G_PlayEffect( G_EffectIndex( "rockettrooper/flameNEW" ), self->playerModel, self->genericBolt2, self->s.number, self->currentOrigin, qtrue, qtrue ); } //take-off sound G_SoundOnEnt( self, CHAN_ITEM, "sound/chars/boba/bf_blast-off.wav" ); //jet loop sound self->s.loopSound = G_SoundIndex( "sound/chars/boba/bf_jetpack_lp.wav" ); if ( self->NPC ) { self->count = Q3_INFINITE; // SEEKER shot ammo count } } }
void Boba_DoFlameThrower( gentity_t *self ) { if ( self->s.number < MAX_CLIENTS ) { if ( self->client ) { if ( !self->client->ps.forcePowerDuration[FP_LIGHTNING] ) { NPC_SetAnim( self, SETANIM_TORSO, BOTH_FORCELIGHTNING_HOLD, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD ); self->client->ps.torsoAnimTimer = BOBA_FLAMEDURATION; G_SoundOnEnt( self, CHAN_WEAPON, "sound/weapons/boba/bf_flame.mp3" ); G_PlayEffect( G_EffectIndex("boba/fthrw"), self->playerModel, self->genericBolt3, self->s.number, self->s.origin, 1 ); self->client->ps.forcePowerDuration[FP_LIGHTNING] = 1; } Boba_FireFlameThrower( self ); } return; } if (!(NPCInfo->aiFlags&NPCAI_FLAMETHROW) && TIMER_Done(self, "nextAttackDelay")) { Boba_StartFlameThrower( self ); } if ( (NPCInfo->aiFlags&NPCAI_FLAMETHROW)) { Boba_FireFlameThrower( self ); } }
/* ------------------------- Sentry_RangedAttack ------------------------- */ void Sentry_RangedAttack( qboolean visible, qboolean advance ) { if ( TIMER_Done( NPC, "attackDelay" ) && NPC->attackDebounceTime < level.time && visible ) // Attack? { if ( NPCInfo->burstCount > 6 ) { if ( !NPC->fly_sound_debounce_time ) {//delay closing down to give the player an opening NPC->fly_sound_debounce_time = level.time + Q_irand( 500, 2000 ); } else if ( NPC->fly_sound_debounce_time < level.time ) { NPCInfo->localState = LSTATE_ACTIVE; NPC->fly_sound_debounce_time = NPCInfo->burstCount = 0; TIMER_Set( NPC, "attackDelay", Q_irand( 2000, 3500 ) ); NPC->flags |= FL_SHIELDED; NPC_SetAnim( NPC, SETANIM_BOTH, BOTH_FLY_SHIELDED, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD ); G_SoundOnEnt( NPC, CHAN_AUTO, "sound/chars/sentry/misc/sentry_shield_close" ); } } else { Sentry_Fire(); } } if ( NPCInfo->scriptFlags & SCF_CHASE_ENEMIES ) { Sentry_Hunt( visible, advance ); } }
/* ------------------------- NPC_Sentry_Pain ------------------------- */ void NPC_Sentry_Pain( gentity_t *self, gentity_t *inflictor, gentity_t *other, vec3_t point, int damage, int mod,int hitLoc ) { NPC_Pain( self, inflictor, other, point, damage, mod ); if ( mod == MOD_DEMP2 || mod == MOD_DEMP2_ALT ) { self->NPC->burstCount = 0; TIMER_Set( self, "attackDelay", Q_irand( 9000, 12000) ); self->flags |= FL_SHIELDED; NPC_SetAnim( self, SETANIM_BOTH, BOTH_FLY_SHIELDED, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD ); G_SoundOnEnt( self, CHAN_AUTO, "sound/chars/sentry/misc/sentry_pain" ); self->NPC->localState = LSTATE_ACTIVE; } // You got hit, go after the enemy // if (self->NPC->localState == LSTATE_ASLEEP) // { // G_Sound( self, G_SoundIndex("sound/chars/sentry/misc/shieldsopen.wav")); // // self->flags &= ~FL_SHIELDED; // NPC_SetAnim( self, SETANIM_BOTH, BOTH_POWERUP1, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD ); // self->NPC->localState = LSTATE_WAKEUP; // } }
void G_ATSTCheckPain( gentity_t *self, gentity_t *other, const vec3_t point, int damage, int mod,int hitLoc ) { int newBolt; if ( rand() & 1 ) { G_SoundOnEnt( self, CHAN_LESS_ATTEN, "sound/chars/atst/atst_damaged1" ); } else { G_SoundOnEnt( self, CHAN_LESS_ATTEN, "sound/chars/atst/atst_damaged2" ); } if ((hitLoc==HL_ARM_LT) && (self->locationDamage[HL_ARM_LT] > LEFT_ARM_HEALTH)) { if (self->locationDamage[hitLoc] >= LEFT_ARM_HEALTH) // Blow it up? { newBolt = gi.G2API_AddBolt( &self->ghoul2[self->playerModel], "*flash3" ); if ( newBolt != -1 ) { // G_PlayEffect( "small_chunks", self->playerModel, self->genericBolt1, self->s.number); ATST_PlayEffect( self, self->genericBolt1, "env/med_explode2" ); G_PlayEffect( G_EffectIndex("blaster/smoke_bolton"), self->playerModel, newBolt, self->s.number, point); } gi.G2API_SetSurfaceOnOff( &self->ghoul2[self->playerModel], "head_light_blaster_cann", TURN_OFF ); } } else if ((hitLoc==HL_ARM_RT) && (self->locationDamage[HL_ARM_RT] > RIGHT_ARM_HEALTH)) // Blow it up? { if (self->locationDamage[hitLoc] >= RIGHT_ARM_HEALTH) { newBolt = gi.G2API_AddBolt( &self->ghoul2[self->playerModel], "*flash4" ); if ( newBolt != -1 ) { // G_PlayEffect( "small_chunks", self->playerModel, self->genericBolt2, self->s.number); ATST_PlayEffect( self, self->genericBolt2, "env/med_explode2" ); G_PlayEffect( G_EffectIndex("blaster/smoke_bolton"), self->playerModel, newBolt, self->s.number, point); } gi.G2API_SetSurfaceOnOff( &self->ghoul2[self->playerModel], "head_concussion_charger", TURN_OFF ); } } }
/* ------------------------- Sentry_AttackDecision ------------------------- */ void Sentry_AttackDecision( void ) { float distance; qboolean visible; qboolean advance; // Always keep a good height off the ground Sentry_MaintainHeight(); NPC->s.loopSound = G_SoundIndex( "sound/chars/sentry/misc/sentry_hover_2_lp" ); //randomly talk if ( TIMER_Done(NPC,"patrolNoise") ) { if (TIMER_Done(NPC,"angerNoise")) { G_SoundOnEnt( NPC, CHAN_AUTO, va("sound/chars/sentry/misc/talk%d", Q_irand(1, 3)) ); TIMER_Set( NPC, "patrolNoise", Q_irand( 4000, 10000 ) ); } } // He's dead. if (NPC->enemy->health<1) { NPC->enemy = NULL; Sentry_Idle(); return; } // If we don't have an enemy, just idle if ( NPC_CheckEnemyExt(qfalse) == qfalse ) { Sentry_Idle(); return; } // Rate our distance to the target and visibilty distance = (int) DistanceHorizontalSquared( NPC->r.currentOrigin, NPC->enemy->r.currentOrigin ); visible = NPC_ClearLOS4( NPC->enemy ); advance = (qboolean)(distance > MIN_DISTANCE_SQR); // If we cannot see our target, move to see it if ( visible == qfalse ) { if ( NPCInfo->scriptFlags & SCF_CHASE_ENEMIES ) { Sentry_Hunt( visible, advance ); return; } } NPC_FaceEnemy( qtrue ); Sentry_RangedAttack( visible, advance ); }
void G_Victory( gentity_t *ent ) { if ( ent->health > 0 ) {//say something and put away saber G_SoundOnEnt( ent, CHAN_VOICE, "sound/chars/kyle/misc/taunt1.wav" ); if ( ent->client ) { ent->client->ps.saberActive = qfalse; } } }
void Interrogator_Idle( void ) { if ( NPC_CheckPlayerTeamStealth() ) { G_SoundOnEnt( NPC, CHAN_AUTO, "sound/chars/mark1/misc/anger.wav" ); NPC_UpdateAngles( qtrue, qtrue ); return; } Interrogator_MaintainHeight(); NPC_BSIdle(); }
static qboolean Hirogen_Speak( void ) { //Make sure we haven't already tried to say the line if ( NPCInfo->squadState ) return qfalse; switch ( NPCInfo->localState ) { case 0: G_SoundOnEnt( NPC, CHAN_VOICE, alphaSpeech[0] ); TIMER_Set( NPC, "speech", 2500 ); break; case 1: G_SoundOnEnt( NPC, CHAN_VOICE, alphaSpeech[1] ); TIMER_Set( NPC, "speech", 2500 ); break; case 3: G_SoundOnEnt( NPC, CHAN_VOICE, alphaSpeech[2] ); TIMER_Set( NPC, "speech", 2500 ); break; case 5: G_SoundOnEnt( NPC, CHAN_VOICE, alphaSpeech[3] ); TIMER_Set( NPC, "speech", 2500 ); break; case 7: G_SoundOnEnt( NPC, CHAN_VOICE, alphaSpeech[4] ); TIMER_Set( NPC, "speech", 2500 ); break; default: return qfalse; break; } NPCInfo->squadState = 1; return qtrue; }
void NPC_GM_StartLaser( void ) { if ( !NPC->lockCount ) {//haven't already started a laser attack //warm up for the beam attack TIMER_Set( NPC, "beamDelay", NPC->client->ps.torsoTimer ); TIMER_Set( NPC, "attackDelay", NPC->client->ps.torsoTimer+3000 ); NPC->lockCount = 1; //turn on warmup effect G_PlayEffectID( G_EffectIndex("galak/beam_warmup"), NPC->r.currentOrigin, vec3_origin ); G_SoundOnEnt( NPC, CHAN_AUTO, "sound/weapons/galak/lasercharge.wav" ); } }
void NPC_GM_StartLaser( void ) { if ( !NPC->lockCount ) {//haven't already started a laser attack //warm up for the beam attack NPC_SetAnim( NPC, SETANIM_TORSO, TORSO_RAISEWEAP2, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD ); TIMER_Set( NPC, "beamDelay", NPC->client->ps.torsoAnimTimer ); TIMER_Set( NPC, "attackDelay", NPC->client->ps.torsoAnimTimer+3000 ); NPC->lockCount = 1; //turn on warmup effect G_PlayEffect( "galak/beam_warmup", NPC->s.number ); G_SoundOnEnt( NPC, CHAN_AUTO, "sound/weapons/galak/lasercharge.wav" ); } }
void ImperialProbe_AttackDecision( void ) { float distance; qboolean visible; qboolean advance; // Always keep a good height off the ground ImperialProbe_MaintainHeight(); //randomly talk if ( TIMER_Done(NPC,"patrolNoise") ) { if (TIMER_Done(NPC,"angerNoise")) { G_SoundOnEnt( NPC, CHAN_AUTO, va("sound/chars/probe/misc/probetalk%d", Q_irand(1, 3)) ); TIMER_Set( NPC, "patrolNoise", Q_irand( 4000, 10000 ) ); } } // If we don't have an enemy, just idle if ( NPC_CheckEnemyExt(qfalse) == qfalse ) { ImperialProbe_Idle(); return; } NPC_SetAnim( NPC, SETANIM_BOTH, BOTH_RUN1, SETANIM_FLAG_NORMAL); // Rate our distance to the target, and our visibilty distance = (int) DistanceHorizontalSquared( NPC->r.currentOrigin, NPC->enemy->r.currentOrigin ); visible = NPC_ClearLOS4( NPC->enemy ); advance = (qboolean)(distance > MIN_DISTANCE_SQR); // If we cannot see our target, move to see it if ( visible == qfalse ) { if ( NPCInfo->scriptFlags & SCF_CHASE_ENEMIES ) { ImperialProbe_Hunt( visible, advance ); return; } } // Sometimes I have problems with facing the enemy I'm attacking, so force the issue so I don't look dumb NPC_FaceEnemy( qtrue ); // Decide what type of attack to do ImperialProbe_Ranged( visible, advance ); }
void RT_JetPackEffect( int duration ) { if ( NPC->genericBolt1 != -1 ) { G_PlayEffect( G_EffectIndex( "rockettrooper/flameNEW" ), NPC->playerModel, NPC->genericBolt1, NPC->s.number, NPC->currentOrigin, duration, qtrue ); } if ( NPC->genericBolt2 != -1 ) { G_PlayEffect( G_EffectIndex( "rockettrooper/flameNEW" ), NPC->playerModel, NPC->genericBolt2, NPC->s.number, NPC->currentOrigin, duration, qtrue ); } //take-off sound G_SoundOnEnt( NPC, CHAN_ITEM, "sound/chars/boba/bf_blast-off.wav" ); }
/* ------------------------- Interrogator_Attack ------------------------- */ void Interrogator_Attack( void ) { float distance; qboolean visible; qboolean advance; // Always keep a good height off the ground Interrogator_MaintainHeight(); //randomly talk if ( TIMER_Done(NPC,"patrolNoise") ) { if (TIMER_Done(NPC,"angerNoise")) { G_SoundOnEnt( NPC, CHAN_AUTO, va("sound/chars/probe/misc/talk.wav", Q_irand(1, 3)) ); TIMER_Set( NPC, "patrolNoise", Q_irand( 4000, 10000 ) ); } } // If we don't have an enemy, just idle if ( NPC_CheckEnemyExt(qfalse) == qfalse ) { Interrogator_Idle(); return; } // Rate our distance to the target, and our visibilty distance = (int) DistanceHorizontalSquared( NPC->r.currentOrigin, NPC->enemy->r.currentOrigin ); visible = NPC_ClearLOS4( NPC->enemy ); advance = (qboolean)(distance > MIN_DISTANCE*MIN_DISTANCE ); if ( !visible ) { advance = qtrue; } if ( NPCInfo->scriptFlags & SCF_CHASE_ENEMIES ) { Interrogator_Hunt( visible, advance ); } NPC_FaceEnemy( qtrue ); if (!advance) { Interrogator_Melee( visible, advance ); } }
void NPC_GM_StartLaser( void ) { if ( !NPCS.NPC->lockCount ) {//haven't already started a laser attack //warm up for the beam attack #if 0 NPC_SetAnim( NPC, SETANIM_TORSO, TORSO_RAISEWEAP2, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD ); #endif TIMER_Set( NPCS.NPC, "beamDelay", NPCS.NPC->client->ps.torsoTimer ); TIMER_Set( NPCS.NPC, "attackDelay", NPCS.NPC->client->ps.torsoTimer+3000 ); NPCS.NPC->lockCount = 1; //turn on warmup effect G_PlayEffectID( G_EffectIndex("galak/beam_warmup"), NPCS.NPC->r.currentOrigin, vec3_origin ); G_SoundOnEnt( NPCS.NPC, CHAN_AUTO, "sound/weapons/galak/lasercharge.wav" ); } }
void NPC_JumpSound() { if ( NPC->client->NPC_class == CLASS_HOWLER ) { //FIXME: can I delay the actual jump so that it matches the anim...? } else if ( NPC->client->NPC_class == CLASS_BOBAFETT || NPC->client->NPC_class == CLASS_ROCKETTROOPER ) { // does this really need to be here? //RAFIXME - CLASS_ROCKETTROOPER|CLASS_BOBAFETT //JET_FlyStart(NPC); } else { G_SoundOnEnt( NPC, CHAN_BODY, "sound/weapons/force/jump.wav" ); } }
void G_PlayerGuiltDeath( void ) { if ( player && player->client ) {//simulate death player->client->ps.stats[STAT_HEALTH] = 0; //turn off saber if ( player->client->ps.weapon == WP_SABER && player->client->ps.saberActive ) { G_SoundOnEnt( player, CHAN_WEAPON, "sound/weapons/saber/saberoff.wav" ); player->client->ps.saberActive = qfalse; } //play the "what have I done?!" anim NPC_SetAnim( player, SETANIM_BOTH, BOTH_FORCEHEAL_START, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD ); player->client->ps.legsAnimTimer = player->client->ps.torsoAnimTimer = -1; //look at yourself player->client->ps.stats[STAT_DEAD_YAW] = player->client->ps.viewangles[YAW]+180; } }
void Boba_StartFlameThrower( gentity_t *self ) { if (!(NPCInfo->aiFlags&NPCAI_FLAMETHROW)) { NPC_SetAnim( self, SETANIM_TORSO, BOTH_FORCELIGHTNING_HOLD, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD ); self->NPC->aiFlags |= NPCAI_FLAMETHROW; self->client->ps.torsoAnimTimer = BOBA_FLAMEDURATION; TIMER_Set( self, "flameTime", BOBA_FLAMEDURATION); TIMER_Set( self, "nextAttackDelay", BOBA_FLAMEDURATION); TIMER_Set( self, "nextFlameDelay", BOBA_FLAMEDURATION*2); TIMER_Set( self, "Boba_TacticsSelect", BOBA_FLAMEDURATION); G_SoundOnEnt( self, CHAN_WEAPON, "sound/weapons/boba/bf_flame.mp3" ); G_PlayEffect( G_EffectIndex("boba/fthrw"), self->playerModel, self->genericBolt3, self->s.number, self->s.origin, 1 ); Boba_Printf("FlameThrower ON"); } }
/* ================ ItemUse_Bacta ================ */ void ItemUse_Bacta(gentity_t *ent) { if (!ent || !ent->client) { return; } if (ent->health >= ent->client->ps.stats[STAT_MAX_HEALTH] || !ent->client->ps.inventory[INV_BACTA_CANISTER] ) { return; } ent->health += MAX_BACTA_HEAL_AMOUNT; if (ent->health > ent->client->ps.stats[STAT_MAX_HEALTH]) { ent->health = ent->client->ps.stats[STAT_MAX_HEALTH]; } ent->client->ps.inventory[INV_BACTA_CANISTER]--; G_SoundOnEnt( ent, CHAN_VOICE, va( "sound/weapons/force/heal%d_%c.mp3", Q_irand( 1, 4 ), g_sex->string[0] ) ); }
void NPC_BSSniper_Attack( void ) { //Don't do anything if we're hurt if ( NPC->painDebounceTime > level.time ) { NPC_UpdateAngles( qtrue, qtrue ); return; } //NPC_CheckEnemy( qtrue, qfalse ); //If we don't have an enemy, just idle if ( NPC_CheckEnemyExt() == qfalse )//!NPC->enemy )// { NPC->enemy = NULL; NPC_BSSniper_Patrol();//FIXME: or patrol? return; } if ( TIMER_Done( NPC, "flee" ) && NPC_CheckForDanger( NPC_CheckAlertEvents( qtrue, qtrue, -1, qfalse, AEL_DANGER ) ) ) {//going to run NPC_UpdateAngles( qtrue, qtrue ); return; } if ( !NPC->enemy ) {//WTF? somehow we lost our enemy? NPC_BSSniper_Patrol();//FIXME: or patrol? return; } enemyLOS = enemyCS = qfalse; AImove = qtrue; faceEnemy = qfalse; shoot = qfalse; enemyDist = DistanceSquared( NPC->currentOrigin, NPC->enemy->currentOrigin ); if ( enemyDist < 16384 )//128 squared {//too close, so switch to primary fire if ( NPC->client->ps.weapon == WP_DISRUPTOR ) {//sniping... should be assumed if ( NPCInfo->scriptFlags & SCF_ALT_FIRE ) {//use primary fire trace_t trace; gi.trace ( &trace, NPC->enemy->currentOrigin, NPC->enemy->mins, NPC->enemy->maxs, NPC->currentOrigin, NPC->enemy->s.number, NPC->enemy->clipmask, G2_NOCOLLIDE, 0 ); if ( !trace.allsolid && !trace.startsolid && (trace.fraction == 1.0 || trace.entityNum == NPC->s.number ) ) {//he can get right to me NPCInfo->scriptFlags &= ~SCF_ALT_FIRE; //reset fire-timing variables NPC_ChangeWeapon( WP_DISRUPTOR ); NPC_UpdateAngles( qtrue, qtrue ); return; } } //FIXME: switch back if he gets far away again? } } else if ( enemyDist > 65536 )//256 squared { if ( NPC->client->ps.weapon == WP_DISRUPTOR ) {//sniping... should be assumed if ( !(NPCInfo->scriptFlags&SCF_ALT_FIRE) ) {//use primary fire NPCInfo->scriptFlags |= SCF_ALT_FIRE; //reset fire-timing variables NPC_ChangeWeapon( WP_DISRUPTOR ); NPC_UpdateAngles( qtrue, qtrue ); return; } } } Sniper_UpdateEnemyPos(); //can we see our target? if ( NPC_ClearLOS( NPC->enemy ) )//|| (NPCInfo->stats.aim >= 5 && gi.inPVS( NPC->client->renderInfo.eyePoint, NPC->enemy->currentOrigin )) ) { NPCInfo->enemyLastSeenTime = level.time; VectorCopy( NPC->enemy->currentOrigin, NPCInfo->enemyLastSeenLocation ); enemyLOS = qtrue; float maxShootDist = NPC_MaxDistSquaredForWeapon(); if ( enemyDist < maxShootDist ) { vec3_t fwd, right, up, muzzle, end; trace_t tr; AngleVectors( NPC->client->ps.viewangles, fwd, right, up ); CalcMuzzlePoint( NPC, fwd, right, up, muzzle, 0 ); VectorMA( muzzle, 8192, fwd, end ); gi.trace ( &tr, muzzle, NULL, NULL, end, NPC->s.number, MASK_SHOT, G2_RETURNONHIT, 0 ); int hit = tr.entityNum; //can we shoot our target? if ( Sniper_EvaluateShot( hit ) ) { enemyCS = qtrue; } } } /* else if ( gi.inPVS( NPC->enemy->currentOrigin, NPC->currentOrigin ) ) { NPCInfo->enemyLastSeenTime = level.time; faceEnemy = qtrue; } */ if ( enemyLOS ) {//FIXME: no need to face enemy if we're moving to some other goal and he's too far away to shoot? faceEnemy = qtrue; } if ( enemyCS ) { shoot = qtrue; } else if ( level.time - NPCInfo->enemyLastSeenTime > 3000 ) {//Hmm, have to get around this bastard... FIXME: this NPCInfo->enemyLastSeenTime builds up when ducked seems to make them want to run when they uncrouch Sniper_ResolveBlockedShot(); } //Check for movement to take care of Sniper_CheckMoveState(); //See if we should override shooting decision with any special considerations Sniper_CheckFireState(); if ( AImove ) {//move toward goal if ( NPCInfo->goalEntity )//&& ( NPCInfo->goalEntity != NPC->enemy || enemyDist > 10000 ) )//100 squared { AImove = Sniper_Move(); } else { AImove = qfalse; } } if ( !AImove ) { if ( !TIMER_Done( NPC, "duck" ) ) { if ( TIMER_Done( NPC, "watch" ) ) {//not while watching ucmd.upmove = -127; } } //FIXME: what about leaning? //FIXME: also, when stop ducking, start looking, if enemy can see me, chance of ducking back down again } else {//stop ducking! TIMER_Set( NPC, "duck", -1 ); } if ( TIMER_Done( NPC, "duck" ) && TIMER_Done( NPC, "watch" ) && (TIMER_Get( NPC, "attackDelay" )-level.time) > 1000 && NPC->attackDebounceTime < level.time ) { if ( enemyLOS && (NPCInfo->scriptFlags&SCF_ALT_FIRE) ) { if ( NPC->fly_sound_debounce_time < level.time ) { NPC->fly_sound_debounce_time = level.time + 2000; } } } if ( !faceEnemy ) {//we want to face in the dir we're running if ( AImove ) {//don't run away and shoot NPCInfo->desiredYaw = NPCInfo->lastPathAngles[YAW]; NPCInfo->desiredPitch = 0; shoot = qfalse; } NPC_UpdateAngles( qtrue, qtrue ); } else// if ( faceEnemy ) {//face the enemy Sniper_FaceEnemy(); } if ( NPCInfo->scriptFlags&SCF_DONT_FIRE ) { shoot = qfalse; } //FIXME: don't shoot right away! if ( shoot ) {//try to shoot if it's time if ( TIMER_Done( NPC, "attackDelay" ) ) { WeaponThink( qtrue ); if ( ucmd.buttons&(BUTTON_ATTACK|BUTTON_ALT_ATTACK) ) { G_SoundOnEnt( NPC, CHAN_WEAPON, "sound/null.wav" ); } //took a shot, now hide if ( !(NPC->spawnflags&SPF_NO_HIDE) && !Q_irand( 0, 1 ) ) { //FIXME: do this if in combat point and combat point has duck-type cover... also handle lean-type cover Sniper_StartHide(); } else { TIMER_Set( NPC, "attackDelay", NPCInfo->shotTime-level.time ); } } } }
void NPC_Respond( gentity_t *self, int userNum ) { int event = -1; /* if ( Q_irand( 0, 1 ) ) { event = Q_irand(EV_RESPOND1, EV_RESPOND3); } else { event = Q_irand(EV_BUSY1, EV_BUSY3); } */ if ( !Q_irand( 0, 1 ) ) {//set looktarget to them for a second or two NPC_TempLookTarget( self, userNum, 1000, 3000 ); } //some last-minute hacked in responses switch ( self->client->NPC_class ) { case CLASS_JAN: if ( self->enemy ) { if ( !Q_irand( 0, 2 ) ) { event = Q_irand( EV_CHASE1, EV_CHASE3 ); } else if ( Q_irand( 0, 1 ) ) { event = Q_irand( EV_OUTFLANK1, EV_OUTFLANK2 ); } else { event = Q_irand( EV_COVER1, EV_COVER5 ); } } else if ( !Q_irand( 0, 2 ) ) { event = EV_SUSPICIOUS4; } else if ( !Q_irand( 0, 1 ) ) { event = EV_SOUND1; } else { event = EV_CONFUSE1; } break; case CLASS_LANDO: if ( self->enemy ) { if ( !Q_irand( 0, 2 ) ) { event = Q_irand( EV_CHASE1, EV_CHASE3 ); } else if ( Q_irand( 0, 1 ) ) { event = Q_irand( EV_OUTFLANK1, EV_OUTFLANK2 ); } else { event = Q_irand( EV_COVER1, EV_COVER5 ); } } else if ( !Q_irand( 0, 6 ) ) { event = EV_SIGHT2; } else if ( !Q_irand( 0, 5 ) ) { event = EV_GIVEUP4; } else if ( Q_irand( 0, 4 ) > 1 ) { event = Q_irand( EV_SOUND1, EV_SOUND3 ); } else { event = Q_irand( EV_JDETECTED1, EV_JDETECTED2 ); } break; case CLASS_LUKE: if ( self->enemy ) { event = EV_COVER1; } else { event = Q_irand( EV_SOUND1, EV_SOUND3 ); } break; case CLASS_JEDI: case CLASS_KYLE: if ( !self->enemy ) { /* if ( !(self->svFlags&SVF_IGNORE_ENEMIES) && (self->NPC->scriptFlags&SCF_LOOK_FOR_ENEMIES) && self->client->enemyTeam == TEAM_ENEMY ) { event = Q_irand( EV_ANGER1, EV_ANGER3 ); } else */ { event = Q_irand( EV_CONFUSE1, EV_CONFUSE3 ); } } break; case CLASS_PRISONER: if ( self->enemy ) { if ( Q_irand( 0, 1 ) ) { event = Q_irand( EV_CHASE1, EV_CHASE3 ); } else { event = Q_irand( EV_OUTFLANK1, EV_OUTFLANK2 ); } } else { event = Q_irand( EV_SOUND1, EV_SOUND3 ); } break; case CLASS_REBEL: if ( self->enemy ) { if ( !Q_irand( 0, 2 ) ) { event = Q_irand( EV_CHASE1, EV_CHASE3 ); } else { event = Q_irand( EV_DETECTED1, EV_DETECTED5 ); } } else { event = Q_irand( EV_SOUND1, EV_SOUND3 ); } break; case CLASS_BESPIN_COP: if ( !Q_stricmp( "bespincop", self->NPC_type ) ) {//variant 1 if ( self->enemy ) { if ( Q_irand( 0, 9 ) > 6 ) { event = Q_irand( EV_CHASE1, EV_CHASE3 ); } else if ( Q_irand( 0, 6 ) > 4 ) { event = Q_irand( EV_OUTFLANK1, EV_OUTFLANK2 ); } else { event = Q_irand( EV_COVER1, EV_COVER5 ); } } else if ( !Q_irand( 0, 3 ) ) { event = Q_irand( EV_SIGHT2, EV_SIGHT3 ); } else if ( !Q_irand( 0, 1 ) ) { event = Q_irand( EV_SOUND1, EV_SOUND3 ); } else if ( !Q_irand( 0, 2 ) ) { event = EV_LOST1; } else if ( !Q_irand( 0, 1 ) ) { event = EV_ESCAPING2; } else { event = EV_GIVEUP4; } } else {//variant2 if ( self->enemy ) { if ( Q_irand( 0, 9 ) > 6 ) { event = Q_irand( EV_CHASE1, EV_CHASE3 ); } else if ( Q_irand( 0, 6 ) > 4 ) { event = Q_irand( EV_OUTFLANK1, EV_OUTFLANK2 ); } else { event = Q_irand( EV_COVER1, EV_COVER5 ); } } else if ( !Q_irand( 0, 3 ) ) { event = Q_irand( EV_SIGHT1, EV_SIGHT2 ); } else if ( !Q_irand( 0, 1 ) ) { event = Q_irand( EV_SOUND1, EV_SOUND3 ); } else if ( !Q_irand( 0, 2 ) ) { event = EV_LOST1; } else if ( !Q_irand( 0, 1 ) ) { event = EV_GIVEUP3; } else { event = EV_CONFUSE1; } } break; case CLASS_R2D2: // droid G_Sound(self, G_SoundIndex(va("sound/chars/r2d2/misc/r2d2talk0%d.wav",Q_irand(1, 3)))); break; case CLASS_R5D2: // droid G_Sound(self, G_SoundIndex(va("sound/chars/r5d2/misc/r5talk%d.wav",Q_irand(1, 4)))); break; case CLASS_MOUSE: // droid G_Sound(self, G_SoundIndex(va("sound/chars/mouse/misc/mousego%d.wav",Q_irand(1, 3)))); break; case CLASS_GONK: // droid G_Sound(self, G_SoundIndex(va("sound/chars/gonk/misc/gonktalk%d.wav",Q_irand(1, 2)))); break; case CLASS_JAWA: G_SoundOnEnt(self, CHAN_VOICE, va("sound/chars/jawa/misc/chatter%d.wav",Q_irand(1, 6)) ); if ( self->NPC ) { self->NPC->blockedSpeechDebounceTime = level.time + 2000; } break; default: break; } if ( event != -1 ) { //hack here because we reuse some "combat" and "extra" sounds qboolean addFlag = (qboolean)((self->NPC->scriptFlags&SCF_NO_COMBAT_TALK) != 0); self->NPC->scriptFlags &= ~SCF_NO_COMBAT_TALK; G_AddVoiceEvent( self, event, 3000 ); if ( addFlag ) { self->NPC->scriptFlags |= SCF_NO_COMBAT_TALK; } } }