Jump to content

jmerry

Modders
  • Posts

    1,356
  • Joined

  • Last visited

Posts posted by jmerry

  1. Now that I think about it, it feels like an accessibility issue. The white spell icons have low contrast in the light-background spellbook interface, and that means some people will have difficulty reading them. Especially the "faded" versions of those icons when a spell needs to be refreshed.

    Hmm... maybe recoloring that part of the spellbook would be the way to go? What do some of the major UI mods do with that screen?

  2. There's a script action for it: ForceRandomEncounter. EE only, unfortunately. It gets used in several EE companion quests.

    The other tool you have to work with are the encounter probabilities associated with travel links in the world map structure. That has a SetEncounterProbability script action associated with it ... which works in BG2 and the EE, but not original BG1. You can set a link's probability to 100 in your mod and force an encounter every time; it's just changing that probability dynamically in-game that needs the script action.

    In original BG1, without either of those script actions available, about all you can do is manipulate which links are traversable by hiding and revealing areas.

  3. Those particular commands - ReallyForceSpell and ApplySpell - are part of the base BCS/BAF scripting language, rather than the extensions SSL adds like that "RequireBlock". Which means that you can reference the IESDP page on script actions for what they do.

    Quote

    This action causes the active creature to cast the specified spell at the target object. The spell need not currently be memorised by the caster, and will not be interrupted while being cast. The spell is cast instantly (i.e. with a casting time of 0). The caster must meet the level requirements of the spell. This action does not work in the script round where the active creature has died.

    Quote

    This action causes the active creature to cast the specified spell at the target object. The spell is applied instantly; no casting animation is played. The spell cannot be interrupted. For the RES version of the action, the spell name can not consist of only numbers, should be written in upper case and should be no more than 7 characters long. Both actions apply the spell at the lowest casting level (they will even use a level 0 ability if the spell has one, which other actions cannot do) and ignore its projectile (i.e. they use projectile #1|None) - the casting level of the originating creature is ignored. Note that for normal spellcasting the probability dice values for effects are rolled for each spell, whereas spells applied in the same scripting block by ApplySpell use a single dice value.

    So, these two actions are functionally very similar. Both will cast the spell instantly, ignoring memorization. Also, the syntax is the same - target first, spell second. The differences are in the casting level and projectile; ReallyForceSpell uses the active creature's caster level (so a level 20 mage will get a 20d8 Horrid Wilting) and ApplySpell uses the minimum caster level and no projectile (so a level 20 mage will do 16d8 damage to the target with no AoE). I don't think ApplySpell is a good idea here.

    As for targeting an enemy ... actions with no valid target shouldn't crash anything. Most likely, they just won't be executed. At worst, they might prevent any later actions in the same block from being executed. Still, you should include some form of "there's an enemy nearby" in the trigger conditions for a block like this that targets an enemy.

  4. 5 hours ago, gatperdut said:

    I imagine the same might be true for other such items equipped by enemies (few, if any, as they might be).

    A complete list of those NPC mages in the main campaigns of the BG series:

    - Edwin (all), wearing "Edwin's Amulet" for +1 or +2 slots at each level. They're filled.

    - Ramazith (BG1), wearing "The Amplifier" for +1 level 2 slot. His vanilla version is a level 9 mage with 4/3/2/1 memorization; same as a level 7 mage with no boost from the item.

    - Sunin (BG1), wearing "Evermemory" for double level 1 slots. His vanilla version is a level 6 specialist mage with 5/4/2 memorization; an unfilled level 3 slot, an extra level 2 spell, and no doubling at level 1.

    - Winski Perorate (BG1), carelessly cloned from Sunin and not actually someone that can be fought. (His only purpose is to show up and kill you if you fail the Ducal Palace encounter)

    - Kherriun (SoD), wearing a "Ring of Wizardry" for double level 1 slots. Her vanilla version is a level 13 specialist mage with 12/6/6/5/5/3 memorization. Fully accurate with the item included.

    - Lavok (SoA), wearing the "Ring of Acuity" for bonus slots at levels 2, 3, and 4. In the version you fight, he's a level 21 mage with 5/4/5/2/3/4/3/2/2 memorization. Plenty of empty slots there.

    - Nadinal (SoA), wearing the "Reaching Ring" for one extra slot at each of levels 5, 6, and 7. His vanilla version is a level 10 specialist mage with 3/1/3/1/2 memorization - lots of empty spell slots no matter how you look at it.

    - Ribald (SoA), wearing an undroppable "Reaching Ring". His vanilla version is a level 16/14 fighter/mage with 6/6/8/3/2/3/3/1 memorization. Wait, you're saying that there are tables for how many spells a mage gets at each level?

    - Jon Irenicus from the first pocket plane challenge (ToB), wearing an undroppable "Reaching Ring". Level 20 mage, 0/0/0/0/6/10/6/5/5 memorization. Rules are only suggestions for your enemies.

    - Semaj from the second pocket plane challenge (ToB), wearing an undroppable "Reaching Ring". Level 20 mage, 4/5/3/4/6/5/5/3/3 memorization in both versions. Actually pretty close to living within his means; he only needs one more slot each at levels 7 and 9 to have those spells legitimately.

    So, verdict. It's a pretty manageable list if you want to implement it. And the vanilla game really doesn't care about matching memorization to the spell slots an enemy should have, most of the time.

  5. Yeah, that's lore identification. Your lore score is based on your class and level, with modifiers based on INT and WIS. Any variations from the standard rules here will show up in LORE.2DA (lore per level rates) or LOREBON.2DA (modifiers from mental stats).

    Now, that ring ... that sounds like an item that really shouldn't have dropped. There are lots of items that exist to apply some bonus to a monster (i.e. undead/construct immunities on RING95.ITM); these are traditionally rings that are undroppable so you'll never actually see them. They don't get proper names and descriptions because you're not supposed to ever be able to look at them anyway. And - well, sometimes mods make mistakes. Create a new item like that, forget to apply the undroppable flag, and you get something like this.

    Or maybe it's an item you're meant to see, and the mod forgot to give it a proper name and description. That can happen too.

  6. If the items are identified before even looking at them, a mod changed those items by either applying the "identified" flag or lowering the lore requirement to identify them to zero. (Aside from items that were already like this, such as mundane weapons and armor)

    If the items become identified when you inspect them, the character looking at them has a high lore score, at least compared to those items' lore requirement. In the standard rules, bards have very high lore scores (10 per level base, and nothing requires more than 100 to identify), thieves and mages have decent lore scores (3 per level base), and all other classes have poor lore scores (1 per level base).

  7. It should be. The "world map" structure uses exactly the same format across all games, so it should just be a matter of inserting the strings and editing that one file.

    ... and I've already written a component to do exactly this. My tweak mod is EE only as a whole, but I could extract this component as a stand-alone. Here it is, extended to work on any game that includes BG1. Hopefully.

    j8-map-names.zip

  8. And if it didn't work this way, you could reach STR 20 by simply taking off the girdle before you rest and re-equipping it after. Stat-setting always comes before stat-incrementing when calculating how effects combine, and anything like an "only if STR <= 18" test is only checked when the effect is initially applied.

    Would you wear all your gear to bed? In flavor terms, it makes sense to use the before-equipment baseline here.

  9. So the action here happens in ability/make_str_payload.tpa; that's where the tables for what strength does are updated. For lock-bashing and weight limit, this is the actual update:

    				PATCH_IF VARIABLE_IS_SET $bend_bars("%str%") BEGIN
    					SET_2DA_ENTRY row 3 5 $bend_bars("%str%")
    				END
    				PATCH_IF VARIABLE_IS_SET $weight_limit("%str%") BEGIN
    					SET_2DA_ENTRY row 3 5 $weight_limit("%str%")
    				END
    

    Update the lock-bashing value, using a previously-defined array of lock-bashing values. Then update the lock-bashing value again, using a previously-defined array of weight limit values. Which are much higher. Oops. That second SET_2DA_ENTRY should change entry 4 in the row rather than entry 3.

    That definitely accounts for strength 11 through 18; those are the values in the 2DA file used to build the bend_bars and weight_limit arrays earlier in this tpa. I'm not sure where things go wrong for strength 10, though...

    [Added in edit]

    What does STRMOD.2DA look like for you? It should be in the override, and that's a human-readable text format - no special tools required to read it.

  10. The difference between those timing modes is sharpest with stat-modifying opcodes. For those, timing mode 1 changes the base value of that stat for the creature, and does not leave any sort of effect behind that can be reversed. The Manual of Bodily Health applies +1 CON with timing mode 1.

    Timing mode 9, on the other hand, leaves a permanent stat-altering effect in place. That effect will endure even through death and resurrection, but can still be removed. The Dragon Disciple's CON bonus at levels 5 and 15 applies +1 CON each time with timing mode 9. So if a (non-protagonist) DD leaves the party, their kit abilities are removed and they lose that CON bonus. Bring them back, and the abilities are reapplied.

    Neither of these effects would work properly if the timing modes were swapped.

  11. On 1/13/2024 at 12:23 PM, Dan_P said:

    There's some bugginess in BG2EE as well. If starting a new game in SoA with a single class mage or sorcerer, you won't get minor sequencer. If starting a new game in ToB, you get only Contingency and Chain Contingency (once you get level 9 spells).

    Looks like the current version of things doesn't work for levels taken during the character creation process. I'm not sure why; abilities associated with those levels should just be applied when you enter the game. But that's what it is. Anyway, what's different about the actual spells here from older versions?

    - The applicator now removes its ability before applying it. This prevents multiple instances of a given sequencer/contingency stacking up when an NPC leaves the party and returns.

    - There is now a "wrap" layer which filters through a class check. This was clearly added in an attempt to exclude (unkitted) sorcerers, but doesn't actually do that because sorcerers apparently count as mages.

    Does removing that wrap layer fix this bug? It should be testable in a game with the component already installed by replacing instances of dwsqwr (the wrap spells) with dwsqds (the applicator spells) in the kit CLABs.

    [Disclaimer: I do not currently have any instances of the games with SCS installed]

  12. Ah. And that's implemented in how the applicator spell is built; it filters using opcode 177 so that only mages (including multiclass) and bards actually get the innate. Unkitted sorcerers have the applicator spell in their ability table, but it does nothing for them.

    So actually, you'd have to change more than just the code I quoted above if you wished to extend this tweak to sorcerers.

    Verdict: deliberate change working as intended, nothing to see here.

  13. So, a bit more in-depth on how this works. The file for the innate sequencers tweaks those spells, builds the "grant ability" spell, and then adds them to the ability tables with this:

       // apply the wraps to the CLAB files
       
       kit.edit_all[mage|clab_only:i=1]
       [
    		k.kit_apply_powers{%string_mage%}
       ]
        kit.edit_all[bard|clab_only:i=1]
       [
    		k.kit_apply_powers{%string_bard%}
       ]

    All mage kits and all bard kits, including CLABMA01 and CLABBA01 which apply to the "base class" version. And here's the old version:

       // patch innates into kits and update the class text to describe the new innate powers
    
      // mages
       OUTER_SPRINT seq_desc_string @1000
       LAF edit_all_kits STR_VAR parent_class=mage editstring="%kit_edit_mage% patch_description_strref=>seq_desc" END
       ACTION_IF enhanced_edition BEGIN
          LAF edit_kit STR_VAR kit=dragon_disciple editstring="%kit_edit_mage% patch_description_strref=>seq_desc" END
       END
    
      // bards
    
      OUTER_SPRINT seq_desc_string @1001
      ACTION_IF VARIABLE_IS_SET $spell_level_to_caster_level("bard" "7") BEGIN
         OUTER_SPRINT temp @1002
         OUTER_SPRINT seq_desc_string "%seq_desc_string%%temp%"
      END
      ACTION_IF VARIABLE_IS_SET $spell_level_to_caster_level("bard" "8") BEGIN
         OUTER_SPRINT temp @1003
         OUTER_SPRINT seq_desc_string "%seq_desc_string%%temp%"
      END
       LAF edit_all_kits STR_VAR parent_class=bard editstring="%kit_edit_bard% patch_description_strref=>seq_desc" END

    Basically the same, except that it also specifically calls out dragon disciples. Any sorcerer kits added by other mods are out of luck.

    So, what's up with sorcerers, and what's new? Well, unkitted sorcerers use the same ability table as unkitted mages. They're going to get the abilities regardless. But sorcerer kits aren't picked up by the call for all mage kits, so they get skipped. The Dragon Disciple is the only one in vanilla, but now ToF adds a bunch more sorcerer kits that should be supported.

    It looks like just adding another kit.edit_all call for sorcerer kits should work. Unless that doubles up on CLABMA01 - testing recommended.

  14. Checking the code ... that version of the tweak takes whatever table is already in place (normally the BG2 values) and multiplies every value by the entered percentage. With a floor of 1 XP each, if any XP was granted before; if you enter 0, that drops it to 1 XP per trap/lock/scroll instead of zero. The "Disabled" component is functionally identical to entering 0 in the "Custom Value" component.

  15. Yeah, that looks right. The full death ward package includes a bunch more immunities, some of which you may also want. (For example, the "vorpal hit" string)

    As for the "unused" segment of the effect block, it's just that - unused. Whatever's in there can be anything, as it's not read in an opcode 101 effect. That segment is used for a resource name when the effect refers to some specific resource, as in the opcode 206 effects that ring also have.

  16. Vorpal hits are opcode 13 "kill" effects. Basically the only stuff out there in vanilla that blocks that are death ward effects and full immortality effects. No items grant just the death ward part without other side effects, so you'd have to either add effects to the creatures directly or modify the general "dragring" immunity item.

    And yes, earlier versions of SCS did give dragons immunity to instant death. Here's a snippet from v34's dragon_shared.tph:

    //////////////////////////////////////////////////////////////////
    ////   Baseline patch for dragons
    //////////////////////////////////////////////////////////////////
    
    DEFINE_PATCH_FUNCTION dragon_general BEGIN
     LPF check_ini STR_VAR ini=bypass_dragon_immunity_changes RET value END
     PATCH_IF value=0 BEGIN
       PATCH_MAKE_PATCH
          delete_effect=>~opcode=193~
          add_effect_inline=>~opcode=>193 parameter2=>1~
          immunity_to_opcode=>~74 13 55 211 19~//immunity to blindness/slay/death/imprisonment/Mind Flayer
          immunity_to_string=>~1474 32089 14674~ // blindness, devour brain
          immunity_to_spell=>~%WIZARD_IMPRISONMENT%~
       END
       PATCH_IF !is_iwd BEGIN
          SPRINT $patch_data("immunity_to_spell'") "%DRAGON_WING_BUFFET%"
       END
       LPF apply_patches STR_VAR edits=patch_data file_ext=CRE END
     END
     PATCH_MAKE_PATCH
          class=>"if enhanced_edition then no_change else FIGHTER_MAGE_CLERIC"
          strip_scs_scripts=>null
     END
     LPF apply_patches STR_VAR edits=patch_data file_ext=CRE END
    END
    
    //////////////////

    And in v35 ... no changes to this section at this time. Which means that the likely cause here is changed library functions requiring different syntax for the same effect. Either that, or this particular SCS-added dragon didn't get the function applied for some reason.

  17. Well, if this is part of a BCS script, that's not a problem; the engine only sees the compiled code, which wouldn't have the named constant anyway. DLG files, though, have the BAF-format code in their raw forms. So there ... the engine loads the IDS files and uses them to interpret any constants that show up in the code.

  18. 10 hours ago, svj said:

    How does one append something to dialog tlk to be used in future for DisplayStringHead?

    RESOLVE_STR_REF is suitable for this. It returns a number, which you save in a variable. Then in that script bit, you include that variable in %% signs and compile it with an EVALUATE_BUFFER.

    Just in case this compile-time string-saving doesn't work out for you.

×
×
  • Create New...