//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; 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 ( (G_IsPlayer(attacker) &&!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; } } } } } } }
/* ------------------------- NAVNEW_PushBlocker ------------------------- */ void NAVNEW_PushBlocker( gentity_t *self, gentity_t *blocker, vec3_t right, qboolean setBlockedInfo ) {//try pushing blocker to one side trace_t tr; vec3_t mins, end; float rightSucc, leftSucc, moveamt; if ( self->NPC->shoveCount > 30 ) {//don't push for more than 3 seconds; return; } if ( G_IsPlayer(blocker) ) {//never push the player return; } if ( !blocker->client || !VectorCompare( blocker->client->pushVec, vec3_origin ) ) {//someone else is pushing him, wait until they give up? return; } VectorCopy( blocker->r.mins, mins ); mins[2] += STEPSIZE; moveamt = (self->r.maxs[1] + blocker->r.maxs[1]) * 1.2;//yes, magic number VectorMA( blocker->r.currentOrigin, -moveamt, right, end ); trap_Trace( &tr, blocker->r.currentOrigin, mins, blocker->r.maxs, end, blocker->s.number, blocker->clipmask|CONTENTS_BOTCLIP); if ( !tr.startsolid && !tr.allsolid ) { leftSucc = tr.fraction; } else { leftSucc = 0.0f; } if ( leftSucc >= 1.0f ) {//it's clear, shove him that way VectorScale( right, -moveamt, blocker->client->pushVec ); blocker->client->pushVecTime = level.time + 2000; } else { VectorMA( blocker->r.currentOrigin, moveamt, right, end ); trap_Trace( &tr, blocker->r.currentOrigin, mins, blocker->r.maxs, end, blocker->s.number, blocker->clipmask|CONTENTS_BOTCLIP ); if ( !tr.startsolid && !tr.allsolid ) { rightSucc = tr.fraction; } else { rightSucc = 0.0f; } if ( leftSucc == 0.0f && rightSucc == 0.0f ) {//both sides failed if ( d_patched.integer ) {//use patch-style navigation blocker->client->pushVecTime = 0; } return; } if ( rightSucc >= 1.0f ) {//it's clear, shove him that way VectorScale( right, moveamt, blocker->client->pushVec ); blocker->client->pushVecTime = level.time + 2000; } //if neither are enough, we probably can't get around him, but keep trying else if ( leftSucc >= rightSucc ) {//favor the left, all things being equal VectorScale( right, -moveamt, blocker->client->pushVec ); blocker->client->pushVecTime = level.time + 2000; } else { VectorScale( right, moveamt, blocker->client->pushVec ); blocker->client->pushVecTime = level.time + 2000; } } if ( setBlockedInfo ) { //we tried pushing self->NPC->shoveCount++; } }