请选择 进入手机版 | 继续访问电脑版

GA地精研究院

 找回密码
 立即注册
查看: 4093|回复: 18

[演示&系统] 可移植智能AI对战系统+万能对战AI模板

[复制链接]
发表于 2013-8-25 16:44:38 | 显示全部楼层 |阅读模式
智能AI对战系统
用了半个月才完成的坑爹AI系统,功能是强化对战AI,有点类似于AMAI的一个系统,不过可塑性比AMAI强,因为WEer可以移植到任意一张地图中,并根据实际需要自行修改这个系统,也就是说即使是自创种族也能运行该AI系统,并且不受 魔兽版本限制 。


该系统主要的功能:
-普通单位、英雄补刀(正反)
-受伤单位回避
-保护残血英雄(使用回城卷轴、无敌药水等)
-集中火力攻击血量较少的单位
-部队优先攻击弱势单位
-势力强弱判定,强迫弱势部队逃跑
-主动攻击被忽略的敌人
-改进某些单位的技能释放环境
-改进英雄某些技能的释放环境(如剑圣会用疾风步偷袭对手、牛头人会用踩地板限制敌方英雄等)
-改进英雄对某些物品的使用环境(恢复卷轴、医疗剂等)
-英雄会寻找AI建造位置偏僻的商店(四族的商店)
-英雄试图寻找地精商店并购买物品(目前设定有小型无敌药水、回城卷轴、生命护身符、尘土之影)
-英雄会使用物品应对敌方隐形英雄(尘土之影)
-降低部队生产后被建筑卡住的概率
-允许AI玩家感到无力回天时自宫





 楼主| 发表于 2013-8-25 16:47:02 | 显示全部楼层
本帖最后由 金皮蛋 于 2013-8-25 16:49 编辑

使用方法(注意顺序):
将该AI系统代码复制到地图自定义脚本区

A1.JPG
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-25 16:50:04 | 显示全部楼层
触发=动作-自定义代码-输入
call AIsystem_StartAI()【开启智能AI系统】
call AIsystem_UnlockIMBAmode()【启用疯狂模式(默认为关闭)】
call AIsystem_ChangePlayerName()【允许修改AI玩家名字】
call AIsystem_LockIMBAmode()【关闭疯狂模式(默认为关闭)】

call AIsystem_UseAIForPlayer(Player(0))【为某玩家运行AI系统(Player(0)为玩家1,Player(1)为玩家2...)】
call AIsystem_StopAIForPlayer(Player(0))【为某玩家停止AI系统(Player(0)为玩家1,Player(1)为玩家2...)】



A2.JPG
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-25 16:52:03 | 显示全部楼层
代码:


library AIsystem

globals
//***************AISettings
//AISettings

//Item
private constant integer Item_stwp = 'stwp'
private constant integer Item_pnvl = 'pnvl'
private constant integer Item_dust = 'dust'
private constant integer Item_prvt = 'prvt'
private constant integer Item_hslv = 'hslv'
private constant integer Item_sreg = 'sreg'
//Unit
private constant integer Unit_Pea = 'hpea'
private constant integer Unit_PeaSol = 'hmil'
private constant integer Unit_Bat = 'otbr'
private constant integer Unit_DrTalon = 'edot'
private constant integer Unit_DrTalonM = 'edtm'
private constant integer Unit_DrClaw = 'edoc'
private constant integer Unit_Statue = 'uobs'
private constant integer Unit_Shop = 'ngme'
private constant integer Unit_HShop = 'hvlt'
private constant integer Unit_OShop = 'ovln'
private constant integer Unit_UShop = 'utom'
private constant integer Unit_EShop = 'eden'
//Hero
private constant integer Hero_MK = 'Hmkg'
private constant integer Hero_PLA = 'Hpla'
private constant integer Hero_AM = 'Hamg'
private constant integer Hero_BLM = 'Hblm'
private constant integer Hero_BM = 'Obla'
private constant integer Hero_SH = 'Oshd'
private constant integer Hero_TC = 'Otch'
private constant integer Hero_FS = 'OFar'
private constant integer Hero_DK = 'Udea'
private constant integer Hero_LICH = 'Ulic'
private constant integer Hero_CL = 'Ucrl'
private constant integer Hero_DR = 'Udre'
private constant integer Hero_KOG = 'Ekee'
private constant integer Hero_POM = 'Emoo'
private constant integer Hero_DH = 'Edem'
private constant integer Hero_WD = 'Ewar'
//Ability
private constant integer Skill_Thunderbolt = 'AHtb'
private constant integer Skill_Blizzard = 'AHbz'
private constant integer Skill_flamestrike = 'AHfs'
private constant integer Skill_Holybolt = 'AHhb'
private constant integer Skill_Windwalk = 'AOwk'
private constant integer Skill_Stomp = 'AOws'
private constant integer Skill_Hex = 'AOhx'
private constant integer Skill_Lighting = 'AOcl'
private constant integer Skill_Deathcoil = 'AUdc'
private constant integer Skill_Frostnova = 'AUfn'
private constant integer Skill_Sleep = 'AUsl'
private constant integer Skill_Roots = 'AEer'
private constant integer Skill_Blink = 'AEbl'
private constant integer Skill_Meld = 'Ashm'
private constant integer Skill_rainoffire = 'ANrf'
private constant integer Skill_Item_AttackSpeed = 'AIsx'
private constant integer Skill_Item_HPrecover = 'Arel'
//Effect
private constant integer Buff_Invisibility = 'Binv'
private constant integer Buff_Windwalk = 'BOwk'
private constant integer Buff_Hex = 'BOhx'
private constant integer Buff_BIrl = 'BIrl'
private constant integer Buff_ShadowStrike = 'BEsh'
private constant integer Buff_Roots = 'BEer'
private constant integer Buff_Immolation = 'BEim'
//***************AI
private integer array AIPlayer
private unit Attacker
private unit Victim
private unit array Hero
private unit array Shop
private unit array PShop
private unit array BMattackTarget
private unit array CommandHero
private unit GroupPickUnit
private unit array FirstHero
private unit array SecondHero
private unit array ThirdHero
private unit array soldier1
private unit array soldier2
private unit array soldier3
private unit array Unit
private unit array UnitR
private player AttackerOwner
private player VictimOwner
private player WeakPlayer
private player StrongPlayer
private player RichFriend
private real AttackerFacing
private real VictimFacing
private real AttackerHp
private real AttackerHpMax
private real AttackerHpPercent
private real VictimHp
private real VictimHpMax
private real VictimHpPercent
private real AttackerX
private real AttackerY
private real VictimX
private real VictimY
private real VictimTargetX
private real VictimTargetY
private real AttackerMoveSpeed
private real VictimMoveSpeed
private real ShortestDistance
private integer AttackerLevel
private integer VictimLevel
private integer AttackerOwnerId
private integer VictimOwnerId
private integer array AllyGroupUse
private integer array EnemyGroupUse
private integer SingleGroupCountUnit
private integer HeroNumber
private integer StrongEnemyGroupCountUnit
private integer ShopNumber
private integer array BuyDust
private integer array Lose
private integer array SkillWaitID
private integer imbaAI
private integer changeplayername
private integer OrderMove
private integer array BeingAttacked
private integer array LastEnemyLevel
private integer array LastAllyLevel
private integer UnitTop
private integer UnitFuncI
private integer UnitRTop
private integer array Spelling
private integer array URI
private location AttackerPostion
private location VictimPostion
private location array StartLoc
private group array AllyAttackGroup
private group array EnemyAttackGroup
private group SingleJudgementGroup
private group WeakAllyGroup
private group StrongEnemyGroup
private group HerosGroup
private group AllyTargetGroup
private group EnemyTargetGroup
private group array OrderMELEEGroup
private group array OrderRANGEDGroup
private group array OrderMAGEGroup
private group AllUnits
private group ReturnUnitsGroup
private force StrongPlayers
private force WeakPlayers
private force Force
private item VictimItem
private timer AttackIntervalTimer
private timer array AllyTimer
private timer array EnemyTimer
private timer array BMtimer
private timer array SkillWaitTimer
private timer array AETim
private timer array SpellingTimer
private trigger AttackingTrigger
private trigger AnyUnitEnter
private trigger AnyUnitDead
private trigger AnyUnitSpell
private region RectRegion
private string UnitString
endglobals

private function NewDistanceBetweenXY takes real x1, real x2, real y1, real y2 returns real
    return SquareRoot((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))
endfunction

private function NewAngleBetweenXY takes real x1, real x2, real y1, real y2 returns real
    return bj_RADTODEG*Atan2(y2-y1,x2-x1)
endfunction

private function EnableAttackingTrigger takes nothing returns nothing
    call EnableTrigger(AttackingTrigger)
endfunction

private function AllyGroupClearTimer takes nothing returns nothing
    local integer i=1
    local integer n=0
    loop
    exitwhen i>12 or n==1
    if GetExpiredTimer()==AllyTimer[i] then
    set AllyGroupUse[i]=0
    set n=1
    endif
    set i=i+1
    endloop
endfunction

private function EnemyGroupClearTimer takes nothing returns nothing
    local integer i=1
    local integer n=0
    loop
    exitwhen i>12 or n==1
    if GetExpiredTimer()==EnemyTimer[i] then
    set EnemyGroupUse[i]=0
    set n=1
    endif
    set i=i+1
    endloop
endfunction

private function NewGetInventoryIndexOfItemType takes unit whichUnit, integer itemId returns integer
    local integer index
    local item indexItem
    set index = 0
    loop
        set indexItem = UnitItemInSlot(whichUnit, index)
        if (indexItem != null) and (GetItemTypeId(indexItem) == itemId) then
            set indexItem=null
            return index + 1
        endif
        set index = index + 1
        exitwhen index >= bj_MAX_INVENTORY
    endloop
    return 0
endfunction

private function NewGetItemOfTypeFromUnit takes unit whichUnit, integer itemId returns item
    local integer index = NewGetInventoryIndexOfItemType(whichUnit, itemId)
    if (index == 0) then
        return null
    else
        return UnitItemInSlot(whichUnit, index - 1)
    endif
endfunction

private function UnitUseItemAtLoc takes unit whichUnit, item whichItem, location loc returns boolean
    return UnitUseItemPoint(whichUnit, whichItem, GetLocationX(loc), GetLocationY(loc))
endfunction

private function UnitHasBuff takes unit whichUnit, integer buffcode returns boolean
    return (GetUnitAbilityLevel(whichUnit, buffcode) > 0)
endfunction

private function AdjustPlayerStateSimple takes player whichPlayer, playerstate whichPlayerState, integer delta returns nothing
    call SetPlayerState(whichPlayer, whichPlayerState, GetPlayerState(whichPlayer, whichPlayerState) + delta)
endfunction

private function AdjustPlayerState takes integer delta, player whichPlayer, playerstate whichPlayerState returns nothing
    if (delta > 0) then
        if (whichPlayerState == PLAYER_STATE_RESOURCE_GOLD) then
            call AdjustPlayerStateSimple(whichPlayer, PLAYER_STATE_GOLD_GATHERED, delta)
        elseif (whichPlayerState == PLAYER_STATE_RESOURCE_LUMBER) then
            call AdjustPlayerStateSimple(whichPlayer, PLAYER_STATE_LUMBER_GATHERED, delta)
        endif
    endif

    call AdjustPlayerStateSimple(whichPlayer, whichPlayerState, delta)
endfunction

private function CountPlayersInEnumForce takes nothing returns nothing
    set bj_forceCountPlayers = bj_forceCountPlayers + 1
endfunction

private function CountPlayersInForce takes force f returns integer
    set bj_forceCountPlayers = 0
    call ForForce(f, function CountPlayersInEnumForce)
    return bj_forceCountPlayers
endfunction

private function TriggerRegisterPlayerUnitsEventSimple takes trigger trig, player whichPlayer, playerunitevent whichEvent returns event
    return TriggerRegisterPlayerUnitEvent(trig, whichPlayer, whichEvent, null)
endfunction

private function GetPlayerStartLocationL takes player whichPlayer returns location
    return GetStartLocationLoc(GetPlayerStartLocation(whichPlayer))
endfunction

function NewGetPlayersMatching takes boolexpr filter returns force
    call ForceEnumPlayers(Force,filter)
    call DestroyBoolExpr(filter)
    return Force
endfunction

function UnitId2StringAI takes integer unitId returns string
    set UnitString = UnitId2String(unitId)
    if (UnitString != null) then
       else
       set UnitString="N"
    endif
    return UnitString
