int Plane::OnSameSide(const Vec3& pa, const Vec3& pb) const { auto da = DistanceTo(pa); auto db = DistanceTo(pb); if (da < 0 && db < 0) return -1; if (da > 0 && db > 0) return 1; return 0; }
/* ================ rvMonsterConvoyGround::State_Legs_Move ================ */ stateResult_t rvMonsterConvoyGround::State_Legs_Move ( const stateParms_t& parms ) { enum { STAGE_INIT, STAGE_MOVE }; switch ( parms.stage ) { case STAGE_INIT: move.fl.allowAnimMove = true; move.fl.allowPrevAnimMove = false; move.fl.running = true; move.currentDirection = MOVEDIR_FORWARD; // TODO: Looks like current anim rate never gets reset, so they do not correctly accelerate from a stop // unfortunately, adding this change (with a decent acceleration factor) caused them to do lots of // not-so-good looking short moves. // moveCurrentAnimRate = 0; oldOrigin = physicsObj.GetOrigin ( ); PlayCycle ( ANIMCHANNEL_LEGS, "run", 0 ); StartSound( "snd_move", SND_CHANNEL_BODY3, 0, false, NULL ); return SRESULT_STAGE ( STAGE_MOVE ); case STAGE_MOVE: // If not moving forward just go back to idle if ( !move.fl.moving || !CanMove() ) { StopSound( SND_CHANNEL_BODY3, 0 ); PostAnimState ( ANIMCHANNEL_LEGS, "Legs_Idle", 0 ); return SRESULT_DONE; } // If on the ground update the animation rate based on the normal of the ground plane if ( !ai_debugHelpers.GetBool ( ) && physicsObj.HasGroundContacts ( ) ) { float rate; idVec3 dir; dir = (physicsObj.GetOrigin ( ) - oldOrigin); if ( DistanceTo ( move.moveDest ) < move.walkRange ) { rate = moveAnimRateMin; } else if ( dir.Normalize ( ) > 0.0f ) { rate = idMath::ClampFloat ( -0.7f, 0.7f, physicsObj.GetGravityNormal ( ) * dir ) / 0.7f; rate = moveAnimRateMin + moveAnimRateRange * (1.0f + rate) / 2.0f; } else { rate = moveAnimRateMin + moveAnimRateRange * 0.5f; } moveCurrentAnimRate += ((rate - moveCurrentAnimRate) * moveAccelRate); animator.CurrentAnim ( ANIMCHANNEL_LEGS )->SetPlaybackRate ( gameLocal.time, moveCurrentAnimRate ); } oldOrigin = physicsObj.GetOrigin ( ); return SRESULT_WAIT; } return SRESULT_ERROR; }
END_CLASS_STATES //------------------------------------------------------------ // rvMonsterBossBuddy::State_Torso_RocketAttack //------------------------------------------------------------ stateResult_t rvMonsterBossBuddy::State_Torso_RocketAttack( const stateParms_t& parms ) { enum { STAGE_INIT, STAGE_WAITSTART, STAGE_LOOP, STAGE_WAITLOOP, STAGE_WAITEND }; switch ( parms.stage ) { case STAGE_INIT: DisableAnimState( ANIMCHANNEL_LEGS ); PlayAnim( ANIMCHANNEL_TORSO, "attack_rocket2start", parms.blendFrames ); mShots = (gameLocal.random.RandomInt( 3 ) + 2) * combat.aggressiveScale; return SRESULT_STAGE( STAGE_WAITSTART ); case STAGE_WAITSTART: if ( AnimDone( ANIMCHANNEL_TORSO, 0 )) { return SRESULT_STAGE( STAGE_LOOP ); } return SRESULT_WAIT; case STAGE_LOOP: PlayAnim( ANIMCHANNEL_TORSO, "attack_rocket2loop2", 0 ); return SRESULT_STAGE( STAGE_WAITLOOP ); case STAGE_WAITLOOP: if ( AnimDone( ANIMCHANNEL_TORSO, 0 )) { if ( --mShots <= 0 || // exhausted mShots? .. or (!IsEnemyVisible() && rvRandom::irand(0,10)>=8 ) || // ... player is no longer visible .. or ( enemy.ent && DistanceTo(enemy.ent)<256 ) ) // ... player is so close, we prolly want to do a melee attack { PlayAnim( ANIMCHANNEL_TORSO, "attack_rocket2end", 0 ); return SRESULT_STAGE( STAGE_WAITEND ); } return SRESULT_STAGE( STAGE_LOOP ); } return SRESULT_WAIT; case STAGE_WAITEND: if ( AnimDone( ANIMCHANNEL_TORSO, 4 )) { return SRESULT_DONE; } return SRESULT_WAIT; } return SRESULT_ERROR; }
double Point2d::DistanceToLine(Point2d p0, Point2d dp, bool segment) { double m = dp.x*dp.x + dp.y*dp.y; if(m < LENGTH_EPS*LENGTH_EPS) return VERY_POSITIVE; // Let our line be p = p0 + t*dp, for a scalar t from 0 to 1 double t = (dp.x*(x - p0.x) + dp.y*(y - p0.y))/m; if((t < 0 || t > 1) && segment) { // The closest point is one of the endpoints; determine which. double d0 = DistanceTo(p0); double d1 = DistanceTo(p0.Plus(dp)); return min(d1, d0); } else { Point2d closest = p0.Plus(dp.ScaledBy(t)); return DistanceTo(closest); } }
//--------------------------------------------------------------------------- int Plane3::WhichSide(const Vec3& p) const { Real distance = DistanceTo(p); if (distance<0.0f) return -1; if (distance>0.0) return 1; return 0; }
Path PathFinder::findPath(const Coord& start, const Coord& end) { Coord mapEnd; if ( makeMap( start, DistanceTo(end), ReachedPos(end), &mapEnd ) ) { return getPath(start, end); } return Path(); }
E_PlaneSide mxPlane::ClassifyPointRelation( const Vec3D& point ) const { const f32 fDist = DistanceTo( point ); if ( fDist < -PLANESIDE_EPSILON ) { return SIDE_BACK; } else if ( fDist > +PLANESIDE_EPSILON ) { return SIDE_FRONT; } return SIDE_ON; }
E_PlaneSide mxPlane::ClassifyPointRelation_epsilon( const Vec3D& point, const f32 epsilon /* =PLANESIDE_EPSILON */ ) const { const f32 fDist = DistanceTo( point ); if ( fDist < -epsilon ) { return SIDE_BACK; } else if ( fDist > +epsilon ) { return SIDE_FRONT; } return SIDE_ON; }
int Plane3x::WhichSide (const Vector3x& rkQ) const { fixed fDistance = DistanceTo(rkQ); if (fDistance < FIXED_ZERO) { return -1; } if (fDistance > FIXED_ZERO) { return +1; } return 0; }
void Key::cursor_value( const DataSource::PixelInfo& info, float value ) { bool approx = false; if ( std::isnan(value) ) { /* Search for color in key closest to info.color */ std::vector<Color>::iterator element = std::min_element( colors.begin(), colors.end(), DistanceTo(info.pixel) ); value = values[ element - colors.begin() ]; approx = true; } wxChar cbuffer[128]; float remainder; const wxChar *SI_unit_prefix; make_SI_prefix( value, remainder, SI_unit_prefix ); wxSnprintf(cbuffer, 128, wxT("%.3g %s"), remainder, SI_unit_prefix); cursor->SetLabel( ((approx) ? wxT("ca. ") : wxT("")) + wxString(cbuffer) ); }
void Mass::ApplyGravityFrom(const Mass body, float timestep) { float dx = this->position.X() - body.GetPosition().X(), dy = this->position.Y() - body.GetPosition().Y(), d = DistanceTo(body); if(d < 20) d = 20.0f; /* Accel due to gravity = GM / d^2 = d / t^2 We want change in velocity, which is d/t So multiply accel by t: GM / d^2 * t = GMt / d^2 unit: d/t But we want the components of that velocity So multiply by dx/d and dy/d: delta xv = GMt * dx / d^3 delta yv = GMt * dy / d^3 Calculate once GMt / d^3: */ float hertz = body.GetMass() * timestep * -0.0015 / (d*d*d); this->velocity = this->velocity + Vector2D(hertz*dx, hertz*dy); }
E_PlaneSide mxPlane::ClassifyVolumeRelation( const AABB& bv, const f32 epsilon /* =PLANESIDE_EPSILON */ ) const { // if mxBounds is an axis aligned bounding box Vec3D vCenter = (bv.MinEdge + bv.MaxEdge) * 0.5f; f32 dist1 = DistanceTo( vCenter ); const f32 * center = reinterpret_cast< const f32* >( & vCenter ); const f32 * b1 = reinterpret_cast< const f32* >( & bv.MaxEdge ); const f32 * normal = reinterpret_cast< const f32* >( & Normal ); f32 dist2 = idMath::Fabs( ( b1[0] - center[0] ) * normal[0] ) + idMath::Fabs( ( b1[1] - center[1] ) * normal[1] ) + idMath::Fabs( ( b1[2] - center[2] ) * normal[2] ); if ( dist1 - dist2 > epsilon ) { return SIDE_FRONT; } if ( dist1 + dist2 < -epsilon ) { return SIDE_BACK; } return SIDE_CROSS; }
// ******************************************************************************************** // Checks for changes every NPS_TICKRATE milliseconds // Checks: // * if we've gotten close enough to a nav point for it to be counted as "Visited" // * If we're current AutoNavigating it checks if we need to autodisengage void NavSystem_Do() { static unsigned int last_update = 0; if (clock () - last_update > NPS_TICKRATE) { if (AutoPilotEngaged) { if (The_mission.flags & MISSION_FLAG_USE_AP_CINEMATICS) { camera *cam = nav_get_set_camera(); if (CinematicStarted) { // update our cinematic and possibly perform warp //if (!CameraMoving) if(cam != NULL) cam->set_rotation_facing(&Player_obj->pos); if (timestamp() >= MoveCamera && !CameraMoving && vm_vec_mag(&cameraTarget) > 0.0f) { //Free_camera->set_position(&cameraTarget, float(camMovingTime), float(camMovingTime)/2.0f); //Free_camera->set_translation_velocity(&cameraTarget); CameraMoving = true; } if (timestamp() >= EndAPCinematic || !CanAutopilot()) { nav_warp(); EndAutoPilot(); } } else { // start cinematic if (UseCutsceneBars) { Cutscene_bar_flags |= CUB_CUTSCENE; Cutscene_bar_flags &= ~CUB_GRADUAL; } nav_warp(true); if(cam != NULL) { cam->set_position(&cameraPos); cam->set_rotation_facing(&Autopilot_flight_leader->pos); } CinematicStarted = true; } } else { if (!CanAutopilot()) EndAutoPilot(); } } // check if a NavPoints target has left, delete it if so int i; for (i = 0; i < MAX_NAVPOINTS; i++) { if ((Navs[i].flags & NP_SHIP) && (Navs[i].target_obj != NULL)) { if (((ship*)Navs[i].target_obj)->objnum == -1) { if (CurrentNav == i) CurrentNav = -1; DelNavPoint(i); } } } // check if we're reached a Node for (i = 0; i < MAX_NAVPOINTS; i++) { if (Navs[i].target_obj != NULL) { if (Navs[i].flags & NP_VALIDTYPE && DistanceTo(i) < 1000) Navs[i].flags |= NP_VISITED; } } } // ramp time compression - only if not using cinematics if (AutoPilotEngaged && !(The_mission.flags & MISSION_FLAG_USE_AP_CINEMATICS)) { int dstfrm_start = start_dist - DistanceTo(CurrentNav); // Ramp UP time compression if (dstfrm_start < (3500*ramp_bias)) { if (dstfrm_start >= (3000*ramp_bias) && DistanceTo(CurrentNav) > 30000) set_time_compression(64); else if (dstfrm_start >= (2000*ramp_bias)) set_time_compression(32); else if (dstfrm_start >= (1600*ramp_bias)) set_time_compression(16); else if (dstfrm_start >= (1200*ramp_bias)) set_time_compression(8); else if (dstfrm_start >= (800*ramp_bias)) set_time_compression(4); else if (dstfrm_start >= (400*ramp_bias)) set_time_compression(2); } // Ramp DOWN time compression if (DistanceTo(CurrentNav) <= (7000*ramp_bias)) { int dist = DistanceTo(CurrentNav); if (dist >= (5000*ramp_bias)) set_time_compression(32); else if (dist >= (4000*ramp_bias)) set_time_compression(16); else if (dist >= (3000*ramp_bias)) set_time_compression(8); else if (dist >= (2000*ramp_bias)) set_time_compression(4); else if (dist >= (1000*ramp_bias)) set_time_compression(2); } } /* Link in any ships that need to be linked in when the player gets close enough. Always done by the player because: "making sure the AI fighters are where they're supposed to be at all times is like herding cats" -Woolie Wool */ for (int i = 0; i < MAX_SHIPS; i++) { if (Ships[i].objnum != -1 && Ships[i].flags2 & SF2_NAVPOINT_NEEDSLINK) { object *other_objp = &Objects[Ships[i].objnum]; if (vm_vec_dist_quick(&Player_obj->pos, &other_objp->pos) < (NavLinkDistance + other_objp->radius)) { Ships[i].flags2 &= ~SF2_NAVPOINT_NEEDSLINK; Ships[i].flags2 |= SF2_NAVPOINT_CARRY; send_autopilot_msgID(NP_MSG_MISC_LINKED); } } } }
bool Plane::Contains(const Vector& v) const { return (Abs(DistanceTo(v)) < EPSILON); }
unsigned int DistanceTo(char *nav) { int n = FindNav(nav); return DistanceTo(n); }
bool Plane::OnFrontSide(const Vector& v) const { return (DistanceTo(v) > -EPSILON); }
bool Plane::OnBackSide(const Vector& v) const { return (DistanceTo(v) < EPSILON); }
Vector Plane::Reflect(const Vector& v) const { return (v - (2.0f * m_Normal * DistanceTo(v))); }
Vec3 Plane::ProjectPoint(const Vec3& p) const { auto d = DistanceTo(p); return p - mNormal * p; }
// ******************************************************************************************** // Engages autopilot // This does: // * Control switched from player to AI // * Time compression to 32x // * Lock time compression -WMC // * Tell AI to fly to targeted Nav Point (for all nav-status wings/ships) // * Sets max waypoint speed to the best-speed of the slowest ship tagged bool StartAutopilot() { // Check for support ship and dismiss it if it is not doing anything. // If the support ship is doing something then tell the user such. for ( object *objp = GET_FIRST(&obj_used_list); objp !=END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) { if ((objp->type == OBJ_SHIP) && !(objp->flags & OF_SHOULD_BE_DEAD)) { Assertion((objp->instance >= 0) && (objp->instance < MAX_SHIPS), "objp does not have a valid pointer to a ship. Pointer is %d, which is smaller than 0 or bigger than %d", objp->instance, MAX_SHIPS); ship *shipp = &Ships[objp->instance]; if (shipp->team != Player_ship->team) continue; Assertion((shipp->ship_info_index >= 0) && (shipp->ship_info_index < MAX_SHIP_CLASSES), "Ship '%s' does not have a valid pointer to a ship class. Pointer is %d, which is smaller than 0 or bigger than %d", shipp->ship_name, shipp->ship_info_index, MAX_SHIP_CLASSES); ship_info *sip = &Ship_info[shipp->ship_info_index]; if ( !(sip->flags & SIF_SUPPORT) ) continue; // don't deal with dying or departing support ships if ( shipp->flags & (SF_DYING | SF_DEPARTING) ) continue; Assert(shipp->ai_index != -1); ai_info* support_ship_aip = &(Ai_info[Ships[objp->instance].ai_index]); // is support ship trying to rearm-repair if ( ai_find_goal_index( support_ship_aip->goals, AI_GOAL_REARM_REPAIR ) == -1 ) { // no, so tell it to depart ai_add_ship_goal_player( AIG_TYPE_PLAYER_SHIP, AI_GOAL_WARP, -1, NULL, support_ship_aip ); } else { // yes send_autopilot_msgID(NP_MSG_FAIL_SUPPORT_WORKING); return false; } } } if (!CanAutopilot()) return false; AutoPilotEngaged = true; // find the ship that is "leading" all of the ships when the player starts // autopilot // by default the ship that is leading the autopilot session the player's // wing leader (if the player is the wing leader then it will be the // player). // TODO:implement a way to allow a FREDer to say a different ship is leader Autopilot_flight_leader = get_wing_leader(Player_ship->wingnum); if ( Autopilot_flight_leader == NULL ) { // force player to be the leader if he doesn't have a wing Autopilot_flight_leader = Player_obj; } if (The_mission.flags & MISSION_FLAG_USE_AP_CINEMATICS) LockAPConv = timestamp(); // lock convergence instantly else LockAPConv = timestamp(3000); // 3 seconds before we lock convergence Player_use_ai = 1; set_time_compression(1); lock_time_compression(true); // determine speed cap int i,j, wcount=1, tc_factor=1; float speed_cap = 1000000.0; // 1m is a safe starting point float radius = Player_obj->radius, distance = 0.0f, ftemp; bool capshipPresent = false; int capship_counts[3]; // three size classes capship_counts[0] = 0; capship_counts[1] = 0; capship_counts[2] = 0; int capship_placed[3]; // three size classes capship_placed[0] = 0; capship_placed[1] = 0; capship_placed[2] = 0; float capship_spreads[3]; capship_spreads[0] = 0.0f; capship_spreads[1] = 0.0f; capship_spreads[2] = 0.0f; SCP_vector<int> capIndexes; // empty the autopilot wings map autopilot_wings.clear(); // vars for usage w/ cinematic vec3d pos, norm1, perp, tpos, rpos = Player_obj->pos, zero; memset(&zero, 0, sizeof(vec3d)); // instantly turn player toward tpos if (The_mission.flags & MISSION_FLAG_USE_AP_CINEMATICS) { vm_vec_sub(&norm1, Navs[CurrentNav].GetPosition(), &Player_obj->pos); vm_vector_2_matrix(&Player_obj->orient, &norm1, NULL, NULL); } for (i = 0; i < MAX_SHIPS; i++) { if (Ships[i].objnum != -1 && (Ships[i].flags2 & SF2_NAVPOINT_CARRY || (Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags & WF_NAV_CARRY) ) ) { if (speed_cap > vm_vec_mag(&Ship_info[Ships[i].ship_info_index].max_vel)) speed_cap = vm_vec_mag(&Ship_info[Ships[i].ship_info_index].max_vel); } } // damp speed_cap to 90% of actual -- to make sure ships stay in formation if (The_mission.flags & MISSION_FLAG_USE_AP_CINEMATICS) speed_cap = 0.90f * speed_cap; if ( speed_cap < 1.0f ) { /* We need to deal with this so that incorrectly flagged ships will not cause the engine to fail to limit all the ships speeds correctly. */ Warning(LOCATION, "Ship speed cap is way too small (%f)!\n" "This is normally caused by a ship that has nav-carry-status set, but cannot move itself (like a Cargo container).\n" "Speed cap has been set to 1.0 m/s.", speed_cap); speed_cap = 1.0f; } ramp_bias = speed_cap/50.0f; // assign ship goals // when assigning goals to individual ships only do so if Ships[shipnum].wingnum != -1 // we will assign wing goals below for (i = 0; i < MAX_SHIPS; i++) { if (Ships[i].objnum != -1 && (Ships[i].flags2 & SF2_NAVPOINT_CARRY || (Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags & WF_NAV_CARRY) ) ) { // do we have capital ships in the area? if (Ship_info[Ships[i].ship_info_index].flags & ( SIF_CRUISER | SIF_CAPITAL | SIF_SUPERCAP | SIF_CORVETTE | SIF_AWACS | SIF_GAS_MINER | SIF_FREIGHTER | SIF_TRANSPORT)) { capshipPresent = true; capIndexes.push_back(i); // ok.. what size class if (Ship_info[Ships[i].ship_info_index].flags & (SIF_CAPITAL | SIF_SUPERCAP)) { capship_counts[0]++; if (capship_spreads[0] < Objects[Ships[i].objnum].radius) capship_spreads[0] = Objects[Ships[i].objnum].radius; } else if (Ship_info[Ships[i].ship_info_index].flags & (SIF_CORVETTE)) { capship_counts[1]++; if (capship_spreads[1] < Objects[Ships[i].objnum].radius) capship_spreads[1] = Objects[Ships[i].objnum].radius; } else { capship_counts[2]++; if (capship_spreads[2] < Objects[Ships[i].objnum].radius) capship_spreads[2] = Objects[Ships[i].objnum].radius; } } // check for bigger radius for usage later /*if (!vm_vec_cmp(&rpos, &Player_obj->pos)) // want to make sure rpos isn't player pos - we can worry about it being largest object's later { rpos = Objects[Ships[i].objnum].pos; }*/ if (Objects[Ships[i].objnum].radius > radius) { rpos = Objects[Ships[i].objnum].pos; radius = Objects[Ships[i].objnum].radius; } if (The_mission.flags & MISSION_FLAG_USE_AP_CINEMATICS) {// instantly turn the ship to match the direction player is looking //vm_vec_sub(&norm1, Navs[CurrentNav].GetPosition(), &Player_obj->pos); vm_vector_2_matrix(&Objects[Ships[i].objnum].orient, &norm1, NULL, NULL); } // snap wings into formation if (The_mission.flags & MISSION_FLAG_USE_AP_CINEMATICS && // only if using cinematics (Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags & WF_NAV_CARRY) // only if in a wing && Autopilot_flight_leader != &Objects[Ships[i].objnum]) //only if not flight leader's object { ai_info *aip = &Ai_info[Ships[i].ai_index]; int wingnum = aip->wing, wing_index = get_wing_index(&Objects[Ships[i].objnum], wingnum); vec3d goal_point; object *leader_objp = get_wing_leader(wingnum); if (leader_objp != &Objects[Ships[i].objnum]) { // not leader.. get our position relative to leader get_absolute_wing_pos_autopilot(&goal_point, leader_objp, wing_index, aip->ai_flags & AIF_FORMATION_OBJECT); } else { ai_clear_wing_goals(wingnum); j = 1+int( (float)floor(double(wcount-1)/2.0) ); switch (wcount % 2) { case 1: // back-left vm_vec_add(&perp, &zero, &Autopilot_flight_leader->orient.vec.rvec); //vm_vec_sub(&perp, &perp, &Player_obj->orient.vec.fvec); vm_vec_normalize(&perp); vm_vec_scale(&perp, -166.0f*j); // 166m is supposedly the optimal range according to tolwyn vm_vec_add(&goal_point, &Autopilot_flight_leader->pos, &perp); break; default: //back-right case 0: vm_vec_add(&perp, &zero, &Autopilot_flight_leader->orient.vec.rvec); //vm_vec_sub(&perp, &perp, &Player_obj->orient.vec.fvec); vm_vec_normalize(&perp); vm_vec_scale(&perp, 166.0f*j); vm_vec_add(&goal_point, &Autopilot_flight_leader->pos, &perp); break; } autopilot_wings[wingnum] = wcount; wcount++; } Objects[Ships[i].objnum].pos = goal_point; if (vm_vec_dist_quick(&Autopilot_flight_leader->pos, &Objects[Ships[i].objnum].pos) > distance) { distance = vm_vec_dist_quick(&Autopilot_flight_leader->pos, &Objects[Ships[i].objnum].pos); } } // lock primary and secondary weapons if ( LockWeaponsDuringAutopilot ) Ships[i].flags2 |= (SF2_PRIMARIES_LOCKED | SF2_SECONDARIES_LOCKED); // clear the ship goals and cap the waypoint speed ai_clear_ship_goals(&Ai_info[Ships[i].ai_index]); Ai_info[Ships[i].ai_index].waypoint_speed_cap = (int)speed_cap; // if they're not part of a wing set their goal if (Ships[i].wingnum == -1 || The_mission.flags & MISSION_FLAG_USE_AP_CINEMATICS) { if (Navs[CurrentNav].flags & NP_WAYPOINT) { ai_add_ship_goal_player( AIG_TYPE_PLAYER_SHIP, AI_GOAL_WAYPOINTS_ONCE, 0, ((waypoint_list*)Navs[CurrentNav].target_obj)->get_name(), &Ai_info[Ships[i].ai_index] ); //fixup has to wait until after wing goals } else { ai_add_ship_goal_player( AIG_TYPE_PLAYER_SHIP, AI_GOAL_FLY_TO_SHIP, 0, ((ship*)Navs[CurrentNav].target_obj)->ship_name, &Ai_info[Ships[i].ai_index] ); } } } } // assign wing goals if (!(The_mission.flags & MISSION_FLAG_USE_AP_CINEMATICS)) { for (i = 0; i < MAX_WINGS; i++) { if (Wings[i].flags & WF_NAV_CARRY ) { //ai_add_ship_goal_player( int type, int mode, int submode, char *shipname, ai_info *aip ); //ai_add_wing_goal_player( AIG_TYPE_PLAYER_WING, AI_GOAL_STAY_NEAR_SHIP, 0, target_shipname, wingnum ); //ai_add_wing_goal_player( AIG_TYPE_PLAYER_WING, AI_GOAL_WAYPOINTS_ONCE, 0, target_shipname, wingnum ); //ai_clear_ship_goals( &(Ai_info[Ships[num].ai_index]) ); ai_clear_wing_goals( i ); if (Navs[CurrentNav].flags & NP_WAYPOINT) { ai_add_wing_goal_player( AIG_TYPE_PLAYER_WING, AI_GOAL_WAYPOINTS_ONCE, 0, ((waypoint_list*)Navs[CurrentNav].target_obj)->get_name(), i ); // "fix up" the goal for (j = 0; j < MAX_AI_GOALS; j++) { if (Wings[i].ai_goals[j].ai_mode == AI_GOAL_WAYPOINTS_ONCE || Wings[i].ai_goals[j].ai_mode == AIM_WAYPOINTS ) { autopilot_ai_waypoint_goal_fixup(&(Wings[i].ai_goals[j])); } } } else { ai_add_wing_goal_player( AIG_TYPE_PLAYER_WING, AI_GOAL_FLY_TO_SHIP, 0, ((ship*)Navs[CurrentNav].target_obj)->ship_name, i ); } } } } // fixup has to go down here because ships are assigned goals during wing goals as well for (i = 0; i < MAX_SHIPS; i++) { if (Ships[i].objnum != -1) { if (Ships[i].flags2 & SF2_NAVPOINT_CARRY || (Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags & WF_NAV_CARRY)) for (j = 0; j < MAX_AI_GOALS; j++) { if (Ai_info[Ships[i].ai_index].goals[j].ai_mode == AI_GOAL_WAYPOINTS_ONCE || Ai_info[Ships[i].ai_index].goals[j].ai_mode == AIM_WAYPOINTS) { autopilot_ai_waypoint_goal_fixup( &(Ai_info[Ships[i].ai_index].goals[j]) ); // formation fixup //ai_form_on_wing(&Objects[Ships[i].objnum], &Objects[Player_ship->objnum]); } } } } start_dist = DistanceTo(CurrentNav); // ----------------------------- setup cinematic ----------------------------- if (The_mission.flags & MISSION_FLAG_USE_AP_CINEMATICS) { if (capshipPresent) { // position capships vec3d right, front, up, offset; for (SCP_vector<int>::iterator idx = capIndexes.begin(); idx != capIndexes.end(); ++idx) { vm_vec_add(&right, &Autopilot_flight_leader->orient.vec.rvec, &zero); vm_vec_add(&front, &Autopilot_flight_leader->orient.vec.fvec, &zero); vm_vec_add(&up, &Autopilot_flight_leader->orient.vec.uvec, &zero); vm_vec_add(&offset, &zero, &zero); if (Ship_info[Ships[*idx].ship_info_index].flags & (SIF_CAPITAL | SIF_SUPERCAP)) { //0 - below - three lines of position // front/back to zero vm_vec_add(&front, &zero, &zero); // position below vm_vec_scale(&up, capship_spreads[0]); // scale the up vector by the radius of the largest ship in this formation part switch (capship_placed[0] % 3) { case 1: // right vm_vec_scale(&right, capship_spreads[0]); break; case 2: // left vm_vec_scale(&right, -capship_spreads[0]); break; default: // straight case 0: vm_vec_add(&right, &zero, &zero); vm_vec_scale(&up, 1.5); // add an extra half-radius break; } // scale by row vm_vec_scale(&right, (1+((float)floor((float)capship_placed[0]/3)))); vm_vec_scale(&up, -(1+((float)floor((float)capship_placed[0]/3)))); capship_placed[0]++; } else if (Ship_info[Ships[*idx].ship_info_index].flags & SIF_CORVETTE) { //1 above - 3 lines of position // front/back to zero vm_vec_add(&front, &zero, &zero); // position below vm_vec_scale(&up, capship_spreads[1]); // scale the up vector by the radius of the largest ship in this formation part switch (capship_placed[1] % 3) { case 1: // right vm_vec_scale(&right, capship_spreads[1]); break; case 2: // left vm_vec_scale(&right, -capship_spreads[1]); break; default: // straight case 0: vm_vec_add(&right, &zero, &zero); vm_vec_scale(&up, 1.5); // add an extra half-radius break; } // scale by row vm_vec_scale(&right, (1+((float)floor((float)capship_placed[1]/3)))); vm_vec_scale(&up, (1+((float)floor((float)capship_placed[1]/3)))); // move ourselves up and out of the way of the smaller ships vm_vec_add(&perp, &Autopilot_flight_leader->orient.vec.uvec, &zero); vm_vec_scale(&perp, capship_spreads[2]); vm_vec_add(&up, &up, &perp); capship_placed[1]++; } else { //2 either side - 6 lines of position (right (dir, front, back), left (dir, front, back) ) // placing pattern: right, left, front right, front left, rear right, rear left // up/down to zero vm_vec_add(&up, &zero, &zero); switch (capship_placed[2] % 6) { case 5: // rear left vm_vec_scale(&right, -capship_spreads[2]); vm_vec_scale(&front, -capship_spreads[2]); break; case 4: // rear right vm_vec_scale(&right, capship_spreads[2]); vm_vec_scale(&front, -capship_spreads[2]); break; case 3: // front left vm_vec_scale(&right, -capship_spreads[2]); vm_vec_scale(&front, capship_spreads[2]); break; case 2: // front right vm_vec_scale(&right, capship_spreads[2]); vm_vec_scale(&front, capship_spreads[2]); break; case 1: // straight left vm_vec_scale(&right, 1.5); vm_vec_scale(&right, -capship_spreads[2]); vm_vec_add(&front, &zero, &zero); break; default: // straight right case 0: vm_vec_scale(&right, 1.5); vm_vec_scale(&right, capship_spreads[2]); vm_vec_add(&front, &zero, &zero); break; } // these ships seem to pack a little too tightly vm_vec_scale(&right, 2*(1+((float)floor((float)capship_placed[2]/3)))); vm_vec_scale(&front, 2*(1+((float)floor((float)capship_placed[2]/3)))); // move "out" by 166*(wcount-1) so we don't bump into fighters vm_vec_add(&perp, &Autopilot_flight_leader->orient.vec.rvec, &zero); vm_vec_scale(&perp, 166.0f*float(wcount-1)); if ( (capship_placed[2] % 2) == 0) vm_vec_add(&right, &right, &perp); else vm_vec_sub(&right, &right, &perp); capship_placed[2]++; } // integrate the up/down componant vm_vec_add(&offset, &offset, &up); //integrate the left/right componant vm_vec_add(&offset, &offset, &right); //integrate the left/right componant vm_vec_add(&offset, &offset, &front); // global scale the position by 50% //vm_vec_scale(&offset, 1.5); vm_vec_add(&Objects[Ships[*idx].objnum].pos, &Autopilot_flight_leader->pos, &offset); if (vm_vec_dist_quick(&Autopilot_flight_leader->pos, &Objects[Ships[*idx].objnum].pos) > distance) { distance = vm_vec_dist_quick(&Autopilot_flight_leader->pos, &Objects[Ships[*idx].objnum].pos); } } } ftemp = floor(Autopilot_flight_leader->phys_info.max_vel.xyz.z/speed_cap); if (ftemp >= 2.0f && ftemp < 4.0f) tc_factor = 2; else if (ftemp >= 4.0f && ftemp < 8.0f) tc_factor = 4; else if (ftemp >= 8.0f) tc_factor = 8; tpos = *Navs[CurrentNav].GetPosition(); // determine distance toward nav at which camera will be vm_vec_sub(&pos, &tpos, &Autopilot_flight_leader->pos); vm_vec_normalize(&pos); // pos is now a unit vector in the direction we will be moving the camera //norm1 = pos; vm_vec_scale(&pos, 5*speed_cap*tc_factor); // pos is now scaled by 5 times the speed (5 seconds ahead) vm_vec_add(&pos, &pos, &Autopilot_flight_leader->pos); // pos is now 5*speed cap in front of player ship switch (myrand()%24) // 8 different ways of getting perp points // 4 of which will not be used when capships are present (anything below, or straight above) { case 1: // down case 9: case 16: if (capship_placed[0] == 0) vm_vec_sub(&perp, &zero, &Autopilot_flight_leader->orient.vec.uvec); else { // become up-left vm_vec_add(&perp, &zero, &Autopilot_flight_leader->orient.vec.uvec); vm_vec_sub(&perp, &perp, &Autopilot_flight_leader->orient.vec.rvec); } break; case 2: // up case 10: case 23: vm_vec_add(&perp, &perp, &Autopilot_flight_leader->orient.vec.uvec); if (capshipPresent) // become up-right vm_vec_add(&perp, &perp, &Autopilot_flight_leader->orient.vec.rvec); break; case 3: // left case 11: case 22: vm_vec_sub(&perp, &zero, &Autopilot_flight_leader->orient.vec.rvec); break; case 4: // up-left case 12: case 21: vm_vec_sub(&perp, &zero, &Autopilot_flight_leader->orient.vec.rvec); vm_vec_add(&perp, &perp, &Autopilot_flight_leader->orient.vec.uvec); break; case 5: // up-right case 13: case 20: vm_vec_add(&perp, &zero, &Autopilot_flight_leader->orient.vec.rvec); vm_vec_add(&perp, &perp, &Autopilot_flight_leader->orient.vec.uvec); break; case 6: // down-left case 14: case 19: vm_vec_sub(&perp, &zero, &Autopilot_flight_leader->orient.vec.rvec); if (capship_placed[0] < 2) vm_vec_sub(&perp, &perp, &Autopilot_flight_leader->orient.vec.uvec); else vm_vec_add(&perp, &perp, &Autopilot_flight_leader->orient.vec.uvec); break; case 7: // down-right case 15: case 18: vm_vec_add(&perp, &zero, &Autopilot_flight_leader->orient.vec.rvec); if (capship_placed[0] < 1) vm_vec_sub(&perp, &perp, &Autopilot_flight_leader->orient.vec.uvec); else vm_vec_add(&perp, &perp, &Autopilot_flight_leader->orient.vec.uvec); break; default: case 0: // right case 8: case 17: perp = Autopilot_flight_leader->orient.vec.rvec; break; } vm_vec_normalize(&perp); //vm_vec_scale(&perp, 2*radius+distance); vm_vec_scale(&perp, Autopilot_flight_leader->radius+radius); // randomly scale up/down by up to 20% j = 20-myrand()%40; // [-20,20] vm_vec_scale(&perp, 1.0f+(float(j)/100.0f)); vm_vec_add(&cameraPos, &pos, &perp); if (capshipPresent) { vm_vec_normalize(&perp); // place it behind //vm_vec_copy_scale(&norm1, &Player_obj->orient.vec.fvec, -2*(Player_obj->radius+radius*(1.0f+(float(j)/100.0f)))); //vm_vec_add(&cameraTarget, &cameraTarget, &norm1); vm_vec_copy_scale(&cameraTarget,&perp, radius/5.0f); //vm_vec_scale(&cameraTarget, Player_obj->radius+radius*(1.0f+(float(j)/100.0f))); //vm_vec_add(&cameraTarget, &pos, &cameraTarget); //CameraSpeed = (radius+distance)/25; //vm_vec_add(&cameraTarget, &zero, &perp); //vm_vec_scale(&CameraVelocity, (radius+distance/100.f)); //vm_vec_scale(&CameraVelocity, 1.0f/float(NPS_TICKRATE*tc_factor)); } else { vm_vec_add(&cameraTarget, &zero, &zero); //CameraSpeed = 0; } //CameraMoving = false; EndAPCinematic = timestamp((10000*tc_factor)+NPS_TICKRATE); // 10 objective seconds before end of cinematic MoveCamera = timestamp((5500*tc_factor)+NPS_TICKRATE); camMovingTime = int(4.5*float(tc_factor)); set_time_compression((float)tc_factor); } return true; }
qboolean Pet_FindTarget(edict_t * self) { edict_t * enemy = 0; edict_t * PetOwner = self->monsterinfo.PetOwner; int radius = 500; // int bCammed = false; // follow mode means ignore combat if (self->monsterinfo.PetState & PET_FOLLOW) { self->enemy = 0; self->goalentity = PetOwner; return true; } // optional bonus for a pet actively being cammed // if (PetOwner->client->petcam == self) // { // bCammed = true; // radius = 1000; // } // help master if appropriate if (!(self->monsterinfo.PetState & PET_FREETARGET) && PetOwner->enemy) { vec3_t dir; double distance; VectorSubtract(self->s.origin,PetOwner->s.origin, dir); distance = VectorLength(dir); if ( distance < 400) enemy = PetOwner->enemy; } if (!enemy) enemy = FindEnemy(self, radius); if (enemy) { self->enemy = enemy; FoundTarget (self); if (!(self->monsterinfo.aiflags & AI_SOUND_TARGET) && (self->monsterinfo.sight)) self->monsterinfo.sight (self, self->enemy); return true; } // no enemy, what about following owner ? self->enemy = 0; // 2000/05/27 self->goalentity = 0; if (!(self->monsterinfo.PetState & PET_FREE) && visible(self, PetOwner)) { if (DistanceTo(self, PetOwner) > 100) { self->goalentity = PetOwner; self->monsterinfo.pausetime = level.time; } else { self->monsterinfo.stand (self); self->monsterinfo.pausetime = level.time + 30; } } return false; }
/* ================ rvMonsterStroggHover::Think ================ */ void rvMonsterStroggHover::Think ( void ) { idAI::Think ( ); if ( !aifl.dead ) { // If thinking we should play an effect on the ground under us if ( !fl.hidden && !fl.isDormant && (thinkFlags & TH_THINK ) && !aifl.dead ) { trace_t tr; idVec3 origin; idMat3 axis; // Project the effect 80 units down from the bottom of our bbox GetJointWorldTransform ( jointDust, gameLocal.time, origin, axis ); // RAVEN BEGIN // ddynerman: multiple clip worlds gameLocal.TracePoint ( this, tr, origin, origin + axis[0] * (GetPhysics()->GetBounds()[0][2]+80.0f), CONTENTS_SOLID, this ); // RAVEN END // Start the dust effect if not already started if ( !effectDust ) { effectDust = gameLocal.PlayEffect ( gameLocal.GetEffect ( spawnArgs, "fx_dust" ), tr.endpos, tr.c.normal.ToMat3(), true ); } // If the effect is playing we should update its attenuation as well as its origin and axis if ( effectDust ) { effectDust->Attenuate ( 1.0f - idMath::ClampFloat ( 0.0f, 1.0f, (tr.endpos - origin).LengthFast ( ) / 127.0f ) ); effectDust->SetOrigin ( tr.endpos ); effectDust->SetAxis ( tr.c.normal.ToMat3() ); } // If the hover effect is playing we can set its end origin to the ground /* if ( effectHover ) { effectHover->SetEndOrigin ( tr.endpos ); } */ } else if ( effectDust ) { effectDust->Stop ( ); effectDust = NULL; } //Try to circle strafe or pursue if ( circleStrafing ) { CircleStrafe(); } else if ( !inPursuit ) { if ( !aifl.action && move.fl.done && !aifl.scripted ) { if ( GetEnemy() ) { if ( DistanceTo( GetEnemy() ) > 2000.0f || (GetEnemy()->GetPhysics()->GetLinearVelocity()*(GetEnemy()->GetPhysics()->GetOrigin()-GetPhysics()->GetOrigin())) > 1000.0f ) {//enemy is far away or moving away from us at a pretty decent speed TryStartPursuit(); } } } } else { Pursue(); } //Dodge if ( !circleStrafing ) { if( combat.shotAtTime && gameLocal.GetTime() - combat.shotAtTime < 1000.0f ) { if ( nextBombFireTime < gameLocal.GetTime() - 3000 ) { if ( gameLocal.random.RandomFloat() > evadeChance ) { //40% chance of ignoring it - makes them dodge rockets less often but bullets more often? combat.shotAtTime = 0; } else if ( evadeDebounce < gameLocal.GetTime() ) { //ramps down from 400 to 100 over 1 second float speed = evadeSpeed - ((((float)(gameLocal.GetTime()-combat.shotAtTime))/1000.0f)*(evadeSpeed-(evadeSpeed*0.25f))); idVec3 evadeVel = viewAxis[1] * ((combat.shotAtAngle >= 0)?-1:1) * speed; evadeVel.z *= 0.5f; move.addVelocity += evadeVel; move.addVelocity.Normalize(); move.addVelocity *= speed; /* if ( move.moveCommand < NUM_NONMOVING_COMMANDS ) { //just need to do it once? combat.shotAtTime = 0; } */ if ( evadeDebounceRate > 1 ) { evadeDebounce = gameLocal.GetTime() + gameLocal.random.RandomInt( evadeDebounceRate ) + (ceil(((float)evadeDebounceRate)/2.0f)); } } } } } //If using melee rush to nav to him, stop when we're close enough to attack if ( combat.tacticalCurrent == AITACTICAL_MELEE && move.moveCommand == MOVE_TO_ENEMY && !move.fl.done && nextBombFireTime < gameLocal.GetTime() - 3000 && enemy.fl.visible && DistanceTo( GetEnemy() ) < 2000.0f ) { StopMove( MOVE_STATUS_DONE ); ForceTacticalUpdate(); } else { //whenever we're not in the middle of something, force an update of our tactical if ( !aifl.action ) { if ( !aasFind ) { if ( move.fl.done ) { if ( !inPursuit && !circleStrafing ) { ForceTacticalUpdate(); } } } } } } //update light // if ( lightOn ) { UpdateLightDef ( ); // } }
// The only difference between ProjectPoint and // ProjectVector is the addition of m_Distance... Vector Plane::ProjectPoint(const Vector& v) const { return (v - (m_Normal * DistanceTo(v))); }
/* virtual methods from class ObservationZone */ virtual bool IsInSector(const GeoPoint &location) const override { return DistanceTo(location) <= radius; }