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
Oh, so you did translate it, sorry about that. The latter comment still stands though. Read the code thoroughly this time, looks like the suggestions were implemented.
EDIT: I think the previous instance method should be retained.
a huge overhaul it is, almost no wrapper function,
I want to note that :
- this version has a limit of ROUNDUP(8190/udg_limit)-1 instances running at the same time.
- you're not using map header, how you can be sure that your script run before user's trigger?
- you should add how to import instructions.
nope, what I meant is, the target of this resource is pure GUI non JNGP user. if such user would like to implement this in their 50% done map and change already made spell to conform to this resource, how will they do it? isn't this resource will be compiled at the bottom of the code, not at the top?
rather than information to copy and paste the variable, why not make a GUI trigger using all global variable that just need to be copy-pasted? so user who has enable "Automatically create unknown variables when passing trigger data" or such can just copy that trigger into their map then delete it.
and still, I suggest to add destructable set to this.
nope, what I meant is, the target of this resource is pure GUI non JNGP user. if such user would like to implement this in their 50% done map and change already made spell to conform to this resource, how will they do it? isn't this resource will be compiled at the bottom of the code, not at the top?
but that doesn't really matters. the important thing is that this resource should be loaded before the user fires the timer. that happends on casting spells and those don't happend on init. is that your concern?.
rather than information to copy and paste the variable, why not make a GUI trigger using all global variable that just need to be copy-pasted? so user who has enable "Automatically create unknown variables when passing trigger data" or such can just copy that trigger into their map then delete it.
but that doesn't really matters. the important thing is that this resource should be loaded before the user fires the timer. that happends on casting spells and those don't happend on init. is that your concern?.
I meant the previous instancing method, not the instance method. The reason is the array limits will greatly reduce the amount of spell instance per spell type.
but that doesn't really matters. the important thing is that this resource should be loaded before the user fires the timer. that happends on casting spells and those don't happend on init. is that your concern?.
He is talking about syntax errors, your system must be declared above the triggers that will use it, that's why he suggested to put it on the map header section.
I meant the previous instancing method, not the instance method. The reason is the array limits will greatly reduce the amount of spell instance per spell type.
if you put a limit of 50, you will be able to have ~163 instances at a time. 163 spell in the same time, didn't see that before. i really, really think that user will not reach that number.
edit: although, now that i think... i have an entire hashtable that i can use if the user goes over the limit... uhmm c:
edit: yes i will add destructibles too .
the only kind of spells in my head which can reach the limit of 50 unit/real/integer variable is a custom Cluster Rockets with each unit variable referring to missile and real variable for its trajectory.
He is talking about syntax errors, your system must be declared above the triggers that will use it, that's why he suggested to put it on the map header section.
yeah at first I actually think the same thing, but after further reading, his script is never been called outside of his script, and the only thing user need to do is setting variable and using it. so yeah, I think this won't need to be inside map init.
i did realice though that i'm not reseting the counter.
edit:
the only kind of spells in my head which can reach the limit of 50 unit/real/integer variable is a custom Cluster Rockets with each unit variable referring to missile and real variable for its trajectory.
Another thing to add with your update would be easier importing to new maps.
Make an eventless trigger and set all your variables in it so they can be copied over easily.
[trigger=]
Events
Conditions
Actions
Set boolean[0] = False
Set effect[0] = (Last created special effect)
Set effect_helper = (Last created special effect)
Set group[0] = (Random 4 units from (Units in (Playable map area)))
Set group_helper = (Random 4 units from (Units in (Playable map area)))
Set hashtable = (Last created hashtable)
Set integer[0] = 0
Set integer_helper = 0
Set player[0] = (Owner of (Triggering unit))
Set player_helper = (Owner of (Triggering unit))
Set point[0] = ((Center of (Playable map area)) offset by (0.00, 0.00))
Set point_helper = ((Center of (Playable map area)) offset by (0.00, 0.00))
Set real[0] = 0.00
Set real_helper = 0.00
Set trigger = (This trigger)
Set unit[0] = (Last created unit)
Set unit_helper = (Last created unit)
[/TRIGGER]
+ added reset on finish
+ added destructible support
+ improved map-example
i check for recursion problems... nothing happended so it should work fine .
edit: seems like there's a bug because dat-c3's spell is not working properly
edit: after thinking, the only solution that came to me is:
edit: good news, wasn't because of recursion problems, it was because of a mistake of mine c:. the time when your entire utility fails because of a division u.u
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
if ( instance > 1 ) then
set instance = instance * udg_limit
endif
return instance
endfunction
without the code below the reserving space, the instance available are from start are 1,2,3,4,5,6,7,8,....
using the code below the reserving space, the instance become: 1,100,150,200,250,300,350,400,..., its not using the index of 51-100 for anything which means yours actually have a maximum instance of ROUNDUP(8190/udg_limit)-2 not ROUNDUP(8190/udg_limit)-1 (not much effect actually, only one instance less).
and on the recycleinstance, I haven't checked if integer round up or down when dealing with fractions in calculation, but considering this line
JASS:
set instance = instance / udg_limit
if instance given is 1, if the integer round up, it will do well, but if it round down to 0, it will bug off the allocation/deallocation to the point it will always create instance as udg_recycle will always 0.
if instance given is 1, if the integer round up, it will do well, but if it round down to 0, it will bug off the allocation/deallocation to the point it will always create instance as udg_recycle will always 0.
ehm, its still round(8190/limit) - 1 max instance, why?
JASS:
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
if ( instance > 0 ) then
set instance = instance * udg_limit
endif
return instance
endfunction
function MUI_RecycleInstance takes integer instance returns nothing
if ( instance > 0 ) then
set instance = instance / udg_limit
endif
set udg_recycleNext[instance] = udg_recycle
set udg_recycle = instance
endfunction
your instance given before the //reserving space is still 1,2,3,...
and after the if check, it becomes 50,100,150,... which means index 0-50 is still unused. and by the way, because the instance count always start from 1 and increase, you don't need the if instance > 0 check both in createinstance and recycleinstance, you can just multiply or divide it directly, no need for an if check. like this:
JASS:
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
function MUI_RecycleInstance takes integer instance returns nothing
set instance = instance / udg_limit
set udg_recycleNext[instance] = udg_recycle
set udg_recycle = instance
endfunction
I like the whole Idea, it let's me focus more on the skill/ability I am creating.
It is a template (eh duh ppl it is in the template section) that takes care of the
tedious things that could annoy and bore you.
The only thing is that you have to make a list for yourself what number corresponds
with which type of saved unit.
Also What would happen if I have a channelled spell and an other spellcaster
uses an ability?
(assuming both triggers use the set(1) for casting unit)
That would cause some errors I'm sure.
so must we have a list of corresponding numbers that are each unique to prevent this?
I hope not...
It would still make for some easier spell making.
Which would be great when triggering minion spells
(no need to explain that term right?)
Looks neat and will try. Hope it works.
or get's improved and then approved.
just wondering, why not try to contact some Spells section moderator to make notice of this resource? I found that some latest submitted resource already moderated while this one left unmoderated for a month.
approval may not be warrant, but at least you can improve this resource through what those moderators found.
A resource like this is not an easy thing to moderate because you have to consider the impact this will have on future resources.
@Ruke, have you tested how many handles this works with before the op limit kicks in? (Try something like 20 units, items, destructables, effects, etc...)
To be honest, I'm not a fan of the system. It does unnecessary work if there is nothing to loop. And it hides the spell making mechanics from the user, using this can make it harder for people to move from gui to jass/vjass. It can still be useful to some people and it think it is approvable.
You have more control over the game when you use jass, vjass makes it easier to control that. Anyway, just to clear things up, I'm not against this system.
@Ruke, have you tested how many handles this works with before the op limit kicks in? (Try something like 20 units, items, destructables, effects, etc...)
Yea, and a custom-tailored game engine is nearly always better than using something general. But people will keep using general solutions to make things faster even if they lose some of the performance.
Yeah... it might even make it hard for them to make MUI if they ever need to make it themselves...
IMHO, it is better to teach users to know how to make MUI by themselves rather than teaching them to rely on a general resource to make MUI for them... that will serve them better in the future... and making MUI after all is not a really complex or hard thing, at least it won't be for much of the things that you can do in GUI...
especially seeing as how the GUI part of this is pretty much all just set-up... and the "hidden" jass part is what does everything...
anyway, yes, the "system" does what it was meant to do... just not fond of this kind of systems...
Yeah... it might even make it hard for them to make MUI if they ever need to make it themselves...
IMHO, it is better to teach users to know how to make MUI by themselves rather than teaching them to rely on a general resource to make MUI for them... that will serve them better in the future... and making MUI after all is not a really complex or hard thing, at least it won't be for much of the things that you can do in GUI...
making mui with gui isn't hard, but anoying/time-consuming/repetitive and it converts our global variables in a mess. this utility fixes those problems.
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.