• 🏆 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!

[Misc] Tips & Tricks - Using Abilities as Data Reference for Triggering

B22

B22

Level 6
Joined
Sep 29, 2014
Messages
49
I wasn't quite sure where to post this specifically, so hopefully this is the right thread.
While this is something to be used with triggering, there is not much specific and in-depth coding. It is also compatible with both GUI and scripting, so posting it on only one of the threads does not feel right. It is also not a Spell, acts as a support for other Systems rather than being a System on its own and not exactly a template since its usage really depends on what you want, so I also feel it does not belong on there.

So mods, should you find this placement disagreeable, feel free to move it around.

Tips & Tricks

Using Abilities as Data Reference for Triggering

For the remainder of this thread, I'm going to call this method PRAT (Procedural Referencing with Ability object for Triggering) to make it easier.
I recently came up with this method and could not find any mention of something similar in Hiveworkshop or cases where its being used in projects. Although of course, the applications of this are quite limited outside of systems and multi-map projects like custom campaign, so I guess not many consider something like this important.

ASCII table scripts are not always required but are essential to unlock the full potential of PRAT, you can find some here.

What's the Point of Implementing This?​

The aim of PRAT is to reduce the number of times you need to dive into your Triggers (whether it be a script like vJass and Lua or GUI) to make adjustments or fine tuning. Instead of defining constants inside of the Trigger, we can instead call the Data Field of a custom ability. By doing this, the trigger will be more scalable to larger projects like Custom Campaigns or System/Templates.

How Does This Work?​

First things first, the functions we will be using are not the Ability - Get Integer/Real/String/Boolean Field - XXX types. These are inefficient for our workflow. To even be able to get this method, we have to go through:
  • Set TmpPointA = (Center of (Playable map area))
  • Unit - Create 1 DummyUnit for Neutral Passive at TmpPointA facing Default building facing degrees
  • Custom script: call RemoveLocation(udg_TmpPointA)
  • Unit - Add PRAT to (Last created unit)
  • Set var = Ability - Get Integer/Real/String/Boolean Field - XXX
  • Unit - Remove (Last created unit) from the game
The function calls we desire are instead these ones:, these functions works even without any instances of the ability in the game.

GUI

Jass


  • Set var = (Mana cost of PRAT , Level X)
  • Note: Integer above is available in dropdown menu as "Ability - Ability Mana Cost"
  • Set var = (Cooldown of PRAT , Level X)
  • Note: Real above is available in dropdown menu as "Game - Ability Cooldown"
  • Set var = (Tooltip of PRAT for level X)
  • Note: String above is available in dropdown menu as "Ability - Ability Tooltip"
  • -------- And more of their kinds --------

JASS:
set var = BlzGetAbilityTooltip('prat', X)
set var = BlzGetAbilityCooldown('prat', X)
set var = BlzGetAbilityTooltip('prat', X)
//-------- And more of their kinds --------

Why Abilities?​

Some of you might notice that units have similar function calls available, but here are why abilities are superior in option.
Units have way too many Editor fields that are are not of our interest, we cannot get the data from Combat - Attack 1 - Cooldown Time, Text - Tooltip - Extended or Movement - Speed Base and these fields are cluttering our view.
Abilities on the other hand have minimal "Unused Fields" and we can even control the numbers with Stats - Levels. On top of that, the ones we want to use are grouped relatively close near the bottom.
Finally, check this table below. This is the approximate number of data you can get from each type.
Directly Accessible Data
Ability
Unit-Type
Item-Type
Integer
1 per Level (Max 100)
3
0
Real
1 per Level (Max 100)
0
0
String
4 per Level (Max 400) + 2
(Not Including Name and Art Paths)
1
0
Boolean
3
8
3
It should be clear that there is no reason to use Units and Items. For booleans, you can instead play around with 0s and 1s in any of the fields.
Keep in mind that Strings are really powerful once you know some string manipulations. For example, you can list multiple things in one String Field and separate them with "," (comma) or " " (space). And then in the trigger, you can split where to assign using substring and other methods.