endfunction

private function GetGold takes player p returns integer
return GetPlayerState(p,PLAYER_STATE_RESOURCE_GOLD)
endfunction

private function GetWood takes player p returns integer
return GetPlayerState(p,PLAYER_STATE_RESOURCE_LUMBER)
endfunction

private function GetFood takes player p returns integer
return GetPlayerState(p,PLAYER_STATE_RESOURCE_FOOD_USED)
endfunction

private function GetUnitStatePercent2 takes unit whichUnit, unitstate whichState, unitstate whichMaxState returns real
    local real value=GetUnitState(whichUnit,whichState)
    local real maxValue=GetUnitState(whichUnit,whichMaxState)
    if (whichUnit==null) or (maxValue==0) then
        return 0.0
    endif
    return value/maxValue*1.0
endfunction

private function GetUnitLifePercent2 takes unit whichUnit returns real
    return GetUnitStatePercent2(whichUnit,UNIT_STATE_LIFE,UNIT_STATE_MAX_LIFE)
endfunction

private function GroupCountUnits takes group g returns integer
    local unit u
    local integer n
    local group G
            set n=0
            set G=CreateGroup()
            loop
                 set u=FirstOfGroup(g)
                 if u!= null then
                    call GroupAddUnit(G,u)
                     set n=n+1
                 endif
                 call GroupRemoveUnit(g,u)
                 exitwhen u==null
             endloop
             loop
                 set u=FirstOfGroup(G)
                 if u!= null then
                    call GroupAddUnit(g,u)
                 endif
                 call GroupRemoveUnit(G,u)
                 exitwhen u==null
             endloop
             call GroupClear(G)
             call DestroyGroup(G)
             set G=null
    set u=null
    return n
endfunction

private function GroupClearAbandonUnits takes group g returns group
    local unit u
    local group G
            set G=CreateGroup()
            loop
                 set u=FirstOfGroup(g)
                 if u!= null then
                    if IsUnitType(u,UNIT_TYPE_DEAD)==false then
                       call GroupAddUnit(G,u)
                    endif
                 endif
                 call GroupRemoveUnit(g,u)
                 exitwhen u==null
             endloop
             loop
                 set u=FirstOfGroup(G)
                 if u!= null then
                    call GroupAddUnit(g,u)
                 endif
                 call GroupRemoveUnit(G,u)
                 exitwhen u==null
             endloop
             call GroupClear(G)
             call DestroyGroup(G)
             set G=null
    set u=null
    return g
endfunction

private function GroupPickUpUnitNum takes group g, integer n returns unit
    local unit u
    local integer i
    local group G
            set i=0
            set GroupPickUnit=null
            set G=CreateGroup()
            loop
                 set u=FirstOfGroup(g)
                 if u!= null then
                    set i=i+1
                    call GroupAddUnit(G,u)
                    if i==n then
                       set GroupPickUnit=u
                    endif
                 endif
                 call GroupRemoveUnit(g,u)
                 exitwhen u==null
             endloop
             loop
                 set u=FirstOfGroup(G)
                 if u!= null then
                    call GroupAddUnit(g,u)
                 endif
                 call GroupRemoveUnit(G,u)
                 exitwhen u==null
             endloop
             call GroupClear(G)
             call DestroyGroup(G)
             set G=null
    set u=null
    return GroupPickUnit
endfunction

private function AttackingEliminate takes nothing returns nothing
    local integer i=1
    local integer n=0
    loop
    exitwhen i>12 or n==1
    if GetExpiredTimer()==AETim[i] then
    set BeingAttacked[i]=0
    set n=1
    endif
    set i=i+1
    endloop
endfunction

private function OrderUnitMove takes unit u, real x, real y, real d, real a returns nothing
        set x=x+d*Cos(a*bj_DEGTORAD)
        set y=y+d*Sin(a*bj_DEGTORAD)
        call IssuePointOrder(u,"move",x,y)
endfunction

private function HeroProtection takes unit hero returns nothing
        local item Item
        local player p
        local integer id
        set p=GetOwningPlayer(hero)
        set id=GetPlayerId(p)+1
        set Item=NewGetItemOfTypeFromUnit(hero,Item_pnvl)
        if GetItemCharges(Item)>0 then
           call UnitUseItem(hero,Item)
        else
           set Item=NewGetItemOfTypeFromUnit(hero,Item_stwp)
           if GetItemCharges(Item)>0 then
              call UnitUseItemAtLoc(hero,Item,StartLoc[id])
           else
              call IssuePointOrderLoc(hero,"move",StartLoc[id])
           endif
        endif
        set Item=null
        set p=null
endfunction

private function AttackerAndVictim takes nothing returns nothing
    local unit u
    local integer ram
    call DisableTrigger(AttackingTrigger)
    call TimerStart(AttackIntervalTimer,0.03,false,function EnableAttackingTrigger)
    set Attacker=GetAttacker()
    set Victim=GetTriggerUnit()
    if IsUnitType(Victim, UNIT_TYPE_STRUCTURE)==false then
       set AttackerOwner=GetOwningPlayer(Attacker)
       set VictimOwner=GetOwningPlayer(Victim)
       set AttackerFacing=GetUnitFacing(Attacker)
       set VictimOwnerId=GetPlayerId(VictimOwner)+1
       set AttackerOwnerId=GetPlayerId(AttackerOwner)+1
       set AttackerX=GetUnitX(Attacker)
       set AttackerY=GetUnitY(Attacker)
       set VictimX=GetUnitX(Victim)
       set VictimY=GetUnitY(Victim)
       set VictimMoveSpeed=GetUnitMoveSpeed(Victim)
       set AttackerHp=GetUnitState(Attacker, UNIT_STATE_LIFE)
       set AttackerHpMax=GetUnitState(Attacker, UNIT_STATE_MAX_LIFE)
       set AttackerHpPercent=GetUnitLifePercent2(Attacker)
       set VictimHp=GetUnitState(Victim, UNIT_STATE_LIFE)
       set VictimHpMax=GetUnitState(Victim, UNIT_STATE_MAX_LIFE)
       set VictimHpPercent=GetUnitLifePercent2(Victim)
       if AIPlayer[VictimOwnerId]==1 then//VictimIsAI
          set BeingAttacked[VictimOwnerId]=1
          call TimerStart(AETim[VictimOwnerId],3.00,false,function AttackingEliminate)
          if OrderMove==1 then
          if IsUnitInGroup(Victim,OrderMELEEGroup[VictimOwnerId])==true or IsUnitInGroup(Victim,OrderRANGEDGroup[VictimOwnerId])==true or IsUnitInGroup(Victim,OrderMAGEGroup[VictimOwnerId])==true or IsUnitType(Victim,UNIT_TYPE_HERO)==true then
          endif
          endif
          if GetOwningPlayer(Attacker)!=Player(PLAYER_NEUTRAL_AGGRESSIVE) then
          if IsUnitType(Victim,UNIT_TYPE_HERO)==false then//CommonUnit
             set VictimLevel=GetUnitLevel(Victim)
             if VictimHpPercent<=0.13 then
                if AllyGroupUse[VictimOwnerId]==0 then
                set AllyGroupUse[VictimOwnerId]=1
                call GroupEnumUnitsInRange(AllyAttackGroup[VictimOwnerId],VictimX,VictimY,I2R(VictimLevel)*50.00+100.00,null)
                loop
                  set u=FirstOfGroup(AllyAttackGroup[VictimOwnerId])
                  if u!=null and IsUnitType(u,UNIT_TYPE_DEAD)==false and IsUnitOwnedByPlayer(u,VictimOwner) and u!=Victim and IsUnitType(u,UNIT_TYPE_PEON)==false then
                     call IssueTargetOrder(u,"attack",Victim)
                  endif
                  call GroupRemoveUnit(AllyAttackGroup[VictimOwnerId],u)
                  exitwhen u==null
                endloop
                call GroupClear(AllyAttackGroup[VictimOwnerId])
                call TimerStart(AllyTimer[VictimOwnerId],1.00,false,function AllyGroupClearTimer)
                if IsUnitInGroup(Victim,ReturnUnitsGroup)==false then
                if VictimMoveSpeed>=200 then
                   call OrderUnitMove(Victim,VictimX,VictimY,650,AttackerFacing)
                endif   
                endif
                endif
             elseif VictimHpPercent<=0.23 then
                    if IsUnitInGroup(Victim,ReturnUnitsGroup)==false then
                    if AttackerHpPercent>0.25 then
                       if VictimMoveSpeed>=200 then
                          call OrderUnitMove(Victim,VictimX,VictimY,356,AttackerFacing)
                       endif   
                    else
                       call IssueTargetOrder(Victim,"attack",Attacker)
                    endif
                    endif
                    if AttackerHpPercent<=0.21 then
                    if IsUnitInGroup(Victim,ReturnUnitsGroup)==false then
                    call IssueTargetOrder(Victim,"attack",Attacker)
                    endif
                    endif
             elseif VictimHpPercent<=0.40 then
                    if IsUnitInGroup(Victim,ReturnUnitsGroup)==false then
                    set SingleGroupCountUnit=0
                    call GroupEnumUnitsInRange(SingleJudgementGroup,VictimX,VictimY,600.0,null)
                    loop
                    set u=FirstOfGroup(SingleJudgementGroup)
                    if u!=null and IsUnitType(u,UNIT_TYPE_DEAD)==false and IsUnitOwnedByPlayer(u,VictimOwner) and u!=Victim and IsUnitType(u,UNIT_TYPE_PEON)==false then
                       set SingleGroupCountUnit=SingleGroupCountUnit+1
                       if IsUnitType(u,UNIT_TYPE_HERO)==true then
                          set SingleGroupCountUnit=SingleGroupCountUnit+2
                       endif   
                    endif
                    call GroupRemoveUnit(SingleJudgementGroup,u)
                    exitwhen u==null
                    endloop
                    call GroupClear(SingleJudgementGroup)
                    call TimerStart(AllyTimer[VictimOwnerId],1.00,false,function AllyGroupClearTimer)
                    if SingleGroupCountUnit<=3 then
                       call OrderUnitMove(Victim,VictimX,VictimY,2000/I2R((SingleGroupCountUnit+1)),AttackerFacing)
                    endif
                    endif
             elseif VictimHpPercent<=0.86 then
                    if IsUnitInGroup(Victim,ReturnUnitsGroup)==false then
                    set SingleGroupCountUnit=0
                    call GroupEnumUnitsInRange(WeakAllyGroup,VictimX,VictimY,600.0,null)
                    loop
                    set u=FirstOfGroup(WeakAllyGroup)
                    if u!=null and IsUnitType(u,UNIT_TYPE_DEAD)==false and IsUnitOwnedByPlayer(u,VictimOwner) and u!=Victim and IsUnitType(u,UNIT_TYPE_PEON)==false then
                       set SingleGroupCountUnit=SingleGroupCountUnit+1
                    endif
                    call GroupRemoveUnit(WeakAllyGroup,u)
                    exitwhen u==null
                    endloop
                    call GroupClear(WeakAllyGroup)
                    set StrongEnemyGroupCountUnit=0
                    call GroupEnumUnitsInRange(StrongEnemyGroup,VictimX,VictimY,600.0,null)
                    loop
                    set u=FirstOfGroup(StrongEnemyGroup)
                    if u!=null and IsUnitType(u,UNIT_TYPE_DEAD)==false and IsUnitEnemy(u,VictimOwner)==true and u!=Victim and IsUnitType(u,UNIT_TYPE_PEON)==false then
                       set StrongEnemyGroupCountUnit=StrongEnemyGroupCountUnit+1
                    endif
                    call GroupRemoveUnit(StrongEnemyGroup,u)
                    exitwhen u==null
                    endloop
                    call GroupClear(StrongEnemyGroup)
                    if SingleGroupCountUnit<5 and StrongEnemyGroupCountUnit>=5 then
                       call OrderUnitMove(Victim,VictimX,VictimY,2000,AttackerFacing)
                    endif
                    endif
             endif
          else//Hero
             set VictimLevel=GetHeroLevel(Victim)
             if VictimHpPercent<=0.14 then
                if AllyGroupUse[VictimOwnerId]==0 then
                set AllyGroupUse[VictimOwnerId]=1
                call GroupEnumUnitsInRange(AllyAttackGroup[VictimOwnerId],VictimX,VictimY,300.00+I2R(VictimLevel)*50.00,null)
                loop
                  set u=FirstOfGroup(AllyAttackGroup[VictimOwnerId])
                  if u!=null and IsUnitType(u,UNIT_TYPE_DEAD)==false and IsUnitOwnedByPlayer(u,VictimOwner) and u!=Victim and IsUnitType(u,UNIT_TYPE_PEON)==false then
                     call IssueTargetOrder(u,"attack",Victim)
                  endif
                  call GroupRemoveUnit(AllyAttackGroup[VictimOwnerId],u)
                  exitwhen u==null
                endloop
                call GroupClear(AllyAttackGroup[VictimOwnerId])
                call TimerStart(AllyTimer[VictimOwnerId],1.00,false,function AllyGroupClearTimer)
                call OrderUnitMove(Victim,VictimX,VictimY,1000,AttackerFacing)
                call HeroProtection(Victim)
                endif
             elseif VictimHpPercent<=0.23 then
                    call HeroProtection(Victim)
             elseif VictimHpPercent>0.23 and VictimHpPercent<=0.55 then
                    if AttackerHpPercent>0.20 then
                       if IsUnitInGroup(Victim,ReturnUnitsGroup)==false then
                       if GetUnitTypeId(Victim)==Hero_BM and GetUnitState(Victim,UNIT_STATE_MANA)>=75 then
                       else
                          if NewDistanceBetweenXY(VictimX,GetLocationX(StartLoc[AttackerOwnerId]),VictimY,GetLocationY(StartLoc[AttackerOwnerId]))<1300 then
                          call IssuePointOrderLoc(Victim,"move",StartLoc[VictimOwnerId])
                          else
                          call OrderUnitMove(Victim,VictimX,VictimY,550,AttackerFacing)
                          endif
                       endif  
                       endif
                    else
                       call IssueTargetOrder(Victim,"attack",Attacker)
                    endif
             elseif VictimHpPercent<=0.85 then
                    if IsUnitInGroup(Victim,ReturnUnitsGroup)==false then
                    set ram=GetRandomInt(1,3)
                    if ram==1 then
                    call OrderUnitMove(Victim,VictimX,VictimY,500,AttackerFacing)
                    endif
                    endif
             endif      
          endif
          endif
       endif
       if AIPlayer[AttackerOwnerId]==1 then//AttackerIsAI
          if IsUnitType(Victim,UNIT_TYPE_HERO)==false then//CommonUnit
             set VictimLevel=GetUnitLevel(Victim)
             if VictimHpPercent<=0.18 then
                if EnemyGroupUse[AttackerOwnerId]==0 then
                set EnemyGroupUse[AttackerOwnerId]=1
                call GroupEnumUnitsInRange(EnemyAttackGroup[AttackerOwnerId],VictimX,VictimY,I2R(VictimLevel)*50.00+100,null)
                loop
                  set u=FirstOfGroup(EnemyAttackGroup[AttackerOwnerId])
                  if u!=null and IsUnitType(u,UNIT_TYPE_DEAD)==false and IsUnitOwnedByPlayer(u,AttackerOwner)==true and u!=Attacker and IsUnitType(u,UNIT_TYPE_PEON)==false then
                     call IssueTargetOrder(u,"attack",Victim)
                  endif
                  call GroupRemoveUnit(EnemyAttackGroup[AttackerOwnerId],u)
                  exitwhen u==null
                endloop
                call GroupClear(EnemyAttackGroup[AttackerOwnerId])
                call TimerStart(EnemyTimer[AttackerOwnerId],1.00,false,function EnemyGroupClearTimer)
                endif
             endif
             if AttackerHpPercent<=0.25 then
                set ram=GetRandomInt(1,2)
                if VictimHpPercent>=0.35 and VictimHp>70 and ram==2 then
                   call OrderUnitMove(Attacker,AttackerX,AttackerY,250,AttackerFacing+180)
                endif
             endif
          else//Hero
             set VictimLevel=GetHeroLevel(Victim)
             if VictimHpPercent<=0.28 then
                if EnemyGroupUse[AttackerOwnerId]==0 then
                set EnemyGroupUse[AttackerOwnerId]=1
                call GroupEnumUnitsInRange(EnemyAttackGroup[AttackerOwnerId],VictimX,VictimY,200+I2R(VictimLevel)*100.00,null)
                loop
                  set u=FirstOfGroup(EnemyAttackGroup[AttackerOwnerId])
                  if u!=null and IsUnitType(u,UNIT_TYPE_DEAD)==false and IsUnitOwnedByPlayer(u,AttackerOwner) and u!=Attacker then
                     call IssueTargetOrder(u,"attack",Victim)
                  endif
                  call GroupRemoveUnit(EnemyAttackGroup[AttackerOwnerId],u)
                  exitwhen u==null
                endloop
                call GroupClear(EnemyAttackGroup[AttackerOwnerId])
                call TimerStart(EnemyTimer[AttackerOwnerId],1.00,false,function EnemyGroupClearTimer)
                endif
             endif
             if AttackerHpPercent<=0.25 then
                set ram=GetRandomInt(1,2)
                if VictimHpPercent>=0.25 and VictimHp>100 and ram==2 then
                   call OrderUnitMove(Attacker,AttackerX,AttackerY,300,AttackerFacing+180)
                endif
             endif
          endif
       endif
    endif
    set u=null
