Hero Selection System 1.30b
A dynamic, completely customizable Hero Selection System!
A dynamic, completely customizable Hero Selection System!
Read Me - Basic:
Hero Selection System 1.30b - By: emjlr3
The basic steps to setup the system in your map
*Copy the Select Hero and Random Hero units to your map
*Copy the HSS and GetPlayerNameColored(if not already there) triggers to your map
*Configure he options you can(everything but Choose/RandomHeroOrder)
*Save, if that works, then everything is good, if not, start over and try again from the beginning
*Type -HSSGetOrders while in single player to determine the order ids for selling your selection units
This will create a hero at Player 1s start location. You can select choose hero or random hero on this hero, and it will display the correct order id for that selection. Write these two order ids down, and move to the next step
*Configure the order id options in HSS (ChooseHeroOrder and RandomHeroOrder)
*Add heroes to your map, owned by neutral passive, set their level and abilities learned to whatever you want, add a rect around your hero gallery
*Copy HSSSetup to yor map
*Look through HSSSetup, this is the trigger that will start and setup the system for you. You can have this run after X seconds, as I do, You can execute the trigger later, among many other things. Read through this and configure it to match your maps needs
*Save, if that works, yo are good to go, if not, look through HSSSetup again and see where your syntax went wrong
The basic steps to setup the system in your map
*Copy the Select Hero and Random Hero units to your map
*Copy the HSS and GetPlayerNameColored(if not already there) triggers to your map
*Configure he options you can(everything but Choose/RandomHeroOrder)
*Save, if that works, then everything is good, if not, start over and try again from the beginning
*Type -HSSGetOrders while in single player to determine the order ids for selling your selection units
This will create a hero at Player 1s start location. You can select choose hero or random hero on this hero, and it will display the correct order id for that selection. Write these two order ids down, and move to the next step
*Configure the order id options in HSS (ChooseHeroOrder and RandomHeroOrder)
*Add heroes to your map, owned by neutral passive, set their level and abilities learned to whatever you want, add a rect around your hero gallery
*Copy HSSSetup to yor map
*Look through HSSSetup, this is the trigger that will start and setup the system for you. You can have this run after X seconds, as I do, You can execute the trigger later, among many other things. Read through this and configure it to match your maps needs
*Save, if that works, yo are good to go, if not, look through HSSSetup again and see where your syntax went wrong
Read Me - Advanced:
Hero Selection System 1.30b - By: emjlr3
The more advanced configuration required for the system to function, or to be further customized
*All system used global arrays are stored as the id of the player they are for, ex. HSS_HeroSelection = GetPlayerId(unit)
*As seen in HSSSetup in this map, you must store the Hero Selection Gallery Rect and Hero Creation Loc for every player in your map, else the system does not know where they are
HSS_HeroSelection in a rect array used for the hero gallery
HSS_HeroCreation is a location array use for the creation of heroes
*The global trigger HSS_CreatedHeroTrigger will run once a hero is created, if set as a trigger. The created hero can be retrieved as "bj_lastCreatedUnit"
*The global unit array HSS_Heroes refers to heroes selected using the system
*The global group HSS_SelectableHeroes contains to all those heroes initialy selectable using the system
*Since players are given control of Player 15s units, the bong sound is played(unavoidable), and a message is displayed(also unavoidable)
However, in the gameplay constants you can edit this displayed message, as seen in this map
*Selecting the random hero flag before the map is loaded creates random heroes for all players
*You can edit the fields in HSSSetup to load the system when you want, or even completely scratch that trigger and do it yourself some place else, though this is not recommended
The more advanced configuration required for the system to function, or to be further customized
*All system used global arrays are stored as the id of the player they are for, ex. HSS_HeroSelection = GetPlayerId(unit)
*As seen in HSSSetup in this map, you must store the Hero Selection Gallery Rect and Hero Creation Loc for every player in your map, else the system does not know where they are
HSS_HeroSelection in a rect array used for the hero gallery
HSS_HeroCreation is a location array use for the creation of heroes
*The global trigger HSS_CreatedHeroTrigger will run once a hero is created, if set as a trigger. The created hero can be retrieved as "bj_lastCreatedUnit"
*The global unit array HSS_Heroes refers to heroes selected using the system
*The global group HSS_SelectableHeroes contains to all those heroes initialy selectable using the system
*Since players are given control of Player 15s units, the bong sound is played(unavoidable), and a message is displayed(also unavoidable)
However, in the gameplay constants you can edit this displayed message, as seen in this map
*Selecting the random hero flag before the map is loaded creates random heroes for all players
*You can edit the fields in HSSSetup to load the system when you want, or even completely scratch that trigger and do it yourself some place else, though this is not recommended
Systems Code:
JASS:
library HSS initializer GetOrders needs GetPlayerNameColored
//=====HSS 1.30b=====\\
globals
// Config. Options:
private constant integer ChooseHeroUnitId = 039;h000039; // Rawcode of Choose Hero Unit
private constant integer ChooseHeroOrder = 1747988528 // Orderid when Choose Hero is selected
private constant integer RandomHeroUnitId = 039;h001039; // Rawcode of Random Hero Unit
// Use 0 if you don't want to let players choose a random hero
private constant integer RandomHeroOrder = 1747988529 // Orderid when Random Hero is selected
private constant real TimeLimit = 60. // Time limit for selecting heroes, after which players get a random hero
// Use 0. if you desire no time limit
private constant real MaxCompTime = 15. // Max time a computer will take to choose a random hero, this should be lower then TimeLimit
private constant boolean CleanUp = true // Whether you want the hero gallery removed after all players have a hero
private constant boolean DoubleHeroes = false // Whether you want to allow more then one of the same hero to be chosen
private constant boolean CompHeroes = true // Whether you want computer players to choose heroes.
private constant boolean RemoveChosen = true // Whether you want chosen heroes removed if DoubleHeroes is true
// If this is false, heroes will become opaque and non-selectable
private constant string DialogTitle = "Hero Selection Time" // The title of the timerdialog that shows the remaining selection time
//===========Don't touch past here unless you know what you are doing===========\\
// Needed Globals:
public unit array Heroes
public trigger CreatedHeroTrigger = null
public location array HeroCreation
public rect array HeroSelection
public group SelectableHeroes = CreateGroup()
public integer Players = 0
private unit Hero = null
private trigger Sell = CreateTrigger()
private trigger Orders = CreateTrigger()
private trigger Setup = CreateTrigger()
private string S = " has chosen the "
endglobals
//=====Get Selection Orders=====\\
private function GetSelectionOrders_Effects takes nothing returns nothing
local integer id = GetIssuedOrderId()
local unit u = GetOrderedUnit()
if GetTriggerEventId()==EVENT_UNIT_ISSUED_ORDER and id!=851972 then
call BJDebugMsg("The order for that selection is |cffff0000"+I2S(id)+"|r.")
endif
call DisableTrigger(GetTriggeringTrigger())
call PauseUnit( u, true)
call IssueImmediateOrder( u, "stop" )
call PauseUnit( u, false)
call EnableTrigger(GetTriggeringTrigger())
endfunction
private function GetSelectionOrders takes nothing returns boolean
local real x
local real y
local unit u
if not bj_isSinglePlayer then
return false
endif
set x = GetPlayerStartLocationX(Player(0))
set y = GetPlayerStartLocationY(Player(0))
set u = CreateUnit(Player(15),039;Hpal039;,x,y,0)
set Setup = CreateTrigger()
call SetPlayerAlliance(Player(15),Player(0),ALLIANCE_SHARED_CONTROL,true)
call SetPlayerAlliance(Player(15),Player(0),ALLIANCE_SHARED_VISION,true)
if GetLocalPlayer()==Player(0) then
call SetCameraPosition(x,y)
call ClearSelection()
call SelectUnit(u,true)
endif
call UnitRemoveAbility(u, 039;Amov039;)
call UnitAddAbility(u, 039;Abun039;)
call UnitAddAbility(u,039;Asud039;)
call AddUnitToStock(u, ChooseHeroUnitId,1,1)
call AddUnitToStock(u, RandomHeroUnitId,1,1)
call SetUnitInvulnerable(u,true)
call UnitModifySkillPoints(u, -1)
call TriggerRegisterUnitEvent(Setup, u, EVENT_UNIT_ISSUED_ORDER )
call TriggerAddAction(Setup,function GetSelectionOrders_Effects)
call DestroyTrigger(GetTriggeringTrigger())
return false
endfunction
private function GetOrders takes nothing returns nothing
call TriggerRegisterPlayerChatEvent( Setup, Player(0), "-HSSGetOrders", true )
call TriggerAddCondition(Setup,Condition(function GetSelectionOrders))
endfunction
//=====Main System=====\\
private function Cleaner takes nothing returns nothing
if CleanUp then
loop
set Hero = FirstOfGroup(SelectableHeroes)
exitwhen Hero==null
call GroupRemoveUnit(SelectableHeroes,Hero)
call RemoveUnit(Hero) // Lets hope for no bugs.... <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite1" alt=":)" title="Smile :)" loading="lazy" data-shortname=":)" />
endloop
endif
call DestroyGroup(SelectableHeroes)
set SelectableHeroes = null
call DestroyTrigger(Sell)
call DestroyTrigger(Orders)
call DestroyTrigger(Setup)
set Sell = null
set Orders = null
set Setup = null
endfunction
private function CreateHero takes unit u, player p returns nothing
local integer id = GetPlayerId(p)
local real x = GetLocationX(HeroCreation[id])
local real y = GetLocationY(HeroCreation[id])
set Hero = CreateUnit(p,GetUnitTypeId(u),x,y,GetRandomReal(0.,360.))
if GetLocalPlayer()==p then
call SelectUnit(Hero,true)
call SetCameraPosition(x,y)
endif
if (IsPlayerInForce(GetLocalPlayer(), bj_FORCE_ALL_PLAYERS)) then
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, GetPlayerNameColored(p)+S+GetPlayerColorS(p)+GetUnitName(Hero)+"|r.")
endif
call SetPlayerAlliance(Player(15),p,ALLIANCE_SHARED_CONTROL,false)
call SetPlayerAlliance(Player(15),p,ALLIANCE_SHARED_VISION,false)
set Heroes[id] = Hero
if CreatedHeroTrigger != null then
set bj_lastCreatedUnit = Hero
if TriggerEvaluate(CreatedHeroTrigger) then
call TriggerExecute(CreatedHeroTrigger)
endif
endif
if not DoubleHeroes then
if RemoveChosen then
call RemoveUnit(u) // please don't bug <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite1" alt=":)" title="Smile :)" loading="lazy" data-shortname=":)" />
else
call UnitAddAbility(u,039;Aloc039;)
call SetUnitVertexColor( u, 255, 255, 255, 127 )
call GroupRemoveUnit(SelectableHeroes,u)
endif
endif
endfunction
private function GiveRandomHero takes player p, boolean forced returns nothing
if CountUnitsInGroup(SelectableHeroes)<=0 then
call BJDebugMsg("HSS Error: "+GetPlayerNameColored(p)+" |cffff0000will not recieve a hero because there are none left to give.")
return
endif
if forced then
set S = " has been forced into the "
else
set S = " has randomed the "
endif
set Hero = GroupPickRandomUnit(SelectableHeroes)
call CreateHero(Hero,p)
set S = " has chosen the "
endfunction
private function GiveComputerHero takes player p returns nothing
if MaxCompTime>TimeLimit then
call PolledWait(GetRandomReal(2.,TimeLimit-1.))
call BJDebugMsg("HSS Error: |cffff0000Your TimeLimit is lower then your MaxCompTime.")
else
call PolledWait(GetRandomReal(2.,MaxCompTime))
endif
call GiveRandomHero(p,false)
endfunction
private function GiveAllRandomHeroes takes nothing returns nothing
local integer i = 0
loop
exitwhen i>Players
if GetPlayerSlotState(Player(i))==PLAYER_SLOT_STATE_PLAYING and (CompHeroes or GetPlayerController(Player(i))!=MAP_CONTROL_COMPUTER) then
call GiveRandomHero(Player(i),false)
endif
call TriggerSleepAction(0.)
set i = i + 1
endloop
call Cleaner()
endfunction
private function Sold takes nothing returns nothing
set bj_ghoul[55] = GetSoldUnit()
if GetUnitTypeId(bj_ghoul[55])==ChooseHeroUnitId then
call CreateHero(GetSellingUnit(),GetOwningPlayer(bj_ghoul[55]))
else
call GiveRandomHero(GetOwningPlayer(bj_ghoul[55]),false)
endif
call RemoveUnit(bj_ghoul[55])
endfunction
private function StopOrders takes nothing returns nothing
local integer id = GetIssuedOrderId()
set Hero = GetTriggerUnit()
if id == 851972 or id == ChooseHeroOrder or id == RandomHeroOrder then
return
endif
call DisableTrigger(Orders)
call PauseUnit( Hero, true)
call IssueImmediateOrder( Hero, "stop" )
call PauseUnit( Hero, false)
call EnableTrigger(Orders)
endfunction
private function FilterHeroes takes nothing returns boolean
return IsUnitType(GetFilterUnit() , UNIT_TYPE_HERO)
endfunction
private function SetupHeroes takes nothing returns nothing
set Hero = GetEnumUnit()
call UnitRemoveAbility(Hero, 039;Amov039;)
call UnitAddAbility(Hero, 039;Abun039;)
call UnitAddAbility(Hero,039;Asud039;)
call AddUnitToStock(Hero, ChooseHeroUnitId,1,1)
if RandomHeroUnitId > 0 then
call AddUnitToStock(Hero, RandomHeroUnitId,1,1)
endif
call SetUnitInvulnerable(Hero,true)
call TriggerRegisterUnitEvent(Sell,Hero,EVENT_UNIT_SELL)
call TriggerRegisterUnitEvent( Orders, Hero, EVENT_UNIT_ISSUED_TARGET_ORDER )
call TriggerRegisterUnitEvent( Orders, Hero, EVENT_UNIT_ISSUED_POINT_ORDER )
call TriggerRegisterUnitEvent( Orders, Hero, EVENT_UNIT_ISSUED_ORDER )
endfunction
public function Start takes nothing returns nothing
local integer i = 0
local integer j = 0
local real x
local real y
local timer t = null
local timerdialog td
set Players = GetPlayers() - 1
call GroupEnumUnitsOfPlayer(SelectableHeroes,Player(15) , Condition(function FilterHeroes))
if IsMapFlagSet(MAP_RANDOM_HERO) then
call GiveAllRandomHeroes()
return
endif
call TriggerAddAction(Sell,function Sold)
call TriggerAddAction(Orders,function StopOrders)
call ForGroup(SelectableHeroes,function SetupHeroes)
loop
exitwhen i > Players
set x = GetRectCenterX(HeroSelection<i>)
set y = GetRectCenterY(HeroSelection<i>)
call SetPlayerAlliance(Player(15),Player(i),ALLIANCE_SHARED_CONTROL,true)
call SetPlayerAlliance(Player(15),Player(i),ALLIANCE_SHARED_VISION,true)
if GetLocalPlayer()==Player(i) then
call SetCameraPosition(x,y)
endif
if CompHeroes and GetPlayerSlotState(Player(i))==PLAYER_SLOT_STATE_PLAYING and GetPlayerController(Player(i))==MAP_CONTROL_COMPUTER then
call GiveComputerHero.execute(Player(i))
endif
set i = i + 1
endloop
if TimeLimit>0. then
set t = CreateTimer()
call TimerStart(t,TimeLimit,false,null)
set td = CreateTimerDialog(t)
call TimerDialogSetTitle(td,DialogTitle)
call TriggerSleepAction(0.)
call TimerDialogDisplay(td,true)
endif
loop
set i = 0
set j = 0
loop
exitwhen i > Players
if Heroes<i>==null and GetPlayerSlotState(Player(i))==PLAYER_SLOT_STATE_PLAYING and (CompHeroes or GetPlayerController(Player(i))!=MAP_CONTROL_COMPUTER) then
if t!=null and TimerGetRemaining(t)<=.1 then
call GiveRandomHero(Player(i),true)
endif
set j = j + 1
elseif GetLocalPlayer()==Player(i) then
call TimerDialogDisplay(td,false)
endif
set i = i + 1
endloop
exitwhen j<=0
if CountUnitsInGroup(SelectableHeroes)<=0 then
call BJDebugMsg("HSS Error: |cffff0000There are no more heroes left to select.")
exitwhen true
endif
call TriggerSleepAction(0.)
endloop
if t!=null then
call DestroyTimer(t)
call DestroyTimerDialog(td)
set t = null
set td = null
endif
call Cleaner()
endfunction
endlibrary</i></i></i>
Setup Code:
JASS:
scope HSSSetup
//=====HSS 1.30b=====\\
globals
// This trigger can be referred to as HSSSetup_Trigger publically
// I have this as running after .01s, but you can execute it when you want, or change that time length to your liking (amoung other things)
public trigger Trigger = CreateTrigger()
endglobals
private function Actions takes nothing returns nothing
// Get total players in your map, but in JASS players start at 0, so subtract 1
local integer i = GetPlayers() - 1
// Loop through players in map, setting up their hero selection rects and hero creation locs
loop
exitwhen i < 0
// This is the rect where this player can choose heroes from
set HSS_HeroSelection<i> = gg_rct_HeroSelection
// This is the loc where this players heroes will be created once chosen
set HSS_HeroCreation<i> = GetStartLocationLoc(GetPlayerStartLocation(Player(i)))
set i = i - 1
endloop
// Store the trigger to be ran when a hero is created
set HSS_CreatedHeroTrigger = gg_trg_PostHeroCreation
// Start the selection system
call HSS_Start()
// Clean leak
call DestroyTrigger(Trigger)
set Trigger = null
endfunction
//===========================================================================
public function InitTrig takes nothing returns nothing
call TriggerAddAction( Trigger, function Actions )
// Length in time after game starts that we want to start the HSS
call TriggerRegisterTimerEvent(Trigger,.01,false)
endfunction
endscope</i></i>
Version History:
- 1.30b - Fixed the problem with -HSSSetup not working to well
- 1.30 - Several new config. options
Added a function to GetPlayerNameColored Library, to allow for colored hero names
Minor coding updates/optimizations
Errors messages now display in red
Now reports an error if your max computer hero selection time is greater then your total selection time
Improved the way hero selection messages were displayed
Minor test map updates - 1.20 - Setup and readme completely redone
HSS is now a library that contains the GetSelectionOrders system
HSSSetup now sets up the systems variables and starts the HSS
A few minor coding enhancements per Vexorians advice
New option for max computer hero selection time - 1.10 - Users no longer need to manually input the number of players
Added error messages in case the map runs out of heroes
Slight updates/additions to readme
Slight code updates and optimizations
A few minor bug fixes(nothing related to system functionality) - 1.00 - Initial Release
Please report any and all bugs, and please leave comments and thoughts. Thanks and enjoy!!