Jump to content

guyudennis

Members
  • Posts

    82
  • Joined

  • Last visited

Everything posted by guyudennis

  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...
  15. This also means for the majority of BG1 portion, players don't see much difference (apart from saving throws) between the specialist mages, unless he/she also install the specialist tweaks component. Don't know if you want to mention that in the description of this component.
  16. Thanks, and done. My misunderstanding came from mistakenly thinking op326 reads both stats.ids and splprof.2da with para2 < 0x100 triggering stats.ids.
  17. Ok...call me stupid, or I'm not reading IESDP right...but op326 seems to only reference SPLPROT.2DA, while completely ignoring STATS.IDS? Let's say proficiency showbow is listed as 105 in STATS.IDS, so I did this: LPF ADD_SPELL_EFFECT INT_VAR opcode = 326 target = 1 parameter1 = 0 parameter2 = 0x00000069 timing = 1 resist_dispel = 2 STR_VAR resource = ~MY_CUSTOM_SHORTBOW_233_SUBSPL~ END But when I check my main spell with 326 in NI later. it shows para2 = Class, as is listed in SPLPROT.2DA. What am I missing?
  18. Regarding op233... I want to apply an ability through CLAB that (a) gives a kit 1 proficiency point if he doesn't yet have it, but (b) at the same time do nothing to an existing proficiency if he already has it. When I use Set if Higher in para2, it achieves (a) but at the same time force overwrites any existing proficiency also back to 1. On the other hand, if I use Increment it increments everything, effectively also achieving (a), but it has the undesired side-effect of increasing any existing proficiency by 1, possibly exceeding what he can legally achieve through normal means. What I am missing? Or is op233+Set_if_higher somehow bugged? LPF ADD_SPELL_EFFECT INT_VAR opcode = 233 target = 1 parameter1 = 0x00000001 parameter2 = 0x00000059 timing = 9 resist_dispel = 2 END // modify proficiencies: bastard sword (89)
  19. @argent77 Thank you for the fast response. @jastey Please feel free to move this topic into the IWDification subforum if it's needed.
  20. Hi @argent77, I'll post here since I don't have an account in any other BG modding forums. I think there's an incompatibility between the mods in the title. What I found out was: if I install Reveal Hidden Gameplay Options with the 1st choice "install all options at once" (no need to install the hotkey update component), and afterwards install IWDification and/or SCS, then when I start a game later the executable (SoD on MacOS) would complain about syntax errors within bgee.lua and error out. WeiDu changelog pointed out that all three mods make changes to bgee.lua, and at least with SCS it's unavoidable since the change is tied to its "initialize" process. The errors are usually in the "cheat menu" section for arcane and divine spells, usually with missing comma or the additional rows named "DW_INSERT1/2/3"... Sometimes either IWDification or SCS together with Reveal Hidden Gameplay Options is enough to bring out the syntax errors, while in other times it would need all three mods installed to bring out the errors. I could "fix" it by manually adding back the commas and deleting the "DW_INSERT..."s in bgee.lua, but the remaining content still looked messy and clearly missing entries. I also found out if the "improved cheat menu" component alone from Reveal Hidden Gameplay Options is installed *after* IWDification's arcane/divine spell packs and/or SCS, there's no longer any syntax errors in bgee.lua. I thought you might want to know this and perform further analysis, since the incompatibility seems to be brought up only with the v4.x of Reveal Hidden Gameplay Options with which the "improved cheat menu" component was introduced. Cheers~
  21. Thank you. That Hold Person example clarified my confusion.
  22. Thank you, both. So in a nutshell, I should: duplicate an existing HLA spl edit the duplicate so that: its spell type is changed to innate optional: change its location to 4 (innate) keep only the 1st extended header and delete the rest if there are more than 1 headers; this preserves the original extended header's target, range, casting time and projectile (if any), etc modify the extended header so that its range is (original range minus 3) delete all the (extended) spell effects in the remaining extended header, and add an op146 (if the original HLA was targeting a creature [including self-targeting]) or an op148 (if the original HLA was an AoE) make sure the op146/op148 has SET target = 1 (self) parameter2 = 1 timing mode = 1 SPRINT resource = ~original HLA~ Correct? Did I miss anything else that's worth changing?
  23. Not to hijack the SCS thread, so I ask my questions here. @jmerry by “mode 1” you meant timing mode = 1 or para2 = 1? @subtledoctor I don’t really catch what you meant here? Within the scope of what we were talking about, making innate wrappers to cast the original HLA spells, I would guess the target of 146/148 would always be Self? If that’s correct, then what’s the difference between those Opcodes, again within the scope as mentioned above? And what about para1 and para2? My guess is para1 = 0 and para2 = 0, no matter what opcode (146/148) we use or if the actual HLA is self-targeting or AoE, correct?
×
×
  • Create New...