• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

PSN Hero Selection

Level 2
Joined
Nov 19, 2007
Messages
8
Hail and greetings, comrades.

Herein contains a method for using "Previous" / "Select" / "Next" buttons in hero selection - without requiring a separate "hero" ability for each desired hero, or vast If/Then loops as described here.

Instead, we will be making use of a HeroType[] array, properly initialized, and some additional helper arrays to control camera use and hero generation.
  • A few brief notes:
  • The system was originally designed for a 4-player "Warchasers"-type map, so the code is all based on a 4-player scenario. This is easily adjusted, aside from the computer controllers used in the attached demo map.
  • An adjustable camera system is integrated with this setup as well, and will be explained briefly at the end. Since the "SnapCam" functions are required for controlling the view of heroes during selection, I deemed it necessary to include them, although control of the game camera could be set aside as a separate trigger cluster.
  • The code is as efficient as I could make it, though I'm certain that a JASS-based version of this method could cut down on the number of arrays needed and reduce memory use even further.
  • I use many array-type variables, so for those who don't know already - a variable with brackets[] is an array. Furthermore, the number inside the brackets[#] is the index value. This can be set to any integer, including the integer value of a Player Number (thus Player 1 would be an array index of 1, or array[1]). The purpose of this document is to show a new method for hero selection - if you need a bit more help understanding arrays, I recommend looking here first.
  • A healthy chunk of credit should be given to Fulla for the ability-removal codes, Hero-spawning, creep/enemy spawning, and also some alliance-setup functions in the demo's map initialization (although the latter items are used for the demo's playability, not strictly the hero-selection).
Let's begin...


PSN Hero Selection: Simplified

1. Setup

Before writing up the triggers, it's best to have all the necessary references in place. What you will need:
  • An area on the map set aside for Hero selection. This may take any form you like, from a line of duplicate environments (see demo), to a small circle with each SelectP# region visible to the other players.
  • A number of SelCAM P# camera objects and SelectP# regions equal to the number of Players you wish to allow in-game.
  • Three custom abilities, Previous / Select / Next - set to do essentially 'nothing' and all based on different null spell IDs.
  • At least one "StartGen" starting region, for spawning heroes into the game once selected. For random locations, you may wish to place more.
If you are using custom units, it is strongly suggested that you create these first as well, although since you can use placeholders and 'fill in' later, it's not necessary.
*Note: wherever P# is used, this means Player Number. Thus, Player 3 (Teal) would be SelCAM P3, and SelectP3 region.


2. Trigger - Map Initialization

The important chunk of map init is as follows: check to see if PlayerSlot is occupied, check to see if PlayerSlot is a computer player (optional?).
For this purpose, I have essentially reused the bPlayerDead[] array from Warchasers, albeit with some adjustments.

PlayerStatus[] - Boolean Array

  • The "PlayerStatus" boolean tracks two things
  • Is Player's Hero alive?
  • Is Player "Active"?
The first rank of the array (From 1 to however many players you would like) tracks whether the Player's hero is alive. This will be referred to henceforth as PlayerStatus[1st], and implies the appropriate Player number as the index value of the array.
The second rank (+total players) tracks whether the player is "Active" or not - "Active" in this sense refers to whether or not the player has chosen a hero. It is used for the camera snaps, to determine whether to switch between Game mode or Selection mode, since some method of camera lock is preferred during character generation. Referred to as PlayerStatus[2nd] and implies Player Number + "Total Number of Players possible" (Note - if you have eight open slots, but only three are filled, you want to use 8 as the total number, since your map can allow for UP TO eight players).

  • Initialize
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- Initializing for 1-4 Players --------
      • For each (Integer A) from 1 to 4, do (Actions)
        • Loop - Actions
          • Player Group - Add (Player((Integer A))) to Guardians
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Player((Integer A))) slot status) Not equal to Is playing
            • Then - Actions
              • Set PlayerStatus[(Integer A)] = True
              • Set PlayerStatus[((Integer A) + 4)] = True
            • Else - Actions
      • Trigger - Run Initialize Heroes <gen> (ignoring conditions)
  • You'll note that if a player slot is empty, both the 1st and 2nd ranks of PlayerStatus[] are set to True. These iron out as follows:
  • 1st - "True" = Hero is 'dead' (Player is not active and can be ignored for future functions involving hero processing)
  • 2nd - "True" = Hero is Selected (Player is finished with Chargen)
