FFXIAH.com |
||
|
GearSwap Tutorial Pt2
GearSwap Tutorial (v0.1)PART 2There was one fairly big 'situational' bit left out of part 1: exactly what ability or spell are you trying to perform or cast? Cure potency doesn't help you when casting Barfira or Haste or Raise, nor does fast cast help your weaponskill. Well, that parameter that's given to your function, 'spell', contains the info we need. Code function precast(spell) equip(sets.precast) end The 'spell' parameter is itself a table, and it contains lots of details about the spell you're trying to cast. Two values in particular are of interest: spell.name, and spell.english (or spell.french or spell.german or spell.japanese, as the case may be). spell.name is the name of the action being performed, in the language of the system you're using. If you're using an English system, it will be the English name. If you're using a French system, it will be the French name. Etc. spell.english, on the other hand, will always be the English name. If you're only ever using your own lua scripts, you can just use spell.name and ignore the other details. If you're using or sharing your files with other people, you may sometimes want to specify exactly which language you're using, so that the comparison works regardless of what language is being used on the system that's running your script. It's usually easiest to specify the language when checking things on input (eg: use spell.english when looking at the spell and deciding what to do), and use spell.name for any output (ie: notifying the user about whatever you're doing). We'll stick with spell.english for anything else in this tutorial. In addition, the 'spell' parameter contains certain general categories that describe the spell in question. The categories we're immediately interested in are: spell.action_type -- This can be 'Magic' for any sort of magic spell, 'Ability' for any sort of ability or weaponskill, 'Ranged Attack' for ranged attacks, or 'Item' for item use. spell.type -- This is the 'type' of the spell, as defined in Windower's resources. 'Haste' would be type 'WhiteMagic'. 'Fire Shot' would be type 'CorsairShot'. "Hunter's Roll" would be type 'CorsairRoll'. 'Penury' would be type 'Scholar'. "Curing Waltz II" would be type 'Waltz'. Etc. spell.skill -- This is the skill that's used when casting magic spells, such as 'Enhancing Magic', 'Dark Magic', 'Ninjutsu', etc. Also, for weaponskills, it provides the skill the weaponskill is based on ('Hand-to-hand', 'Marksmanship', etc). All other types of abilities don't contain any value for skill. In addition, we need to decide how to tell the program what sort of situation we're specifying. That is, we define the conditions under which certain parts of the program are run, using something called a 'conditional': an if-then statement. Code -- conditional if value_a == condition_b then -- do stuff end It's expressed pretty much as you'd say it: if what I'm checking for is equal to some value, then I want to do something specific. If you want to check for "not equal to", you'd use ~= instead, and if you're comparing numbers you can use standard <, >, <= and >= symbols for less than and greater than type comparisons. So going back to our whm, we want to be more specific about certain things. We want to use our fast cast gloves only for magical spells, not for anything else. We can determine whether we're performing a magic spell from spell.action_type. Therefore: Code function precast(spell) if spell.action_type == 'Magic' then equip(sets.precast) end end We probably also want to name our set a bit better, so that we know exactly what its purpose is. We can call it sets.precast.fastcast, or perhaps shorten it to sets.precast.FC. However in order to add FC to the precast table, we also have to make sure that the sets.precast table exists first. Code function get_sets() sets.precast = {} -- just making sure the table exists sets.precast.FC = {hands="Gendewitha Gages"} sets.midcast = {main="Tamaxchi", hands="Bokwus Gloves"} sets.aftercast = {main="Bolelabunga", sub="Genbu's Shield", hands="Serpentes Cuffs", feet="Herald's Gaiters"} end function precast(spell) if spell.action_type == 'Magic' then equip(sets.precast.FC) end end function midcast(spell) equip(sets.midcast) end function aftercast(spell) equip(sets.aftercast) end We'd also like to do something similar for our midcast set. We only want the Bokwus Gloves to be equipped when we're casting cures. Unfortunately we don't have anything specific enough in the spell variable to tell us that. At best, spell.skill is 'Healing Magic', which also includes -na spells and raises and such. The long way is to list every possible option: Code if spell.name == 'Cure' or spell.name == 'Cure II' or spell.name == 'Cure III' or spell.name == 'Cure IV' or spell.name == 'Cure V' or spell.name == 'Cure VI' or spell.name == 'Curaga' or spell.name == 'Curaga II' or spell.name == 'Curaga III' or spell.name == 'Curaga IV' or spell.name == 'Curaga V' or spell.name == 'Cura' or spell.name == 'Cura II' or spell.name == 'Cura III' then equip(sets.midcast) end However that's a bit messy. Surely there's an easier way? Well, we can look at the spell name itself and realize that the spell names mostly all start with some of the same letters: 'Cure' for all the cures, and 'Cura' for all the cura/curagas. Aside: Some would shorten this to just 'Cur' for all cures and curagas together, but 'Cur' will also match 'Cursna', so we don't want that. To do that we'll use a handy string function called 'startswith' (see part 7, Library Tools). You can apply this to a string to find out if it does, in fact, start with some specified value. Code if spell.english:startswith('Cure') or spell.english:startswith('Cura') then equip(sets.midcast) end Aside: 'applying' a function to an object is a way of saying that that object inherently contains a function that can operate on itself. In this case, all strings have a function called "startswith" that can be used to find out if the string starts with some other string. To apply the function, use the colon (:) character rather than the period (.) character. So the above has: spell - this is a table that contains a bunch of info about the spell being cast spell.english - this a string inside the table that holds the spell's name (in English) spell.english:startswith - this is a function that a string can use spell.english:startswith('Cure') - this checks if the spell's english name starts with the string 'Cure' (ie: Cure, Cure II, Cure III, etc). Also note that this would be a case where spell.english can lead to different results than spell.name. In German, we'd want to check spell.name:startswith('Heilen'). In French, we'd want to check spell.name:startswith('Soin'). By explicitly making the comparison with spell.english, we don't have to worry about the different values spell.name might have. Anyway, much simpler. Now we can also rename our midcast set so that it's clear what it's being used for. Code function get_sets() sets.precast = {} -- just making sure the table exists sets.precast.FC = {hands="Gendewitha Gages"} sets.midcast = {} -- just making sure the table exists sets.midcast.Cure = {main="Tamaxchi", hands="Bokwus Gloves"} sets.aftercast = {main="Bolelabunga", sub="Genbu's Shield", hands="Serpentes Cuffs"} end function precast(spell) if spell.action_type == 'Magic' then equip(sets.precast.FC) end end function midcast(spell) if spell.english:startswith('Cure') or spell.english:startswith('Cura') then equip(sets.midcast.Cure) end end function aftercast(spell) equip(sets.aftercast) end And finally, there are other bits of information available to us aside from the 'spell' parameter, that are always around. Things like 'player' and 'world' that are part of the environment, but not specific to the various event functions, so aren't passed in as parameters. Of particular interest here is that we can find out what the player's status is by simply checking player.status. In the above, we actually only want to equip that aftercast gear set when we're idle. If we were meleeing, we'd want a proper melee set. So we need to check our status and only equip what's appropriate. Code if player.status == 'Idle' then equip(sets.aftercast) end And once again, we can rename our set to be more intuitive. Code function get_sets() sets.precast = {} -- just making sure the table exists sets.precast.FC = {hands="Gendewitha Gages"} sets.midcast = {} sets.midcast.Cure = {main="Tamaxchi", hands="Bokwus Gloves"} sets.idle = {main="Bolelabunga", sub="Genbu's Shield", hands="Serpentes Cuffs", feet="Herald's Gaiters"} end function precast(spell) if spell.action_type == 'Magic' then equip(sets.precast.FC) end end function midcast(spell) if spell.english:startswith('Cure') or spell.english:startswith('Cura') then equip(sets.midcast.Cure) end end function aftercast(spell) if player.status == 'Idle' then equip(sets.idle) end end After that, it's just adding more checks for more specific situations. Navigation Part 1 - Basic Sets and Events Part 2 - Conditionals and Testing Part 3 - More on Conditionals Part 4 - Tables Part 5 - Abstractions Part 6 - Asking the Right Questions Part 7 - Library Tools Author:
Motenten
Date Created: 2014-04-25 17:55:59
Date Last Modified: 2014-05-19 11:08:11
Updates: 6
Bytes: 9989
|
|
All FFXI content and images © 2002-2024 SQUARE ENIX CO., LTD. FINAL
FANTASY is a registered trademark of Square Enix Co., Ltd.
|