/* ------------------------- Rancor_Patrol ------------------------- */ void Rancor_Patrol( void ) { NPCS.NPCInfo->localState = LSTATE_CLEAR; //If we have somewhere to go, then do that if ( UpdateGoal() ) { NPCS.ucmd.buttons &= ~BUTTON_WALKING; NPC_MoveToGoal( qtrue ); } else { if ( TIMER_Done( NPCS.NPC, "patrolTime" )) { TIMER_Set( NPCS.NPC, "patrolTime", crandom() * 5000 + 5000 ); } } if ( NPC_CheckEnemyExt( qtrue ) == qfalse ) { Rancor_Idle(); return; } Rancor_CheckRoar( NPCS.NPC ); TIMER_Set( NPCS.NPC, "lookForNewEnemy", Q_irand( 5000, 15000 ) ); }
/* ------------------------- NPC_Rancor_Pain ------------------------- */ void NPC_Rancor_Pain( gentity_t *self, gentity_t *attacker, int damage ) { qboolean hitByRancor = qfalse; if ( attacker&&attacker->client&&attacker->client->NPC_class==CLASS_RANCOR ) { hitByRancor = qtrue; } if ( attacker && attacker->inuse && attacker != self->enemy && !(attacker->flags&FL_NOTARGET) ) { if ( !self->count ) { if ( (!attacker->s.number&&!Q_irand(0,3)) || !self->enemy || self->enemy->health == 0 || (self->enemy->client&&self->enemy->client->NPC_class == CLASS_RANCOR) || (self->NPC && self->NPC->consecutiveBlockedMoves>=10 && DistanceSquared( attacker->r.currentOrigin, self->r.currentOrigin ) < DistanceSquared( self->enemy->r.currentOrigin, self->r.currentOrigin )) ) {//if my enemy is dead (or attacked by player) and I'm not still holding/eating someone, turn on the attacker //FIXME: if can't nav to my enemy, take this guy if I can nav to him G_SetEnemy( self, attacker ); TIMER_Set( self, "lookForNewEnemy", Q_irand( 5000, 15000 ) ); if ( hitByRancor ) {//stay mad at this Rancor for 2-5 secs before looking for attacker enemies TIMER_Set( self, "rancorInfight", Q_irand( 2000, 5000 ) ); } } } } if ( (hitByRancor|| (self->count==1&&self->activator&&!Q_irand(0,4)) || Q_irand( 0, 200 ) < damage )//hit by rancor, hit while holding live victim, or took a lot of damage && self->client->ps.legsAnim != BOTH_STAND1TO2 && TIMER_Done( self, "takingPain" ) ) { if ( !Rancor_CheckRoar( self ) ) { if ( self->client->ps.legsAnim != BOTH_MELEE1 && self->client->ps.legsAnim != BOTH_MELEE2 && self->client->ps.legsAnim != BOTH_ATTACK2 ) {//cant interrupt one of the big attack anims /* if ( self->count != 1 || attacker == self->activator || (self->client->ps.legsAnim != BOTH_ATTACK1&&self->client->ps.legsAnim != BOTH_ATTACK3) ) */ {//if going to bite our victim, only victim can interrupt that anim if ( self->health > 100 || hitByRancor ) { TIMER_Remove( self, "attacking" ); VectorCopy( self->NPC->lastPathAngles, self->s.angles ); if ( self->count == 1 ) { NPC_SetAnim( self, SETANIM_BOTH, BOTH_PAIN2, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD ); } else { NPC_SetAnim( self, SETANIM_BOTH, BOTH_PAIN1, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD ); } TIMER_Set( self, "takingPain", self->client->ps.legsTimer+Q_irand(0, 500) ); if ( self->NPC ) { self->NPC->localState = LSTATE_WAITING; } } } } } //let go /* if ( !Q_irand( 0, 3 ) && self->count == 1 ) { Rancor_DropVictim( self ); } */ } }
//void NPC_Rancor_Pain( gentity_t *self, gentity_t *inflictor, gentity_t *other, const vec3_t point, int damage, int mod,int hitLoc ) void NPC_Rancor_Pain( gentity_t *self, gentity_t *attacker, int damage ) { qboolean hitByRancor = qfalse; //[CoOp] if ( self->NPC && self->NPC->ignorePain ) { return; } if ( !TIMER_Done( self, "breathAttack" ) ) {//nothing interrupts breath attack return; } TIMER_Remove( self, "confusionTime" ); //[/CoOp] if ( attacker&&attacker->client&&attacker->client->NPC_class==CLASS_RANCOR ) { hitByRancor = qtrue; } if ( attacker && attacker->inuse && attacker != self->enemy && !(attacker->flags&FL_NOTARGET) ) { if ( !self->count ) { //[CoOp] //adjusting for more than one player if ( (attacker->s.number < MAX_CLIENTS &&!Q_irand(0,3)) //if ( (!attacker->s.number&&!Q_irand(0,3)) //[/CoOp] || !self->enemy //[CoOp] //can be dead below 0 in MP || self->enemy->health <= 0 //|| self->enemy->health == 0 //[/CoOp] || (self->enemy->client&&self->enemy->client->NPC_class == CLASS_RANCOR) //[CoOp] SP Code || (!Q_irand(0, 4 ) && DistanceSquared( attacker->r.currentOrigin, self->r.currentOrigin ) < DistanceSquared( self->enemy->r.currentOrigin, self->r.currentOrigin )) ) //|| (self->NPC && self->NPC->consecutiveBlockedMoves>=10 && DistanceSquared( attacker->r.currentOrigin, self->r.currentOrigin ) < DistanceSquared( self->enemy->r.currentOrigin, self->r.currentOrigin )) ) ///[CoOp] {//if my enemy is dead (or attacked by player) and I'm not still holding/eating someone, turn on the attacker //FIXME: if can't nav to my enemy, take this guy if I can nav to him //[CoOp] self->lastEnemy = self->enemy; //[/CoOp] G_SetEnemy( self, attacker ); //[CoOp] //RAFIXME - useDebounceTime not implimented /* SP Code if ( self->enemy != self->lastEnemy ) {//clear this so that we only sniff the player the first time we pick them up self->useDebounceTime = 0; } */ //[/CoOp] TIMER_Set( self, "lookForNewEnemy", Q_irand( 5000, 15000 ) ); if ( hitByRancor ) {//stay mad at this Rancor for 2-5 secs before looking for attacker enemies TIMER_Set( self, "rancorInfight", Q_irand( 2000, 5000 ) ); } } } } if ( (hitByRancor|| (self->count==1&&self->activator&&!Q_irand(0,4)) || Q_irand( 0, 200 ) < damage )//hit by rancor, hit while holding live victim, or took a lot of damage && self->client->ps.legsAnim != BOTH_STAND1TO2 && TIMER_Done( self, "takingPain" ) ) { if ( !Rancor_CheckRoar( self ) ) { if ( self->client->ps.legsAnim != BOTH_MELEE1 && self->client->ps.legsAnim != BOTH_MELEE2 //[CoOp] //move animations are uninterruptable in SP. && self->client->ps.legsAnim != BOTH_ATTACK2 && self->client->ps.legsAnim != BOTH_ATTACK10 && self->client->ps.legsAnim != BOTH_ATTACK11 ) //&& self->client->ps.legsAnim != BOTH_ATTACK2 ) //[/CoOp] {//cant interrupt one of the big attack anims /* if ( self->count != 1 || attacker == self->activator || (self->client->ps.legsAnim != BOTH_ATTACK1&&self->client->ps.legsAnim != BOTH_ATTACK3) ) */ {//if going to bite our victim, only victim can interrupt that anim if ( self->health > 100 || hitByRancor ) { TIMER_Remove( self, "attacking" ); VectorCopy( self->NPC->lastPathAngles, self->s.angles ); if ( self->count == 1 ) { NPC_SetAnim( self, SETANIM_BOTH, BOTH_PAIN2, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD ); } else { NPC_SetAnim( self, SETANIM_BOTH, BOTH_PAIN1, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD ); } //[CoOp] SP Code TIMER_Set( self, "takingPain", self->client->ps.legsTimer+Q_irand(0, 500*(2-g_spskill.integer)) ); //TIMER_Set( self, "takingPain", self->client->ps.legsTimer+Q_irand(0, 500) ); //[CoOp] if ( self->NPC ) { self->NPC->localState = LSTATE_WAITING; } } } } } //let go /* if ( !Q_irand( 0, 3 ) && self->count == 1 ) { Rancor_DropVictim( self ); } */ } }