Page 1 of 1

HOWTO: Building Spells

Posted: Wed Dec 04, 2013 8:09 pm
by John Adams
I created this forum to for discussions about Spells/Abilities and how best to support them as well as discussion on how to design/share LUA that will be similar across many classes. Ie., lots of spells are simply DamageType + Min/Max. No sense writing that lua 200 times, just use an example script we determine is "common" from here.

I will also be documenting my current spell development "flow" to give you a starting point in which to grow from. This system works for me, since I wrote the editor :roll: so by all means don't listen to a word I say and do whatever you want :P :P :P

First, the initial documentation of how to use the Spells Editor can be found in the wiki HERE.

In the following posts I will go through it a little more detailed, explaining why I am doing what I'm doing.


Current claimed tasks:
JA - Guardian, Assassin
Jabantiz - Paladin, Necromancer, Mystic, Swashbuckler, Monk, Fury, Bruiser, Conjuror, Defiler, Warlock, Ranger, Shadowknight, Inquisitor, Coercer
Zcoretri - Templar, Wizard, Brigand, Troubador
Foof - Dirge, Warden, Illusionist, Berserker

To Do:
Channeler

Beastlord

UPDATED: 3/13/14 Zcoretri

Re: HOWTO: Building Spells

Posted: Wed Dec 04, 2013 9:13 pm
by John Adams
Our current Spell Data is 100% from SOE API data feed, which means it's missing a ton of data. If the spell from SOE has an associating "RAW" data record (from Collects), there is a link on Spells tab to refresh the data, though RAW data may be outdated already... so keep that in mind.


To start, open the editor and click on Spells, and choose Type = All. This will enable 2 other fields for Classification (also set to All) and Player Class. Pick the class of the spells you plan to work on for this session.
  • Note: For now, we should only work on player class spells from level's 1 through 50
Image


Once you get a grid of spells filtered to your liking, pick a spell to work on by clicking it's Spell_ID in the left-most column
WARNING!!!
The FIRST thing you need to do is check the LUA Script field.
WARNING!!!
Image
WARNING!!!
The FIRST thing you need to do is check the LUA Script field.
WARNING!!!
If this says ANYTHING other than "Your/Relative/Path/To/The/Spell" then DO NOT SAVE on the Spells tab until you create the LUA script first!

We'll get back to LUA building shortly.



Click on the Script tab

Image
The Script editor should show the Name of the spell being created "Taunting Blow", and in (parens) should show the relative path to the script (Spells/Fighter/Warrior/Guardian/TauntingBlow.lua). The script engine will build a starting header, and populate the body with the same data from the `spell_display_effects` table for this spell+tier - this is to help you develop the script, seeing what the net Effects are.


A few notes about the buttons along the bottom, as they vary --
Create: This button only shows up when there is NO LUA Script on the drive nor already linked to the spell - it's brand new.
Re-Link: This button only shows up when there IS a LUA Script, but it is not yet linked to the spell itself (in the `lua_script` field).
Rebuild: This button is always present, in case your spell is linked to a very old script and you wish to start over again. NOTE: This PERMANENTLY erases the script from the disk and re-writes it like it was a Create. Use with caution.


Off to the right are some basic templates you can use to insert. Since this is a Melee Damage + Taunt spell, I can click Damage to the right, and get a damage function cast() inserted automatically.

Image
Now all I have to add is the Taunt component and click "Create".

So Step 1 is to create the LUA script (even if empty for now) and link it to the spell - only because previously this was done automatically and with the tons of new data, I didn't have time to fix that.


With the spell Script set,
Click on the Spell tab

Image
Pointing out the few items that need changing here, if you know the proper messaging for Success, Effect and Fades, type it in - otherwise these defaults are used.

The only other 2 pieces of data required on this page is the Spell Visual (the impressive animation effect) and setting the spell to is_active.


Click on Tiers

There are between 1 and 10 tiers for every spell/ability. Their data varies ever-so-slightly from Tier to Tier. You will notice this easily in this step.

Image

First, a word about the 3 Apprentice tiers.
  • Normally, the first Apprentice tier of any ability is given to you by your Class, or leveling up - automatically. All other tiers are Spellscrolls you purchase or create through crafting.
    This is important to understand because there are NO ITEMS for Apprentice Tier 1 spells/abilities in which to parse data from the SOE API Items list (for Resistiblity and range, for instance)
This means, when you SOE the Apprentice tiers, you MUST click Tier 2's SOE button ONLY, and it will update both Tier's 1 and 3 as well. You must then FIX the Tier 1 "given_by" value back to Class manually.

Clicking SOE for all the tiers will fix the Range, Resistiblity, radius, range, power, etc... though at this time they should all be accurate to SOE API data. I do this merely to get Range, since without Range, the spells won't work in-game.

Click SOE all the way down all 9 tiers. You'll know they are done because the float for Recast becomes a whole number. One the Tiers are done, we move on.


Click on Effects

Review the entries for Spell Display Effects data closely, and make a quick determination of how many elements your LUA function will need. Some can be consolidated, if for example a spell will add 1.8% to Slashing, Crushing and Piercing... that is 1 param (1.8%) and you would use the same parameter 3 times. We'll cover LUA later...

