示例#1
0
void DoTargetedCommand(int x, int y, Unit *target, int fow_unit)
{
    if (!*bw::is_targeting)
        return;
    EndTargeting();

    int16_t order, error = -1;
    bool can_attack = false, can_cast_spell = false, has_energy = false;

    if (target)
        order = *bw::unit_order_id;
    else if (fow_unit != Unit::None)
        order = *bw::obscured_unit_order_id;
    else
        order = *bw::ground_order_id;

    int targeting_weapon = orders_dat_targeting_weapon[order];
    int weapon_targeting = orders_dat_use_weapon_targeting[order];
    int energy = 0, tech = orders_dat_energy_tech[order];
    if (tech != Tech::None)
        energy = techdata_dat_energy_cost[tech] * 256;

    if (orders_dat_obscured[order] == Order::None)
        fow_unit = Unit::None;

    for (unsigned i = 0; i < Limits::Selection; i++)
    {
        Unit *unit = bw::client_selection_group[i];
        if (!unit)
            break;
        if (unit->IsDisabled())
            continue;
        if (weapon_targeting)
        {
            if (targeting_weapon == Weapon::None)
            {
                if (!target)
                {
                    if (unit->unit_id == Unit::InfestedTerran || unit->CanAttackFowUnit(fow_unit))
                        can_attack = true;
                }
                else
                {
                    if (unit->GetRClickAction() == RightClickAction::Attack) // sieged tank, towerit, etc
                    {
                        if (IsOutOfRange(unit, target))
                        {
                            error = String::Error_OutOfRange;
                            continue;
                        }
                        else if (IsTooClose(unit, target))
                        {
                            error = String::Error_TooClose;
                            continue;
                        }
                    }
                    can_attack |= unit->CanAttackUnit(target, true);
                }
            }
            else
            {
                if (!CanHitUnit(target, unit, targeting_weapon) && (fow_unit != Unit::None || units_dat_flags[fow_unit] & UnitFlags::Invincible))
                {
                    continue;
                }
                if (!NeedsMoreEnergy(unit, energy))
                    has_energy = true;
                can_attack = true;
            }

        }
        else if (tech != Tech::None)
        {
            if (CanTargetSpell(unit, x, y, &error, tech, target, fow_unit))
            {
                if (!NeedsMoreEnergy(unit, energy))
                    has_energy = true;
                can_cast_spell = true;
            }
        }
        else if (fow_unit == Unit::None)
        {
            CanTargetOrder(unit, target, order, &error); // Not checking anything, just to get error
        }
        else
        {
            CanTargetOrderOnFowUnit(unit, fow_unit, order, &error); // Same
        }
    }

    Unit *unit = *bw::selection_rank_order;

    if (weapon_targeting)
    {
        if (!can_attack || error != -1)
        {
            GetAttackErrorMessage(target, targeting_weapon, &error);
            ShowInfoMessage(error, Sound::Error_Zerg + unit->GetRace(), unit->player);
            if (targeting_weapon == Weapon::None)
                SendTargetedOrderCommand(order, x, y, target, fow_unit, *bw::is_queuing_command); // So it'll move there anyways
            return;
        }
        else if (energy && !has_energy)
        {
            int race = unit->GetRace();
            ShowInfoMessage(String::NotEnoughEnergy + race, Sound::NotEnoughEnergy + race, unit->player);
            return;
        }
    }
    else if (energy)
    {
        if (!can_cast_spell)
        {
            if (error == -1)
                error = String::Error_InvalidTarget;
            ShowErrorMessage((*bw::stat_txt_tbl)->GetTblString(error), *bw::command_user, unit);
            return;
        }
        else if (/*energy && */!has_energy)
        {
            int race = unit->GetRace();
            ShowInfoMessage(String::NotEnoughEnergy + race, Sound::NotEnoughEnergy + race, unit->player);
            return;
        }
    }
    if (error != -1)
    {
        ShowErrorMessage((*bw::stat_txt_tbl)->GetTblString(error), unit->player, unit);
    }
    else
    {
        PlayYesSoundAnim(bw::selection_rank_order[0]);
        SendTargetedOrderCommand(order, x, y, target, fow_unit, *bw::is_queuing_command);
    }
}