WayPoint ResetCurrentWP (TaskForce tf) { WayPoint w; GridIndex x,y,ux,uy; w = tf->GetCurrentUnitWP(); while (w && w->GetWPDepartureTime() < Camp_GetCurrentTime()) { if (w->GetWPFlags()) // Make sure we actually get here, it's important { w->GetWPLocation(&x,&y); tf->GetLocation(&ux,&uy); if (DistSqu(x,y,ux,uy) > 2.0F) return w; if (DoWPAction(tf,w)) return tf->GetCurrentUnitWP(); } w = w->GetNextWP(); tf->SetCurrentUnitWP(w); } return w; }
int TaskForceClass::MoveUnit (CampaignTime time) { GridIndex x = 0, y = 0; GridIndex nx = 0, ny = 0; GridIndex ox = 0, oy = 0; WayPoint w = NULL, ow = NULL; Objective o = NULL; int moving = 1; CampaignHeading h = 0; // RV - Biker // Naval units now have three modes: // (a) Sit still in harbor // (b) Do a 20 km track (repeating waypoints) // (c) Followy WPs GetLocation(&x,&y); w = ResetCurrentWP(this); FindNearestUnit(x, y, NULL); // Check for mode a o = FindNearestObjective(x, y, NULL, 1); // RV - Biker - If we are in port and have no WPs do nothing if (o && o->GetType() == TYPE_PORT && !w) { return TRUE; } // If not in port and no WPs... create a repeating path 20 km north and back if (!w) { DisposeWayPoints(); w = AddUnitWP(x, y, 0, 60, TheCampaign.CurrentTime + (rand()%15), 0, 0); w->SetWPFlags(WPF_REPEAT); // This should prevent naval units to run into ground if (GetCover(x, y+20) == Water) { w = AddUnitWP(x, y+20, 0, 60, TheCampaign.CurrentTime + (15+(rand()%15))*CampaignMinutes, 0, 0); } else { w = AddUnitWP(x, y, 0, 60, TheCampaign.CurrentTime + 15*CampaignMinutes, 0, 0); } w->SetWPFlags(WPF_REPEAT); w = AddUnitWP(x, y, 0, 60, TheCampaign.CurrentTime + (30+(rand()%15))*CampaignMinutes, 0xffffffff, 0); w->SetWPFlags(WPF_REPEAT); SetCurrentWaypoint (1); w = GetCurrentUnitWP(); } w->GetWPLocation(&nx, &ny); // RV - Biker - Wait for departure if (Camp_GetCurrentTime() < w->GetWPDepartureTime()) { SetUnitLastMove(Camp_GetCurrentTime()); return 0; } // Move, if we're not at destination if (x!=nx || y!=ny) { if (w) ow = w->GetPrevWP(); if (ow) ow->GetWPLocation(&ox, &oy); else GetLocation(&ox, &oy); while (moving) { h = DirectionTo(ox, oy, nx, ny, x, y); if (h > 7) { moving = 0; h = Here; } // This is kinda hacky - basically, limit change in direction to 45 deg per move if (h > last_direction) { if (h - last_direction < 5) h = (last_direction+1) & 0x07; else h = (last_direction+7) & 0x07; } else if (h < last_direction) { if (last_direction - h < 5) h = (last_direction+7) & 0x07; else h = (last_direction+1) & 0x07; } //this moves the unit if (ChangeUnitLocation(h) > 0) { last_direction = h; } else { moving = 0; } // Now do combat if (GetCombatTime() > CombatTime()) { DoCombat(); } } } return 0; }
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; }