endfunction   

private function BMAttack takes nothing returns nothing
         local integer i=1
         loop
         exitwhen i>HeroNumber
         if GetExpiredTimer()==BMtimer[i] then
            call UnitRemoveAbility(Hero[i],Buff_Windwalk)
            call UnitDamageTarget(Hero[i],BMattackTarget[i],I2R(GetHeroAgi(Hero[i],true))+I2R(GetUnitAbilityLevel(Hero[i],Skill_Windwalk))*30+30.0,true,false,ATTACK_TYPE_HERO,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_METAL_HEAVY_SLICE)
         endif
         set i=i+1
         endloop
endfunction

private function BMInfest takes unit bm, unit target returns nothing
         local integer i=0
         local location l
         if GetOwningPlayer(target)==Player(PLAYER_NEUTRAL_AGGRESSIVE) then
            loop
            exitwhen i>11
            if IsUnitEnemy(bm,Player(i))==true and GetPlayerSlotState(Player(i))==PLAYER_SLOT_STATE_PLAYING then
               set l=StartLoc[i+1]
            endif
            set i=i+1
            endloop
            set i=0
         else
            loop
            exitwhen i>11
            if GetOwningPlayer(target)==Player(i) then
               set l=StartLoc[i+1]
            endif
            set i=i+1
            endloop
            set i=0
         endif
         call IssuePointOrderLoc(bm, "move",l)
         set l=null
endfunction

private function IsUnitSoldier takes unit u returns boolean
return IsUnitType(u,UNIT_TYPE_STRUCTURE)==false and (IsUnitType(u,UNIT_TYPE_GROUND)==true or IsUnitType(u,UNIT_TYPE_FLYING)==true) and IsUnitType(u,UNIT_TYPE_PEON)==false
endfunction

