System Hero Selection System 1.30b

emjlr3

Change can be a good thing
Reaction score
395
Hero Selection System 1.30b

HSS.jpg


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

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

Systems Code:
JASS:
library HSS initializer GetOrders needs GetPlayerNameColored

//=====HSS 1.30b=====\\

globals
    // Config. Options:
    private constant integer ChooseHeroUnitId = 'h000' // Rawcode of Choose Hero Unit
    private constant integer ChooseHeroOrder = 1747988528 // Orderid when Choose Hero is selected
    private constant integer RandomHeroUnitId = 'h001' // 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),'Hpal',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, 'Amov')
    call UnitAddAbility(u, 'Abun')
    call UnitAddAbility(u,'Asud') 
    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)+&quot;|r.&quot;)
    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&#039;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;Aloc&#039;)
            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)&lt;=0 then
        call BJDebugMsg(&quot;HSS Error: &quot;+GetPlayerNameColored(p)+&quot; |cffff0000will not recieve a hero because there are none left to give.&quot;)
        return
    endif
    
    if forced then
        set S = &quot; has been forced into the &quot;
    else
        set S = &quot; has randomed the &quot;
    endif
    
    set Hero = GroupPickRandomUnit(SelectableHeroes)
    call CreateHero(Hero,p)
    
    set S = &quot; has chosen the &quot;