Update:
Found out from here that it is possible to store several strings inside a unit. I still would not recommend it over abilities, but here is the details after several testings:
  • You can store strings, mostly inside Art - Special and Art - Target
  • Yes, you can store any string inside. It does not have to be a model
  • For information:
    • Art - Special determines what model appears when unit dies from Artillery (Other sources of damage might also do it, but as far as I know, Artillery is the easiest example).
    • Art - Target YES IT DOES DO SOMETHING determines what model appears to secondary targets hit by Weapon Type: Missile (Line) and Artillery (Line). It does not appear on the main target. It does not appear on other Weapon Types with multi target attacks.
  • When more than one model/line, it bugs out entirely. Not showing anything on the events I mentioned above.
  • Those two fields presented themselves as array, but apparently it is not. Atleast when called using GetAbilityEffectById
    • Using GetAbilityEffectById(GetUnitTypeId(unitInstance), EFFECT_TYPE_TARGET, X) with X as any integer value. It returns all of its content separated by a "," regardless of X's value. Still useful but will require a bit more work.
From such, these conclusions can be taken:
  • It is less intuitive
    • String Fields in ability are separated into four sections more or less with the tooltip types, which you can treat as a category or separator.
    • There is also the Learn Tooltip which I myself frequently use as a note/comment to guide or keep track of what is what.
    • You cannot have all of this in Unit.
    • It also still requires an instance of a unit in the map for it to work.
  • However,
    • It is of course very useful if the data is a unit-type specific, since you won't need to create some convoluted links between multiple FourCC codes in a PRAT. By extension, reducing the amount of PRAT required.
  • For some concerns regarding fields being necessary:
    • With a little tinkering using Bribe's Damage Engine and Attack Indexer, it should be possible to replicate the intended effect.
    • You can store the Actual Data to the first index, only treat only indexes after it as the data field.
    • By detecting weapon type artillery on a death event, you can spawn a special effect based on the first data.
    • By detecting weapon type XX (Line), you can spawn a special effect on collateral targets. (Using Attack Indexer)
Update Over

Examples:​

The implementation of PRAT really varies on what you want, so instead of explaining and telling the steps, I will just show you some examples of how I used it so far.

Spell Events of Spells with Similar Nature

Pseudo Linked List of Spells

As a String Database 1

As a String Database 2

Custom Item Drop Tables


This was the first instance I ever utilized PRAT in full.

Goal:​

Expand on Bribe's HealEvent to detect Healing Sources using Magtheridon96's GUI SpellEvent.

Issue:​

A functional Heal Detection System need to be able to register any healing abilities being cast. While it is possible to register all default healing abilities to SpellEvent, any new abilities require modification to the triggers. One or two new abilities might not be too bad, but multiple more and put the system into a custom campaign that is constantly being updated... imagine the amount of work.

PRAT's Solution:​

So, let's create a PRAT, under the code 'Dhsi'.
I will be using "Text - Tooltip - Normal" to store the FourCC/AbilityID codes of each ability. To count the number of abilities in the list, I will be putting it in "Level 1 - Stats - Mana Cost". The resulting PRAT should look similar to below.
As a bonus, I can also give a description by turning it to a Hero Ability and put some notes in the "Text - Tooltip - Learn - Extended". This should help other editors to understand what to modify should they want to.
1703913622633.png
1703917756782.png
With PRAT set up, my Spell Register Trigger turns from this:
  • set SpellEventAbility[0] = Heal (Priest)
  • set SpellEventAbility[1] = Heal (Neutral Hostile 1)
  • set SpellEventAbility[2] = Heal (Neutral Hostile 2)
  • set SpellEventAbility[3] = Heal (Neutral Hostile 3)
  • set SpellEventAbility[4] = Holy Light
  • set SpellEventAbility[5] = Holy Light (Item)
  • set SpellEventAbility[6] = Death Coil
  • For each (Integer A) from 0 to 6 do (Actions)
    • Loop - Actions
      • Set SpellEventTrigger[(Integer A)] = STHealEvents <gen>
  • set SpellEventAbility[7] = Essence of Blight
  • set SpellEventAbility[8] = Item Area Healing (Greater)
  • For each (Integer A) from 7 to 8 do (Actions)
    • Loop - Actions
      • Set SpellEventTrigger[(Integer A)] = AOEHealEvents <gen>
  • Trigger - Run GUISpellEvent <gen> (Ignoring conditions)