private function HeroStatus takes unit hero, integer id returns nothing
         local unit u=null
         local unit u2=null
         local group g=null
         local group g2=null
         local real x=0
         local real y=0
         local real x1=0
         local real y1=0
         local real x0=0
         local real y0=0
         local player p=null
         local player p2=null
         local integer l=0
         local integer I=0
         local integer ID=0
         local real heroHP=0
         local real heroHPmax=0
         local real heroMana=0
         local real heroHPpercent=0
         local real unitHP=0
         local real unitHPmax=0
         local real unitHPpercent=0
         local integer attacking=0
         local location startloc=null
         set x=GetUnitX(hero)
         set y=GetUnitY(hero)
         set p=GetOwningPlayer(hero)
         set l=GetHeroLevel(hero)
         set heroHP=GetUnitState(hero,UNIT_STATE_LIFE)
         set heroHPmax=GetUnitState(hero,UNIT_STATE_MAX_LIFE)
         set heroMana=GetUnitState(hero,UNIT_STATE_MANA)
         set heroHPpercent=GetUnitLifePercent2(hero)
         set ID=GetPlayerId(p)+1
         set LastAllyLevel[ID]=0
         set LastEnemyLevel[ID]=0
         set startloc=StartLoc[ID]
         set x0=GetLocationX(startloc)
         set y0=GetLocationY(startloc)
         set g=CreateGroup()
         call GroupEnumUnitsInRange(g,x,y,600.00,null)
            loop
            set u=FirstOfGroup(g)
            if u!=null and IsUnitType(u,UNIT_TYPE_DEAD)==false then
               set p2=GetOwningPlayer(u)
               set unitHP=GetUnitState(u,UNIT_STATE_LIFE)
               set unitHPmax=GetUnitState(u,UNIT_STATE_MAX_LIFE)
               set unitHPpercent=GetUnitLifePercent2(u)
               set x1=GetUnitX(u)
               set y1=GetUnitY(u)
               set attacking=0
               if GetUnitTypeId(u)==Unit_Shop and GetGold(p)>200 then
                  if GetItemCharges(NewGetItemOfTypeFromUnit(hero,Item_pnvl))<1 then
                     call IssueTargetOrder(u,"neutralinteract",hero)
                     call IssueNeutralImmediateOrderById(p,u,Item_pnvl)
                  endif
                  if GetItemCharges(NewGetItemOfTypeFromUnit(hero,Item_stwp))<1 and GetGold(p)>350 then
                     call IssueTargetOrder(u,"neutralinteract",hero)
                     call IssueNeutralImmediateOrderById(p,u,Item_stwp)
                  endif
                  if GetItemCharges(NewGetItemOfTypeFromUnit(hero,Item_dust))<1 and GetGold(p)>75 and BuyDust[id]==1 then
                     call IssueTargetOrder(u,"neutralinteract",hero)
                     call IssueNeutralImmediateOrderById(p,u,Item_dust)
                  endif
                  if GetItemCharges(NewGetItemOfTypeFromUnit(hero,Item_prvt))<1 and GetGold(p)>375 and heroHPmax<600 then
                     call IssueTargetOrder(u,"neutralinteract",hero)
                     call IssueNeutralImmediateOrderById(p,u,Item_prvt)
                  endif
               endif
               if heroHPpercent<=0.35 and NewDistanceBetweenXY(x,x0,y,y0)<600 then
                  if GetItemCharges(NewGetItemOfTypeFromUnit(hero,Item_stwp))>0 then
                     call IssuePointOrderLoc(hero,"move",startloc)
                  else
                     if PShop[ID]!=null and IsUnitType(PShop[ID],UNIT_TYPE_DEAD)==false then
                        call IssueTargetOrder(hero,"smart",PShop[ID])
                     else   
                        call IssuePointOrderLoc(hero,"move",startloc)
                     endif   
                  endif   
               endif
               if GetItemCharges(NewGetItemOfTypeFromUnit(hero,Item_hslv))>0 and heroHP<300 and UnitHasBuff(hero,Buff_BIrl)==false then
                  call UnitUseItemTarget(hero,NewGetItemOfTypeFromUnit(hero,Item_hslv),hero)
               endif
               if GetItemCharges(NewGetItemOfTypeFromUnit(hero,Item_sreg))>0 and heroHP<300 then
                  call UnitUseItem(hero,NewGetItemOfTypeFromUnit(hero,Item_sreg))
               endif
               if IsUnitOwnedByPlayer(u,p) then//Own
                  if 1>2 then
                     set LastAllyLevel[ID]=LastAllyLevel[ID]+GetUnitLevel(u)
                  endif
                  if u!=hero then
                  if unitHP<=35+l*10 and IsUnitType(u,UNIT_TYPE_STRUCTURE)==false then
                     set attacking=1
                     call IssueTargetOrder(hero,"attack",u)
                  endif  
                  if GetUnitTypeId(hero)==Hero_PLA and heroMana>=65 then
                     if IsUnitType(u,UNIT_TYPE_HERO)==true and unitHP<=300 then
                        call IssueTargetOrder(hero,"holybolt",u)   
                     endif
                  elseif GetUnitTypeId(hero)==Hero_DK and heroMana>=75 then
                     if IsUnitType(u,UNIT_TYPE_HERO)==true and unitHP<=300 then
                        call IssueTargetOrder(hero,"deathcoil",u)
                     endif
                  endif
                  endif
                  if OrderMove==1 then
                     if IsUnitSoldier(u)==true and IsUnitType(u,UNIT_TYPE_HERO)==false then
                        if IsUnitType(u,UNIT_TYPE_MELEE_ATTACKER)==true then
                           if IsUnitInGroup(u,OrderMELEEGroup[ID])==false then
                              call GroupAddUnit(OrderMELEEGroup[ID],u)
                           endif
                        elseif IsUnitType(u,UNIT_TYPE_RANGED_ATTACKER)==true then   
                               if GetUnitState(u,UNIT_STATE_MAX_MANA)>0 then
                                  if IsUnitInGroup(u,OrderMAGEGroup[ID])==false then
                                     call GroupAddUnit(OrderMAGEGroup[ID],u)
                                  endif
                               else
                                  if IsUnitInGroup(u,OrderRANGEDGroup[ID])==false then
                                     call GroupAddUnit(OrderRANGEDGroup[ID],u)
                                  endif
                               endif
                        endif        
                     endif
                  endif
               elseif IsUnitAlly(u,p)==true then//Ally
                      if 1>2 then
                         if IsUnitSoldier(u)==true then
                         set LastAllyLevel[ID]=LastAllyLevel[ID]+GetUnitLevel(u)
                         endif
                      endif
               elseif IsUnitEnemy(u,p)==true then//Enemy
                      if (BeingAttacked[ID]==0 or BeingAttacked[GetPlayerId(p2)+1]==0) and p2!=Player(PLAYER_NEUTRAL_AGGRESSIVE) then
                         call IssueTargetOrder(hero,"attack",u)
                      endif
                      if 1>2 then
                         set LastEnemyLevel[ID]=LastEnemyLevel[ID]+GetUnitLevel(u)
                      endif
                      if unitHP<=50+l*10 and Spelling[id]==0 then
                         set attacking=1
                         call IssueTargetOrder(hero,"attack",u)
                      endif
                      if GetUnitTypeId(hero)!=Hero_BM then
                      if unitHPpercent<=0.25 and IsUnitType(u,UNIT_TYPE_GROUND)==true then
                         set attacking=1
                         if BMattackTarget[id]==null or IsUnitType(BMattackTarget[id],UNIT_TYPE_DEAD)==true then
                         set BMattackTarget[id]=u
                         endif
                      endif
                      if unitHP<=50+l*10 and IsUnitType(u,UNIT_TYPE_GROUND)==true then
                         set attacking=1
                         set BMattackTarget[id]=u
                      endif
                      if BMattackTarget[id]!=null and Spelling[id]==0 then
                         if heroHP>200 then
                           if IsUnitType(hero,UNIT_TYPE_MELEE_ATTACKER)==true then
                           if NewDistanceBetweenXY(x,GetUnitX(BMattackTarget[id]),y,GetUnitY(BMattackTarget[id]))<=200 then
                              call IssueTargetOrder(hero,"attack",BMattackTarget[id])
                           endif
                           else
                              call IssueTargetOrder(hero,"attack",BMattackTarget[id])
                           endif
                         endif
                         if NewDistanceBetweenXY(x,GetUnitX(BMattackTarget[id]),y,GetUnitY(BMattackTarget[id]))>1000 then
                            set BMattackTarget[id]=null
                         endif
                      endif
                      endif
                      if IsUnitType(u,UNIT_TYPE_HERO)==true then
                         if UnitHasBuff(u,Buff_Windwalk)==true or UnitHasBuff(u,Buff_Invisibility)==true or GetUnitAbilityLevel(u,Skill_Meld)>0 then
                            set BuyDust[id]=1
                            if GetItemCharges(NewGetItemOfTypeFromUnit(hero,Item_dust))>0 then
                            call UnitUseItem(hero,NewGetItemOfTypeFromUnit(hero,Item_dust))
                            endif
                         endif
                      endif
                      if GetUnitTypeId(hero)==Hero_PLA and heroMana>=65 then
                         if IsUnitType(u,UNIT_TYPE_HERO)==true then
                            if unitHP<=(-80+I2R(GetUnitAbilityLevel(hero,Skill_Holybolt))*150) and IsUnitType(u,UNIT_TYPE_UNDEAD)==true then
                               call IssueTargetOrder(hero,"holybolt",u)
                            endif   
                         endif
                      elseif GetUnitTypeId(hero)==Hero_AM and heroMana>=75 then
                         if heroHP<=50 and NewDistanceBetweenXY(x,x0,y,y0)>1200 then
                            call IssuePointOrder(hero,"blizzard",x,y)
                         endif
                         if unitHP<=100 and IsUnitType(u,UNIT_TYPE_HERO)==true then
                            call IssuePointOrder(hero,"blizzard",x1,y1)
                         endif
                      elseif GetUnitTypeId(hero)==Hero_BLM and heroMana>=135 then
                         if heroHP<=100 and NewDistanceBetweenXY(x,x0,y,y0)>1200 then
                            call IssuePointOrder(hero,"flamestrike",x,y)
                         endif
                         if unitHP<=100 and IsUnitType(u,UNIT_TYPE_HERO)==true then
                            call IssuePointOrder(hero,"flamestrike",x1,y1)
                         endif
                      elseif GetUnitTypeId(hero)==Hero_MK and heroMana>=75 then
                         if GetUnitLevel(u)>=2+GetUnitAbilityLevel(hero,Skill_Thunderbolt) and unitHP<=(-100+I2R(GetUnitAbilityLevel(hero,Skill_Thunderbolt))*200) then
                            call IssueTargetOrder(hero,"thunderbolt",u)
                         endif
                      elseif GetUnitTypeId(hero)==Hero_SH and heroMana>=70 then
                         if IsUnitType(u,UNIT_TYPE_HERO)==true and UnitHasBuff(u,Buff_Hex)==false then
                            call IssueTargetOrder(hero,"hex",u)
                         endif
                      elseif GetUnitTypeId(hero)==Hero_TC and heroMana>=90 then
                         if IsUnitType(u,UNIT_TYPE_HERO)==true then
                            if NewDistanceBetweenXY(x,x1,y,y1)<=200+I2R(GetUnitAbilityLevel(u,Skill_Stomp))*50 then
                               call IssueImmediateOrder(hero,"stomp")
                            endif   
                            if unitHP<100 and NewDistanceBetweenXY(x,x1,y,y1)>350 then
                               call IssuePointOrder(hero,"shockwave",x1,y1)
                            endif
                         endif
                         if heroHPpercent<0.35 and NewDistanceBetweenXY(x,x1,y,y1)<=200+I2R(GetUnitAbilityLevel(u,Skill_Stomp))*50 then
                            call IssueImmediateOrder(hero,"stomp")
                         endif   
                      elseif GetUnitTypeId(hero)==Hero_FS and heroMana>=125 then
                         if IsUnitType(u,UNIT_TYPE_HERO)==true and unitHPpercent<0.35 then
                            call IssueTargetOrder(hero,"chainlightning",u)
                         endif
                      elseif GetUnitTypeId(hero)==Hero_DK and heroMana>=75 then
                         if IsUnitType(u,UNIT_TYPE_HERO)==true then
                            if unitHP<=(-80+I2R(GetUnitAbilityLevel(hero,Skill_Deathcoil))*150) and IsUnitType(u,UNIT_TYPE_UNDEAD)==false then
                               call IssueTargetOrder(hero,"deathcoil",u)
                            endif   
                         endif
                      elseif GetUnitTypeId(hero)==Hero_CL and heroMana>=100 then
                         if IsUnitType(u,UNIT_TYPE_HERO)==true then
                            if IsUnitType(u,UNIT_TYPE_HERO)==true and unitHPpercent<0.35 then
                               call IssuePointOrder(hero,"impale",x1,y1)
                            endif  
                         endif
                      elseif GetUnitTypeId(hero)==Hero_LICH and heroMana>=125 then
                         if GetUnitLevel(u)>=2+GetUnitAbilityLevel(hero,Skill_Frostnova) and unitHP<=(-100+I2R(GetUnitAbilityLevel(hero,Skill_Frostnova))*200) then
                            call IssueTargetOrder(hero,"frostnova",u)
                         endif
                      elseif GetUnitTypeId(hero)==Hero_DR and heroMana>=50 then
                         if unitHP<100 and NewDistanceBetweenXY(x,x1,y,y1)>350 and heroMana>=100 then
                            call IssuePointOrder(hero,"carrionswarm",x1,y1)
                         endif
                         if (heroHPpercent<0.25 and GetUnitLevel(u)>3 and unitHP>500) or (IsUnitType(u,UNIT_TYPE_HERO)==true and NewDistanceBetweenXY(x,x1,y,y1)>400) then
                            call IssueTargetOrder(hero,"sleep",u)
                         endif
                      elseif GetUnitTypeId(hero)==Hero_WD and heroMana>=10 then
                         if IsUnitType(u,UNIT_TYPE_HERO)==true then
                            if unitHPpercent<0.35 and heroHPpercent>0.55 then
                               call IssuePointOrder(hero,"blink",x1,y1)
                            endif
                            if UnitHasBuff(u,Buff_ShadowStrike)==false and heroMana>=65 then
                               call IssueTargetOrder(hero,"shadowstrike",u)
                            endif  
                            if heroHPpercent<0.25 then
                               call IssuePointOrder(hero,"blink",x0,y0)
                            endif
                         endif
                      elseif GetUnitTypeId(hero)==Hero_KOG and heroMana>=75 then
                         if unitHPpercent<0.6 and IsUnitType(u,UNIT_TYPE_HERO)==true and UnitHasBuff(u,Buff_Roots)==false then
                            call IssueTargetOrder(hero,"entanglingroots",u)
                         endif
                      elseif GetUnitTypeId(hero)==Hero_DH and heroMana>=50 then
                         if IsUnitType(u,UNIT_TYPE_HERO)==true then
                            call IssueTargetOrder(hero,"manaburn",u)
                         endif
                      elseif GetUnitTypeId(hero)==Hero_POM and heroMana>=10 then
                         if IsUnitType(u,UNIT_TYPE_HERO)==true and unitHPpercent<0.75 then
                            call IssueTargetOrder(hero,"attack",u)
                         endif
                    elseif GetUnitTypeId(hero)==Hero_BM and heroMana>=50 and heroHPpercent>0.2 then
                       if BMattackTarget[id]==null then
                          if IsUnitType(u, UNIT_TYPE_STRUCTURE)==false then
                          if p2!=Player(PLAYER_NEUTRAL_AGGRESSIVE) then
                          set BMattackTarget[id]=u
                          endif
                          elseif unitHPpercent<=0.20 then
                          set BMattackTarget[id]=u
                          endif
                       endif   
                       if heroHPpercent<0.65 and heroMana>=75 then
                          call IssueImmediateOrder(hero,"windwalk")
                       endif
                       if IsUnitType(u,UNIT_TYPE_HERO)==true and IsUnitEnemy(u,p)==true then
                          if (unitHPpercent<=0.75 and heroHPpercent>=0.25) or (unitHPpercent<=0.35 and heroMana>=70) then
                             if (BMattackTarget[id]==null or IsUnitType(BMattackTarget[id],UNIT_TYPE_DEAD)==true or NewDistanceBetweenXY(x,GetUnitX(BMattackTarget[id]),y,GetUnitY(BMattackTarget[id]))>1000) then
                                if p2!=Player(PLAYER_NEUTRAL_AGGRESSIVE) then
                                set BMattackTarget[id]=u
                                endif
                             endif   
                             if UnitHasBuff(hero,Buff_Windwalk)==true then
                                call IssuePointOrder(hero,"move",x1,y1)
                                if NewDistanceBetweenXY(x,x1,y,y1)<=100 then
                                   call SetUnitAnimation(hero,"attack")
                                   call TimerStart(BMtimer[id],0.25,false,function BMAttack)
                                endif
                             endif   
                          else
                             set I=0
                             set g2=CreateGroup()
                             call GroupEnumUnitsInRange(g2,x,y,600.00,null)
                             loop
                             set u2=FirstOfGroup(g2)
                             if u2!=null and IsUnitType(u2,UNIT_TYPE_DEAD)==false and GetOwningPlayer(u2)==p then
                                set I=I+1
                             endif
                             call GroupRemoveUnit(g2,u2)
                             exitwhen u2==null
                             endloop
                             call GroupClear(g2)
                             call DestroyGroup(g2)  
                             if GetFood(p)<50 and I<2 and NewDistanceBetweenXY(x,GetLocationX(StartLoc[id]),y,GetLocationY(StartLoc[id]))>2000 then
                                call IssueImmediateOrder(hero,"windwalk")
                                call BMInfest(hero,u)
                             else
                                call IssueTargetOrder(hero,"attack",u)
                             endif   
                          endif   
                       endif
                       if IsUnitType(u,UNIT_TYPE_PEON)==true and IsUnitEnemy(u,p)==true then
                          if (BMattackTarget[id]==null or IsUnitType(BMattackTarget[id],UNIT_TYPE_DEAD)==true or NewDistanceBetweenXY(x,GetUnitX(BMattackTarget[id]),y,GetUnitY(BMattackTarget[id]))>1000) then
                            if p2!=Player(PLAYER_NEUTRAL_AGGRESSIVE) then
                                set BMattackTarget[id]=u
                            endif
                          endif   
                          if UnitHasBuff(hero,Buff_Windwalk)==true then
                             call IssuePointOrder(hero,"move",x1,y1)
                             if NewDistanceBetweenXY(x,x1,y,y1)<=100 then
                                call SetUnitAnimation(hero,"attack")
                                call TimerStart(BMtimer[id],0.25,false,function BMAttack)
                             endif  
                          endif
                       endif
                       if IsUnitType(u, UNIT_TYPE_STRUCTURE) == false and IsUnitType(u,UNIT_TYPE_HERO)==false and IsUnitEnemy(u,p)==true and p2!=Player(PLAYER_NEUTRAL_AGGRESSIVE) then
                          if NewDistanceBetweenXY(x,GetLocationX(StartLoc[GetPlayerId(p2)+1]),y,GetLocationY(StartLoc[GetPlayerId(p2)+1]))>1000 then
                             call BMInfest(hero,u)
                          endif
                          if unitHPpercent<=0.35 or unitHP<=100+10*l then
                             if (BMattackTarget[id]==null or IsUnitType(BMattackTarget[id],UNIT_TYPE_DEAD)==true or NewDistanceBetweenXY(x,GetUnitX(BMattackTarget[id]),y,GetUnitY(BMattackTarget[id]))>1000) then
                                if p2!=Player(PLAYER_NEUTRAL_AGGRESSIVE) then
                                set BMattackTarget[id]=u
                                endif
                             endif
                             if UnitHasBuff(hero,Buff_Windwalk)==true then
                                call IssuePointOrder(hero,"move",x1,y1)
                                if NewDistanceBetweenXY(x,x1,y,y1)<=100 then
                                call SetUnitAnimation(hero,"attack")
                                call TimerStart(BMtimer[id],0.25,false,function BMAttack)   
                             endif   
                             endif   
                          endif
                       elseif p2==Player(PLAYER_NEUTRAL_AGGRESSIVE) and heroMana>=150 then
                              set I=0
                              set g2=CreateGroup()
                              call GroupEnumUnitsInRange(g2,x,y,600.00,null)
                              loop
                              set u2=FirstOfGroup(g2)
                              if u2!=null and IsUnitType(u2,UNIT_TYPE_DEAD)==false and GetOwningPlayer(u2)==p then
                                 set I=I+1
                              endif
                              call GroupRemoveUnit(g2,u2)
                              exitwhen u2==null
                              endloop
                              call GroupClear(g2)
                              call DestroyGroup(g2)  
                              if I<2 then
                              if heroHPpercent<0.25 then
                                 call IssueImmediateOrder(hero,"windwalk")
                              endif   
                              if GetRandomInt(1,10)==1 then
                              call BMInfest(hero,u)
                              endif
                              endif
                       endif
                       if heroHPpercent>0.30 and heroMana>=25 then
                       call IssueTargetOrder(hero,"attack",BMattackTarget[id])
                       endif
                    endif
               endif   
               if 1>2 then
               if LastAllyLevel[ID]*2<LastEnemyLevel[ID] then
               if IsUnitOwnedByPlayer(u,p) and NewDistanceBetweenXY(x,x0,y,y0)>1000 then
                  if GetUnitTypeId(u)==Hero_BM and GetUnitState(hero,UNIT_STATE_MANA)>=75 then
                  else
                  call IssuePointOrderLoc(u,"move",startloc)
                  if NewDistanceBetweenXY(x,x0,y,y0)>2000 and heroHP<100 then
                     call HeroProtection(hero)
                  endif
                  endif
               endif
               elseif GetUnitTypeId(hero)==Hero_DH and UnitHasBuff(hero,Buff_Immolation)==true and LastEnemyLevel[ID]==0 then
                  call IssueImmediateOrder(hero,"unimmolation")
               endif
               endif
            endif
            call GroupRemoveUnit(g,u)
            exitwhen u==null
            endloop
            call GroupClear(g)
            call DestroyGroup(g)  
         set g=null
         set u=null
         set p=null
         set p2=null
         set u2=null
         set g2=null
         set startloc=null