The second rank allows for a distinction between the player slot being used by a Player vs a Computer, and as you'll see later on, for computer Hero selection (as implemented in the Demo). It also functions as a catch-all, so that any unused slots don't hold up a CharGen process that might require all characters to be selected before-hand. This is not the case here, but that is one of its purposes in this trigger.

Also, pay note of the "Guardians" line - Guardians is a Player Group variable. It gets called mainly for camera funtions, but can also be employed for system messages or other instances when you need to select human players (and computer companions, if desired).


3. Triggers - Hero Initialization and Camera Setup

The Hero init and Camera are set as two separate (linked) triggers, to allow for more versatility. First up, the Hero init:

  • Initialize Heroes
    • Events
    • Conditions
    • Actions
      • -------- Initialize Region Array --------
      • Set SelectPNreg[1] = SelectP1 <gen>
      • Set SelectPNreg[2] = SelectP2 <gen>
      • Set SelectPNreg[3] = SelectP3 <gen>
      • Set SelectPNreg[4] = SelectP4 <gen>
      • -------- Initialize Hero-Type Arra --------
      • Set HeroType[1] = Paladin
      • Set HeroType[2] = Blood Mage
      • Set HeroType[3] = Blademaster of Blackrock Clan
      • Set HeroType[4] = Shadow Hunter
      • Set HeroType[5] = Crypt Lord
      • Set HeroType[6] = Demon Hunter
      • Set HeroType[7] = Firelord
      • Set HeroType[8] = Pit Lord
      • Set HeroType[9] = Lady Vashj
      • For each (Integer A) from 1 to 4, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • PlayerStatus[(Integer A)] Equal to False
              • ((Player((Integer A))) controller) Equal to User
            • Then - Actions
              • Selection - Clear selection for (Player((Integer A)))
              • Unit - Create 1 HeroType[1] for (Player((Integer A))) at (Center of SelectPNreg[(Integer A)]) facing 270.00 degrees
              • Unit Group - Add (Last created unit) to HeroGroup
              • Selection - Select (Last created unit) for (Player((Integer A)))
              • Set HeroSelected[(Integer A)] = (Last created unit)
            • Else - Actions
          • -------- Optional Code - Generates a random hero for a computer opponent --------
          • -------- Requires additional Triggers for Computer Hero's AI --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Player((Integer A))) controller) Equal to Computer
            • Then - Actions
              • Unit - Create 1 HeroType[(Random integer number between 1 and 9)] for (Player((Integer A))) at (Center of StartGen <gen>) facing 270.00 degrees
              • Set PlayerStatus[((Integer A) + 4)] = True
              • Set HeroSelected[(Integer A)] = (Last created unit)
              • Special Effect - Create a special effect attached to the origin of (Last created unit) using Abilities\Spells\Items\AIem\AIemTarget.mdl
            • Else - Actions
      • Unit Group - Pick every unit in HeroGroup and do (Actions)
        • Loop - Actions
          • Custom script: call UnitRemoveAbility(GetEnumUnit(),'Amov')
          • Custom script: call UnitRemoveAbility(GetEnumUnit(),'Aatk')
          • Unit - Add View Next Hero (CharGen) to (Picked unit)
          • Unit - Add View Previous Hero (CharGen) to (Picked unit)
          • Unit - Add Select Hero (CharGen) to (Picked unit)
          • Unit - Remove Shadow Meld from (Picked unit)
          • Hero - Modify unspent skill points of (Picked unit): Set to 0 points
          • Unit - Make (Picked unit) Invulnerable
      • -------- Onward! To the hero-viewer! --------
      • Trigger - Run Set Cameras <gen> (checking conditions)
  • In the initialization there, you'll want three arrays and a UnitGroup variable.
  • SelectPNreg[] - Region array
    During initialization, this sets each player-selection area to the array, so that a simple For/Integer loop can be used to cycle through the whole system at once, eliminating the need for specific <gen>-based triggers for each hero 'initial' spawn.
  • HeroType[] - Unit-Type array
    This is where it starts to get good. Use that line of Set Variable triggers to initialize each hero you want to use. For long lists, say 15 or more, you may wish to implement a few extra "selection abilities" like "Prev/Next>>5" (skip back/ahead 5 heroes), Select Random (random hero), or something else entirely. This area of the method is as versatile as you choose to make it.
  • HeroSelected[] - Unit Array
    This array tracks (by player number) the unit currently selected. Doing so will tell the triggers further on what hero to spawn, as well as lock the camera onto the player-specific hero during CharGen. Having the chosen hero stored in a player array also makes for a number of other possibilities, but for this writing I'll stick to the Hero Selection methods.
  • HeroGroup - Unit Group
    Probably not [essential] to the code, but having all heroes lumped into one heading makes the ability edits much easier to handle.
    Some of this code was borrowed from Fulla's hero selection method - my thanks to him, there.