endfunction
private function GiveComputerHero takes player p returns nothing
    if MaxCompTime&gt;TimeLimit then
        call PolledWait(GetRandomReal(2.,TimeLimit-1.))
        call BJDebugMsg(&quot;HSS Error: |cffff0000Your TimeLimit is lower then your MaxCompTime.&quot;)
    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&gt;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, &quot;stop&quot; )
    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;Amov&#039;)
    call UnitAddAbility(Hero, &#039;Abun&#039;)
    call UnitAddAbility(Hero,&#039;Asud&#039;) 
    call AddUnitToStock(Hero, ChooseHeroUnitId,1,1) 
    if RandomHeroUnitId &gt; 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 &gt; 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&gt;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 &gt; 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)&lt;=.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&lt;=0
        if CountUnitsInGroup(SelectableHeroes)&lt;=0 then
            call BJDebugMsg(&quot;HSS Error: |cffff0000There are no more heroes left to select.&quot;)
            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 &lt; 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!!
 

Attachments

  • HSS.jpg
    HSS.jpg
    296.7 KB · Views: 451
  • Hero Selection System 1.30b - emjlr3.w3x
    76.7 KB · Views: 671

Ghostwind

o________o
Reaction score
172
It works for me. Interesting how you can preview the hero's skills but it takes a long time to select them. Maybe better for RPG maps than fast-paced games where you need to pick buy and get the f*ck out there :thup:
 

emjlr3

Change can be a good thing
Reaction score
395
yea its really better for an AoS or RPG type game, where the first minute or so of the game are not really a big deal, and you can check out all the heroes

thnx for trying it out
 

PurgeandFire

zxcvmkgdfg
Reaction score
509
Wow, beautiful coding. =D

Really nice job. Especially on the map. I owned them all. I got to lvl 7 while they only got to level 3 (I was the tinker :D)

Yeah, I was just bored. Still, great job. Really good and easy to customize.
 

Kenny

Back for now.
Reaction score
202
Whoa, very nice selection system.

I can't find anything that may need to be changed, it looks spot on. Good work :)

By the way, was this at all inspired by the Age of Myths hero selection system, as it is pretty similar.
 

Atreyu

One Last Breath.
Reaction score
49
When you choose a hero, they become invisible? Neat... There's even a check mark and ability.... :thup::thup:
 

AceHart

Your Friendly Neighborhood Admin
Reaction score
1,494
How is this different (at least on the outside) from Vexorian's system?


JASS:
if DoubleHeroes then
    exitwhen true
endif


Wasn't really your day, was it? :p


> private integer Players = 4

Can't you find this out yourself?


Is there a "repick" option?


> they become invisible?

No, just unselectable (Locust).
Unless you set DoubleHeroes to true.
 

emjlr3

Change can be a good thing
Reaction score
395
Vexs does not allow multiple players to select and look at the same hero simultaneously (and most systems that allow this do not show heroes skills to look at). This system does. Other then that though, most of the differences are in the scripting, both efficiency and customizability, as well as its general method of selection.

JASS:
if DoubleHeroes then
    exitwhen true
endif


I am sorry I do not know what you mean about this....

@ Can't you find this out yourself?

perhaps, but a user defined variable works too

@ Is there a "repick" option?

no, I really think -repick is a flawed option, its either random, in which case you get a random hero, or you get to pick, what is the point of random if you just opt out of random heroes, not very random anymore....this really could be added, but then, I don't really agree with it

I just thought of something, if you do not allow double heroes, and there are no more heroes left to choose, but people trying to choose them, they either will not able to choose, or an op limit will result from trying to find a random one. Though that is really the users fault, its still a problem with the system.
 

Kenny

Back for now.
Reaction score
202
> I just thought of something, if you do not allow double heroes, and there are no more heroes left to choose, but people trying to choose them, they either will not able to choose, or an op limit will result from trying to find a random one. Though that is really the users fault, its still a problem with the system.

So basically, to fix this problem, the game just has to have more hero options than number of players?
 

emjlr3

Change can be a good thing
Reaction score
395
> I just thought of something, if you do not allow double heroes, and there are no more heroes left to choose, but people trying to choose them, they either will not able to choose, or an op limit will result from trying to find a random one. Though that is really the users fault, its still a problem with the system.

So basically, to fix this problem, the game just has to have more hero options than number of players?

or allow double heroes, but then again if you got less heroes then players, and you do not allow double heroes, your map has a problem, lol

Isn't it the same as Vexorian's Hero Selection System?

re-read the top of post #8

Whoa, very nice selection system.

I can't find anything that may need to be changed, it looks spot on. Good work :)

By the way, was this at all inspired by the Age of Myths hero selection system, as it is pretty similar.

not at all, inspired by Vexs, with a little method help from Fulla
 

AceHart

Your Friendly Neighborhood Admin
Reaction score
1,494
> Vexs does not allow multiple players to select and look at the same hero simultaneously

Easily explains why I didn't notice :p


> perhaps, but a user defined variable works too

It is safe to assume that people that manage to import this into their map also manage to count the number of players they have.

But, what I would like to know is why that option is needed? And why do I have to set it?
What happens if it's wrong?

What happens if a players leaves before selection is done?


> if you got less heroes then players, and you do not allow double heroes, your map has a problem

Sort of.
Now, if the Hero system counted the players as well as the Heroes... :p


> I do not know what you mean about this

exitwhen DoubleHeroes
 

emjlr3

Change can be a good thing
Reaction score
395
@ MCR - should be right under the globals


@ What happens if it's wrong?

Bad news I suppose

@ What happens if a players leaves before selection is done?

Then their now computer owner would get a random hero after the alloted time,f a time is specified, else, I guess they never would, something to think about I guess, this would also cause no cleanup(which it seems I forogt to add a call Cleaner() in function Start, silly me)

@ exitwhen DoubleHeroes

yes, a silly goof on my part, lol
 

cr4xzZz

Also known as azwraith_ftL.
Reaction score
51
Such dumb person I am. I just noticed that I have to manually store the Gallery Rect and Hero Creation Rect... And I was pwning my head, thinking why does it create all Heroes at the map's centre... X_X

Anyway, this system really rox. Really simple to use, user friendly and such. GJ :thup:
 

waaaks!

Zinctified
Reaction score
255
can u make an all random mode and all pick using this hero selection system?
cause most people now wanted to use different heroes, not just heroes from ur team but all heroes, especially when playing with other players

for all random, this way the host can make the game random, not just making all players manually click the random button, because some people dont want random heroes, and maybe they wont use random and pick of their own
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top