HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Spell Templates in vJass?

10-24-2009, 02:27 PM#1
Vexorian
I've been wanting to make templates once again.
Why not just a well-scope vJass scope?
Many probably use these already, simply copy a well-written vJass spell's trigger and paste it, then rename the library/scope and you got a whole new spell. There's a problem with this and it is that when you update the code, you have to do it twice, there is also the problem of updating without rewritting the data....

So, I've been thinking, there could be many better ways...

Option A - modules
This is the fastest by far, imagine your typical vjass spell:

Collapse JASS:
scope Spell initializer init
     globals
         private constant integer SPELL_ID = 'A000'
         // other config constants
    endglobals
    private function Damage takes real level returns real 
         return 67.0 + 6.0* level
    endfunction
    // spell's code:
// ...
    private function DoDamage takes unit u, integer level returns nothing
     local real x = Damage(level)
    endfunction

    private function init takes nothing returns nothing
      local trigger t =CreateTrigger()
           //blah blah blah...
    endfunction
endscope

To make it a template, you would have to split the logic in two parts, the implementation and the config, then you have to use modules...

Collapse JASS:
module SpellTemplateName
    private static method DoDamage takes unit u, integer level returns nothing
     local real x = Damage(level)
    endmethod

    private static method onInit takes nothing returns nothing
      local trigger t =CreateTrigger()
           //blah blah blah...
    endmethod

endmodule
The config part is a struct in another trigger/file and implements the module...

Collapse JASS:
struct Spell
    private static constant integer SPELL_ID = 'A000'
    // other config constants

    private static method Damage takes real level returns real 
         return 67.0 + 6.0* level
    endmethod

    implement SpellTemplateName
endstruct

Then another spell can be made:


Collapse JASS:
struct Spell2
    private static constant integer SPELL_ID = 'A001'
    // other config constants

    private static method Damage takes real level returns real 
         return 107.0 + 16.0* level
    endmethod

    implement SpellTemplateName
endstruct


The problem I think is having to use static member syntax for things that are actually functions and globals...
10-24-2009, 02:45 PM#2
Vexorian
Option B - hashtable + struct

This one is a little slower and closer to the old spell templates ( specifically, you needed to store spell id and level everywhere and then fetch spell data from them)

With hashtables and structs, it should be much faster than old massively gamecache spell templates, though.

The idea is to let the user do stuff like this:

Collapse JASS:
scope mySpell initializer init
    private function init takes nothing  returns nothing
       local spelltemplatename st = spelltemplatename.create('A00H')
            //[0] : default for all level...set st.damage[0] = 11.0
            set st.damage[1] = 45.0
            set st.damage[2] = 65.0
            set st.damage[3] = 1005.0
    endfunction
endscope
10-26-2009, 12:47 AM#3
Anitarf
Do spells really suffer that much from multi-version syndrome to need this kind of update-friendlyness?

Well, I dislike the first option because it kind of assumes the whole spell is in a single struct. I often prefer to organize my spells into multiple structs, there could be one for the main channeled spell instance, another for the projectiles that are being spawned etc. Of course, if all non-config code is outsourced then you could still have multiple structs all forming a single calibration section.

The hashtable idea is interesting, too.

Perhaps it makes more sense if you're using files but with GUI triggers it feels like having two instead of one is more trouble than it's worth, the one-"trigger"-per-spell requirement of JESP was a good thing and usage of vJass libraries already violates that enough (of course, in that case it's worth it because libraries have other massive advantages).
10-26-2009, 03:44 AM#4
Vexorian
"WE" triggers are inexpensive. The most it takes is a CNP.

With JESP you have one trigger per instance of the template. So it is really the same, except with a real template you can modify the code of all the spells simultaneously without messing up with the config parts.

With something like this, all instances of the spell would be able to use certain things that are really redundant when you do the JESP-style CNP. Those boolexpr filters and group globals and other small things...

The whole point is to use the same code for 5+ spells, with JESP that would take 5 triggers, with this it would take 6 triggers, unless you use option B in which it would actually take just 2 triggers if you want....

Yep, modules version would blow in practice.

Kind of wish there was some sort of ultra-module thing that worked in library level in the way modules do in structs... Kind of far-fetched though.


Anyway, on that "trigger" topic, I'll make it personal in the following weeks to end that practice for once and make everybody move to files, it is the right thing to do. I think that if things go like I plan them, it will be far easier and more powerful to ditch WE and do so.
10-28-2009, 08:57 PM#5
Anitarf
Well, the thing you need to consider is, how many similar spells will you have in a map? Generally, you would want the spells to be diverse, in order for a map to have 5 spells using the same code it would have to be either a really boring map or the code would need to support ultra calibration. I think systems already cover the "generic calibrateable spell objects" niche pretty well, stuff like xe or ABuff.