• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[AI] Boss Attack Scripting

Status
Not open for further replies.
Level 17
Joined
Feb 11, 2011
Messages
1,860
Hello guys,

I am trying to write a script for the first boss (Lich) in my map. Here it is:
JASS:
function Boss_Cast_Abilities_Conditions takes nothing returns boolean
    return (IsPlayerEnemy(GetOwningPlayer(GetFilterUnit()), Player(11)) == true) and (UnitHasBuffBJ(GetFilterUnit(), 'B003') == false) and (IsUnitType(GetFilterUnit(), UNIT_TYPE_HERO) == true)
endfunction

function Boss_Cast_Abilities takes nothing returns nothing
    local real life
    local unit u
    local unit targ
    local unit boss = udg_Boss_Unit
    local real x = GetUnitX(boss)
    local real y = GetUnitY(boss)
    local real x2
    local real y2
    //Picking hero with the lowest hit points:
    call GroupEnumUnitsInRange(bj_lastCreatedGroup, x, y, 800, Condition(function Boss_Cast_Abilities_Conditions))
    set life = GetUnitState(GroupPickRandomUnit(bj_lastCreatedGroup), UNIT_STATE_LIFE)
    loop
        set u = FirstOfGroup(bj_lastCreatedGroup)
        exitwhen u == null
        if (GetUnitState(u, UNIT_STATE_LIFE) < life) then
            set life = GetUnitState(u, UNIT_STATE_LIFE)
            set targ = u
        endif  
        call GroupRemoveUnit(bj_lastCreatedGroup, u)
    endloop
    if (targ == null) then
        return 
    endif
    //Casting orders - level 5 (Lich):
    if (GetUnitTypeId(boss) == 'U007') then //Checks whether the boss is the level 5 boss.
        //Breath of Frost:
        set x = GetUnitX(targ)
        set y = GetUnitY(targ)
        call IssuePointOrder(boss, "breathoffrost", x2, y2)
        //Frost Pulse (heal):
        if (GetUnitLifePercent(boss) < 75) then
            call IssueTargetOrder(boss, "holybolt", boss)
        endif
    endif
    set u = null
    set targ = null
    set boss = null
endfunction

function InitTrig_Boss_Cast_Abilities takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterTimerEventPeriodic(t, 0.03)
    call TriggerAddAction(t, function Boss_Cast_Abilities)
    set t = null
endfunction
Explanation
Basically, it checks periodically how many heroes are within 800 range of the boss that don't have an invisibility buff. The system then picks the hero with the least life (not lowest percentage). It then orders the boss to cast "Breath of Frost" on this hero. Then, when the boss is below 75% health, he casts heal on himself.
Do you have any tips for me on how to improve this? It seems to be working - just wandering how I can improve the script.

Thanks for reading!

P.S. I am still learning JASS/vJASS, so go easy on me! :grin:
 
Level 14
Joined
Nov 18, 2007
Messages
1,084
  • In your filter method, it'd probably be easier to use IsUnitEnemy rather than IsPlayerEnemy.
  • Use GetWidgetLife instead of GetUnitState.
  • To elaborate on Maker's point of using I/T/E:
    JASS:
    local boolean healing = false // True only if the boss can cast the spell on itself
    // ...
    if GetWidgetLife(boss)/GetUnitState(boss, UNIT_STATE_MAX_LIFE) < 0.75 then
        set healing = IssueTargetOrder(boss, "holybolt", boss)
    endif
    
    // If the boss can't heal, try nuking
    if not healing then
        set x2 = GetUnitX(targ)
        set y2 = GetUnitY(targ)
        call IssuePointOrder(boss, "breathoffrost", x2, y2)
    endif
  • I think you should use a timer over a trigger for periodic enumeration. Your timer period might also be a bit too high.
 
Level 17
Joined
Feb 11, 2011
Messages
1,860
@Maker:
With reference to GetUnitAbilityLevel, what happens if my hero has the ability "Wind Walk" but does NOT have Wind Walk buff? Won't it exclude him?

@watermelon_1234:
Does GetWidgetLife apply for percentages? I want to boss to heal himself when he has 75% or less HP.
Also, what happens when the boss reaches less than 75% HP and the heal is cooling down? Surely it will try to cast it but won't be able to, and it will skip the nuke?

General:
Is there no non-BJ way to count the units in a group? I want to know this because I will skip the rest of the actions if there are no enemies within 800 range of the boss.
 
Level 14
Joined
Nov 18, 2007
Messages
1,084
Does GetWidgetLife apply for percentages? I want to boss to heal himself when he has 75% or less HP.
The example code I posted showed you how to do that. You need to divide the current life of the unit by the unit's maximum life like the BJ does to get the percentage.
JASS:
if GetWidgetLife(boss)/GetUnitState(boss, UNIT_STATE_MAX_LIFE) < 0.75 then
Also, what happens when the boss reaches less than 75% HP and the heal is cooling down? Surely it will try to cast it but won't be able to, and it will skip the nuke?
It will not skip the nuke because IssueTargetOrder would return false for healing while the ability is on cooldown or when the boss can't issue the healing spell on itself for whatever reason.
Is there no non-BJ way to count the units in a group? I want to know this because I will skip the rest of the actions if there are no enemies within 800 range of the boss.
With the way you've coded it, you could just initialize targ as null. If targis not set to u, your code would already skip the rest of the actions.
 
Status
Not open for further replies.
Top