/* ====================== 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); } }
/* ====================== 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); } }
/* ====================== 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_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); } }