# lib_spl function library

Dependencies: alter_effect, ds, lib_2da, lib_2daq, lib_anon, lib_array, lib_class, lib_cre, lib_data, lib_eff, lib_fn, lib_ids, lib_ietool, lib_ini, lib_kit, lib_script, lib_sfo, lib_splconv, lib_ssl, lib_struct, lib_sugar, lib_tools, lib_ui, lib_vtable, resolve_spell, ui_add_subraces, ui_bonus_spells, ui_deolvynize, ui_detect_class_kit, ui_dual_class_kits, ui_externalize_hlas, ui_externalize_proficiencies, ui_extra_spells, ui_on_open, ui_shared_code, ui_spell_system, ui_system_call, ui_virtual_class

## Description

Functions specifically aimed at editing .spl files.

## Public functions

spl_cd_scroll_name(spell_resref:s)=(scroll_resref:s) dimorphic

Given a (wizard or priest) spell resref, assign it Cam's standard scroll name, i.e. CDIDxyz for SPPRxyz, CDIAxyz for SPWIxyz

spl_copy(tv:b, allow_missing:b, debug:b=1, is_ids:b="-1", standard_icons:b=1, create_scroll:b=1, overwrite:b, overwrite_on_mismatch:b, force_extended:b, spl:s, path:s, location:s, locbase:s, source_path:s, source_location:s, source_locbase:s, icon_base_name:s, icon_path:s, icon_location:s, icon_locbase:s, edits:f, type:s)=(value:s, scroll:s, spell_resref:s, scroll_resref:s) action

General copier for spl files.

'spl' is a list of k=>v pairs. Each spell k.spl is copied to v.spl. source_path/source_location/source_locbase and path/location/locbase respectively define the locations of k.spl and v.spl, with an empty path interpreted as the override in both cases. (If k is missing, we whine unless allow_missing=1.) The function 'edits' is applied to each file during copy. You can use the anonymous function construct; if you do, the spl will be read into the struct 'm' beforehand and written back afterward.

Alternately, spl can be a list of strings k..., in which case k.spl is copied to k.spl as above.

If the dest file is an ids entry (determined heuristically unless is_ids is set) then we add it to spell.ids, use it as a resref, add icons in the standard format (unless standard_icons=0) and (unless create_scroll=0) build a scroll. In this case, we use icon_path, icon_location, icon_locbase (if set) to determine where the spell icons are, and copy them over if they're in the format [ABC].bam. (If icon_base_name is unset, we use the ids name.)

By default, if the dest file is an IDS entry we put the spell in the SPWI, SPPR or SPIN namespace based on the type in the copied spell. You can override this by setting 'type' to 'wizard','priest','innate' or 'class'. (But this only determines where the spell ends up; it doesn't change its internal type.

If tv=1, we prepend "_" onto each k and v on BGTUTU installs.

If debug=1, we try to debug the anonymous function to detect any nonexistent field writes.

If overwrite=1, we install the spell if it's already present, overwriting any previous copy (or giving that previous copy a new placeholder IDS if it's at the wrong level/of the wrong type). If overwrite=0 and overwrite_on_mismatch=1, we overwrite only if there's a level or type mismatch. If overwrite=0 and overwrite_on_mismatch=0, we never overwrite.

Returns the resref of the last spell created (value; synonym:spell_resref), and its scroll (scroll; synonym:scroll_resref) if any. (Only really useful if you're copying to an ids, and only if you're only doing it once.)

spl_deabbreviate(spell:s)=(resref:s, type:s, level:s) dimorphic

Take either a spell resref, or a spell ids name, or an abbreviated spell ids name (without the WIZARD_/CLERIC_ prefix). Return the spell resref, the level, and the type (innate/priest/wizard)

spl_edit(tv:i, allow_missing:b, debug:b=1, edit_strrefs_in_place:b, spl:s, path:s, location:s, locbase:s, edits:s)=() action

General editor for spl files. spl is a list of resrefs, each with location defined by path/location/locbase, or in override/a game file if all are blank. Each is copied, and edits is applied as a patch function. You can use the anonymous function construct; if you do, the spl will be read into the struct 'm' beforehand and written back afterward.

If tv=1, we prepend "_" onto each k and v on BGTUTU installs.

If debug=1, we try to debug the anonymous function to detect any nonexistent field writes.

spl_enforce_school(preloaded:b, sounds_colors:b=1, struct:s, arguments:s)=(struct:a) dimorphic

Forces a spell to fit the rules for the specified school, or the current school if none is specified, adjusting casting colors, casting sounds, and for wizard spells, barred schools. Barred schools are read in from data_loc_shared/mageschools.tpa, or use the BG2/IWD defaults if it doesn't exist.

If preloaded=1, assume that the array 'unusable_array' already contains the unusuable spell types (good for batch application). If sounds_colors=0, don't do the sounds and colors.

Note that this also works on items (i.e., scrolls), though the sounds/colors bit is skipped.

spl_generate_smtable(2da:s, contents:s, hit_animation:s, area_hit_animation:s)=() action

Streamlined generator for smtable 2das - assumes animations are constant (as is true in all vanilla entries)

spl_hide_spells(scrolls_only:i, spells:s, spell_array:s)=() action

Given a list of spells (as IDS), removes those spells entirely from the game: the spells themselves hidden in HIDESPL; all copies of the scrolls are removed from stores, creatures, areas and 2da rndtres/rndscrol; the scroll itself is replaced by a minor gem. The actual spells are still present.

You can also specify the spells as a k=>blank array. If you set the INT_VAR scrolls_only to 1, the scrolls are removed but the spells are still available to select at chargen and at sorcerer/shaman levelup, and are still given to priests.

