| 04-19-2008, 05:40 PM | #1 | ||
Hero Selection System 1.30
![]() A dynamic, completely customizable Hero Selection System! Had originally been using Vex's system for a map I have been playing around with, and finally got fed up with players not being able to view the same hero simultaneously. So, with a little inspiration and minor coding help from Vexs system, and after some discussion with Fulla, this system was born. Credits to Vexorian for his original system and the GetPlayerNameColored function, and to Fulla for our hero selection discussions. Credits also to Acehart for the original demo map he made, of which its terrain I used as a template for this map. Read Me - Basic:
Read Me - Advanced
Systems Code: JASS:library HSS initializer GetOrders needs GetPlayerNameColored //=====HSS 1.30=====\\ 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(Setup) call PauseUnit( u, true) call IssueImmediateOrder( u, "stop" ) call PauseUnit( u, false) call EnableTrigger(Setup) endfunction private function GetSelectionOrders takes nothing returns boolean local real x local real y local unit u if 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.... :) 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 :) else call UnitAddAbility(u,'Aloc') 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, 'Amov') call UnitAddAbility(Hero, 'Abun') call UnitAddAbility(Hero,'Asud') 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 Setup Code: JASS:scope HSSSetup //=====HSS 1.30=====\\ 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 the 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 Version History:
Please report any and all bugs, and please leave comments and thoughts. Thanks and enjoy!! |
| 04-19-2008, 09:40 PM | #2 |
It's a scope with no initializer? How are people supposed to use it? Edit: I see, that's lame. This is a vJass map so I demand vJass to be exploited. 1. Use this, instead of your custom script section, have it in some trigger. JASS:library GetPlayerNameColored function GetPlayerNameColored takes player id returns string local playercolor col=GetPlayerColor(id) local string r=GetPlayerName(id) if col == PLAYER_COLOR_RED then set r="|cffff0000"+r+"|r" elseif col == PLAYER_COLOR_BLUE then set r="|cff0000ff"+r+"|r" elseif col == PLAYER_COLOR_CYAN then set r="|cff93ffc9"+r+"|r" elseif col == PLAYER_COLOR_PURPLE then set r="|cff400080"+r+"|r" elseif col == PLAYER_COLOR_YELLOW then set r="|cffffff00"+r+"|r" elseif col == PLAYER_COLOR_ORANGE then set r="|cffff8000"+r+"|r" elseif col == PLAYER_COLOR_GREEN then set r="|cff00c400"+r+"|r" elseif col == PLAYER_COLOR_PINK then set r="|cffff80c0"+r+"|r" elseif col == PLAYER_COLOR_LIGHT_GRAY then set r="|cff808080"+r+"|r" elseif col == PLAYER_COLOR_LIGHT_BLUE then set r="|cffc1c1ff"+r+"|r" elseif col == PLAYER_COLOR_AQUA then set r="|cff5e5e2f"+r+"|r" elseif col == PLAYER_COLOR_BROWN then set r="|cff004000"+r+"|r" else set r="|cff000000"+r+"|r" endif return r endfunction endlibrary 1. Make HSS a library that requires it and also a library called HSS_setup, also make start begin automatically (an initializer) 2. Is the trigger that begins with GetSelectionOrders_Effects part of your HSS? Then include that in the library or make a library required by it. 3. Regarding the contents of HSS_setup, it should replace this: JASS:
local integer i = 0
// Loop through players in map, setting up their hero selection rects and hero creation locs
loop
exitwhen i > 3
set HSS_HeroSelection[i] = gg_rct_HeroSelection
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_PostHeroCreationSo, in other words your users will just need to modify the setup library and just include your HSS instead of messing with when and how to call ExecuteFunc("Start_HSS") , btw, I should advice against ever ExecuteFunc, if necessary use .execute() this time it was not necessary. The reasoning is that jasshelper will some day integrate the map optimizer's capabilities but taking advantage of the higher level syntax, so if we just use alternatives to ExecuteFunc the optimization will be much better than with the optimizer, .execute() is faster anyways. 4. Oh yes, if you make a function public, make sure to document what it does. ... I don't like this, don't worry, the reason I don't like it is that my old hero system code has a lot of messy stuff, and yours has inherited most of the bad things old hss had. Can you try fixing them? Will save me the time of having to update it, for example it is way too liberal about dynamic triggers. |
| 04-20-2008, 02:23 PM | #3 |
updated if there is anything you don't agree with or still have problems accepting, let me know and I will happily explain the reasoning behind my madness |
| 04-20-2008, 04:24 PM | #4 |
JASS:private function SinglePlayer takes nothing returns boolean return bj_isSinglePlayer endfunction |
| 04-20-2008, 05:18 PM | #5 |
Anyways, it needs big cleanup specially the part that's from my system, why did you base it from my system anyways? I think the final result is too different from mine so I doubt you really needed my code if it isn't for just making the system messier. If you are blocking orders like I did in the old system using DisableTrigger, etc. Change it to a 0. seconds timeout timer to order stop ASAP. |
| 04-20-2008, 06:38 PM | #6 |
As both are different approaches, your HSS should be updated anyway Vexorian. Especially fixing that damn bug that desyncs Mac users. |
| 04-20-2008, 06:54 PM | #7 |
@Dusk - was going to do that, but ended up adding a condition function, dont remember why *now i remember - did not feeling like having to declare all my locals, then check if single player, then set them all up, that was it @Vex - I based it on yours because it worked like I wanted this one to, minus the multi-player-selecting 1 unit part I dont really see how it is "messy", or needs all this "cleanup" I do disable the trigger, if it is a huge performance gain by using a timer as opposed to disabling and enabling the trigger, I would change it, but as it is now, i cant really justify doing so @Soki - this really is not much different then Vexs (the approach is exactly the same), other then the fact that I think its cleaner, more optimized, and allows multiple players to select and view the same hero (which is why the install/setup requires an extra step) then down part is you do not get the selection arrow when viewing a hero, but then that is a product of the system |
| 04-20-2008, 07:16 PM | #8 |
This makes me want to package the system I've had in DoE and AotZ for years and release it, it's shorter, easier to read, and does all of the same stuff as this one. (Just without the config, hence the need to package) EDIT: Actually, looking at your code mine does some stuff yours does not. Hrm. |
| 04-20-2008, 07:25 PM | #9 |
whats stopping you? the fact there were no real good updated ones out is what made me make this for myself, and eventually release it |
| 04-20-2008, 07:31 PM | #10 | |
Quote:
|
| 04-20-2008, 08:12 PM | #11 | |
Quote:
i needed to do the work anyhow, because Vexs was not quite what I wanted anymore, the work was already done, uploading it here and adding a readme was simply all the extra work needed how you would render this obsolete i cannot guess, if i remember correctly, you dont even let players view skills. Other then perhaps flamboyant effects, which i dont remember in DoE or AotZ, im at a loss for all these featuers yours contains that I seem to have overlooked, and the fact that you may save a few line somewhere I don't see as being anything special other then the fact that your name is Rising_Dusk, i can't say people would like it any better, but who am I too judge, I'm not the one with two succesful maps at WC3C ;) |
| 04-20-2008, 08:15 PM | #12 | |
Quote:
|
| 04-20-2008, 08:21 PM | #13 |
o well, can't say I'd lament people deciding against the use of my system all the usage I care about I'm getting, the rest is merely superfluous obsolete away all mighty sun setting one :), just keep me updated, so I can avoid catering to Vexs needs :) |
| 04-21-2008, 11:30 AM | #14 |
Dusk has his own selection system?? I thought you were using Vex's system, with little modifications by adding the stories ![]() |
| 04-21-2008, 12:01 PM | #15 |
Interesting. Does this system supports remaking maps? Also completely hiding units is way better than making them transparent. I sometimes try to click on the transparent unit (don't ask why). |