Into this:
  • Set SpellEventMultLoopIndex = 0
  • For each (Integer A) from 0 to ((Mana cost of PRAT - HealEvent ST Instant , Level 0) - 1) do (Actions)
    • Loop - Actions
      • Custom script: set udg_SpellEventAbility[udg_SpellEventMultLoopIndex] = S2A(BlzGetAbilityTooltip('Dhsi', GetForLoopIndexA()))
      • Set SpellEventTrigger[SpellEventMultLoopIndex] = STHealEvents <gen>
      • Set SpellEventMultLoopIndex = (SpellEventMultLoopIndex + 1)
  • For each (Integer A) from 0 to ((Mana cost of PRAT - HealEvent AOE Instant , Level 0) - 1) do (Actions)
    • Loop - Actions
      • Custom script: set udg_SpellEventAbility[udg_SpellEventMultLoopIndex] = S2A(BlzGetAbilityTooltip('Dhai', GetForLoopIndexA()))
      • Set SpellEventTrigger[SpellEventMultLoopIndex] = AOEHealEvents <gen>
      • Set SpellEventMultLoopIndex = (SpellEventMultLoopIndex + 1)
  • Trigger - Run GUISpellEvent <gen> (Ignoring conditions)
And now, everytime I made a new ability, or decided that another ability can be included in the category, instead of doing:
1. Add new set SpellEventAbility[X] = NewAbility
2. Modify the loop number manually for Set SpellEventTrigger[(Integer A)] = AOEHealEvents <gen>
I can instead:
1. Add 1 to PRAT level and manacost
2. Add the FourCC code into the tooltip of new level

When listed like this, the difference might not be that big. However,
  • Changing fields in ObjectEditor is faster than changing lines in trigger, especially for GUI.
  • When using in custom campaign (which I am doing), the trigger modification number is multiplied with the number of maps I have.

Footnote​

While PRAT did its job and was able to detect newly added healing abilities, it was unfortunate that both events Begin Casting and Starts the Effect fires after the healing was done instead of just before😿, meaning the HeavEvent always triggers with Healing Amount of 0. I do think it should be possible to implement it with OrderEvent and IsUnitMoving checks, but let's put that aside for now

Goal:​

Detect when workers start mining a gold mine.

Issue:​

Every "Gold Mine" type requires a different "Harvest" abilities, trigger should not run when a Human Peasant right-clicks a Haunted Gold Mine.
There are cases where maps have custom Gold Mine like SC2 Geyser replication for example. The system need to be able to detect it without extensive modification.

PRAT's Solution:​

So, let's create a PRAT, under name "PRAT - Mine Harvest Ability Link".
I will be using:
  • "Text - Tooltip - Normal" to store the FourCC/AbilityID codes of the Harvest Ability.
  • "Text - Tooltip - Normal - Extended" to store the FourCC/AbilityID codes of the Gold Mine Ability.
  • "Text - Tooltip - Turn Off" to store the integer which will refer to what the Gold Mine ability is based on. (e.g. Custom Gold Mines based on Blighted Gold Mine are assigned 2)
  • "Text - Tooltip - Turn Off - Extended" refers to the Code IDs of "Text - Tooltip - Turn Off"
1703928329484.png