endfunction         

private function UnitRPop takes integer i returns nothing
     call GroupRemoveUnit(ReturnUnitsGroup,UnitR[i])
     set UnitR[i]=UnitR[UnitRTop]
     set URI[i]=URI[UnitRTop]
     set UnitR[UnitRTop]=null
     set UnitRTop=UnitRTop-1
endfunction

private function UnitReturn takes nothing returns nothing
     local integer i=UnitRTop
     local player p
     loop
         exitwhen i<0
         if IsUnitType(UnitR[i],UNIT_TYPE_DEAD) or UnitR[i]==null then
             call UnitRPop(i)
         else
             set p=GetOwningPlayer(UnitR[i])
             call IssuePointOrderLoc(UnitR[i],"AImove",StartLoc[GetPlayerId(p)+1])
             set URI[i]=URI[i]+1
             if URI[i]>=6 then
                set UnitR[i]=null
             endif
         endif   
         set i=i-1
     endloop
     set p=null            
endfunction

private function UnitPop takes integer i returns nothing
     set Unit[i]=Unit[UnitTop]
     set Unit[UnitTop]=null
     set UnitTop=UnitTop-1
endfunction

private function UnitLoop takes nothing returns nothing
     local integer i=UnitTop
     local real x=0
     local real y=0
     local real x0=0
     local real y0=0
     local integer id=0
     local player p=null
     local real unitHP=0
     local real unitHPmax=0
     local real unitHPpercent=0
     local unit u=null
     local group G=null
     local integer AllyI=0
     local integer EnemyI=0
     local real HPmin=0
     local unit weakUnit=null
     loop
         exitwhen i<0
         if IsUnitType(Unit[i],UNIT_TYPE_DEAD) or Unit[i]==null then
             call UnitPop(i)
         else
             if IsUnitType(Unit[i],UNIT_TYPE_STRUCTURE)==false then
             set AllyI=0
             set EnemyI=0
             set HPmin=2000.0
             set p=GetOwningPlayer(Unit[i])
             set id=GetPlayerId(p)+1
             set x=GetUnitX(Unit[i])
             set y=GetUnitY(Unit[i])
             set x0=GetLocationX(StartLoc[id])
             set y0=GetLocationY(StartLoc[id])
             set unitHP=GetUnitState(Unit[i],UNIT_STATE_LIFE)
             set unitHPmax=GetUnitState(Unit[i],UNIT_STATE_MAX_LIFE)
             set unitHPpercent=GetUnitLifePercent2(Unit[i])
             if unitHP<100 and unitHPpercent<0.20 then
                if NewDistanceBetweenXY(x,x0,y,y0)>800 then
                  call IssuePointOrderLoc(Unit[i],"move",StartLoc[id])
                endif  
             endif
             set G=CreateGroup()
             call GroupEnumUnitsInRange(G,x,y,600,null)
             loop
                 set u=FirstOfGroup(G)
                 if u!=null and IsUnitType(u,UNIT_TYPE_DEAD)==false and GetUnitLevel(u)>1 then
                    if IsUnitEnemy(u,p)==true then
                       set EnemyI=EnemyI+1
                       if GetUnitState(u,UNIT_STATE_LIFE)<HPmin then
                          set HPmin=GetUnitState(u,UNIT_STATE_LIFE)
                          set weakUnit=u
                       endif
                    else
                       set AllyI=AllyI+1
                    endif
                 endif
                 call GroupRemoveUnit(G,u)
                 exitwhen u==null
             endloop
             call GroupClear(G)
             call DestroyGroup(G)
             if I2R(EnemyI)>I2R(AllyI)*2 then
                if NewDistanceBetweenXY(x,x0,y,y0)>1500 then
                if GetUnitTypeId(Unit[i])==Hero_BM and GetUnitState(Unit[i],UNIT_STATE_MANA)>=75 then
                else
                call IssuePointOrderLoc(Unit[i],"move",StartLoc[id])
                set UnitRTop=UnitRTop+1
                set UnitR[UnitRTop]=Unit[i]
                set URI[UnitRTop]=0
                if IsUnitInGroup(Unit[i],ReturnUnitsGroup)==false then
                call GroupAddUnit(ReturnUnitsGroup,Unit[i])
                endif
                endif
                endif
             endif
             if weakUnit!=null and HPmin<500 and unitHP>200 and unitHPpercent>0.25 and IsUnitType(Unit[i],UNIT_TYPE_HERO)==false and BeingAttacked[id]==1 then
                if IsUnitType(Unit[i],UNIT_TYPE_MELEE_ATTACKER)==true then
                   if IsUnitType(weakUnit,UNIT_TYPE_GROUND)==true and NewDistanceBetweenXY(x,GetUnitX(weakUnit),y,GetUnitY(weakUnit))<=200 then
                      call IssueTargetOrder(Unit[i],"attack",weakUnit)
                   endif
                else
                   call IssueTargetOrder(Unit[i],"attack",weakUnit)
                endif   
             endif
             if GetUnitTypeId(Unit[i])==Unit_Statue then
                if unitHP<=500 and unitHP>=300 then
                call IssueImmediateOrder(Unit[i],"avengerform")
                endif
             elseif GetUnitTypeId(Unit[i])==Unit_DrTalon then
                    if unitHP<=55 then
                    call IssueImmediateOrder(Unit[i],"ravenform")
                    endif
             elseif GetUnitTypeId(Unit[i])==Unit_DrTalonM then
                    if unitHP>=70 then
                    call IssueImmediateOrder(Unit[i],"unravenform")
                    endif
             elseif GetUnitTypeId(Unit[i])==Unit_DrClaw then
                    if unitHP<=500 and unitHP>=100 then
                    call IssueImmediateOrder(Unit[i],"bearform")
                    endif
             elseif GetUnitTypeId(Unit[i])==Unit_PeaSol and EnemyI<1 then
                    call IssueImmediateOrder(Unit[i],"militiaoff")
             elseif GetUnitTypeId(Unit[i])==Hero_DH and UnitHasBuff(Unit[i],Buff_Immolation)==true and EnemyI<1 then
                    call IssueImmediateOrder(Unit[i],"unimmolation")      
             endif
             elseif IsUnitType(Unit[i],UNIT_TYPE_TOWNHALL)==false then
                call IssuePointOrder(Unit[i],"setrally",0,0)
             endif               
         endif
         set i=i-1
     endloop
     set p=null
     set G=null
     set weakUnit=null
endfunction

private function HeroLoop takes nothing returns nothing
         local integer i=1
         local integer id=0
         loop
         exitwhen i>HeroNumber
         if Hero[i]!=null then
            set id=GetPlayerId(GetOwningPlayer(Hero[i]))+1
         if id>0 and AIPlayer[id]==1 and IsUnitType(Hero[i],UNIT_TYPE_DEAD)==false then
            call HeroStatus(Hero[i],i)
            if OrderMove==1 then
            if CommandHero[id]==null then
            set CommandHero[id]=Hero[i]
            else
            if IsUnitType(CommandHero[id],UNIT_TYPE_DEAD)==true then
            set CommandHero[id]=null
            endif
            if ThirdHero[id]!=null and IsUnitType(ThirdHero[id],UNIT_TYPE_DEAD)==false and GetUnitTypeId(ThirdHero[id])!=Hero_BM then
               set CommandHero[id]=ThirdHero[id]
            endif
            if SecondHero[id]!=null and IsUnitType(SecondHero[id],UNIT_TYPE_DEAD)==false and GetUnitTypeId(SecondHero[id])!=Hero_BM then
               set CommandHero[id]=SecondHero[id]
            endif
            if FirstHero[id]!=null and IsUnitType(FirstHero[id],UNIT_TYPE_DEAD)==false and GetUnitTypeId(FirstHero[id])!=Hero_BM then
               set CommandHero[id]=FirstHero[id]
            endif
            endif
            endif
            if imbaAI==1 then
               call AdjustPlayerState(10,Player(id-1),PLAYER_STATE_RESOURCE_GOLD)
               call AdjustPlayerState(5,Player(id-1),PLAYER_STATE_RESOURCE_LUMBER)
               call SetUnitState(Hero[i],UNIT_STATE_LIFE,GetUnitState(Hero[i],UNIT_STATE_LIFE)+0.01*GetUnitState(Hero[i],UNIT_STATE_MAX_LIFE))
               call SetUnitState(Hero[i],UNIT_STATE_MANA,GetUnitState(Hero[i],UNIT_STATE_MANA)+0.01*GetUnitState(Hero[i],UNIT_STATE_MAX_MANA))
            endif
         endif
         endif   
         set i=i+1
         endloop
         set UnitFuncI=UnitFuncI+1
         if UnitFuncI>=2 then
            set UnitFuncI=0
            call UnitLoop()
         endif
