Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
Hi there, this time with an utility exclusively for GUIers (sorry jassers :c) which I think you gonna love it.
It's well knowed that making MUI spells in JASS is easier than GUI. That is because of the shitty process of making it MUI, instead of just worry about the spell itself.
Some people, do use the array technique; other use hashtables; and crazy ones uses waits with locals. All of these ways work fine, the problem resides in repetitive steps, and, when we are developing it, it is hard to mantain (unless you're using wait-technique, but cmom, waits! >: o)
So, what if we create another way of make MUI abilities with a little bit of dark magic wit?
This is exactly what I'm bringing. A new, ordered, elegant and extremelly easy, way of making MUI abilities in GUI (without need of jass new gen pack).
Let's see an example of an a burning ability, those that really like me c:
Burning
Events
Unit - A unit Starts the effect of an ability
Conditions
(Ability being cast) Equal to Burning
Actions
Set set_unit[1] = (Triggering unit)
Set set_unit[2] = (Target unit of ability being cast)
Special Effect - Create a special effect attached to the chest of (Target unit of ability being cast) using Abilities\Spells\Human\FlameStrike\FlameStrikeEmbers.mdl
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
get_real[1] Greater than 0.00
Then - Actions
-------- If there is still time, make damage --------
Unit - Cause get_unit[1] to damage get_unit[2], dealing 10.00 damage of attack type Spells and damage type Normal
Else - Actions
-------- Out of time, finish --------
Game - Display to (All players) the text: Finished spell
-------- Automatically remove leaks, like a boss --------
Set automaticClean = True
Set finish = True
Sweet, isn't?
Without need of loops (array technique), without need of loading from hashtable (hashtable technique) and without, of course, ugly waits . This allow the final user (you), to focus completelly on his ability .
Hey man, you have leaks in that trigger!
Do I?, this utility can handle all destructors (remove location, destroy group, etc.), so you don't have to worry about it anymore .
MUI (utility's name) is yet in experimental-phase. I did not test it exaustly, but it did pass some of the test that I made it.
To use it, just create a trigger called "MUI" (without quotes) and paste this, and don't forget the variables!:
JASS:
// allocator
// thanks nestharus/vexorian c:
function MUI_CreateInstance takes nothing returns integer
local integer instance
if ( udg_recycle == 0 ) then
set udg_instanceCount = udg_instanceCount + 1
set instance = udg_instanceCount
else
set instance = udg_recycle
set udg_recycle = udg_recycleNext[udg_recycle]
endif
// reserving space
set instance = instance * udg_limit
return instance
endfunction
// deallocator
// thanks nestharus/vexorian c:
function MUI_RecycleInstance takes integer instance returns nothing
set instance = instance / udg_limit
set udg_recycleNext[instance] = udg_recycle
set udg_recycle = instance
endfunction
function MUI_ShowOverLimitError takes nothing returns nothing
call BJDebugMsg("No puedes guardar mas de " + I2S(udg_limit) + ". Si necesitas mas, modifica la variable limit.\nYou can't save more than " + I2S(udg_limit) + ". If you need more, modify the variable called 'limit'")
endfunction
// private
function MUI_SaveUnits takes integer instance returns nothing
local integer i = 1
loop
set udg_mui_unit[instance + i] = udg_set_unit[i]
set udg_set_unit[i] = null
exitwhen i == udg_used_units
set i = i + 1
endloop
set udg_mui_used_units[instance] = udg_used_units
endfunction
// private
function MUI_SaveReals takes integer instance returns nothing
local integer i = 1
loop
set udg_mui_real[instance + i] = udg_set_real[i]
set udg_set_real[i] = 0.
exitwhen i == udg_used_reals
set i = i + 1
endloop
set udg_mui_used_reals[instance] = udg_used_reals
endfunction
// private
function MUI_SavePlayers takes integer instance returns nothing
local integer i = 1
loop
set udg_mui_player[instance + i] = udg_set_player[i]
set udg_set_player[i] = null
exitwhen i == udg_used_players
set i = i + 1
endloop
set udg_mui_used_players[instance] = udg_used_players
endfunction
// private
function MUI_SavePoints takes integer instance returns nothing
local integer i = 1
loop
set udg_mui_point[instance + i] = udg_set_point[i]
set udg_set_point[i] = null
exitwhen i == udg_used_points
set i = i + 1
endloop
set udg_mui_used_points[instance] = udg_used_points
endfunction
// private
function MUI_SaveEffects takes integer instance returns nothing
local integer i = 1
loop
set udg_mui_effect[instance + i] = udg_set_effect[i]
set udg_set_effect[i] = null
exitwhen i == udg_used_effects
set i = i + 1
endloop
set udg_mui_used_effects[instance] = udg_used_effects
endfunction
// private
function MUI_SaveIntegers takes integer instance returns nothing
local integer i = 1
loop
set udg_mui_integer[instance + i] = udg_set_integer[i]
set udg_set_integer[i] = 0
exitwhen i == udg_used_integers
set i = i + 1
endloop
set udg_mui_used_integers[instance] = udg_used_integers
endfunction
// private
function MUI_SaveUnitGroups takes integer instance returns nothing
local integer i = 1
loop
set udg_mui_group[instance + i] = udg_set_group[i]
set udg_set_group[i] = null
exitwhen i == udg_used_groups
set i = i + 1
endloop
set udg_mui_used_groups[instance] = udg_used_groups
endfunction
// private
function MUI_SaveBooleans takes integer instance returns nothing
local integer i = 1
loop
set udg_mui_boolean[instance + i] = udg_set_boolean[i]
set udg_set_boolean[i] = false
exitwhen i == udg_used_booleans
set i = i + 1
endloop
set udg_mui_used_booleans[instance] = udg_used_booleans
endfunction
// private
function MUI_SaveDestructibles takes integer instance returns nothing
local integer i = 1
loop
set udg_mui_destructible[instance + i] = udg_set_destructible[i]
set udg_set_destructible[i] = null
exitwhen i == udg_used_destructibles
set i = i + 1
endloop
set udg_mui_used_destructibles[instance] = udg_used_destructibles
endfunction
// private
function MUI_Periodic takes nothing returns nothing
local timer expiredTimer = GetExpiredTimer()
local integer expiredTimerId = GetHandleId(expiredTimer)
local integer instance = LoadInteger(udg_hashtable, expiredTimerId, 0)
local integer i
// avoid recursion problems
local unit array prevGetUnit
local real array prevGetReal
local player array prevGetPlayer
local location array prevGetPoint
local effect array prevGetEffect
local integer array prevGetInteger
local group array prevGetGroup
local boolean array prevGetBoolean
local destructable array prevGetDestructible
local boolean prevAutomaticClean = udg_automaticClean
local boolean prevFinish = udg_finish
// unit
if ( udg_mui_used_units[instance] > 0 ) then
set i = 1
loop
set prevGetUnit[i] = udg_get_unit[i]
set udg_get_unit[i] = udg_mui_unit[instance + i]
exitwhen i == udg_mui_used_units[instance]
set i = i + 1
endloop
endif
// real
if ( udg_mui_used_reals[instance] > 0 ) then
set i = 1
loop
set prevGetReal[i] = udg_get_real[i]
set udg_get_real[i] = udg_mui_real[instance + i]
exitwhen i == udg_mui_used_reals[instance]
set i = i + 1
endloop
endif
// player
if ( udg_mui_used_players[instance] > 0 ) then
set i = 1
loop
set prevGetPlayer[i] = udg_get_player[i]
set udg_get_player[i] = udg_mui_player[instance + i]
exitwhen i == udg_mui_used_players[instance]
set i = i + 1
endloop
endif
// location
if ( udg_mui_used_points[instance] > 0 ) then
set i = 1
loop
set prevGetPoint[i] = udg_get_point[i]
set udg_get_point[i] = udg_mui_point[instance + i]
exitwhen i == udg_mui_used_points[instance]
set i = i + 1
endloop
endif
// effect
if ( udg_mui_used_effects[instance] > 0 ) then
set i = 1
loop
set prevGetEffect[i] = udg_get_effect[i]
set udg_get_effect[i] = udg_mui_effect[instance + i]
exitwhen i == udg_mui_used_effects[instance]
set i = i + 1
endloop
endif
// integer
if ( udg_mui_used_integers[instance] > 0 ) then
set i = 1
loop
set prevGetInteger[i] = udg_get_integer[i]
set udg_get_integer[i] = udg_mui_integer[instance + i]
exitwhen i == udg_mui_used_integers[instance]
set i = i + 1
endloop
endif
// group
if ( udg_mui_used_groups[instance] > 0 ) then
set i = 1
loop
set prevGetGroup[i] = udg_get_group[i]
set udg_get_group[i] = udg_mui_group[instance + i]
exitwhen i == udg_mui_used_groups[instance]
set i = i + 1
endloop
endif
// boolean
if ( udg_mui_used_booleans[instance] > 0 ) then
set i = 1
loop
set prevGetBoolean[i] = udg_get_boolean[i]
set udg_get_boolean[i] = udg_mui_boolean[instance + i]
exitwhen i == udg_mui_used_booleans[instance]
set i = i + 1
endloop
endif
// destructible
if ( udg_mui_used_destructibles[instance] > 0 ) then
set i = 1
loop
set prevGetDestructible[i] = udg_get_destructible[i]
set udg_get_destructible[i] = udg_mui_destructible[instance + i]
exitwhen i == udg_mui_used_destructibles[instance]
set i = i + 1
endloop
endif
call TriggerExecute(LoadTriggerHandle(udg_hashtable, expiredTimerId, 1))
// unit
if ( udg_mui_used_units[instance] > 0 ) then
set i = 1
loop
if ( udg_finish ) then
set udg_mui_unit[instance + i] = null
else
set udg_mui_unit[instance + i] = udg_get_unit[i]
endif
set udg_get_unit[i] = prevGetUnit[i]
set prevGetUnit[i] = null
exitwhen i == udg_mui_used_units[instance]
set i = i + 1
endloop
endif
// real
if ( udg_mui_used_reals[instance] > 0 ) then
set i = 1
loop
if ( udg_finish ) then
set udg_mui_real[instance + i] = 0.
else
set udg_mui_real[instance + i] = udg_get_real[i]
endif
set udg_get_real[i] = prevGetReal[i]
exitwhen i == udg_mui_used_reals[instance]
set i = i + 1
endloop
endif
// player
if ( udg_mui_used_players[instance] > 0 ) then
set i = 1
loop
if ( udg_finish ) then
set udg_mui_player[instance + i] = null
else
set udg_mui_player[instance + i] = udg_get_player[i]
endif
set udg_get_player[i] = prevGetPlayer[i]
set prevGetPlayer[i] = null
exitwhen i == udg_mui_used_players[instance]
set i = i + 1
endloop
endif
// location
if ( udg_mui_used_points[instance] > 0 ) then
set i = 1
loop
if ( udg_finish ) then
if ( udg_automaticClean ) then
call RemoveLocation(udg_mui_point[instance + i])
call RemoveLocation(udg_get_point[i])
endif
set udg_mui_point[instance + i] = null
else
if ( udg_mui_point[instance + i] != udg_get_point[i] ) then
call RemoveLocation(udg_mui_point[instance + i])
set udg_mui_point[instance + i] = udg_get_point[i]
endif
endif
set udg_get_point[i] = prevGetPoint[i]
set prevGetPoint[i] = null
exitwhen i == udg_mui_used_points[instance]
set i = i + 1
endloop
endif
// effect
if ( udg_mui_used_effects[instance] > 0 ) then
set i = 1
loop
if ( udg_finish ) then
if ( udg_automaticClean ) then
call DestroyEffect(udg_mui_effect[instance + i])
call DestroyEffect(udg_get_effect[i])
endif
set udg_mui_effect[instance + i] = null
else
if ( udg_mui_effect[instance + i] != udg_get_effect[i] ) then
call DestroyEffect(udg_mui_effect[instance + i])
set udg_mui_effect[instance + i] = udg_get_effect[i]
endif
endif
set udg_get_effect[i] = prevGetEffect[i]
set prevGetEffect[i] = null
exitwhen i == udg_mui_used_effects[instance]
set i = i + 1
endloop
endif
// integer
if ( udg_mui_used_integers[instance] > 0 ) then
set i = 1
loop
if ( udg_finish ) then
set udg_mui_integer[instance + i] = 0
else
set udg_mui_integer[instance + i] = udg_get_integer[i]
endif
set udg_get_integer[i] = prevGetInteger[i]
exitwhen i == udg_mui_used_integers[instance]
set i = i + 1
endloop
endif
// groups
if ( udg_mui_used_groups[instance] > 0 ) then
set i = 1
loop
if ( udg_finish ) then
if ( udg_automaticClean ) then
call DestroyGroup(udg_mui_group[instance + i])
call DestroyGroup(udg_get_group[i])
endif
set udg_mui_group[instance + i] = null
else
if ( udg_mui_group[instance + i] != udg_get_group[i] ) then
call DestroyGroup(udg_mui_group[instance + i])
set udg_mui_group[instance + i] = udg_get_group[i]
endif
endif
set udg_get_group[i] = prevGetGroup[i]
set prevGetGroup[i] = null
exitwhen i == udg_mui_used_groups[instance]
set i = i + 1
endloop
endif
// boolean
if ( udg_mui_used_booleans[instance] > 0 ) then
set i = 1
loop
if ( udg_finish ) then
set udg_mui_boolean[instance + i] = false
else
set udg_mui_boolean[instance + i] = udg_get_boolean[i]
endif
set udg_get_boolean[i] = prevGetBoolean[i]
exitwhen i == udg_mui_used_booleans[instance]
set i = i + 1
endloop
endif
// destructible
if ( udg_mui_used_destructibles[instance] > 0 ) then
set i = 1
loop
if ( udg_finish ) then
if ( udg_automaticClean ) then
call RemoveDestructable(udg_mui_destructible[instance + i])
call RemoveDestructable(udg_get_destructible[instance + i])
endif
set udg_mui_destructible[instance + i] = null
else
set udg_mui_destructible[instance + i] = udg_get_destructible[i]
endif
set udg_get_destructible[i] = prevGetDestructible[i]
exitwhen i == udg_mui_used_destructibles[instance]
set i = i + 1
endloop
endif
if ( udg_finish ) then
set udg_mui_used_units[instance] = 0
set udg_mui_used_reals[instance] = 0
set udg_mui_used_players[instance] = 0
set udg_mui_used_points[instance] = 0
set udg_mui_used_effects[instance] = 0
set udg_mui_used_integers[instance] = 0
set udg_mui_used_groups[instance] = 0
set udg_mui_used_booleans[instance] = 0
set udg_mui_used_destructibles[instance] = 0
call MUI_RecycleInstance(instance)
call FlushChildHashtable(udg_hashtable, expiredTimerId)
call PauseTimer(expiredTimer)
call DestroyTimer(expiredTimer)
endif
set udg_automaticClean = prevAutomaticClean
set udg_finish = prevFinish
set expiredTimer = null
endfunction
// private
function MUI_OnTimeoutChange takes nothing returns nothing
local timer periodicTimer = CreateTimer()
local integer instance = MUI_CreateInstance()
// units
if ( udg_used_units > 0 ) then
if ( udg_used_units > udg_limit ) then
call MUI_ShowOverLimitError()
else
call MUI_SaveUnits(instance)
set udg_used_units = 0
endif
endif
// reals
if ( udg_used_reals > 0 ) then
if ( udg_used_reals > udg_limit ) then
call MUI_ShowOverLimitError()
else
call MUI_SaveReals(instance)
set udg_used_reals = 0
endif
endif
// players
if ( udg_used_players > 0 ) then
if ( udg_used_players > udg_limit ) then
call MUI_ShowOverLimitError()
else
call MUI_SavePlayers(instance)
set udg_used_players = 0
endif
endif
// points
if ( udg_used_points > 0 ) then
if ( udg_used_points > udg_limit ) then
call MUI_ShowOverLimitError()
else
call MUI_SavePoints(instance)
set udg_used_points = 0
endif
endif
// effects
if ( udg_used_effects > 0 ) then
if ( udg_used_effects > udg_limit ) then
call MUI_ShowOverLimitError()
else
call MUI_SaveEffects(instance)
set udg_used_effects = 0
endif
endif
// integers
if ( udg_used_integers > 0 ) then
if ( udg_used_integers > udg_limit ) then
call MUI_ShowOverLimitError()
else
call MUI_SaveIntegers(instance)
set udg_used_integers = 0
endif
endif
// groups
if ( udg_used_groups > 0 ) then
if ( udg_used_groups > udg_limit ) then
call MUI_ShowOverLimitError()
else
call MUI_SaveUnitGroups(instance)
set udg_used_groups = 0
endif
endif
// boolean
if ( udg_used_booleans > 0 ) then
if ( udg_used_booleans > udg_limit ) then
call MUI_ShowOverLimitError()
else
call MUI_SaveBooleans(instance)
set udg_used_booleans = 0
endif
endif
// destructibles
if ( udg_used_destructibles > 0 ) then
if ( udg_used_destructibles > udg_limit ) then
call MUI_ShowOverLimitError()
else
call MUI_SaveDestructibles(instance)
set udg_used_destructibles = 0
endif
endif
call SaveInteger(udg_hashtable, GetHandleId(periodicTimer), 0, instance)
call SaveTriggerHandle(udg_hashtable, GetHandleId(periodicTimer), 1, udg_trigger)
call TimerStart(periodicTimer, udg_timeout, true, function MUI_Periodic)
set udg_timeout = 0.
set udg_trigger = null
set periodicTimer = null
endfunction
// initializer
function InitTrig_MUI takes nothing returns nothing
set gg_trg_MUI = CreateTrigger()
set udg_hashtable = InitHashtable()
call TriggerRegisterVariableEvent(gg_trg_MUI, "udg_timeout", GREATER_THAN, 0)
call TriggerAddAction(gg_trg_MUI, function MUI_OnTimeoutChange)
endfunction
How does it works?
Like array technique and hashtable, just hidding the process to the final user making it more friendly and easy to work with.
Is it efficient?
If you're really asking me this, I will say: go home my friend, you're drunk.
Can you explain me a little bit more how to save things?
It's very simple.
First, we need something to save. Let's say that we want to save a caster:
Set set_unit[1] = (Triggering unit)
Notice that when we save, we have to use the set_x (where x is the type of the data that we are going to save).
After we save something, we need to tell to this utility, how many space do we use. So, if we save 1 unit, we just say:
Set used_units = 1
If we're using 2, then we say 2, etc.
When we want to retrieve the data that we just saved, we just need to use the get_x variables (where x is the type, same as set_x).
If I saved this:
Set set_unit[1] = (Triggering unit)
Set set_unit[2] = (Target unit of ability being cast)
Set used_units = 2
To access to (Triggering unit), we just have to use get_unit[1]. To access (Target unit of ...) we just use unit[2]. You got it?, it depends on the order in what we save it.
Same with the other variable types (real, integer, etc.).
What is trigger?
The trigger' variable is used by this utility to know what trigger to execute when the timer expires. Before you set the timeout variable, you must set the trigger first.
What is timeout?
When you set a value to timeout (mean timeout = x) a timer will begin with the timeout of timeout (dah!). When it expires (the timer) it will execute the trigger that you set.
Important: Set timeout at the very last of the trigger.
What is automaticClean?
If you don't wan't to worry about leaks, when you finish your spell, just set it to true. If it is true, this utility will clear leaks for you .
What is finish?
Set finish to true, when you wan't to finish the spell.
Can I use the variables called mui_x?
Please no, those are used by this utility.
15th Dec 2013
Maker: Auseful system that can makes creating spells
easier.
The system has a bit of overhead since it checks for every
type even if they are not used
15th Dec 2013
Maker: Auseful system that can makes creating spells
easier.
The system has a bit of overhead since it checks for every
type even if they are not used
Where's the loop? You should make two spells instead of one for the example because I see nothing interesting about this. How does giving stuff an array number of one/1 make stuff MUI?
there is no loop my friend .
well the mui crap is handled by the utility, the variables get their value depending on the order in which were saved (read read c.
so, when the timer gets executed, the utility sets value to the variables, so the user can use them .
yes "it is". could be more efficient?, yes it can, but it will be kinda pointless (i didn't see high fps-drops). the goal of this, is to make gui-users' life easier.
Making triggering easier like this is an example of bad habits of code or something like that someone has said before.
it is not. you can keep repeating your self with the other methods, but why?, it is a waste of time. and remember, we are in gui.
the same goes for the leak-cleaner. users still have to make use of destroy-effect, group, etc., but they don't have to make x = null, that is old-school.
uhmm, it is not a tutorial, i'm presenting an utility. but it should have its own tutorial.
One question... how large is the limit? 8191 normally for normal MUI stuff due to array limit. If this is hashtables then it would be 255 right? I am not sure which area this falls in, but it looks like arrays. Just curious to how large the arrays go if not to the max.
it isn't efficient?, what kinda of maps/abilities do you have in mind that requires this to be more efficient?, limits?, how is that?
again, this is not intended to be efficient, but to easy things up.
Aha I was doing something wrong as usual, I finally made a beam with your index system. I must say it was pretty easy and fast once I got the hang of it. Thank you making such a system yet I do want to see it handle something more complex to see how much it can handle lag-wise.
Fyi I was trying to create them at a certain spot every so tick of the timer yet it moved all of them in the timer trigger so instead I created them all at once in the execute trigger.
Aha I was doing something wrong as usual, I finally made a beam with your index system. I must say it was pretty easy and fast once I got the hang of it. Thank you making such a system yet I do want to see it handle something more complex to see how much it can handle lag-wise.
Fyi I was trying to create them at a certain spot every so tick of the timer yet it moved all of them in the timer trigger so instead I created them all at once in the execute trigger.
BJDebugMsg("MUI - No podes guardar mas de " + I2S(MUI_GetLimit()) + ". Si necesitas mas, incrementa el limite en MUI_GetLimit")
The counting key functions are pointless.
I don't see how this is better than learning indexed arrays. Since indexed arrays are much faster. OR learning MUI hashtables. It is not hard at all.
It is better if you put more notes in your work.
It seems like you create multiple hashtables for each different spell.
A true MUI system would take advantage of one spell.
I would suggest a complete rework or scrapping it.
You should really explain your work better. Also anything submitted should be as efficient as possible.
Since this handles spells. It should use coordinates not locations. Creating and destroying locations is very inefficient compared to using coordinates.
if you like to repeat yourself, you're welcome to do it.
It is better if you put more notes in your work.
It seems like you create multiple hashtables for each different spell.
A true MUI system would take advantage of one spell.
at the begining i didn't know if this were to work, so it's kinda improvised (that is why the lack of comments, although names are quite self-explanatory).
You should really explain your work better. Also anything submitted should be as efficient as possible.
oh, but it is efficient... on real/most-scenarios c:
i dont know if i can explain it better :\, i mean, i put 3 examples (i have to upload one more that was donated by Dat-C3, thanks by the way).
Since this handles spells. It should use coordinates not locations. Creating and destroying locations is very inefficient compared to using coordinates.
1) They are pointless because they return the same number so just simply use that number in the functions rather than create unnecessary function calls.
2) That was pointless and ignorant. What i said is valid.
3) Then put in comments after.
4) If it is not efficient in all scenarios then it is not efficient.
5) Yes as creating and destroying locations is very inefficient.
You can simply take a location using a function and change it to coordinates. That way every time those coordinates are used it is more efficient.
If it's not efficient it most likely will not be approved.
1) They are pointless because they return the same number so just simply use that number in the functions rather than create unnecessary function calls.
5) Yes as creating and destroying locations is very inefficient.
You can simply take a location using a function and change it to coordinates. That way every time those coordinates are used it is more efficient.
efficient is not the point, but the ease (less time doing something, gives you more time to do other), increse productivity of the user (it is easy!) and increase scalability maintainability (easy to read, easy to maintain). but (there is always a but) with this, you have to sacrifice something, and that is efficiency. you lose a little bit of that but you're gaining other stuff (which i think they are more important, dont you think so?).
i read your idea again... i think i don't follow it.
i mean, took a location from gui -> pass it to real -> what to do with the location? -> save the real -> when the user requires his location -> pass a real? -> user gets mad
i think locations are more easy to use in gui than coordinates.
6) Efficiency plays a big role in all systems. All systems should be as efficient as possible.
an example: your system works awesome in every scenario where it will be used. you know that you can improve it to make it work more efficient, but why?, users will no see any diference and it is not required! (cuz it does his job, and it does pretty well ).
Though he should be using coordinates. Check out my beam example using his indexer, it starts to lag at 12+ instances casted at the same time
I'm going to spare my review table for this one, when i first saw the trigger script .... it was awful, the really really long trigger is like 4x larger than normal MUI, we, coders do! And, for instance, i was completely Lost in it
I'll stand with the first comments and say: make a Tutorial, attach a demo map to the thread, it would be extremely better
yep, i will add it later, thanks.
also i will translate the messages too.
when i first saw the trigger script .... it was awful, the really really long trigger is like 4x larger than normal MUI, we, coders do! And, for instance, i was completely Lost in it
I dont see this getting approved. Also my spells took me about 15 minutes with indexed arrays. So this won't save any time. Hashtables are up to 8 times slower than indexed arrays.
Also how do you follow which unit belongs to what spell ?
Like said earlier something like this is bad coding practice. It is also inefficient and the TO doesn't seem to want to change anything to make it better.
I made something like this a while back but with some major differences. The spells were saved by the triggers handle id. Then each instance was increased for that certain spell. I then used a timer event loop to keep track of when the instance should end so there is no unecessary looping. It was still slow because it used hashtables and I never submitted it because it is simply bad practice.
Like said earlier something like this is bad coding practice. It is also inefficient and the TO doesn't seem to want to change anything to make it better.
i will improve it, but not in areas where it does not need to.
I made something like this a while back but with some major differences. The spells were saved by the triggers handle id. Then each instance was increased for that certain spell. I then used a timer event loop to keep track of when the instance should end so there is no unecessary looping. It was still slow because it used hashtables and I never submitted it because it is simply bad practice.
This type of thing is bad practice because it is doesn't show the right way on how spells should be made.
Ask bribe for his benchmark. He is the one that found this out.
Quote:
Also how do you follow which unit belongs to what spell ?
you save it.
When someone asks something like that normally you show them where in the code it does that not just say you save it.
I don't code in GUI anymore. This won't save time. Also my spells are complex you should look before saying they are simple.
The spell you showed is also inefficient and very bad to.
That spell uses an old style of indexing and de-indexing. The old style runs through indexes that are already used. It also has more lines of code than the new style.
the utility is like structs from vjass but to gui.
you init the "process" with MUI_Start(timeout).
MUI_Start it's like struct.create(), it gives you an instance where you can save your data (unit, real, etc.). also, it starts a timer with the timeout that has been passed.
that timer, holds the instance (the one that we just created with MUI_Start), so when it expires, we're able to retrieve the data.
when the data is retrieved, it is assigned to the variables so that the user can use them.
MUI_End it is like struct.destroy, it recycles the instance and clear things up.
the saving process is:
instance, amount_of_this_type_of_data_saved, data
where amount_of_this_type_of_data_saved is a counting which increases every time the user saves something of that same type.
example:
call MUI_Unit(unit)
instance, 1, unit
call MUI_Unit(unit)
instance, 2 (here, the counter has been increased), unit
if a say:
call MUI_Real(real)
instance, 1, real
why 1?, because it's the first of this type
but, why it doesn't collide?
because of MUI_GetStartXNumber, where X it's the type.
so, if unit begins at 0, the counter will start at that number.
if reals begins at 1000, counter will start at that number.
i was talking about if you did try this utility. if you didn't, you can't say if this does or not saves time.
The spell you showed is also inefficient and very bad to.
That spell uses an old style of indexing and de-indexing. The old style runs through indexes that are already used. It also has more lines of code than the new style.
I know how structs work i only code in jass and vJass. Try one of my spells with this system.
All local handles must be nulled when assigned a value. You barely null half of them.
Also as previously stated get rid of all the function calls that aren't needed. If you are only using one hashtable. Why would you create extra handles (that you are leaking btw) to store the hashtable if you already know the hashtables name...
Same with a ton of the other function calls.
i'm not creating extra handles, i'm working with only 1 hashtable. if the hashtable has been created, return it, if not, create it, and then return it.
it doesn't leak, because the hashtable is never destroyed.
There's actually no leak dude, the handle is never destroyed, it will never be recycled so the local handles will always point to a single handle instance. But the amount of function calls should be reduced if possible.
There's actually no leak dude, the handle is never destroyed, it will never be recycled so the local handles will always point to a single handle instance. But the amount of function calls should be reduced if possible.
I suggest you to remove the remaining BJ in your script, as you can see:
JASS:
function ConditionalTriggerExecute takes trigger trig returns nothing
if TriggerEvaluate(trig) then
call TriggerExecute(trig)
endif
endfunction
and I suggest you to inline those MUI_GetHashtable() directly to the hashtable itself rather than using senseless wrapper, why senseless?
consider that MUI_GetHashtable() will:
1. always return the same hashtable
2. always out of user reach as it is system use
3. always initiated first time and never be initiated again
4. never be destroyed
so why always check if its exist everytime it is called?
rather than chobibo's method to change this:
JASS:
function MUI_GetHashtable takes nothing returns hashtable
if ( udg_hashtable == null ) then
set udg_hashtable = InitHashtable()
endif
return udg_hashtable
endfunction
into
JASS:
function MUI_GetHashtable takes nothing returns hashtable
return udg_hashtable
endfunction
function MUI_InitHashtable takes nothing returns nothing
set udg_hashtable = InitHashtable()
endfunction
I suggest you to do this:
JASS:
function MUI_InitHashtable takes nothing returns nothing
set udg_hashtable = InitHashtable()
endfunction
it saves one function call and one if check almost everywhere in your script as any function in your script have MUI_GetHashtable() in it.
and yes, local handle will have pointer leak if not nulled.
and why use local on this? local hashtable hashTable = MUI_GetHashtable()
use the udg_hashtable directly.
add support for destructable, although its rarely used.
why give the option to remove leak or not in MUI_End? the only case where it will be false is only when the user passes a global variable which is used in the map which is a bad practice anyway.
I suggest you to remove the remaining BJ in your script, as you can see:
JASS:
function ConditionalTriggerExecute takes trigger trig returns nothing
if TriggerEvaluate(trig) then
call TriggerExecute(trig)
endif
endfunction
and I suggest you to inline those MUI_GetHashtable() directly to the hashtable itself rather than using senseless wrapper, why senseless?
consider that MUI_GetHashtable() will:
1. always return the same hashtable
2. always out of user reach as it is system use
3. always initiated first time and never be initiated again
4. never be destroyed
so why always check if its exist everytime it is called?
rather than chobibo's method to change this:
JASS:
function MUI_GetHashtable takes nothing returns hashtable
if ( udg_hashtable == null ) then
set udg_hashtable = InitHashtable()
endif
return udg_hashtable
endfunction
into
JASS:
function MUI_GetHashtable takes nothing returns hashtable
return udg_hashtable
endfunction
function MUI_InitHashtable takes nothing returns nothing
set udg_hashtable = InitHashtable()
endfunction
I suggest you to do this:
JASS:
function MUI_InitHashtable takes nothing returns nothing
set udg_hashtable = InitHashtable()
endfunction
it saves one function call and one if check almost everywhere in your script as any function in your script have MUI_GetHashtable() in it.
and yes, local handle will have pointer leak if not nulled.
and why use local on this? local hashtable hashTable = MUI_GetHashtable()
use the udg_hashtable directly.
add support for destructable, although its rarely used.
why give the option to remove leak or not in MUI_End? the only case where it will be false is only when the user passes a global variable which is used in the map which is a bad practice anyway.
That is what i've been saying for a lot of posts lol. Thanks
The last thing i believe is necessary as some spells may have several steps. If it destroys something before all steps are completed it will cause crash.
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.