subtledoctor Posted February 24, 2023 Share Posted February 24, 2023 (edited) One of my mods requires several hundred effects to be active on spellcasters. This is not troublesome, but I'm a bit concerned about savegame bloat where, if I cycle through lots of different party members over the course of a game, the savegame will still have to track all those effects on NPCs who are not in the party. I have a .SPL set up to remove those effects, and another one to add them back; what I'm a bit unclear on is how to apply those spells when leaving and re-joining the party. I have some vague ideas for how this could work: Maybe: find the dialogue for each NPC (from PDIALOG.2da etc.) and add an ApplySpellRES() to each instance of leaving or joining the party? Not totally sure how to systematically find those events within the dialogues, though. Maybe: have BALDUR.bcs constantly try to ApplySpellRES my spell to all joinable NPCs; but have BALDUR.bcs make Player1-Player6 (anyone in the party) immune to application of the spell Spoiler IF [this_npc is not in party...??] TriggerOverride("[this_npc]",Global("NPC_OUT","LOCALS",0) THEN RESPONSE #100 ActionOverride("[this_npc]",SetGlobal("NPC_OUT",GLOBAL",1) ApplySpellRES("[spell]","[this_npc]") END IF TriggerOverride("Player[1-6]",Global("NPC_OUT","LOCALS",1) THEN RESPONSE #100 ActionOverride("Player[1-6]",SetGlobal("NPC_OUT",GLOBAL",0) ApplySpellRES("[other_spell]","[this_npc]") END ...? I'm sure there is a sensible answer here, but this is not an area I have much experience with. Edited February 24, 2023 by subtledoctor Quote Link to comment
jastey Posted February 24, 2023 Share Posted February 24, 2023 Just two quick things: 1. My 7th party members are not "InParty" (nor Player2-6). 2. How about adding a script.to the NPCs or a block.to the NPCs override script that checks for InParty/ not in party? Quote Link to comment
jmerry Posted February 24, 2023 Share Posted February 24, 2023 There's already something kind of like this in the base game - Story Mode gets cleared from anyone that leaves the party. Mostly, anyway. It's done through a block in the characters' override scripts - exactly jastey's suggestion. (And Imoen is missing this block in BGEE if you also have SoD) Quote Link to comment
subtledoctor Posted February 24, 2023 Author Share Posted February 24, 2023 (edited) Huh. I didn’t even realize there was an InParty trigger! That simplifies things. I also didn’t know if I could rely on every NPC having an override script. That should work fine. And I can potentially whitelist NPCs who can operate as 7th members. (There are only, what, four of them?) I don’t actually know how much difference this will make. But when I look at an NPC who has ~1,200 active effects in my savegame, it seems like it’s worth experimenting with removing them if they are not needed. Specifically this is for 5E spellcasting. The easiest way to set it up might be to cast the “change my prepared spells” ability when leaving the party. This would require them to sleep after re-joining in order to cast spells again - not too problematic if they are waiting at an inn or something. Or I could even give them a single-use innate to restart their spellcasting upon rejoining, then no sleep would be needed. Okay I’ve got some fairly simple ideas to work with, I’ll experiment a bit. Thanks for the guidance. Edited February 24, 2023 by subtledoctor Quote Link to comment
argent77 Posted February 24, 2023 Share Posted February 24, 2023 38 minutes ago, subtledoctor said: And I can potentially whitelist NPCs who can operate as 7th members. (There are only, what, four of them?) Doesn't work if you install characters with the NPC Generator. It allows every generated NPC to tag along as a follower. Quote Link to comment
CamDawg Posted February 24, 2023 Share Posted February 24, 2023 If the effects are applied via ability tables, they're already removed/re-applied as the NPC joins and leaves. However, I don't think this is the case for any subspells that get invoked unless it's done in a way to preserve the spell source in the effects. Alternatively, if the concern is that you're going to get multiple sets of the same effects you can add a 321 at the top of an effect stack to prevent stacking of unnecessary effects, the same way that normal spells prevent stacking. Quote Link to comment
subtledoctor Posted February 24, 2023 Author Share Posted February 24, 2023 (edited) 1 hour ago, CamDawg said: If the effects are applied via ability tables, they're already removed/re-applied as the NPC joins and leaves. They’re not. A brief explanation: The system polls every valid memorizable wizard and priest spell in the game, and creates an innate ability that casts each spell via 146/148. So, about ~700 innates. And an innate-grant spell with 171 for each innate. And a grant-block spell with 206 vs. each innate-grant spell. When you have spells memorized and rest, a script checks which spells you don’t have memorized, and applies the grant-block 206 spell for each one. Then the script casts all 700 innate-grant spells. So if you have 10 spells memorized, you must carry 690 constant 206 effects, and only 10 of the 700 innate-grant spells actually get through. Result: you get innate abilities corresponding to the 10 spells you had memorized. (And the upshot is, you can cast those memorized spells like a sorcerer does.) You have a ‘change memorization’ innate ability that 1) wipes out all 690 of those grant-block 206 effects, and 2) allows you to memorize different spells to start the process over. After using this ability, but before resting, you have no 206 effects on you. If you have six party members with a thousand active effects each, it’s not a big deal. But, maybe, by late BG2 there might be 40 or more NPCs with a thousand active effects. Possibly, this is contributing to .GAM file bloat and saves that can’t be opened. But if each NPC simply casts the ‘change memorization’ spell when leaving the party, then bam - (34x700) ~24,000 active effects that no longer need to be tracked in the savegame. Presumably, maybe, that will slim down the file. I even already have a mechanism to restore their spellcasting when they rejoin, and this mechanism can be used by 7th-member NPCs so even they should be fine. The only sticking point (in theory) is nailing that “when leaving the party” condition for casting the spell. I’ll check out the Story Mode thing when I get a chance, that sounds promising. Edited February 24, 2023 by subtledoctor Quote Link to comment
subtledoctor Posted February 25, 2023 Author Share Posted February 25, 2023 (edited) For the sake of posterity, this is what I'm going with: Spoiler COPY ~%MOD_FOLDER%/lib/semi_spont/d5_base.spl~ ~override/d5zleav.spl~ LPF ADD_SPELL_EFFECT INT_VAR opcode = 326 target = 1 parameter1 = 0 parameter2 = %not_prep_row% timing = 1 STR_VAR resource = ~d5zprp~ END LPF ADD_SPELL_EFFECT INT_VAR opcode = 326 target = 1 parameter1 = 0 parameter2 = %not_prep_row% timing = 1 STR_VAR resource = ~d5jpmem~ END <<<<<<<< d5/leavscpt.baf IF !InParty(Myself) Global("D5_LEFT","LOCALS",0) THEN RESPONSE #100 SetGlobal("D5_LEFT","LOCALS",1) ReallyForceSpellRES("D5ZLEAV",Myself) Continue() END IF InParty(Myself) Global("D5_LEFT","LOCALS",1) THEN RESPONSE #100 SetGlobal("D5_LEFT","LOCALS",0) Continue() END >>>>>>>> COPY ~d5/leavscpt.baf~ ~weidu_external/%MOD_FOLDER%/compile/leavscpt.baf~ LAM JOINABLE_NPC_ARRAYS ACTION_PHP_EACH JOINABLE_NPC_ARRAY AS cre => dv BEGIN // PRINT ~%cre% => %dv%~ COPY_EXISTING ~%cre%~ ~override~ READ_ASCII 0x248 override_script SPRINT $npc_scripts(~%override_script%~)~1~ BUT_ONLY END ACTION_PHP_EACH npc_scripts AS script => ind BEGIN ACTION_IF (FILE_EXISTS_IN_GAME ~%script%.bcs~) BEGIN EXTEND_TOP ~%script%.bcs~ ~weidu_external/%MOD_FOLDER%/compile/leavscpt.baf~ END END The JOINABLE_NPC_ARRAYS is the k4thos macro which can be found in the useful Weidu macros thread. EDIT - Derp. The joinable NPCs macro is not working, the spell is being applied to everyone on every map. Don't think it'll actually cause any problems... but I should try to nail that down. EDIT 2 - I think the macro caught a false positive, who has SHOUT.bcs as their override script. And now everyone covered by SHOUT.bcs is having it applied. Edited February 26, 2023 by subtledoctor Quote Link to comment
subtledoctor Posted February 26, 2023 Author Share Posted February 26, 2023 (edited) Okay here's a revised version. It avoids patching SHOUT.bcs and adds a secondary local variable (D5_PNPC) that prevents anything from happening until someone has actually been in the party. So the spell should only be cast on actual party members who subsequently leave. Spoiler COPY ~%MOD_FOLDER%/lib/semi_spont/d5_base.spl~ ~override/d5zleav.spl~ LPF ADD_SPELL_EFFECT INT_VAR opcode = 326 target = 1 parameter1 = 0 parameter2 = %not_prep_row% timing = 1 STR_VAR resource = ~d5zprp~ END LPF ADD_SPELL_EFFECT INT_VAR opcode = 326 target = 1 parameter1 = 0 parameter2 = %not_prep_row% timing = 1 STR_VAR resource = ~d5jpmem~ END <<<<<<<< d5/leavscpt.baf IF !InParty(Myself) Global("D5_LEFT","LOCALS",0) Global("D5_PNPC","LOCALS",1) THEN RESPONSE #100 SetGlobal("D5_LEFT","LOCALS",1) ReallyForceSpellRES("D5ZLEAV",Myself) Continue() END IF InParty(Myself) Global("D5_LEFT","LOCALS",0) Global("D5_PNPC","LOCALS",0) THEN RESPONSE #100 SetGlobal("D5_PNPC","LOCALS",1) Continue() END IF InParty(Myself) Global("D5_LEFT","LOCALS",1) THEN RESPONSE #100 SetGlobal("D5_LEFT","LOCALS",0) Continue() END >>>>>>>> COPY ~d5/leavscpt.baf~ ~weidu_external/%MOD_FOLDER%/compile/leavscpt.baf~ LAM JOINABLE_NPC_ARRAYS ACTION_PHP_EACH JOINABLE_NPC_ARRAY AS cre => dv BEGIN COPY_EXISTING ~%cre%~ ~override~ READ_ASCII 0x248 override_script PATCH_IF !(~%override_script%~ STRING_EQUAL_CASE ~SHOUT~) BEGIN SPRINT $npc_scripts(~%override_script%~)~1~ END BUT_ONLY END ACTION_PHP_EACH npc_scripts AS script => ind BEGIN ACTION_IF (FILE_EXISTS_IN_GAME ~%script%.bcs~) BEGIN EXTEND_TOP ~%script%.bcs~ ~weidu_external/%MOD_FOLDER%/compile/leavscpt.baf~ END END Only odd thing is, in my test, some scripts had the EXTEND_TOP applied more than once. I thought using them in the first "column" (key?) of an array should prevent them from doubling up. It probably won't make a difference... but, cleaner is better. Does UNLESS work with EXTEND_TOP? Edited February 26, 2023 by subtledoctor Quote Link to comment
Recommended Posts
Join the conversation
You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.