//##Start##
//===================================================================================================
function SimError takes player ForPlayer, string msg returns nothing
local sound error=CreateSoundFromLabel( "InterfaceError",false,false,false,10,10)
if (GetLocalPlayer() == ForPlayer) then
call ClearTextMessages()
call DisplayTimedTextToPlayer( ForPlayer, 0.52, -1.00, 2.00, "|cffffcc00"+msg+"|r" )
call StartSound( error )
endif
call KillSoundWhenDone( error)
set error=null
endfunction
//##end##
//##Start##
//===================================================================================================
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
set col=null
return r
endfunction
//##End##
//##Start##
//******************************************************************************************************
//*
//* Theorically you won't need to change these functions unless you are an advanced mapper
//* that wants to improve the Selection System, I left a lot of comments just in case you want
//* to try, If you find a better way of doing this stuff send me the new functions in a pm at
//* wc3c, If I they improve the system, I'll replace mine with them and give you credit.
//*
//* ..........................
//* : Input Global Variables : (Used by the mapper to configure the Selection system)
//* ``````````````````````````
//* group udg_hss_SelectableHeroes Heroes used by the selection system
//*
//* group udg_hss_AvailableHeroes Heroes use by Random Hero functions
//*
//* rect array udg_hss_HeroSection Determines a Player's Hero Gallery (1 to 12)
//*
//* rect array udg_hss_HeroCreation Determines a Player's Hero Spawn Rect (1 to 12)
//*
//* boolean udg_hss_DoubleHeroesEnabled Determines if players can use already chosen heroes
//*
//* trigger udg_hss_CreatedHeroTrigger Determines the trigger to be executed after hero creation
//*
//* integer array udg_hss_abilities Determines the abilities used by the Selection System
//* udg_hss_abilities[0] must store Choose Hero
//* udg_hss_abilities[1] must store Random Hero
//* udg_hss_abilities[3] must store Selection Arrow
//* ...........................
//* : Output Global Variables : (Used to store the results of the Selection system)
//* ```````````````````````````
//* unit array udg_hss_Heroes Stores a player's hero after its creation (1 to 12)
//* 13 to 24 temporary store the current selected hero
//*
//******************************************************************************************************
//======================================================================================================
// Filter functions:
//
function hssFilterIsPossible takes nothing returns boolean
return IsUnitInGroup(GetFilterUnit(), udg_hss_SelectableHeroes) and RectContainsUnit( udg_hss_HeroSection[GetConvertedPlayerId(bj_groupEnumOwningPlayer)], GetFilterUnit() )
endfunction
function hssFilterIsAvailable takes nothing returns boolean
if GetTriggerUnit() == null and FirstOfGroup(udg_hss_AvailableHeroes) == null then
//* In Case a Weird thing happened and there were not heroes available for computers
return hssFilterIsPossible()
endif
return IsUnitInGroup(GetFilterUnit(), udg_hss_AvailableHeroes) and RectContainsUnit( udg_hss_HeroSection[GetConvertedPlayerId(bj_groupEnumOwningPlayer)], GetFilterUnit() )
endfunction
function hssFilterIsComputerWithoutHero takes nothing returns boolean
return GetPlayerController(GetFilterPlayer()) == MAP_CONTROL_COMPUTER and udg_hss_Heroes[GetConvertedPlayerId(GetFilterPlayer())] == null // and udg_hss_Heroes[GetPlayerId(GetFilterPlayer()) + 13] == null
endfunction
//======================================================================================================
//===========================================================================================
function SetPlayerHero takes player id, unit hero, string suffix returns nothing
//
// Determines a player's hero
// - id player argument is self explanatory (Create the hero for that player)
// - hero unit argument is self explanatory too (The hero that was in the gallery)
// - suffix string argument is added to the "(Player) has selected the (Hero)" message
//
// Will Run the trigger udg_hss_CreatedHeroTrigger after creating the hero
// (Use last created unit to reffer to the hero)
//
local integer P=GetPlayerId(id)+1
local real x=GetRectCenterX(udg_hss_HeroCreation[P])
local real y=GetRectCenterY(udg_hss_HeroCreation[P])
if (id == null) or (P > 12) or (hero == null) then
return //* Invalid Request, halt the function
endif
call GroupRemoveUnit( udg_hss_AvailableHeroes, hero ) //*Makes Hero Unselectable by Random Hero button / Computers
if not udg_hss_DoubleHeroesEnabled then
//*In case DoubleHeroesEnabled is false, make hero unselectable
call SetUnitColor( hero, GetPlayerColor(id) )
call UnitAddAbility(hero,'Aloc')
call SetUnitVertexColor( hero, 255, 255, 255, 127 )
endif
//* Create the new hero, select it and move the camera
set udg_hss_Heroes[P]=CreateUnit(id, GetUnitTypeId(hero),x,y, bj_UNIT_FACING )
call SelectUnitAddForPlayer( udg_hss_Heroes[P], id )
call SetCameraPositionForPlayer(id, x, y)
call DisplayTextToForce( GetPlayersAll(), GetPlayerNameColored(id)+" has selected the "+GetUnitName(hero)+" "+suffix)
//* In case there is a CreateHeroTrigger, Execute it and make sure Last Created Unit works
if udg_hss_CreatedHeroTrigger != null then
set bj_lastCreatedUnit=udg_hss_Heroes[P]
call ConditionalTriggerExecute( udg_hss_CreatedHeroTrigger )
endif
endfunction
//===========================================================================================
function hss_OrderToPreviewHero takes nothing returns nothing
//
// When A hero from the gallery is issued an order, check if it was the choose hero or the
// Random Hero Button, after that block the order by pausing the unit and ordering it to stop
//
local unit selunit=GetTriggerUnit()
local player selplayer=GetOwningPlayer(selunit)
local group uu
if GetIssuedOrderId() == OrderId("stop") or GetUnitUserData( selunit) == 1 or udg_hss_Heroes[13+GetPlayerId(selplayer)] != selunit then
//* A lot of conditions added because this trigger was causing massive lag
set selunit=null
set selplayer=null
return
endif
call SetUnitUserData(selunit,1) //* Part of the things that help this trigger to be lag-free, this trigger won't run when the unit has a Custom Value of 1
if GetIssuedOrderId() == 852273 then //*Select Hero Clicked
call SetUnitOwner( selunit, Player(PLAYER_NEUTRAL_PASSIVE), true )
call UnitRemoveAbility( selunit,udg_hss_abilities[2]) //* Remove the Selection Arrow Special Effect
call SetPlayerHero(selplayer, selunit, "")
elseif GetIssuedOrderId() == 852277 then //*Random Hero Clicked
set bj_groupEnumOwningPlayer=selplayer //* I use that Blizzard variable to make sure the filter chooses only the heroes a player can have
set uu=GetUnitsOfPlayerMatching(Player(PLAYER_NEUTRAL_PASSIVE), Condition(function hssFilterIsAvailable))
if FirstOfGroup(uu) == null then
//* There is a chance that the map had an incredibly low number of heroes and that eventually there
// weren't heroes available, in that case show an error message instead of continuing with the selection
call SimError(GetOwningPlayer(selunit), "Couldn't find heroes for Random Hero feature")
else
set selunit = GroupPickRandomUnit(uu) //* Save a random unit from the available heroes into a variable
call SetUnitOwner( GetTriggerUnit(), Player(PLAYER_NEUTRAL_PASSIVE), true )
call UnitRemoveAbility( GetTriggerUnit(), udg_hss_abilities[2]) //* Remove the Selection Arrow Special Effect
call SetPlayerHero(selplayer, selunit, "(Random Hero)") //* Calls the SetPlayerHero function with a "(Random Hero)" suffix for the message
endif
call DestroyGroup(uu)
set uu=null
else
call SimError(GetOwningPlayer(selunit), "Please choose your hero") //* The Player was trying to use an ability, show an error to him/her/ it?
endif
//* Pause the unit, order it to stop and unpause the unit, so it ignores the issued order
set selunit=GetTriggerUnit()
call PauseUnit( selunit, true)
call IssueImmediateOrder( selunit, "stop" )
call PauseUnit(selunit, false)
call SetUnitUserData( selunit, 0 )
set selunit=null
set selplayer=null
endfunction
//===========================================================================================
function hss_HeroIsClicked takes nothing returns nothing
//
// This function is executed when a Player Clicks an unit, if the unit belongs to his gallery,
// Give the unit to the player, and show the Selection Arrow, if it doesn't, restore the previus
// selected unit.
//
local unit sel=GetTriggerUnit()
local player sp=GetTriggerPlayer()
local integer a
local unit old=udg_hss_Heroes[13+GetPlayerId(sp)] //* Save the current hero that is selected by the player into a variable
if old != sel then //* Just to make "clicking a hero a lot of times till it says something funny" possible
call SetUnitOwner( old, Player(15), true ) //* give the last unit back to Neutral Passive
call UnitRemoveAbility( old, udg_hss_abilities[2]) //* Remove the Selection Arrow Special Effect
set udg_hss_Heroes[13+GetPlayerId(sp)] = null //* Clear the Global Variable
if udg_hss_Heroes[GetConvertedPlayerId(sp)] == null and IsUnitInGroup(sel,udg_hss_SelectableHeroes) and IsUnitOwnedByPlayer(sel,Player(15)) then
//* The Hero is a member of the Possible Selectable Heroes
if RectContainsUnit( udg_hss_HeroSection[GetConvertedPlayerId(sp)], sel ) then
//* The Hero can be used by the player
call SetUnitManaPercentBJ( sel, 100 ) //* Just in case the map author forgot to give the hero mana (So the hero abilities buttons don't show up blue)
set udg_hss_Heroes[13+GetPlayerId(sp)] = sel //* Save the selected unit into a global
call UnitAddAbility(sel, udg_hss_abilities[2]) //* Show the Selection Arrow Special Effect
call SetUnitUserData( sel,1) //* Just In case. (See the OrderToPreviewHero function for more information)
call SetUnitOwner( sel, sp, true ) //* Give the selected unit to the player
call SetUnitUserData( sel,0) //* Just In case. ^
else
//* The Hero doesn't belong to the player's team, show error message
call SimError(sp, "Your team can't choose that hero")
endif
endif
endif
set sel=null
set sp=null
set old=null
endfunction
//===========================================================================================
function hss_HeroShareVision takes nothing returns nothing
//
// Executed for every Selectable Hero, makes sure a player can choose it and if that is true,
// makes the player share vision with the hero, so the player can click on the hero
//
if RectContainsUnit( udg_hss_HeroSection[bj_forLoopAIndex+1], GetEnumUnit() ) then
call UnitShareVision( GetEnumUnit(), Player(bj_forLoopAIndex), true)
endif
endfunction
//===========================================================================================
function hss_MakePlayerChooseHero_child takes nothing returns nothing
local player id=bj_groupEnumOwningPlayer
local unit current = udg_hss_Heroes[GetPlayerId(id) + 13]
call PolledWait(GetRandomReal(0.5,3))
call SetUnitUserData( current, 0)
if IsUnitOwnedByPlayer( current, id) then
call IssueImmediateOrderById( current, 852273)
endif
set id=null
set current=null
endfunction
function hss_MakePlayerChooseHero takes player id, unit hero returns boolean
//
// Makes a Player Choose a hero, but makes sure it looks as if the player choosed it
// calls hss_MakePlayerChooseHero_child in another thread, returns false if the hero
// wasn't selectable / the player already had a hero.
//
local trigger thread=CreateTrigger()
local boolean res=false
if udg_hss_Heroes[GetPlayerId(id) + 13] != null and udg_hss_Heroes[GetPlayerId(id) + 13] != hero then
call SetUnitOwner( udg_hss_Heroes[GetPlayerId(id) + 13], Player(15), true ) //* give the last unit back to Neutral Passive
call UnitRemoveAbility( udg_hss_Heroes[GetPlayerId(id) + 13], udg_hss_abilities[2]) //* Remove the Selection Arrow Special Effect
endif
if udg_hss_Heroes[GetPlayerId(id)+1] == null and IsUnitInGroup(hero,udg_hss_SelectableHeroes) and IsUnitOwnedByPlayer(hero,Player(15)) then
set udg_hss_Heroes[GetPlayerId(id) + 13] = hero
call UnitAddAbility( hero, udg_hss_abilities[2])
call SetUnitOwner( hero, id, true)
set bj_groupEnumOwningPlayer=id
call TriggerAddAction( thread, function hss_MakePlayerChooseHero_child )
call TriggerExecute(thread)
set res=true
endif
call DestroyTrigger(thread)
set thread=null
set hero=null
set id=null
return res
endfunction
//===========================================================================================
function StartVxHSS takes boolean rand, boolean comps, boolean cleanup returns nothing
//
// (The Main Function that Starts the Selection System and Finishes it)
//
// - rand boolean argument determines the availability of the random hero option.
// - comps boolean argument determines if Computer Players can Choose their Heroes
// - cleanup boolean argument determines if the gallery heroes are removed once everybody gets a hero.
//
local group heroes=CreateGroup()
local unit current
local integer a=0
local real x //* To easily save a coordinate I use x and y
local real y
local trigger UnitSel=CreateTrigger()
local trigger UnitOrder=CreateTrigger()
local force forcevar
local player ai
call TriggerAddAction(UnitOrder, function hss_OrderToPreviewHero)
call TriggerAddAction(UnitSel, function hss_HeroIsClicked)
set bj_wantDestroyGroup=false
call GroupAddGroup(udg_hss_SelectableHeroes,heroes)
loop
set current = FirstOfGroup(heroes)
exitwhen current == null //* Clearly better than a ForGroup call
//* Hero Setup for the Selection System:
call GroupRemoveUnit(heroes, current)
call UnitRemoveAbility(current, 'Amov' ) //* Removes movement
call UnitRemoveAbility(current, 'Aatk' ) //* Removes Attack
call UnitAddAbility(current, udg_hss_abilities[0] ) //* Adds Choose Hero Button
if rand then
call UnitAddAbility(current, udg_hss_abilities[1] ) //* Adds Random Hero Button
endif
//* Register Order events for the hero
call TriggerRegisterUnitEvent( UnitOrder, current, EVENT_UNIT_ISSUED_TARGET_ORDER )
call TriggerRegisterUnitEvent( UnitOrder, current, EVENT_UNIT_ISSUED_POINT_ORDER )
call TriggerRegisterUnitEvent( UnitOrder, current, EVENT_UNIT_ISSUED_ORDER )
endloop
call DestroyGroup(heroes)
loop
exitwhen a>11
set x=GetRectCenterX(udg_hss_HeroSection[a+1])
set y=GetRectCenterY(udg_hss_HeroSection[a+1])
//* Move camera and spacebar point for the player
if GetLocalPlayer() == Player(a) then
call SetCameraPosition(x,y)
call SetCameraQuickPosition(x,y)
endif
set bj_forLoopAIndex=a
call ForGroup( udg_hss_SelectableHeroes, function hss_HeroShareVision)
call TriggerRegisterPlayerSelectionEventBJ( UnitSel, Player(a), true ) //* Register a selection event for the player
set a=a+1
endloop
//* Setup Completed
if rand and IsMapFlagSet(MAP_RANDOM_HERO) then
//* Random Hero feature is enabled and the Game Created Checked the Random Hero Option
//* So this will automatically choose a Random Hero for every player
set a=0
loop
exitwhen a>11
call TriggerSleepAction(0) //* Just to give war3 a breathing space
if GetPlayerSlotState(Player(a)) == PLAYER_SLOT_STATE_PLAYING and (comps or GetPlayerController(Player(a)) != MAP_CONTROL_COMPUTER) then
//* The Player is playing (uh?)
//* Computer Players shouldn't automatically get a hero if comps is false
set bj_groupEnumOwningPlayer=Player(a) //* I use that Blizzard variable to make sure the filter chooses only the heroes a player can have
set heroes = GetUnitsOfPlayerMatching(Player(PLAYER_NEUTRAL_PASSIVE), Condition(function hssFilterIsAvailable))
set current = GroupPickRandomUnit(heroes)
if current == null then //* No more available heroes, use a repeated hero
call DestroyGroup(heroes)
set bj_groupEnumOwningPlayer=Player(a)
set heroes = GetUnitsOfPlayerMatching(Player(15), Condition(function hssFilterIsPossible))
set current = GroupPickRandomUnit(heroes)
endif
call SetPlayerHero(Player(a), current, "(Automatic)") //* Calls the SetPlayerHero function with an "(Automatic)" preffix
call DestroyGroup(heroes)
endif
set a=a+1
endloop
elseif comps then
//* Automatically Choose random heroes for computer players when comps is true
set a=0
loop
call TriggerSleepAction( GetRandomReal(0.05, 2) ) //* To make things realistic
set forcevar = GetPlayersMatching(Condition(function hssFilterIsComputerWithoutHero)) //* Save Computer Players that don't have heroes into a force
set ai = ForcePickRandomPlayer(forcevar)
//* Once ai==null the force is empty => there are no more computer players that need a hero
exitwhen ai==null or a>40 //* About the a>40 : There is a chance that it would happen (Low number of available heroes)
set bj_groupEnumOwningPlayer=ai //* Once again this thing
set heroes = GetUnitsOfPlayerMatching(Player(PLAYER_NEUTRAL_PASSIVE), Condition(function hssFilterIsAvailable))
set current = GroupPickRandomUnit(heroes)
if current == null and a>30 then //* a>30 because it could be that a player was about to select somebody
call DestroyGroup(heroes)
set bj_groupEnumOwningPlayer=ai //* Once again this thing
set heroes = GetUnitsOfPlayerMatching(Player(PLAYER_NEUTRAL_PASSIVE), Condition(function hssFilterIsPossible))
set current = GroupPickRandomUnit(heroes)
endif
call hss_MakePlayerChooseHero(ai, current)
call DestroyGroup(heroes)
call DestroyForce(forcevar)
set a=a+1
endloop
set forcevar=null
set ai=null
endif
endfunction
//##End##
Name | Type | is_array | initial_value |
ACage | destructable | No | |
AG1 | group | No | |
AG2 | group | No | |
AG3 | group | No | |
AG4 | group | No | |
AG5 | group | No | |
Amy | unit | No | |
AmyCellDoor | destructable | No | |
AmyPVP | unit | No | |
ARank | unit | No | |
ARK | timerdialog | No | |
ARKCollison | timer | No | |
ATeleport | unit | No | |
Big | unit | No | |
BingoParts | questitem | No | |
BioLizard | unit | No | |
Black_Level | integer | No | |
blastgraphic | effect | No | |
Blink_Storm_Caster | unit | Yes | |
Blink_Storm_Target | unit | Yes | |
Blink_Storm_Targets | group | Yes | |
CB_Level | integer | No | |
CEB | unit | No | |
CEG | unit | No | |
CELB | unit | No | |
CEO | unit | No | |
CEP | unit | No | |
CER | unit | No | |
CEW | unit | No | |
Chaos | unit | No | |
Chaos4 | unit | No | |
ChaosE | questitem | No | |
ChaosEmerald | integer | Yes | |
Charmy | unit | No | |
CharmyPVP | unit | No | |
ChTeleport | unit | No | |
Cinematic | integer | No | |
CP1 | unit | No | |
CP2 | unit | No | |
CP3 | unit | No | |
CP4 | unit | No | |
CQR | questitem | No | |
Cream | unit | No | |
CreamPVP | unit | No | |
CreamsMother | quest | No | |
CrTeleport | unit | No | |
CTeleport | unit | No | |
Dandude776 | unit | No | |
DeForm | terraindeformation | No | |
DElf | unit | No | |
E102 | unit | No | |
EContainer | destructable | No | |
EG_Count | integer | No | |
EggMan | unit | No | |
Eggmantrans | unit | No | |
Emerl | unit | No | |
Enlarged | unit | No | |
Espio | unit | No | |
EspioPVP | unit | No | |
EsTeleport | unit | No | |
ETeleport | unit | No | |
Fat_Group | group | No | |
FightRoundWorld | quest | No | |
FinalHazard | unit | No | |
FixCasino | timer | No | |
FRWR | questitem | No | |
Gemerl | unit | No | |
Group | group | No | |
Hammer_Level | integer | No | |
hss_abilities | abilcode | Yes | |
hss_AvailableHeroes | group | No | |
hss_CreatedHeroTrigger | trigger | No | |
hss_DoubleHeroesEnabled | boolean | No | |
hss_HeroCreation | rect | Yes | |
hss_Heroes | unit | Yes | |
hss_HeroSection | rect | Yes | |
hss_LimitTime | real | No | |
hss_SelectableHeroes | group | No | |
HyperSonic | unit | No | |
KC | unit | No | |
KillEggRobotMKII | questitem | No | |
Knuckles | unit | No | |
KnucklesPVP | unit | No | |
KTeleport | unit | No | |
LeftPiston | unit | No | |
Magnum | unit | No | |
MSG | unit | No | |
MSM | unit | No | |
MSP | unit | No | |
Omega | unit | No | |
Pheon_Missile | effect | Yes | |
Player_Integer | integervar | Yes | |
Point | location | No | |
Point_Of_Wave | real | No | |
QuestBarrier | unit | No | |
Rabbit | unit | No | |
RC | unit | No | |
RCR | group | No | |
ReachLv6 | questitem | No | |
RecruitCharmy | quest | No | |
RecruitE102 | quest | No | |
RecruitEspio | quest | No | |
RecruitVector | quest | No | |
Reinforcements | timer | No | |
RepairCasinopolis | quest | No | |
Repairs | timerdialog | No | |
Rewindow | timerdialog | No | |
RG1 | group | No | |
RG2 | group | No | |
RG3 | group | No | |
RG4 | group | No | |
RG5 | group | No | |
RightPiston | unit | No | |
Rouge | unit | No | |
RougePVP | unit | No | |
RTeleport | unit | No | |
S1FT | texttag | No | |
S1TimeAttack | timer | No | |
S2FT | texttag | No | |
S2TimeAttack | timer | No | |
S3FT | texttag | No | |
S3TimeAttack | timer | No | |
SA2FT | texttag | No | |
SACountDown | timerdialog | No | |
SAFT | texttag | No | |
SAQR | questitem | No | |
SAQuest | quest | No | |
SATimeAttack | timer | No | |
Scale | real | Yes | |
SCDFT | texttag | No | |
SCDTimeAttack | timer | No | |
SFactory | unit | No | |
Shadow | unit | No | |
ShadowPVP | unit | No | |
Shields | unit | No | |
ShTeleport | unit | No | |
Sonic | unit | No | |
SonicPVP | unit | No | |
SpareParts | item | No | |
STeleport | unit | No | |
SvS1 | camerasetup | No | |
Tails | unit | No | |
TailsPVP | unit | No | |
Target_Random | unit | Yes | |
TheEye | unit | No | |
TheLeaderboard | leaderboard | No | |
Tidal_Level | integer | No | |
Tikal | unit | No | |
Timequest | questitem | No | |
Tornado | unit | No | |
Tornado2 | unit | No | |
TTeleport | unit | No | |
Vector | unit | No | |
VectorPVP | unit | No | |
VTeleport | unit | No | |
Wrath_Perfect | integer | No | |
Zero | unit | No | |
Zeroweak | unit | No |