endfunction

private function OrderMoveMovement takes unit hero, group g1, group g2, group g3 returns nothing
        local real x=0
        local real y=0
        local real f=0
        local group army=null
        local integer number=0
        local integer ArmyIndex1=0
        local integer ArmyIndex2=0
        local integer ArmyIndex3=0
        local real array ArmyFacing1
        local real array ArmyFacing2
        local real array ArmyFacing3
        local real array ArmyDistance1
        local real array ArmyDistance2
        local real array ArmyDistance3
        local integer I=0
        local real targetX=0
        local real targetY=0
        if hero!=null then
              set x=GetUnitX(hero)
              set y=GetUnitY(hero)
              set f=GetUnitFacing(hero)
              set I=0
              set army=GroupClearAbandonUnits(g1)
              set number=GroupCountUnits(army)
              if number>0 then//MELEE
                 set ArmyIndex1=number
                 if number>=1 then
                    set I=I+1
                    set soldier1[I]=GroupPickUpUnitNum(army,I)
                    set ArmyFacing1[I]=f
                    set ArmyDistance1[I]=300.0
                    if number>=2 then  
                       set I=I+1
                       set soldier1[I]=GroupPickUpUnitNum(army,I)
                       set ArmyFacing1[I]=f+45.0
                       set ArmyDistance1[I]=300.0
                       if number>=3 then  
                          set I=I+1
                          set soldier1[I]=GroupPickUpUnitNum(army,I)
                          set ArmyFacing1[I]=f-45.0
                          set ArmyDistance1[I]=300.0
                          if number>=4 then  
                             set I=I+1
                             set soldier1[I]=GroupPickUpUnitNum(army,I)
                             set ArmyFacing1[I]=f-90.0
                             set ArmyDistance1[I]=300.0
                             if number>=5 then  
                                set I=I+1
                                set soldier1[I]=GroupPickUpUnitNum(army,I)
                                set ArmyFacing1[I]=f+90.0
                                set ArmyDistance1[I]=300.0
                             endif
                          endif
                       endif
                    endif
                 endif
              endif
              set I=0
              set army=GroupClearAbandonUnits(g2)
              set number=GroupCountUnits(army)
              if number>0 then//RANGED
                 set ArmyIndex2=number
                 if number>=1 then
                    set I=I+1
                    set soldier2[I]=GroupPickUpUnitNum(army,I)
                    set ArmyFacing2[I]=f
                    set ArmyDistance2[I]=200.0
                    if number>=2 then
                       set I=I+1
                       set soldier2[I]=GroupPickUpUnitNum(army,I)
                       set ArmyFacing2[I]=f-180.0
                       set ArmyDistance2[I]=200.0
                       if number>=3 then
                          set I=I+1
                          set soldier2[I]=GroupPickUpUnitNum(army,I)
                          set ArmyFacing2[I]=f+90.0
                          set ArmyDistance2[I]=200.0
                          if number>=4 then
                             set I=I+1
                             set soldier2[I]=GroupPickUpUnitNum(army,I)
                             set ArmyFacing2[I]=f-90.0
                             set ArmyDistance2[I]=200.0
                          endif
                       endif
                    endif
                 endif
              endif
              set I=0
              set army=GroupClearAbandonUnits(g3)
              set number=GroupCountUnits(army)
              if number>0 then//MAGE
                 set ArmyIndex3=number
                 if number>=1 then
                    set I=I+1
                    set soldier3[I]=GroupPickUpUnitNum(army,I)
                    set ArmyFacing3[I]=f-180.0
                    set ArmyDistance3[I]=100.0
                    if number>=2 then
                       set I=I+1
                       set soldier3[I]=GroupPickUpUnitNum(army,I)
                       set ArmyFacing3[I]=f-135.0
                       set ArmyDistance3[I]=200.0
                       if number>=3 then
                          set I=I+1
                          set soldier3[I]=GroupPickUpUnitNum(army,I)
                          set ArmyFacing3[I]=f+135.0
                          set ArmyDistance3[I]=200.0
                       endif
                    endif  
                 endif  
              endif      
              set I=1
              loop
                 exitwhen I>ArmyIndex1 or ArmyIndex1==0
                 set targetX=GetUnitX(hero)+ArmyDistance1[I]*Cos(ArmyFacing1[I]*bj_DEGTORAD)
                 set targetY=GetUnitY(hero)+ArmyDistance1[I]*Sin(ArmyFacing1[I]*bj_DEGTORAD)
                 call IssuePointOrder(soldier1[I],"move",targetX,targetY)

                 set I=I+1
              endloop   
              set I=1
              loop
                 exitwhen I>ArmyIndex2 or ArmyIndex2==0
                 set targetX=GetUnitX(hero)+ArmyDistance2[I]*Cos(ArmyFacing2[I]*bj_DEGTORAD)
                 set targetY=GetUnitY(hero)+ArmyDistance2[I]*Sin(ArmyFacing2[I]*bj_DEGTORAD)
                 call IssuePointOrder(soldier2[I],"move",targetX,targetY)
                 set I=I+1
              endloop
              set I=1
              loop
                 exitwhen I>ArmyIndex3 or ArmyIndex3==0
                 set targetX=GetUnitX(hero)+ArmyDistance3[I]*Cos(ArmyFacing3[I]*bj_DEGTORAD)
                 set targetY=GetUnitY(hero)+ArmyDistance3[I]*Sin(ArmyFacing3[I]*bj_DEGTORAD)
                 call IssuePointOrder(soldier3[I],"move",targetX,targetY)
                 set I=I+1
              endloop
           endif
        set army=null
endfunction

private function OrderMoveLoop takes nothing returns nothing
        local integer index=1
        loop
        exitwhen index>12
        if AIPlayer[index]==1 and BeingAttacked[index]==0 then
        call OrderMoveMovement(CommandHero[index],OrderMELEEGroup[index],OrderRANGEDGroup[index],OrderMAGEGroup[index])   
        endif
        set index=index+1
        endloop
endfunction

private function StrongEnemyPlayers takes nothing returns boolean
    return IsPlayerEnemy(GetFilterPlayer(),WeakPlayer)==true
endfunction

private function IsWeakPlayer takes player p returns boolean
return GetFood(p)<5 or (GetFood(p)<10 and (GetGold(p)<500+imbaAI*99999 or (GetGold(p)>1000 and GetWood(p)<150)))
endfunction

private function PlayerConsciousness takes nothing returns nothing
         local integer i=0
         local group g=null
         local unit u=null
         local player p=null
         set i=0
         loop
         exitwhen i>11
         set p=Player(i)
         if GetPlayerSlotState(p) == PLAYER_SLOT_STATE_PLAYING then
         if RichFriend==null then
            if GetGold(p)>2000 and AIPlayer[i+1]==1 then
               set RichFriend=p
            endif
         else
            if IsPlayerAlly(RichFriend,Player(i))==true and GetPlayerSlotState(p)==PLAYER_SLOT_STATE_PLAYING and AIPlayer[i+1]==1 and GetFood(p)>30 and 1>2 then
               if GetGold(RichFriend)>2000 and GetGold(p)<1000 then
                  call AdjustPlayerState(0,p,PLAYER_STATE_RESOURCE_GOLD)
                  call AdjustPlayerState(0,RichFriend,PLAYER_STATE_RESOURCE_GOLD)
               endif      
            endif
            if p==RichFriend and GetGold(p)<=2000 then
               set RichFriend=null
            endif
         endif
         if AIPlayer[i+1]==1 and WeakPlayer==null and Lose[i+1]==0 and IsWeakPlayer(p)==true then
            set WeakPlayer=p
            if IsPlayerInForce(WeakPlayer,StrongPlayers)==true then
               call ForceRemovePlayer(StrongPlayers,WeakPlayer)
            endif
            if IsPlayerInForce(WeakPlayer, WeakPlayers)==false then
               call ForceAddPlayer(WeakPlayers,WeakPlayer)
            endif
            if StrongPlayer==WeakPlayer then
               set StrongPlayer=null
            endif
         endif
         if StrongPlayer==null and GetFood(p)>70 and GetGold(p)>200 then
            set StrongPlayer=p
            if IsPlayerInForce(StrongPlayer,WeakPlayers)==true then
               call ForceRemovePlayer(WeakPlayers,StrongPlayer)
            endif
            if IsPlayerInForce(StrongPlayer,StrongPlayers)==false then
               call ForceAddPlayer(StrongPlayers,StrongPlayer)
            endif
            if StrongPlayer==WeakPlayer then
               set WeakPlayer=null
            endif
            set StrongPlayer=null
         endif
         if WeakPlayer!=null and CountPlayersInForce(StrongPlayers)>0 and Lose[i+1]==0 and GetFood(WeakPlayer)<10 then
            if CountPlayersInForce(NewGetPlayersMatching(Condition(function StrongEnemyPlayers)))>0 then
            set Lose[i+1]=1
            set g=CreateGroup()
            call GroupEnumUnitsInRange(g,0,0,99999.00,null)
            loop
            set u=FirstOfGroup(g)
            if u!=null and IsUnitType(u,UNIT_TYPE_DEAD)==false and GetOwningPlayer(u)==WeakPlayer then
               call KillUnit(u)
            endif   
            call GroupRemoveUnit(g,u)
            exitwhen u==null
            endloop
            call GroupClear(g)
            call DestroyGroup(g)
            set WeakPlayer=null
            endif
         endif
         endif
         set i=i+1
         endloop
         set g=null
         set u=null
         set p=null
endfunction

private function HeroBuyItem takes nothing returns nothing
         local integer i=1
         local integer n=1
         local integer ram=1
         local integer id=0
         local real d=0
         local real d2=0
         local real x=0
         local real y=0
         local real x0=0
         local real y0=0
         set id=0
         set d=1.00
         loop
         exitwhen i>HeroNumber
         if Hero[i]!=null then
            set id=GetPlayerId(GetOwningPlayer(Hero[i]))+1
         if id>0 and AIPlayer[id]==1 and IsUnitType(Hero[i],UNIT_TYPE_DEAD)==false and BeingAttacked[id]==0 then
            set x=GetUnitX(Hero[i])
            set y=GetUnitY(Hero[i])
            set ShortestDistance=20000.0
            loop
            exitwhen n>ShopNumber or Shop[1]==null
            if Shop[n]!=null then
               set x0=GetUnitX(Shop[n])
               set y0=GetUnitY(Shop[n])
               set d=NewDistanceBetweenXY(x,x0,y,y0)
               if d<ShortestDistance then
                  set ShortestDistance=d
               endif   
            endif   
            set n=n+1
            endloop
            set n=1
            set ram=GetRandomInt(1,2)
            loop
            exitwhen n>ShopNumber
            if Shop[n]!=null then   
               set x0=GetUnitX(Shop[n])
               set y0=GetUnitY(Shop[n])
               set d=NewDistanceBetweenXY(x,x0,y,y0)
               if d==ShortestDistance and ram>0 then
                  call IssueTargetOrder(Hero[i],"smart",Shop[n])
               endif   
            endif
            set n=n+1
            endloop
         if PShop[id]!=null then
            set x0=GetUnitX(PShop[id])
            set y0=GetUnitY(PShop[id])
            set d2=NewDistanceBetweenXY(x,x0,y,y0)
            if d2<d and d2<1000 then
               call IssueTargetOrder(Hero[i],"smart",PShop[id])
            endif
         endif
         endif  
         endif
         set i=i+1
         endloop
         set ShortestDistance=20000.0
         call PlayerConsciousness()
endfunction

private function TriggerRegisterEnterRect takes trigger trig, rect r returns event
    call RegionAddRect(RectRegion, r)
    return TriggerRegisterEnterRegion(trig, RectRegion, null)
endfunction

