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

[AI]Melee AI system

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
  • Like
Reactions: Sarsaparilla
Melee AI system:
(compatible with AMAI)
last hit and deny, to kill a unit when residual blood
units who badly wounded will evade the enemy
prevent heroes rushing to the battlefront ,and residual blood hero will sent back to the base
other farmers to buy zeppelin, logging machines and mercenary
transports are using better than original melee AI
may do TowerRush if AI has adequate resources
Hero who is stuck can return to base
AI may attack some destructables, such as gate
hero will buy some items and use them
hero will pick up items along the way
expand the scope of building construction around the base
AI will suicide when it was put at a disadvantage

JASS:
 //TESH.scrollpos=1291
//TESH.alwaysfold=0
library AIsystem initializer InitAll
globals
//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'
private constant integer Item_ssan = 'ssan'
private constant integer Item_spre = 'spre'
private constant integer Item_clsd = 'clsd'

//Unit
private constant integer Ut_hto1 = 'htow'
private constant integer Ut_hto2 = 'hkee'
private constant integer Ut_hto3 = 'hcas'
private constant integer Ut_oto1 = 'ogre'
private constant integer Ut_oto2 = 'ostr'
private constant integer Ut_oto3 = 'ofrt'
private constant integer Ut_uto1 = 'unpl'
private constant integer Ut_uto2 = 'unp1'
private constant integer Ut_uto3 = 'unp2'
private constant integer Ut_eto1 = 'etol'
private constant integer Ut_eto2 = 'etoa' 
private constant integer Ut_eto3 = 'etoe'
private constant integer Ut_htw1 = 'hwtw'
private constant integer Ut_htw2 = 'hgtw'
private constant integer Ut_utw1 = 'uzig'
private constant integer Ut_utw2 = 'uzg1'
private constant integer Ut_utw3 = 'uzg2'
private constant integer Ut_etw1 = 'emow'

private constant integer FoodUsed_upg_town1 = 30
private constant integer FoodUsed_upg_town2 = 65

private constant integer UnitType_zeppelin = 'nzep'
private constant integer UnitType_TronGloem = 'ngir'
private constant integer UnitType_AmmoDump = 'ngad'
//Buff
private constant integer Buff_sleep = 'BUsl'

//testunit
private constant integer UnitType_build_block = 'ncp2'
private constant integer UnitType_Harvest = 'nmpe'
endglobals

