T Azimuth(m2::Point<T> const & p1, m2::Point<T> const & p2, T north = 0) { T azimuth = math::pi2 - (AngleTo(p1, p2) + north); if (azimuth < 0) azimuth += math::twicePi; return azimuth; }
int TaskForceClass::GetVehicleDeagData (SimInitDataClass *simdata, int remote) { static CampEntity ent; static int round; int dist, i, ptIndexAt; // Reinitialize static vars upon query of first vehicle if (simdata->vehicleInUnit < 0) { simdata->vehicleInUnit = 0; ent = NULL; if (!remote) { // Used only in port round = 0; simdata->ptIndex = GetDeaggregationPoint(0, &ent); if (simdata->ptIndex) { // Yuck! The first call returns only the list index, NOT a real point index. // To ensure we have at least one set of points we have to actually query for them // then reset again... simdata->ptIndex = GetDeaggregationPoint(0, &ent); if (simdata->ptIndex) simdata->ptIndex = GetDeaggregationPoint(0, &ent); ent = NULL; GetDeaggregationPoint(0, &ent); } // Used only at sea WayPoint w; w = GetCurrentUnitWP(); if (w) { // Find heading to next waypoint GridIndex ux,uy,wx,wy; GetLocation(&ux,&uy); w->GetWPLocation(&wx,&wy); simdata->heading = AngleTo(ux,uy,wx,wy); } } } else { simdata->vehicleInUnit++; } if (!remote) { if (simdata->ptIndex) { // In port float dx, dy; // Find the center point and direction point for this ship simdata->ptIndex = GetDeaggregationPoint(simdata->campSlot, &ent); ptIndexAt = GetDeaggregationPoint(simdata->campSlot, &ent); if (!ptIndexAt) { ShiAssert( !simdata->ptIndex ); // We should always have an even number of points // Reuse the old points, but with an offset ent = NULL; GetDeaggregationPoint(simdata->campSlot, &ent); // Reset simdata->ptIndex = GetDeaggregationPoint(simdata->campSlot, &ent); ptIndexAt = GetDeaggregationPoint(simdata->campSlot, &ent); round++; } ShiAssert( ptIndexAt ); // We must have at least two points (center and toward) TranslatePointData(ent, simdata->ptIndex, &simdata->x, &simdata->y); // Face toward the "at" point dx = PtDataTable[ptIndexAt].yOffset - PtDataTable[simdata->ptIndex].yOffset; // KCK NOTE: axis' are reversed dy = PtDataTable[ptIndexAt].xOffset - PtDataTable[simdata->ptIndex].xOffset; // KCK NOTE: axis' are reversed simdata->heading = (float)atan2(dx,dy); // If we reused a point, shift our center point along the at vector simdata->x += dx * round; simdata->y += dy * round; } else { // At sea dist = (simdata->vehicleInUnit - 1) >> 2; switch ( (simdata->vehicleInUnit - 1) & 0x3 ) { case 0: simdata->x = XPos() - 1500.0f - 1500.0f * dist; simdata->y = YPos() - 1500.0f - 1500.0f * dist; break; case 1: simdata->x = XPos() + 1500.0f + 1500.0f * dist; simdata->y = YPos() - 1500.0f - 1500.0f * dist; break; case 2: simdata->x = XPos() + 1500.0f + 1500.0f * dist; simdata->y = YPos() + 1500.0f + 1500.0f * dist; break; case 3: default: simdata->x = XPos() - 1500.0f - 1500.0f * dist; simdata->y = YPos() + 1500.0f + 1500.0f * dist; break; } } } // We're always at sea level simdata->z = 0.0f; // Determine skill (Sim only uses it for anti-air stuff right now, so bow to expedience simdata->skill = ((TeamInfo[GetOwner()]->airDefenseExperience - 60) / 10) + rand()%3 - 1; // simdata->skill = ((TeamInfo[GetOwner()]->navalExperience - 60) / 10) + rand()%3 - 1; // Clamp it to legal sim side values if (simdata->skill > 4) simdata->skill = 4; if (simdata->skill < 0) simdata->skill = 0; // Weapon loadout for (i=0; i<HARDPOINT_MAX; i++) { simdata->weapon[i] = GetUnitWeaponId(i,simdata->campSlot); if (simdata->weapon[i]) simdata->weapons[i] = GetUnitWeaponCount(i,simdata->campSlot); else simdata->weapons[i] = 0; } simdata->playerSlot = NO_PILOT; simdata->waypointList = CloneWPToList(GetFirstUnitWP(),NULL); return MOTION_GND_AI; }
Heading Position::HeadingTo (const Position &Other_i) { return Heading::DegToHeading (AngleTo (Other_i)); }