Image

The reason you need to take a look at this first is because the next step will be building the data parameters that are going to be send to LUA. You need to know how many parameters you will need. Once you have a game plan --


Click on Data
Data is where you will add all the parameters. From the above example, I know I need 5 parameters... 1 for DamageType (melee). 2 for Min/Max damage. and 2 for Min/Max taunt.

Now, I can waste time picking each data type, index value, and data value and inserting 5 rows manually here --

Image

Or, I can use the Display Effects Parser that, at least for the simpler spells, cuts this work into 1/10th as much data entry.
Here you see the 5 elements I know I need for this spell.
Image
I can simply click Submit on Tier 1, Effect 0,0, and 3 pieces of data will be entered at once.

Now you see, melee (13) of between 3 and 6 are my first 3 params ready to be sent to the LUA script.
Image

I do the same thing for the Taunt values in Tier 1, and Tier 1 is complete. Rinse, Repeat for all the spell tiers on this spell and you have all your data ready to go.
Image



Click on Classes
Just a quick check to ensure the classes required to use this spell are set properly. 99% of the time it will be correct.

IMPORTANT: See this note below


Finally...
Click on the Script tab
Now we're back to the LUA part. You can click Rebuild here if you made any changes to the Spell Display Effects data, so you can build the reference comments to work from.

Since I knew I needed a damage type, min/max for damage and min/max for a taunt, I added 5 params to my function cast() line:
Image
I then build out my script using whatever logic makes sense to me to get the job done. LUA, like any other language, has 10 ways to do the same thing, so pick what works best for you, or work together to create a standard.


Couple notes
  • about what >> I << chose to do... I preserve the notes, and move them to where the component is being evaluated. Only for a reminder to the next guy, that this is why we're doing this.

    I also chose to NOT create a local variable, especially if it's only used once, to do min/max math.randoms(). A SpellDamage(Target, DmgType, math.random(MinVal, MaxVal)) works just as well.

    I also like 4 spaces, not tabs, in my indents. Not 2, not 3, not 16... 4 seems clean.

    I also like leaving a NPC Say in the script when functionality cannot be completed (the Not Implemented template button). This shouts out that something isn't implemented, so we get reminded to add the feature.

    I also recommend leaving the spell to is_active = false unless at least 50% of it's functionality can be completed - and consider the functional part actually useful... ie., if it grants you Moon Jump after completely healing all players in the zone, and the heal part doesn't work, then perhaps that one can remain inactive.

    Anything that cannot be done should be brought up to the C++/LUA developers to see if they have time to whip up the feature you need to finish your spell. A "sudden resurrection on death" effect would really surprise a player if they died and, well, stayed dead.

Any questions before you get started? If not, dive in. But please announce what Class you plan to work on, and how far you plan to take it.

Re: HOWTO: Building Spells

Posted: Wed Dec 04, 2013 10:10 pm
by John Adams
The short version of the above post:

1. Click Spells, Type = All, Classification = All, Class = {your assignment}
2. Click the spell_id
3. Click Script and Create/Relink the LUA
4. Click Spell, validate data, set a Spell Visual, Save
5. Click Tiers, update all tiers with SOE data, fix tier 1 "given_by" (so we can find it later)
6. Click Data and Parse the display effects properly, making note of the number of params you need for LUA
7. Verify Classes is right class
8. Build script
9. Back on Spells, set is_active = true, reload your world/spells, and test.

Re: HOWTO: Building Spells

Posted: Fri Dec 06, 2013 7:40 am
by John Adams
Couple more tips I thought of as I was trying to fall asleep last night :mrgreen:


Archetype/Class Data
While in the normal world, all 6 Fighter classes used to have "Taunt" (plain, simple Taunt). But Spells have undergone so many revamps in 5 years, I have no idea if Archetype (Fighter/Priest/Mage/Scout) abilities are inherited down anymore. The only one I know FOR SURE with Fighters seems to be Fighting Chance (HO starter). So this is why I am suggesting we skip configuring those, even though SOE Data has tons of spells in these ranges... I'll start a post to discuss them separately - HERE.


Visuals:
The Lookup Visual will pop a new dialog which has the option of selecting category and type, or a Lookup box to type text into and click Search. One thing I noticed after processing reference_spell_effects for the ToV client, there is a category called "spell_revamp" that seems to have a LOT of stuff in it, that wasn't there before. I would suggest looking here for effects first for your classes, then broadening your search if you still haven't found what you're looking for.

Also remember, you can preview animations in-game by typing /useability {1 - 3720}, where the ID is the id in the Lookup Visual table.


Tier Classifications:
Mentioned before, but this deserves a reminder: Tier's "given_by" value MUST remain accurate - not for the game server, but for the editor. If accidentally re-classify a "Class" spell as a "Spellscroll", the editor will not be able to find it again easily. The spell should always show up in it's class list, or in the Lookup for sure... but to use filtering properly, classify your tiers.

Example I used before, if you use "SOE" button to sync Tier 1, it will overwrite `given_by` = "class" with "spellscroll". Any spell given at class level up (tier 1) should be classified as "class".

