Пример #1
0
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);
			}
		}
	}
}
Пример #2
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;
}