void MonkeyScript::IssueCommands() { BattleCommander* monkeyCommander = nullptr; for (BattleCommander* commander : _simulator->GetCommanders()) if (commander->GetType() == BattleCommanderType::Player) { monkeyCommander = commander; break; } if (monkeyCommander == nullptr) return; std::vector<Unit*> monkeyUnits; std::vector<Unit*> enemyUnits; for (Unit* unit : _simulator->GetUnits()) if (!unit->state.IsRouting()) { if (unit->commander == monkeyCommander) monkeyUnits.push_back(unit); else if (unit->commander->GetTeam() != monkeyCommander->GetTeam()) enemyUnits.push_back(unit); } if (enemyUnits.empty()) return; if (monkeyUnits.empty()) return; glm::vec2 playerCenter = FindClusterCenter(enemyUnits); glm::vec2 scriptCenter = FindClusterCenter(monkeyUnits); for (Unit* unit : monkeyUnits) { glm::vec2 unitCenter = unit->state.center; Unit* targetUnit = FindNearestUnit(enemyUnits, unitCenter); if (targetUnit == nullptr) continue; glm::vec2 targetCenter = targetUnit->state.center; if (unit->stats.missileType != MissileType::None) { float range = unit->stats.maximumRange; glm::vec2 diff = targetCenter - unitCenter; float dist = glm::length(diff); if (dist > 0.9f * range) { glm::vec2 destination = targetCenter - 0.9f * range * glm::normalize(diff); UnitCommand command; command.path.push_back(unitCenter); command.path.push_back(destination); command.bearing = angle(destination - unitCenter); _simulator->SetUnitCommand(unit, command, 0); } else if (dist < 0.5f * range) { glm::vec2 destination = targetCenter - 0.7f * range * glm::normalize(diff); UnitCommand command; command.path.push_back(unitCenter); command.path.push_back(destination); command.bearing = angle(destination - unitCenter); command.running = true; _simulator->SetUnitCommand(unit, command, 0); } else { UnitCommand command; command.bearing = angle(targetCenter - unitCenter);; _simulator->SetUnitCommand(unit, command, 0); } } else { if (glm::distance(targetUnit->state.center, unitCenter) < 80) { UnitCommand command; command.path.push_back(unitCenter); command.path.push_back(targetCenter); command.bearing = angle(targetCenter - unitCenter); _simulator->SetUnitCommand(unit, command, 0); } else { glm::vec2 diff = unitCenter - scriptCenter; float dist = glm::length(diff); if (dist > 100) diff *= 100 / dist; glm::vec2 destination = playerCenter + diff; UnitCommand command; command.path.push_back(unitCenter); command.path.push_back(destination); command.bearing = angle(destination - unitCenter); _simulator->SetUnitCommand(unit, command, 0); } } } }
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; }