You can also see the PlayerStatus[] bool coming into play.
Note that PlayerStatus[2nd] is set to True once the computer has selected its hero (randomized) and that HeroSelected[] is set for the comp as well. These are important and will serve you well if you choose to implement computer AI heroes.

What it does:
The For loop checks to see if the player is active [and] a user (human player), and if so generates one unit for the specified player at the Select region (as initialized earlier in the SelectPNreg[] array). It sets the HeroSelected[] array to the user's current hero, and snaps their selection circle to it.
The Unit Group function further down sets up the "Selection" abilities (Prev - Sel - Next), and removes "Shadow Meld" from any heroes, to keep them from ghosting at startup. Be sure to remove any other odd default abilities from custom heroes in this area (I have a hero who can 'eat tree' for example, so remove ability Eat Tree would also be applied in this area)

*NOTE: If you want to spawn heroes at random locations, you can (and should) reuse the SelectPNreg[] array to initialize in the starting regions. Then, later on when the StartGen region is called, you might replace it with a call to the SelectPNreg[], with a randomized index value. Just be sure not to randomize yourself back to the hero-selection area!

Now, for the Camera functions...

  • Set Cameras
    • Events
    • Conditions
    • Actions
      • Set CAM_ID[1] = SelCAM P1 <gen>
      • Set CAM_ID[2] = SelCAM P2 <gen>
      • Set CAM_ID[3] = SelCAM P3 <gen>
      • Set CAM_ID[4] = SelCAM P4 <gen>
      • For each (Integer A) from 1 to 4, do (Camera - Apply CAM_ID[(Integer A)] for (Player((Integer A))) over 0.00 seconds)
      • Player Group - Pick every player in Guardians and do (Actions)
        • Loop - Actions
          • Cinematic - Fade in over 2.00 seconds using texture Black Mask and color (0.00%, 0.00%, 0.00%) with 0.00% transparency
          • Camera - Set (Picked player)'s camera Field of view to 50.00 over 5.00 seconds
          • Camera - Lock camera target for (Picked player) to HeroSelected[(Player number of (Triggering player))], offset by (0.00, 0.00) using The unit's rotation
      • Trigger - Turn on SnapCam to Player <gen>
As with the SelectPNreg[] array before it, the CAM_ID array loads in the placed selection cameras from your map's hero-area. Since these cameras will be called in the SnapCam trigger further on, it's good to have them loaded into a variable now. Beyond that, this section is mostly cinema.


4. Triggers - Prev/Next and Select

The part you're probably reading this for. Well, having seen my previous use of arrays, it probably won't shock you when you see what happens here. You'll need one more array:

HeroCount[] - Integer Array

The reason this is used as an array is due to multiple players using the same function. Its purpose is to track each player's selection based on the index value (HeroCount[PlayerNumber]), so that each player does not need a separate variable.

  • View Next Hero
    • Events
      • Unit - A unit Begins casting an ability
    • Conditions
      • (Ability being cast) Equal to View Next Hero (CharGen)
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • HeroCount[(Player number of (Triggering player))] Less than 9
        • Then - Actions
          • Set HeroCount[(Player number of (Triggering player))] = (HeroCount[(Player number of (Triggering player))] + 1)
        • Else - Actions
          • Set HeroCount[(Player number of (Owner of (Triggering unit)))] = 1
      • Unit Group - Remove HeroSelected[(Player number of (Triggering player))] from HeroGroup
      • Unit - Replace HeroSelected[(Player number of (Triggering player))] with a HeroType[HeroCount[(Player number of (Triggering player))]] using The new unit's default life and mana
      • Unit Group - Add (Last replaced unit) to HeroGroup
      • Unit Group - Pick every unit in HeroGroup and do (Actions)
        • Loop - Actions
          • Custom script: call UnitRemoveAbility(GetEnumUnit(),'Amov')
          • Custom script: call UnitRemoveAbility(GetEnumUnit(),'Aatk')
          • Unit - Add View Previous Hero (CharGen) to (Picked unit)
          • Unit - Add View Next Hero (CharGen) to (Picked unit)
          • Unit - Add Select Hero (CharGen) to (Picked unit)
          • Unit - Remove Shadow Meld from (Picked unit)
          • Hero - Modify unspent skill points of (Picked unit): Set to 0 points
          • Unit - Make (Picked unit) Invulnerable
      • Selection - Select (Last replaced unit) for (Owner of (Triggering unit))
      • Set HeroSelected[(Player number of (Triggering player))] = (Last replaced unit)
