Jump to content

guyudennis

Members
  • Posts

    82
  • Joined

  • Last visited

About guyudennis

  • Birthday 02/05/1981

Profile Information

  • Gender
    Male

Recent Profile Visitors

1,371 profile views

guyudennis's Achievements

  1. I first observed this when switching mages to sorcerers, that the mage’s known spells are treated as the sorcerer’s known spells, so the sorcerer would end up with more spells that he/she should legally have. A more severe case happened to me recently when I tried switching Faldorn to a shaman (I was at level 6-7ish), that she ran out of spells to choose during the leveling process after the class change, and the UI hang there with no way to go out. I had modded my game so druids have a slightly lower number of spells available, which could be a contributing factor, but on the other hand I also had IWD spells and SCS new spells installed, which should more than even out my tweak to the Druid spell availability. So it looks like a bug that can trigger for edge cases. Maybe for sorcerers and shamans an additional background action can be performed to first clear the known spells before leveling up?
  2. Or recommend (in the documentation) that the bug fixes component in its entirety should best be installed as early as possible? That’s how I install it always.
  3. Wouldn't an ini file moot the problem of ACTION_READLN? I somehow always thought of ini files as a hard perquisite for batch-mode... for what's its worth, my own private mod is structured in such a way that in the tp2 only the top-level installation choices are present (ie. "Druid Revisions"), then all the class features are individually turned on/off or chosen (when more than one choices are presented) through a settings.ini file. In this sense the ini file becomes mandatory rather than optional or "only for advanced users".
  4. Here is yet another "spell-2-innate" type of function, which is based on Subtledoctor's original function, while the op146/148 target matching portion is based on Luke's MAKE_SPELL-LIKE_ABILITY. The function would make a "wrapper spell" that would in turn launch a "payload spell", regardless if it's uninterruptible or not. For the wrapper spell, one can further define spell type, spell location, spell name, and spell description. Otherwise, it would retain the payload spell's most information intact (sectype would be changed to none and casting speed to zero in case of innate type), have only one ability header without any projectile, and have only one extended effect to launch the payload spell (via 146/148 depending on the payload spell's targeting). There is an additional boolean variable to enable Subtledoctor's original fix to op148's targeting. I could not reproduce the intended issue in game myself, so I made it default to no-fix. Sample usage: Thanks go to @subtledoctor and @jmerry for their patience and help.
  5. Final check before I post it in the other thread? @subtledoctor @jmerry ///////////////////////////////////////////////////////////////////////////////////////////////////// // Borrowed and adapted from 5E Spellcasting: create wrapper spell from any existing payload spell // ///////////////////////////////////////////////////////////////////////////////////////////////////// DEFINE_ACTION_FUNCTION PAYLOAD_SPELL_TO_WRAPPER_SPELL INT_VAR wrapper_type = 4 // default to innate (0 - special, 1 - wizard, 2 - priest, 3 - psionic, 4 - innate, 5 - bard song) wrapper_location = 4 // default to ability (0 - none, 1 - weapon, 2 - spell, 3 - item, 4 - ability) STR_VAR payload_spell = ~~ // default to empty wrapper_spell = ~~ // default to empty wrapper_name = ~~ // default to empty (payload spell name) wrapper_desc = ~~ // default to empty (payload spell description) RET debug_msg BEGIN COPY_EXISTING ~%payload_spell%.spl~ ~override/%wrapper_spell%.spl~ READ_STRREF NAME1 payload_name PATCH_IF (STRING_LENGTH ~%wrapper_name%~ > 0) BEGIN SAY NAME1 ~%wrapper_name%~ // set spell name END READ_STRREF NAME1 wrapper_name PATCH_IF (STRING_LENGTH ~%wrapper_desc%~ > 0) BEGIN SAY UNIDENTIFIED_DESC ~%wrapper_desc%~ // set spell description END WRITE_SHORT 0x1c wrapper_type // set spell type PATCH_IF wrapper_type = 4 BEGIN WRITE_BYTE 0x27 0 // no sectype for innates END LPF ALTER_SPELL_HEADER INT_VAR location = wrapper_location END // set ability location READ_LONG 0x64 abil_offset READ_SHORT 0x68 abil_number READ_BYTE (%abil_offset% + 0x0c) abil_target READ_SHORT (%abil_offset% + 0x0e) abil_range WHILE (%abil_number% > 1) BEGIN SET abil_number = (%abil_number% - 1) READ_SHORT (%abil_offset% + 0x10 + (0x28 * %abil_number%)) abil_minlv LPF DELETE_SPELL_HEADER INT_VAR header_type = "-1" min_level = abil_minlv END // delete all but the 1st ability headers END WRITE_SHORT (%abil_offset% + 0x26) 1 // set projectile to none LPF DELETE_EFFECT END // delete all existing spell extended effects PATCH_IF (%abil_target% = 4) BEGIN // if ability target is any point within range LPF ADD_SPELL_EFFECT INT_VAR opcode = 148 target = 1 parameter2 = 1 timing = 1 STR_VAR resource = EVAL ~%payload_spell%~ END // cast spell at point: payload spell PATCH_IF (%abil_range% < 35) BEGIN PATCH_IF (%abil_range% > 4) BEGIN LPF ALTER_SPELL_HEADER INT_VAR range = (%abil_range% - 3) END // workaround to engine wierdness END PATCH_IF (%abil_range% < 5) BEGIN LPF ALTER_SPELL_HEADER INT_VAR target = 5 END // set ability target to self; might need to carve out exceptions, e.g. burning hands END END END ELSE BEGIN LPF ADD_SPELL_EFFECT INT_VAR opcode = 146 target = 2 parameter2 = 1 timing = 1 STR_VAR resource = EVAL ~%payload_spell%~ END // caste spell at creature: payload spell END BUT_ONLY OUTER_TEXT_SPRINT debug_msg ~Wrapper spell %wrapper_spell% (%wrapper_name%) of type %wrapper_type% created at location %wrapper_location% to launch payload spell %payload_spell% (%payload_name%).~ END The function would make a "wrapper spell" that would in turn launch a "payload spell". For the wrapper spell, one can further define spell type, spell location, spell name, and spell description. Otherwise, it would retain the payload spell's most information intact (sectype would be changed to none in case of innate type), have only one ability header without any projectile, and have only one extended effect to launch the payload spell (via 146/148 depending on the payload spell's targeting). I toyed around the idea of also giving the option to change wrapper spell flags and exclusion flags, but could not get my head around how the default value would be set, since both none and all could be potentially what one wants to set exactly. Distinguishing BAND or BOR is another complication. I hope I finally got the targeting of 146 and 148 correct respectively... please help me double check. Sample usage: ACTION_FOR_EACH filename IN ~sppr731~ ~sppr732~ BEGIN // payload spells: fire elemental transformation, earth elemental transformation LAF PAYLOAD_SPELL_TO_WRAPPER_SPELL INT_VAR wrapper_type = 4 wrapper_location = 4 STR_VAR payload_spell = EVAL ~%filename%~ wrapper_spell = EVAL ~%filename%w~ wrapper_name = EVAL ~%filename% wrapper~ wrapper_desc = EVAL ~%filename% blah blah blah~ RET debug_msg END PRINT ~%debug_msg%~ END
  6. Thanks. But here I think you meant to say 146 instead of 148 (which according to IESDP should just have target = 1) ? Other than that, two more observations/questions regarding @subtledoctor's example code: The LPF DELETE_EFFECT INT_VAR match_probability2 = 0 END bit does not clean out all existing spell effects as intended, as there's spells (ie conjure XXX elemental) whose spell effects have non-zero probability2 settings. (Probably a reading of effect# offset coupled with a loop to delete them all would be a more robust solution?) In case the payload spell has multiple ability headers for different levels, should the wrapper spell inherit all these headers (with each header just a 146/148)? I guess it doesn't really matter in practice, but in principle we only need one ability header for the wrapper spell, right?
  7. Coming back to this as I finally got around to implement this; one question regarding your example code: for op146, why do you use target = 2 (instead of 1) and timing = 9 (instead of 1)? If I look at IESDP spell file format, it says the target does not matter here because it's cast as a subspell. The timing bit I guess comes down to my lack of understanding of the differences between 1 and 9...
  8. Thanks. And yes, REPLACE_TEXTUALLY is a proper bitch. Using your quoted code as an example, if your @10001 = ~I am a master of WeiDU~ it will execute fine, but if your @10001 = ~I am a master (+++) of WeiDU~ it will do nothing, NOTHING!
  9. Maybe you're right...that it's not worth the extra effort to further complicate things, and there's more than one way to judge if a piece of code is clean. Thanks for the discussion.
  10. Thanks for the quick reply. I'm tweaking druid class, and have a bunch of ini options to enable/disable certain class features. So in the druid tweak tpa file, which is run fairly early since it's modifying a base class,I have this kind of code: LAF GET_KIT_STRREF_EX STR_VAR kit_name = ~DRUID~ RET kit_strref END // custom function to return druid class description OUTER_SPRINT help_druid @15 // my custom druid description as the basis OUTER_PATCH_SAVE help_druid ~%help_druid%~ BEGIN // becasue we want later components to be able to inherit an already-changed description // do some textual replacements here based on different ini options END STRING_SET_EVALUATE %kit_strref% ~%help_druid%~ // set it here already in case only this particular component is installed Then in another component, say an item tweak component, which is run towards the tail-end of the installation process to ensure all items are patched, I have this kind of code: ACTION_IF (druid_short_bow = 1) BEGIN LAF GET_KIT_STRREF_EX STR_VAR kit_name = ~DRUID~ RET kit_strref END ACTION_IF (NOT (VARIABLE_IS_SET ~help_druid~)) BEGIN // in case the druid class tweak component from earlier was not installed ACTION_GET_STRREF %kit_strref% help_druid // so we pull the default one instead END OUTER_PATCH_SAVE help_druid ~%help_druid%~ BEGIN REPLACE_TEXTUALLY ~\(May only use the following weapons: scimitar, dagger, club, spear, quarterstaff, dart, sling\)~ ~\1, shortbow~ END STRING_SET_EVALUATE %kit_strref% ~%help_druid%~ END This runs okey, since the item tweak code can basically detect any previous changes to the druid class description made by any earlier components and have the default one as fallback, and dynamically modify the description further, and still saves the description as an variable just in case any other component might want to modify the same description later again. However, as you can see, even though it's utilizing a tra, the code in the item tweak section is not really translation-friendly. I know I could set up the two strings in the REPLACE_TEXTUALLY portion as two further references in the tra file, but then I need to SPRINT another two variables against these two references just to satisfy syntax compatibility for REPLACE_TEXTUALLY. So I'm wondering if there's a more elegant way of doing it. PS. I am aware I could simply break down the original class description (@15) in my tra into several pieces, then I can have all scenarios covered and perhaps avoid the need to do any textual modifications at all, but it involves even more (in my opinion needlessly consumed) variables here: LAF GET_KIT_STRREF_EX STR_VAR kit_name = ~DRUID~ RET kit_strref END OUTER_SPRINT help_druid1 @15 OUTER_SPRINT help_druid2 @16 OUTER_SPRINT help_druid3 @17 ACTION_IF (druid_3e_alignments = 1) BEGIN OUTER_SPRINT help_druid4 @19 END ELSE BEGIN OUTER_SPRINT help_druid4 @18 END OUTER_SPRINT help_druid5 @20 OUTER_SPRINT help_druid ~%help_druid1%%WNL%%help_druid2%%WNL%%help_druid3%%WNL%%help_druid4%%WNL%%help_druid5%~ STRING_SET_EVALUATE %kit_strref% ~%help_druid%~
  11. Apart from using (OUTER)SPRINT my_var @tra_ref, are there any other ways to treat tra references as variables directly? I'm trying to manipulate tra references conditionally at install time, using SPRINT and OUTER_PATCH_SAVE with a variable acting as a manipulateable placeholder for a tra reference, but I'm wondering if there're any other ways to let my alter the tra ref directly without the intermediate variable.
  12. What the unreleased KR did in this regard was pretty cool in my opinion: instead of giving text descriptions of a particular map, it functioned as non-magical detect invisibility at the cost of movement rate.
  13. Thank you for the quick answer. I’m also one of those that cannot leverage EEex (I’m on Linux and MacOS).
  14. Say, if I wanted to change a particular (existing/new) priest kit so that his/her *divine* enchantment spells are harder to save the same way as his/her fellow wizardary specialist enchanter functions in that respect, how would I do it? There does not seem to have a particular opcode to apply these saving-throw-per-school-bonus to creatures directly...
×
×
  • Create New...