spl_make(debug:b=1, is_ids:b="-1", standard_icons:b=1, create_scroll:b=1, force_extended:b, overwrite:b, overwrite_on_mismatch:b, spl:s, edits:f, location:s, locbase:s, path:s, icon_location:s, icon_locbase:s, icon_path:s, icon_base_name:s)=(value:s, scroll:s, spell_resref:s, scroll_resref:s) dimorphic

General maker for spl files.

We create a new spell 'spl'.spl, location specified by path/location/locbase, or 'override' if all are blank. The function 'edits' is applied to the file after creation. You can use the anonymous function construct; if you do, the spl will be read into the struct 'm' beforehand and written back afterward.

If spl is an ids entry (determined heuristically unless is_ids is set) then we add it to spell.ids, use it as a resref, add icons in the standard format (unless standard_icons=1) and (unless create_scroll=0) build a scroll.

If debug=1, we try to debug the anonymous function to detect any nonexistent field writes.

If force_extended=1, we add the spell to the extended namespace even if there's space in standard namespace.

If overwrite=1, we install the spell if it's already present, overwriting any previous copy (or giving that previous copy a new placeholder IDS if it's at the wrong level/of the wrong type). If overwrite=0 and overwrite_on_mismatch=1, we overwrite only if there's a level or type mismatch. If overwrite=0 and overwrite_on_mismatch=0, we never overwrite.

Returns the resref of the spell, and its scroll if any.

spl_make_all_scrolls(name_function:s="spl_cd_scroll_name", price_table:s="MOD_FOLDER/sfo/data/scroll_prices.2da")=() action

Construct a scroll for any SPPR/SPWI spell that doesn't have one and should (i.e. exclude spells unavailable to the player, as well as the Wild Mage spells)

spl_make_aura(spell:s, payload:s, effect:s)=() action

Make an aura power. 'spell', when applied, permanently causes the caster to cast 'payload' 1/sec. The intermediate effect has its name autogenerated unless set explicitly.

spl_make_hla_class_ability(force_innate:b=1, resref:s, id:s)=(new_resref:s) action

Copy a spell (assumed to be a wizard/priest spell, though we don't enforce this) to the SPCL namespace. and optionally make it innate. (Set force_innate=0 if you don't want to.) You need to specify the resref. Optionally you can specify the id; if not we'll infer it or make it up. Strip it from any clone (i.e., in simulacr/projimag) in the process. The new spell will have id HLA_[old_id]

Because we expect to use this in bulk applications, it adds new IDS entries unsorted. (Sort at the end using ids_sort.)

spl_make_innate_repeating_spell(new_is_ids:i=1, cooldown:i, overwrite:i, allow_missing:i, patch_description:i=1, override_description:i, delete_casting:i, desc_strref_cd:i=100404, the, string, to, be, appended, to, the, description,, with, 99999, replaced, by, the, actual, repeat, time., Default, value, is, from, SCS, shared.tra, desc_strref_atwill:i=100405, this, string, says, 'use, at, will', and, gets, appended, instead, if, cooldown:i, arguments:s)=() action

Make a spell (from a template) that you get back after a certain period

spl_make_scroll(price:i="-1", spell_resref:s, scroll_resref:s, icon:s="%spell_resref%A", name_function:s="spl_cd_scroll_name", price_table:s="MOD_FOLDER/sfo/data/scroll_prices.2da")=(scroll_resref:s) dimorphic

Given a (wizard or priest) spell, generate a scroll for that spell, using CamDawg's naming conventions by default

spl_make_summoning_2da(filename:s, monsters:s, anim_hit:s="msumm1h", anim_area:s="msumm1x")=() action

Given a list of monsters, a filename of a 2da (omitting '2da'), and an optional choice of anim_hit and anim_area animations (defaulting to 'msumm1h' and 'msumm1x'), make a standard-format summoning 2da

spl_remap_level_9_wizard_spells()=() action

Move the spells in the SPWI926-SPWI949 range into the SPWI0xyz range.

spl_resolve_ids(level:i, force_extended:b, replace_on_mismatch:b, ids_sort:i=1, ids:s, type:[wizard|priest|innate|class|1|2|3|4|5])=(resref:s, mismatch:s, already_present:s, lua_line_needed:s) dimorphic

Given an ids entry (WIZARD_THIS_SPELL, etc) find its id resref (or dw_ext_spell resref), if necessary adding it to spell.ids. Need to supply the spell type and the level.

On EE, if full, or if force_extended=1, add it to the extended namespace instead.

If it's already present, return already_present=1. Check if its level and type match the requested level and type. If not, return 'mismatch=1' (otherwise, return 0). If 'replace_on_mismatch' is set to 1, instead replace the old id with a placeholder and add the new id in the correct place (and return mismatch=0, already_present=0).

By default the ids file is resorted, so that the new entry appears in the right place. Skip this by setting ids_sort=0. (This is sensible for bulk additions, where you'll want to sort once at the end.)

spl_resolve_smtables_entry(name:s, 2da:s)=(value:s) action

Return the number corresponding to a given named smtable.2da entry (we search for [0-9]+_name), adding it if necessary (for the latter, need to supply a 2da name too.)

spl_resref_to_type_level(resref:s)=(type:s, level:s) dimorphic

Take a spell resref of a spell in spell.ids. Return its type (priest/innate/class/wizard) and level (assuming it fits standard conventions, and using 1 for innate and class).

## Internal functions

These should not be called from outside the library itself.

spl_check_resolve_mismatch(level:i, type:s, resref:s)=(mismatch:s) action

spl_free_ids_slot_for_l9_remap(start_slot:i=2050)=(value:s, ids:s) patch