private function AvoidSkillTimer takes nothing returns nothing
         local integer i=1
         loop
         exitwhen i>HeroNumber
         if GetExpiredTimer()==SkillWaitTimer[i] then
            call HeroProtection(Hero[i])
            call DestroyTimer(SkillWaitTimer[i])
         endif
         set i=i+1
         endloop
endfunction

private function SpellMovementTimer takes nothing returns nothing
         local integer i=1
         loop
         exitwhen i>HeroNumber
         if GetExpiredTimer()==SpellingTimer[i] then
            set Spelling[i]=0
         endif
         set i=i+1
         endloop
endfunction

private function GetInstantAbility takes integer skill returns boolean
        return (skill==Skill_Lighting or skill==Skill_Hex or skill==Skill_Sleep or skill==Skill_Frostnova or skill==Skill_Roots  or skill==Skill_Holybolt)
endfunction

private function TriggerRegisterAnyUnitSpell takes nothing returns nothing
         local unit speller=null
         local unit target=null
         local unit u=null
         local location l=null
         local integer i=0
         local integer id=0
         local integer Level=0
         local integer skill=0
         local real x=0
         local real y=0
         local group g=null
         local real a=0
         local integer num=0
         set speller=GetTriggerUnit()
         set target=GetSpellTargetUnit()
         set skill=GetSpellAbilityId()
         set id=GetPlayerId(GetOwningPlayer(speller))+1
         if skill==Skill_Blizzard or skill==Skill_flamestrike or skill==Skill_rainoffire then
            set l=GetSpellTargetLoc()
            set x=GetLocationX(l)
            set y=GetLocationY(l)
            set g=CreateGroup()
            call GroupEnumUnitsInRange(g,x,y,225.00,null)
            loop
            set u=FirstOfGroup(g)
            if u!=null and IsUnitType(u,UNIT_TYPE_DEAD)==false and AIPlayer[GetPlayerId(GetOwningPlayer(u))+1]==1 then
               set a=NewAngleBetweenXY(x,GetUnitX(u),y,GetUnitY(u))
               call IssuePointOrder(u,"move",x+256*Cos(a*bj_DEGTORAD),y+256*Sin(a*bj_DEGTORAD))
            endif   
            call GroupRemoveUnit(g,u)
            exitwhen u==null
            endloop
            call GroupClear(g)
            call DestroyGroup(g)
            call RemoveLocation(l)
         endif
         if IsUnitType(speller,UNIT_TYPE_HERO)==true then
            set num=1
            loop
            exitwhen num>HeroNumber
            if speller==Hero[num] then
                set Spelling[num]=1
                call TimerStart(SpellingTimer[num],1.5,false,function SpellMovementTimer)
            endif  
            set num=num+1
            endloop
            if target!=null then
               if IsUnitType(target,UNIT_TYPE_HERO)==true and IsPlayerEnemy(GetOwningPlayer(target),GetOwningPlayer(speller))==true and AIPlayer[GetPlayerId(GetOwningPlayer(target))+1]==1 then
                  set x=GetUnitX(speller)+1000*Cos(GetUnitFacing(speller)*bj_DEGTORAD)
                  set y=GetUnitY(speller)+1000*Sin(GetUnitFacing(speller)*bj_DEGTORAD)
                  call IssuePointOrder(target,"move",x,y)
                  set Level=GetUnitAbilityLevel(speller,skill)
                  set id=GetPlayerId(GetOwningPlayer(target))+1
                  if GetUnitTypeId(target)==Hero_WD then
                     call IssuePointOrderLoc(target,"blink",StartLoc[GetPlayerId(GetOwningPlayer(target))+1])
                  endif
                  if GetUnitState(target,UNIT_STATE_LIFE)<200*I2R(Level)-100 and GetUnitLifePercent2(target)<0.55 then
                     if GetInstantAbility(skill)==true then
                        call HeroProtection(target)
                     else
                     set num=1
                     loop
                     exitwhen num>HeroNumber
                     if target==Hero[num] then
                        set SkillWaitID[num]=GetPlayerId(GetOwningPlayer(target))+1
                        set SkillWaitTimer[num]=CreateTimer()
                        call TimerStart(SkillWaitTimer[num],0.4,false,function AvoidSkillTimer)
                     endif  
                     set num=num+1
                     endloop
                     endif
                  endif
               endif   
            else
               set Level=GetUnitAbilityLevel(speller,skill)
               if skill==Skill_Stomp then
                  set x=GetUnitX(speller)
                  set y=GetUnitY(speller)
                  set g=CreateGroup()
                  call GroupEnumUnitsInRange(g,x,y,200.00+I2R(Level)*50,null)
                  loop
                  set u=FirstOfGroup(g)
                  if u!=null and IsUnitType(u,UNIT_TYPE_DEAD)==false and AIPlayer[GetPlayerId(GetOwningPlayer(u))+1]==1 and IsUnitType(u,UNIT_TYPE_GROUND)==true and IsPlayerEnemy(GetOwningPlayer(u),GetOwningPlayer(speller))==true then
                     set a=NewAngleBetweenXY(x,GetUnitX(u),y,GetUnitY(u))
                     call IssuePointOrder(u,"move",x+(200.00+I2R(Level)*50)*Cos(a*bj_DEGTORAD),y+(200.00+I2R(Level)*50)*Sin(a*bj_DEGTORAD))
                     if IsUnitType(u,UNIT_TYPE_HERO)==true and GetUnitState(u,UNIT_STATE_LIFE)/GetUnitState(u,UNIT_STATE_MAX_LIFE)<0.15*I2R(Level) then
                        call HeroProtection(u)
                     endif   
                  endif   
                  call GroupRemoveUnit(g,u)
                  exitwhen u==null
                  endloop
                  call GroupClear(g)
                  call DestroyGroup(g)
                  call RemoveLocation(l)
               endif
               if skill==Skill_Blink and 1>2 then
                  set l=GetSpellTargetLoc()
                  set a=NewAngleBetweenXY(x,GetLocationX(l),y,GetLocationY(l))
                  set x=GetUnitX(speller)+1000*Cos(a*bj_DEGTORAD)
                  set y=GetUnitY(speller)+1000*Sin(a*bj_DEGTORAD)
                  call SetUnitPosition(speller,x,y)
                  if Level==1 then
                     call SetUnitState(speller,UNIT_STATE_MANA,GetUnitState(speller,UNIT_STATE_MANA)-50.00)
                  else
                     call SetUnitState(speller,UNIT_STATE_MANA,GetUnitState(speller,UNIT_STATE_MANA)-10.00)
                  endif
                  call RemoveLocation(l)
               endif
            endif      
         endif         
         if GetUnitTypeId(speller)==Unit_Bat and target!=null and IsUnitType(target,UNIT_TYPE_FLYING)==true then
            set x=GetUnitX(target)
            set y=GetUnitY(target)
            set g=CreateGroup()
            call GroupEnumUnitsInRange(g,x,y,400.00,null)
            loop
            set u=FirstOfGroup(g)
            if u!=null and u!=target and IsUnitType(u,UNIT_TYPE_DEAD)==false and AIPlayer[GetPlayerId(GetOwningPlayer(u))+1]==1 and IsUnitType(u,UNIT_TYPE_FLYING)==true and IsPlayerEnemy(GetOwningPlayer(u),GetOwningPlayer(speller))==true then
               set a=NewAngleBetweenXY(x,GetUnitX(u),y,GetUnitY(u))
               call IssuePointOrder(u,"move",x+400*Cos(a*bj_DEGTORAD),y+400*Sin(a*bj_DEGTORAD))
            endif   
            call GroupRemoveUnit(g,u)
            exitwhen u==null
            endloop
            call GroupClear(g)
            call DestroyGroup(g)
         endif
         set u=null
         set speller=null
         set target=null
         set l=null
         set g=null
endfunction

private function TriggerRegisterAnyUnitDead takes nothing returns nothing
         local unit u=GetTriggerUnit()
         if IsUnitInGroup(u,AllyTargetGroup)==true then
            call GroupRemoveUnit(AllyTargetGroup,u)
         elseif IsUnitInGroup(u,EnemyTargetGroup)==true then
                call GroupRemoveUnit(EnemyTargetGroup,u)
         endif      
         set u=null
endfunction

private function TriggerRegisterAnyUnit takes nothing returns nothing
     local integer i=1
     local unit u=GetTriggerUnit()
     local player p=GetOwningPlayer(u)
     set i=GetPlayerId(p)+1
       if AIPlayer[i]==1 then
          if IsUnitType(u,UNIT_TYPE_HERO)==true then
             if IsUnitIllusion(u)==false and IsUnitInGroup(u,HerosGroup)==false then
             set HeroNumber=HeroNumber+1
             set Hero[HeroNumber]=u
             call GroupAddUnit(HerosGroup,u)
             set SpellingTimer[HeroNumber]=CreateTimer()
             set Spelling[HeroNumber]=0
             if FirstHero[i]==null then
                set FirstHero[i]=u
             endif
             if SecondHero[i]==null and FirstHero[i]!=null and u!=FirstHero[i] then
                set SecondHero[i]=u
             endif
             if ThirdHero[i]==null and FirstHero[i]!=null and SecondHero[i]!=null and u!=FirstHero[i] and u!=SecondHero[i] then
                set ThirdHero[i]=u
             endif
             if GetUnitTypeId(Hero[HeroNumber])==Hero_BM then
                set BMtimer[HeroNumber]=CreateTimer()
             endif  
             endif
          endif
          if GetUnitTypeId(u)==Unit_HShop or GetUnitTypeId(u)==Unit_OShop or GetUnitTypeId(u)==Unit_UShop or GetUnitTypeId(u)==Unit_EShop then
             set PShop[i]=u
          endif   
          if IsUnitType(u,UNIT_TYPE_SUMMONED)==false and GetUnitAbilityLevel(u,'Aloc')==0 then
             set UnitTop=UnitTop+1
             set Unit[UnitTop]=u
             if imbaAI==1 then
                if GetUnitAbilityLevel(u,Skill_Item_AttackSpeed)==0 then
                   call UnitAddAbility(u,Skill_Item_AttackSpeed)
                   call UnitAddAbility(u,Skill_Item_HPrecover)
                   if IsUnitType(u,UNIT_TYPE_STRUCTURE)==true then
                      call UnitSetConstructionProgress(u,15)
                   endif   
                endif
             endif   
          endif
       endif
     set u=null
     set p=null
endfunction

private function TriggerProduceTimer takes nothing returns nothing
     local integer i=0
     call DestroyTrigger(AnyUnitEnter)
     call DestroyTrigger(AttackingTrigger)
     call DestroyTrigger(AnyUnitSpell)
     set AnyUnitEnter=CreateTrigger()
     set AttackingTrigger=CreateTrigger()
     set AnyUnitSpell=CreateTrigger()
     call TriggerRegisterEnterRect(AnyUnitEnter,bj_mapInitialPlayableArea)
     call TriggerAddAction(AnyUnitEnter,function TriggerRegisterAnyUnit)
     call TriggerAddAction(AttackingTrigger,function AttackerAndVictim)
     call TriggerAddAction(AnyUnitSpell,function TriggerRegisterAnyUnitSpell)
     loop
     exitwhen i>11
     call TriggerRegisterPlayerUnitsEventSimple(AttackingTrigger,Player(i),EVENT_PLAYER_UNIT_ATTACKED)
     call TriggerRegisterPlayerUnitsEventSimple(AnyUnitSpell,Player(i),EVENT_PLAYER_UNIT_SPELL_CHANNEL)
     set i=i+1
     endloop
endfunction

public function LockIMBAmode takes nothing returns nothing
        local integer i=0
        set imbaAI=0
        loop
        exitwhen i>11
        if GetPlayerController(Player(i))==MAP_CONTROL_COMPUTER then
           call SetPlayerHandicapXP(Player(i),1.00)
        endif
        set i=i+1
        endloop
endfunction

public function ChangePlayerName takes nothing returns nothing
       if changeplayername==0 then
       set changeplayername=1
       else
       set changeplayername=0
       endif
endfunction

public function UnlockIMBAmode takes nothing returns nothing
        local integer i=0
        set imbaAI=1
        loop
        exitwhen i>11
        if GetPlayerController(Player(i))==MAP_CONTROL_COMPUTER and AIPlayer[i+1]==1 then
           call SetPlayerHandicapXP(Player(i),2.00)
        endif
        set i=i+1
        endloop
endfunction

public function StopAIForPlayer takes player p returns nothing
        if GetPlayerController(p)==MAP_CONTROL_COMPUTER then
           set AIPlayer[GetPlayerId(p)+1]=0
           if changeplayername==1 then
           call SetPlayerName(p,"computer"+I2S(GetRandomInt(1,100)))
           endif
        endif   