My triggers changes from:
  • Set GMC_GOLD_MINE_NORMAL = 0
  • Set GMC_GOLD_MINE_BLIGHTED = 1
  • Set GMC_GOLD_MINE_ENTANGLED = 2
  • -------- Ability Codes --------
  • Set GMC_MineCodeVariants = 3
  • Set GMC_CodeMineKeyAbility[0] = Gold Mine ability
  • Set GMC_CodeWorkKeyAbility[0] = Harvest (Gold and Lumber)
  • Set GMC_MineType[0] = GMC_GOLD_MINE_NORMAL
  • Set GMC_CodeMineKeyAbility[1] = Gold Mine ability
  • Set GMC_CodeWorkKeyAbility[1] = Harvest (Neutral)
  • Set GMC_MineType[1] = GMC_GOLD_MINE_NORMAL
  • Set GMC_CodeMineKeyAbility[2] = Blighted Gold Mine ability
  • Set GMC_CodeWorkKeyAbility[2] = Gather(Acolyte Gold)
  • Set GMC_MineType[2] = GMC_GOLD_MINE_BLIGHTED
  • Set GMC_CodeMineKeyAbility[3] = Load (Entangled Gold Mine)
  • Set GMC_CodeWorkKeyAbility[3] = Gather (Wisp Gold and Lumber)
  • Set GMC_MineType[3] = GMC_GOLD_MINE_ENTANGLED
to:
  • Set GMC_PRAT = PRAT - Mine Harvest Ability Link
  • Custom script: set udg_GMC_GOLD_MINE_NORMAL = S2I(BlzGetAbilityActivatedExtendedTooltip(udg_GMC_PRAT, 0))
  • Custom script: set udg_GMC_GOLD_MINE_BLIGHTED = S2I(BlzGetAbilityActivatedExtendedTooltip(udg_GMC_PRAT, 1))
  • Custom script: set udg_GMC_GOLD_MINE_ENTANGLED = S2I(BlzGetAbilityActivatedExtendedTooltip(udg_GMC_PRAT, 2))
  • -------- Ability Codes --------
  • Set GMC_MineCodeVariants = (Mana cost of GMC_PRAT, Level 0)
  • For each (Integer A) from 0 to (GMC_MineCodeVariants - 1), do (Actions)
    • Loop - Actions
      • Custom script: set udg_GMC_CodeWorkKeyAbility[bj_forLoopAIndex] = S2A(BlzGetAbilityTooltip(udg_GMC_PRAT, bj_forLoopAIndex))
      • Custom script: set udg_GMC_CodeMineKeyAbility[bj_forLoopAIndex] = S2A(BlzGetAbilityExtendedTooltip(udg_GMC_PRAT, bj_forLoopAIndex))
      • Custom script: set udg_GMC_MineType[bj_forLoopAIndex] = S2I(BlzGetAbilityActivatedTooltip(udg_GMC_PRAT, bj_forLoopAIndex))
1703929641661.png
1703929663383.png
Now, Gold Mine and Harvest might not be an attractive example, but how about you consider a custom Lightning Shield that only damages enemies. The standard practice is to create a copy of Permanent Immolation, put it into a Hidden Spellbook and give it to the unit. But even in the default object data, there are 3 different Lightning Shields, each with potentially different damage, aoe and duration; Should you decide to create a new one, assigning the two codes of Lightning Shield being cast and the Spellbook given to the unit and maybe also the Buff code for checking inside a PRAT will make the process much more scalable.


Goal:​

Modify UI to show units level and classification(s). Should also allow modifications of the classification names.

Issue:​

As far as I know, getting data from Game Interface and Game Constants are not possible with triggers.
Also 'Ancient' and 'Town Hall' are two classifications with no string attached to it.

PRAT's Solution:​