There's the magic - "Unit - Replace HeroSelected[]..."
In a nutshell, what this trigger does is increment that HeroCount[] integer for the calling (read: casting) player and swap out the casting unit for the next hero up or down in the HeroType[] array. The unit 'casting' "Previous" or "Next", which is set up as a spell-ability (a la Azeroth Grand Prix) is removed from HeroGroup, replaced, and the replacing unit is added into the group where it runs through the same functions for erasing default abilities and adding the Prev/Sel/Next buttons. HeroSelected[] tracks the unit's type (by instance), and the ability increases/decreases the HeroCount[] by one (depending on whether the previous or next button was 'cast').

*Note: I mentioned earlier that a Skip>>5 hero button might be useful for large quantities of heroes. If you find yourself in need of this, or wish to insert a 'random hero' button as a selector as well, just stick them into the unit-group loop at the bottom as "Add Ability" and copy the Prev/Next triggers (renaming appropriately). Then, all you need to do is change the increment value from 1 to however many heroes you wish to skip ahead.

*Warning: Note these lines

  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • HeroCount[(Player number of (Triggering player))] Less than 9
[...]
  • Else - Actions
    • Set HeroCount[(Player number of (Owner of (Triggering unit)))] = 1
If you modify the number of heroes (and I'm certain you will), be sure to account for that in the if conditions. Incrementing is lovely, but if you overstep your bounds and find yourself in a HeroType[] index with a null value, you'll have no unit to lock onto and no way to backtrack - essentially, your chargen won't cycle properly and you'll be stuck in selection mode.

Now, for the selection button...

  • Confirm Hero
    • Events
      • Unit - A unit Begins casting an ability
    • Conditions
      • (Ability being cast) Equal to Select Hero (CharGen)
      • PlayerStatus[((Player number of (Owner of (Triggering unit))) + 4)] Equal to False
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ((Unit-type of (Triggering unit)) is A Hero) Equal to True
        • Then - Actions
          • Set PlayerStatus[((Player number of (Triggering player)) + 4)] = True
          • Unit - Create 1 (Unit-type of (Triggering unit)) for (Triggering player) at (Center of StartGen <gen>) facing 270.00 degrees
          • Selection - Select (Last created unit) for (Triggering player)
          • Set HeroSelected[(Player number of (Triggering player))] = (Last created unit)
          • Special Effect - Create a special effect attached to the origin of (Last created unit) using Abilities\Spells\Items\AIem\AIemTarget.mdl
        • Else - Actions
      • Unit - Remove (Triggering unit) from the game
Amazingly short, right? Key things to note here are that it sets the PlayerStatus[2nd] bool for the calling player to True - the player has made a hero choice. Then, the trigger spawns a new hero (fresh) at the starting region (StartGen) and sets the HeroSelected[] array to your new hero. The trigger also sets HeroSelected[] to generated unit. Since this var will keep track of your hero throughout the game, it's rather critical. Between PlayerStatus[2nd] and HeroSelected[], the SnapCam trigger has everything it needs for Game mode camera controls.
Finally, the casting unit is removed. Always clean up your toys when you're finished playing. And again, remember that if adjusting for more or fewer players, that +4 in the PlayerStatus[] lines will need to change.


5. Game Trigger - SnapCam

In the demo map, you'll find a lot of uses of the Arithmatic function to allow user control over the camera. Those can be found at the comment "Functions for Game Camera."
However, for our purposes here, I'm going to focus on the uses during character selection.

  • SnapCam to Player
    • Events
      • Time - Every 0.05 seconds of game time
    • Conditions
    • Actions
      • Player Group - Pick every player in Guardians and do (Actions)
        • Loop - Actions
          • Camera - Lock camera target for (Picked player) to HeroSelected[CAMindex[(Player number of (Picked player))]], offset by (0.00, 0.00) using The unit's rotation
          • Camera - Set (Picked player)'s camera Roll to 0.00 over 1.00 seconds
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • PlayerStatus[((Player number of (Picked player)) + 4)] Equal to True
            • Then - Actions
              • -------- Functions for Game Camera --------
            • Else - Actions
              • -------- Functions for CharGen Camera --------
              • Camera - Set (Picked player)'s camera Angle of attack to (Angle of attack of CAM_ID[(Player number of (Picked player))]) over 0.00 seconds
              • Camera - Set (Picked player)'s camera Rotation to (Rotation of CAM_ID[(Player number of (Picked player))]) over 0.00 seconds
Pretty straightforward, right? If PlayerStatus[2nd] is false (player hasn't chosen a hero yet), lock the camera to the CAM_ID[] of that player. Keeps the camera fixed right where it's at, so the player doesn't accidentally shift their view and lose track of their generated hero.

Now, pay attention to the Lock Camera line. See that CAMindex[] thing nestled in the HeroSelected[] index? That's a function call for the demo map's additional camera options. It's explained below, but if you choose not to use those options, simply erase CAMindex and leave "Player number of (Picked)" nested in HeroSelected[]'s index brackets.


6. Game Trigger - Hero Death

  • HeroDeath
    • Events
      • Unit - A unit owned by Player 1 (Red) Dies
      • Unit - A unit owned by Player 2 (Blue) Dies
      • Unit - A unit owned by Player 3 (Teal) Dies
      • Unit - A unit owned by Player 4 (Purple) Dies
    • Conditions
      • (Triggering unit) Equal to HeroSelected[(Player number of (Triggering player))]
    • Actions
      • Set PlayerStatus[(Player number of (Triggering player))] = True
So, if a hero dies, the player's status is Dead. Ergo, set PlayerStatus[1st] to true.
Simple, right?

In the download, you'll find a few other functions here. Those handle the resurrection conditions for this particular map. As such, you'd want to insert your own actions/conditions/triggers in here as well, to deal with the possibility of a hero coming back to life. For the hero-management pieces of this code, just know that once a hero dies, the first rank of PlayerStatus[] should get set to True.


7. Additional Trigger Functions

SnapCam - Game Mode
  • Then - Actions
    • -------- Functions for Game Camera --------
    • Camera - Set (Picked player)'s camera Distance to target to (CAMorientation[((Player number of (Picked player)) + 4)] + 2048.00) over 1.00 seconds
    • Camera - Set (Picked player)'s camera Angle of attack to 305.00 over 2.00 seconds
    • Camera - Set (Picked player)'s camera Field of view to 75.00 over 2.00 seconds
    • Camera - Set (Picked player)'s camera Rotation to CAMorientation[(Player number of (Picked player))] over 2.00 seconds
    • -------- Uses Hero's orientation for camera. Dizzying in quick turns. --------
    • DIS-Camera - Set (Picked player)'s camera Rotation to (CAMorientation[(Player number of (Picked player))] + (Facing of HeroSelected[(Player number of (Picked player))])) over 2.00 seconds
*DIS means the trigger was disabled in code. If you prefer to set the cam rotation to the hero's facing, disable the line [above] the comment and enable the line below it.

For camera control in the demo map, two new arrays were initialized at startup.
CAMorientation[], a Real array, handles the camera's rotation AND zoom, using the same 1st/2nd rank method as PlayerStatus[]
-1st Rank controls rotation, and should be the same index as Player#
-2nd Rank controls zoom in/out (distance to target) and its index should be incremented by the number of open slots in your map (+total players)
CAMIndex[], another Integer array that tracks camera lock-ons.

Above, see that CAMorient[2nd] is applied as "Distance to Target" and CAMorient[1st] is set as Rotation.
Do you remember CAMIndex[]?
  • Player Group - Pick every player in Guardians and do (Actions)
    • Loop - Actions
      • Camera - Lock camera target for (Picked player) to HeroSelected[CAMindex[(Player number of (Picked player))]], offset by (0.00, 0.00) using The unit's rotation
      • Camera - Set (Picked player)'s camera Roll to 0.00 over 1.00 seconds
The reason it's nested in there is so that the camera is not locking directly to HeroSelected[]'s index (that is, Player#), but rather to the value of CAMIndex[]'s player@. Why do that? Because upon a hero's death, the map and camera allow you to cycle your view through other player's heroes, locking your camera onto their units until your own is revived.

Hero Revival
  • Set PlayerStatus[(Player number of (Triggering player))] = False
  • Set CAMindex[(Player number of (Triggering player))] = (Player number of (Triggering player))
  • Selection - Select (Triggering unit) for (Triggering player)
To re-lock the camera to the player's unit, include the Set CAMindex[] line.
It's also nice to re-select their hero for them, so they don't go flailing about with the mouse.
And be sure to set PlayerStatus[] back to False, now that they're alive again.

*Note: these lines are actually found in the HeroDeath trigger, in the demo.

Camera Rotation/Cycling
  • AdjCam Left
    • Events
      • Player - Player 1 (Red) Presses the Left Arrow key
      • Player - Player 2 (Blue) Presses the Left Arrow key
      • Player - Player 3 (Teal) Presses the Left Arrow key
      • Player - Player 4 (Purple) Presses the Left Arrow key
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • PlayerStatus[(Player number of (Triggering player))] Equal to False
        • Then - Actions
          • -------- Hero is Alive - Rotate Camera --------
          • Set CAMorientation[(Player number of (Triggering player))] = (CAMorientation[(Player number of (Triggering player))] - 5.00)
          • If (CAMorientation[(Player number of (Triggering player))] Less than or equal to -360.00) then do (Set CAMorientation[(Player number of (Triggering player))] = 0.00) else do (Do nothing)
        • Else - Actions
          • -------- Hero is Dead - cycle through other Heroes --------
          • Set CAMorientation[(Player number of (Triggering player))] = 0.00
          • If (CAMindex[(Player number of (Triggering player))] Greater than 1) then do (Set CAMindex[(Player number of (Triggering player))] = (CAMindex[(Player number of (Triggering player))] - 1)) else do (Set CAMindex[(Player number of (Triggering player))] = 4)
In the same sense that the Prev/Next buttons used an increment/decrement method on HeroCount[], the same thing happens here with CAMOrientation[1st] and CAMIndex[].
Note that CAMIndex only comes into play if PlayerStatus[1st] is True (dead). And thanks to those lines in the Hero Death/Revival section, the CAMIndex is reset once the player's back among the living, so you're not accidentally stuck rotating yourself around someone else's hero.

  • AdjCam ZoomIn
    • Events
      • Player - Player 1 (Red) Presses the Up Arrow key
      • Player - Player 2 (Blue) Presses the Up Arrow key
      • Player - Player 3 (Teal) Presses the Up Arrow key
      • Player - Player 4 (Purple) Presses the Up Arrow key
    • Conditions
    • Actions
      • Set CAMorientation[((Player number of (Triggering player)) + 4)] = (CAMorientation[((Player number of (Triggering player)) + 4)] - 32.00)
      • If (CAMorientation[((Player number of (Triggering player)) + 4)] Less than or equal to -1024.00) then do (Set CAMorientation[((Player number of (Triggering player)) + 4)] = -1024.00) else do (Do nothing)
Finally, this one uses CAMOrientation[2nd] to do the exact same thing as [1st], but with distance to target instead of rotation. The IF statement sets boundaries, so you don't zoom in infinitely close or get a negative zoom.
By extension, the Zoom Out function uses a similar If to prevent you from zooming yourself out into low orbit.


8. Credits

My thanks to the makers of Azeroth Grand Prix, for the idea.
To Fulla, for the snippets of code from his map, and the inspiration it sparked that helped me get everything working.
To the other tutorial writers, for helping me relearn GUI triggers. May I one day comprehend JASS.
(Must find time to read all the tutorials I've saved...)
To Fox, for getting me back into "WarCrafting".
To Blizzard, for such an awesome product.
And thanks to you, for reading.
 

Attachments

  • InstantGratification.w3x
    101.2 KB · Views: 621
Last edited:
Level 2
Joined
Nov 19, 2007
Messages
8
A few addendums:
-I've read about memory leaks, and can identify a few of them here (such as the spawn specialFX call after hero selection), but most of them are, quite frankly, over my head. Any help in pointing them out would be very appreciated, as well as suggested fixes (or at least a place to look for fixes)
-The custom script calls are also 'over my head,' in that I know what they do, but wouldn't have known to use them without seeing them elsewhere. Point is, they're the only reason I've used HeroGroup at all. I imagine putting the calls into the For loop and setting everything else in that list to Last Created or Triggering Unit (depending on the trigger) would be more efficient.

Anyone able to help me slim this down a little more and make it leak less?
 
Top