Jump to content

jmerry

Modders
  • Posts

    1,356
  • Joined

  • Last visited

Posts posted by jmerry

  1. SoD ties a lot of things to difficulty level. There are scripts for "despawn this creature below difficulty X", so lots of encounters are only at full size if you're playing at Insane difficulty. Some other creatures apply difficulty modifiers in other ways; the Shadow Aspect, for example, uses Mislead at Insane, Improved Invisibility at Core or Hard, and Invisibility at Easy or Normal. Basically, if you want the full strength version of everything, you play at Insane difficulty.

    SoD has its own combat scripts, which are a lot more complex than those in the rest of the series. But by the same token, I'm not aware of any mods that "improve" them; SCS leaves them alone.

    As for that free action ring and the shambling mounds, that effect does things in a tricky way. Just like the priest spell, it applies the Entangle cosmetic effects, multiplies movement speed by 0, and penalizes AC by 2. Now, a standard free action package includes immunity to movement speed modifiers and the entangle overlay, so it should still protect you ... and I checked the item in question. You should be getting that immunity. I don't know what went wrong, unless something else edited the item afterward.

  2. With CLABPR01, it looks like the logic here trims any ABILITYN rows that don't have any ability entries. Which is harmless. Or at least, it's harmless as long as there's at least one ability row left (Have you checked CLABFI01 or CLABMA01? Those don't have any abilities at all). But at the same time ... is there any positive reason to do so? The only way trimming rows might matter is if you needed to make room, and I don't think there's a maximum number of rows in the format.

    With QDMAGUS, it's the already known issue with the table parser not recognizing rows that don't have the ABILITYN label. That will be fixed.

  3. 1 hour ago, Morgoth said:

    edit: I just got cursed while fighting the beast lord. And I realized the reason - the curse is the effect of Durlag's goblet that lasts 12 hours. 

    Ah, that makes sense. That effect uses the "curse" icon, but it isn't a curse in terms of mechanics. Also, it does nothing if you have any form of fear immunity active when you drink - you get the icon for twelve hours, but no other lingering effects.

  4. 16 minutes ago, MachoGrande said:

    I did replace the default.bs script with the one from the original BG2.

    This wouldn't matter; .bs scrips are never assigned to monsters outside the party, and can't be.

    This looks like another bug similar to the one that erased "talk to a PC" scripts from NPCs in earlier versions of v35; the new Carrion Crawler script is likely being removed after it has been assigned. With no replacement. And since that's their combat script, they just stand there doing nothing.

  5. [ENEMY], used as an object identifier, looks for anything with the ENEMY allegiance - that is, another creature hostile to the party. Which means it won't do anything if this creature is alone. I recommend using something like NearestEnemyOf(Myself) instead.

    (Also, that extra empty line between the trigger block and action block is nonstandard. I don't think it does anything when this compiles, but it can't hurt to remove it.)

    Also, as that's a player-usable ability you're using, beware interference from other mods. The Tweaks Anthology "Shapeshifter Rebalancing" component changes that spell to create a paw token that can be equipped to cause the transformation, for example - it no longer directly transforms the subject. If you want a spell that will definitely work, I recommend making a clone of the base spell yourself and including it with your mod.

  6. The "Remove Curse" effect does two things. It unequips items with the "cursed" flag, and it removes spells/effects applied with the "curse" opcode.

    The "Cursed" portrait icon is not either of those things, directly. Cursed items usually apply a "cursed" portrait icon as an equip effect, and curse spells usually have that portrait icon among their effects, but there's no intrinsic link. You can have an effect that "Remove Curse" will clear that doesn't have the portrait icon, and you can have something that applies the portrait icon but isn't affected by "Remove Curse".

    So, what effect exactly happened to you?

  7. BGEE rest spawns definitely aren't using the same scaling as BGEE spawn points. My test referenced earlier used the xvart village with a full party at the campaign cap (sum of levels 51), and got ten xvarts (power level 4) whenever that rest spawn (difficulty 2, maximum number 10) triggered. If that were running on the same scaling that the spawn points use, it would have been one xvart (51*2/100 total power, divide by 4 and round up to one enemy).

    Most likely, it just isn't using that factor of 100 in the calculation. So that's ceiling(51*2/4) = 26 xvarts, truncated to 10 by the secondary cap. Working as apparently intended.

  8. Exactly. Another round of BGEE tests - increase the numbers to 13 for an area in a save, try to rest ... eight successful rests out of twenty. So it's eight independent rolls on the table to get through a rest successfully. If you fail, the monsters show up and no time passes regardless of which roll it was that failed.

    The oIWD numbers look like a much more intuitive "this is the chance of encountering something in the entire rest". And there's no easy conversion between the two systems.

    So, three possibilities: either oIWD and IWDEE use different rest encounter calculations, the oIWD numbers are badly out of whack and that change was made so that it was reasonably possible to rest in the wilderness and dungeons (more than a 98% chance of an encounter for a region with a "40" probability such as daytime AR2000), or oBG2/BGEE uses a different calculation to oIWD/IWDEE and the changed numbers were a mistake.

    Testing the system in both IWD and IWDEE should clear this up.

  9. I checked the IESDP to see what that bit of crowdsourced wisdom had to say ... ARE v1.0 applies to all games under consideration. The info on the rest encounter substructure claims that it's a per-hour percentage chance, with no mention of any variation between games. Which ... testing in BGEE ... seems plausible, at least for the EE engine. If it was true for original IWD with the larger numbers above, that would make it essentially impossible to ever rest in most of those areas, given the eight uninterrupted hours needed.

    (Outdoor wilderness areas in BGEE tend to have that rest probability field at 3 or 4.)

  10. Also of note - the way dual-classing works in the standard rules, it'll wipe out any XP past your current level so you're best off doing it immediately after leveling up.

    The requirements for dual-classing are defined in two 2DA tables; ABDCDSRQ defines the stats needed to dual into a class or kit, while ABDCSCRQ defines the stats needed to dual from a class or kit. (And of course, in the standard rules, you're not allowed to dual-class into a kit)

    So for that ranger/cleric combination, we'd look at the RANGER row in ABDCSCRQ (15 15 0 0 15 0) and the CLERIC row in ABDCDSRQ (0 0 0 0 17 0). Combine those, and the stats needed (in the standard rules) are 15 STR, 15 DEX, and 17 WIS.

  11. After ending the CHAIN, you need a new action. You can't just have a state floating around unconnected; WeiDU doesn't know what dialogue file that's supposed to go into. From context, I think you want to add it to your already created "rqrugos" dialogue file, which would be an APPEND action.

  12. Shorter resource names are just fine in opcodes that use a resource reference; the remaining bytes of that field are filled out with nulls.

    SPLs referenced in a kit's CLAB - the GA_ and AP_ entries - can have a resource name of up to eight characters, at least in the EE. The first entry in Wilson the bear's kit CLAB, for example, is AP_OHRBEAR1. And of course, that resource name doesn't have to be of any particular form.

    Entries in spell.ids encode the filename, and that filename is one of exactly four thousand possibilities (SPPR###, SPWI###, SPIN###, and SPCL###, where ### are digits). That's not just a convention; it's hardcoded in how the file works. Fortunately, you can tell scripts to use spells that don't have spell.ids labels; all of the "use a spell" actions have RES versions that take the resource name as a parameter. For example, here's a block from Aerie's script in BG2EE, to give her the right holy symbol:

    IF
    	HasItem("CDHLYSYM",Myself)  // No such index
    THEN
    	RESPONSE #100
    		ApplySpellRES("CDHLYSY2",Myself)
    		ActionOverride(Myself,TransformItem("CDHLYSYM","beltbw"))
    END

     

  13. Reflecting between multiple characters with turning effects is dependent on game version, and specifically changed in patch 2.6. As of 2.6, a given spell can only reflect twice; if a (vanilla) elder orb casts Minor Spell Turning and then uses a ray against your character with the Shield of Balduran, that ray will reflect off the shield, reflect off the MST (and probably exhaust it), then return to hit its target despite them having the shield.

    So, in your example, if playing on (EE) version 2.6, you'd deplete both your and the opponent's Spell Turning effects a bit, and your Chromatic Orb would hit them after the two bounces. Unless they had another defense like a deflection or globe.

  14. Your reasoning is operating on a completely different axis than my thought was. You're looking at how many spell-breakers it takes to bring the defense down, in which case every spell is another layer of protection unless you use something like Spell Thrust or Spellstrike that can take down multiple protections at once.

    My claim was about how many normal spells it takes to burn through the defenses. Four levels of deflection from Minor Spell Deflection, ten from Spell Deflection - if I toss a Polymorph Other (level 4) at that, the MSD is exhausted and the SD is down to six levels left.

    As for how turning and deflection effects interact, if both are present ... I'm not actually sure. Haven't tested that. Wait - I can test it right now. Text character 1 casts Minor Spell Turning (up to level 4, 4 total levels of turning) and Spell Deflection (up to level 9, 10 total levels of deflection). Test character 2 casts Spirit Armor at test character 1. Result: test character 2 is now buffed by Spirit Armor, and the graphics and portrait icon for Minor Spell Turning are gone. Follow up with Improved Haste ... Spell Ineffective. And the Spell Deflection graphics are still there. Add another Spirit Armor - ineffective, and that exhausts the Spell Deflection.

    OK. Spell deflection and spell turning are separate layers, which do effectively add to each other in protecting against normal spells. Also of note is how these interact with a globe of invulnerability; if I load the test character up with a Globe of Invulnerability as well and repeatedly cast Spirit Armor at it, the first one gets reflected onto the caster and exhausts the Minor Spell Turning, the next three exhaust the Spell Deflection, and any after that do nothing because of the globe. Turning applies before deflection, which applies before blanket immunity.

  15. 22 minutes ago, gatperdut said:

    Discussing a bit with someone on SCS v30, similar behavior happened, in that higher-level protections don't protect lower-level ones.

    For example, Spell Turning doesn't prevent Spell Thrust from taking down MGoI. Adding Spell Trap on top doesn't make any difference, either. 

    That is not something changed by SCS, in any versions. It's just the way spell protections work. General deflection/turning/trap effects don't block anything with the MAGICATTACK type, which includes all the spell-breakers like Spell Thrust and Secret Word. In vanilla, it also includes Breach - that's what SCS (or, at least, one important component) changes.

    On top of that, when you do run a normal spell into those protections? It decrements all of them at once. Stacking multiple layers of deflection and turning effects doesn't get you any more protection than the strongest one alone.

    Now, Spell Shield is special. It's one level of deflection, only against the MAGICATTACK type. And with SCS, also against the new type that Breach gets. So that genuinely does provide an extra layer, eating one spell-breaker. So against an enemy with Spell Shield, you want to throw one cheap spell-breaker at them first. Don't open with that Spellstrike when you see a Spell Shield in the log - use it second instead.

    35 minutes ago, gatperdut said:

    This raises the question of whether there is an order in which protections are supposed to be dispelled, like peeling an onion, or if they can be taken down in any order.

    Not really. You take down Spell Shield first, then you throw spell-breakers at the problem until there isn't anything left, then you breach. Order really doesn't matter in that intermediate stage; the only case of a protection blocking a spell you might use here is that Globe of Invulnerability (not the Minor version) blocks Spell Thrust. And then you repeat whatever's needed when the enemy mage re-ups some of their protections. That's the standard paradigm with SCS.

    Variations may apply. If you have a level advantage, you might aim to take down their combat protections with a dispel instead of a Breach - in which case most of the spell protections don't matter, and you can just throw out that Remove Magic first thing unless they're one of the few enemies that use abjuration immunity. Or use Spell Thrust to take down that immunity even if they still have higher-level protections up. If you're planning on killing them with AoE fire spells, all you care about taking down is their fire protection spell, and that's not something they'll ever recast once it's gone. If you're a particularly arcane-heavy party, you might task a mage with casting True Sight to deal with the enemy's invisibility instead of leaving that one to a thief or cleric.

  16. That's very odd, since I looked at the area in NI and compared the order of elements (the stuff with offset entries in the header) to some other areas. No difference. Sure, there's one empty element at offset zero (always potential trouble, there), but that same empty element was at offset zero in every area I checked.

  17. All right, looks like a bug with that component. Diving into the code ...

    Here's the function call that's supposed to delete the Robe of Vecna from the store, in v35:

    sto.edit[wmart2][ m.item.delete{s_resref STR_EQ wa2robe} ]

    New sfo2e stuff. Which I don't really understand. But I can tell that the ones for the Helm of Vhailor and Shield of Balduran are basically the same. And then I looked at another component, removing arrows of dispelling from stores ... and there was a key difference. s_resref was inclosed in %%, WeiDU's way of saying to evaluate the variable. Oh. That explains it. s_resref is an element of the structure describing this "item" element of the store, but only if the variable is actually evaluated.

    The current code for the items that get removed from Deidre's store apparently tests for which item to delete by comparing a resource reference (i.e wa2robe) with the literal string s_resref. Which always returns false, so nothing changes. Enclosing that s_resref in percentage signs in the m.item.delete lines from item/balduran_shield.tpa, item/vecna.tpa, and item/vhailor_helm.tpa should fix this so the items are properly removed from the stores. In each of item/balduran_shield.tpa, item/vecna.tpa, and item/vhailor_helm.tpa, there is a line including "m.item.delete{s_resref STR_EQ"; if I'm right, each of those should be modified to replace s_resref with %s_resref%.

  18. Honestly, I don't know that much about two-dimensional arrays - I just know the one setup that I used in the snippet from my mod, with the array and two arguments. Copying a row at a time and then pulling elements of that row - not something I'm sure about. And so, I'm not surprised when the version I posted didn't work.

    Oh, wait. I'm pretty sure that should be PHP_EACH rather than FOR_EACH. It's an array we're working with here, not a simple list...

    Alternate form, using the exact structure I'm familiar with:

    Spoiler
    OUTER_FOR (row = 0; row < pricelist; ++row) BEGIN
        OUTER_SPRINT FileID $pricelist(~%row%~ ~0~) // First entry of the row
        COPY_EXISTING ~%FileID%.itm~ ~override~
            PATCH_IF (SOURCE_SIZE > 0x71) BEGIN // Sanity check
                SET newprice = $pricelist(~%row%~ ~1~)
                PATCH_IF (newprice > -1) BEGIN
                    WRITE_LONG 0x34 newprice
                END // Another sanity check? I don't think you really need all of them.
            END
        BUT_ONLY IF_EXISTS // OK, I added one more sanity check here. No copying files that don't exist.
    END

     

     

  19. Oh, there's lots of broken things about that code. Copied, with tweaks to indenting and new comments.

    Spoiler
    ////////////////////////////////////////////////////////////////////
    BEGIN ~Change item prices for IR to their original values~
    //REQUIRE_COMPONENT "item_rev.tp2" 0 "This component needs to be installed after Item Revisions"
    ////////////////////////////////////////////////////////////////////
    
    COPY ~weidu_external/data/WStweaks/pricelist.2da~ ~override~
        READ_2DA_ENTRIES_NOW pricelist 2  // Read the entries in "pricelist". "pricelist.2da" is only 2 columns 
    BUT_ONLY
    
    COPY_EXISTING_REGEXP GLOB ~.*\.itm~ ~override~
      PATCH_IF (SOURCE_SIZE > 0x71) THEN BEGIN
        READ_LONG 0x34 "price"
      END // Ends IF block
      OUTER_SET "new_price" = "-1" // This is an ACTION. Close the item. Or actually, wait until you've gone through all the items and only do this after the last one. Even if zzz.ITM was a stub with zero file size.
      OUTER_SPRINT "item_name" "%SOURCE_RES%" // Another ACTION
      ACTION_FOR_EACH row IN pricelist BEGIN // Another ACTION
        PATCH_IF ("%row_0%" STRING_EQUAL_CASE "item_name") THEN BEGIN // PATCH but nothing's loaded. Syntax error.
          SET "new_price" = "%row_1%" // Another PATCH.
        END // Close IF block
      END // Close array loop. Also, see explanation below for why your structure is inefficient.
      PATCH_IF ("%new_price%" > "-1") THEN BEGIN // PATCH
        WRITE_LONG 0x34 ("%new_price%") // PATCH
      END // Close IF block
      END // Close ... nothing. Syntax error.
    BUT_ONLY // If you still had an item loaded, this would be useful.

     

    So the main thing there is the distinction between ACTION and PATCH. When you try to use an ACTION with a file loaded, you close that file. When you try to use a PATCH without a file loaded, you get a syntax error. Lots of commands, like OUTER_SET and SET for setting integer variables, have both ACTION and PATCH versions; make sure you're using the right versions for your current environment.

    Then there are two more issues.

    First, and more minor, your sanity check is basically nullified by ENDing it before you do anything else. If you want to condition your changes on the file being valid, you have to put your changes inside the IF block. Which is probably about the extra END; in retrospect, the END immediately after the IF looks like the one that shouldn't be there.

    Second, your fundamental structure here is O(n^2) in the number of items, when it could be O(n). There are about 3000 items in unmodified BG2EE. Making your code run a thousand times faster is absolutely worth it. What you're currently doing - or at least, trying to do - is to iterate over every item, then compare each item to the entire array of items and do stuff when they match. What you could do instead is iterate over the array and load the item file the current row corresponds to:

    Spoiler
    ACTION_FOR_EACH row IN pricelist BEGIN
      COPY_EXISTING ~%row_0%.itm~ ~override~ // First entry in row is item name
        // Do stuff with the item and the row's data
      BUT_ONLY
    END // End array loop

     

    That way, you're only making a single pass through the items, in that array loop. 

  20. Are you on a new save, or did you continue an existing run that had already seen that shop? Visited shops get copied into the save, and the version in the save (which mods don't touch) is what's used from then on in that run.

    For files that exist in both the BIFs and the override, Near Infinity will always display the override version, because that's what the game would use. You can change whether this file is displayed under "Override" or its filetype with the "Show Override Files" options, but you'll always see the version that actually gets used.

  21. CHAIN is its own top-level .D action. It does not go inside an APPEND; that's where the syntax error comes from. APPEND to BELMIN, and the next thing WeiDU sees isn't a state.

    Also, it's good practice to impose conditions on the starting point of a CHAIN; you don't want Belmin to try to initiate that every time anyone talks to him even if your new elf isn't in the party.

×
×
  • Create New...