So, let's create a PRAT, under the code 'Dfrt'.
I will be using "Text - Tooltip - Normal" to store the string data of the classifications. I will also utilize the "Stats - Mana Cost" as a Boolean here, 0 will make it that the trigger ignore the classification, otherwise use as normal.
As a bonus, I can also give a description by turning it to a Hero Ability and put some notes in the "Text - Tooltip - Learn - Extended". This should help other editors to understand what to modify should they want to.
1703924610962.png
1703924660383.png
JASS:
library moCustomUI initializer Init
    globals
        //Controls
        private real updateFreq = 0.03

        //FrameHandles
        private framehandle fhClassValue
     
        //AbilityCodeLists
        private integer acClassText

        //Classifications
        private string textGiant
        private string textMechanical
        private string textTauren
        private string textUndead
        private string textTownHall
        private string textAncient
        private integer showGiant
        private integer showMechanical
        private integer showTauren
        private integer showUndead
        private integer showTownHall
        private integer showAncient

        //Others
        private group currGroup
        private unit currUnit
        private unit prevUnit
    endglobals
 
    public function UpdateFrames takes nothing returns nothing
        local string tmpText = ""
        local real tmpReal = 0.0
        local boolean isNotBuild = false
        call GroupEnumUnitsSelected(currGroup, GetLocalPlayer(), null)
        set currUnit = FirstOfGroup(currGroup)
        call GroupClear(currGroup)

        if currUnit != prevUnit then
            //---------------
            //Classifications
            //---------------
            set tmpText = ""
            set isNotBuild = not IsUnitType(currUnit, UNIT_TYPE_STRUCTURE)
            //Ignore Level if Stucture
            if IsUnitType(currUnit, UNIT_TYPE_STRUCTURE) then
                set tmpText = tmpText + " "
            else
                set tmpText = tmpText + " " + GetLocalizedString("LEVEL")

                //Check Hero
                if IsUnitType(currUnit, UNIT_TYPE_HERO) then
                    set tmpText = tmpText + " " + I2S(GetHeroLevel(currUnit))
                else
                    set tmpText = tmpText + " " + I2S(GetUnitLevel(currUnit))
                endif
            endif
     
            //Classifications
            if IsUnitType(currUnit, UNIT_TYPE_MECHANICAL) and showMechanical != 0 and isNotBuild then
                set tmpText = tmpText + " " + textMechanical
            endif
            if IsUnitType(currUnit, UNIT_TYPE_GIANT) and showGiant != 0 and isNotBuild then
                set tmpText = tmpText + " " + textGiant
            endif
            if IsUnitType(currUnit, UNIT_TYPE_ANCIENT) and showAncient != 0 then
                set tmpText = tmpText + " " + textAncient
            endif
            if IsUnitType(currUnit, UNIT_TYPE_TOWNHALL) and showTownHall != 0 then
                set tmpText = tmpText + " " + textTownHall
            endif
            if IsUnitType(currUnit, UNIT_TYPE_UNDEAD) and showUndead != 0 and isNotBuild then
                set tmpText = tmpText + " " + textUndead
            endif
            if IsUnitType(currUnit, UNIT_TYPE_TAUREN) and showTauren != 0 and isNotBuild then
                set tmpText = tmpText + " " + textTauren
            endif

            //Hero Name
            if IsUnitType(currUnit, UNIT_TYPE_HERO) then
                set tmpText = tmpText + " " + GetUnitName(currUnit)
            endif
     
            set tmpText = SubStringBJ(tmpText, 2, StringLength(tmpText))
            call BlzFrameSetText(BlzGetFrameByName("moSimpleUnitStatsPanel", 0), tmpText)
 
            set prevUnit = currUnit
            set currUnit = null

        endif

    endfunction
 
    public function InitFrames takes nothing returns nothing
        local timer tmpTimer = CreateTimer()
        call BlzLoadTOCFile("GameEssentials\\moCustomUIData.toc")


        //FrameHandles
        set fhClassValue = BlzGetFrameByName("moSimpleUnitStatsPanel", 0)

        //AbilityCodeLists
        set acClassText = 'Dfrt'
     
        //Classifications
        set textGiant = BlzGetAbilityTooltip(acClassText, 0)
        set textMechanical = BlzGetAbilityTooltip(acClassText, 1)
        set textTauren = BlzGetAbilityTooltip(acClassText, 2)
        set textUndead = BlzGetAbilityTooltip(acClassText, 3)
        set textTownHall = BlzGetAbilityTooltip(acClassText, 4)
        set textAncient = BlzGetAbilityTooltip(acClassText, 5)
        set showGiant = BlzGetAbilityManaCost(acClassText, 0)
        set showMechanical = BlzGetAbilityManaCost(acClassText, 1)
        set showTauren = BlzGetAbilityManaCost(acClassText, 2)
        set showUndead = BlzGetAbilityManaCost(acClassText, 3)
        set showTownHall = BlzGetAbilityManaCost(acClassText, 4)
        set showAncient = BlzGetAbilityManaCost(acClassText, 5)

        //Others
        set prevUnit = null
     
        //Setup
        call BlzFrameSetVisible(BlzGetFrameByName("SimpleUnitStatsPanel", 0), false)
        call BlzFrameSetSize(BlzGetFrameByName("SimpleUnitStatsPanel", 0), 0.00001, 0.00001)
        call BlzCreateSimpleFrame("moSimpleUnitStatsPanel", BlzGetFrameByName("SimpleInfoPanelUnitDetail", 0), 0)

        call TimerStart(tmpTimer, updateFreq, true, function UpdateFrames)
    endfunction
 
    public function Init takes nothing returns nothing
        local timer tmpTimer = CreateTimer()

        set currGroup = CreateGroup()
        call TimerStart(tmpTimer, 0.0, false, function InitFrames)
        call DestroyTimer(tmpTimer)
    endfunction