//math
function DistanceBetweenXY takes real x1,real x2,real y1,real y2 returns real
return SquareRoot(( x1 - x2 ) * ( x1 - x2 ) + ( y1 - y2 ) * ( y1 - y2 ))
endfunction
function AngleBetweenXY takes real x1, real x2, real y1, real y2 returns real
return bj_RADTODEG*Atan2( y2 - y1 , x2 - x1 )
endfunction
function RadianBetweenXY takes real x1, real x2, real y1, real y2 returns real
return Atan2( y2 - y1 , x2 - x1 )
endfunction
function DistanceBetweenUnits takes unit u1, unit u2 returns real
local real x1 = GetUnitX(u1)
local real x2 = GetUnitX(u2)
local real y1 = GetUnitY(u1)
local real y2 = GetUnitY(u2)
return SquareRoot(( x1 - x2 ) * ( x1 - x2 ) + ( y1 - y2 ) * ( y1 - y2 ))
endfunction
function AngleBetweenUnits takes unit u1, unit u2 returns real
return bj_RADTODEG*Atan2( GetUnitY(u2) - GetUnitY(u1) , GetUnitX(u2) - GetUnitX(u1) )
endfunction
function RadianBetweenUnits takes unit u1, unit u2 returns real
return Atan2( GetUnitY(u2) - GetUnitY(u1) , GetUnitX(u2) - GetUnitX(u1) )
endfunction
function DistanceBetweenPoint takes location l1, location l2 returns real
local real x1 = GetLocationX(l1)
local real x2 = GetLocationX(l2)
local real y1 = GetLocationY(l1)
local real y2 = GetLocationY(l2)
return SquareRoot(( x1 - x2 ) * ( x1 - x2 ) + ( y1 - y2 ) * ( y1 - y2 ))
endfunction
globals
private real map_max_X 
private real map_max_Y 
private real map_min_X 
private real map_min_Y 
endglobals
//
function OrderUnitMoveAng takes unit u, real dis, real ang returns nothing
local real x = 0.
local real y = 0.
set x = GetUnitX(u) + dis*Cos(ang*bj_DEGTORAD)
set y = GetUnitY(u) + dis*Sin(ang*bj_DEGTORAD)
call IssuePointOrder(u,"move",x,y)
endfunction
function OrderUnitMove takes unit u, real dis, real ang returns nothing
local real x = 0.
local real y = 0.
set x = GetUnitX(u) + dis*Cos(ang)
set y = GetUnitY(u) + dis*Sin(ang)
call IssuePointOrder(u,"move",x,y)
endfunction
function OrderUnitMoveXY takes unit u,real x,real y,real dis,real ang returns nothing
set x = x + dis*Cos(ang)
set y = y + dis*Sin(ang)
call IssuePointOrder(u,"move",x,y)
endfunction
//
function MoveUnitXY takes unit u, real dis, real ang returns nothing
local real x = GetUnitX(u)
local real y = GetUnitY(u)
set x = x + dis*Cos(ang*bj_DEGTORAD)
set y = y + dis*Sin(ang*bj_DEGTORAD)
if x<map_max_X and y<map_max_Y and x>map_min_X and y>map_min_Y then
call SetUnitX(u,x)
call SetUnitY(u,y)
endif
endfunction
//
function IsUnitInvulnerable takes unit u returns boolean
local real h = GetUnitState(u,UNIT_STATE_LIFE)
call UnitDamageTarget(u,u,0.01,false,false,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
if GetUnitState(u,UNIT_STATE_LIFE) < h then
call SetUnitState(u,UNIT_STATE_LIFE,h) 
return false
endif
return true
endfunction
//
function SetUnitPathingAll takes unit u,boolean b returns nothing
if GetUnitAbilityLevel(u,'Atwa') < 1 then
call UnitAddAbility( u, 'Atwa' )
call UnitRemoveAbility( u, 'Atwa' )
if b==true then
call ShowUnit(u,false)
call ShowUnit(u,true)
endif
endif
endfunction
//
function CancelUnitMoveAndAttack takes unit u returns nothing
call UnitRemoveAbility( u, 'Amov' )
call UnitRemoveAbility( u, 'Aatk' )
endfunction
//build
private function IssueHauntOrderAtLocEx takes unit whichPeon,location loc,integer typeid returns nothing
local group g = null
local unit goldMine = null
set g = CreateGroup()
call GroupEnumUnitsInRangeOfLoc(g, loc, 256.0, filterIssueHauntOrderAtLocBJ)
set goldMine = FirstOfGroup(g)
call GroupClear(g)
call DestroyGroup(g)
set g = null
if (goldMine != null) then
call IssueTargetOrderById(whichPeon, typeid, goldMine)
endif
set goldMine = null
endfunction
function BuildOrderByIdNearbyLoc takes unit builder,integer structure,location loc returns nothing
local location testloc
local integer level = 0
local unit testunit = CreateUnitAtLoc(Player(PLAYER_NEUTRAL_PASSIVE), structure, loc, 0.)
set testloc = GetUnitLoc(testunit)
set level = GetUnitAbilityLevel(testunit, 'Abgm')
call ShowUnit( testunit,false )
call KillUnit( testunit )
if level > 0 then
call IssueHauntOrderAtLocEx(builder, loc, structure)
else
call IssueBuildOrderById(builder, structure, GetLocationX(testloc), GetLocationY(testloc))
endif
call RemoveLocation( testloc )
set testloc = null
set testunit = null
endfunction
//
function IsUnitNarrowPathed takes unit u returns boolean
local unit testunit 
local real i = 0.0
local real a = 0.0
local integer n = 0
local real x = GetUnitX(u)
local real y = GetUnitY(u)
loop
exitwhen i > 7.0
set a=45.0 * i
set testunit = CreateUnit(Player(15),'nsln',x+168.0*Cos(a*bj_DEGTORAD),y+168.0*Sin(a*bj_DEGTORAD),0.)
if DistanceBetweenXY(GetUnitX(testunit),x,GetUnitY(testunit),y) > 184.0 then
set n = n + 1
endif
call ShowUnit( testunit,false )
call KillUnit( testunit )
set testunit = null
set i = i + 1.0
endloop
if n > 2 then
return true
endif
return false
endfunction
//groups
globals
private unit GroupPickUnit
endglobals
//
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
//
function GroupClearDeadUnits takes group g returns nothing
local unit u
local group G
set G=CreateGroup() 
loop
set u=FirstOfGroup(g)
if u!= null then
if GetUnitState(u,UNIT_STATE_LIFE)>0.0 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
endfunction
function GroupCountUnitsRemoveDead 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
if GetUnitState(u,UNIT_STATE_LIFE)>0.0 then
call GroupAddUnit(G,u)
set n=n+1
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 n
endfunction
//AI
globals
private region RectRegion
private trigger AnyUnitEnter = CreateTrigger()
private group group_speller = CreateGroup()
private trigger AnyUnitSpell = CreateTrigger()
private trigger AnyUnitSpellEnd = CreateTrigger()
private unit ItemPicker
private integer Num_PickItems = 0
private item item_Picking = null
private group group_item_pickers = CreateGroup()
private integer Top_item_pickers = -1
private unit array hero_item_picker
private integer array  item_picker_times
private destructable tree = null
private real destructableX = 0.0
private real destructableY = 0.0
private real destCenterX = 0.0 
private real destCenterY = 0.0
private real destructableRadius = 0.0
private boolexpr filterEnumDestructablesInCircle
private unit harvest_unit
private integer array Top_Units 
private integer max_array_units = 250
private group group_transportation = CreateGroup()
private unit array ai_units
private boolean AttackTree = false
private trigger AnyUnitSold = CreateTrigger()
private real array unit_LastX
private real array unit_LastY 
private integer array int_unit_blocked 
private trigger AnyUnitOrderPoint = CreateTrigger()
private trigger MeleeHeroGetItem = CreateTrigger()
endglobals
//
private function GetAiUnitsID takes unit u returns integer
local integer playerid = GetPlayerId(GetOwningPlayer(u))
local integer i = Top_Units[playerid]
local integer ID = -1
loop
exitwhen i < 0 or ID > -1
if u == ai_units[playerid * max_array_units + i] then
set ID = i
endif
set i = i - 1
endloop
return ID
endfunction
//

private function GainTree takes nothing returns nothing
set tree = GetEnumDestructable()
endfunction
private function EnumDestructablesInCircleFilter takes nothing returns boolean
local destructable d = GetFilterDestructable()
local real x = GetDestructableX(d)
local real y = GetDestructableY(d)
local boolean result = false
set result = DistanceBetweenXY(x,destCenterX,y,destCenterY) <= destructableRadius
set d = null
return result
endfunction
private function EnumDestructablesXY takes real radius,real x,real y,boolean range,code actionFunc returns nothing
local rect r = null
if radius >= 0 then
set destCenterX = x
set destCenterY = y
set destructableRadius = radius
set r = Rect(destCenterX-radius,destCenterY-radius,destCenterX+radius,destCenterY+radius)
if range == true then
call EnumDestructablesInRect(r, filterEnumDestructablesInCircle, actionFunc)
else
call EnumDestructablesInRect(r, null, actionFunc)
endif
call RemoveRect(r)
endif
set r = null
endfunction
private function IsDestructablesTree takes destructable tree returns boolean
if IssueTargetOrder( harvest_unit, "harvest", tree ) then
call IssueImmediateOrder( harvest_unit, "stop" )
return true
endif
return false
endfunction
//判断单位是否正在施法
function IsUnitSpelling takes unit u returns boolean
if IsUnitInGroup(u,group_speller)==true then
return true
endif
return false
endfunction
//判断单位是运输工具(AI)
function IsUnitTransportation takes unit u returns boolean
if IsUnitInGroup(u,group_transportation)==true then
return true
endif
return false
endfunction
//
private function GetPlayerGold takes player p returns integer
return GetPlayerState(p,PLAYER_STATE_RESOURCE_GOLD)
endfunction
private function GetPlayerWood takes player p returns integer
return GetPlayerState(p,PLAYER_STATE_RESOURCE_LUMBER)
endfunction
private function GetPlayerFoodUsed takes player p returns integer
return GetPlayerState(p,PLAYER_STATE_RESOURCE_FOOD_USED)
endfunction
private function AdjustPlayerGold takes integer delta, player whichPlayer returns nothing
local integer i = GetPlayerGold(whichPlayer)+delta
if i < 0 then
set i = 0
endif
call SetPlayerState(whichPlayer,PLAYER_STATE_RESOURCE_GOLD,i)
endfunction
private function AdjustPlayerWood takes integer delta, player whichPlayer returns nothing
local integer i = GetPlayerWood(whichPlayer)+delta
if i < 0 then
set i = 0
endif
call SetPlayerState(whichPlayer,PLAYER_STATE_RESOURCE_LUMBER,i)
endfunction
private function PlayerDivertsResources takes player p1,player p2,integer gold,integer wood returns nothing
local integer i = GetPlayerGold(p1)
if gold > i then
set gold = i
endif
call AdjustPlayerGold( -gold, p1 )
call AdjustPlayerGold( gold, p2 )
set i = GetPlayerWood(p1)
if wood > i then
set wood = i
endif
call AdjustPlayerWood( -wood, p1 )
call AdjustPlayerWood( wood, p2 )
endfunction
private function GetItemNumOfItemType takes unit whichUnit, integer itemId returns integer
local integer index
local item indexItem = null
local integer n = 0
set index = 0
loop
set indexItem = UnitItemInSlot(whichUnit, index)
if indexItem != null and GetItemTypeId(indexItem) == itemId then
set n = n + 1
endif
set index = index + 1
exitwhen index >= bj_MAX_INVENTORY
endloop
set indexItem = null
return n
endfunction
private function GetInventoryIndexOfItemType takes unit whichUnit, integer itemId returns integer
local integer index
local item indexItem = null
set index = 0
loop
set indexItem = UnitItemInSlot(whichUnit, index)
if indexItem != null and GetItemTypeId(indexItem) == itemId then
set indexItem = null
return index 
endif
set index = index + 1
exitwhen index >= bj_MAX_INVENTORY
endloop
set indexItem = null
return -1
endfunction
private function GetItemOfTypeFromUnit takes unit whichUnit, integer itemId returns item
local integer index = GetInventoryIndexOfItemType(whichUnit, itemId)
if index == -1 then
return null
else
return UnitItemInSlot(whichUnit, index)
endif
endfunction
private function UnitUseItemAtLoc takes unit whichUnit, item whichItem, location loc returns boolean
return UnitUseItemPoint(whichUnit, whichItem, GetLocationX(loc), GetLocationY(loc))
endfunction
function HeroInventoryCount takes unit whichUnit returns integer
local integer index = 0
local integer count = 0
loop
if UnitItemInSlot(whichUnit, index) != null then
set count = count + 1
endif
set index = index + 1
exitwhen index >= bj_MAX_INVENTORY
endloop
return count
endfunction
function IsUnitBackpackFull takes unit u returns boolean
if HeroInventoryCount(u) >= UnitInventorySize(u) then
return true
endif
return false
endfunction
//
private function GetHeroStatePercent takes unit whichUnit, unitstate whichState returns real
local real value = GetUnitState(whichUnit,whichState)
local real maxValue = 0.0
if whichState == UNIT_STATE_MANA then
set maxValue = GetUnitState(whichUnit,UNIT_STATE_MAX_MANA)
else
set maxValue = GetUnitState(whichUnit,UNIT_STATE_MAX_LIFE)
endif
if whichUnit == null or maxValue == 0.0 then
return 0.0
endif
return value/maxValue*1.0
endfunction
//

private function TestUnitEffect takes unit u returns nothing
call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Other\\Monsoon\\MonsoonBoltTarget.mdl",u,"overhead"))
endfunction
//
private function ItemPickingIntermission takes nothing returns nothing
local integer n = 0
if AttackTree == false then
set AttackTree = true
else
set AttackTree = false
endif
loop
exitwhen n > Top_item_pickers
call GroupRemoveUnit(group_item_pickers,hero_item_picker[n])
set n = n + 1
endloop
set Top_item_pickers = -1
endfunction
private function PickItem takes nothing returns nothing
set item_Picking = GetEnumItem()
set Num_PickItems = Num_PickItems + 1
endfunction
private function HeroPickItem takes unit hero,real x,real y returns nothing
local rect ItemRect
local integer n = 0
set Num_PickItems = 0
set ItemRect = Rect(x-800.,y-800.,x+800.,y+800.)
set ItemPicker = hero
call EnumItemsInRect(ItemRect,null,function PickItem)
if Num_PickItems > 0 then
if IsUnitInGroup(hero,group_item_pickers) == false then
call GroupAddUnit(group_item_pickers,hero)
set Top_item_pickers = Top_item_pickers + 1
set hero_item_picker[Top_item_pickers] = hero
set item_picker_times[Top_item_pickers] = 0
call IssueTargetOrder(ItemPicker,"smart",item_Picking)
else
loop
exitwhen n > Top_item_pickers
if hero == hero_item_picker[n] then
set item_picker_times[n] = item_picker_times[n] + 1
if item_picker_times[n] < 6 then
call IssueTargetOrder(ItemPicker,"smart",item_Picking)
endif
endif
set n = n + 1
endloop
endif
if GetWidgetLife(item_Picking) < 0.1 then
call SetWidgetLife( item_Picking, 50. )
call RemoveItem(item_Picking)
endif
endif
call RemoveRect(ItemRect)
set ItemRect = null
endfunction
private function HeroBuyItem takes unit hero,integer playerid,unit shop,integer typeitem returns nothing
if IsUnitBackpackFull(hero) == false then
call IssueNeutralTargetOrder( Player(playerid), shop, "neutralinteract", hero )
call IssueNeutralImmediateOrderById( Player(playerid), shop, typeitem )
endif
endfunction
//Meele AI系统
globals
private integer Un_hto1
private integer Un_hto2
private integer Un_hto3
private integer Un_oto1
private integer Un_oto2
private integer Un_oto3
private integer Un_uto1
private integer Un_uto2
private integer Un_uto3
private integer Un_eto1
private integer Un_eto2
private integer Un_eto3
endglobals
globals

private location array loc_startLoc
private integer id_timer_player = 0
private integer Top_units_NoAI = -1
private unit array units_NoAI
private real array time_unit_guardPos
private integer array id_unit_guardPos
private trigger MeleeHero_Attacked_Trg = CreateTrigger()
private location array loc_rallyLoc
private integer int_buyitemHome = 0
private boolean array Melee_AI_On
private unit array hero_av_abi
private integer Top_hero_av_abi = -1
private integer int_player_con = 0
private boolean array b_player_loser


private group group_peons = CreateGroup()

private boolean array b_unit_guardPos
private unit array melee_ai_shops
private unit array unit_transport
private integer array int_transport
private unit array unit_peon_buyer
private unit array natural_shop_AmmoDump
private integer natural_max_AmmoDump = 0
private unit array target_shop_AmmoDump
private integer array num_zeppelin
private integer array num_IronGolem
private integer UnitType_GetSoldUnit = 0
private unit array Unit_GetSoldShop
private unit array natural_shop_Merchant
private integer natural_max_Merchant = 0
private location array loc_hero_orderLoc
private timer array timer_transport
private boolean array b_transport_getTarget
private unit array test_block_buildings [12][10]
private integer array type_unit_siege
private integer array type_melee_tower
private unit array unit_peon_towerbuilder
private location array loc_enemy_targetLoc
private boolean array b_onlyoneEnemy
private group group_final_attack = CreateGroup()
private boolean array b_invisible_enemy
private boolean array b_melee_herobuy
endglobals
private function GroupClearTrg takes nothing returns nothing
call GroupClearDeadUnits(group_transportation)
call GroupClearDeadUnits(group_peons)
call GroupClear(group_final_attack)
endfunction

private function ClearTownHallNum takes nothing returns nothing
set Un_hto1 = 0
set Un_hto2 = 0
set Un_hto3 = 0
set Un_oto1 = 0
set Un_oto2 = 0
set Un_oto3 = 0
set Un_uto1 = 0
set Un_uto2 = 0
set Un_uto3 = 0
set Un_eto1 = 0
set Un_eto2 = 0
set Un_eto3 = 0
endfunction
private function SetTownHallTypeNum takes unit town, integer pid returns nothing
//hum
if GetPlayerRace(Player(pid)) == RACE_HUMAN then
if GetUnitTypeId(town) == Ut_hto1 then
set Un_hto1 = Un_hto1 + 1
elseif GetUnitTypeId(town) == Ut_hto2 then
set Un_hto2 = Un_hto2 + 1
elseif GetUnitTypeId(town) == Ut_hto3 then
set Un_hto3 = Un_hto3 + 1
endif
//orc
elseif GetPlayerRace(Player(pid)) == RACE_ORC then
if GetUnitTypeId(town) == Ut_oto1 then
set Un_oto1 = Un_oto1 + 1
elseif GetUnitTypeId(town) == Ut_oto2 then
set Un_oto2 = Un_oto2 + 1
elseif GetUnitTypeId(town) == Ut_oto3 then
set Un_oto3 = Un_oto3 + 1
endif
//undead
elseif GetPlayerRace(Player(pid)) == RACE_UNDEAD then
if GetUnitTypeId(town) == Ut_uto1 then
set Un_uto1 = Un_uto1 + 1
elseif GetUnitTypeId(town) == Ut_uto2 then
set Un_uto2 = Un_uto2 + 1
elseif GetUnitTypeId(town) == Ut_uto3 then
set Un_uto3 = Un_uto3 + 1
endif
//elf
elseif GetPlayerRace(Player(pid)) == RACE_NIGHTELF then
if GetUnitTypeId(town) == Ut_eto1 then
set Un_eto1 = Un_eto1 + 1
elseif GetUnitTypeId(town) == Ut_eto2 then
set Un_eto2 = Un_eto2 + 1
elseif GetUnitTypeId(town) == Ut_eto3 then
set Un_eto3 = Un_eto3 + 1
endif
endif
endfunction
private function UpgradeTown takes unit town,integer newtype ,integer pid,integer level returns nothing
local integer foodused = GetPlayerFoodUsed(Player(pid))
local boolean upg = false
if level == 1 then
if foodused >= FoodUsed_upg_town1 then
set upg = true
endif
elseif level == 2 then
if foodused >= FoodUsed_upg_town2 then
set upg = true
endif
endif
if upg == true then
call IssueImmediateOrderById( town, newtype )
endif
endfunction
private function UpgradeTownHall takes unit town, integer pid returns nothing
//hum
if GetPlayerRace(Player(pid)) == RACE_HUMAN then
if GetUnitTypeId(town) == Ut_hto1 then
if Un_hto2 + Un_hto3 < 1 then
call UpgradeTown( town, Ut_hto2, pid,1 )
endif
elseif GetUnitTypeId(town) == Ut_hto2 then
if Un_hto3 < 1 then
call UpgradeTown( town, Ut_hto3, pid,2 )
endif
elseif GetUnitTypeId(town) == Ut_hto3 then
endif
//orc
elseif GetPlayerRace(Player(pid)) == RACE_ORC then
if GetUnitTypeId(town) == Ut_oto1 then
if Un_oto2 + Un_oto3 < 1 then
call UpgradeTown( town, Ut_oto2, pid,1 )
endif
elseif GetUnitTypeId(town) == Ut_oto2 then
if Un_oto3 < 1 then
call UpgradeTown( town, Ut_oto3, pid,2 )
endif
elseif GetUnitTypeId(town) == Ut_oto3 then
endif
//undead
elseif GetPlayerRace(Player(pid)) == RACE_UNDEAD then
if GetUnitTypeId(town) == Ut_uto1 then
if Un_uto2 + Un_uto3 < 1 then
call UpgradeTown( town, Ut_uto2, pid,1 )
endif
elseif GetUnitTypeId(town) == Ut_uto2 then
if Un_uto3 < 1 then
call UpgradeTown( town, Ut_uto3, pid,2 )
endif
elseif GetUnitTypeId(town) == Ut_uto3 then
endif
//elf
elseif GetPlayerRace(Player(pid)) == RACE_NIGHTELF then
if GetUnitTypeId(town) == Ut_eto1 then
if Un_eto2 + Un_eto3 < 1 then
call UpgradeTown( town, Ut_eto2, pid,1 )
endif
elseif GetUnitTypeId(town) == Ut_eto2 then
if Un_eto3 < 1 then
call UpgradeTown( town, Ut_eto3, pid,2 )
endif
elseif GetUnitTypeId(town) == Ut_eto3 then
endif
endif
endfunction
private function MeleeHeroFindShop takes unit hero, integer pid, integer ui returns nothing
local integer n = 1
local real dismin = 20000.0
local real dis = 0.0
local unit shop = null
loop
exitwhen n > natural_max_Merchant
set dis = DistanceBetweenUnits(hero,natural_shop_Merchant[n])
if dis < dismin then
set dismin = dis
set shop = natural_shop_Merchant[n]
endif
set n = n + 1
endloop
if shop != null and dis < 3000. and b_melee_herobuy[pid] == true then
//call Unit_RemoveAI(hero,ui,5.0)
call IssueTargetOrder( hero, "smart", shop )
if IsUnitInRange(hero,shop,300.) == true then
set b_melee_herobuy[pid] = false
endif
endif
set shop = null
endfunction
private function MeleeHeroProtection takes unit hero returns nothing
local item Item 
local player p 
local integer id = 0
if GetUnitAbilityLevel(hero,Buff_sleep) > 0 then
return
endif
set p = GetOwningPlayer(hero)
set id = GetPlayerId(p)
set Item = GetItemOfTypeFromUnit(hero,Item_pnvl)
if GetItemCharges(Item) > 0 then
if IsUnitInvulnerable(hero) == false then
call UnitUseItem(hero,Item)
endif   
else
set Item = GetItemOfTypeFromUnit(hero,Item_stwp)
if GetItemCharges(Item) > 0 then
if IsUnitInvulnerable(hero) == false then
call UnitUseItemAtLoc(hero,Item,loc_startLoc[id])
endif
else
             
endif
endif
set Item = null
set p = null
endfunction
private function Melee_HeroGetItem takes nothing returns nothing
local integer Item = GetItemTypeId(GetManipulatedItem())
local integer n = GetItemNumOfItemType(GetTriggerUnit(),Item)
if Item == Item_clsd then
return
endif
if n == 1 then
call SetItemPawnable( GetManipulatedItem(), false )
elseif n > 1 then
call SetItemPawnable( GetManipulatedItem(), true )
endif
endfunction 
private function MeleeHeroAttacked takes nothing returns nothing
if GetHeroStatePercent(GetTriggerUnit(),UNIT_STATE_LIFE) <= 0.15 then 
call MeleeHeroProtection(GetTriggerUnit())
endif
endfunction  
private function AI_Hero_AvoidAbilityDam takes nothing returns nothing
local integer i = 1
call DestroyTimer(GetExpiredTimer())
call MeleeHeroProtection(hero_av_abi[0])
set hero_av_abi[0] = null
loop
exitwhen i > Top_hero_av_abi
set hero_av_abi[i-1] = hero_av_abi[i]
set i = i + 1
endloop
set hero_av_abi[Top_hero_av_abi] = null
set Top_hero_av_abi = Top_hero_av_abi - 1
endfunction
private function Transport_Timer takes nothing returns nothing
local integer index = 0
local location orderpoint = null
local unit transport = null
loop
exitwhen index > 11
if GetExpiredTimer() == timer_transport[index] then
set orderpoint = loc_hero_orderLoc[index]
set transport = unit_transport[index]
set b_transport_getTarget[index] = true
call IssuePointOrder(transport,"unloadall",GetLocationX(orderpoint),GetLocationY(orderpoint))
endif
set index = index + 1
endloop
set orderpoint = null
set transport = null
endfunction
private function Pop_NoAIUnits takes integer i returns nothing
if units_NoAI[i] != null then
call RecycleGuardPosition( units_NoAI[i] )
set b_unit_guardPos[id_unit_guardPos[i]] = true
endif
set units_NoAI[i] = units_NoAI[Top_units_NoAI]
set time_unit_guardPos[i] = time_unit_guardPos[Top_units_NoAI]
set id_unit_guardPos[i] = id_unit_guardPos[Top_units_NoAI]
set units_NoAI[Top_units_NoAI] = null
set Top_units_NoAI = Top_units_NoAI - 1
endfunction
private function NoAIUnits_Loop takes nothing returns nothing
local integer i = Top_units_NoAI
local real hptest = 0.0
//call BJDebugMsg(I2S(i))
loop
exitwhen i < 0
set hptest = 0.
set hptest = GetUnitState(units_NoAI[i], UNIT_STATE_LIFE)
if hptest < 0.40 or time_unit_guardPos[i] <= 0.0 then
call Pop_NoAIUnits(i)
else
set time_unit_guardPos[i] = time_unit_guardPos[i] - 0.5
endif
set i = i - 1
endloop
endfunction
private function Unit_RemoveAI takes unit u , integer unitid, real timemax returns nothing
local integer n = 0
if b_unit_guardPos[unitid] == true then
set b_unit_guardPos[unitid] = false
set Top_units_NoAI = Top_units_NoAI + 1
set units_NoAI[Top_units_NoAI] = u
set time_unit_guardPos[Top_units_NoAI] = timemax
set id_unit_guardPos[Top_units_NoAI] = unitid
call RemoveGuardPosition( u )
else
loop
exitwhen n > Top_units_NoAI
if u == units_NoAI[n] then
if timemax > time_unit_guardPos[n] then
set time_unit_guardPos[n] = timemax
endif
endif
set n = n + 1
endloop
endif
endfunction
private function Pop_ai_Units takes integer playerid,integer i returns nothing
local integer product = playerid * max_array_units
local integer unitid = product + i
local integer topid = product + Top_Units[playerid]
set ai_units[unitid] = ai_units[topid]
set unit_LastX[unitid] = unit_LastX[topid]
set unit_LastY[unitid] = unit_LastY[topid]
set int_unit_blocked[unitid] = int_unit_blocked[topid]
set ai_units[topid] = null
set Top_Units[playerid] = Top_Units[playerid] - 1
endfunction
private function PeonBuildTower takes integer playerid returns nothing
local unit builder = unit_peon_towerbuilder[playerid]
local location loc = GetUnitLoc(builder)
if IsUnitSpelling(builder) == false and DistanceBetweenPoint(loc,loc_startLoc[playerid]) > 1200. then
if GetPlayerGold(Player(playerid)) > 1500 and GetPlayerWood(Player(playerid)) > 500 then
if IsUnitType(builder, UNIT_TYPE_UNDEAD) == true then
if IsPointBlighted(GetLocationX(loc), GetLocationY(loc)) == true then
call BuildOrderByIdNearbyLoc( builder, type_melee_tower[playerid], loc )
else
call BuildOrderByIdNearbyLoc( builder, Ut_uto1, loc )
endif
else
call BuildOrderByIdNearbyLoc( builder, type_melee_tower[playerid], loc )
endif
if loc_enemy_targetLoc[playerid] != null and GetRandomInt(1,2) == 1 /*
*/ and DistanceBetweenPoint(loc,loc_enemy_targetLoc[playerid]) > 800. then
call IssuePointOrderLoc( builder, "move", loc_enemy_targetLoc[playerid] )
endif
endif
endif
call RemoveLocation(loc)
set loc = null
endfunction
private function PeonBuy takes integer playerid, boolean havepeon returns nothing
if havepeon == true then
if target_shop_AmmoDump[playerid] != null then
if IsUnitInRange(unit_peon_buyer[playerid],target_shop_AmmoDump[playerid],250.) then
if type_melee_tower[playerid] != 0 then
set unit_peon_towerbuilder[playerid] = unit_peon_buyer[playerid]
endif
set unit_peon_buyer[playerid] = null
endif
if num_zeppelin[playerid] < 2 then
call IssueNeutralImmediateOrderById(Player(playerid),target_shop_AmmoDump[playerid],UnitType_zeppelin)
endif
if num_IronGolem[playerid] < 1 then
call IssueNeutralImmediateOrderById(Player(playerid),target_shop_AmmoDump[playerid],UnitType_TronGloem)
endif
endif
if UnitType_GetSoldUnit != 0 and Unit_GetSoldShop[playerid] != null then
call IssueNeutralImmediateOrderById(Player(playerid),Unit_GetSoldShop[playerid],UnitType_GetSoldUnit)
if IsUnitInRange(unit_peon_buyer[playerid],Unit_GetSoldShop[playerid],250.) then
if type_melee_tower[playerid] != 0 then
set unit_peon_towerbuilder[playerid] = unit_peon_buyer[playerid]
endif
set unit_peon_buyer[playerid] = null
endif
endif
endif
endfunction
private function MeleeHerosBuyItems takes unit hero,integer id,real x,real y returns nothing
local item Item = null
local group G = CreateGroup()
local unit u = null
local unit shop = null
local integer typeitem
call GroupEnumUnitsInRange(G,x,y,400.0,null)
loop
set u = FirstOfGroup(G)
if GetUnitState(u,UNIT_STATE_LIFE) > 0.41 then
if GetUnitAbilityLevel(u,'Apit') > 0 then
set shop = u
endif
endif
call GroupRemoveUnit(G,u)
exitwhen u == null
endloop
call DestroyGroup(G)
if shop != null then
set typeitem = Item_stwp
set Item = GetItemOfTypeFromUnit(hero,typeitem)
if GetItemCharges(Item) < 1 then
call HeroBuyItem(hero,id,shop,typeitem)
endif
set typeitem = Item_pnvl
set Item = GetItemOfTypeFromUnit(hero,typeitem)
if GetItemCharges(Item) < 1 then
call HeroBuyItem(hero,id,shop,typeitem)
endif
set typeitem = Item_ssan
if GetItemNumOfItemType(hero,typeitem) < 1 then
call HeroBuyItem(hero,id,shop,typeitem)
endif
set typeitem = Item_spre
if GetItemNumOfItemType(hero,typeitem) < 1 then
call HeroBuyItem(hero,id,shop,typeitem)
endif
if b_invisible_enemy[id] == true then
set typeitem = Item_dust
set Item = GetItemOfTypeFromUnit(hero,typeitem)
if GetItemCharges(Item) < 1 then
call HeroBuyItem(hero,id,shop,typeitem)
endif
endif
endif
set Item = null
set u = null
set G = null
set shop = null
endfunction
private function Melee_Heros_Loop takes unit hero,integer id,real x,real y,real dis,real en,real an,unit eu,unit au,real wehp,real ang,integer ui returns nothing
local real level = I2R(GetHeroLevel(hero))
local real treehp = 0.0
local group G = null
local unit u = null
//if en < 1. then
//call MeleeHeroFindShop(hero,id,ui)
//endif
call MeleeHerosBuyItems(hero,id,x,y)
if AttackTree == true then
set tree = null
call EnumDestructablesXY(GetRandomReal(256.,768.),x,y,false,function GainTree)
set treehp = GetDestructableLife(tree)
if treehp > 0. and IsDestructablesTree(tree) == false then
call Unit_RemoveAI(hero,ui,3.0)
set G = CreateGroup()
call GroupEnumUnitsInRange(G,x,y,400.0,null)
loop
set u = FirstOfGroup(G)
if GetUnitState(u,UNIT_STATE_LIFE) > 0.41 and GetOwningPlayer(u) == Player(id) then
if IsUnitSpelling(u) == false and IsUnitType(u, UNIT_TYPE_PEON) == false then
call IssueTargetOrder( u, "attack", tree )
endif
endif
call GroupRemoveUnit(G,u)
exitwhen u == null
endloop
call DestroyGroup(G)
endif
endif
if int_buyitemHome > 7 then
if dis < 500.0 and melee_ai_shops[id] != null then
call IssueTargetOrder( hero, "smart", melee_ai_shops[id] )
call Unit_RemoveAI(hero,ui,5.0)
endif
endif
if IsUnitSpelling(hero) == false then
if en > 1. and (en - an > 2. or an > 2.) then
call OrderUnitMoveXY(hero,x,y,600.0,ang+GetRandomReal(-0.15,0.15))
endif
if eu != null then
if wehp < 50. + 15. * level + an * 5. then
call IssueTargetOrder( hero, "smart", eu )
endif
endif
if au != null and en > 0. then
call IssueTargetOrder( hero, "attack", au )
endif
endif
if IsUnitBackpackFull(hero) == false then
call HeroPickItem(hero,x,y)
endif
set u = null
set G = null
endfunction
private function ai_Units_Loop takes nothing returns nothing
local integer i = Top_Units[id_timer_player]
local real x = 0.0
local real y = 0.0
local real x0 = 0.0
local real y0 = 0.0
local integer unitid = 0
local real unitHP = 0.0
local real unitHPmax = 0.0
local real unitHPpercent = 0.0
local unit u = null
local group G = null
local real hp = 0.0
local real hpmax = 0.0
local real hpPercent = 0.0    
local integer actindex = 0
local real hptest = 0.0
local unit AIunit = null
local real dis_fromhome = 0.0
local real hpmin = 2000.0
local unit weakEnemyUnit = null
local unit weakAllyUnit = null
local real power_enemy = 0.0
local real power_ally = 0.0
local boolean retreat = false
local real sum_x = 0.0
local real sum_y = 0.0
local real ang_enemy = -1.0
local boolean spelling = false
local real num_enemy = 0.0
local boolean avoid = false
local integer ramInt = 1
local boolean peon = false
local unit transport = null
local boolean canbuy = false
local unit array townhall
local integer num_townhall = 0
local integer n = 0
local boolean IsZeppelin = false
local boolean haveorder = false
local integer orderid = 0
local location orderpoint = null
local boolean hero = false
local real transport_dismin = 200.0
local real num_tower = 0.0
local unit tower_undead = null
local unit tower_human = null
local real dis_nearEnemyHome = 5000.0
local unit structrue = null
local integer e_pid = 0
local boolean have_invisible = false
local item Item = null
//call BJDebugMsg(I2S(i))
call ClearTownHallNum()
set actindex = id_timer_player * max_array_units
set G = CreateGroup()
loop
exitwhen i < 0
set unitid = actindex + i
set hptest = 0.
set hptest = GetUnitState(ai_units[unitid], UNIT_STATE_LIFE)
if hptest < 0.40 then
if IsUnitType(ai_units[unitid], UNIT_TYPE_HERO) == false then
call Pop_ai_Units(id_timer_player,i)
else
if IsUnitTransportation(ai_units[unitid]) == true then
set num_zeppelin[id_timer_player] = num_zeppelin[id_timer_player] - 1
elseif GetUnitTypeId(ai_units[unitid]) == UnitType_TronGloem then
set num_IronGolem[id_timer_player] = num_IronGolem[id_timer_player] - 1
endif
endif
else
set AIunit = ai_units[unitid]
if IsUnitType(AIunit, UNIT_TYPE_STRUCTURE) == false then
set x = GetUnitX(AIunit)
set y = GetUnitY(AIunit)
set x0 = GetLocationX(loc_startLoc[id_timer_player])
set y0 = GetLocationY(loc_startLoc[id_timer_player])
set unitHP = GetUnitState(AIunit,UNIT_STATE_LIFE)
set unitHPmax = GetUnitState(AIunit,UNIT_STATE_MAX_LIFE)+1.0
set unitHPpercent = unitHP/unitHPmax*1.0
set retreat = false
set sum_x = 0.0
set sum_y = 0.0
set power_enemy = 0.0
set power_ally = 0.0
set weakEnemyUnit = null
set weakAllyUnit = null
set u = null
set spelling = IsUnitSpelling(AIunit)
set num_enemy = 0.0
set dis_fromhome = 0.0
set avoid = false
set peon = IsUnitInGroup(AIunit, group_peons)
set transport = null
set IsZeppelin = IsUnitTransportation(AIunit)
set haveorder = true
set orderid = GetUnitCurrentOrder(AIunit)
set hero = IsUnitType(AIunit, UNIT_TYPE_HERO)
set num_tower = 0.0
set dis_nearEnemyHome = 5000.0
set structrue = null
set have_invisible = false
if orderid == 0 then
set haveorder = false
endif
if x - unit_LastX[unitid] > -150. and x - unit_LastX[unitid] < 150. /*
*/ and y - unit_LastY[unitid] > -150. and y - unit_LastY[unitid] < 150. then
if (IsZeppelin == true or orderid == 851986) and IsUnitLoaded(AIunit) == false then
set int_unit_blocked[unitid] = int_unit_blocked[unitid] + 1 
endif
else
set int_unit_blocked[unitid] = 0
endif

if int_unit_blocked[unitid] > 6 then
if IsZeppelin == true then
call IssuePointOrderLoc(AIunit,"unloadall",loc_startLoc[id_timer_player])
endif
if int_unit_blocked[unitid] == 10 and hero == true then
call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Human\\MassTeleport\\MassTeleportCaster.mdl",x,y))
call SetUnitX(AIunit,GetLocationX(loc_startLoc[id_timer_player]))
call SetUnitY(AIunit,GetLocationY(loc_startLoc[id_timer_player]))
call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Human\\MassTeleport\\MassTeleportTarget.mdl",AIunit,"origin"))
endif
endif
set unit_LastX[unitid] = x
set unit_LastY[unitid] = y

if b_onlyoneEnemy[id_timer_player] == true then
if spelling == false and peon == false and IsUnitInGroup(AIunit,group_final_attack) == false then
call Unit_RemoveAI(AIunit,unitid,30.0)
call IssuePointOrderLoc( AIunit, "attack", loc_enemy_targetLoc[id_timer_player] )
call GroupAddUnit(group_final_attack,AIunit)
endif
endif

call GroupEnumUnitsInRange(G,x,y,600.0,null)
loop
set u=FirstOfGroup(G)
set hp = 0.0
set hp = GetUnitState(u,UNIT_STATE_LIFE)
if hp > 0.41 then
set hpmax = GetUnitState(u,UNIT_STATE_MAX_LIFE)
set hpPercent = hp/hpmax*1.0
if IsUnitEnemy(u,Player(id_timer_player)) == true then
if IsUnitType(u, UNIT_TYPE_PEON) == false then
set power_enemy = power_enemy + 1.0
set sum_x = sum_x + GetUnitX(u)
set sum_y = sum_y + GetUnitY(u)
if IsUnitInvisible(u, Player(id_timer_player)) == true then
set have_invisible = true
set b_invisible_enemy[id_timer_player] = true
endif
if IsUnitType(u, UNIT_TYPE_STRUCTURE) == true then
set structrue = u
if IsUnitType(u, UNIT_TYPE_RANGED_ATTACKER) == true then
set num_tower = num_tower + 1.0
endif
endif
endif
if hp < hpmin and hpPercent < unitHPpercent + 0.1 /*
*/ and IsUnitIllusion(u) == false and GetUnitAbilityLevel(u,Buff_sleep) < 1 then
set hpmin = hp
set weakEnemyUnit = u
endif
else
if IsUnitType(u, UNIT_TYPE_PEON) == false and IsUnitType(u, UNIT_TYPE_STRUCTURE) == false then
set power_ally = power_ally + 1.0
endif
if hpPercent < 0.2 and hp < 50. and GetOwningPlayer(u) == Player(id_timer_player) then
set weakAllyUnit = u
endif
endif                
endif
call GroupRemoveUnit(G,u)
exitwhen u == null
endloop
call GroupClear(G)
set power_enemy = power_enemy + num_tower
set num_enemy = power_enemy

if hero == true then
set unitHPpercent = unitHPpercent * 0.85
if have_invisible == true then
set Item = GetItemOfTypeFromUnit(AIunit,Item_dust)
if GetItemCharges(Item) > 0 then
call UnitUseItem( AIunit, Item )
endif
endif
endif

if peon == true then
set unitHPpercent = unitHPpercent * 0.7
if GetUnitTypeId(AIunit) == UnitType_TronGloem then
set dis_fromhome = DistanceBetweenXY(x,x0,y,y0)
if dis_fromhome < 1800. then
if GetRandomInt(1,10) == 1 then
call IssueImmediateOrderById( AIunit, 852022 )
endif
endif
endif
if haveorder == false or orderid == 852020 then
if GetUnitState(unit_peon_buyer[id_timer_player],UNIT_STATE_LIFE) < 0.4 /*
*/ and GetUnitTypeId(AIunit) != UnitType_TronGloem then
set unit_peon_buyer[id_timer_player] = AIunit
else
endif
else

endif
endif
if IsZeppelin == true then
if GetUnitState(unit_transport[id_timer_player],UNIT_STATE_LIFE) < 0.4 then
set unit_transport[id_timer_player] = AIunit
else
if unitHPpercent < 0.35 then
set transport_dismin = 999999.
endif
endif
else
if unit_transport[id_timer_player] != null then
set transport = unit_transport[id_timer_player]
if int_transport[id_timer_player] > 0 then
if IsUnitLoaded(AIunit) == false and num_enemy == 0. /*
*/ and spelling == false and peon == false then

if loc_hero_orderLoc[id_timer_player] != null then
set orderpoint = loc_hero_orderLoc[id_timer_player]
if DistanceBetweenXY(x,GetLocationX(orderpoint),y,GetLocationY(orderpoint)) > 1800. /*
*/ and IsUnitInRange(AIunit,transport,1200.) == true then
call RemoveGuardPosition( transport )
call Unit_RemoveAI(AIunit,unitid,3.0)
call IssueTargetOrder( AIunit, "smart", transport )
call TimerStart(timer_transport[id_timer_player],1.0,false,function Transport_Timer)
endif
endif
endif
endif
endif
endif


if power_enemy > power_ally then
set power_enemy = power_enemy * 2.0 - power_ally
endif


if unitHPpercent < 0.25+power_enemy*0.03 then
if num_enemy > 0.0 then
set sum_x = sum_x / num_enemy
set sum_y = sum_y / num_enemy
set ang_enemy = RadianBetweenXY(sum_x,x,sum_y,y)
if dis_nearEnemyHome > 1800. then
call OrderUnitMoveXY(AIunit,x,y,600.0+50.0/unitHPpercent,ang_enemy)
else
call IssuePointOrderLoc( AIunit, "move", loc_startLoc[id_timer_player] )
endif
if GetRandomInt(1,2) == 1 then
set avoid = true
endif
endif
if structrue != null then
set e_pid = GetPlayerId(GetOwningPlayer(structrue))
set dis_nearEnemyHome = DistanceBetweenXY(x,GetLocationX(loc_startLoc[e_pid]),y,GetLocationY(loc_startLoc[e_pid]))
endif
if unitHP < 100.+power_enemy*(10.+power_enemy*2.) and unitHPpercent < 0.25+power_enemy*0.01 or num_tower > 5. then
set retreat = true
endif
endif

if peon == false and IsZeppelin == false /*
*/ and b_unit_guardPos[unitid] == true /*
*/ and spelling == false and retreat == false then
if weakEnemyUnit != null and avoid == false then
call IssueTargetOrder( AIunit, "smart", weakEnemyUnit )
endif
if weakAllyUnit != null and num_enemy > 0.0 then
call IssueTargetOrder( AIunit, "attack", weakAllyUnit )
endif
endif

if hero == true then
set dis_fromhome = DistanceBetweenXY(x,x0,y,y0)
call Melee_Heros_Loop(AIunit,id_timer_player,x,y,dis_fromhome,num_enemy,power_ally,weakEnemyUnit,weakAllyUnit,hp,ang_enemy,unitid)
endif



if retreat == true then
if dis_fromhome == 0.0 then
set dis_fromhome = DistanceBetweenXY(x,x0,y,y0)
endif
call Unit_RemoveAI(AIunit,unitid,1.0/unitHPpercent+num_tower)
if dis_fromhome > 400.0 then
if power_enemy > 2.0 and dis_nearEnemyHome > 1800. then
call OrderUnitMoveXY(AIunit,x,y,1800.0,ang_enemy)
else
call IssuePointOrderLoc( AIunit, "move", loc_startLoc[id_timer_player] )
endif
endif
endif
           
else
if IsUnitType(AIunit,UNIT_TYPE_TOWNHALL) == false then
call IssuePointOrderLoc(AIunit, "setrally", loc_rallyLoc[id_timer_player] )
if GetUnitTypeId(AIunit) == Ut_utw1 then
set tower_undead = AIunit
elseif GetUnitTypeId(AIunit) == Ut_htw1 then
set tower_human = AIunit
endif
else
set num_townhall = num_townhall + 1
set townhall[num_townhall] = AIunit
call SetTownHallTypeNum(AIunit,id_timer_player)
endif 
endif
endif
set i = i - 1
endloop
call DestroyGroup(G)
if orderpoint != null and transport != null then
if DistanceBetweenXY(GetUnitX(transport),GetLocationX(orderpoint),GetUnitY(transport),GetLocationY(orderpoint)) < transport_dismin then
call RecycleGuardPosition(transport)
set b_transport_getTarget[id_timer_player] = false
call IssuePointOrderLoc( transport, "move", loc_startLoc[id_timer_player] )
call IssuePointOrder(transport,"unloadall",GetUnitX(transport),GetUnitY(transport))
endif
endif
set n = 1
loop
exitwhen n > num_townhall
call UpgradeTownHall(townhall[n],id_timer_player)
set n = n + 1
endloop
if GetUnitState(unit_peon_buyer[id_timer_player],UNIT_STATE_LIFE) > 0.41 then
set canbuy = true
endif
if tower_undead != null then
if GetPlayerGold(Player(id_timer_player)) > 600 and GetPlayerWood(Player(id_timer_player)) > 200 then
if GetRandomInt(1,4) == 1 then
call IssueImmediateOrderById( tower_undead, Ut_utw3 )
else
call IssueImmediateOrderById( tower_undead, Ut_utw2 )
endif
endif
endif
if tower_human != null then
if GetPlayerGold(Player(id_timer_player)) > 600 and GetPlayerWood(Player(id_timer_player)) > 200 then
if GetRandomInt(1,2) == 1 then
call IssueImmediateOrderById( tower_undead, Ut_htw2 )
endif
endif
endif
call PeonBuy(id_timer_player,canbuy)
if unit_peon_towerbuilder[id_timer_player] != null then
call PeonBuildTower(id_timer_player)
endif
if int_transport[id_timer_player] > 35 then
set int_transport[id_timer_player] = 0
else
set int_transport[id_timer_player] = int_transport[id_timer_player] + 1
endif
set id_timer_player = id_timer_player+1
if id_timer_player > 11 then
set id_timer_player = 0
set int_buyitemHome = int_buyitemHome + 1
endif
if int_buyitemHome > 10 then
set int_buyitemHome = 0
endif
set u = null
set AIunit = null
set weakEnemyUnit = null
set weakAllyUnit = null
set transport = null
set G = null
set orderpoint = null
set tower_undead = null
set tower_human = null
set structrue = null
set Item = null
endfunction
private function IsEnemyAroundUnit takes unit target, integer playerid returns boolean
local unit u = null
local group g = CreateGroup()
local boolean b = false
call GroupEnumUnitsInRange(g, GetUnitX(target), GetUnitY(target) ,500.0, null)
loop
set u = FirstOfGroup(g)
exitwhen u == null
if IsUnitEnemy(u,Player(playerid)) == true and GetUnitState(u,UNIT_STATE_LIFE) > 0. /*
*/ and IsUnitHidden(u) == false then
set b = true
endif
call GroupRemoveUnit(g,u)
endloop
call DestroyGroup(g)
set u = null
set g = null
return b
endfunction
private function PeonFindShop takes integer playerid, integer enemyid returns nothing
local integer n = 1
local real dismin = 20000.0
local real dis = 0.0
local unit buyer = null
local unit shop = null
local group g = null
local unit u = null
if unit_peon_buyer[playerid] != null then
set buyer = unit_peon_buyer[playerid]
set n = 1
loop
exitwhen n > natural_max_AmmoDump
set dis = DistanceBetweenUnits(buyer,natural_shop_AmmoDump[n])
if dis < dismin and IsEnemyAroundUnit(natural_shop_AmmoDump[n],playerid) == false then
set dismin = dis
set shop = natural_shop_AmmoDump[n]
endif
set n = n + 1
endloop
if shop != null then
set target_shop_AmmoDump[playerid] = shop
call IssueTargetOrder( buyer, "smart", shop )
endif
if Unit_GetSoldShop[playerid] != null then
if GetRandomInt(1,1) == 1 or shop == null then
set dismin = 20000.0
set dis = 0.0
set g = CreateGroup()
call GroupEnumUnitsOfPlayer(g,Player(15),null)
loop
set u = FirstOfGroup(g)
exitwhen u == null 
if GetUnitTypeId(u) == GetUnitTypeId(Unit_GetSoldShop[playerid]) then
set dis = DistanceBetweenUnits(buyer,u)
if dis < dismin and IsEnemyAroundUnit(u,playerid) == false then
set dismin = dis
set Unit_GetSoldShop[playerid] = u
endif
endif
call GroupRemoveUnit(g,u)
endloop
call DestroyGroup(g)
call IssueTargetOrder( buyer, "smart", Unit_GetSoldShop[playerid] )
endif
else
if shop == null and type_melee_tower[playerid] != 0 /*
*/ and GetPlayerGold(Player(playerid)) > 1500 and GetPlayerWood(Player(playerid)) > 500 then
set unit_peon_towerbuilder[playerid] = unit_peon_buyer[playerid]
set buyer = unit_peon_towerbuilder[playerid]
if GetRandomInt(1,2) == 1 or enemyid == 0 then
call IssuePointOrder(buyer,"move",GetRandomReal(-2500.,2500.),GetRandomReal(-2500.,2500.))
else
call IssuePointOrderLoc(buyer,"move",loc_startLoc[enemyid])
endif
endif
endif
endif
set buyer = null
set shop = null
set g = null
set u = null
endfunction
private function PlayerFindEnemyStructrue takes integer pid, integer targetid returns nothing
local group g = null
local unit u = null
local integer num_enemy_structure = 0
set g = CreateGroup()
call GroupEnumUnitsInRange(g,800.,GetLocationX(loc_startLoc[targetid]),GetLocationY(loc_startLoc[targetid]),null)
loop
set u = FirstOfGroup(g)
exitwhen u == null 
if IsUnitType(u, UNIT_TYPE_STRUCTURE) == true and IsUnitEnemy(u,Player(pid)) == true then
set num_enemy_structure = num_enemy_structure + 1
endif
call GroupRemoveUnit(g,u)
endloop
call DestroyGroup(g)
if num_enemy_structure < 1 then
set g = CreateGroup()
call GroupEnumUnitsOfPlayer(g,Player(targetid),null)
loop
set u = FirstOfGroup(g)
exitwhen u == null 
if IsUnitType(u, UNIT_TYPE_STRUCTURE) == true then
set loc_enemy_targetLoc[pid] = GetUnitLoc(u)
set loc_startLoc[targetid] = GetUnitLoc(u)
endif
call GroupRemoveUnit(g,u)
endloop
call DestroyGroup(g)
endif
set u = null
set g = null
endfunction
private function PlayerConsciousness takes nothing returns nothing
local integer  index = 0
local group g = null
local unit u = null
local boolean HaveStrongEnemy = false
local player player_ally = null
local player p = Player(int_player_con)
local integer  n = 0
local integer  enemy = 0
local integer array enemyplayerid
local integer targetid = 0
local integer  ally = 0
if Melee_AI_On[int_player_con] == true and b_player_loser[int_player_con] == false then
set b_melee_herobuy[int_player_con] = true
loop
exitwhen index > 11
if GetPlayerSlotState(Player(index)) == PLAYER_SLOT_STATE_PLAYING then
if IsPlayerEnemy(p,Player(index)) == true then 
if GetPlayerStructureCount(Player(index), true) > 0 then
set enemy = enemy + 1
set enemyplayerid[enemy] = index
if GetPlayerGold(Player(index)) > 800 and GetPlayerFoodUsed(Player(index)) > 50 then
set HaveStrongEnemy = true
endif
endif
else
if p != Player(index) and b_player_loser[index] == false then
set player_ally = Player(index)
if GetPlayerStructureCount(Player(index), true) > 0 and GetPlayerFoodUsed(Player(index)) > 50 then
set ally = ally + 1
endif
endif
endif
endif
set index = index + 1
endloop
if enemy > 0 then
set targetid = enemyplayerid[GetRandomInt(1,enemy)]
set loc_enemy_targetLoc[int_player_con] = loc_startLoc[targetid]
if enemy == 1 and ally > 0 then
if GetPlayerFoodUsed(p) > 70 - (ally * 3) then
set b_onlyoneEnemy[int_player_con] = true
call PlayerFindEnemyStructrue(int_player_con,targetid)
elseif GetPlayerFoodUsed(p) < 30 then
set b_onlyoneEnemy[int_player_con] = false
endif
endif
endif
if GetPlayerGold(p) > 500 and GetPlayerWood(p) > 150 and GetPlayerFoodUsed(p) > 30 then
call PeonFindShop(int_player_con,targetid)
endif
if HaveStrongEnemy == true /*
*/ and (GetPlayerGold(p) < 500 and GetPlayerFoodUsed(p) < 10) or GetPlayerFoodUsed(p) < 2 then
set g = CreateGroup()
call GroupEnumUnitsOfPlayer(g,p,null)
loop
set u = FirstOfGroup(g)
exitwhen u == null 
call KillUnit(u)
call GroupRemoveUnit(g,u)
endloop
call DestroyGroup(g)
set n = 0
loop
exitwhen n > 7
call KillUnit(test_block_buildings[int_player_con][n])
set n = n + 1
endloop
set b_player_loser[int_player_con] = true
if player_ally != null then
call PlayerDivertsResources(p,player_ally,GetPlayerGold(p),GetPlayerWood(p)) 
endif
endif
endif
set int_player_con = int_player_con + 1
if int_player_con > 11 then
set int_player_con = 0
endif
set u = null
set g = null
endfunction
private function MeleeAiSettings takes nothing returns nothing
local integer i = 0
local real ang = 0.0
local real x = 0.0
local real y = 0.0
local group g = null
local unit u = null
local unit goldmine = null
local unit townhall = null
local unit testunit = null
local real n = 0.0
call DestroyTimer(GetExpiredTimer())
loop
exitwhen i > 11
if loc_startLoc[i] != null and Melee_AI_On[i] == true then
set x = GetLocationX(loc_startLoc[i])
set y = GetLocationY(loc_startLoc[i])
set y = 0.0
set g = CreateGroup()
call GroupEnumUnitsInRangeOfLoc(g, loc_startLoc[i], 1200.0, null)
loop
set u = FirstOfGroup(g)
if GetUnitAbilityLevel(u, 'Agld') > 0 then
set goldmine = u
endif
if GetOwningPlayer(u) == Player(i) then    
if IsUnitType(u,UNIT_TYPE_STRUCTURE)==true and IsUnitType(u,UNIT_TYPE_TOWNHALL)==true then
set townhall = u
endif
endif
call GroupRemoveUnit(g,u)
exitwhen u == null
endloop
call GroupClear(g)
call DestroyGroup(g)
if townhall != null and goldmine != null then
set ang = RadianBetweenUnits(goldmine,townhall)
set x = GetUnitX(townhall)
set y = GetUnitY(townhall)
set n = 0.0
if UnitType_build_block != 0 then
loop
exitwhen n > 7.0
set testunit = CreateUnit(Player(13),UnitType_build_block,x+500.*Cos(n*0.785),y+500.*Sin(n*0.785),0.)
call SetUnitX(testunit,map_max_X)
call SetUnitY(testunit,map_max_Y)
call PauseUnit(testunit,true)
call SetUnitInvulnerable( testunit, true )
call CancelUnitMoveAndAttack(testunit)
set test_block_buildings[i][R2I(n)] = testunit
set n = n + 1.0
endloop
endif
set x = x + 200. * Cos(ang)
set y = y + 200. * Sin(ang)
endif
set loc_rallyLoc[i] = Location(x,y)
endif    
set i = i + 1
endloop    
set g = CreateGroup()
call GroupEnumUnitsOfPlayer(g,Player(15),null)
loop
set u = FirstOfGroup(g)
exitwhen u == null 
if GetUnitTypeId(u) == UnitType_AmmoDump then
set natural_max_AmmoDump = natural_max_AmmoDump + 1
set natural_shop_AmmoDump[natural_max_AmmoDump] = u
endif
if GetUnitAbilityLevel(u,'Apit') > 0 then
set natural_max_Merchant = natural_max_Merchant + 1
set natural_shop_Merchant[natural_max_Merchant] = u
endif
call GroupRemoveUnit(g,u)
endloop
call DestroyGroup(g)    
set g = null
set u = null
set goldmine = null
set townhall = null
set testunit = null
endfunction

public function melee_ai_Init takes nothing returns nothing
local integer i = 0
loop
exitwhen i > 15
set b_player_loser[i] = false
set unit_transport[i] = null
set int_transport[i] = 0
set unit_peon_buyer[i] = null
set target_shop_AmmoDump[i] = null
set num_zeppelin[i] = 0
set num_IronGolem[i] = 0
set Unit_GetSoldShop[i] = null
set loc_hero_orderLoc[i] = null
set timer_transport[i] = null
set b_transport_getTarget[i] = false
set type_unit_siege[i] = 0
set type_melee_tower[i] = 0
set unit_peon_towerbuilder[i] = null
set loc_enemy_targetLoc[i] = null
set b_onlyoneEnemy[i] = false
set b_invisible_enemy[i] = false
set b_melee_herobuy[i] = false
set Top_Units[i] = -1
if GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING then
set loc_startLoc[i] = GetStartLocationLoc(GetPlayerStartLocation(Player(i)))
if Melee_AI_On[i] == true then
set timer_transport[i] = CreateTimer()
call SetPlayerName( Player(i), ( "[EggStrAI]" + GetPlayerName(Player(i)) ) )
endif
endif
set i = i + 1
endloop
call TriggerAddAction(MeleeHero_Attacked_Trg,function MeleeHeroAttacked)
call TimerStart(CreateTimer(),1.73/12.0,true,function ai_Units_Loop)
call TimerStart(CreateTimer(),0.5,true,function NoAIUnits_Loop)
call TimerStart(CreateTimer(),1.0,false,function MeleeAiSettings)
call TimerStart(CreateTimer(),23.3/12.0,true,function PlayerConsciousness)
endfunction
public function SetAIplayer takes player p, boolean b returns nothing
if GetPlayerSlotState(p) == PLAYER_SLOT_STATE_PLAYING and GetPlayerController(p) == MAP_CONTROL_COMPUTER then
set Melee_AI_On[GetPlayerId(p)] = b
endif
endfunction
//RPG AI系统
globals
private unit array ai_hero
private integer Top_ai_hero = -1
private player CreepPlayer = Player(PLAYER_NEUTRAL_AGGRESSIVE)
private group group_creepcamp = CreateGroup()
private group array groups_camg
private location array loc_min_camg
private group group_AI_hero = CreateGroup()
private integer Top_creepcamp = -1
private boolean array b_ai_MF
private location array loc_ai_retreat
private boolean array b_ai_retreat
private real array hp_ai_retreat
private boolean array b_ai_pickItem
private group array group_AI_herounits 
private location ai_attacktargetloc
private integer ai_attacktargetgroup
private boolean array b_creeps_canattack
private boolean array b_ai_havetarget
private integer array creeps_level
private integer array mf_max_level
private boolean array b_can_atk_camg[11][500]
private trigger hero_attacked_trigger = CreateTrigger()
private boolean array hero_evade_boolean
private timer array hero_evade_timer
private boolean array b_attack_ally
private boolean array b_attack_weakunit
private group group_evade = CreateGroup()
private unit array hero_testunit_attack
private location array ai_hero_targetloc
private boolean array b_ai_attacktarget
private integer open_ai = 0
private real HPmin_hero_attack
private real MANAmin_hero_attack
endglobals
//
function GetEnemyArmyAngle takes unit u0,integer min returns real
local unit u
local real i = 0.0
local real a = 0.0
local real angle = 0.0
local integer n = 0
local integer max = 0
local group g = CreateGroup() 
local player p = GetOwningPlayer(u0)
local real x = GetUnitX(u0)
local real y = GetUnitY(u0)
loop
exitwhen i > 7.0
set a = 45.0*i
call GroupEnumUnitsInRange(g,x+450.0*Cos(a*bj_DEGTORAD),y+450.0*Sin(a*bj_DEGTORAD),300.00,null)
set n = 0
loop
set u = FirstOfGroup(g)
if u!=null and IsUnitType(u,UNIT_TYPE_DEAD)==false and IsUnitEnemy(u,p)==true then
set n = n + 1
endif
call GroupRemoveUnit(g,u)
exitwhen u == null
endloop
if max < n then
set max = n
set angle = a
endif   
set i = i + 1.0
call GroupClear(g)
endloop
call DestroyGroup(g)
set g = null
set u = null
set p = null
if max == 0 or max <= min then
set angle = -1.0
endif
return angle
endfunction
//
private function GetAiHeroID takes unit hero returns integer
local integer i = Top_ai_hero
local integer ID = -1
loop
exitwhen i < 0 or ID > -1
if hero==ai_hero[i] then
set ID = i
endif
set i = i - 1
endloop
return ID
endfunction

private function HeroUnitsGroup takes nothing returns nothing
call IssuePointOrderLoc(GetEnumUnit(), "attack", ai_attacktargetloc )
endfunction
private function CanAttackCreeps takes unit hero, integer id, integer cn returns boolean
local boolean b = false
local unit u = FirstOfGroup(groups_camg[cn])
local player p = GetOwningPlayer(hero)
local integer i = GetPlayerId(p)
call SetUnitOwner( hero_testunit_attack[id], p, true )
if u != null then
if IsUnitVisible(u, p) == true then
if IssueTargetOrder(hero_testunit_attack[id], "smart", u ) then
set b_can_atk_camg[i][cn] = true
call IssueImmediateOrder(hero_testunit_attack[id], "stop")
else
set b_can_atk_camg[i][cn] = false
endif
elseif IsUnitInRange(hero,u,800.) == true then
set b_can_atk_camg[i][cn] = false
endif
else
set b_can_atk_camg[i][cn] = false
endif
call SetUnitOwner( hero_testunit_attack[id], Player(15), true )
set u = null
set p = null
return b_can_atk_camg[i][cn] 
endfunction
private function CheckHeroAttackTarget takes integer i,real HPpercent returns nothing
if HPpercent > hp_ai_retreat[i] and ai_hero_targetloc[i] != null then
call GroupClearDeadUnits(group_AI_herounits[i])
set ai_attacktargetloc = ai_hero_targetloc[i]
call ForGroup( group_AI_herounits[i] , function HeroUnitsGroup )
set b_ai_havetarget[i] = true
endif
endfunction
private function CheckHeroMf takes integer i,real HPpercent returns nothing
local integer cn = 0
local real x0 = 0.0
local real y0 = 0.0
local real x1 = 0.0
local real y1 = 0.0
local real dis = 0.0
local real dismin = 0.0
local integer herolevel = 0
local location target = null
local unit u  = null
set x0 = GetUnitX(ai_hero[i])
set y0 = GetUnitY(ai_hero[i])
set cn = 0
set dismin = 80000.0
set herolevel = GetHeroLevel(ai_hero[i])
if HPpercent > hp_ai_retreat[i]*0.9 then
loop
exitwhen cn > Top_creepcamp
set x1 = GetLocationX(loc_min_camg[cn])
set y1 = GetLocationY(loc_min_camg[cn])
set dis = DistanceBetweenXY(x0,x1,y0,y1)
if groups_camg[cn] != null /* 
*/ and loc_min_camg[cn] != null /* 
*/ and creeps_level[cn] < herolevel + mf_max_level[i] /* 
*/ and CanAttackCreeps(ai_hero[i],i,cn) == true /* 
*/ and GroupCountUnitsRemoveDead(groups_camg[cn]) > 0 /* 
*/ and dis < dismin then
set dismin = dis
set target = loc_min_camg[cn]
endif
set cn = cn + 1
endloop
if target != null then
call GroupClearDeadUnits(group_AI_herounits[i])
set ai_attacktargetloc = target
set ai_attacktargetgroup = cn
call ForGroup( group_AI_herounits[i] , function HeroUnitsGroup )
set b_ai_havetarget[i] = true
endif
endif
set target = null
set u = null
endfunction
private function SetEvadeBoolean takes nothing returns nothing
local integer id = 0
local integer e = 0
loop
exitwhen id > Top_ai_hero or e == 1
if hero_evade_timer[id] == GetExpiredTimer() then
set hero_evade_boolean[id] = true
set e = 1
endif
set id = id + 1
endloop
endfunction
private function AiHeroAttacked takes nothing returns nothing
local unit hero = GetTriggerUnit()
local integer id = GetAiHeroID(hero)
local group G = null
local unit u = null
local integer n = 0
local real EnemyN = 0.
local real dis = 256.
if hero_evade_boolean[id] == true then
set G=CreateGroup()
call GroupEnumUnitsInRange(G,GetUnitX(hero),GetUnitY(hero),600.0,null)
loop
set u=FirstOfGroup(G)
if IsUnitType(u,UNIT_TYPE_DEAD)==false and u!=null and IsUnitEnemy(u,GetOwningPlayer(hero))==true then
set n = n + 1
if GetOwningPlayer(u) != CreepPlayer then
set EnemyN = EnemyN + 1.
endif
endif     
call GroupRemoveUnit(G,u)
exitwhen u==null
endloop
call GroupClear(G)
call DestroyGroup(G)
if n > 1 then
if IsUnitSpelling(hero) == false then
if IsUnitType(GetAttacker(), UNIT_TYPE_STRUCTURE) == true then
set EnemyN = EnemyN + 2.
set dis = 800.
endif
call OrderUnitMoveAng(hero,dis,AngleBetweenUnits(GetAttacker(),hero))
endif
if EnemyN > 5. then
set EnemyN = 5.
endif
call TimerStart(hero_evade_timer[id],6.5,false,function SetEvadeBoolean)
set hero_evade_boolean[id] = false
if IsUnitInGroup(hero,group_evade)==false then
call GroupAddUnit(group_evade,hero)
endif
endif
endif
set u = null
set G = null
set hero = null
endfunction
private function AiHeroAttackWeakUnit takes unit hero,real x,real y,player p,group G,integer id returns nothing
local unit u = null
local real HPmin = 5000.0
local unit weakEnemy = null
local unit weakHero = null
local unit weakAlly = null
local real uHP = 0.0
local real uHPmax = 0.0
local real uHPpercent = 0.0 
local real attack_dis = 800.0
local real level = I2R(GetHeroLevel(hero))
local boolean b = false
local integer EnemyheroN = 0
if IsUnitType(hero,UNIT_TYPE_MELEE_ATTACKER)==true then
set attack_dis = 400.0
endif
call SetUnitOwner( hero_testunit_attack[id], p, true )
loop
set b = false
set u = FirstOfGroup(G)
set uHP = GetUnitState(u,UNIT_STATE_LIFE)
set uHPmax = GetUnitState(u,UNIT_STATE_MAX_LIFE)+1.0
set uHPpercent = uHP/uHPmax*1.0
if IssueTargetOrder(hero_testunit_attack[id],"smart",u) then
call IssueImmediateOrder(hero_testunit_attack[id], "stop")
if IsUnitEnemy(u,p) then
if uHP < HPmin then
set HPmin = uHP
set weakEnemy = u
if IsUnitType(u,UNIT_TYPE_HERO)==true then
set EnemyheroN = EnemyheroN + 1
endif
endif
if IsUnitType(u,UNIT_TYPE_HERO)==true then
if uHPpercent < 0.5 then
set attack_dis = 800.0
set weakHero = u
endif
endif
else
if b_attack_ally[id]==true and uHPpercent<0.35 and uHP<50.0+5.0*level then
set weakAlly = u
endif
endif
endif
call GroupRemoveUnit(G,u)
exitwhen u==null
endloop
call GroupClear(G)
if weakEnemy != null then
if attack_dis>=DistanceBetweenXY(x,GetUnitX(weakEnemy),y,GetUnitY(weakEnemy)) /*
*/ and IsUnitSpelling(hero) == false then
call IssueTargetOrder(hero,"attack",weakEnemy)
endif
endif
if weakHero != null and IsUnitSpelling(hero) == false then
call IssueTargetOrder(hero,"attack",weakHero)
endif
if weakAlly != null and IsUnitSpelling(hero) == false and EnemyheroN > 0 then
call IssueTargetOrder(hero,"attack",weakAlly)
endif
call SetUnitOwner( hero_testunit_attack[id], Player(15), true )
set u = null
set weakAlly = null
set weakEnemy = null
set weakHero = null
endfunction
private function ai_Hero_Loop takes nothing returns nothing
local integer i = 0
local group G = null
local player p = null
local real heroHP = 0.0
local real heroHPmax = 0.0
local real heroHPpercent = 0.0
local real heroMana = 0.0
local real heroManaMax = 0.0
local real heroManaPercent = 0.0
local unit u = null
local integer AllyI = 0
local integer EnemyI = 0
local group g_weak = null
local real x = 0.
local real y = 0.
local unit EnemyU = null
local integer EnemyN = 0
loop
exitwhen i > Top_ai_hero
if IsUnitType(ai_hero[i],UNIT_TYPE_DEAD)==false or ai_hero[i]!=null then
set x = GetUnitX(ai_hero[i])
set y = GetUnitY(ai_hero[i])
set p = GetOwningPlayer(ai_hero[i])
set heroHP = GetUnitState(ai_hero[i],UNIT_STATE_LIFE)
set heroHPmax = GetUnitState(ai_hero[i],UNIT_STATE_MAX_LIFE)+1.0
set heroHPpercent = heroHP/heroHPmax*1.0
set heroMana = GetUnitState(ai_hero[i],UNIT_STATE_MANA)
set heroManaMax = GetUnitState(ai_hero[i],UNIT_STATE_MAX_MANA)+1.0
set heroManaPercent = heroMana/heroManaMax*1.0
set G=CreateGroup()
call GroupEnumUnitsInRange(G,x,y,800.0,null)
set g_weak = CreateGroup()
loop
set u=FirstOfGroup(G)
if IsUnitType(u,UNIT_TYPE_DEAD)==false and u!=null then
call GroupAddUnit(g_weak,u)
if GetOwningPlayer(u)==p /*
*/ and IsUnitInGroup(u,group_AI_herounits[i])==false /*
*/ and IsUnitType(u,UNIT_TYPE_PEON)==false then
call GroupAddUnit(group_AI_herounits[i],u)
endif
if IsUnitEnemy(u,p) == true then
set EnemyN = EnemyN + 1
set EnemyU = u
endif       
endif      
call GroupRemoveUnit(G,u)
exitwhen u==null
endloop
if b_attack_weakunit[i] == true then
if IsUnitInGroup(ai_hero[i],group_evade)==true then
call GroupRemoveUnit(group_evade,ai_hero[i])
else
call AiHeroAttackWeakUnit(ai_hero[i],x,y,p,g_weak,i)
endif
endif
call DestroyGroup(g_weak)
if loc_ai_retreat[i]!=null and heroHPpercent<hp_ai_retreat[i] and b_ai_retreat[i]==true then
if EnemyN > 0 then
call IssuePointOrderLoc( ai_hero[i], "move", loc_ai_retreat[i] )
if EnemyN < 2 and GetUnitState(EnemyU,UNIT_STATE_LIFE) < 50. then
call IssueTargetOrder( ai_hero[i], "attackone", EnemyU )
endif
endif
endif
call GroupClear(G)
call DestroyGroup(G)
if loc_ai_retreat[i] != null then
if DistanceBetweenXY(x,GetLocationX(loc_ai_retreat[i]),y,GetLocationY(loc_ai_retreat[i]))<=800. then
if heroHPpercent < HPmin_hero_attack or heroManaPercent < MANAmin_hero_attack then
call IssuePointOrderLoc( ai_hero[i], "attack", loc_ai_retreat[i] )
endif
endif 
endif
if b_ai_pickItem[i] == true and IsUnitBackpackFull(ai_hero[i]) == false then
call HeroPickItem(ai_hero[i],x,y)
endif
endif
set i = i + 1
endloop
set u = null
set G = null
set p = null
set g_weak = null
set EnemyU = null
endfunction
private function GetCreepsCamp takes nothing returns nothing
local unit u
local unit camu
local group camg 
local group g = CreateGroup()
local integer i = 0
local integer pi = 0
call GroupClear(group_creepcamp)
loop
exitwhen i > Top_creepcamp
call GroupClear(groups_camg[i])
call DestroyGroup(groups_camg[i])
set groups_camg[i] = null
set b_creeps_canattack[i]=true
call RemoveLocation(loc_min_camg[i])
set creeps_level[i] = 0
set i = i + 1
endloop
set Top_creepcamp = -1
call GroupEnumUnitsOfPlayer(g,CreepPlayer,null)
loop
set u = FirstOfGroup(g)
if IsUnitInGroup(u,group_creepcamp)==false and IsUnitType(u,UNIT_TYPE_DEAD)==false then
set Top_creepcamp = Top_creepcamp + 1
set pi = 0
loop
exitwhen pi > 11
set b_can_atk_camg[pi][Top_creepcamp] = true
set pi = pi + 1
endloop
set loc_min_camg[Top_creepcamp] = Location(GetUnitX(u),GetUnitY(u))
if groups_camg[Top_creepcamp] == null then
set groups_camg[Top_creepcamp] = CreateGroup()
endif
set camg = CreateGroup()
call GroupEnumUnitsInRange(camg,GetUnitX(u),GetUnitY(u),800.99,null)
loop
set camu = FirstOfGroup(camg)
if GetOwningPlayer(camu)==CreepPlayer and IsUnitType(camu,UNIT_TYPE_DEAD)==false then
set creeps_level[Top_creepcamp] = creeps_level[Top_creepcamp] + GetUnitLevel(camu)
call GroupAddUnit(group_creepcamp,camu)
call GroupAddUnit(groups_camg[Top_creepcamp],camu)
endif
call GroupRemoveUnit(camg,camu)
exitwhen camu==null
endloop
call GroupClear(camg)
call DestroyGroup(camg)
endif
call GroupRemoveUnit(g,u)
exitwhen u==null
endloop
call GroupClear(g)
call DestroyGroup(g)
set u = null
set g = null
set camu = null
set camg = null
endfunction
private function CheckHeroTarget takes nothing returns nothing
local integer i = 0
local real heroHP = 0.0
local real heroHPmax = 0.0
local real heroHPpercent = 0.0
loop
exitwhen i > Top_ai_hero
set heroHP = GetUnitState(ai_hero[i],UNIT_STATE_LIFE)
set heroHPmax = GetUnitState(ai_hero[i],UNIT_STATE_MAX_LIFE)+1.0
set heroHPpercent = heroHP/heroHPmax*1.0
set b_ai_havetarget[i] = false
if b_ai_MF[i] == true then
call CheckHeroMf(i,heroHPpercent)
endif
if b_ai_havetarget[i] == false then
if b_ai_attacktarget[i] == true then
call CheckHeroAttackTarget(i,heroHPpercent)
endif
endif
if b_ai_havetarget[i] == false then
if b_ai_retreat[i] == true and loc_ai_retreat[i] != null then
call IssuePointOrderLoc( ai_hero[i], "move", loc_ai_retreat[i] )
endif
endif
set i = i + 1
endloop
endfunction
private function RegisterAiHero takes unit hero returns nothing
if IsUnitType(hero,UNIT_TYPE_HERO)==true /* 
*/ and GetPlayerController(GetOwningPlayer(hero))==MAP_CONTROL_COMPUTER /* 
*/ and IsUnitInGroup(hero,group_AI_hero) == false then 
call GroupAddUnit(group_AI_hero,hero)
set Top_ai_hero = Top_ai_hero + 1
if open_ai == 0 then
call TimerStart(CreateTimer(),4.92,true,function CheckHeroTarget)
call TimerStart(CreateTimer(),45.86,true,function GetCreepsCamp)
call TimerStart(CreateTimer(),0.73,true,function ai_Hero_Loop)
endif
set open_ai = open_ai + 1
set ai_hero[Top_ai_hero] = hero
set b_ai_MF[Top_ai_hero] = false
set b_ai_retreat[Top_ai_hero] = false
set b_ai_pickItem[Top_ai_hero] = false
set b_ai_havetarget[Top_ai_hero] = false
set mf_max_level[Top_ai_hero] = 0
set group_AI_herounits[Top_ai_hero] = CreateGroup()
set hero_evade_timer[Top_ai_hero] = CreateTimer()
set hero_evade_boolean[Top_ai_hero] = true
set b_attack_ally[Top_ai_hero] = false
set b_attack_weakunit[Top_ai_hero] = false
set b_ai_attacktarget[Top_ai_hero] = false
set hero_testunit_attack[Top_ai_hero] = CreateUnit(Player(15),GetUnitTypeId(hero),map_max_X,map_max_Y,0.)
call ShowUnit(hero_testunit_attack[Top_ai_hero],false)
call UnitAddAbility( hero_testunit_attack[Top_ai_hero], 'Aloc' )
call TriggerRegisterUnitEvent(hero_attacked_trigger,ai_hero[Top_ai_hero],EVENT_UNIT_ATTACKED)
call SetPlayerName( GetOwningPlayer(hero), ( "[EggHeroAI]" + GetPlayerName(GetOwningPlayer(hero)) ) )
endif
endfunction
function SetAiHeroAttackTarget takes unit hero, location loc, boolean b returns nothing
local integer id = 0
call RegisterAiHero(hero)
set id = GetAiHeroID(hero)
set ai_hero_targetloc[id] = loc
set b_ai_attacktarget[id] = b
endfunction
function SetAiHeroMF takes unit hero, integer level, boolean b returns nothing
local integer id = 0
call RegisterAiHero(hero)
set id = GetAiHeroID(hero)
set b_ai_MF[id] = b
set mf_max_level[id] = level
endfunction
function SetAiHeroRetreat takes unit hero, location loc, real hpmin, boolean b returns nothing
local integer id = 0
call RegisterAiHero(hero)
set id = GetAiHeroID(hero)
set loc_ai_retreat[id] = loc
set b_ai_retreat[id] = b
set hp_ai_retreat[id] = hpmin
endfunction
function SetAiHeroPickItem takes unit hero, boolean b returns nothing
call RegisterAiHero(hero)
set b_ai_pickItem[GetAiHeroID(hero)] = b
endfunction
function SetAiHeroAttackWeak takes unit hero, boolean b1, boolean b2 returns nothing
local integer id = 0
call RegisterAiHero(hero)
set id = GetAiHeroID(hero)
set b_attack_weakunit[id] = b1
set b_attack_ally[id] = b2
endfunction
public function rpg_ai_Init takes nothing returns nothing
call GetCreepsCamp()
call TriggerAddAction(hero_attacked_trigger,function AiHeroAttacked)
set HPmin_hero_attack = 0.95
set MANAmin_hero_attack = 0.90
endfunction
//triggers
private function TriggerRegisterAnyUnitPoint takes nothing returns nothing
local unit u = GetTriggerUnit()
local player p = GetOwningPlayer(u)
local integer id = GetPlayerId(p)
if GetPlayerController(p) == MAP_CONTROL_COMPUTER and Melee_AI_On[id] == true then
if IsUnitType(u, UNIT_TYPE_HERO) == true and b_transport_getTarget[id] == false then//and GetIssuedOrderId() == 851983 then
if loc_hero_orderLoc[id] != null then
call RemoveLocation(loc_hero_orderLoc[id])
endif
set loc_hero_orderLoc[id] = GetOrderPointLoc()
endif
endif
set u = null
set p = null
endfunction
private function TriggerRegisterAnyUnitSold takes nothing returns nothing
local integer typeid = GetUnitTypeId(GetSoldUnit())
local integer i = 0
if GetPlayerId(GetOwningPlayer(GetSellingUnit())) == 15 /*
*/ and GetUnitTypeId(GetSellingUnit()) != UnitType_AmmoDump then
loop
exitwhen i > 11
set Unit_GetSoldShop[i] = GetSellingUnit()
set i = i + 1
endloop
endif
if typeid != UnitType_TronGloem and typeid != UnitType_zeppelin then
set UnitType_GetSoldUnit = typeid
endif
endfunction
private function TriggerRegisterAnyUnitSpellEffect takes nothing returns nothing
endfunction
private function TriggerRegisterAnyUnitSpellEnd takes nothing returns nothing
if IsUnitInGroup(GetTriggerUnit(),group_speller)==true then
call GroupRemoveUnit(group_speller,GetTriggerUnit())
endif
endfunction
private function TriggerRegisterAnyUnitSpell takes nothing returns nothing
local real timeout = 0.0
local unit target = null
local unit speller = GetTriggerUnit()
set target = GetSpellTargetUnit()
if IsUnitInGroup(speller,group_speller)==false then
call GroupAddUnit(group_speller,speller)
endif
if target != null then
if IsUnitType(target, UNIT_TYPE_HERO) == true then
if Melee_AI_On[GetPlayerId(GetOwningPlayer(target))] == true /*
*/ and GetHeroStatePercent(target,UNIT_STATE_LIFE) <= 0.15 /*
*/ and IsUnitEnemy(speller,GetOwningPlayer(target)) == true then
set Top_hero_av_abi = Top_hero_av_abi + 1
set hero_av_abi[Top_hero_av_abi] = target
if GetRandomInt(1,2) == 1 then
set timeout = 0.35
endif
call TimerStart(CreateTimer(),timeout,false,function AI_Hero_AvoidAbilityDam)
endif
endif  
endif
set target = null
set speller = null
endfunction
private function TriggerRegisterAnyUnitDead takes nothing returns nothing
endfunction 
private function TriggerRegisterAnyUnit takes nothing returns nothing
local integer id = 0
local integer unitid = 0
local unit u = GetTriggerUnit()
local player p = GetOwningPlayer(u)
local integer towertype = 0
set id = GetPlayerId(p)
if Melee_AI_On[id] == true then
if GetUnitAbilityLevel(u,'Aloc') == 0 and IsUnitIllusion(u) == false and Top_Units[id] < max_array_units then
set Top_Units[id] = Top_Units[id] + 1
set unitid = id * max_array_units + Top_Units[id]
set ai_units[unitid] = u
set b_unit_guardPos[unitid] = true
set unit_LastX[unitid] = 0.
set unit_LastY[unitid] = 0.
set int_unit_blocked[unitid] = 0
if IsUnitType(ai_units[unitid], UNIT_TYPE_PEON) == true then
call GroupAddUnit(group_peons,ai_units[unitid])
endif
if GetUnitAbilityLevel(ai_units[unitid], 'Sch3') > 0 /*
*/ or GetUnitAbilityLevel(ai_units[unitid], 'Sch5') > 0 then
call GroupAddUnit(group_transportation,ai_units[unitid])
set num_zeppelin[id] = num_zeppelin[id] + 1
call IssuePointOrderLoc( ai_units[unitid], "move", loc_startLoc[id] )
endif
if GetUnitTypeId(ai_units[unitid]) == UnitType_TronGloem then
call RemoveGuardPosition(ai_units[unitid])
call IssuePointOrderLoc( ai_units[unitid], "move", loc_startLoc[id] )
call GroupAddUnit(group_peons,ai_units[unitid])
set num_IronGolem[id] = num_IronGolem[id] + 1
endif
//if IssuePointOrder( ai_units[unitid], "attackground", x, y ) then
//call IssueImmediateOrder( ai_units[unitid], "stop" )
//elseif GetUnitAbilityLevel(ai_units[unitid],'Aatk') > 0 /*
//*/ and IsUnitType(ai_units[unitid], UNIT_TYPE_STRUCTURE) == false  then
//set type_unit_siege[id] = GetUnitTypeId(ai_units[unitid])
//endif
if IsUnitType(ai_units[unitid], UNIT_TYPE_HERO) == true then
call TriggerRegisterUnitEvent(MeleeHero_Attacked_Trg,ai_units[unitid],EVENT_UNIT_ATTACKED)
call TriggerRegisterUnitEvent(MeleeHeroGetItem,ai_units[unitid],EVENT_UNIT_PICKUP_ITEM)
elseif IsUnitType(ai_units[unitid], UNIT_TYPE_STRUCTURE) == true then
if GetUnitAbilityLevel(ai_units[unitid], 'Apit') > 0 then
set melee_ai_shops[id] = ai_units[unitid]
endif
set towertype = GetUnitTypeId(ai_units[unitid])
if (IsUnitType(ai_units[unitid], UNIT_TYPE_RANGED_ATTACKER) == true /*
*/ and GetUnitAbilityLevel(ai_units[unitid], 'Abtl') < 1) or /*
*/ towertype == Ut_htw1 or towertype == Ut_utw1 or towertype == Ut_etw1 then
set type_melee_tower[id] = towertype
endif
endif
endif
endif
set p = null
set u = null
endfunction 
private function TriggerClearRegister takes nothing returns nothing
endfunction
private function TriggerProduce takes nothing returns nothing
local integer i = 0
set RectRegion = CreateRegion()
call RegionAddRect(RectRegion,bj_mapInitialPlayableArea)
call TriggerAddAction(AnyUnitEnter,function TriggerRegisterAnyUnit)
call TriggerAddAction(AnyUnitSpell,function TriggerRegisterAnyUnitSpell)
call TriggerAddAction(AnyUnitSpellEnd,function TriggerRegisterAnyUnitSpellEnd)
call TriggerRegisterEnterRegion(AnyUnitEnter,RectRegion,null)
call TriggerAddAction(AnyUnitSold,function TriggerRegisterAnyUnitSold)
call TriggerAddAction(AnyUnitOrderPoint,function TriggerRegisterAnyUnitPoint)
call TriggerAddAction(MeleeHeroGetItem,function Melee_HeroGetItem)
loop
exitwhen i > 15    
call TriggerRegisterPlayerUnitEvent(AnyUnitSpell,Player(i),EVENT_PLAYER_UNIT_SPELL_CHANNEL,null)
call TriggerRegisterPlayerUnitEvent(AnyUnitSpellEnd,Player(i),EVENT_PLAYER_UNIT_SPELL_ENDCAST,null)
call TriggerRegisterPlayerUnitEvent(AnyUnitSold,Player(i),EVENT_PLAYER_UNIT_SELL,null)
call TriggerRegisterPlayerUnitEvent(AnyUnitOrderPoint,Player(i),EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER,null)
set i = i + 1
endloop
endfunction
//start
private function InitAll takes nothing returns nothing
local integer i = 0
loop
exitwhen i > 15
set Melee_AI_On[i] = false
set i = i + 1
endloop
set map_max_X = GetRectMaxX(bj_mapInitialPlayableArea)
set map_max_Y = GetRectMaxY(bj_mapInitialPlayableArea)
set map_min_X = GetRectMinX(bj_mapInitialPlayableArea)
set map_min_Y = GetRectMinY(bj_mapInitialPlayableArea)
call TimerStart(CreateTimer(),20.3,true, function ItemPickingIntermission)
call TimerStart(CreateTimer(),34.4,true, function GroupClearTrg)
set filterEnumDestructablesInCircle = Filter(function EnumDestructablesInCircleFilter)
set harvest_unit = CreateUnit(Player(15),UnitType_Harvest,map_max_X,map_max_Y,0.)
call ShowUnit(harvest_unit,false)
call UnitRemoveAbility(harvest_unit,'Aatk')
call UnitAddAbility(harvest_unit,'Aloc')
if GetUnitAbilityLevel(harvest_unit,'ANha') < 1 then
call UnitAddAbility(harvest_unit,'ANha')
endif
call TriggerProduce()
//call rpg_ai_Init()
//call melee_ai_Init()
endfunction
endlibrary

Keywords:
AI,JASS
Contents

[AI]Strengthen Melee AI System (Map)

Reviews
12th Dec 2015 IcemanBo: Too long as NeedsFix. Rejected. 09:06, 17th Mar 2014 BPower: Awaits proper identation and a minimum of documentation. You are using vJass so please get rid of location use of any kind.

Moderator

M

Moderator

12th Dec 2015
IcemanBo: Too long as NeedsFix. Rejected.

09:06, 17th Mar 2014
BPower:
Awaits proper identation and a minimum of documentation.
You are using vJass so please get rid of location use of any kind.
 
You need to fix your Indentation :)

