| 07-21-2008, 01:49 AM | #1 | |
HCS - HeroChooseSystem
I decided to post this since I wanted to remake the (GUI) herochoose I was using before. Then again, I thought "if you're going to make one anyway, why not release it?" So, what does this system offer, what makes it "special"? 1. It features a variable number of teams That's right. You can have 1-12 teams, for 12 players, or even 16 teams if you want to include all the neutral players, although noone will probably ever want to do that.
2. It "looks" good Ever played AotZ or DoE? Well, then you basically know how this system looks like: It will give every choosable hero an ability that the user can activate in order to choose that hero. Also you can define a custom camera-setting for each team, the camera will get locked to that setting aslong as the system is running. 4. It's easy to use It's not hard to use at all, still it will provide you with a very flexible way of handling choosed heroes, and starting and ending the herochoose. 5. Includes randomness It will take care of choosing a random hero if a player wants one, you'll only have to tell the system which unit(type) it is that will give a random hero. Also the system will give random heroes to players who weren't fast enough to choose one - unless you disable this, of course. 6. It's customizable You can choose if you want to enable or disable multiple picking of the same hero, if you want the heroes only to be hidden instead of removed(for remakes), you can specify the error-msg given to players that can't pick a certain hero, and you can specify the effect that will be used when a hero is picked. 7. It is remake-friendly You can run it as often as you want. Aslong as wc3 doesn't crash, no buts. 8. Its user friendly It saves the alliance settings you've done with the DummyPlayer and restores them when the system is finished, no need to worry there. Also it makes it impossible for players to choose heroes they shall not choose. The attached example-map, which also includes the system, shows that this system is really easy to use. I'll also post the example-script into this thread, so people can look through it without having to dl/open the map. First, the documentation: JASS://********************************************************* // // HCS - HeroChooseSystem v1.2f // // by Blubb-Tec // //********************************************************* //========================================================= //********************************************************* // // IMPLEMENTATION: // Copy the HCS Dummy unit aswell as the HCS Choose Unit ability and this trigger into your map. // //********************************************************** //========================================================== //********************************************************** // USAGE: // // For Configuration, look into the HCS-Trigger, information about // needed configurations will be given there. This is only an // instruction about which functions need to be called. // // There are 2 functions you need to know, 2 optional ones, and 2 callbacks you have to create. // // function HCS_AddTeam takes group heroes, force team, camerasetup cam, HCS_CallbackFunc callback, real SpawnX, real SpawnY returns nothing // // group heroes: the heroes that shall be choosable for the given team. DO NOT modify this group afterwards! // force team: the players that shall be able to choose the given heroes. You can remove players from this force. // camerasetup cam: the camere that shall be applied for the players // real SpawnX and SpawnY: those two define the spawn-point of chosen heroes // HCS_CallbackFunc callback: your function that will be called whenever a hero is choosen // it has to follow this interface declaration: // // public function interface CallbackFunc takes unit created returns nothing // // unit created: the chosen and created hero // // Example: function MyHerochooseCallback takes unit created returns nothing // // // The next function is: // // function HCS_Start takes nothing returns nothing // // After you finished your HCS_AddTeam calls to set up the system, // call this function to start the herochoosing. // // // The first optional function is: // // function HCS_EnableRepick takes HCS_RepickCallback rc returns nothing // // HCS_RepickCallback rc: your custom function that is called when a player types -repick // this interface looks like the following: // // public function interface RepickCallback takes player p returns integer // // player p: The player that wants to repick his hero // return-value(integer): the unitid of the hero the player had chosen before. // The system needs it in order to make the hero availiable again. // // The second optional(and last) function is: // // function HCS_End takes nothing returns nothing // // Well, guess what this one does :P Right, it tells the system // that the choosing is over, and to clean itself up. You don't need // to call this manually, since it will automatically be called when the // timer has ended. // // // Thats all you need. If you got any questions, or are looking // for the latest version, look into this link: // // [url]http://www.wc3campaigns.net/showthread.php?p=1024151[/url] // // Thanks for reading! //********************************************************** //========================================================== //********************************************************** // // REQUIREMENTS & RESTRICTIONS: // vJass & patch 1.24 // //********************************************************** //========================================================== //********************************************************** Then the actual system: JASS://********************************************************* // // HCS - HeroChooseSystem v1.2f // // by Blubb-Tec // //********************************************************* //========================================================= //********************************************************* // // Configuration is further down. // If you found this system in some other map, please look // for the latest version and a better documentation under: // [url]http://www.wc3campaigns.net/showthread.php?p=1024151[/url] // //********************************************************** //========================================================== //********************************************************** library HCS initializer init // dirty lil' helpers begin here - globals private integer randomcounter private unit randomunit private hashtable ht endglobals private function GroupGetRandomUnitEnum takes nothing returns nothing if IsUnitHidden(GetEnumUnit()) then return else if randomcounter == 0 then set randomunit = GetEnumUnit() endif set randomcounter = randomcounter - 1 endif endfunction private function GroupGetRandomUnit takes group g, integer count returns unit set randomunit = null set randomcounter = GetRandomInt(0,count-1) call ForGroup(g, function GroupGetRandomUnitEnum) return randomunit endfunction private function SetUnitVal takes unit u, integer val returns nothing call SaveInteger(ht, StringHash(SCOPE_PREFIX+"_____"), GetHandleId(u), val) endfunction private function GetUnitVal takes unit u returns integer return LoadInteger(ht, StringHash(SCOPE_PREFIX+"_____"), GetHandleId(u)) endfunction // - and end here. // CONFIGURATION globals // DummyPlayer: the player who will own the choosable heroes, // and over whom all players will gain shared units. // make sure no other units of this player are visible during the herochoose, // or the players will be able to control them. public constant player DummyPlayer = Player(15) //Neutral Extra // DummyID: the ID of the dummy public constant integer DummyID = 'e000' // SoldDummyID: the id of the dummy unit that will serve as a 'tooltip' // for the "pick-this-hero"-button public constant integer SoldDummyID = 'e001' // SoldRandomID: same as above, but it will only be added to the hero // that serves as a random-chooser, so you can add another tooltip // for that one. public constant integer SoldRandomID = 'e002' // ChooseAbilID: the ID of the HCS Choose Unit ability you copied into your map public constant integer ChooseAbilID = 'A000' // randomPickerID: the ID of the hero that will serve as a random-hero-picker // whenever this unit can be choosen as a hero, it will give a random hero instead public constant integer randomPickerID = 'N000' // multiPick: defines if a single hero can be picked multiple times public constant boolean multiPick = false // HCDuration: the duration for which the Herochoose is running(in seconds) public constant real HCDuration = 30. // randomHeroesAtEnd: defines if players without heroes shall be given random ones // when the hero choose is over public constant boolean randomHeroesAtEnd = true // ErrorMsg: the message that will be given to a player who wants to choose a hero he can't public constant string ErrorMsg = "This Hero belongs to another team - you can't pick it!" // EyeCandyChoose: this string determines which effect shall be used on chosen heroes public constant string EyeCandyChoose = "Abilities\\Spells\\Human\\ReviveHuman\\ReviveHuman.mdl" // EyeCandyCreate: this string determines which effect shall be used on spawned Heroes public constant string EyeCandyCreate = "Abilities\\Spells\\Human\\ReviveHuman\\ReviveHuman.mdl" endglobals // CONFIGURATION END // library code begins here - struct FullAllianceSetting private boolean array s[8] private player p static method create takes player p returns FullAllianceSetting local FullAllianceSetting f = FullAllianceSetting.allocate() set f.p = p set f.s[0] = GetPlayerAlliance(DummyPlayer, p, ALLIANCE_PASSIVE) set f.s[1] = GetPlayerAlliance(DummyPlayer, p, ALLIANCE_HELP_REQUEST) set f.s[2] = GetPlayerAlliance(DummyPlayer, p, ALLIANCE_HELP_RESPONSE) set f.s[3] = GetPlayerAlliance(DummyPlayer, p, ALLIANCE_SHARED_XP) set f.s[4] = GetPlayerAlliance(DummyPlayer, p, ALLIANCE_SHARED_SPELLS) set f.s[5] = GetPlayerAlliance(DummyPlayer, p, ALLIANCE_SHARED_CONTROL) set f.s[6] = GetPlayerAlliance(DummyPlayer, p, ALLIANCE_SHARED_VISION) set f.s[7] = GetPlayerAlliance(DummyPlayer, p, ALLIANCE_SHARED_ADVANCED_CONTROL) return f endmethod method onDestroy takes nothing returns nothing call SetPlayerAlliance(DummyPlayer, .p, ALLIANCE_PASSIVE, .s[0]) call SetPlayerAlliance(DummyPlayer, .p, ALLIANCE_HELP_REQUEST, .s[1]) call SetPlayerAlliance(DummyPlayer, .p, ALLIANCE_HELP_RESPONSE, .s[2]) call SetPlayerAlliance(DummyPlayer, .p, ALLIANCE_SHARED_XP, .s[3]) call SetPlayerAlliance(DummyPlayer, .p, ALLIANCE_SHARED_SPELLS, .s[4]) call SetPlayerAlliance(DummyPlayer, .p, ALLIANCE_SHARED_CONTROL, .s[5]) call SetPlayerAlliance(DummyPlayer, .p, ALLIANCE_SHARED_VISION, .s[6]) call SetPlayerAlliance(DummyPlayer, .p, ALLIANCE_SHARED_ADVANCED_CONTROL, .s[7]) endmethod endstruct public function interface CallbackFunc takes unit created returns nothing public function interface RepickCallback takes player p returns integer globals private FullAllianceSetting array Alliances private RepickCallback repickCallback private HeroChooser array AllHeroChooser private integer HeroChooserCount = 0 private unit array dummys private trigger cancelOrders private trigger unitBought private trigger repickTrig private camerasetup array cams private timer PeriodicCams = CreateTimer() private timer HCTimer = CreateTimer() private timerdialog HCTimerDialog = CreateTimerDialog(HCTimer) private camerasetup gcam private integer RepickID = 0 private force geforce private group ggroup private integer gindex private integer enumcounter private unit rndPicker = null endglobals struct HeroChooser private group heroes = CreateGroup() private force team = CreateForce() private camerasetup cam private CallbackFunc callback private unit randomPicker private boolean multiPick private boolean randomHeroes private integer index = -1 private integer herocount private real SpawnX private real SpawnY static method create takes group Heroes, force Team, camerasetup Cam, CallbackFunc Callback, integer Index, real spawnX, real spawnY returns HeroChooser local HeroChooser a = HeroChooser.allocate() set a.heroes = Heroes set a.team = Team set a.cam = Cam set a.callback = Callback set a.index = Index set a.SpawnX = spawnX set a.SpawnY = spawnY return a endmethod static method InitSinglePlayer takes player p returns nothing local FullAllianceSetting f = FullAllianceSetting.create(p) local unit u = dummys[GetPlayerId(p)] if u == null then set u = CreateUnit(p, DummyID, CameraSetupGetDestPositionX(gcam), CameraSetupGetDestPositionY(gcam), 0.) set dummys[GetPlayerId(p)] = u endif set Alliances[GetPlayerId(p)] = f set cams[GetPlayerId(p)] = gcam call SetPlayerAlliance(DummyPlayer, p, ALLIANCE_PASSIVE, true) call SetPlayerAlliance(DummyPlayer, p, ALLIANCE_HELP_REQUEST, true) call SetPlayerAlliance(DummyPlayer, p, ALLIANCE_HELP_RESPONSE, true) call SetPlayerAlliance(DummyPlayer, p, ALLIANCE_SHARED_XP, true) call SetPlayerAlliance(DummyPlayer, p, ALLIANCE_SHARED_SPELLS, true) call SetPlayerAlliance(DummyPlayer, p, ALLIANCE_SHARED_CONTROL, true) call SetPlayerAlliance(DummyPlayer, p, ALLIANCE_SHARED_VISION, true) call SetPlayerAlliance(DummyPlayer, p, ALLIANCE_SHARED_ADVANCED_CONTROL, false) if GetLocalPlayer() == p then call SetCameraTargetController(u, 0., 0., true) call CameraSetupApplyForceDuration(gcam, false, 0.) endif set u = null endmethod static method PreparePlayersEnum takes nothing returns nothing call HeroChooser.InitSinglePlayer(GetEnumPlayer()) endmethod static method PrepareHeroesEnum takes nothing returns nothing if (RepickID != 0) then if GetUnitTypeId(GetEnumUnit()) == RepickID then call ShowUnit(GetEnumUnit(), true) call PauseUnit(GetEnumUnit(), false) endif return endif call ShowUnit(GetEnumUnit(), true) call PauseUnit(GetEnumUnit(), false) if GetUnitTypeId(GetEnumUnit()) == randomPickerID then set rndPicker = GetEnumUnit() endif set enumcounter = enumcounter + 1 if GetUnitVal(GetEnumUnit()) != 0 then call SetUnitVal(GetEnumUnit(), gindex) return endif call SetUnitOwner(GetEnumUnit(), DummyPlayer, false) call SetUnitInvulnerable(GetEnumUnit(), true) call UnitAddAbility(GetEnumUnit(), ChooseAbilID) call UnitAddAbility(GetEnumUnit(), 'Asud') call UnitAddAbility(GetEnumUnit(), 'Abun') call UnitRemoveAbility(GetEnumUnit(), 'Amov') call SetUnitPathing(GetEnumUnit(), false) call SetUnitVal(GetEnumUnit(), gindex) if GetUnitTypeId(GetEnumUnit()) == randomPickerID then call AddUnitToStock(GetEnumUnit(), SoldRandomID, 1, 1) else call AddUnitToStock(GetEnumUnit(), SoldDummyID, 1, 1) endif endmethod method start takes nothing returns nothing set geforce = .team set gcam = .cam set gindex = .index + 1 set enumcounter = 0 set ggroup = .heroes set rndPicker = null call ForGroup(ggroup, function HeroChooser.PrepareHeroesEnum) call ForForce(geforce, function HeroChooser.PreparePlayersEnum) set .herocount = enumcounter set .randomPicker = rndPicker set ggroup = null set rndPicker = null set geforce = null set gindex = -1 endmethod method assignRandomHero takes player whichPlayer returns nothing if .randomPicker != null then call GroupRemoveUnit(.heroes, .randomPicker) set .herocount = .herocount - 1 endif if .herocount != 0 then call .picked(GroupGetRandomUnit(.heroes,.herocount),whichPlayer) endif if .randomPicker != null then call GroupAddUnit(.heroes, .randomPicker) set .herocount = .herocount + 1 endif endmethod method picked takes unit whichHero, player whichPlayer returns nothing local integer id = GetUnitTypeId(whichHero) local unit u if id == randomPickerID then call .assignRandomHero(whichPlayer) return endif //call RemoveUnit(dummys[GetPlayerId(whichPlayer)]) //set dummys[GetPlayerId(whichPlayer)] = null call DestroyEffect(AddSpecialEffect(EyeCandyChoose, GetUnitX(whichHero), GetUnitY(whichHero))) if not multiPick then call ShowUnit(whichHero, false) call PauseUnit(whichHero, true) set .herocount = .herocount - 1 endif call Alliances[GetPlayerId(whichPlayer)].destroy() set Alliances[GetPlayerId(whichPlayer)] = 0 set cams[GetPlayerId(whichPlayer)] = null set u = CreateUnit(whichPlayer, id, .SpawnX, .SpawnY, 0.) call DestroyEffect(AddSpecialEffectTarget(EyeCandyCreate, u, "origin")) if GetLocalPlayer() == whichPlayer then call ResetToGameCamera(0.) call PanCameraToTimed(.SpawnX, .SpawnY, 0.) call ClearSelection() call SelectUnit(u, true) endif call .callback.evaluate(u) return endmethod method check takes player p returns boolean return Alliances[GetPlayerId(p)] != 0 endmethod method checkBasic takes player p returns boolean return IsPlayerInForce(p, .team) endmethod method Repick takes player p, integer unitid returns nothing set gcam = .cam call HeroChooser.InitSinglePlayer(p) set gcam = null if not multiPick then set .herocount = .herocount +1 set RepickID = unitid call ForGroup(.heroes, function HeroChooser.PrepareHeroesEnum) set RepickID = 0 endif endmethod static method CleanupPlayers takes nothing returns nothing if not HeroChooser(gindex).check(GetEnumPlayer()) then call RemoveUnit(dummys[GetPlayerId(GetEnumPlayer())]) set dummys[GetPlayerId(GetEnumPlayer())] = null return endif if randomHeroesAtEnd then call HeroChooser(gindex).assignRandomHero(GetEnumPlayer()) else call Alliances[GetPlayerId(GetEnumPlayer())].destroy() set Alliances[GetPlayerId(GetEnumPlayer())] = 0 set cams[GetPlayerId(GetEnumPlayer())] = null if GetLocalPlayer() == GetEnumPlayer() then call ResetToGameCamera(0.) endif call RemoveUnit(dummys[GetPlayerId(GetEnumPlayer())]) set dummys[GetPlayerId(GetEnumPlayer())] = null endif endmethod static method HideHeroesEnum takes nothing returns nothing call ShowUnit(GetEnumUnit(), false) call PauseUnit(GetEnumUnit(), true) endmethod method onDestroy takes nothing returns nothing set gindex = integer(this) call ForForce(.team, function HeroChooser.CleanupPlayers) call ForGroup(.heroes, function HeroChooser.HideHeroesEnum) set .heroes = null set .team = null endmethod endstruct private function PeriodicCamReset takes nothing returns nothing local integer i = 0 loop exitwhen i >= 16 if (GetLocalPlayer() == Player(i)) and (cams[i] != null) then call SetCameraTargetController(dummys[i], 0., 0., true) call CameraSetupApplyForceDuration(cams[i], false, 0.) endif set i = i + 1 endloop endfunction public function AddTeam takes group heroes, force team, camerasetup cam, CallbackFunc callback, real SpawnX, real SpawnY returns nothing local HeroChooser hc = HeroChooser.create(heroes, team, cam, callback, HeroChooserCount, SpawnX, SpawnY) set AllHeroChooser[HeroChooserCount] = hc set HeroChooserCount = HeroChooserCount + 1 endfunction public function EnableRepick takes RepickCallback rc returns nothing call EnableTrigger(repickTrig) set repickCallback = rc endfunction public function End takes nothing returns nothing local integer i = 0 call DisableTrigger(unitBought) call DisableTrigger(cancelOrders) call DisableTrigger(repickTrig) set repickCallback = 0 call PauseTimer(PeriodicCams) loop exitwhen HeroChooserCount <= 0 set HeroChooserCount = HeroChooserCount - 1 call AllHeroChooser[HeroChooserCount].destroy() endloop loop exitwhen i >= bj_MAX_PLAYERS if dummys[i] != null then call RemoveUnit(dummys[i]) set dummys[i] = null endif if Alliances[i] != 0 then call Alliances[i].destroy() set Alliances[i] = 0 endif set i = i + 1 endloop call PauseTimer(HCTimer) call TimerDialogDisplay(HCTimerDialog, false) endfunction private function DelayedTimer takes nothing returns nothing call TimerStart(HCTimer, HCDuration, false, function End) call TimerDialogSetTitle(HCTimerDialog, "Herochoose") call TimerDialogDisplay(HCTimerDialog, true) endfunction public function Start takes nothing returns nothing local integer i = 0 call EnableTrigger(unitBought) call EnableTrigger(cancelOrders) loop exitwhen i >= HeroChooserCount call AllHeroChooser[i].start() set i = i + 1 endloop call TimerStart(PeriodicCams, 0.04, true, function PeriodicCamReset) call TimerStart(HCTimer, 0.1, false, function DelayedTimer) endfunction public function RepickHero takes integer repickIndex, integer unitid, player owner returns nothing if not AllHeroChooser[repickIndex-1].check(owner) then call AllHeroChooser[repickIndex-1].Repick(owner, unitid) endif endfunction public function IsRunning takes nothing returns boolean return TimerGetRemaining(HCTimer) > 0. endfunction private function RepickActions takes nothing returns boolean local integer i = 0 local player p = GetTriggerPlayer() if not IsRunning() then return false endif loop exitwhen i >= HeroChooserCount if AllHeroChooser[i].checkBasic(p) then if not AllHeroChooser[i].check(p) then call AllHeroChooser[i].Repick(p, repickCallback.evaluate(p)) endif return false endif set i = i + 1 endloop return false endfunction private function cancelOrdersConditions takes nothing returns boolean if GetUnitAbilityLevel(GetOrderedUnit(), ChooseAbilID) == 0 then return false endif if (GetIssuedOrderId() == SoldDummyID) or (GetIssuedOrderId() == SoldRandomID) then return false endif if OrderId("stop") == GetIssuedOrderId() then return false endif return true endfunction private function cancelOrdersActions takes nothing returns nothing call DisableTrigger(cancelOrders) call PauseUnit(GetOrderedUnit(), true) call IssueImmediateOrder(GetOrderedUnit(), "stop") call PauseUnit(GetOrderedUnit(), false) call EnableTrigger(cancelOrders) endfunction private function unitBoughtConditions takes nothing returns boolean if ( (GetUnitTypeId(GetSoldUnit()) == SoldDummyID) or (GetUnitTypeId(GetSoldUnit()) == SoldRandomID) ) and (GetUnitTypeId(GetBuyingUnit()) == DummyID) then if not AllHeroChooser[GetUnitVal(GetSellingUnit())-1].check(GetOwningPlayer(GetSoldUnit())) then call DisplayTextToPlayer( GetOwningPlayer(GetSoldUnit()), 0.80, 0, "|c00FFFF00" + ErrorMsg + "|r" ) call RemoveUnit(GetSoldUnit()) return false endif return true endif call RemoveUnit(GetSoldUnit()) return false endfunction private function unitBoughtActions takes nothing returns nothing call AllHeroChooser[GetUnitVal(GetSellingUnit())-1].picked(GetSellingUnit(),GetOwningPlayer(GetSoldUnit())) call RemoveUnit(GetSoldUnit()) endfunction private function init takes nothing returns nothing local integer i = 0 set cancelOrders = CreateTrigger() set unitBought = CreateTrigger() set repickTrig = CreateTrigger() set ht = InitHashtable() loop exitwhen i >= 15 set Alliances[i] = 0 set dummys[i] = null call TriggerRegisterPlayerChatEvent(repickTrig, Player(i), "-repick", true) set i = i + 1 endloop call TriggerRegisterPlayerUnitEvent(cancelOrders,DummyPlayer,EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER,null) call TriggerRegisterPlayerUnitEvent(cancelOrders,DummyPlayer,EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER,null) call TriggerRegisterPlayerUnitEvent(cancelOrders,DummyPlayer,EVENT_PLAYER_UNIT_ISSUED_ORDER,null) call TriggerRegisterPlayerUnitEvent(unitBought,DummyPlayer,EVENT_PLAYER_UNIT_SELL,null) call TriggerAddAction(unitBought, function unitBoughtActions) call TriggerAddCondition(cancelOrders, Condition(function cancelOrdersConditions)) call TriggerAddAction(cancelOrders, function cancelOrdersActions) call TriggerAddCondition(unitBought, Condition(function unitBoughtConditions)) call TriggerAddCondition(repickTrig, Condition(function RepickActions)) call DisableTrigger(unitBought) call DisableTrigger(cancelOrders) endfunction // - and ends here. endlibrary // Thanks for using :) and the example from the attached map: JASS:scope HCSExample // for HCS v1.2f globals // we need to put the heroes chooseable for every team into a group group HeroesTeam1 = CreateGroup() group HeroesTeam2 = CreateGroup() group HeroesTeam3 = CreateGroup() group HeroesTeam4 = CreateGroup() // forces for all the player-teams force Team1 = CreateForce() force Team2 = CreateForce() force Team3 = CreateForce() force Team4 = CreateForce() // for our -rmk mode and -repick, stores all spawned heroes unit array AllHeroes // condition for only picking the function given below - onlyHeroesAllowed boolexpr onlyHeroes endglobals // function used for GroupEnumUnitsBla() private function onlyHeroesAllowed takes nothing returns boolean return IsUnitType(GetFilterUnit(), UNIT_TYPE_HERO) endfunction //in order to not get confused, start reading from the bottom now. // the function that will be called when a player has choosen a hero. // it takes the created hero as an argument. public function Callback takes unit created returns nothing // at this point in time, the player's alliances with the DummyPlayer are // already restored. we don't have to do nothing about them :) local player p = GetOwningPlayer(created) // display a little info-msg call BJDebugMsg("Player " + GetPlayerName(p) + " has choosen " + GetUnitName(created) + "!") // and add the hero to our AllHeroes array, allowing us the -rmk and -repick mode set AllHeroes[GetPlayerId(p)] = created endfunction // a player wants to repick a hero, our function has to return the unitid of the already picked hero public function RepickCallback takes player p returns integer // save the unitid local integer id = GetUnitTypeId(AllHeroes[GetPlayerId(p)]) // remove the current hero from the map call RemoveUnit(AllHeroes[GetPlayerId(p)]) set AllHeroes[GetPlayerId(p)] = null // and return the hero id return id endfunction // our main function, it sets up and starts the herochoose private function StartActions takes nothing returns nothing // "feed" the herochoose-system with info: // 1 unitgroup, 1 player-force, 1 camerasetup and 1 callback-func for each team, // aswell as the point where picked heroes spawn. // (we use the same callback function for every team, you can define custom ones) call HCS_AddTeam(HeroesTeam1, Team1, gg_cam_HeroChooseTeam1, HCS_CallbackFunc.HCSExample_Callback, GetStartLocationX(GetPlayerStartLocation(Player(0))), GetStartLocationY(GetPlayerStartLocation(Player(0)))) call HCS_AddTeam(HeroesTeam2, Team2, gg_cam_HeroChooseTeam2, HCS_CallbackFunc.HCSExample_Callback, GetStartLocationX(GetPlayerStartLocation(Player(3))), GetStartLocationY(GetPlayerStartLocation(Player(3)))) call HCS_AddTeam(HeroesTeam3, Team3, gg_cam_HeroChooseTeam3, HCS_CallbackFunc.HCSExample_Callback, GetStartLocationX(GetPlayerStartLocation(Player(6))), GetStartLocationY(GetPlayerStartLocation(Player(6)))) call HCS_AddTeam(HeroesTeam4, Team4, gg_cam_HeroChooseTeam4, HCS_CallbackFunc.HCSExample_Callback, GetStartLocationX(GetPlayerStartLocation(Player(9))), GetStartLocationY(GetPlayerStartLocation(Player(9)))) call HCS_EnableRepick(HCS_RepickCallback.HCSExample_RepickCallback) // having fed the system, we let it go! call HCS_Start() endfunction // we want a remake. remove all picked heroes and restart the map. private function RmkActions takes nothing returns nothing local integer i = 0 // if the herochoose isn't over yet, we have to end it: if HCS_IsRunning() then call HCS_End() endif // remove all the heroes loop exitwhen i >= 15 if AllHeroes[i] != null then call RemoveUnit(AllHeroes[i]) set AllHeroes[i] = null endif set i = i + 1 endloop // and start it again call StartActions() endfunction // hero has died, we have to revive it. private function ReviveActions takes nothing returns nothing if not IsUnitType(GetDyingUnit(), UNIT_TYPE_HERO) then return endif call ReviveHero(GetDyingUnit(), GetStartLocationX(GetPlayerStartLocation(GetOwningPlayer(GetDyingUnit()))), GetStartLocationY(GetPlayerStartLocation(GetOwningPlayer(GetDyingUnit()))), true) endfunction // init of our map public function InitTrig takes nothing returns nothing local trigger trig = CreateTrigger() local integer i = 0 // this will come in handy during the next few steps. set onlyHeroes = Condition(function onlyHeroesAllowed) // we need to group up the heroes for each team, I did this by // simply giving them to the first players of each team call GroupEnumUnitsOfPlayer(HeroesTeam1, Player(0), onlyHeroes) call GroupEnumUnitsOfPlayer(HeroesTeam2, Player(3), onlyHeroes) call GroupEnumUnitsOfPlayer(HeroesTeam3, Player(6), onlyHeroes) call GroupEnumUnitsOfPlayer(HeroesTeam4, Player(9), onlyHeroes) // this looks a bit messy, but if you take a closer look, // it simply adds all PLAYING(may it be cpu or not) players to the teams, // and registers the hero-revive trigger loop exitwhen i >= 3 if GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING then call ForceAddPlayer(Team1, Player(i)) call TriggerRegisterPlayerUnitEvent(trig, Player(i), EVENT_PLAYER_UNIT_DEATH, null) endif if GetPlayerSlotState(Player(i+3)) == PLAYER_SLOT_STATE_PLAYING then call ForceAddPlayer(Team2, Player(i+3)) call TriggerRegisterPlayerUnitEvent(trig, Player(i+3), EVENT_PLAYER_UNIT_DEATH, null) endif if GetPlayerSlotState(Player(i+6)) == PLAYER_SLOT_STATE_PLAYING then call ForceAddPlayer(Team3, Player(i+6)) call TriggerRegisterPlayerUnitEvent(trig, Player(i+6), EVENT_PLAYER_UNIT_DEATH, null) endif if GetPlayerSlotState(Player(i+9)) == PLAYER_SLOT_STATE_PLAYING then call ForceAddPlayer(Team4, Player(i+9)) call TriggerRegisterPlayerUnitEvent(trig, Player(i+9), EVENT_PLAYER_UNIT_DEATH, null) endif set i = i + 1 endloop // our hero-revive call TriggerAddAction(trig, function ReviveActions) // we want a remake when player red types -rmk, // this is the trigger-setup. set trig = CreateTrigger() call TriggerRegisterPlayerChatEvent(trig, Player(0), "-rmk", true) call TriggerAddAction(trig, function RmkActions) // let it be light, light, and nothing but light! call FogEnable(false) call FogMaskEnable(false) call SetFloatGameState(GAME_STATE_TIME_OF_DAY, 13.) call SuspendTimeOfDay(true) // and a nice msg at the end call BJDebugMsg("Player Red can use -rmk to restart the map, and all players can use -repick to pick a new hero!") // credits :P call BJDebugMsg("HCS v1.2e Example Map, HCS by Blubb-Tec") call BJDebugMsg("Thanks for playing :)") // go, Herochoose! call StartActions() endfunction endscope Changelog: Code:
v1.2f: got rid of the UnitUserData requirement, now working fully withhashtables(requires 1.24(1.23b+) now. turned the changelog upside down, so that is shows recent changes first(>.>) v1.2e: fixed another bug with repicking, and updated the test-map to a working one v1.2d: fixed another bug concerning randomness, and one concerning remakes and repicking v1.2c: fixed the 1.2b testmap which wasn't working, and fixed the camera-lock. v1.2b: fixed some bugs with the random function, which e.g. led to people sometimes not getting a hero at the end of the timer when there was no random picker v1.2: big changes in usage, syntax for almost all functions changed. Best to look into the Documentation to see the changes. Now includes it's own timer and timerwindow, and automatically creates the hero for the player, also takes care of applying the camera and selecting the hero. v1.1: added a periodic-reset camera, removed the onlyHideHeroesAtEnd boolean, players will have to remove the chooseable heroes themselves. Also added a function HCS_RepickHero which allows addition of a -repick mode. v1.1b: fixed a bug that prevented the alliance-restoring from working in most cases fixed a bug that disabled the multiPick option fixed a bug that was able to make heroes unchooseable when players used one of their abilities v1.0: first release Thanks for reading, I'm always happy about comments, don't hold back your breath on anything! |
| 07-21-2008, 02:54 AM | #2 |
Is this a Hero Selection System? |
| 07-21-2008, 06:54 AM | #3 | |
Quote:
On-topic: This looks snazzy, although there's been 1001 of these before. Guess we'll see what the mods think. |
| 07-21-2008, 01:34 PM | #4 |
Sorry, I was just wondering if what I was thinking was right, my fault, I was in a rush when I posted that. The System looks good, supports randomizing and re picking heroes, makes life easier for those who make AoS maps. |
| 07-21-2008, 02:11 PM | #5 |
oh well, re picking is not supported. just multiple picking of the same hero. Also maybe today or tomorrow, I'll release v1.1 with a periodic-set camera, from what I heard the only possibility to "keep" the camera locked. For the re-picking, I'd have to think of a way to put a single player back into his original force. well, since that seems to be a desirable feature, I'll include that as well. |
| 07-21-2008, 05:53 PM | #6 |
I got confused about the remake lol, I thought it was a repick. Anyways, Good Luck. Oh and adding repick would be good really great. |
| 07-22-2008, 06:54 PM | #7 |
Version 1.1 released; Changelog in first post, it now includes: -A REALLY locked camera, players can't trick it anymore. -the function HCS_RepickHero, it allows for a player to repick his hero. -A Screenshot/icon for the system(nothing great though :/) Just a question, is the documentation of system/config/example understandable, or is it too crappy? Edit: also, if anyone sees memory leaks in the (uncommented) script, please tell me. |
| 08-02-2008, 11:56 PM | #8 |
In the testmap, when you random a hero using the Tinker, the hero you get isn't selected so you will still have the Tinker as your selected hero. |
| 08-03-2008, 12:54 PM | #9 | |
Quote:
mhhh I don't really understand your problem. I just tested it again with the 1.1 testmap from this thread, and chose the tinker as player 1, got a random hero, did a -repick, picked the tinker again, got another random hero. Maybe you can tell me which player-slot you used? |
| 08-03-2008, 04:18 PM | #10 |
What's the deal with all of the force copying functions? Those seem... I don't know, unnecessary? I'm sure you could do all of the same things without the extra function calls sapping (However little) speed from the system. Additionally, I had a few minor concerns. When a hero is selected by a team member, it should automatically hide the unselected heroes assuming everyone from the team has selected. Also, I was unable to test, but it hides/cleans up the timer as soon as all players from all teams select as well I hope. Additionally, it should select the hero (Like, for the player, unit selection) upon selection. I like it though, it's cute. |
| 08-03-2008, 11:47 PM | #11 | |||||
ahh, finally some more feedback :D Well then, let me answer all those things.. Quote:
Quote:
Quote:
And since the testmap includes a repick-mode, I think it is best not to hide/destroy the herochoose-timer before the time is up. Quote:
I'll add that though when(if?) I release another version, since I basically only forgot it in the example-map ^_^ Quote:
|
| 08-05-2008, 12:00 PM | #12 |
v1.1b released, fixed some bugs. |
| 08-09-2008, 05:51 PM | #13 | |
Quote:
Also, I'm confused. Why do you have so much stuff in the test map if it isn't a part of the system? That's misleading to people like me that test it to see all of what your system does. Also, selecting the hero for the player and monitoring timers -- To me -- Is a key part of the hero selection system. So if it isn't in your system now, I highly recommend you incorporate it. |
| 08-10-2008, 11:26 AM | #14 | ||
Quote:
Quote:
But creating the hero, selecting it etc shouldn't be a problem for the system, would only require an x and y param for every team, and I'll just go and build that timer into the system, since probably 99% of all mappers use timers to end their herochoose anyway. So I'll put all those changes into the next version, shouldn't be too much so I figure I'll be able to release it later today. Edit: v1.2 released, changelog in first post. Edit2: hotfixed v1.2, repicking was not disabled by default. The file only had 1 view, so I didn't release v1.2a or so.. |
| 09-03-2008, 05:09 PM | #15 |
version 1.2b out, fixed a few bugs with the random-function |