endlibrary
With PRAT set up, instead of specifying the texts inside the script, I can just call the data from PRAT and keep the script untouched even when I want a modification like changing the name of Undead classification to Unholy, giving color to Mechanicals or hiding the Tauren classification.

These are the first instances of me using PRAT for minor usages.

Goal:​

Provide easier way to change Cinematic Transmission Names.
It is not rare for us to play a campaign, control a hero with name like "Brian" for example. But during cinematics, instead of simply "Gardon" it becomes "Lord Brian the Fallen" when speaking. Most creators will simply write this string data down in the Transmission trigger, or the meticulous ones will store it in a variable first. Regardless, when creating campaigns with multiple maps, in the case where you want to change this name to for example "Baby Brian the Droller", having to revisit each map and change it will become cumbersome.

PRAT's Solution:​

For this example, I'm using a Scourge of Lordaeron, and I made two PRAT, one to store Arthas' prefix and suffix, and another for Uther's. Prefixes are stored in "Level 0 Text - Tooltip - Normal" and Suffixes in "Level 1 Text - Tooltip - Normal". With such setup, now the triggering looks more like this, and if I want to change Uther's title from " the Lightbringer" to " the Death Bringer", I can do so from the object editor and it will apply everywhere.
1703926159126.png

1703926165049.png



Goal:​

Trigger a random item drop based on drop table.

Issue:​

Item - Create trigger only have the option of Item-Type Of Item, Random Item-Type, Random Item-Type Of Class. With the latter 2 only takes level and cannot read the Item-Type's "Stats - Include As Random Choice" normally used by melee map makers.
How to incorporate these drops without moving every single item to specific classification which might cause it to be unintuitive for item editing.
There might be a need to create several different drop tables for different units.

PRAT's Solution:​

For this Drop Table, I want different table for different Levels.
I created 6 different PRAT, each for level 1 to 6, and an additional PRAT (MasterTable) to call the other PRATs in the Triggers.
I will be using "Text - Tooltip - Normal" to store the FourCC code of items I want inside the drop table.
1703931524926.png
1703931201334.png
1703931233995.png