How I have been doing my tiers is, I sync tiers 1, 2 and 3 using the Tier 2's SOE button... then manually flip Tier 1 back to "class" and Update. Tedious, and if you have a better way to manage this, I'm open to suggestions.


Tier Call Frequency (tick):
Spells with Ticks (DoTs, recurring effects) need their `call_frequency` value set (in 10ths of a second). Something that fires off every 3 seconds needs a "30" in call_frequency. This has to be set manually, as there is no live data to define tick duration.

See below about the Data Parser warning... the display effects will usually show the tick duration, but we don't want to pass that into the LUA script as a param.


Re-Indexing:
I forgot to cover this very important feature, if you discover a spell for your class off in the unknown range (2,000,000+) you can move it to your class by using the Re-Index button. You would pick a pre-defined range (arts, spells, pcinnates etc) or more than likely, a class. The script will go find the next available spell ID in that classes range, and you move all data related this way.


Unknowns:
If I didn't cover it elsewhere, anything I could not identify as a Art/Spell (class), a PC Innate, Ability or Tradeskill, ended up in the "Unknowns", starting at ID 2mil. Lots of stuff here, so if you are missing something, do a Lookup search for the name... it might be there.


Traits:
While we're not working on anything other than class spells at this moment, Zcoretri and I will be having a discussion about how to manage these. I believe most PC Innates are in the 1,000,000 range, as there wound up being a lot of them after all (2,988 in fact). These spells will expose a "Traits" tab in the editor, where we will need to build the `spell_traits` data manually, until I understand the data better then maybe I can bulk insert them.

Previously, our `spell_traits` were 1 tier... but SOE data seems to be demonstrating mutliple tiers for these as well. Not sure if that's valid, or they are incorrectly classified. They can be re-indexed, if they end up being wrong.


AA's
We're not doing these yet either, but if you pick an AA to look at, you will see the "AA" tab appear. It is read-only, directly from SOE API data, some data I need Zcoretri to look at and tell me how (or if) it fits into our world data.


Spell Data Parser - WARNING!
Something that came to mind was, you cannot just blindly "Submit" every parsed row in the Data Parser... because the parser is not smart enough to recognize a value from a Timer.

Example, Inflicts 6 - 8 melee damage every 3 seconds.

Data Parser will parse Melee, 6, and 8, and the 3. But the 3 is not part of the LUA data, it is the `call_frequency` for the tier, which must be set manually (no Tick data is provided by SOE).

This is why the Display Effect Text is highlighted in RED above the parsed data, so you can determine what needs to be inserted and what should be skipped.

More to come as I remember ;)

Re: HOWTO: Building Spells

Posted: Sat Dec 07, 2013 10:10 am
by John Adams
Here's a visual example of the Data Parser warning mentioned above. Note this tier's display effects:

Image

First thing to notice, which I was talking about on IRC last night, is the Decreases Piercing of target by 1.5. You'll notice in Effect 0,3, it's additionally a decrease of 1.5 also for Slashing and Crushing. I have no idea why they are separate, but we only need to send ONE value (1.5) to the LUA script, and then AddSkillBonus() 3 times for Piercing, Crushing and Slashing.

Second, and probably more importantly, notice Effect 0,2, which says Inflicts 10 - 12 slashing damage on target every 5 seconds. My parser has no idea that 5 is not part of the parameters... when it really is the call_frequency back on the Tier tab.


In fact, you also do not need to pass the Piercing in the example that is decreased, nor the Crushing (set those back to No Effect to not submit them) because you already know you need those skill adjustments in the script.

So, before you Submit this row, you must blank out the "5" (or whatever value it is)
or you will end up with too many parameters in your LUA that you do not need.

So the proper parsing of this display effect looks like this:

Image
Submit Effect 0,0
Set No Effect on Effect 0, 1 and submit the -1.5
Set the "5 seconds" to blank (cannot be zero) in Effect 0,2 and submit the DoT
Completely ignore Effect 0,3 as it is not needed as params

Refresh your Data tab, and it should look like this:

Image
Slashing 23 - 39
Decrease -1.5
DoT slashing for 10-12 - and set call_frequency = 50 (in Tiers)

Clear as mud?


I will attempt to beef up the Parsing logic to automatically push the 'n' seconds to the tier eventually.

Re: HOWTO: Building Spells

Posted: Sun Dec 22, 2013 1:20 pm
by John Adams
Couple things as I have been reviewing editor functionality and the current work thusfar.

I made a really big deal about this -

Image

So please be sure your script names are set right. There have been a few I've had to fix, but considering the amount of effort being made, the ratio of bad script names is within tolerance levels ;) Just double check your work, please.


Also something I completely forgot to mention, if the same spell can be used by multiple classes in the same hierarchy, it would save some data loading/memory if we modified the spell_classes accordingly.

Ie., for a Priest spell "Revive", for all priest types, instead of having 7 entries in spell_classes, removing all but 1 and giving it the "Priest" class will still load that spell for all 7 classes.


Before:

Image

After:

Image


Note: You don't have to do this, spells will still work fine. It's just unnecessary data.