HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Blocking AI orders?

09-28-2007, 08:20 PM#1
Blackroot
Hey, I'm looking for a quick way to stop all artificial input on a certain target unit, but without stopping it from receiving player orders. Basicaly, I want to stop my unit from doing anything unless directly ordered to. (IE: Stopping a melee unit from walking up to an enemy just because he's in range.) I know I can cut the acusition range of the unit, but he'll still fight back if hit.

Thanks, Blackroot.
09-28-2007, 08:26 PM#2
moyack
Unfortunately is not as easy as putting a command, the AI sends orders continuously to the units, so the only solution is fighting fire with fire, in other words, sending repeatedly order commands.

I've done this by sending every 0.2 - 0.4 seconds a specific order, and the unit behaves properly. Do your test and tell me if it works for you :)
09-28-2007, 10:03 PM#3
Blackroot
Doesn't work, my unit still is displaced slightly enough to damage my triggers. I'm fairly sure there's a way to block orders, I'm running through the list right now.

[edit]
Bleh I can mute whole player AI orders but not individuals, looks like I'll have to order my units to stop each time they receive an order. What a waste of clock cycles :(
09-28-2007, 10:39 PM#4
rain9441
If all your after is getting rid of unit's autoattack move then add UNIT_TYPE_PEON classification to them upon creation and set their CanFlee attribute to false. They wont auto engage, it'll be similar to them holding position.
09-29-2007, 12:10 AM#5
moyack
Quote:
Originally Posted by Blackroot
Doesn't work, my unit still is displaced slightly enough to damage my triggers.
Damage triggers?? I don't understand.

Let me show one code i did months ago, where I can control an AI worker, so it can build a shipyard in water terrain, something that a normal AI wouldn't do it normally. Please read the comments.

Collapse JASS:
// Force to build a Shipyard in the right pathing.
function Force_to_build_shipyards_Conditions takes nothing returns boolean
    local unit u = GetTriggerUnit()
    local player p = GetOwningPlayer(u)
    local race r = GetPlayerRace(p)
    local boolean b1 = FALSE
    local boolean b2 = GetPlayerController(p) == MAP_CONTROL_COMPUTER
    if r == RACE_ORC then
        set b1 = CountLivingPlayerUnitsOfTypeId('o004', p) < 1
    elseif r == RACE_HUMAN then
        set b1 = CountLivingPlayerUnitsOfTypeId('h00A', p) < 1
    endif
    set u = null
    set p = null
    set r = null
    return b1 and b2
endfunction

function Force_to_build_shipyards_DeathConditions takes nothing returns boolean
    local unit u = GetDyingUnit()
    local player p = GetOwningPlayer(u)
    local race r = GetUnitRace(u)
    local boolean b1 = FALSE
    local boolean b2 = GetPlayerController(p) == MAP_CONTROL_COMPUTER
    if r == RACE_ORC then
        set b1 = GetUnitTypeId(u) == 'o004'
    elseif r == RACE_HUMAN then
        set b1 = GetUnitTypeId(u) == 'h00A'
    endif
    set u = null
    set p = null
    set r = null
    return b1 and b2
endfunction

function Force_to_build_shipyards_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local player p = GetOwningPlayer(u)
    local race r = GetPlayerRace(p)
    local real x
    local real y
    local real angle = GetRandomReal(0, 2 * bj_PI)
    local integer i
    local group g
    loop  // <= Checks if it has resources
        exitwhen GetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD) >= 400 and GetPlayerState(p, PLAYER_STATE_RESOURCE_LUMBER) >= 100
        call TriggerSleepAction(1.0)
    endloop
    if r == RACE_ORC then //<= gets the correct worker type
        set i = 'o003'
    else
        set i = 'h000'
    endif
    set u = null
    loop //  <= Gets one of the workers
        set g = GetUnitsOfPlayerAndTypeId(p, i)
        set u = FirstOfGroup(g)
        call DestroyGroup(g)
        exitwhen u != null
        call TriggerSleepAction(10.0)
    endloop
    if r == RACE_ORC then // <= selects the racial shipyard
        set i = 'o004'
    else
        set i = 'h00A'
    endif
    loop // Detects a right path and force the AI to build that shipyard
        set x = GetPlayerStartLocationX(p)
        set y = GetPlayerStartLocationY(p)
        set x = x + 6000.0 * Cos( angle )
        set y = y + 6000.0 * Sin( angle )
        call IssuePointOrder(u, "move", x, y) // force to the worker to move to any point
        call TriggerSleepAction(0.5)
        exitwhen IssueBuildOrderById(u, i, GetUnitX(u), GetUnitY(u)) //order to the worker to build in its current place, if true, it's because it was able to do it :)
        set angle = angle + bj_PI / 120.0
    endloop
    set x = GetUnitX(u)
    set y = GetUnitY(u)
    set p = null
    set r = null
    set u = null
    set g = null  
endfunction

//===========================================================================
function InitTrig_Force_to_build_shipyards takes nothing returns nothing
    local trigger t = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_UPGRADE_FINISH )
    call TriggerAddCondition( t, Condition( function Force_to_build_shipyards_Conditions ) )
    call TriggerAddAction( t, function Force_to_build_shipyards_Actions )
    set t = null
    set t = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_DEATH )
    call TriggerAddCondition( t, Condition( function Force_to_build_shipyards_DeathConditions ) )
    call TriggerAddAction( t, function Force_to_build_shipyards_Actions )
    set t = null
endfunction

As you can see, I use a periodic loop that forces to the unit to accomplish its task, I'm pretty sure that you can do something similar with you AI. I hope this can help you.
09-29-2007, 04:05 AM#6
Blackroot
I found an alternate solution, I created a local trigger to issue the stop command every time the unit attained a target, or found a target in acquisition range. This makes it so you can issue any player-order and still have no artificial input for the duration.