I belive this one used for a Melee map only ?

You need to read this: http://www.hiveworkshop.com/forums/...80/jpag-jass-proper-application-guide-204383/ and this too: http://www.hiveworkshop.com/forums/rules-information-710/spell-submission-rules-230362/

And here's author codes:
JASS:
library AIsystem initializer InitAll
globals
//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'
private constant integer Item_ssan = 'ssan'
private constant integer Item_spre = 'spre'
private constant integer Item_clsd = 'clsd'

//Unit
private constant integer Ut_hto1 = 'htow'
private constant integer Ut_hto2 = 'hkee'
private constant integer Ut_hto3 = 'hcas'
private constant integer Ut_oto1 = 'ogre'
private constant integer Ut_oto2 = 'ostr'
private constant integer Ut_oto3 = 'ofrt'
private constant integer Ut_uto1 = 'unpl'
private constant integer Ut_uto2 = 'unp1'
private constant integer Ut_uto3 = 'unp2'
private constant integer Ut_eto1 = 'etol'
private constant integer Ut_eto2 = 'etoa' 
private constant integer Ut_eto3 = 'etoe'
private constant integer Ut_htw1 = 'hwtw'
private constant integer Ut_htw2 = 'hgtw'
private constant integer Ut_utw1 = 'uzig'
private constant integer Ut_utw2 = 'uzg1'
private constant integer Ut_utw3 = 'uzg2'
private constant integer Ut_etw1 = 'emow'

