| 02-24-2009, 09:56 PM | #1 |
I was curious as to what the most efficient way to make an array of functions? I am working on a Casting System with castbars and I planned to use a timer to call a function for the actual spell affect. I would assign each spell an ID and then call a function from an Array with the same index as the ID, but I have never made a code array before. Any help? To give more information, I simply need something where I can store functions inside of an Array. I can use attached tables to store all the data I need, I just simply need a way to store a function. Driving me bonkers. |
| 02-24-2009, 11:12 PM | #2 |
JASS:function interface FI takes nothing returns nothing globals FI array Functions endglobals //blerh FI[0] = Function1Name FI[1] = Function2Name //blehr Read this if you don't understand the code: \/ http://www.wc3c.net/showthread.php?t=103408 |
| 02-25-2009, 01:09 AM | #3 |
Awesome, this is exactly what I need. If a spell takes a point target, and I use GetSpellTargetUnit(), will that return null? Trying to make a function that will return a boolean as to whether it takes a point or unit target. Once I have that I believe all the pieces I need will be complete. To give some further insight, the reason I need the point/unit target function is because I am going to be attaching a Table to a unit whenever it learns a spell. The table will be named EXACTLY what the spell is. All the data for the spell is passed to that table. Upon the spell being cast, I can recall the table since the spellname is exactly what the table is labeled. I will do the casttime, and then the table will have an ID number that will correspond to the SL index that will hold it's function. This function is what will play the graphic and do the damage. |
| 02-25-2009, 01:28 AM | #4 |
It should I believe since point target spells don't target units. -Av3n |
| 02-27-2009, 04:49 AM | #5 |
Ok, first off. This is the first piece of code I have that I am posting on here. I have several questions. 1) Removed 2) Notation. I believe I have decent notation. I know I comment well, so at least there is that. If you cannot help me with the function interface question, please assist me in bettering my notation so the next pieces of code I write are legible. 3) Inefficiency. Once again, if you cannot assist with number 1, please point out any type of inefficiency I have in this code so I can better it and in turn better my coding skills. Explanation: What this code does is upon any type of spell being cast, it calls CastSpell. This function creates a struct for all neccisary data, and displays a cast bar and a Spellname + ( + Timeleft + ) to make it look real nice. Upon Castime ending, it calls a function from the function interface, which corresponds to the spell being case (The Id variable defines this). Please note this is NOT FINISHED. I need to add in OrderID's to check if the unit interupts the cast still, and I need to finish the loop. However I wanted this checked out beforehand so I can get the function interface problem solved. References: CSData CSSafteyCache Intuitive Damage Detection System TimerUtils (Blue) JASS:scope SpellLibrary initializer Init //Everything in here is used ONLY by CastTimeFunction private keyword FI // <-- Is required in order to initalize the FI array since it is not declared yet. globals FI array SL string green = "|cff90ee90aa" string gray = "|cff808080ss" string end = "/r" endglobals //This function is here for the future when there may be talents that shorten casts. function SpellHasteExceptionMod takes unit caster, real casttime returns real local real ct = casttime local string HS = GetAttachedString(caster, "HS") //This is where I could check to see if the caster has any skills that improve casting, such as -.5 seconds off Fireball. return ct endfunction private struct SpellData integer Id real x = 0 real y = 0 unit target = null unit caster real dbot real dtop string array CastbarGreen[52] string array CastbarGray[52] real timeleft real increment texttag bar texttag time static method create takes integer whatspell, unit caster, unit target, location aoe, boolean isaoe, texttag te, texttag ti returns SpellData local SpellData D = SpellData.allocate() local integer i = 2 local string HS = GetAttachedString(caster, "HS") //Calculation Values for Damage local real db = S2R(GetAbilityEffectById(whatspell, EFFECT_TYPE_CASTER, 0)) local real dt = S2R(GetAbilityEffectById(whatspell, EFFECT_TYPE_EFFECT, 0)) local real sd = GetTableReal(HS, "spelldamage") local real sdm = GetTableReal(HS, "spelldamagemod") local real coeff //Calculation for Cast Time and Bar local real ct = S2R(GetAbilityEffectById(whatspell, EFFECT_TYPE_AREA_EFFECT, 0)) local real sh = GetTableReal(HS, "spellhaste") //Basics set D.caster = caster set D.Id = S2I(GetAbilityEffectById(whatspell, EFFECT_TYPE_SPECIAL, 0)) //Set Coefficient if (GetAbilityEffectById(whatspell, EFFECT_TYPE_MISSILE, 0) == "") then set coeff = ct/3.5 else set coeff = S2R(GetAbilityEffectById(whatspell, EFFECT_TYPE_MISSILE, 0)) endif //Calculate Damage Base set D.dbot = ((1.00 + (1.00 * sdm)*(db + (sd * coeff)))) set D.dtop = ((1.00 + (1.00 * sdm)*(dt + (sd * coeff)))) //If AoE, get the X/Y if (isaoe) then set D.x = GetLocationX(aoe) set D.y = GetLocationY(aoe) else set D.target = target endif //Calculate the Castbar set D.CastbarGreen[0] = green set D.CastbarGray[0] = gray set D.CastbarGreen[1] = "l" set D.CastbarGray[1] = "l" loop exitwhen i > 50 set D.CastbarGreen[i] = D.CastbarGreen[i-1] + D.CastbarGreen[1] set D.CastbarGray[i] = D.CastbarGray[i-1] + D.CastbarGray[1] set i = i + 1 endloop set D.CastbarGreen[51] = end set D.CastbarGray[51] = end //Calculate Casttime set ct = SpellHasteExceptionMod(caster, ct) set D.timeleft = ((1.00+(1.00*sh))*ct) set D.increment = .02*((1.00+(1.00*sh))*ct) //Update the Bar call SetTextTagText(te, D.CastbarGray[0] + D.CastbarGray[50] + D.CastbarGray[51], 0.020) call SetTextTagText(ti, R2SW(D.timeleft, 1, 1), 0.020) set D.bar = te set D.time = ti return D endmethod method onDestroy takes nothing returns nothing local integer i = 0 set .Id = 0 set .x = 0 set .y = 0 set .target = null set .caster = null set .dbot = 0 set .dtop = 0 loop exitwhen i > 51 set .CastbarGreen[i] = "" set .CastbarGray[i] = "" set i = i + 1 endloop set .timeleft = 0 set .increment = 0 endmethod endstruct private function interface FI takes SpellData D returns nothing // <-- Where does this go? lol //********************************************************************************** //Spell Library // // // // private function Fireball takes nothing returns nothing endfunction private function MagicMissle takes nothing returns nothing endfunction // // // //************************************************************************************ private function LoopCast takes nothing returns nothing local timer t = GetExpiredTimer() local SpellData D = GetTimerData(t) local real timeleft = D.timeleft local real increment = D.increment set timeleft = timeleft - .01 if (timeleft <= .00) then call DestroyTextTag(D.bar) call DestroyTextTag(D.time) call ReleaseTimer(t) call SL[D.Id].evaluate(D) else endif endfunction private function LoopChannel takes nothing returns nothing endfunction //CastTimeFunction function CastSpell takes integer whatspell, unit caster, unit target, location aoe, boolean isaoe, boolean ischannel returns nothing local timer t = NewTimer() local texttag te = CreateTextTag() local texttag ti = CreateTextTag() local SpellData D call SetTextTagText(te, "", 0.020) call SetTextTagPos(te, GetUnitX(caster), GetUnitY(caster), 80.00) call SetTextTagVelocity(te, 0, 0.00) call SetTextTagVisibility(te, true) call SetTextTagPermanent(te, false) call SetTextTagText(ti, "", 0.028) call SetTextTagPos(te, GetUnitX(caster), GetUnitY(caster), 120.00) call SetTextTagVelocity(te, 0, 0.00) call SetTextTagVisibility(te, true) call SetTextTagPermanent(te, false) set D = SpellData.create(whatspell, caster, target, aoe, isaoe, te, ti) call SetTimerData(t, D) if (ischannel) then call TimerStart(t, .01, true, function LoopChannel) else call TimerStart(t, .01, true, function LoopCast) endif set t = null set te = null set ti = null endfunction private function Init takes nothing returns nothing //Load Library set SL[0] = Fireball set SL[1] = MagicMissle endfunction endscope Edit: Discovered I can highlight the problem. Awesome. |
| 02-27-2009, 05:54 AM | #6 | |
Quote:
JASS:private function Loop takes nothing returns nothing local timer t = GetExpiredTimer() local SpellData D = GetTimerData(t) local real timeleft = D.timeleft local real increment = D.increment set timeleft = timeleft - .01 if (timeleft <= .01) then call DestroyTextTag(D.bar) call DestroyTextTag(D.time) call PauseTimer(t) call SL[D.Id].execute() else endif endfunction Your actual code is almost impossible to read; you indent fine but you don't space out related blocks of code [which I'd suggest]. |
| 02-27-2009, 06:14 AM | #7 |
Problem with that is I can't pass any relevant data to that. Although I could just make the FI take arguements eh? Oi and it is spaced out isnt it? |
| 02-27-2009, 06:25 AM | #8 | |
Quote:
I don't know what you mean 'spaced out'? Use globals to pass the data you need between the timer and the function. |
| 02-27-2009, 06:36 AM | #9 |
Your the one that told me my code isn't spaced out :p. And is it safe to set them to globals despite many people may be using the functon? |
| 02-27-2009, 07:02 AM | #10 |
Since there's no pause between setting the variables and the execution; you'll be ok. What I meant by 'space out'; your code looks like this: JASS:
local SpellData D = SpellData.allocate()
local integer i = 2
local string HS = GetAttachedString(caster, "HS")
//Calculation Values for Damage
local real db = S2R(GetAbilityEffectById(whatspell, EFFECT_TYPE_CASTER, 0))
local real dt = S2R(GetAbilityEffectById(whatspell, EFFECT_TYPE_EFFECT, 0))
local real sd = GetTableReal(HS, "spelldamage")
local real sdm = GetTableReal(HS, "spelldamagemod")
local real coeff
//Calculation for Cast Time and Bar
local real ct = S2R(GetAbilityEffectById(whatspell, EFFECT_TYPE_AREA_EFFECT, 0))
local real sh = GetTableReal(HS, "spellhaste")
//Basics
set D.caster = caster
set D.Id = S2I(GetAbilityEffectById(whatspell, EFFECT_TYPE_SPECIAL, 0))
//Set Coefficient
if (GetAbilityEffectById(whatspell, EFFECT_TYPE_MISSILE, 0) == "") then
set coeff = ct/3.5
else
set coeff = S2R(GetAbilityEffectById(whatspell, EFFECT_TYPE_MISSILE, 0))
endif
//Calculate Damage Base
set D.dbot = ((1.00 + (1.00 * sdm)*(db + (sd * coeff))))
set D.dtop = ((1.00 + (1.00 * sdm)*(dt + (sd * coeff))))
There's no way to tell when the global block ends and the next part begins; without reading the comments. Also; you can't tell what segments of code are doing; because they're all together. Basically; where you have comments you should also add a whitespace to seperate, for legebility. |
| 02-27-2009, 07:19 AM | #11 |
Ah, ok. That makes sense. |
