This is a script for a Unit Aggro System, it takes over the normal computer AI and delegates a units target based on the current threat the units attacking it have.
v1.4 - Added the requires PUI to the library.
v1.3 - Fixed a bug with aggro sorting, now removing aggro applies properly.
v1.2 - Fixed an AI bug with targeting something other then the target.
v1.1 - Fixed some optimization.
V1.0 - Initial release.
Readme
//====================================================================================================
// UAS - Unit Aggro System 1.4
// Created by Dustin "TEC_Ghost" Hendrickson
//
// 1.) WHAT DOES IT DO?
// This is a system designed for realtime aggro management, giving your computer players a
// system in which they target units.
//
// 2.) WHAT DOES IT REQUIRE?
// vJass
// PUI
// A basic understanding of jass.
//
// 3.) HOW DO I USE IT?
// Just copy and paste the library into a custom text trigger.
// The system automatically updates aggro and sorting.
// All you have to do is setup the unit to put it in the system.
//
// There are also a few functions you'll need to use...
//
// SetupAggro(Unit)
// - You'll need to run this for every unit you want in the system.
//
// RemoveAggroUnit(Unit)
// - Removes the unit from the system.
//
// ApplyAggro(UnitA,UnitB,Ammount,Boolean)
// - This function applys aggro to UnitA from UnitB, the Ammount is how much aggro to apply,
// how much aggro to apply, True if you want it to apply to non computers, False if you want
// to apply to only computers.
//
// RemoveAggro(UnitA,UnitB,Ammount,Boolean)
// - Same as the ApplyAggro() function, but removes instead of adds.
//
// ClearAggro(UnitA,UnitB)
// - Does the same as RecycleAggro() but is for manual purposes incase you want to remove all
// of a units aggro from a certain other unit. Clears UnitB's aggro from UnitA.
//
//
//---------------------------------------------------------------------------------------
// Some other variables that can be used for displaying information are as follows...
//---------------------------------------------------------------------------------------
//
// GetAggroSlotUnit(Unit,Integer)returns Unit
// - The array for the sorted aggro list "integer" 1 would be the highest aggro, 2 would be lower
// 3 would be lower yet. "Unit" is the the unit you're pulling the array for. Returns
// a unit.
//
// GetAggroSlotAmmount(Unit,Integer)returns Integer
// - Same as the above, but returns the aggro ammount for the particular slot.
//
// TotalUnits
// - Returns an integer for the total number of units in the system.
//
//
//
//====================================================================================================
System Library
library UAS initializer SystemUpdate requires PUI //================================================================================================================ // UAS - Unit Aggro System 1.4 // Created by Dustin "TEC_Ghost" Hendrickson // // 1.) WHAT DOES IT DO? // This is a system designed for realtime aggro management, giving your computer players a // system in which they target units. // // 2.) WHAT DOES IT REQUIRE? // vJass // PUI // A basic understanding of jass. // // 3.) HOW DO I USE IT? // Just copy and paste the library into a custom text trigger. // The system automatically updates aggro and sorting. // All you have to do is setup the unit to put it in the system. // // There are also a few functions you'll need to use... // // SetupAggro(Unit) // - You'll need to run this for every unit you want in the system. // // RemoveAggroUnit(Unit) // - Removes the unit from the system. // // ApplyAggro(UnitA,UnitB,Ammount,Boolean) // - This function applys aggro to UnitA from UnitB, the Ammount is how much aggro to apply, // how much aggro to apply, True if you want it to apply to non computers, False if you want // to apply to only computers. // // RemoveAggro(UnitA,UnitB,Ammount,Boolean) // - Same as the ApplyAggro() function, but removes instead of adds. // // ClearAggro(UnitA,UnitB) // - Does the same as RecycleAggro() but is for manual purposes incase you want to remove all // of a units aggro from a certain other unit. Clears UnitB's aggro from UnitA. // // //--------------------------------------------------------------------------------------- // Some other variables that can be used for displaying information are as follows... //--------------------------------------------------------------------------------------- // // GetAggroSlotUnit(Unit,Integer)returns Unit // - The array for the sorted aggro list "integer" 1 would be the highest aggro, 2 would be lower // 3 would be lower yet. "Unit" is the the unit you're pulling the array for. Returns // a unit. // // GetAggroSlotAmmount(Unit,Integer)returns Integer // - Same as the above, but returns the aggro ammount for the particular slot. // // TotalUnits // - Returns an integer for the total number of units in the system. // // // //================================================================================================================ // SCRIPT IS BELOW - DO NOT MODIFY ANY OF THIS UNLESS YOU KNOW WHAT YOU'RE DOING! //================================================================================================================
globals privateconstantreal INTERVAL = .30 // Interval for the system to update Recyciling and aggro sorting. UnitAggroArray array UnitAggro // Struct array for the system. privateinteger TotalUnits = 0 // Keeps track of the max units in the system for updates. privatetrigger UpdateCycle // SystemUpdate trigger. endglobals
struct UnitAggroArray unit Unit // The unit. unit Target // The current target. unitarray unit_AggroTable[150]// Unit Refrence. integerarray ammount_AggroTable[150]// Aggro Ammount. unitarray sortedunits_AggroTable[150]// The array for sorted units. integerarray sortedaggroammount_AggroTable[150]// The array for aggro totals of sorted slots. group group_AggroTable // Group of all units aggroed. boolean FlaggedForRemoval // Boolean set to remove unit from system. endstruct
//============================================ //Setup Struct for unit. ---> SetupAggro(Unit) //============================================ function SetupAggro takesunit U returnsnothing localinteger Index = GetUnitIndex(U) set UnitAggro[Index] = UnitAggroArray.create() set UnitAggro[Index].Unit = U set UnitAggro[Index].Target = null set UnitAggro[Index].group_AggroTable = CreateGroup() set TotalUnits = TotalUnits + 1 endfunction
//================================================================================================= //Gets the unit in a certain slot from a units aggro table. ---> GetAggroSlotUnit(Unit,Integer)Unit //================================================================================================= function GetAggroSlotUnit takesunit U, integer i returnsunit localinteger Index = GetUnitUserData(U) return UnitAggro[Index].sortedunits_AggroTable[i] endfunction //==================================================================================================================== //Gets the ammount of aggro in a certain slot from a unit's aggro table. ---> GetAggroSlotAmmount(Unit,Integer)Integer //==================================================================================================================== function GetAggroSlotAmmount takesunit U, integer i returnsinteger localinteger Index = GetUnitUserData(U) return UnitAggro[Index].sortedaggroammount_AggroTable[i] endfunction
//================================================================================================== //Checks the precise slot of UnitB in UnitA's aggro table. ---> GetUnitAggroSlot(UnitA,UnitB)Integer //================================================================================================== function GetUnitAggroSlot takesunit Ua, unit Ub returnsinteger localinteger Index = GetUnitUserData(Ua) localinteger l = 1 localinteger Total = CountUnitsInGroup(UnitAggro[Index].group_AggroTable)
loop exitwhen l > Total
if UnitAggro[Index].sortedunits_AggroTable[l] == Ub then return l endif
set l = l + 1 endloop
return 0 endfunction
//=================================================== //Clear UnitB aggro from UnitA. ---> ClearAggro(Unit) //=================================================== function ClearAggro takesunit Ua, unit Ub returnsnothing localinteger IndexA = GetUnitUserData(Ua) localinteger IndexB = GetUnitUserData(Ub) localinteger Index = 0
set Index = GetUnitAggroSlot(Ua,Ub) set UnitAggro[IndexA].unit_AggroTable[IndexB] = null set UnitAggro[IndexA].ammount_AggroTable[IndexB] = 0 set UnitAggro[IndexA].sortedunits_AggroTable[Index] = null set UnitAggro[IndexA].sortedaggroammount_AggroTable[Index] = 0
//================================================================================= //Checks if any units are dead and removes them from the group. ---> RecycleAggro() //================================================================================= function RecycleAggro takesnothingreturnsnothing localinteger Index = 1 localinteger TempIndex = 0 localinteger Total = TotalUnits localgroup Group = CreateGroup() localunit Unit = null
loop exitwhen Index > Total call GroupAddGroup(UnitAggro[Index].group_AggroTable,Group)
loop set Unit = FirstOfGroup(Group) exitwhen Unit == null
if GetUnitState(Unit, UNIT_STATE_LIFE) <= 0 or UnitAggro[GetUnitUserData(Unit)].FlaggedForRemoval == truethen set TempIndex = GetUnitUserData(Unit) set UnitAggro[TempIndex].Unit = null set UnitAggro[TempIndex].Target = null call ClearAggro(UnitAggro[Index].Unit,Unit) call GroupRemoveUnit(UnitAggro[Index].group_AggroTable,Unit) set UnitAggro[TempIndex].FlaggedForRemoval = false endif call GroupRemoveUnit(Group,Unit) endloop
set Index = Index + 1 endloop
endfunction
//============================================== //Remove unit from system. ---> RemoveUnit(Unit) //============================================== function RemoveAggroUnit takesunit U returnsnothing localinteger Index = GetUnitIndex(U) set UnitAggro[Index].FlaggedForRemoval = true call DestroyGroup(UnitAggro[Index].group_AggroTable) call RecycleAggro() endfunction
//============================================================= //Sorts aggro into table based on ammount. ---> SortAggro(Unit) //============================================================= function SortAggro takesunit U returnsnothing localinteger Index = GetUnitUserData(U) localinteger Rows = CountUnitsInGroup(UnitAggro[Index].group_AggroTable) localunit Tempunit = null localgroup Tempgroup = CreateGroup() localgroup Tempgroup2 = CreateGroup() localinteger l = 1
call GroupAddGroup(UnitAggro[Index].group_AggroTable,Tempgroup) set l = 1
loop exitwhen l > Rows set UnitAggro[Index].sortedaggroammount_AggroTable[l] = 0 loop set Tempunit = FirstOfGroup(Tempgroup) exitwhen Tempunit == null if UnitAggro[Index].ammount_AggroTable[GetUnitUserData(Tempunit)] > UnitAggro[Index].sortedaggroammount_AggroTable[l]then set UnitAggro[Index].sortedunits_AggroTable[l] = Tempunit set UnitAggro[Index].sortedaggroammount_AggroTable[l] = UnitAggro[Index].ammount_AggroTable[GetUnitUserData(Tempunit)] endif
//============================================================================================================================= //Apply aggro to Unit A from Unit B. Allow user controlled players to be affected. ---> ApplyAggro(UnitA,UnitB,Ammount,Boolean) //============================================================================================================================= function ApplyAggro takesunit Ua, unit Ub, integer Ammount, boolean AllowUser returnsnothing localinteger IndexA = GetUnitIndex(Ua) localinteger IndexB = GetUnitIndex(Ub) localboolean NewAdd = false
if AllowUser == falsethen if GetPlayerController(GetOwningPlayer(Ua)) == MAP_CONTROL_USER then return endif endif
if IsUnitInGroup(Ub,UnitAggro[IndexA].group_AggroTable) == truethen set UnitAggro[IndexA].ammount_AggroTable[IndexB] = UnitAggro[IndexA].ammount_AggroTable[IndexB] + Ammount else call GroupAddUnit(UnitAggro[IndexA].group_AggroTable,Ub) set UnitAggro[IndexA].unit_AggroTable[IndexB] = Ub set UnitAggro[IndexA].ammount_AggroTable[IndexB] = UnitAggro[IndexA].ammount_AggroTable[IndexB] + Ammount endif
endfunction
//========================================================================= //Remove aggro on Unit A from Unit B. ---> RemoveAggro(UnitA,UnitB,Ammount,Boolean) //========================================================================= function RemoveAggro takesunit Ua, unit Ub, integer Ammount, boolean AllowUser returnsnothing localinteger IndexA = GetUnitIndex(Ua) localinteger IndexB = GetUnitIndex(Ub)
if AllowUser == falsethen if GetPlayerController(GetOwningPlayer(Ua)) == MAP_CONTROL_USER then return endif endif
if IsUnitInGroup(Ub,UnitAggro[IndexA].group_AggroTable) == truethen set UnitAggro[IndexA].ammount_AggroTable[IndexB] = UnitAggro[IndexA].ammount_AggroTable[IndexB] - Ammount else call GroupAddUnit(UnitAggro[IndexA].group_AggroTable,Ub) set UnitAggro[IndexA].unit_AggroTable[IndexB] = Ub set UnitAggro[IndexA].ammount_AggroTable[IndexB] = UnitAggro[IndexA].ammount_AggroTable[IndexB] - Ammount
endif if UnitAggro[IndexA].ammount_AggroTable[IndexB] < 0 then set UnitAggro[IndexA].ammount_AggroTable[IndexB] = 0 endif
endfunction
//======================================================= //Updates the aggro table with target. ---> UpdateAggro() //======================================================= function UpdateAggro takesnothingreturnsnothing localinteger Total = TotalUnits localinteger Index = 1
loop exitwhen Index > Total if Index != 0 then call SortAggro(UnitAggro[Index].Unit) set UnitAggro[Index].Target = UnitAggro[Index].sortedunits_AggroTable[1] if IsUnitInRange(UnitAggro[Index].Target,UnitAggro[Index].Unit,500) == truethen call IssueTargetOrder(UnitAggro[Index].Unit,"attack",UnitAggro[Index].Target) else call IssueTargetOrder(UnitAggro[Index].Unit,"move",UnitAggro[Index].Target) endif endif set Index = Index + 1 endloop