private constant integer FoodUsed_upg_town1 = 30
private constant integer FoodUsed_upg_town2 = 65

private constant integer UnitType_zeppelin = 'nzep'
private constant integer UnitType_TronGloem = 'ngir'
private constant integer UnitType_AmmoDump = 'ngad'
//Buff
private constant integer Buff_sleep = 'BUsl'

//testunit
private constant integer UnitType_build_block = 'ncp2'
private constant integer UnitType_Harvest = 'nmpe'
endglobals

//math
function DistanceBetweenXY takes real x1,real x2,real y1,real y2 returns real
return SquareRoot(( x1 - x2 ) * ( x1 - x2 ) + ( y1 - y2 ) * ( y1 - y2 ))
endfunction
function AngleBetweenXY takes real x1, real x2, real y1, real y2 returns real
return bj_RADTODEG*Atan2( y2 - y1 , x2 - x1 )
endfunction
function RadianBetweenXY takes real x1, real x2, real y1, real y2 returns real
return Atan2( y2 - y1 , x2 - x1 )
endfunction
function DistanceBetweenUnits takes unit u1, unit u2 returns real
local real x1 = GetUnitX(u1)
local real x2 = GetUnitX(u2)
local real y1 = GetUnitY(u1)
local real y2 = GetUnitY(u2)
return SquareRoot(( x1 - x2 ) * ( x1 - x2 ) + ( y1 - y2 ) * ( y1 - y2 ))
endfunction
function AngleBetweenUnits takes unit u1, unit u2 returns real
return bj_RADTODEG*Atan2( GetUnitY(u2) - GetUnitY(u1) , GetUnitX(u2) - GetUnitX(u1) )
endfunction
function RadianBetweenUnits takes unit u1, unit u2 returns real
return Atan2( GetUnitY(u2) - GetUnitY(u1) , GetUnitX(u2) - GetUnitX(u1) )
endfunction
function DistanceBetweenPoint takes location l1, location l2 returns real
local real x1 = GetLocationX(l1)
local real x2 = GetLocationX(l2)
local real y1 = GetLocationY(l1)
local real y2 = GetLocationY(l2)
return SquareRoot(( x1 - x2 ) * ( x1 - x2 ) + ( y1 - y2 ) * ( y1 - y2 ))
endfunction
globals
private real map_max_X 
private real map_max_Y 
private real map_min_X 
private real map_min_Y 
endglobals
//
function OrderUnitMoveAng takes unit u, real dis, real ang returns nothing
local real x = 0.
local real y = 0.
set x = GetUnitX(u) + dis*Cos(ang*bj_DEGTORAD)
set y = GetUnitY(u) + dis*Sin(ang*bj_DEGTORAD)
call IssuePointOrder(u,"move",x,y)
endfunction
function OrderUnitMove takes unit u, real dis, real ang returns nothing
local real x = 0.
local real y = 0.
set x = GetUnitX(u) + dis*Cos(ang)
set y = GetUnitY(u) + dis*Sin(ang)
call IssuePointOrder(u,"move",x,y)
endfunction
function OrderUnitMoveXY takes unit u,real x,real y,real dis,real ang returns nothing
set x = x + dis*Cos(ang)
set y = y + dis*Sin(ang)
call IssuePointOrder(u,"move",x,y)
endfunction
//
function MoveUnitXY takes unit u, real dis, real ang returns nothing
local real x = GetUnitX(u)
local real y = GetUnitY(u)
set x = x + dis*Cos(ang*bj_DEGTORAD)
set y = y + dis*Sin(ang*bj_DEGTORAD)
if x<map_max_X and y<map_max_Y and x>map_min_X and y>map_min_Y then
call SetUnitX(u,x)
call SetUnitY(u,y)
endif
endfunction
//
function IsUnitInvulnerable takes unit u returns boolean
local real h = GetUnitState(u,UNIT_STATE_LIFE)
call UnitDamageTarget(u,u,0.01,false,false,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
if GetUnitState(u,UNIT_STATE_LIFE) < h then
call SetUnitState(u,UNIT_STATE_LIFE,h) 
return false
endif
return true
endfunction
//
function SetUnitPathingAll takes unit u,boolean b returns nothing
if GetUnitAbilityLevel(u,'Atwa') < 1 then
call UnitAddAbility( u, 'Atwa' )
call UnitRemoveAbility( u, 'Atwa' )
if b==true then
call ShowUnit(u,false)
call ShowUnit(u,true)
endif
endif
endfunction
//
function CancelUnitMoveAndAttack takes unit u returns nothing
call UnitRemoveAbility( u, 'Amov' )
call UnitRemoveAbility( u, 'Aatk' )
endfunction
//build
private function IssueHauntOrderAtLocEx takes unit whichPeon,location loc,integer typeid returns nothing
local group g = null
local unit goldMine = null
set g = CreateGroup()
call GroupEnumUnitsInRangeOfLoc(g, loc, 256.0, filterIssueHauntOrderAtLocBJ)
set goldMine = FirstOfGroup(g)
call GroupClear(g)
call DestroyGroup(g)
set g = null
if (goldMine != null) then
call IssueTargetOrderById(whichPeon, typeid, goldMine)
endif
set goldMine = null
endfunction
function BuildOrderByIdNearbyLoc takes unit builder,integer structure,location loc returns nothing
local location testloc
local integer level = 0
local unit testunit = CreateUnitAtLoc(Player(PLAYER_NEUTRAL_PASSIVE), structure, loc, 0.)
set testloc = GetUnitLoc(testunit)
set level = GetUnitAbilityLevel(testunit, 'Abgm')
call ShowUnit( testunit,false )
call KillUnit( testunit )
if level > 0 then
call IssueHauntOrderAtLocEx(builder, loc, structure)
else
call IssueBuildOrderById(builder, structure, GetLocationX(testloc), GetLocationY(testloc))
endif
call RemoveLocation( testloc )
set testloc = null
set testunit = null
endfunction
//
function IsUnitNarrowPathed takes unit u returns boolean
local unit testunit 
local real i = 0.0
local real a = 0.0
local integer n = 0
local real x = GetUnitX(u)
local real y = GetUnitY(u)
loop
exitwhen i > 7.0
set a=45.0 * i
set testunit = CreateUnit(Player(15),'nsln',x+168.0*Cos(a*bj_DEGTORAD),y+168.0*Sin(a*bj_DEGTORAD),0.)
if DistanceBetweenXY(GetUnitX(testunit),x,GetUnitY(testunit),y) > 184.0 then
set n = n + 1
endif
call ShowUnit( testunit,false )
call KillUnit( testunit )
set testunit = null
set i = i + 1.0
endloop
if n > 2 then
return true
endif
return false
endfunction
//groups
globals
private unit GroupPickUnit
endglobals
//
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
//
function GroupClearDeadUnits takes group g returns nothing
local unit u
local group G
set G=CreateGroup() 
loop
set u=FirstOfGroup(g)
if u!= null then
if GetUnitState(u,UNIT_STATE_LIFE)>0.0 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
endfunction
function GroupCountUnitsRemoveDead 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
if GetUnitState(u,UNIT_STATE_LIFE)>0.0 then
call GroupAddUnit(G,u)
set n=n+1
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 n
endfunction
//AI
globals
private region RectRegion
private trigger AnyUnitEnter = CreateTrigger()
private group group_speller = CreateGroup()
private trigger AnyUnitSpell = CreateTrigger()
private trigger AnyUnitSpellEnd = CreateTrigger()
private unit ItemPicker
private integer Num_PickItems = 0
private item item_Picking = null
private group group_item_pickers = CreateGroup()
private integer Top_item_pickers = -1
private unit array hero_item_picker
private integer array  item_picker_times
private destructable tree = null
private real destructableX = 0.0
private real destructableY = 0.0
private real destCenterX = 0.0 
private real destCenterY = 0.0
private real destructableRadius = 0.0
private boolexpr filterEnumDestructablesInCircle
private unit harvest_unit
private integer array Top_Units 
private integer max_array_units = 250
private group group_transportation = CreateGroup()
private unit array ai_units
private boolean AttackTree = false
private trigger AnyUnitSold = CreateTrigger()
private real array unit_LastX
private real array unit_LastY 
private integer array int_unit_blocked 
private trigger AnyUnitOrderPoint = CreateTrigger()
private trigger MeleeHeroGetItem = CreateTrigger()
endglobals
//
private function GetAiUnitsID takes unit u returns integer
local integer playerid = GetPlayerId(GetOwningPlayer(u))
local integer i = Top_Units[playerid]
local integer ID = -1
loop
exitwhen i < 0 or ID > -1
if u == ai_units[playerid * max_array_units + i] then
set ID = i
endif
set i = i - 1
endloop
return ID
endfunction
//

private function GainTree takes nothing returns nothing
set tree = GetEnumDestructable()
endfunction
private function EnumDestructablesInCircleFilter takes nothing returns boolean
local destructable d = GetFilterDestructable()
local real x = GetDestructableX(d)
local real y = GetDestructableY(d)
local boolean result = false
set result = DistanceBetweenXY(x,destCenterX,y,destCenterY) <= destructableRadius
set d = null
return result
endfunction
private function EnumDestructablesXY takes real radius,real x,real y,boolean range,code actionFunc returns nothing
local rect r = null
if radius >= 0 then
set destCenterX = x
set destCenterY = y
set destructableRadius = radius
set r = Rect(destCenterX-radius,destCenterY-radius,destCenterX+radius,destCenterY+radius)
if range == true then
call EnumDestructablesInRect(r, filterEnumDestructablesInCircle, actionFunc)
else
call EnumDestructablesInRect(r, null, actionFunc)
endif
call RemoveRect(r)
endif
set r = null
endfunction
private function IsDestructablesTree takes destructable tree returns boolean
if IssueTargetOrder( harvest_unit, "harvest", tree ) then
call IssueImmediateOrder( harvest_unit, "stop" )
return true
endif
return false
endfunction
//__________
function IsUnitSpelling takes unit u returns boolean
if IsUnitInGroup(u,group_speller)==true then
return true
endif
return false
endfunction
//_________(AI)
function IsUnitTransportation takes unit u returns boolean
if IsUnitInGroup(u,group_transportation)==true then
return true
endif
return false
endfunction
//
private function GetPlayerGold takes player p returns integer
return GetPlayerState(p,PLAYER_STATE_RESOURCE_GOLD)
endfunction
private function GetPlayerWood takes player p returns integer
return GetPlayerState(p,PLAYER_STATE_RESOURCE_LUMBER)
endfunction
private function GetPlayerFoodUsed takes player p returns integer
return GetPlayerState(p,PLAYER_STATE_RESOURCE_FOOD_USED)
endfunction
private function AdjustPlayerGold takes integer delta, player whichPlayer returns nothing
local integer i = GetPlayerGold(whichPlayer)+delta
if i < 0 then
set i = 0
endif
call SetPlayerState(whichPlayer,PLAYER_STATE_RESOURCE_GOLD,i)
endfunction
private function AdjustPlayerWood takes integer delta, player whichPlayer returns nothing
local integer i = GetPlayerWood(whichPlayer)+delta
if i < 0 then
set i = 0
endif
call SetPlayerState(whichPlayer,PLAYER_STATE_RESOURCE_LUMBER,i)
endfunction
private function PlayerDivertsResources takes player p1,player p2,integer gold,integer wood returns nothing
local integer i = GetPlayerGold(p1)
if gold > i then
set gold = i
endif
call AdjustPlayerGold( -gold, p1 )
call AdjustPlayerGold( gold, p2 )
set i = GetPlayerWood(p1)
if wood > i then
set wood = i
endif
call AdjustPlayerWood( -wood, p1 )
call AdjustPlayerWood( wood, p2 )
endfunction
private function GetItemNumOfItemType takes unit whichUnit, integer itemId returns integer
local integer index
local item indexItem = null
local integer n = 0
set index = 0
loop
set indexItem = UnitItemInSlot(whichUnit, index)
if indexItem != null and GetItemTypeId(indexItem) == itemId then
set n = n + 1
endif
set index = index + 1
exitwhen index >= bj_MAX_INVENTORY
endloop
set indexItem = null
return n
endfunction
private function GetInventoryIndexOfItemType takes unit whichUnit, integer itemId returns integer
local integer index
local item indexItem = null
set index = 0
loop
set indexItem = UnitItemInSlot(whichUnit, index)
if indexItem != null and GetItemTypeId(indexItem) == itemId then
set indexItem = null
return index 
endif
set index = index + 1
exitwhen index >= bj_MAX_INVENTORY
endloop
set indexItem = null
return -1
endfunction
private function GetItemOfTypeFromUnit takes unit whichUnit, integer itemId returns item
local integer index = GetInventoryIndexOfItemType(whichUnit, itemId)
if index == -1 then
return null
else
return UnitItemInSlot(whichUnit, index)
endif
endfunction
private function UnitUseItemAtLoc takes unit whichUnit, item whichItem, location loc returns boolean
return UnitUseItemPoint(whichUnit, whichItem, GetLocationX(loc), GetLocationY(loc))
endfunction
function HeroInventoryCount takes unit whichUnit returns integer
local integer index = 0
local integer count = 0
loop
if UnitItemInSlot(whichUnit, index) != null then
set count = count + 1
endif
set index = index + 1
exitwhen index >= bj_MAX_INVENTORY
endloop
return count
endfunction
function IsUnitBackpackFull takes unit u returns boolean
if HeroInventoryCount(u) >= UnitInventorySize(u) then
return true
endif
return false
endfunction
//
private function GetHeroStatePercent takes unit whichUnit, unitstate whichState returns real
local real value = GetUnitState(whichUnit,whichState)
local real maxValue = 0.0
if whichState == UNIT_STATE_MANA then
set maxValue = GetUnitState(whichUnit,UNIT_STATE_MAX_MANA)
else
set maxValue = GetUnitState(whichUnit,UNIT_STATE_MAX_LIFE)
endif
if whichUnit == null or maxValue == 0.0 then
return 0.0
endif
return value/maxValue*1.0
endfunction
//

private function TestUnitEffect takes unit u returns nothing
call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Other\\Monsoon\\MonsoonBoltTarget.mdl",u,"overhead"))
endfunction
//
private function ItemPickingIntermission takes nothing returns nothing
local integer n = 0
if AttackTree == false then
set AttackTree = true
else
set AttackTree = false
endif
loop
exitwhen n > Top_item_pickers
call GroupRemoveUnit(group_item_pickers,hero_item_picker[n])
set n = n + 1
endloop
set Top_item_pickers = -1
endfunction
private function PickItem takes nothing returns nothing
set item_Picking = GetEnumItem()
set Num_PickItems = Num_PickItems + 1
endfunction
private function HeroPickItem takes unit hero,real x,real y returns nothing
local rect ItemRect
local integer n = 0
set Num_PickItems = 0
set ItemRect = Rect(x-800.,y-800.,x+800.,y+800.)
set ItemPicker = hero
call EnumItemsInRect(ItemRect,null,function PickItem)
if Num_PickItems > 0 then
if IsUnitInGroup(hero,group_item_pickers) == false then
call GroupAddUnit(group_item_pickers,hero)
set Top_item_pickers = Top_item_pickers + 1
set hero_item_picker[Top_item_pickers] = hero
set item_picker_times[Top_item_pickers] = 0
call IssueTargetOrder(ItemPicker,"smart",item_Picking)
else
loop
exitwhen n > Top_item_pickers
if hero == hero_item_picker[n] then
set item_picker_times[n] = item_picker_times[n] + 1
if item_picker_times[n] < 6 then
call IssueTargetOrder(ItemPicker,"smart",item_Picking)
endif
endif
set n = n + 1
endloop
endif
if GetWidgetLife(item_Picking) < 0.1 then
call SetWidgetLife( item_Picking, 50. )
call RemoveItem(item_Picking)
endif
endif
call RemoveRect(ItemRect)
set ItemRect = null
endfunction
private function HeroBuyItem takes unit hero,integer playerid,unit shop,integer typeitem returns nothing
if IsUnitBackpackFull(hero) == false then
call IssueNeutralTargetOrder( Player(playerid), shop, "neutralinteract", hero )
call IssueNeutralImmediateOrderById( Player(playerid), shop, typeitem )
endif
endfunction
//Meele AI__
globals
private integer Un_hto1
private integer Un_hto2
private integer Un_hto3
private integer Un_oto1
private integer Un_oto2
private integer Un_oto3
private integer Un_uto1
private integer Un_uto2
private integer Un_uto3
private integer Un_eto1
private integer Un_eto2
private integer Un_eto3
endglobals
globals

private location array loc_startLoc
private integer id_timer_player = 0
private integer Top_units_NoAI = -1
private unit array units_NoAI
private real array time_unit_guardPos
private integer array id_unit_guardPos
private trigger MeleeHero_Attacked_Trg = CreateTrigger()
private location array loc_rallyLoc
private integer int_buyitemHome = 0
private boolean array Melee_AI_On
private unit array hero_av_abi
private integer Top_hero_av_abi = -1
private integer int_player_con = 0
private boolean array b_player_loser


private group group_peons = CreateGroup()

private boolean array b_unit_guardPos
private unit array melee_ai_shops
private unit array unit_transport
private integer array int_transport
private unit array unit_peon_buyer
private unit array natural_shop_AmmoDump
private integer natural_max_AmmoDump = 0
private unit array target_shop_AmmoDump
private integer array num_zeppelin
private integer array num_IronGolem
private integer UnitType_GetSoldUnit = 0
private unit array Unit_GetSoldShop
private unit array natural_shop_Merchant
private integer natural_max_Merchant = 0
private location array loc_hero_orderLoc
private timer array timer_transport
private boolean array b_transport_getTarget
private unit array test_block_buildings [12][10]
private integer array type_unit_siege
private integer array type_melee_tower
private unit array unit_peon_towerbuilder
private location array loc_enemy_targetLoc
private boolean array b_onlyoneEnemy
private group group_final_attack = CreateGroup()
private boolean array b_invisible_enemy
private boolean array b_melee_herobuy
endglobals
private function GroupClearTrg takes nothing returns nothing
call GroupClearDeadUnits(group_transportation)
call GroupClearDeadUnits(group_peons)
call GroupClear(group_final_attack)
endfunction

private function ClearTownHallNum takes nothing returns nothing
set Un_hto1 = 0
set Un_hto2 = 0
set Un_hto3 = 0
set Un_oto1 = 0
set Un_oto2 = 0
set Un_oto3 = 0
set Un_uto1 = 0
set Un_uto2 = 0
set Un_uto3 = 0
set Un_eto1 = 0
set Un_eto2 = 0
set Un_eto3 = 0
endfunction
private function SetTownHallTypeNum takes unit town, integer pid returns nothing
//hum
if GetPlayerRace(Player(pid)) == RACE_HUMAN then
if GetUnitTypeId(town) == Ut_hto1 then
set Un_hto1 = Un_hto1 + 1
elseif GetUnitTypeId(town) == Ut_hto2 then
set Un_hto2 = Un_hto2 + 1
elseif GetUnitTypeId(town) == Ut_hto3 then
set Un_hto3 = Un_hto3 + 1
endif
//orc
elseif GetPlayerRace(Player(pid)) == RACE_ORC then
if GetUnitTypeId(town) == Ut_oto1 then
set Un_oto1 = Un_oto1 + 1
elseif GetUnitTypeId(town) == Ut_oto2 then
set Un_oto2 = Un_oto2 + 1
elseif GetUnitTypeId(town) == Ut_oto3 then
set Un_oto3 = Un_oto3 + 1
endif
//undead
elseif GetPlayerRace(Player(pid)) == RACE_UNDEAD then
if GetUnitTypeId(town) == Ut_uto1 then
set Un_uto1 = Un_uto1 + 1
elseif GetUnitTypeId(town) == Ut_uto2 then
set Un_uto2 = Un_uto2 + 1
elseif GetUnitTypeId(town) == Ut_uto3 then
set Un_uto3 = Un_uto3 + 1
endif
//elf
elseif GetPlayerRace(Player(pid)) == RACE_NIGHTELF then
if GetUnitTypeId(town) == Ut_eto1 then
set Un_eto1 = Un_eto1 + 1
elseif GetUnitTypeId(town) == Ut_eto2 then
set Un_eto2 = Un_eto2 + 1
elseif GetUnitTypeId(town) == Ut_eto3 then
set Un_eto3 = Un_eto3 + 1
endif
endif
endfunction
private function UpgradeTown takes unit town,integer newtype ,integer pid,integer level returns nothing
local integer foodused = GetPlayerFoodUsed(Player(pid))
local boolean upg = false
if level == 1 then
if foodused >= FoodUsed_upg_town1 then
set upg = true
endif
elseif level == 2 then
if foodused >= FoodUsed_upg_town2 then
set upg = true
endif
endif
if upg == true then
call IssueImmediateOrderById( town, newtype )
endif
endfunction
private function UpgradeTownHall takes unit town, integer pid returns nothing
//hum
if GetPlayerRace(Player(pid)) == RACE_HUMAN then
if GetUnitTypeId(town) == Ut_hto1 then
if Un_hto2 + Un_hto3 < 1 then
call UpgradeTown( town, Ut_hto2, pid,1 )
endif
elseif GetUnitTypeId(town) == Ut_hto2 then
if Un_hto3 < 1 then
call UpgradeTown( town, Ut_hto3, pid,2 )
endif
elseif GetUnitTypeId(town) == Ut_hto3 then
endif
//orc
elseif GetPlayerRace(Player(pid)) == RACE_ORC then
if GetUnitTypeId(town) == Ut_oto1 then
if Un_oto2 + Un_oto3 < 1 then
call UpgradeTown( town, Ut_oto2, pid,1 )
endif
elseif GetUnitTypeId(town) == Ut_oto2 then
if Un_oto3 < 1 then
call UpgradeTown( town, Ut_oto3, pid,2 )
endif
elseif GetUnitTypeId(town) == Ut_oto3 then
endif
//undead
elseif GetPlayerRace(Player(pid)) == RACE_UNDEAD then
if GetUnitTypeId(town) == Ut_uto1 then
if Un_uto2 + Un_uto3 < 1 then
call UpgradeTown( town, Ut_uto2, pid,1 )
endif
elseif GetUnitTypeId(town) == Ut_uto2 then
if Un_uto3 < 1 then
call UpgradeTown( town, Ut_uto3, pid,2 )
endif
elseif GetUnitTypeId(town) == Ut_uto3 then
endif
//elf
elseif GetPlayerRace(Player(pid)) == RACE_NIGHTELF then
if GetUnitTypeId(town) == Ut_eto1 then
if Un_eto2 + Un_eto3 < 1 then
call UpgradeTown( town, Ut_eto2, pid,1 )
endif
elseif GetUnitTypeId(town) == Ut_eto2 then
if Un_eto3 < 1 then
call UpgradeTown( town, Ut_eto3, pid,2 )
endif
elseif GetUnitTypeId(town) == Ut_eto3 then
endif
endif
endfunction
private function MeleeHeroFindShop takes unit hero, integer pid, integer ui returns nothing
local integer n = 1
local real dismin = 20000.0
local real dis = 0.0
local unit shop = null
loop
exitwhen n > natural_max_Merchant
set dis = DistanceBetweenUnits(hero,natural_shop_Merchant[n])
if dis < dismin then
set dismin = dis
set shop = natural_shop_Merchant[n]
endif
set n = n + 1
endloop
if shop != null and dis < 3000. and b_melee_herobuy[pid] == true then
//call Unit_RemoveAI(hero,ui,5.0)
call IssueTargetOrder( hero, "smart", shop )
if IsUnitInRange(hero,shop,300.) == true then
set b_melee_herobuy[pid] = false
endif
endif
set shop = null
endfunction
private function MeleeHeroProtection takes unit hero returns nothing
local item Item 
local player p 
local integer id = 0
if GetUnitAbilityLevel(hero,Buff_sleep) > 0 then
return
endif
set p = GetOwningPlayer(hero)
set id = GetPlayerId(p)
set Item = GetItemOfTypeFromUnit(hero,Item_pnvl)
if GetItemCharges(Item) > 0 then
if IsUnitInvulnerable(hero) == false then
call UnitUseItem(hero,Item)
endif   
else
set Item = GetItemOfTypeFromUnit(hero,Item_stwp)
if GetItemCharges(Item) > 0 then
if IsUnitInvulnerable(hero) == false then
call UnitUseItemAtLoc(hero,Item,loc_startLoc[id])
endif
else
             
endif
endif
set Item = null
set p = null
endfunction
private function Melee_HeroGetItem takes nothing returns nothing
local integer Item = GetItemTypeId(GetManipulatedItem())
local integer n = GetItemNumOfItemType(GetTriggerUnit(),Item)
if Item == Item_clsd then
return
endif
if n == 1 then
call SetItemPawnable( GetManipulatedItem(), false )
elseif n > 1 then
call SetItemPawnable( GetManipulatedItem(), true )
endif
endfunction 
private function MeleeHeroAttacked takes nothing returns nothing
if GetHeroStatePercent(GetTriggerUnit(),UNIT_STATE_LIFE) <= 0.15 then 
call MeleeHeroProtection(GetTriggerUnit())
endif
endfunction  
private function AI_Hero_AvoidAbilityDam takes nothing returns nothing
local integer i = 1
call DestroyTimer(GetExpiredTimer())
call MeleeHeroProtection(hero_av_abi[0])
set hero_av_abi[0] = null
loop
exitwhen i > Top_hero_av_abi
set hero_av_abi[i-1] = hero_av_abi[i]
set i = i + 1
endloop
set hero_av_abi[Top_hero_av_abi] = null
set Top_hero_av_abi = Top_hero_av_abi - 1
endfunction
private function Transport_Timer takes nothing returns nothing
local integer index = 0
local location orderpoint = null
local unit transport = null
loop
exitwhen index > 11
if GetExpiredTimer() == timer_transport[index] then
set orderpoint = loc_hero_orderLoc[index]
set transport = unit_transport[index]
set b_transport_getTarget[index] = true
call IssuePointOrder(transport,"unloadall",GetLocationX(orderpoint),GetLocationY(orderpoint))
endif
set index = index + 1
endloop
set orderpoint = null
set transport = null
endfunction
private function Pop_NoAIUnits takes integer i returns nothing
if units_NoAI[i] != null then
call RecycleGuardPosition( units_NoAI[i] )
set b_unit_guardPos[id_unit_guardPos[i]] = true
endif
set units_NoAI[i] = units_NoAI[Top_units_NoAI]
set time_unit_guardPos[i] = time_unit_guardPos[Top_units_NoAI]
set id_unit_guardPos[i] = id_unit_guardPos[Top_units_NoAI]
set units_NoAI[Top_units_NoAI] = null
set Top_units_NoAI = Top_units_NoAI - 1
endfunction
private function NoAIUnits_Loop takes nothing returns nothing
local integer i = Top_units_NoAI
local real hptest = 0.0
//call BJDebugMsg(I2S(i))
loop
exitwhen i < 0
set hptest = 0.
set hptest = GetUnitState(units_NoAI[i], UNIT_STATE_LIFE)
if hptest < 0.40 or time_unit_guardPos[i] <= 0.0 then
call Pop_NoAIUnits(i)
else
set time_unit_guardPos[i] = time_unit_guardPos[i] - 0.5
endif
set i = i - 1
endloop
endfunction
private function Unit_RemoveAI takes unit u , integer unitid, real timemax returns nothing
local integer n = 0
if b_unit_guardPos[unitid] == true then
set b_unit_guardPos[unitid] = false
set Top_units_NoAI = Top_units_NoAI + 1
set units_NoAI[Top_units_NoAI] = u
set time_unit_guardPos[Top_units_NoAI] = timemax
set id_unit_guardPos[Top_units_NoAI] = unitid
call RemoveGuardPosition( u )
else
loop
exitwhen n > Top_units_NoAI
if u == units_NoAI[n] then
if timemax > time_unit_guardPos[n] then
set time_unit_guardPos[n] = timemax
endif
endif
set n = n + 1
endloop
endif
endfunction
private function Pop_ai_Units takes integer playerid,integer i returns nothing
local integer product = playerid * max_array_units
local integer unitid = product + i
local integer topid = product + Top_Units[playerid]
set ai_units[unitid] = ai_units[topid]
set unit_LastX[unitid] = unit_LastX[topid]
set unit_LastY[unitid] = unit_LastY[topid]
set int_unit_blocked[unitid] = int_unit_blocked[topid]
set ai_units[topid] = null
set Top_Units[playerid] = Top_Units[playerid] - 1
endfunction
private function PeonBuildTower takes integer playerid returns nothing
local unit builder = unit_peon_towerbuilder[playerid]
local location loc = GetUnitLoc(builder)
if IsUnitSpelling(builder) == false and DistanceBetweenPoint(loc,loc_startLoc[playerid]) > 1200. then
if GetPlayerGold(Player(playerid)) > 1500 and GetPlayerWood(Player(playerid)) > 500 then
if IsUnitType(builder, UNIT_TYPE_UNDEAD) == true then
if IsPointBlighted(GetLocationX(loc), GetLocationY(loc)) == true then
call BuildOrderByIdNearbyLoc( builder, type_melee_tower[playerid], loc )
else
call BuildOrderByIdNearbyLoc( builder, Ut_uto1, loc )
endif
else
call BuildOrderByIdNearbyLoc( builder, type_melee_tower[playerid], loc )
endif
if loc_enemy_targetLoc[playerid] != null and GetRandomInt(1,2) == 1 /*
*/ and DistanceBetweenPoint(loc,loc_enemy_targetLoc[playerid]) > 800. then
call IssuePointOrderLoc( builder, "move", loc_enemy_targetLoc[playerid] )
endif
endif
endif
call RemoveLocation(loc)
set loc = null
endfunction
private function PeonBuy takes integer playerid, boolean havepeon returns nothing
if havepeon == true then
if target_shop_AmmoDump[playerid] != null then
if IsUnitInRange(unit_peon_buyer[playerid],target_shop_AmmoDump[playerid],250.) then
if type_melee_tower[playerid] != 0 then
set unit_peon_towerbuilder[playerid] = unit_peon_buyer[playerid]
endif
set unit_peon_buyer[playerid] = null
endif
if num_zeppelin[playerid] < 2 then
call IssueNeutralImmediateOrderById(Player(playerid),target_shop_AmmoDump[playerid],UnitType_zeppelin)
endif
if num_IronGolem[playerid] < 1 then
call IssueNeutralImmediateOrderById(Player(playerid),target_shop_AmmoDump[playerid],UnitType_TronGloem)
endif
endif
if UnitType_GetSoldUnit != 0 and Unit_GetSoldShop[playerid] != null then
call IssueNeutralImmediateOrderById(Player(playerid),Unit_GetSoldShop[playerid],UnitType_GetSoldUnit)
if IsUnitInRange(unit_peon_buyer[playerid],Unit_GetSoldShop[playerid],250.) then
if type_melee_tower[playerid] != 0 then
set unit_peon_towerbuilder[playerid] = unit_peon_buyer[playerid]
endif
set unit_peon_buyer[playerid] = null
endif
endif
endif
endfunction
private function MeleeHerosBuyItems takes unit hero,integer id,real x,real y returns nothing
local item Item = null
local group G = CreateGroup()
local unit u = null
local unit shop = null
local integer typeitem
call GroupEnumUnitsInRange(G,x,y,400.0,null)
loop
set u = FirstOfGroup(G)
if GetUnitState(u,UNIT_STATE_LIFE) > 0.41 then
if GetUnitAbilityLevel(u,'Apit') > 0 then
set shop = u
endif
endif
call GroupRemoveUnit(G,u)
exitwhen u == null
endloop
call DestroyGroup(G)
if shop != null then
set typeitem = Item_stwp
set Item = GetItemOfTypeFromUnit(hero,typeitem)
if GetItemCharges(Item) < 1 then
call HeroBuyItem(hero,id,shop,typeitem)
endif
set typeitem = Item_pnvl
set Item = GetItemOfTypeFromUnit(hero,typeitem)
if GetItemCharges(Item) < 1 then
call HeroBuyItem(hero,id,shop,typeitem)
endif
set typeitem = Item_ssan
if GetItemNumOfItemType(hero,typeitem) < 1 then
call HeroBuyItem(hero,id,shop,typeitem)
endif
set typeitem = Item_spre
if GetItemNumOfItemType(hero,typeitem) < 1 then
call HeroBuyItem(hero,id,shop,typeitem)
endif
if b_invisible_enemy[id] == true then
set typeitem = Item_dust
set Item = GetItemOfTypeFromUnit(hero,typeitem)
if GetItemCharges(Item) < 1 then
call HeroBuyItem(hero,id,shop,typeitem)
endif
endif
endif
set Item = null
set u = null
set G = null
set shop = null
endfunction
private function Melee_Heros_Loop takes unit hero,integer id,real x,real y,real dis,real en,real an,unit eu,unit au,real wehp,real ang,integer ui returns nothing
local real level = I2R(GetHeroLevel(hero))
local real treehp = 0.0
local group G = null
local unit u = null
//if en < 1. then
//call MeleeHeroFindShop(hero,id,ui)
//endif
call MeleeHerosBuyItems(hero,id,x,y)
if AttackTree == true then
set tree = null
call EnumDestructablesXY(GetRandomReal(256.,768.),x,y,false,function GainTree)
set treehp = GetDestructableLife(tree)
if treehp > 0. and IsDestructablesTree(tree) == false then
call Unit_RemoveAI(hero,ui,3.0)
set G = CreateGroup()
call GroupEnumUnitsInRange(G,x,y,400.0,null)
loop
set u = FirstOfGroup(G)
if GetUnitState(u,UNIT_STATE_LIFE) > 0.41 and GetOwningPlayer(u) == Player(id) then
if IsUnitSpelling(u) == false and IsUnitType(u, UNIT_TYPE_PEON) == false then
call IssueTargetOrder( u, "attack", tree )
endif
endif
call GroupRemoveUnit(G,u)
exitwhen u == null
endloop
call DestroyGroup(G)
endif
endif
if int_buyitemHome > 7 then
if dis < 500.0 and melee_ai_shops[id] != null then
call IssueTargetOrder( hero, "smart", melee_ai_shops[id] )
call Unit_RemoveAI(hero,ui,5.0)
endif
endif
if IsUnitSpelling(hero) == false then
if en > 1. and (en - an > 2. or an > 2.) then
call OrderUnitMoveXY(hero,x,y,600.0,ang+GetRandomReal(-0.15,0.15))
endif
if eu != null then
if wehp < 50. + 15. * level + an * 5. then
call IssueTargetOrder( hero, "smart", eu )
endif
endif
if au != null and en > 0. then
call IssueTargetOrder( hero, "attack", au )
endif
endif
if IsUnitBackpackFull(hero) == false then
call HeroPickItem(hero,x,y)
endif
set u = null
set G = null
endfunction
private function ai_Units_Loop takes nothing returns nothing
local integer i = Top_Units[id_timer_player]
local real x = 0.0
local real y = 0.0
local real x0 = 0.0
local real y0 = 0.0
local integer unitid = 0
local real unitHP = 0.0
local real unitHPmax = 0.0
local real unitHPpercent = 0.0
local unit u = null
local group G = null
local real hp = 0.0
local real hpmax = 0.0
local real hpPercent = 0.0    
local integer actindex = 0
local real hptest = 0.0
local unit AIunit = null
local real dis_fromhome = 0.0
local real hpmin = 2000.0
local unit weakEnemyUnit = null
local unit weakAllyUnit = null
local real power_enemy = 0.0
local real power_ally = 0.0
local boolean retreat = false
local real sum_x = 0.0
local real sum_y = 0.0
local real ang_enemy = -1.0
local boolean spelling = false
local real num_enemy = 0.0
local boolean avoid = false
local integer ramInt = 1
local boolean peon = false
local unit transport = null
local boolean canbuy = false
local unit array townhall
local integer num_townhall = 0
local integer n = 0
local boolean IsZeppelin = false
local boolean haveorder = false
local integer orderid = 0
local location orderpoint = null
local boolean hero = false
local real transport_dismin = 200.0
local real num_tower = 0.0
local unit tower_undead = null
local unit tower_human = null
local real dis_nearEnemyHome = 5000.0
local unit structrue = null
local integer e_pid = 0
local boolean have_invisible = false
local item Item = null
//call BJDebugMsg(I2S(i))
call ClearTownHallNum()
set actindex = id_timer_player * max_array_units
set G = CreateGroup()
loop
exitwhen i < 0
set unitid = actindex + i
set hptest = 0.
set hptest = GetUnitState(ai_units[unitid], UNIT_STATE_LIFE)
if hptest < 0.40 then
if IsUnitType(ai_units[unitid], UNIT_TYPE_HERO) == false then
call Pop_ai_Units(id_timer_player,i)
else
if IsUnitTransportation(ai_units[unitid]) == true then
set num_zeppelin[id_timer_player] = num_zeppelin[id_timer_player] - 1
elseif GetUnitTypeId(ai_units[unitid]) == UnitType_TronGloem then
set num_IronGolem[id_timer_player] = num_IronGolem[id_timer_player] - 1
endif
endif
else
set AIunit = ai_units[unitid]
if IsUnitType(AIunit, UNIT_TYPE_STRUCTURE) == false then
set x = GetUnitX(AIunit)
set y = GetUnitY(AIunit)
set x0 = GetLocationX(loc_startLoc[id_timer_player])
set y0 = GetLocationY(loc_startLoc[id_timer_player])
set unitHP = GetUnitState(AIunit,UNIT_STATE_LIFE)
set unitHPmax = GetUnitState(AIunit,UNIT_STATE_MAX_LIFE)+1.0
set unitHPpercent = unitHP/unitHPmax*1.0
set retreat = false
set sum_x = 0.0
set sum_y = 0.0
set power_enemy = 0.0
set power_ally = 0.0
set weakEnemyUnit = null
set weakAllyUnit = null
set u = null
set spelling = IsUnitSpelling(AIunit)
set num_enemy = 0.0
set dis_fromhome = 0.0
set avoid = false
set peon = IsUnitInGroup(AIunit, group_peons)
set transport = null
set IsZeppelin = IsUnitTransportation(AIunit)
set haveorder = true
set orderid = GetUnitCurrentOrder(AIunit)
set hero = IsUnitType(AIunit, UNIT_TYPE_HERO)
set num_tower = 0.0
set dis_nearEnemyHome = 5000.0
set structrue = null
set have_invisible = false
if orderid == 0 then
set haveorder = false
endif
if x - unit_LastX[unitid] > -150. and x - unit_LastX[unitid] < 150. /*
*/ and y - unit_LastY[unitid] > -150. and y - unit_LastY[unitid] < 150. then
if (IsZeppelin == true or orderid == 851986) and IsUnitLoaded(AIunit) == false then
set int_unit_blocked[unitid] = int_unit_blocked[unitid] + 1 
endif
else
set int_unit_blocked[unitid] = 0
endif

if int_unit_blocked[unitid] > 6 then
if IsZeppelin == true then
call IssuePointOrderLoc(AIunit,"unloadall",loc_startLoc[id_timer_player])
endif
if int_unit_blocked[unitid] == 10 and hero == true then
call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Human\\MassTeleport\\MassTeleportCaster.mdl",x,y))
call SetUnitX(AIunit,GetLocationX(loc_startLoc[id_timer_player]))
call SetUnitY(AIunit,GetLocationY(loc_startLoc[id_timer_player]))
call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Human\\MassTeleport\\MassTeleportTarget.mdl",AIunit,"origin"))
endif
endif
set unit_LastX[unitid] = x
set unit_LastY[unitid] = y

if b_onlyoneEnemy[id_timer_player] == true then
if spelling == false and peon == false and IsUnitInGroup(AIunit,group_final_attack) == false then
call Unit_RemoveAI(AIunit,unitid,30.0)
call IssuePointOrderLoc( AIunit, "attack", loc_enemy_targetLoc[id_timer_player] )
call GroupAddUnit(group_final_attack,AIunit)
endif
endif

call GroupEnumUnitsInRange(G,x,y,600.0,null)
loop
set u=FirstOfGroup(G)
set hp = 0.0
set hp = GetUnitState(u,UNIT_STATE_LIFE)
if hp > 0.41 then
set hpmax = GetUnitState(u,UNIT_STATE_MAX_LIFE)
set hpPercent = hp/hpmax*1.0
if IsUnitEnemy(u,Player(id_timer_player)) == true then
if IsUnitType(u, UNIT_TYPE_PEON) == false then
set power_enemy = power_enemy + 1.0
set sum_x = sum_x + GetUnitX(u)
set sum_y = sum_y + GetUnitY(u)
if IsUnitInvisible(u, Player(id_timer_player)) == true then
set have_invisible = true
set b_invisible_enemy[id_timer_player] = true
endif
if IsUnitType(u, UNIT_TYPE_STRUCTURE) == true then
set structrue = u
if IsUnitType(u, UNIT_TYPE_RANGED_ATTACKER) == true then
set num_tower = num_tower + 1.0
endif
endif
endif
if hp < hpmin and hpPercent < unitHPpercent + 0.1 /*
*/ and IsUnitIllusion(u) == false and GetUnitAbilityLevel(u,Buff_sleep) < 1 then
set hpmin = hp
set weakEnemyUnit = u
endif
else
if IsUnitType(u, UNIT_TYPE_PEON) == false and IsUnitType(u, UNIT_TYPE_STRUCTURE) == false then
set power_ally = power_ally + 1.0
endif
if hpPercent < 0.2 and hp < 50. and GetOwningPlayer(u) == Player(id_timer_player) then
set weakAllyUnit = u
endif
endif                
endif
call GroupRemoveUnit(G,u)
exitwhen u == null
endloop
call GroupClear(G)
set power_enemy = power_enemy + num_tower
set num_enemy = power_enemy

if hero == true then
set unitHPpercent = unitHPpercent * 0.85
if have_invisible == true then
set Item = GetItemOfTypeFromUnit(AIunit,Item_dust)
if GetItemCharges(Item) > 0 then
call UnitUseItem( AIunit, Item )
endif
endif
endif

if peon == true then
set unitHPpercent = unitHPpercent * 0.7
if GetUnitTypeId(AIunit) == UnitType_TronGloem then
set dis_fromhome = DistanceBetweenXY(x,x0,y,y0)
if dis_fromhome < 1800. then
if GetRandomInt(1,10) == 1 then
call IssueImmediateOrderById( AIunit, 852022 )
endif
endif
endif
if haveorder == false or orderid == 852020 then
if GetUnitState(unit_peon_buyer[id_timer_player],UNIT_STATE_LIFE) < 0.4 /*
*/ and GetUnitTypeId(AIunit) != UnitType_TronGloem then
set unit_peon_buyer[id_timer_player] = AIunit
else
endif
else

endif
endif
if IsZeppelin == true then
if GetUnitState(unit_transport[id_timer_player],UNIT_STATE_LIFE) < 0.4 then
set unit_transport[id_timer_player] = AIunit
else
if unitHPpercent < 0.35 then
set transport_dismin = 999999.
endif
endif
else
if unit_transport[id_timer_player] != null then
set transport = unit_transport[id_timer_player]
if int_transport[id_timer_player] > 0 then
if IsUnitLoaded(AIunit) == false and num_enemy == 0. /*
*/ and spelling == false and peon == false then

if loc_hero_orderLoc[id_timer_player] != null then
set orderpoint = loc_hero_orderLoc[id_timer_player]
if DistanceBetweenXY(x,GetLocationX(orderpoint),y,GetLocationY(orderpoint)) > 1800. /*
*/ and IsUnitInRange(AIunit,transport,1200.) == true then
call RemoveGuardPosition( transport )
call Unit_RemoveAI(AIunit,unitid,3.0)
call IssueTargetOrder( AIunit, "smart", transport )
call TimerStart(timer_transport[id_timer_player],1.0,false,function Transport_Timer)
endif
endif
endif
endif
endif
endif


if power_enemy > power_ally then
set power_enemy = power_enemy * 2.0 - power_ally
endif


if unitHPpercent < 0.25+power_enemy*0.03 then
if num_enemy > 0.0 then
set sum_x = sum_x / num_enemy
set sum_y = sum_y / num_enemy
set ang_enemy = RadianBetweenXY(sum_x,x,sum_y,y)
if dis_nearEnemyHome > 1800. then
call OrderUnitMoveXY(AIunit,x,y,600.0+50.0/unitHPpercent,ang_enemy)
else
call IssuePointOrderLoc( AIunit, "move", loc_startLoc[id_timer_player] )
endif
if GetRandomInt(1,2) == 1 then
set avoid = true
endif
endif
if structrue != null then
set e_pid = GetPlayerId(GetOwningPlayer(structrue))
set dis_nearEnemyHome = DistanceBetweenXY(x,GetLocationX(loc_startLoc[e_pid]),y,GetLocationY(loc_startLoc[e_pid]))
endif
if unitHP < 100.+power_enemy*(10.+power_enemy*2.) and unitHPpercent < 0.25+power_enemy*0.01 or num_tower > 5. then
set retreat = true
endif
endif

if peon == false and IsZeppelin == false /*
*/ and b_unit_guardPos[unitid] == true /*
*/ and spelling == false and retreat == false then
if weakEnemyUnit != null and avoid == false then
call IssueTargetOrder( AIunit, "smart", weakEnemyUnit )
endif
if weakAllyUnit != null and num_enemy > 0.0 then
call IssueTargetOrder( AIunit, "attack", weakAllyUnit )
endif
endif

if hero == true then
set dis_fromhome = DistanceBetweenXY(x,x0,y,y0)
call Melee_Heros_Loop(AIunit,id_timer_player,x,y,dis_fromhome,num_enemy,power_ally,weakEnemyUnit,weakAllyUnit,hp,ang_enemy,unitid)
endif



if retreat == true then
if dis_fromhome == 0.0 then
set dis_fromhome = DistanceBetweenXY(x,x0,y,y0)
endif
call Unit_RemoveAI(AIunit,unitid,1.0/unitHPpercent+num_tower)
if dis_fromhome > 400.0 then
if power_enemy > 2.0 and dis_nearEnemyHome > 1800. then
call OrderUnitMoveXY(AIunit,x,y,1800.0,ang_enemy)
else
call IssuePointOrderLoc( AIunit, "move", loc_startLoc[id_timer_player] )
endif
endif
endif
           
else
if IsUnitType(AIunit,UNIT_TYPE_TOWNHALL) == false then
call IssuePointOrderLoc(AIunit, "setrally", loc_rallyLoc[id_timer_player] )
if GetUnitTypeId(AIunit) == Ut_utw1 then
set tower_undead = AIunit
elseif GetUnitTypeId(AIunit) == Ut_htw1 then
set tower_human = AIunit
endif
else
set num_townhall = num_townhall + 1
set townhall[num_townhall] = AIunit
call SetTownHallTypeNum(AIunit,id_timer_player)
endif 
endif
endif
set i = i - 1
endloop
call DestroyGroup(G)
if orderpoint != null and transport != null then
if DistanceBetweenXY(GetUnitX(transport),GetLocationX(orderpoint),GetUnitY(transport),GetLocationY(orderpoint)) < transport_dismin then
call RecycleGuardPosition(transport)
set b_transport_getTarget[id_timer_player] = false
call IssuePointOrderLoc( transport, "move", loc_startLoc[id_timer_player] )
call IssuePointOrder(transport,"unloadall",GetUnitX(transport),GetUnitY(transport))
endif
endif
set n = 1
loop
exitwhen n > num_townhall
call UpgradeTownHall(townhall[n],id_timer_player)
set n = n + 1
endloop
if GetUnitState(unit_peon_buyer[id_timer_player],UNIT_STATE_LIFE) > 0.41 then
set canbuy = true
endif
if tower_undead != null then
if GetPlayerGold(Player(id_timer_player)) > 600 and GetPlayerWood(Player(id_timer_player)) > 200 then
if GetRandomInt(1,4) == 1 then
call IssueImmediateOrderById( tower_undead, Ut_utw3 )
else
call IssueImmediateOrderById( tower_undead, Ut_utw2 )
endif
endif
endif
if tower_human != null then
if GetPlayerGold(Player(id_timer_player)) > 600 and GetPlayerWood(Player(id_timer_player)) > 200 then
if GetRandomInt(1,2) == 1 then
call IssueImmediateOrderById( tower_undead, Ut_htw2 )
endif
endif
endif
call PeonBuy(id_timer_player,canbuy)
if unit_peon_towerbuilder[id_timer_player] != null then
call PeonBuildTower(id_timer_player)
endif
if int_transport[id_timer_player] > 35 then
set int_transport[id_timer_player] = 0
else
set int_transport[id_timer_player] = int_transport[id_timer_player] + 1
endif
set id_timer_player = id_timer_player+1
if id_timer_player > 11 then
set id_timer_player = 0
set int_buyitemHome = int_buyitemHome + 1
endif
if int_buyitemHome > 10 then
set int_buyitemHome = 0
endif
set u = null
set AIunit = null
set weakEnemyUnit = null
set weakAllyUnit = null
set transport = null
set G = null
set orderpoint = null
set tower_undead = null
set tower_human = null
set structrue = null
set Item = null
endfunction
private function IsEnemyAroundUnit takes unit target, integer playerid returns boolean
local unit u = null
local group g = CreateGroup()
local boolean b = false
call GroupEnumUnitsInRange(g, GetUnitX(target), GetUnitY(target) ,500.0, null)
loop
set u = FirstOfGroup(g)
exitwhen u == null
if IsUnitEnemy(u,Player(playerid)) == true and GetUnitState(u,UNIT_STATE_LIFE) > 0. /*
*/ and IsUnitHidden(u) == false then
set b = true
endif
call GroupRemoveUnit(g,u)
endloop
call DestroyGroup(g)
set u = null
set g = null
return b
endfunction
private function PeonFindShop takes integer playerid, integer enemyid returns nothing
local integer n = 1
local real dismin = 20000.0
local real dis = 0.0
local unit buyer = null
local unit shop = null
local group g = null
local unit u = null
if unit_peon_buyer[playerid] != null then
set buyer = unit_peon_buyer[playerid]
set n = 1
loop
exitwhen n > natural_max_AmmoDump
set dis = DistanceBetweenUnits(buyer,natural_shop_AmmoDump[n])
if dis < dismin and IsEnemyAroundUnit(natural_shop_AmmoDump[n],playerid) == false then
set dismin = dis
set shop = natural_shop_AmmoDump[n]
endif
set n = n + 1
endloop
if shop != null then
set target_shop_AmmoDump[playerid] = shop
call IssueTargetOrder( buyer, "smart", shop )
endif
if Unit_GetSoldShop[playerid] != null then
if GetRandomInt(1,1) == 1 or shop == null then
set dismin = 20000.0
set dis = 0.0
set g = CreateGroup()
call GroupEnumUnitsOfPlayer(g,Player(15),null)
loop
set u = FirstOfGroup(g)
exitwhen u == null 
if GetUnitTypeId(u) == GetUnitTypeId(Unit_GetSoldShop[playerid]) then
set dis = DistanceBetweenUnits(buyer,u)
if dis < dismin and IsEnemyAroundUnit(u,playerid) == false then
set dismin = dis
set Unit_GetSoldShop[playerid] = u
endif
endif
call GroupRemoveUnit(g,u)
endloop
call DestroyGroup(g)
call IssueTargetOrder( buyer, "smart", Unit_GetSoldShop[playerid] )
endif
else
if shop == null and type_melee_tower[playerid] != 0 /*
*/ and GetPlayerGold(Player(playerid)) > 1500 and GetPlayerWood(Player(playerid)) > 500 then
set unit_peon_towerbuilder[playerid] = unit_peon_buyer[playerid]
set buyer = unit_peon_towerbuilder[playerid]
if GetRandomInt(1,2) == 1 or enemyid == 0 then
call IssuePointOrder(buyer,"move",GetRandomReal(-2500.,2500.),GetRandomReal(-2500.,2500.))
else
call IssuePointOrderLoc(buyer,"move",loc_startLoc[enemyid])
endif
endif
endif
endif
set buyer = null
set shop = null
set g = null
set u = null
endfunction
private function PlayerFindEnemyStructrue takes integer pid, integer targetid returns nothing
local group g = null
local unit u = null
local integer num_enemy_structure = 0
set g = CreateGroup()
call GroupEnumUnitsInRange(g,800.,GetLocationX(loc_startLoc[targetid]),GetLocationY(loc_startLoc[targetid]),null)
loop
set u = FirstOfGroup(g)
exitwhen u == null 
if IsUnitType(u, UNIT_TYPE_STRUCTURE) == true and IsUnitEnemy(u,Player(pid)) == true then
set num_enemy_structure = num_enemy_structure + 1
endif
call GroupRemoveUnit(g,u)
endloop
call DestroyGroup(g)
if num_enemy_structure < 1 then
set g = CreateGroup()
call GroupEnumUnitsOfPlayer(g,Player(targetid),null)
loop
set u = FirstOfGroup(g)
exitwhen u == null 
if IsUnitType(u, UNIT_TYPE_STRUCTURE) == true then
set loc_enemy_targetLoc[pid] = GetUnitLoc(u)
set loc_startLoc[targetid] = GetUnitLoc(u)
endif
call GroupRemoveUnit(g,u)
endloop
call DestroyGroup(g)
endif
set u = null
set g = null
endfunction
private function PlayerConsciousness takes nothing returns nothing
local integer  index = 0
local group g = null
local unit u = null
local boolean HaveStrongEnemy = false
local player player_ally = null
local player p = Player(int_player_con)
local integer  n = 0
local integer  enemy = 0
local integer array enemyplayerid
local integer targetid = 0
local integer  ally = 0
if Melee_AI_On[int_player_con] == true and b_player_loser[int_player_con] == false then
set b_melee_herobuy[int_player_con] = true
loop
exitwhen index > 11
if GetPlayerSlotState(Player(index)) == PLAYER_SLOT_STATE_PLAYING then
if IsPlayerEnemy(p,Player(index)) == true then 
if GetPlayerStructureCount(Player(index), true) > 0 then
set enemy = enemy + 1
set enemyplayerid[enemy] = index
if GetPlayerGold(Player(index)) > 800 and GetPlayerFoodUsed(Player(index)) > 50 then
set HaveStrongEnemy = true
endif
endif
else
if p != Player(index) and b_player_loser[index] == false then
set player_ally = Player(index)
if GetPlayerStructureCount(Player(index), true) > 0 and GetPlayerFoodUsed(Player(index)) > 50 then
set ally = ally + 1
endif
endif
endif
endif
set index = index + 1
endloop
if enemy > 0 then
set targetid = enemyplayerid[GetRandomInt(1,enemy)]
set loc_enemy_targetLoc[int_player_con] = loc_startLoc[targetid]
if enemy == 1 and ally > 0 then
if GetPlayerFoodUsed(p) > 70 - (ally * 3) then
set b_onlyoneEnemy[int_player_con] = true
call PlayerFindEnemyStructrue(int_player_con,targetid)
elseif GetPlayerFoodUsed(p) < 30 then
set b_onlyoneEnemy[int_player_con] = false
endif
endif
endif
if GetPlayerGold(p) > 500 and GetPlayerWood(p) > 150 and GetPlayerFoodUsed(p) > 30 then
call PeonFindShop(int_player_con,targetid)
endif
if HaveStrongEnemy == true /*
*/ and (GetPlayerGold(p) < 500 and GetPlayerFoodUsed(p) < 10) or GetPlayerFoodUsed(p) < 2 then
set g = CreateGroup()
call GroupEnumUnitsOfPlayer(g,p,null)
loop
set u = FirstOfGroup(g)
exitwhen u == null 
call KillUnit(u)
call GroupRemoveUnit(g,u)
endloop
call DestroyGroup(g)
set n = 0
loop
exitwhen n > 7
call KillUnit(test_block_buildings[int_player_con][n])
set n = n + 1
endloop
set b_player_loser[int_player_con] = true
if player_ally != null then
call PlayerDivertsResources(p,player_ally,GetPlayerGold(p),GetPlayerWood(p)) 
endif
endif
endif
set int_player_con = int_player_con + 1
if int_player_con > 11 then
set int_player_con = 0
endif
set u = null
set g = null
endfunction
private function MeleeAiSettings takes nothing returns nothing
local integer i = 0
local real ang = 0.0
local real x = 0.0
local real y = 0.0
local group g = null
local unit u = null
local unit goldmine = null
local unit townhall = null
local unit testunit = null
local real n = 0.0
call DestroyTimer(GetExpiredTimer())
loop
exitwhen i > 11
if loc_startLoc[i] != null and Melee_AI_On[i] == true then
set x = GetLocationX(loc_startLoc[i])
set y = GetLocationY(loc_startLoc[i])
set y = 0.0
set g = CreateGroup()
call GroupEnumUnitsInRangeOfLoc(g, loc_startLoc[i], 1200.0, null)
loop
set u = FirstOfGroup(g)
if GetUnitAbilityLevel(u, 'Agld') > 0 then
set goldmine = u
endif
if GetOwningPlayer(u) == Player(i) then    
if IsUnitType(u,UNIT_TYPE_STRUCTURE)==true and IsUnitType(u,UNIT_TYPE_TOWNHALL)==true then
set townhall = u
endif
endif
call GroupRemoveUnit(g,u)
exitwhen u == null
endloop
call GroupClear(g)
call DestroyGroup(g)
if townhall != null and goldmine != null then
set ang = RadianBetweenUnits(goldmine,townhall)
set x = GetUnitX(townhall)
set y = GetUnitY(townhall)
set n = 0.0
if UnitType_build_block != 0 then
loop
exitwhen n > 7.0
set testunit = CreateUnit(Player(13),UnitType_build_block,x+500.*Cos(n*0.785),y+500.*Sin(n*0.785),0.)
call SetUnitX(testunit,map_max_X)
call SetUnitY(testunit,map_max_Y)
call PauseUnit(testunit,true)
call SetUnitInvulnerable( testunit, true )
call CancelUnitMoveAndAttack(testunit)
set test_block_buildings[i][R2I(n)] = testunit
set n = n + 1.0
endloop
endif
set x = x + 200. * Cos(ang)
set y = y + 200. * Sin(ang)
endif
set loc_rallyLoc[i] = Location(x,y)
endif    
set i = i + 1
endloop    
set g = CreateGroup()
call GroupEnumUnitsOfPlayer(g,Player(15),null)
loop
set u = FirstOfGroup(g)
exitwhen u == null 
if GetUnitTypeId(u) == UnitType_AmmoDump then
set natural_max_AmmoDump = natural_max_AmmoDump + 1
set natural_shop_AmmoDump[natural_max_AmmoDump] = u
endif
if GetUnitAbilityLevel(u,'Apit') > 0 then
set natural_max_Merchant = natural_max_Merchant + 1
set natural_shop_Merchant[natural_max_Merchant] = u
endif
call GroupRemoveUnit(g,u)
endloop
call DestroyGroup(g)    
set g = null
set u = null
set goldmine = null
set townhall = null
set testunit = null
endfunction

public function melee_ai_Init takes nothing returns nothing
local integer i = 0
loop
exitwhen i > 15
set b_player_loser[i] = false
set unit_transport[i] = null
set int_transport[i] = 0
set unit_peon_buyer[i] = null
set target_shop_AmmoDump[i] = null
set num_zeppelin[i] = 0
set num_IronGolem[i] = 0
set Unit_GetSoldShop[i] = null
set loc_hero_orderLoc[i] = null
set timer_transport[i] = null
set b_transport_getTarget[i] = false
set type_unit_siege[i] = 0
set type_melee_tower[i] = 0
set unit_peon_towerbuilder[i] = null
set loc_enemy_targetLoc[i] = null
set b_onlyoneEnemy[i] = false
set b_invisible_enemy[i] = false
set b_melee_herobuy[i] = false
set Top_Units[i] = -1
if GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING then
set loc_startLoc[i] = GetStartLocationLoc(GetPlayerStartLocation(Player(i)))
if Melee_AI_On[i] == true then
set timer_transport[i] = CreateTimer()
call SetPlayerName( Player(i), ( "[EggStrAI]" + GetPlayerName(Player(i)) ) )
endif
endif
set i = i + 1
endloop
call TriggerAddAction(MeleeHero_Attacked_Trg,function MeleeHeroAttacked)
call TimerStart(CreateTimer(),1.73/12.0,true,function ai_Units_Loop)
call TimerStart(CreateTimer(),0.5,true,function NoAIUnits_Loop)
call TimerStart(CreateTimer(),1.0,false,function MeleeAiSettings)
call TimerStart(CreateTimer(),23.3/12.0,true,function PlayerConsciousness)
endfunction
public function SetAIplayer takes player p, boolean b returns nothing
if GetPlayerSlotState(p) == PLAYER_SLOT_STATE_PLAYING and GetPlayerController(p) == MAP_CONTROL_COMPUTER then
set Melee_AI_On[GetPlayerId(p)] = b
endif
endfunction
//RPG AI__
globals
private unit array ai_hero
private integer Top_ai_hero = -1
private player CreepPlayer = Player(PLAYER_NEUTRAL_AGGRESSIVE)
private group group_creepcamp = CreateGroup()
private group array groups_camg
private location array loc_min_camg
private group group_AI_hero = CreateGroup()
private integer Top_creepcamp = -1
private boolean array b_ai_MF
private location array loc_ai_retreat
private boolean array b_ai_retreat
private real array hp_ai_retreat
private boolean array b_ai_pickItem
private group array group_AI_herounits 
private location ai_attacktargetloc
private integer ai_attacktargetgroup
private boolean array b_creeps_canattack
private boolean array b_ai_havetarget
private integer array creeps_level
private integer array mf_max_level
private boolean array b_can_atk_camg[11][500]
private trigger hero_attacked_trigger = CreateTrigger()
private boolean array hero_evade_boolean
private timer array hero_evade_timer
private boolean array b_attack_ally
private boolean array b_attack_weakunit
private group group_evade = CreateGroup()
private unit array hero_testunit_attack
private location array ai_hero_targetloc
private boolean array b_ai_attacktarget
private integer open_ai = 0
private real HPmin_hero_attack
private real MANAmin_hero_attack
endglobals
//
function GetEnemyArmyAngle takes unit u0,integer min returns real
local unit u
local real i = 0.0
local real a = 0.0
local real angle = 0.0
local integer n = 0
local integer max = 0
local group g = CreateGroup() 
local player p = GetOwningPlayer(u0)
local real x = GetUnitX(u0)
local real y = GetUnitY(u0)
loop
exitwhen i > 7.0
set a = 45.0*i
call GroupEnumUnitsInRange(g,x+450.0*Cos(a*bj_DEGTORAD),y+450.0*Sin(a*bj_DEGTORAD),300.00,null)
set n = 0
loop
set u = FirstOfGroup(g)
if u!=null and IsUnitType(u,UNIT_TYPE_DEAD)==false and IsUnitEnemy(u,p)==true then
set n = n + 1
endif
call GroupRemoveUnit(g,u)
exitwhen u == null
endloop
if max < n then
set max = n
set angle = a
endif   
set i = i + 1.0
call GroupClear(g)
endloop
call DestroyGroup(g)
set g = null
set u = null
set p = null
if max == 0 or max <= min then
set angle = -1.0
endif
return angle
endfunction
//
private function GetAiHeroID takes unit hero returns integer
local integer i = Top_ai_hero
local integer ID = -1
loop
exitwhen i < 0 or ID > -1
if hero==ai_hero[i] then
set ID = i
endif
set i = i - 1
endloop
return ID
endfunction

private function HeroUnitsGroup takes nothing returns nothing
call IssuePointOrderLoc(GetEnumUnit(), "attack", ai_attacktargetloc )
endfunction
private function CanAttackCreeps takes unit hero, integer id, integer cn returns boolean
local boolean b = false
local unit u = FirstOfGroup(groups_camg[cn])
local player p = GetOwningPlayer(hero)
local integer i = GetPlayerId(p)
call SetUnitOwner( hero_testunit_attack[id], p, true )
if u != null then
if IsUnitVisible(u, p) == true then
if IssueTargetOrder(hero_testunit_attack[id], "smart", u ) then
set b_can_atk_camg[i][cn] = true
call IssueImmediateOrder(hero_testunit_attack[id], "stop")
else
set b_can_atk_camg[i][cn] = false
endif
elseif IsUnitInRange(hero,u,800.) == true then
set b_can_atk_camg[i][cn] = false
endif
else
set b_can_atk_camg[i][cn] = false
endif
call SetUnitOwner( hero_testunit_attack[id], Player(15), true )
set u = null
set p = null
return b_can_atk_camg[i][cn] 
endfunction
private function CheckHeroAttackTarget takes integer i,real HPpercent returns nothing
if HPpercent > hp_ai_retreat[i] and ai_hero_targetloc[i] != null then
call GroupClearDeadUnits(group_AI_herounits[i])
set ai_attacktargetloc = ai_hero_targetloc[i]
call ForGroup( group_AI_herounits[i] , function HeroUnitsGroup )
set b_ai_havetarget[i] = true
endif
endfunction
private function CheckHeroMf takes integer i,real HPpercent returns nothing
local integer cn = 0
local real x0 = 0.0
local real y0 = 0.0
local real x1 = 0.0
local real y1 = 0.0
local real dis = 0.0
local real dismin = 0.0
local integer herolevel = 0
local location target = null
local unit u  = null
set x0 = GetUnitX(ai_hero[i])
set y0 = GetUnitY(ai_hero[i])
set cn = 0
set dismin = 80000.0
set herolevel = GetHeroLevel(ai_hero[i])
if HPpercent > hp_ai_retreat[i]*0.9 then
loop
exitwhen cn > Top_creepcamp
set x1 = GetLocationX(loc_min_camg[cn])
set y1 = GetLocationY(loc_min_camg[cn])
set dis = DistanceBetweenXY(x0,x1,y0,y1)
if groups_camg[cn] != null /* 
*/ and loc_min_camg[cn] != null /* 
*/ and creeps_level[cn] < herolevel + mf_max_level[i] /* 
*/ and CanAttackCreeps(ai_hero[i],i,cn) == true /* 
*/ and GroupCountUnitsRemoveDead(groups_camg[cn]) > 0 /* 
*/ and dis < dismin then
set dismin = dis
set target = loc_min_camg[cn]
endif
set cn = cn + 1
endloop
if target != null then
call GroupClearDeadUnits(group_AI_herounits[i])
set ai_attacktargetloc = target
set ai_attacktargetgroup = cn
call ForGroup( group_AI_herounits[i] , function HeroUnitsGroup )
set b_ai_havetarget[i] = true
endif
endif
set target = null
set u = null
endfunction
private function SetEvadeBoolean takes nothing returns nothing
local integer id = 0
local integer e = 0
loop
exitwhen id > Top_ai_hero or e == 1
if hero_evade_timer[id] == GetExpiredTimer() then
set hero_evade_boolean[id] = true
set e = 1
endif
set id = id + 1
endloop
endfunction
private function AiHeroAttacked takes nothing returns nothing
local unit hero = GetTriggerUnit()
local integer id = GetAiHeroID(hero)
local group G = null
local unit u = null
local integer n = 0
local real EnemyN = 0.
local real dis = 256.
if hero_evade_boolean[id] == true then
set G=CreateGroup()
call GroupEnumUnitsInRange(G,GetUnitX(hero),GetUnitY(hero),600.0,null)
loop
set u=FirstOfGroup(G)
if IsUnitType(u,UNIT_TYPE_DEAD)==false and u!=null and IsUnitEnemy(u,GetOwningPlayer(hero))==true then
set n = n + 1
if GetOwningPlayer(u) != CreepPlayer then
set EnemyN = EnemyN + 1.
endif
endif     
call GroupRemoveUnit(G,u)
exitwhen u==null
endloop
call GroupClear(G)
call DestroyGroup(G)
if n > 1 then
if IsUnitSpelling(hero) == false then
if IsUnitType(GetAttacker(), UNIT_TYPE_STRUCTURE) == true then
set EnemyN = EnemyN + 2.
set dis = 800.
endif
call OrderUnitMoveAng(hero,dis,AngleBetweenUnits(GetAttacker(),hero))
endif
if EnemyN > 5. then
set EnemyN = 5.
endif
call TimerStart(hero_evade_timer[id],6.5,false,function SetEvadeBoolean)
set hero_evade_boolean[id] = false
if IsUnitInGroup(hero,group_evade)==false then
call GroupAddUnit(group_evade,hero)
endif
endif
endif
set u = null
set G = null
set hero = null
endfunction
private function AiHeroAttackWeakUnit takes unit hero,real x,real y,player p,group G,integer id returns nothing
local unit u = null
local real HPmin = 5000.0
local unit weakEnemy = null
local unit weakHero = null
local unit weakAlly = null
local real uHP = 0.0
local real uHPmax = 0.0
local real uHPpercent = 0.0 
local real attack_dis = 800.0
local real level = I2R(GetHeroLevel(hero))
local boolean b = false
local integer EnemyheroN = 0
if IsUnitType(hero,UNIT_TYPE_MELEE_ATTACKER)==true then
set attack_dis = 400.0
endif
call SetUnitOwner( hero_testunit_attack[id], p, true )
loop
set b = false
set u = FirstOfGroup(G)
set uHP = GetUnitState(u,UNIT_STATE_LIFE)
set uHPmax = GetUnitState(u,UNIT_STATE_MAX_LIFE)+1.0
set uHPpercent = uHP/uHPmax*1.0
if IssueTargetOrder(hero_testunit_attack[id],"smart",u) then
call IssueImmediateOrder(hero_testunit_attack[id], "stop")
if IsUnitEnemy(u,p) then
if uHP < HPmin then
set HPmin = uHP
set weakEnemy = u
if IsUnitType(u,UNIT_TYPE_HERO)==true then
set EnemyheroN = EnemyheroN + 1
endif
endif
if IsUnitType(u,UNIT_TYPE_HERO)==true then
if uHPpercent < 0.5 then
set attack_dis = 800.0
set weakHero = u
endif
endif
else
if b_attack_ally[id]==true and uHPpercent<0.35 and uHP<50.0+5.0*level then
set weakAlly = u
endif
endif
endif
call GroupRemoveUnit(G,u)
exitwhen u==null
endloop
call GroupClear(G)
if weakEnemy != null then
if attack_dis>=DistanceBetweenXY(x,GetUnitX(weakEnemy),y,GetUnitY(weakEnemy)) /*
*/ and IsUnitSpelling(hero) == false then
call IssueTargetOrder(hero,"attack",weakEnemy)
endif
endif
if weakHero != null and IsUnitSpelling(hero) == false then
call IssueTargetOrder(hero,"attack",weakHero)
endif
if weakAlly != null and IsUnitSpelling(hero) == false and EnemyheroN > 0 then
call IssueTargetOrder(hero,"attack",weakAlly)
endif
call SetUnitOwner( hero_testunit_attack[id], Player(15), true )
set u = null
set weakAlly = null
set weakEnemy = null
set weakHero = null
endfunction
private function ai_Hero_Loop takes nothing returns nothing
local integer i = 0
local group G = null
local player p = null
local real heroHP = 0.0
local real heroHPmax = 0.0
local real heroHPpercent = 0.0
local real heroMana = 0.0
local real heroManaMax = 0.0
local real heroManaPercent = 0.0
local unit u = null
local integer AllyI = 0
local integer EnemyI = 0
local group g_weak = null
local real x = 0.
local real y = 0.
local unit EnemyU = null
local integer EnemyN = 0
loop
exitwhen i > Top_ai_hero
if IsUnitType(ai_hero[i],UNIT_TYPE_DEAD)==false or ai_hero[i]!=null then
set x = GetUnitX(ai_hero[i])
set y = GetUnitY(ai_hero[i])
set p = GetOwningPlayer(ai_hero[i])
set heroHP = GetUnitState(ai_hero[i],UNIT_STATE_LIFE)
set heroHPmax = GetUnitState(ai_hero[i],UNIT_STATE_MAX_LIFE)+1.0
set heroHPpercent = heroHP/heroHPmax*1.0
set heroMana = GetUnitState(ai_hero[i],UNIT_STATE_MANA)
set heroManaMax = GetUnitState(ai_hero[i],UNIT_STATE_MAX_MANA)+1.0
set heroManaPercent = heroMana/heroManaMax*1.0
set G=CreateGroup()
call GroupEnumUnitsInRange(G,x,y,800.0,null)
set g_weak = CreateGroup()
loop
set u=FirstOfGroup(G)
if IsUnitType(u,UNIT_TYPE_DEAD)==false and u!=null then
call GroupAddUnit(g_weak,u)
if GetOwningPlayer(u)==p /*
*/ and IsUnitInGroup(u,group_AI_herounits[i])==false /*
*/ and IsUnitType(u,UNIT_TYPE_PEON)==false then
call GroupAddUnit(group_AI_herounits[i],u)
endif
if IsUnitEnemy(u,p) == true then
set EnemyN = EnemyN + 1
set EnemyU = u
endif       
endif      
call GroupRemoveUnit(G,u)
exitwhen u==null
endloop
if b_attack_weakunit[i] == true then
if IsUnitInGroup(ai_hero[i],group_evade)==true then
call GroupRemoveUnit(group_evade,ai_hero[i])
else
call AiHeroAttackWeakUnit(ai_hero[i],x,y,p,g_weak,i)
endif
endif
call DestroyGroup(g_weak)
if loc_ai_retreat[i]!=null and heroHPpercent<hp_ai_retreat[i] and b_ai_retreat[i]==true then
if EnemyN > 0 then
call IssuePointOrderLoc( ai_hero[i], "move", loc_ai_retreat[i] )
if EnemyN < 2 and GetUnitState(EnemyU,UNIT_STATE_LIFE) < 50. then
call IssueTargetOrder( ai_hero[i], "attackone", EnemyU )
endif
endif
endif
call GroupClear(G)
call DestroyGroup(G)
if loc_ai_retreat[i] != null then
if DistanceBetweenXY(x,GetLocationX(loc_ai_retreat[i]),y,GetLocationY(loc_ai_retreat[i]))<=800. then
if heroHPpercent < HPmin_hero_attack or heroManaPercent < MANAmin_hero_attack then
call IssuePointOrderLoc( ai_hero[i], "attack", loc_ai_retreat[i] )
endif
endif 
endif
if b_ai_pickItem[i] == true and IsUnitBackpackFull(ai_hero[i]) == false then
call HeroPickItem(ai_hero[i],x,y)
endif
endif
set i = i + 1
endloop
set u = null
set G = null
set p = null
set g_weak = null
set EnemyU = null
endfunction
private function GetCreepsCamp takes nothing returns nothing
local unit u
local unit camu
local group camg 
local group g = CreateGroup()
local integer i = 0
local integer pi = 0
call GroupClear(group_creepcamp)
loop
exitwhen i > Top_creepcamp
call GroupClear(groups_camg[i])
call DestroyGroup(groups_camg[i])
set groups_camg[i] = null
set b_creeps_canattack[i]=true
call RemoveLocation(loc_min_camg[i])
set creeps_level[i] = 0
set i = i + 1
endloop
set Top_creepcamp = -1
call GroupEnumUnitsOfPlayer(g,CreepPlayer,null)
loop
set u = FirstOfGroup(g)
if IsUnitInGroup(u,group_creepcamp)==false and IsUnitType(u,UNIT_TYPE_DEAD)==false then
set Top_creepcamp = Top_creepcamp + 1
set pi = 0
loop
exitwhen pi > 11
set b_can_atk_camg[pi][Top_creepcamp] = true
set pi = pi + 1
endloop
set loc_min_camg[Top_creepcamp] = Location(GetUnitX(u),GetUnitY(u))
if groups_camg[Top_creepcamp] == null then
set groups_camg[Top_creepcamp] = CreateGroup()
endif
set camg = CreateGroup()
call GroupEnumUnitsInRange(camg,GetUnitX(u),GetUnitY(u),800.99,null)
loop
set camu = FirstOfGroup(camg)
if GetOwningPlayer(camu)==CreepPlayer and IsUnitType(camu,UNIT_TYPE_DEAD)==false then
set creeps_level[Top_creepcamp] = creeps_level[Top_creepcamp] + GetUnitLevel(camu)
call GroupAddUnit(group_creepcamp,camu)
call GroupAddUnit(groups_camg[Top_creepcamp],camu)
endif
call GroupRemoveUnit(camg,camu)
exitwhen camu==null
endloop
call GroupClear(camg)
call DestroyGroup(camg)
endif
call GroupRemoveUnit(g,u)
exitwhen u==null
endloop
call GroupClear(g)
call DestroyGroup(g)
set u = null
set g = null
set camu = null
set camg = null
endfunction
private function CheckHeroTarget takes nothing returns nothing
local integer i = 0
local real heroHP = 0.0
local real heroHPmax = 0.0
local real heroHPpercent = 0.0
loop
exitwhen i > Top_ai_hero
set heroHP = GetUnitState(ai_hero[i],UNIT_STATE_LIFE)
set heroHPmax = GetUnitState(ai_hero[i],UNIT_STATE_MAX_LIFE)+1.0
set heroHPpercent = heroHP/heroHPmax*1.0
set b_ai_havetarget[i] = false
if b_ai_MF[i] == true then
call CheckHeroMf(i,heroHPpercent)
endif
if b_ai_havetarget[i] == false then
if b_ai_attacktarget[i] == true then
call CheckHeroAttackTarget(i,heroHPpercent)
endif
endif
if b_ai_havetarget[i] == false then
if b_ai_retreat[i] == true and loc_ai_retreat[i] != null then
call IssuePointOrderLoc( ai_hero[i], "move", loc_ai_retreat[i] )
endif
endif
set i = i + 1
endloop
endfunction
private function RegisterAiHero takes unit hero returns nothing
if IsUnitType(hero,UNIT_TYPE_HERO)==true /* 
*/ and GetPlayerController(GetOwningPlayer(hero))==MAP_CONTROL_COMPUTER /* 
*/ and IsUnitInGroup(hero,group_AI_hero) == false then 
call GroupAddUnit(group_AI_hero,hero)
set Top_ai_hero = Top_ai_hero + 1
if open_ai == 0 then
call TimerStart(CreateTimer(),4.92,true,function CheckHeroTarget)
call TimerStart(CreateTimer(),45.86,true,function GetCreepsCamp)
call TimerStart(CreateTimer(),0.73,true,function ai_Hero_Loop)
endif
set open_ai = open_ai + 1
set ai_hero[Top_ai_hero] = hero
set b_ai_MF[Top_ai_hero] = false
set b_ai_retreat[Top_ai_hero] = false
set b_ai_pickItem[Top_ai_hero] = false
set b_ai_havetarget[Top_ai_hero] = false
set mf_max_level[Top_ai_hero] = 0
set group_AI_herounits[Top_ai_hero] = CreateGroup()
set hero_evade_timer[Top_ai_hero] = CreateTimer()
set hero_evade_boolean[Top_ai_hero] = true
set b_attack_ally[Top_ai_hero] = false
set b_attack_weakunit[Top_ai_hero] = false
set b_ai_attacktarget[Top_ai_hero] = false
set hero_testunit_attack[Top_ai_hero] = CreateUnit(Player(15),GetUnitTypeId(hero),map_max_X,map_max_Y,0.)
call ShowUnit(hero_testunit_attack[Top_ai_hero],false)
call UnitAddAbility( hero_testunit_attack[Top_ai_hero], 'Aloc' )
call TriggerRegisterUnitEvent(hero_attacked_trigger,ai_hero[Top_ai_hero],EVENT_UNIT_ATTACKED)
call SetPlayerName( GetOwningPlayer(hero), ( "[EggHeroAI]" + GetPlayerName(GetOwningPlayer(hero)) ) )
endif
endfunction
function SetAiHeroAttackTarget takes unit hero, location loc, boolean b returns nothing
local integer id = 0
call RegisterAiHero(hero)
set id = GetAiHeroID(hero)
set ai_hero_targetloc[id] = loc
set b_ai_attacktarget[id] = b
endfunction
function SetAiHeroMF takes unit hero, integer level, boolean b returns nothing
local integer id = 0
call RegisterAiHero(hero)
set id = GetAiHeroID(hero)
set b_ai_MF[id] = b
set mf_max_level[id] = level
endfunction
function SetAiHeroRetreat takes unit hero, location loc, real hpmin, boolean b returns nothing
local integer id = 0
call RegisterAiHero(hero)
set id = GetAiHeroID(hero)
set loc_ai_retreat[id] = loc
set b_ai_retreat[id] = b
set hp_ai_retreat[id] = hpmin
endfunction
function SetAiHeroPickItem takes unit hero, boolean b returns nothing
call RegisterAiHero(hero)
set b_ai_pickItem[GetAiHeroID(hero)] = b
endfunction
function SetAiHeroAttackWeak takes unit hero, boolean b1, boolean b2 returns nothing
local integer id = 0
call RegisterAiHero(hero)
set id = GetAiHeroID(hero)
set b_attack_weakunit[id] = b1
set b_attack_ally[id] = b2
endfunction
public function rpg_ai_Init takes nothing returns nothing
call GetCreepsCamp()
call TriggerAddAction(hero_attacked_trigger,function AiHeroAttacked)
set HPmin_hero_attack = 0.95
set MANAmin_hero_attack = 0.90
endfunction
//triggers
private function TriggerRegisterAnyUnitPoint takes nothing returns nothing
local unit u = GetTriggerUnit()
local player p = GetOwningPlayer(u)
local integer id = GetPlayerId(p)
if GetPlayerController(p) == MAP_CONTROL_COMPUTER and Melee_AI_On[id] == true then
if IsUnitType(u, UNIT_TYPE_HERO) == true and b_transport_getTarget[id] == false then//and GetIssuedOrderId() == 851983 then
if loc_hero_orderLoc[id] != null then
call RemoveLocation(loc_hero_orderLoc[id])
endif
set loc_hero_orderLoc[id] = GetOrderPointLoc()
endif
endif
set u = null
set p = null
endfunction
private function TriggerRegisterAnyUnitSold takes nothing returns nothing
local integer typeid = GetUnitTypeId(GetSoldUnit())
local integer i = 0
if GetPlayerId(GetOwningPlayer(GetSellingUnit())) == 15 /*
*/ and GetUnitTypeId(GetSellingUnit()) != UnitType_AmmoDump then
loop
exitwhen i > 11
set Unit_GetSoldShop[i] = GetSellingUnit()
set i = i + 1
endloop
endif
if typeid != UnitType_TronGloem and typeid != UnitType_zeppelin then
set UnitType_GetSoldUnit = typeid
endif
endfunction
private function TriggerRegisterAnyUnitSpellEffect takes nothing returns nothing
endfunction
private function TriggerRegisterAnyUnitSpellEnd takes nothing returns nothing
if IsUnitInGroup(GetTriggerUnit(),group_speller)==true then
call GroupRemoveUnit(group_speller,GetTriggerUnit())
endif
endfunction
private function TriggerRegisterAnyUnitSpell takes nothing returns nothing
local real timeout = 0.0
local unit target = null
local unit speller = GetTriggerUnit()
set target = GetSpellTargetUnit()
if IsUnitInGroup(speller,group_speller)==false then
call GroupAddUnit(group_speller,speller)
endif
if target != null then
if IsUnitType(target, UNIT_TYPE_HERO) == true then
if Melee_AI_On[GetPlayerId(GetOwningPlayer(target))] == true /*
*/ and GetHeroStatePercent(target,UNIT_STATE_LIFE) <= 0.15 /*
*/ and IsUnitEnemy(speller,GetOwningPlayer(target)) == true then
set Top_hero_av_abi = Top_hero_av_abi + 1
set hero_av_abi[Top_hero_av_abi] = target
if GetRandomInt(1,2) == 1 then
set timeout = 0.35
endif
call TimerStart(CreateTimer(),timeout,false,function AI_Hero_AvoidAbilityDam)
endif
endif  
endif
set target = null
set speller = null
endfunction
private function TriggerRegisterAnyUnitDead takes nothing returns nothing
endfunction 
private function TriggerRegisterAnyUnit takes nothing returns nothing
local integer id = 0
local integer unitid = 0
local unit u = GetTriggerUnit()
local player p = GetOwningPlayer(u)
local integer towertype = 0
set id = GetPlayerId(p)
if Melee_AI_On[id] == true then
if GetUnitAbilityLevel(u,'Aloc') == 0 and IsUnitIllusion(u) == false and Top_Units[id] < max_array_units then
set Top_Units[id] = Top_Units[id] + 1
set unitid = id * max_array_units + Top_Units[id]
set ai_units[unitid] = u
set b_unit_guardPos[unitid] = true
set unit_LastX[unitid] = 0.
set unit_LastY[unitid] = 0.
set int_unit_blocked[unitid] = 0
if IsUnitType(ai_units[unitid], UNIT_TYPE_PEON) == true then
call GroupAddUnit(group_peons,ai_units[unitid])
endif
if GetUnitAbilityLevel(ai_units[unitid], 'Sch3') > 0 /*
*/ or GetUnitAbilityLevel(ai_units[unitid], 'Sch5') > 0 then
call GroupAddUnit(group_transportation,ai_units[unitid])
set num_zeppelin[id] = num_zeppelin[id] + 1
call IssuePointOrderLoc( ai_units[unitid], "move", loc_startLoc[id] )
endif
if GetUnitTypeId(ai_units[unitid]) == UnitType_TronGloem then
call RemoveGuardPosition(ai_units[unitid])
call IssuePointOrderLoc( ai_units[unitid], "move", loc_startLoc[id] )
call GroupAddUnit(group_peons,ai_units[unitid])
set num_IronGolem[id] = num_IronGolem[id] + 1
endif
//if IssuePointOrder( ai_units[unitid], "attackground", x, y ) then
//call IssueImmediateOrder( ai_units[unitid], "stop" )
//elseif GetUnitAbilityLevel(ai_units[unitid],'Aatk') > 0 /*
//*/ and IsUnitType(ai_units[unitid], UNIT_TYPE_STRUCTURE) == false  then
//set type_unit_siege[id] = GetUnitTypeId(ai_units[unitid])
//endif
if IsUnitType(ai_units[unitid], UNIT_TYPE_HERO) == true then
call TriggerRegisterUnitEvent(MeleeHero_Attacked_Trg,ai_units[unitid],EVENT_UNIT_ATTACKED)
call TriggerRegisterUnitEvent(MeleeHeroGetItem,ai_units[unitid],EVENT_UNIT_PICKUP_ITEM)
elseif IsUnitType(ai_units[unitid], UNIT_TYPE_STRUCTURE) == true then
if GetUnitAbilityLevel(ai_units[unitid], 'Apit') > 0 then
set melee_ai_shops[id] = ai_units[unitid]
endif
set towertype = GetUnitTypeId(ai_units[unitid])
if (IsUnitType(ai_units[unitid], UNIT_TYPE_RANGED_ATTACKER) == true /*
*/ and GetUnitAbilityLevel(ai_units[unitid], 'Abtl') < 1) or /*
*/ towertype == Ut_htw1 or towertype == Ut_utw1 or towertype == Ut_etw1 then
set type_melee_tower[id] = towertype
endif
endif
endif
endif
set p = null
set u = null
endfunction 
private function TriggerClearRegister takes nothing returns nothing
endfunction
private function TriggerProduce takes nothing returns nothing
local integer i = 0
set RectRegion = CreateRegion()
call RegionAddRect(RectRegion,bj_mapInitialPlayableArea)
call TriggerAddAction(AnyUnitEnter,function TriggerRegisterAnyUnit)
call TriggerAddAction(AnyUnitSpell,function TriggerRegisterAnyUnitSpell)
call TriggerAddAction(AnyUnitSpellEnd,function TriggerRegisterAnyUnitSpellEnd)
call TriggerRegisterEnterRegion(AnyUnitEnter,RectRegion,null)
call TriggerAddAction(AnyUnitSold,function TriggerRegisterAnyUnitSold)
call TriggerAddAction(AnyUnitOrderPoint,function TriggerRegisterAnyUnitPoint)
call TriggerAddAction(MeleeHeroGetItem,function Melee_HeroGetItem)
loop
exitwhen i > 15    
call TriggerRegisterPlayerUnitEvent(AnyUnitSpell,Player(i),EVENT_PLAYER_UNIT_SPELL_CHANNEL,null)
call TriggerRegisterPlayerUnitEvent(AnyUnitSpellEnd,Player(i),EVENT_PLAYER_UNIT_SPELL_ENDCAST,null)
call TriggerRegisterPlayerUnitEvent(AnyUnitSold,Player(i),EVENT_PLAYER_UNIT_SELL,null)
call TriggerRegisterPlayerUnitEvent(AnyUnitOrderPoint,Player(i),EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER,null)
set i = i + 1
endloop
endfunction
//start
private function InitAll takes nothing returns nothing
local integer i = 0
loop
exitwhen i > 15
set Melee_AI_On[i] = false
set i = i + 1
endloop
set map_max_X = GetRectMaxX(bj_mapInitialPlayableArea)
set map_max_Y = GetRectMaxY(bj_mapInitialPlayableArea)
set map_min_X = GetRectMinX(bj_mapInitialPlayableArea)
set map_min_Y = GetRectMinY(bj_mapInitialPlayableArea)
call TimerStart(CreateTimer(),20.3,true, function ItemPickingIntermission)
call TimerStart(CreateTimer(),34.4,true, function GroupClearTrg)
set filterEnumDestructablesInCircle = Filter(function EnumDestructablesInCircleFilter)
set harvest_unit = CreateUnit(Player(15),UnitType_Harvest,map_max_X,map_max_Y,0.)
call ShowUnit(harvest_unit,false)
call UnitRemoveAbility(harvest_unit,'Aatk')
call UnitAddAbility(harvest_unit,'Aloc')
if GetUnitAbilityLevel(harvest_unit,'ANha') < 1 then
call UnitAddAbility(harvest_unit,'ANha')
endif
call TriggerProduce()
//call rpg_ai_Init()
//call melee_ai_Init()
endfunction
endlibrary

JASS:
library EggMeleeAI initializer MeleeAIsystem_Start
function MeleeAIsystem_Start takes nothing returns nothing
//***************************use the intelligent melee AI for computers
call AIsystem_SetAIplayer(Player(0),true)//Strengthen AI for player 1 , "true" to on, "false" to off
call AIsystem_SetAIplayer(Player(1),true)//Strengthen AI for player 2 , "true" to on, "false" to off
call AIsystem_SetAIplayer(Player(2),true)//Strengthen AI for player 3 , "true" to on, "false" to off
call AIsystem_SetAIplayer(Player(3),true)//Strengthen AI for player 4 , "true" to on, "false" to off
call AIsystem_SetAIplayer(Player(4),true)//Strengthen AI for player 5 , "true" to on, "false" to off
call AIsystem_SetAIplayer(Player(5),true)//Strengthen AI for player 6 , "true" to on, "false" to off
call AIsystem_SetAIplayer(Player(6),true)//Strengthen AI for player 7 , "true" to on, "false" to off
call AIsystem_SetAIplayer(Player(7),true)//Strengthen AI for player 8 , "true" to on, "false" to off
call AIsystem_SetAIplayer(Player(8),true)//Strengthen AI for player 9 , "true" to on, "false" to off
call AIsystem_SetAIplayer(Player(9),true)//Strengthen AI for player 10 , "true" to on, "false" to off
call AIsystem_SetAIplayer(Player(10),true)//Strengthen AI for player 11 , "true" to on, "false" to off
call AIsystem_SetAIplayer(Player(11),true)//Strengthen AI for player 12 , "true" to on, "false" to off
//***************************//***************************
//Start the AI System
call AIsystem_melee_ai_Init()
endfunction
endlibrary

And 3 disabled triggers..
 

Wrda

Spell Reviewer
Level 28
Joined
Nov 18, 2012
Messages
1,991
and what means "Indentation"?
It's just like an essay, if you write it without any paragraphes it will be confusing for the person who will read it, he/she won't understand anything. Here you should inline your scripts:
JASS:
function DistanceBetweenXY takes real x1,real x2,real y1,real y2 returns real
return SquareRoot(( x1 - x2 ) * ( x1 - x2 ) + ( y1 - y2 ) * ( y1 - y2 ))
endfunction
function AngleBetweenXY takes real x1, real x2, real y1, real y2 returns real
return bj_RADTODEG*Atan2( y2 - y1 , x2 - x1 )
endfunction
function RadianBetweenXY takes real x1, real x2, real y1, real y2 returns real
return Atan2( y2 - y1 , x2 - x1 )
endfunction 
//looks confusing and not clear

->
JASS:
function DistanceBetweenXY takes real x1,real x2,real y1,real y2 returns real
    return SquareRoot(( x1 - x2 ) * ( x1 - x2 ) + ( y1 - y2 ) * ( y1 - y2 ))
endfunction

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

function RadianBetweenXY takes real x1, real x2, real y1, real y2 returns real
    return Atan2( y2 - y1 , x2 - x1 )
endfunction
 
Top