void SV_MoveToOrigin( edict_t *ent, const vec3_t pflGoal, float dist, int iMoveType ) { vec3_t vecDist; VectorCopy( pflGoal, vecDist ); if( ent->v.flags & ( FL_FLY|FL_SWIM|FL_ONGROUND )) { if( iMoveType == MOVE_NORMAL ) { if( SV_StepDirection( ent, ent->v.ideal_yaw, dist ) == 0 ) { SV_NewChaseDir( ent, vecDist, dist ); } } else { vecDist[0] -= ent->v.origin[0]; vecDist[1] -= ent->v.origin[1]; if( ent->v.flags & ( FL_FLY|FL_SWIM )) vecDist[2] -= ent->v.origin[2]; else vecDist[2] = 0.0f; VectorNormalize( vecDist ); VectorScale( vecDist, dist, vecDist ); SV_FlyDirection( ent, vecDist ); } } }
/* ====================== SV_MoveToGoal ====================== */ void SV_MoveToGoal (void) { edict_t *ent, *goal; float dist; #ifdef QUAKE2 edict_t *enemy; #endif ent = PROG_TO_EDICT(pr_global_struct->self); goal = PROG_TO_EDICT(ent->v.goalentity); dist = G_FLOAT(OFS_PARM0); if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) ) { G_FLOAT(OFS_RETURN) = 0; return; } // if the next step hits the enemy, return immediately #ifdef QUAKE2 enemy = PROG_TO_EDICT(ent->v.enemy); if (enemy != sv.edicts && SV_CloseEnough (ent, enemy, dist) ) #else if ( PROG_TO_EDICT(ent->v.enemy) != sv.edicts && SV_CloseEnough (ent, goal, dist) ) #endif return; // bump around... if ( (rand()&3)==1 || !SV_StepDirection (ent, ent->v.ideal_yaw, dist)) { SV_NewChaseDir (ent, goal, dist); } }
void SV_NewChaseDir1 (edict_t *self, edict_t *goal, float dist) { int i, bestyaw, minyaw, maxyaw; vec3_t v; if (!goal) return; VectorSubtract(goal->s.origin, self->s.origin, v); bestyaw = vectoyaw(v); minyaw = bestyaw - 90; maxyaw = bestyaw + 90; if (minyaw < 0) minyaw += 360; if (maxyaw > 360) maxyaw -= 360; for (i=minyaw; i<maxyaw; i+=30) { if (SV_StepDirection(self, i, dist, false)) return; } //gi.dprintf("couldnt find a better direction!\n"); SV_NewChaseDir(self, goal, dist); }
void SV_NewChaseDir2 (edict_t *self, vec3_t dest, float dist) { float minyaw, maxyaw, bestyaw, temp; vec3_t v; if (!dest) return; VectorSubtract(dest, self->s.origin, v); bestyaw = vectoyaw(v); minyaw = bestyaw - 90; maxyaw = bestyaw + 90; // try a step forward +/- 90 degrees from ideal yaw if (CheckYawStep(self, minyaw, maxyaw, dist)) { //gi.dprintf("took a step +/- 90 degrees from ideal yaw\n"); return; } // that didn't work, so flip the search pattern and // try going in the opposite direction temp = minyaw; minyaw = maxyaw; maxyaw = temp; if (CheckYawStep(self, minyaw, maxyaw, dist)) { //gi.dprintf("took a step 180 degrees from ideal yaw\n"); return; } //gi.dprintf("couldnt find a better direction!\n"); SV_NewChaseDir(self, self->goalentity, dist); }
/* ====================== SV_MoveToGoal ====================== */ void SV_MoveToGoal (void) { edict_t *ent, *goal; float dist; ent = PROG_TO_EDICT(PR_GLOBAL_STRUCT(self)); // Entity moving goal = PROG_TO_EDICT(ent->v.goalentity); // its goalentity dist = G_FLOAT(OFS_PARM0); // how far to move // Reset trace_plane_normal VectorCopy(vec3_origin, PR_GLOBAL_STRUCT(trace_plane_normal)); // If not onground, flying, or swimming, return 0 if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) ) { G_FLOAT(OFS_RETURN) = 0; return; } // if the next step hits the enemy, return immediately if ( PROG_TO_EDICT(ent->v.enemy) != sv.edicts && SV_CloseEnough (ent, goal, dist) ) { G_FLOAT(OFS_RETURN) = 0; return; } // bump around... if (!SV_StepDirection (ent, ent->v.ideal_yaw, dist))//If can't go in a direction (including step check) or 30% chance... { SV_NewChaseDir (ent, goal, dist);//Find a new direction to go in instead G_FLOAT(OFS_RETURN) = 0; } else { if ((rand()&3)==1) { SV_NewChaseDir (ent, goal, dist);//Find a new direction to go in instead } G_FLOAT(OFS_RETURN) = 1; } return; }
/* ==================== M_MoveAwayFromFlare ==================== */ qboolean M_MoveAwayFromFlare(edict_t *self, float dist) { edict_t *e = NULL; edict_t *goal = NULL; vec3_t delta; vec3_t forward; // find the closest flare while(1) { e = findradius(e, self->s.origin, 256); if (e == NULL) break; if (Q_stricmp(e->classname, "flare") == 0) break; } goal = G_Spawn(); self->goalentity = goal; if (e == NULL) { // just move forward AngleVectors(self->s.angles, forward, NULL, NULL); VectorMA(self->s.origin, 128, forward, goal->s.origin); } else { VectorSubtract(self->s.origin, e->s.origin, delta); VectorNormalize(delta); VectorMA(self->s.origin, 128, delta, goal->s.origin); } if (rand() & (7 == 1)) { // set the ideal_yaw VectorSubtract(goal->s.origin, self->s.origin, delta); self->ideal_yaw = vectoyaw(delta); } if ( (rand()&3)==1 || !SV_StepDirection (self, self->ideal_yaw, dist)) { SV_NewChaseDir (self, goal, dist); } self->goalentity = NULL; G_FreeEdict(goal); return true; }
/* ====================== M_MoveToGoal ====================== */ void M_MoveToGoal(edict_t *ent, float dist){ edict_t *goal; goal = ent->goalentity; if(!ent->groundentity && !(ent->flags &(FL_FLY | FL_SWIM))) return; // if the next step hits the enemy, return immediately if(ent->enemy && SV_CloseEnough(ent, ent->enemy, dist)) return; // bump around... if((rand()&3) == 1 || !SV_StepDirection(ent, ent->ideal_yaw, dist)){ if(ent->inuse) SV_NewChaseDir(ent, goal, dist); } }
/* ====================== M_MoveToGoal ====================== */ void M_MoveToGoal (edict_t *ent, float dist) { edict_t *goal; goal = ent->goalentity; if (!ent->groundentity && !(ent->flags & (FL_FLY|FL_SWIM))) return; // if the next step hits the enemy, return immediately if (ent->enemy && SV_CloseEnough (ent, ent->enemy, dist) ) return; // bump around... // if ( (rand()&3)==1 || !SV_StepDirection (ent, ent->ideal_yaw, dist)) // PMM - charging monsters (AI_CHARGING) don't deflect unless they have to if ( (((rand()&3)==1) && !(ent->monsterinfo.aiflags & AI_CHARGING)) || !SV_StepDirection (ent, ent->ideal_yaw, dist)) { if (ent->inuse) SV_NewChaseDir (ent, goal, dist); } }
/* ====================== M_MoveToGoal ====================== */ void M_MoveToGoal (edict_t *ent, float dist) { edict_t *goal; goal = ent->goalentity; if (!ent->groundentity && !(ent->flags & (FL_FLY|FL_SWIM))) return; // if the next step hits the enemy, return immediately if (ent->enemy && SV_CloseEnough (ent, ent->enemy, dist) ) return; if ( (((rand()&3)==1) && !(ent->monsterinfo.aiflags & AI_CHARGING)) || !SV_StepDirection (ent, ent->ideal_yaw, dist)) { if (ent->monsterinfo.aiflags & AI_BLOCKED) { ent->monsterinfo.aiflags &= ~AI_BLOCKED; return; } if (ent->inuse) SV_NewChaseDir (ent, goal, dist); } }
/* ====================== M_MoveToGoal ====================== */ void M_MoveToGoal (edict_t *ent, float dist) { edict_t *goal; goal = ent->goalentity; if (ent->holdtime > level.time) // stay in-place for medic healing return; if (!ent->groundentity && !(ent->flags & (FL_FLY|FL_SWIM)) && !ent->waterlevel) { //gi.dprintf("not touching ground\n"); return; } // if the next step hits the enemy, return immediately if (ent->enemy && (ent->enemy->solid == SOLID_BBOX) && SV_CloseEnough (ent, ent->enemy, dist) ) //GHz START { vec3_t v; // we need to keep turning to avoid getting stuck doing nothing if (ent->goalentity && ent->goalentity->inuse) // 3.89 make sure the monster still has a goal! { VectorSubtract(ent->goalentity->s.origin, ent->s.origin, v); VectorNormalize(v); ent->ideal_yaw = vectoyaw(v); M_ChangeYaw(ent); } return; } //GHz END // dont move so fast in the water if (!(ent->flags & (FL_FLY|FL_SWIM)) && (ent->waterlevel > 1)) dist *= 0.5; // bump around... // if we can't take a step, try moving in another direction if (!SV_StepDirection (ent, ent->ideal_yaw, dist, true)) { //gi.dprintf("couldnt step\n"); // if the monster hasn't moved much, then increment // the number of frames it has been stuck if (distance(ent->s.origin, ent->monsterinfo.stuck_org) < 64) ent->monsterinfo.stuck_frames++; else ent->monsterinfo.stuck_frames = 0; // record current position for comparison VectorCopy(ent->s.origin, ent->monsterinfo.stuck_org); // attempt a course-correction if (ent->inuse && (level.time > ent->monsterinfo.bump_delay)) { //gi.dprintf("tried course correction %s\n", ent->goalentity?"true":"false"); SV_NewChaseDir (ent, goal, dist); ent->monsterinfo.bump_delay = level.time + FRAMETIME*GetRandom(2, 5); return; } } }
/* ====================== M_MoveToGoal ====================== */ void M_MoveToGoal (edict_t *ent, float dist) { edict_t *goal; goal = ent->goalentity; if (!ent->groundentity && !(ent->flags & (FL_FLY|FL_SWIM))) return; // Lazarus range checks if (!(ent->monsterinfo.aiflags & (AI_CHASE_THING | AI_CHICKEN))) { if (ent->enemy && (ent->monsterinfo.min_range > 0) && ((goal==ent->enemy) || !goal) ) { float dist; dist = realrange(ent,ent->enemy); if(dist < ent->monsterinfo.min_range) { ent->monsterinfo.aiflags |= (AI_STAND_GROUND | AI_RANGE_PAUSE); ent->monsterinfo.rangetime = level.time + 0.5; ent->monsterinfo.stand(ent); return; } } if ((ent->enemy) && (level.time > ent->monsterinfo.rangetime + 0.5) && ((goal==ent->enemy) || !goal) ) { float dist; dist = realrange(ent,ent->enemy); if((dist < ent->monsterinfo.ideal_range[0]) && (rand() & 3)) { ent->monsterinfo.aiflags |= (AI_STAND_GROUND | AI_RANGE_PAUSE); ent->monsterinfo.rangetime = level.time + 1.0; ent->monsterinfo.stand(ent); return; } if((dist < ent->monsterinfo.ideal_range[1]) && (dist > ent->monsterinfo.ideal_range[0]) && (rand() & 1)) { ent->monsterinfo.aiflags |= (AI_STAND_GROUND | AI_RANGE_PAUSE); ent->monsterinfo.rangetime = level.time + 0.2; ent->monsterinfo.stand(ent); return; } } } if( (ent->monsterinfo.aiflags & AI_FOLLOW_LEADER) && (ent->movetarget) && (ent->movetarget->inuse) && (ent->movetarget->health > 0) ) { if(ent->enemy) ent->monsterinfo.currentmove = &actor_move_run; else { float R; R = realrange(ent,ent->movetarget); if(R > ACTOR_FOLLOW_RUN_RANGE) ent->monsterinfo.currentmove = &actor_move_run; else if(R < ACTOR_FOLLOW_STAND_RANGE && ent->movetarget->client) { ent->monsterinfo.pausetime = level.time + 0.5; ent->monsterinfo.currentmove = &actor_move_stand; return; } else ent->monsterinfo.currentmove = &actor_move_walk; } } // If the next step hits the enemy, return immediately. Don't do this for // AI_CHASE_THING, since we want monster to actually touch or pass through // "thing" if (ent->enemy && !(ent->monsterinfo.aiflags & AI_CHASE_THING) && SV_CloseEnough (ent, ent->enemy, dist) ) return; // bump around... if ( (rand()&3)==1 || !SV_StepDirection (ent, ent->ideal_yaw, dist)) { if (ent->inuse) SV_NewChaseDir (ent, goal, dist); } }