[Tool] UI-based Spell Learning for Sorcerers/Shamans
kjeron
Member Posts: 2,368
This function is designed to implement a UI-based Spell selection system, as an alternative to dialog-based Spell Selection, utilizing the Sequencer/Contingency spell selection menu to learn arcane or divine spells. Innate abilities "can" be learned this way as well, but cannot currently be tracked, and thus not supported.
I have kept the changes it makes to UI.MENU to an absolute minimum, to reduce the chances of incompatibility, but any UI mod that outright replaces UI.MENU will obviously not be compatible.
The function requires a 7-character filename and creates the following files:
The function call is as such:
Screenshots:
Not implemented, but possible:
I have tested the function to work for the current patch cycle (v2.5.17.0, 2.5.16.6). However, this bug is still preset in IWDEE, limiting its viability.
I have kept the changes it makes to UI.MENU to an absolute minimum, to reduce the chances of incompatibility, but any UI mod that outright replaces UI.MENU will obviously not be compatible.
The function requires a 7-character filename and creates the following files:
- '%filename%.SPL' - Usable at-will innate ability to access spell menu.
- '%filename%D.SPL' - Sequencer activation subspell, activated automatically.
- '%filename%X.EFF' - Sequencer creation EFF
- '%filename%X.2DA' - Primary spell list, identical in form to the spell lists for Opcode 214 (Select Spell). If specified, the function will automatically populate the list with appropriate "default" spells (SPPR/SPWI), based on HIDESPL.2DA and the specified exclusion flag. Spells may be manually appended to the list as desired, and spell level is automatically detected and filtered by the UI. Spells omitted or removed from this list will not count towards the characters number of spells known (such as the Shaman's bonus spells).
The function call is as such:
INCLUDE ~%filepath%/SEQUENCER_MENU.TPA~ LAF CREATE_SEQUENCER_MENU INT_VAR tip = stringRef // String Reference from dialog.tlk, this is the Instructions displayed in the Sequencer Screen name = stringRef // String Reference from dialog.tlk, this is the name of the ability used to open the Sequencer Menu desc = stringRef // String Reference from dialog.tlk, this is the description for the ability used to open the Sequencer Menu class = value // 1 for arcane, else divine, doesn't matter if using custom spell lists. maxlevel = value // If non-zero, only spells up to this level will be automatically added to the primary spell list. // If zero, no spells will be added (to add them manually or use custom mutlilists). // If omitted, default maximum is used (9 for arcane, 7 for divine). exclude = value // If any exclusion flags at offset 0x1e of a spell match this value, it will be excluded from the primary spell list. multilist = value // If non-zero, function assumes that primary spell list is instead a list of other 2da files each with their own spell lists, all of which will be made available. // Intended for School/Sphere systems, so that each school/sphere can have it's own list, while kits would just have a list of those lists as appropriate. // Such sub-lists 'must' have an accompanying spell of the same name. // If "Sphere1.2da" is a list of spells, "Sphere1.spl" must exist as a spell file, though it's contents are irrelevant. column = value // for use with custom spelllists, column of file to use. alignment = value // If non-zero, function enforces that spell selection should respect alignment restrictions (currently only if they are provided by an external source - it cannot read them through the UI). global = value // If non-zero, function will read known spells in LOCALS and GLOBAL variables. Activating ability will take up to 1 second before menu pops up while variables are checked/set. // If 1, Subspells to learn spells will need to be setup manually, since this mode is only intended for spells that cannot be "known" in the normal manner. // If 2, subspells are still created as normal. // If the spells LOCALS variable is set to 1, it will be considered "known" and count towards the known spell limit. // If the spells LOCALS variable is set to 2, it will be considered "known" but not count towards the known spell limit. // The LOCALS/GLOBAL variable for each spell is it's RESREF. STR_VAR resref = ~filename~ // 7-character or less filename for Spell Selection ability icon = ~filename~ // Icon for Spell Selection ability spelltable = ~filename~ // 2DA table (no extension) for Known Spells, defaults to SPLSRCKN(.2DA) or SPLSHMKN(.2DA) if not specified. // If used, SPLSRCKN.2DA and/or SPLSHMKN.2DA will be cloned as SPLSRCKN_BACKUP.2DA and SPLSHMKN_BACKUP.2DA for future referencing, // while the main files are zeroed out so that normal spell selection is disabled. // The specified 2DA File must exist in game. spelllist = ~filename~ // 2da file (no extension) with custom spell list, only spells in this file will be added, still subject to maxlevel. // First column can contain either IDS label or RESREF of a spell // Other columns contain either '1' (yes) or '0' (no). // The specified 2DA File must exist in game. title = ~string~ // String to display in main "Title" slot of Sequencer Screen, added to appropriate "L_%EE_LANGUAGE%.LUA" file. label = ~string~ // String to display in sub "Title" slot of Sequencer Screen, added to appropriate "L_%EE_LANGUAGE%.LUA" file. attribute = ~value/string~ // 1, STR, STRENGTH, 2, DEX, DEXTERITY, 3, CON, CONSTITUTION, 4, INT, INTELLIGENCE, 5, WIS, WISDOM, 6, CHA, CHR, CHARISMA // Is not case sensitive. Omit if not needed. attrtable = ~filename~ // 2DA table (no extension) with bonus/penalty to Known spells based on specified attribute. // Format is identical to the priests bonus wisdom spell table, MXSPLWIS.2DA. // Table can contain postive and negative values. A sufficiently large penalty can be used to prevent selecting spells at the specified attribute score. // The specified 2DA File must exist in game. // Omit if not needed. subspell = ~character~ // Default = ~L~ // Subspells for each learnable spell will be created, appended with this character (SPPR101.SPL -> SPPR101L.SPL) // Must be a single character, must not already be in use by spells (A,B,C,D,F,P are not permitted) blacklist = ~array name~ // Array ~%blacklist%~ will be scanned over for IDS spell labels as well as spell resrefs. // All valid spells listed will be ommitted from the auto-generated spell lists. // No function when using pre-built spell lists. custom = ~lua function string~ // If this variable is set, only the core function is installed, and the sequencer "resref" is set to call the function defined in this variable. // No files are created related to "resref". // This is only meant to open access to the sequencer/contingency spell lists to other ideas. ENDThe following will mimic the default sorcerer/shaman spell options (provided proper tra references):
OUTER_SPRINT title @293 OUTER_SPRINT action @294 LAF CREATE_SEQUENCER_MENU INT_VAR class = 2 maxlevel = 7 exclude = 0x80000000 tip = RESOLVE_STR_REF (@295) name = RESOLVE_STR_REF (@293) desc = RESOLVE_STR_REF (@293) STR_VAR resref = ~SPLSHMK~ icon = ~SPPR316B~ title action END OUTER_SPRINT title @290 OUTER_SPRINT action @291 LAF CREATE_SEQUENCER_MENU INT_VAR class = 1 maxlevel = 9 exclude = 0x00004000 tip = RESOLVE_STR_REF (@292) name = RESOLVE_STR_REF (@290) desc = RESOLVE_STR_REF (@290) STR_VAR resref = ~SPLSRCK~ icon = ~SPPR316B~ title action ENDThe following is optional code to flag a spell that is on the list of available choices has been given for "free", not counting against their known limit. Apply (w/ Timing Mode 9) the EFF file to the creature when the spell is gained, to prevent it from counting against their spell limit. "SPELL_RES" should be the resref of this "bonus" spell. "%resref%" should be the same string that was passed to the CREATE_SEQUENCER_MENU function. Note that using this will result in the character having a permanent "Spell Sequencer Active" portrait icon.
APPEND ~BGEE.LUA~ ~mageBookStrings['%resref%'].title = mageBookStrings['%resref%X'].title~ CREATE EFF ~(anything)~ WRITE_LONG 0x10 256 WRITE_LONG 0x2c 100 WRITE_ASCII 0x30 ~SPELL_RES~ WRITE_LONG 0x60 1 WRITE_ASCIIE 0x94 ~%resref%~
Screenshots:
Not implemented, but possible:
- Multiclass spell learning. Currently it only reads the first-class Level, the others are accessible, but more complicated to convert to an integer.
I have tested the function to work for the current patch cycle (v2.5.17.0, 2.5.16.6). However, this bug is still preset in IWDEE, limiting its viability.
Post edited by kjeron on
7
Comments
OH. MY GOD. This is what I've needed since forever. Thank you so much!
- Clone all spells in the manner desired. (Wizard -> Priest or Priest -> Wizard)
- Replace the labels in the table with the cloned resrefs. (SET_2DA_ENTRY or REPLACE_TEXTUALLY)
- Run the function on the table for each kit, specifying their column.
Reworked some code, but using the new version should not be mandatory unless you want the attribute options. The old and new should be able to function side-by-side in different mods for now.
@Artemius_I Integration into your shadow magic mod looks quite clean, very nice : .
What about using the hla selection screen? In the back of my head, I've been thinking about repurposing that for custom spell selection for a while. Would that be feasible?
- Resources are pulled from an internal index, so you can't just specify whatever you want on the fly, as the sequencer/contingency screen allows.
- Each class/kit has a hard limit of 256 HLA resources, which populate that index.
- HLA's cannot be chosen at CHARGEN, only LEVELUP.
It is certainly be an option for total conversions (3E/4E/5E/other), where these issues can be worked around, but not much else.
The only methods that I know work involve a permanent 'Spell Sequencer Active' Portrait Icon (Stored Sequencers can be read through the UI).
I not sure how you intend to apply damage to the creature though.
Each sphere would need an unused filename, and all spells it allows would be added to that 2da file.
Each kit (and base class) would need an unused filename, and all spheres available to them would have their filename added to that 2da file. (This 2da would be passed to the function.)
edit - try specifying "maxlevel = 9" in the function call, I think it's defaulting to priest level range(1-7) for custom lists.
I'm working on fixing both.
This will be the subspells it creates to grant the spell.
Not sure how much of the mod was still WIP, but the priest spells did not show up through the item-ability, as the wizard spells did.