endfunction

public function UseAIForPlayer takes player p returns nothing
        local string s=""
        local integer i=1
        local integer n=1
        if GetPlayerController(p)==MAP_CONTROL_COMPUTER then
           set AIPlayer[GetPlayerId(p)+1]=1
           if changeplayername==1 then
           set s=UnitId2StringAI(ChooseRandomCreep(-1))
           set i=StringLength(s)
           if i>=6 and i<=12 then
           set n=i
           set i=GetRandomInt(i-5,i-1)
           set s=SubString(s,i,n)
           endif
           if i>12 then
           set n=i
           set i=GetRandomInt(i-7,i-3)
           set s=SubString(s,i,n)
           endif
           call SetPlayerName(p,"[AISystem]"+s)
           endif
        endif
        set s=null
endfunction

public function StartAI takes nothing returns nothing
         local integer i=1
         local group g=CreateGroup()
         local unit u
         loop
         exitwhen i>12
         set StartLoc[i]=GetPlayerStartLocationL(Player(i-1))
         set BuyDust[i]=0
         set Lose[i]=0
         set AllyGroupUse[i]=0
         set EnemyGroupUse[i]=0
         set BeingAttacked[i]=0
         set LastEnemyLevel[i]=0
         set LastAllyLevel[i]=0
         if GetPlayerController(Player(i+1))==MAP_CONTROL_COMPUTER then
         set AllyTimer[i]=CreateTimer()
         set EnemyTimer[i]=CreateTimer()
         set AETim[i]=CreateTimer()
         set AllyAttackGroup[i]=CreateGroup()
         set EnemyAttackGroup[i]=CreateGroup()
         set OrderMELEEGroup[i]=CreateGroup()
         set OrderRANGEDGroup[i]=CreateGroup()
         set OrderMAGEGroup[i]=CreateGroup()
         set FirstHero[i]=null
         set SecondHero[i]=null
         set ThirdHero[i]=null
         set CommandHero[i]=null
         endif
         if AIPlayer[i]!=1 then
            set AIPlayer[i]=0
         endif   
         set i=i+1
         endloop
         set AIPlayer[0]=0
         set SingleGroupCountUnit=0
         set HeroNumber=0
         set StrongEnemyGroupCountUnit=0
         set ShopNumber=0
         set imbaAI=0
         set changeplayername=0
         set OrderMove=0
         set UnitTop=-1
         set UnitFuncI=0
         set UnitRTop=-1
         set ShortestDistance=10000.0
         set RichFriend=null
         set WeakPlayer=null
         set StrongPlayer=null
         set SingleJudgementGroup=CreateGroup()
         set HerosGroup=CreateGroup()
         set StrongEnemyGroup=CreateGroup()
         set WeakAllyGroup=CreateGroup()
         set ReturnUnitsGroup=CreateGroup()
         set StrongPlayers=CreateForce()
         set WeakPlayers=CreateForce()
         set Force=CreateForce()
         set AttackIntervalTimer=CreateTimer()
         set RectRegion=CreateRegion()
         set AnyUnitEnter=CreateTrigger()
         set AttackingTrigger=CreateTrigger()
         set AnyUnitSpell=CreateTrigger()
         call GroupEnumUnitsInRange(g,0,0,20000.00,null)
         loop
         set u=FirstOfGroup(g)
            if GetUnitTypeId(u)==Unit_Shop then
               set ShopNumber=ShopNumber+1
               set Shop[ShopNumber]=u
            endif   
            call GroupRemoveUnit(g,u)
            exitwhen u==null
         endloop
         call GroupClear(g)
         call DestroyGroup(g)
         call TriggerRegisterEnterRect(AnyUnitEnter,bj_mapInitialPlayableArea)
         call TriggerAddAction(AnyUnitEnter,function TriggerRegisterAnyUnit)
         call TriggerAddAction(AnyUnitSpell,function TriggerRegisterAnyUnitSpell)
         call TriggerAddAction(AttackingTrigger,function AttackerAndVictim)
         call TimerStart(CreateTimer(),60.00,true,function TriggerProduceTimer)
         call TimerStart(CreateTimer(),1.00,true,function HeroLoop)
         call TimerStart(CreateTimer(),30.00,true,function HeroBuyItem)
         call TimerStart(CreateTimer(),0.30,true,function UnitReturn)
         set g=null
         set u=null
endfunction

endlibrary


回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-25 16:54:41 | 显示全部楼层
建议用输入管理器导入以下各族的AI,并如图所示令电脑玩家运行下列AI

AI的文件路径也可以改成
Scripts\orc.ai
Scripts\human.ai
Scripts\undead.ai
Scripts\elf.ai
这样就可直接覆盖魔兽自带AI,不必再使用触发运行了,当然用此方法需要一个动作:对战游戏-对电脑玩家运行AI脚本

A3.JPG
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-25 17:06:57 | 显示全部楼层
万能对战AI模板

送给懒人或不会用AI编辑器的人用的,只需简单替换,再导入游戏中使电脑玩家运行该AI,就可实现自创种族做出建房子、造兵、进攻等行为了

//===========================================================================
// egg.ai
// 通用标准对战AI模板
// 使用方法:将下列的所有物体ID(如'nmpe')替换成你新定义的单位或科技的物体ID(如'n001'),再保存并导入到地图中,最后用触发器运行即可
// 物体ID可在物体编辑器中按下Ctrl+D查看,一般自定义单位或科技会出现两个ID(如 H006:Hpal),取最前面的一个,即('H006')  
// 切勿随意改动物体ID以外的内容,这样做很可能会使整个脚本无法运行  
// by 金皮蛋
//
//===========================================================================

//***************************************************************************
//*
//*  Global Variables
//*
//***************************************************************************

globals
//***********************可修改的内容(仅物体ID)*****************************
//普通单位(空缺单位可用0代替)        
        integer NWorKer='nmpe'//工人
        integer NEleArms1='nnmg'//初级步兵
        integer NEleArms2='e002'//初级射手(需仓库)
        integer NEleArms3='e001'//初级攻城类(需仓库)
        integer NIntArms1='nmyr'//中级兵种1(需二级基地)
        integer NIntArms2='nsnp'//中级兵种2(需二级基地)
        integer NIntArms3=0//中级兵种3(需二级基地)
        integer NIntArms4='nnsw'//法师类1(需二级基地)
        integer NIntArms5='nwgs'//法师类2(需二级基地)
        integer NIntArms6='n008'//法师类3(需二级基地)
        integer NIntArms7='nhyc'//中级兵种4(需三级基地)
        integer NIntArms8=0//法师类4(需三级基地)
        integer NHigArms1='e000'//终极兵种(需三级基地)
        integer NHigArms2=0//终极兵种(需三级基地)      
//英雄        
        integer NHero1='H000'//英雄1
        integer NHero2='H002'//英雄2
        integer NHero3='O000'//英雄3
        integer NHero4='H006'//英雄4
//建筑(空缺建筑可用0代替)   
        integer NTown1='nntt'//第一级基地
        integer NTown2='n000'//第二级基地
        integer NTown3='n001'//第三级基地
        integer NBarracks1='h005'//初级兵营
        integer NBarracks2='nnsg'//中级部队训练营地
        integer NBarracks3='nnsa'//法师类生产基地
        integer NBarracks4='n00B'//终极兵种产地
        integer NHouse='nnfm'//增加人口建筑
        integer NAltar='nnad'//英雄祭坛
        integer NShop='h003'//商店
        integer NDepot='e003'//仓库及研究所
        integer NGuard='nntg'//防御塔
//科技(空缺科技可用0代替)     
        integer NUpdataAttack1='Rnat'//提升攻击1(lv3)
        integer NUpdataDefend1='Rnam'//提升防御1(lv3)
        integer NUpdataAttack2='R001'//提升攻击2(lv3)
        integer NUpdataDefend2='R002'//提升防御2(lv3)
        integer NUpdataDepot='R003'//仓库升级科技(lv1~lv3)
        integer NUpdataEB1='R006'//初级兵营科技1(lv1)
        integer NUpdataEB2='R00A'//初级兵营科技2(lv1)
        integer NUpdataEB3='R00D'//初级兵营科技3(lv1)
        integer NUpdataIB1='R004'//中级兵营科技1(lv1)
        integer NUpdataIB2='Rnen'//中级兵营科技2(lv1)
        integer NUpdataIB3=0//中级兵营科技3(lv1)
        integer NUpdataIB4='R00C'//中级兵营科技4(lv1)
        integer NUpdataIB5='R00B'//法师类科技1(lv1)
        integer NUpdataIB6='Rnsw'//法师类科技2(lv2)
        integer NUpdataIB7='R007'//法师类科技3(lv2)
        integer NUpdataIB8='Rnsi'//法师类科技4(lv1)
        integer NUpdataHB1='R008'//高级兵营科技1(lv1)
        integer NUpdataTown='Rnsb'//城镇科技(lv1)
        integer NUpdataBag='R000'//背包技能(lv1)
//技能
        integer NHA11='A00J'//英雄1的第一个技能
        integer NHA12='A00Y'//英雄1的第二个技能        
        integer NHA13='A00B'//英雄1的第三个技能
        integer NHA14='A02K'//英雄1的终极技能
        integer NHA21='A00H'//英雄2的第一个技能
        integer NHA22='A00A'//英雄2的第二个技能        
        integer NHA23='A02U'//英雄2的第三个技能
        integer NHA24='A00X'//英雄2的终极技能
        integer NHA31='A00C'//英雄3的第一个技能
        integer NHA32='A01Q'//英雄3的第二个技能        
        integer NHA33='A01U'//英雄3的第三个技能
        integer NHA34='A009'//英雄3的终极技能
        integer NHA41='A01A'//英雄4的第一个技能
        integer NHA42='A003'//英雄4的第二个技能        
        integer NHA43='A008'//英雄4的第三个技能
        integer NHA44='A00R'//英雄4的终极技能
//其它
        integer NTotalFoodMAX=100//最大人口数
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-25 17:09:26 | 显示全部楼层
AI系统及脚本

AIsystem为智能AI系统
Egg为万能对战AI模板
其余为自己修改的各族AI脚本

智能AI系统 AI脚本.rar

38.2 KB, 下载次数: 275

回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-25 17:58:28 | 显示全部楼层
回复 支持 反对

使用道具 举报

发表于 2013-8-25 18:02:42 | 显示全部楼层
回复 支持 反对

使用道具 举报

发表于 2013-8-25 18:20:47 | 显示全部楼层
对了,Lz怎么厉害,能不能帮我做个鱼人的
回复 支持 反对

使用道具 举报

发表于 2013-12-19 15:40:05 | 显示全部楼层
yao feng a
回复 支持 反对

使用道具 举报

发表于 2013-12-20 16:35:42 | 显示全部楼层
楼主好厉害
回复 支持 反对

使用道具 举报

发表于 2013-12-20 22:03:05 | 显示全部楼层
LZ  问下   这条J可以用在对抗地图里吗  就像dota那样的
回复 支持 反对

使用道具 举报

发表于 2013-12-21 09:45:09 | 显示全部楼层
LS,没有万能的AI,目前所谓的游戏AI是指在某个框架下的模拟人类操作的程序
普通对战和dota的框架是完全不同,不能兼容。
PS:总体来说类Dota游戏的AI比对战AI简单。
回复 支持 反对

使用道具 举报

发表于 2013-12-21 17:44:57 | 显示全部楼层
那请问有没有这种AI的演示呢
回复 支持 反对

使用道具 举报

发表于 2014-6-30 00:32:01 | 显示全部楼层
楼主求助啊!YDWE怎么修改啊?YDWE有自己的函数系统貌似加上就出错了。要怎么修改以下的、、?
回复 支持 反对

使用道具 举报

发表于 2016-10-21 23:39:53 | 显示全部楼层
顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶大大大
回复 支持 反对

使用道具 举报

发表于 2017-2-12 23:03:58 | 显示全部楼层
完全看不懂啊
回复 支持 反对

使用道具 举报

发表于 2018-8-20 00:43:46 来自GA卫星 | 显示全部楼层
LZ,请问一下,3楼的自定义代码都需要在触发里面输入么?
回复 支持 反对

使用道具 举报

*滑动验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|移动端|小黑屋|地精研究院

GMT+8, 2018-12-15 21:19 , Processed in 0.062408 second(s), 10 queries , Gzip On, Redis On.

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表