When applied to Triggers:
  • Hashtable - Create a hashtable
  • Set DR_ItemTypeHash = (Last created hashtable)
  • Set DR_ItemDropTableLevels = (Mana cost of PRAT - Drop Table (Permanent - MasterTable) , Level 0)
  • For each (Integer A) from 0 to (DR_ItemDropTableLevels - 1), do (Actions)
    • Loop - Actions
      • Custom script: call BJDebugMsg( "Setting up Table for Level " + I2S(bj_forLoopAIndex + 1) )
      • Custom script: set udg_DR_ItemDropTableCode[bj_forLoopAIndex] = S2A(BlzGetAbilityTooltip('DdpM', GetForLoopIndexA()))
      • For each (Integer B) from 0 to ((Mana cost of DR_ItemDropTableCode[(Integer A)], Level 0) - 1), do (Actions)
        • Loop - Actions
          • Custom script: set udg_TmpInt = S2A(BlzGetAbilityTooltip(udg_DR_ItemDropTableCode[bj_forLoopAIndex], GetForLoopIndexB()))
          • Hashtable - Save TmpInt as (Integer A) of (Integer B) in DR_ItemTypeHash
  • Set DR_RandomNumber = (Random real number between 0.00 and 1.00)
  • For each (Integer A) from 1 to 6, do (Actions)
    • Loop - Actions
      • Set TmpReal = (Load (Min(8, (DR_UnitLvForDrop))) of (Integer A) from DR_Chance_ILv_Perm)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • DR_RandomNumber Less than TmpReal
        • Then - Actions
          • Set TmpInt = (Random integer number between 0 and (Mana cost of DR_ItemDropTableCode[((Integer A) - 1)], Level 0))
          • Custom script: set udg_DR_TmpItemCode = LoadIntegerBJ(bj_forLoopAIndex - 1, udg_TmpInt, udg_DR_ItemTypeHash)
          • Item - Create DR_TmpItemCode at DR_UnitDropPosition
          • Custom script: call RemoveLocation(udg_DR_UnitDropPosition)
          • Skip remaining actions
        • Else - Actions
          • Set DR_RandomNumber = (DR_RandomNumber - TmpReal)
In the above Trigger, I have a specified the drop rates for each Unit Levels(Maxing out for Unit Level 8) and Item Levels stored in DR_Chance_ILv_Perm hashtable.
WC3ScrnShot_123023_191941_02.png

 

Attachments

  • 1703927297162.png
    1703927297162.png
    1.2 MB · Views: 4
  • 1703928184792.png
    1703928184792.png
    180.4 KB · Views: 4
  • 1703928421730.png
    1703928421730.png
    202.7 KB · Views: 3
  • 1703928475272.png
    1703928475272.png
    203.5 KB · Views: 3
  • 1703928634324.png
    1703928634324.png
    364.4 KB · Views: 1
  • 1703931220686.png
    1703931220686.png
    4.4 KB · Views: 2
Last edited:

deepstrasz

Map Reviewer
Level 69
Joined
Jun 4, 2009
Messages
18,883
I tried using those here but the overall performances was lacking compared to say a unit indexer. Of course, you might be using them right.
 

B22

B22

Level 6
Joined
Sep 29, 2014
Messages
49
the overall performances was lacking compared to say a unit indexer.
Sorry, but I fail to see the connection to a unit indexer here. This does nothing what unit indexer does, and I even used unit indexer alongside this.
Unit indexer was made to assign a number to each instance of a unit.
PRAT is made to globalize number or object data used by triggers across multiple trigger or maps.
If we were to use you example here. What PRAT does is not helping with MUI, but it will allow you to assign these values through Object Editor isntead of through Trigger Editor. Allowing easier adjustment, should you want to add your shield to another Unit-type, or have a different Shield Value.

if.gif
(Unit-type of (Trained unit)) Equal to Irregular Footman
set.gif
Set ShieldsInitialValue[ShieldsIndexInteger] = 500
 
Top