Jump to content

SubtleMods: NPC_EE - in-game customization for NPCs


Recommended Posts

Quick update to v2.1... this adds compatibility with EET. (At least I think so. Perhaps @K4thos can look it over and confirm. I've marked it as a pre-release for the moment so BWS is still pulling 2.0. Once I hear that this is stable I'll mark it for release.)

 

In addition to some general code cleanup, I've added a single new re-classing component: turn Xzar into a multiclass cleric/mage! He should keep his necromancer kit, so he will have the best of necromancer abilities from both the divine and arcane spell lists. (But, be careful, this is probably not compatible with Refinements HLAs. Of course, this is EE-only and I don't think Refinements is compatible with the EEs, so that should not be a problem.

 

https://github.com/subtledoctor/NPC_EE/releases/tag/2.1

Link to comment

the compatibility stuff looks fine, thanks for the update. What I would suggest are minor changes to how the code is written to not copy the same file over and over again (it's not related to compatibility with EET of course)

 

For example this code (btw. that "~branwe5.cre~ ~override~" line looks like a mistake):

 

 

ACTION_FOR_EACH char IN ~%tutu_var%branwe~ ~%tutu_var%branwe5~ ~o#bran~ ~o#bran25~ BEGIN
  ACTION_IF FILE_EXISTS_IN_GAME ~%char%.cre~ BEGIN
    COPY_EXISTING ~%char%.cre~ ~override~
        WRITE_BYTE 0x0234 1 //sets level to 1
        WRITE_BYTE 0x0235 1
        WRITE_BYTE 0x0236 1
        WRITE_BYTE 0x273 8 // sets class
        WRITE_BYTE 0x0066 10
        WRITE_BYTE 0x006a 5
        WRITE_SHORT 0x0024 12
        WRITE_SHORT 0x0026 12
        READ_BYTE 0x11 rdual
        WRITE_BYTE 0x11 (rdual BAND 0b11111110) // uncheck ranger dual-class flag
        READ_BYTE 0x10 dual
        WRITE_BYTE 0x10 (dual BAND 0b00000111) // uncheck other dual-class flags
    ACTION_IF NOT FILE_EXISTS_IN_GAME ~d5_profs.d5~ THEN BEGIN
        COPY_EXISTING ~%char%.cre~ ~override~
                ~branwe5.cre~ ~override~
            LPF DELETE_EFFECT INT_VAR match_opcode = 233 END
        BUT_ONLY
        COPY_EXISTING ~%char%.cre~ ~override~
            SET_BG2_PROFICIENCY 107 1
            SET_BG2_PROFICIENCY 101 1
            SET_BG2_PROFICIENCY 97 2
        BUT_ONLY
    END
    ACTION_IF FILE_EXISTS_IN_GAME ~d5_tempu.2da~ THEN BEGIN
        COPY_EXISTING ~kitlist.2da~ ~override~
            COUNT_2DA_ROWS 8 "rows"
            FOR ( index = 31 ; index < rows ; index = index + 1 ) BEGIN
                READ_2DA_ENTRY "%index%" 5 8 "clab"
                PATCH_IF ("%clab%" STRING_EQUAL_CASE "d5_tempu" = 1) BEGIN
                    SET "d5_tempu" = "%index%"-1
                    SET "rows" = 0
                END
            END
        BUT_ONLY
        COPY_EXISTING ~%char%.cre~ ~override~
            WRITE_SHORT 0x244 0
            WRITE_SHORT 0x246 0x4000 + ~%d5_tempu%~ // changes kit
            LPF ADD_CRE_EFFECT INT_VAR opcode=171 target=1 timing=9 power=1 STR_VAR resource=~spcl152~ END
            LPF ADD_CRE_EFFECT INT_VAR opcode=171 target=1 timing=9 power=1 STR_VAR resource=~d5_temp1~ END
    END
  END
END

 

 

could be changed to this:

 

 

ACTION_IF FILE_EXISTS_IN_GAME ~d5_tempu.2da~ BEGIN
  COPY_EXISTING ~kitlist.2da~ ~override~
    COUNT_2DA_ROWS 8 "rows"
    FOR ( index = 31 ; index < rows ; index = index + 1 ) BEGIN
      READ_2DA_ENTRY "%index%" 5 8 "clab"
      PATCH_IF ("%clab%" STRING_EQUAL_CASE "d5_tempu" = 1) BEGIN
        SET "d5_tempu" = "%index%"-1
        SET "rows" = 0
      END
    END
  BUT_ONLY
END

ACTION_FOR_EACH char IN ~%tutu_var%branwe~ ~%tutu_var%branwe5~ ~o#bran~ ~o#bran25~ BEGIN
  ACTION_IF FILE_EXISTS_IN_GAME ~%char%.cre~ BEGIN
    COPY_EXISTING ~%char%.cre~ ~override~
      WRITE_BYTE 0x0234 1 //sets level to 1
      WRITE_BYTE 0x0235 1
      WRITE_BYTE 0x0236 1
      WRITE_BYTE 0x273 8 // sets class
      WRITE_BYTE 0x0066 10
      WRITE_BYTE 0x006a 5
      WRITE_SHORT 0x0024 12
      WRITE_SHORT 0x0026 12
      READ_BYTE 0x11 rdual
      WRITE_BYTE 0x11 (rdual BAND 0b11111110) // uncheck ranger dual-class flag
      READ_BYTE 0x10 dual
      WRITE_BYTE 0x10 (dual BAND 0b00000111) // uncheck other dual-class flags
      PATCH_IF NOT FILE_EXISTS_IN_GAME ~d5_profs.d5~ BEGIN
        LPF DELETE_EFFECT INT_VAR match_opcode = 233 END
        SET_BG2_PROFICIENCY 107 1
        SET_BG2_PROFICIENCY 101 1
        SET_BG2_PROFICIENCY 97 2
      END
      PATCH_IF FILE_EXISTS_IN_GAME ~d5_tempu.2da~ BEGIN
        WRITE_SHORT 0x244 0
        WRITE_SHORT 0x246 0x4000 + ~%d5_tempu%~ // changes kit
        LPF ADD_CRE_EFFECT INT_VAR opcode=171 target=1 timing=9 power=1 STR_VAR resource=~spcl152~ END
        LPF ADD_CRE_EFFECT INT_VAR opcode=171 target=1 timing=9 power=1 STR_VAR resource=~d5_temp1~ END
      END
    BUT_ONLY
  END
END

 

 

 

notice that it does exactly the same thing but copies every modified file just once, which makes the code less confusing and the mod will install faster. Just a suggestion, feel free to ignore it.

Edited by K4thos
Link to comment

Good catch on the branwe5 thing.

 

The reason it copies multiple times is, during testing of an early version, when I did a single copy that 1) patched various fields, 2) used DELETE_EFFECT to zero out proficiencies, and 3) used ADD_BG2_PROFICIENCY to set new proficiencies (basically, when I did what you suggest), it didn't work. I forget exactly where it failed... it was either between steps 1 and 2, or between steps 2 and 3. I separated them out and it worked, so I just left it that way. Installation of each component takes a few tenths of a second on my 2012 computer, so I never felt very driven to optimize.

Link to comment

the compatibility stuff looks fine, thanks for the update. What I would suggest are minor changes to how the code is written to not copy the same file over and over again (it's not related to compatibility with EET of course)

 

For example this code (btw. that "~branwe5.cre~ ~override~" line looks like a mistake):

 

 

ACTION_FOR_EACH char IN ~%tutu_var%branwe~ ~%tutu_var%branwe5~ ~o#bran~ ~o#bran25~ BEGIN
  ACTION_IF FILE_EXISTS_IN_GAME ~%char%.cre~ BEGIN
    COPY_EXISTING ~%char%.cre~ ~override~
        WRITE_BYTE 0x0234 1 //sets level to 1
        WRITE_BYTE 0x0235 1
        WRITE_BYTE 0x0236 1
        WRITE_BYTE 0x273 8 // sets class
        WRITE_BYTE 0x0066 10
        WRITE_BYTE 0x006a 5
        WRITE_SHORT 0x0024 12
        WRITE_SHORT 0x0026 12
        READ_BYTE 0x11 rdual
        WRITE_BYTE 0x11 (rdual BAND 0b11111110) // uncheck ranger dual-class flag
        READ_BYTE 0x10 dual
        WRITE_BYTE 0x10 (dual BAND 0b00000111) // uncheck other dual-class flags
    ACTION_IF NOT FILE_EXISTS_IN_GAME ~d5_profs.d5~ THEN BEGIN
        COPY_EXISTING ~%char%.cre~ ~override~
                ~branwe5.cre~ ~override~
            LPF DELETE_EFFECT INT_VAR match_opcode = 233 END
        BUT_ONLY
        COPY_EXISTING ~%char%.cre~ ~override~
            SET_BG2_PROFICIENCY 107 1
            SET_BG2_PROFICIENCY 101 1
            SET_BG2_PROFICIENCY 97 2
        BUT_ONLY
    END
    ACTION_IF FILE_EXISTS_IN_GAME ~d5_tempu.2da~ THEN BEGIN
        COPY_EXISTING ~kitlist.2da~ ~override~
            COUNT_2DA_ROWS 8 "rows"
            FOR ( index = 31 ; index < rows ; index = index + 1 ) BEGIN
                READ_2DA_ENTRY "%index%" 5 8 "clab"
                PATCH_IF ("%clab%" STRING_EQUAL_CASE "d5_tempu" = 1) BEGIN
                    SET "d5_tempu" = "%index%"-1
                    SET "rows" = 0
                END
            END
        BUT_ONLY
        COPY_EXISTING ~%char%.cre~ ~override~
            WRITE_SHORT 0x244 0
            WRITE_SHORT 0x246 0x4000 + ~%d5_tempu%~ // changes kit
            LPF ADD_CRE_EFFECT INT_VAR opcode=171 target=1 timing=9 power=1 STR_VAR resource=~spcl152~ END
            LPF ADD_CRE_EFFECT INT_VAR opcode=171 target=1 timing=9 power=1 STR_VAR resource=~d5_temp1~ END
    END
  END
END

 

 

could be changed to this:

 

 

ACTION_IF FILE_EXISTS_IN_GAME ~d5_tempu.2da~ BEGIN
  COPY_EXISTING ~kitlist.2da~ ~override~
    COUNT_2DA_ROWS 8 "rows"
    FOR ( index = 31 ; index < rows ; index = index + 1 ) BEGIN
      READ_2DA_ENTRY "%index%" 5 8 "clab"
      PATCH_IF ("%clab%" STRING_EQUAL_CASE "d5_tempu" = 1) BEGIN
        SET "d5_tempu" = "%index%"-1
        SET "rows" = 0
      END
    END
  BUT_ONLY
END

ACTION_FOR_EACH char IN ~%tutu_var%branwe~ ~%tutu_var%branwe5~ ~o#bran~ ~o#bran25~ BEGIN
  ACTION_IF FILE_EXISTS_IN_GAME ~%char%.cre~ BEGIN
    COPY_EXISTING ~%char%.cre~ ~override~
      WRITE_BYTE 0x0234 1 //sets level to 1
      WRITE_BYTE 0x0235 1
      WRITE_BYTE 0x0236 1
      WRITE_BYTE 0x273 8 // sets class
      WRITE_BYTE 0x0066 10
      WRITE_BYTE 0x006a 5
      WRITE_SHORT 0x0024 12
      WRITE_SHORT 0x0026 12
      READ_BYTE 0x11 rdual
      WRITE_BYTE 0x11 (rdual BAND 0b11111110) // uncheck ranger dual-class flag
      READ_BYTE 0x10 dual
      WRITE_BYTE 0x10 (dual BAND 0b00000111) // uncheck other dual-class flags
      PATCH_IF NOT FILE_EXISTS_IN_GAME ~d5_profs.d5~ BEGIN
        LPF DELETE_EFFECT INT_VAR match_opcode = 233 END
        SET_BG2_PROFICIENCY 107 1
        SET_BG2_PROFICIENCY 101 1
        SET_BG2_PROFICIENCY 97 2
      END
      PATCH_IF FILE_EXISTS_IN_GAME ~d5_tempu.2da~ BEGIN
        WRITE_SHORT 0x244 0
        WRITE_SHORT 0x246 0x4000 + ~%d5_tempu%~ // changes kit
        LPF ADD_CRE_EFFECT INT_VAR opcode=171 target=1 timing=9 power=1 STR_VAR resource=~spcl152~ END
        LPF ADD_CRE_EFFECT INT_VAR opcode=171 target=1 timing=9 power=1 STR_VAR resource=~d5_temp1~ END
      END
    BUT_ONLY
  END
END

 

 

 

notice that it does exactly the same thing but copies every modified file just once, which makes the code less confusing and the mod will install faster. Just a suggestion, feel free to ignore it.

@ K4thos, just to understand what your proposed code for EET does - (hopefully I completely misunderstand it)

- You take a creature added by a mod, in this case o#bran (appearing in BG2 part)

- You set her level for first class at 0x234 to 1

- You change her kit assignment

- You remove effects added by the original mod and put in effects not intended by the mod

 

I am sure, that I make some error here in my interpretation, I am just not sure which.

Link to comment

@ K4thos, just to understand what your proposed code for EET does - (hopefully I completely misunderstand it)

1- You take a creature added by a mod, in this case o#bran (appearing in BG2 part)

2- You set her level for first class at 0x234 to 1

3- You change her kit assignment

4- You remove effects added by the original mod and put in effects not intended by the mod

 

I am sure, that I make some error here in my interpretation, I am just not sure which.

You might not notice it, but the original code kinda did the same thing. As this is a mod that applies a new kit to the NPC, you need to remove the old, aka effects that it might have so the new ones can be applied without the old one still haunting you. Just check the first spoilers.

1. And ?

2. That's usually the best way to ensure that the player can set the proficiency etc after level 1. And in most cases it also fixes the save throws, and other things ... when you level up. This is in BG2, so the char will level up automatically ... well after the player gets the char, and levels them up, as they are well over the 5000 xp that any xptable ruleset might need to level them up from 1.

3. That's what you do with mods like this.

4. Yeah... as it's not the old kit anymore, but a new one.

 

It's very much like the Level 1 NPCs, but to EE games and with far more limitations. But you hate that mod... so what, it's not like everyone else does. After all it brings more replay-ability to the 15 year old game.

No one is updating the Level 1 NPCs .. cause it's quite complicated for most of us.

Edited by Jarno Mikkola
Link to comment

 

@ K4thos, just to understand what your proposed code for EET does - (hopefully I completely misunderstand it)

1- You take a creature added by a mod, in this case o#bran (appearing in BG2 part)

2- You set her level for first class at 0x234 to 1

3- You change her kit assignment

4- You remove effects added by the original mod and put in effects not intended by the mod

 

I am sure, that I make some error here in my interpretation, I am just not sure which.

You might not notice it, but the original code kinda did the same thing. As this is a mod that applies a new kit to the NPC, you need to remove the old, aka effects that it might have so the new ones can be applied without the old one still haunting you. Just check the first spoilers.

1. And ?

2. That's usually the best way to ensure that the player can set the proficiency etc after level 1. And in most cases it also fixes the save throws, and other things ... when you level up. This is in BG2, so the char will level up automatically ... well after the player gets the char, and levels them up, as they are well over the 5000 xp that any xptable ruleset might need to level them up from 1.

3. That's what you do with mods like this.

4. Yeah... as it's not the old kit anymore, but a new one.

 

It's very much like the Level 1 NPCs, but to EE games and with far more limitations. But you hate that mod... so what, it's not like everyone else does. After all it brings more replay-ability to the 15 year old game.

No one is updating the Level 1 NPCs .. cause it's quite complicated for most of us.

 

Hey, I do not hate mods...some mods have side effects not intended by the author - like changing mod-added creatures into something else. Branwen may not be the best example here, but there are mod characters that are very much depending on their stats, effects, abbilities and kits to work within their own scripts and plots - take Tsujatha, Longer Road Irenicus, Tiax, Ajantis etc.

Of course its a players choice to do what they want - if not by mod they can tweak in shadowkeeper or NI. Just if you mod another modders resources you should advertise that and also take all the responsibility to handle the complaints if that mod character does no longer work within its own quests.

 

PS - I was not critisizing any mod - I was just asking some questions for understanding.

Thank you for answering them.

Edited by Roxanne
Link to comment

Branwen may not be the best example here, but there are mod characters that are very much depending on their stats, effects, abilities and kits to work within their own scripts and plots - take ... Longer Road Irenicus

The abilities and stats are important for the re-kitted characters too. Say, is there a specific reason why LR Irenicus could not be one of the 8 specialist wizards ? He has the stats for most of them, or even a Sorcerer. The others are also likely going to have similar things... say Tiax class, why not give him a kit too... rat catcher, or something to do with Cyrics clerics, cause in my opinion he is not wise enough to actually be a real cleric.. these are small tweaks that a mod like the NPC_EE can do, without making any of them too OP.

The ShadowKeeper and NI usage has the damaging effect that actually if you use them, the character is likely to going to get a head more than if its class/kit is set by a mod... the reason being that you might not want to reduce the 2 extra hitpoint, notice them and so forth... the whole process is actually very work intense. But if it's done by a mod... you pretty much have to do a good job or your mod get's the OP flag.

 

I give the explanation so you can go and proceed with the bug checking and reporting them here and elsewhere. Yes, this is me: bi.gifAnd respect.

Edited by Jarno Mikkola
Link to comment

 

Branwen may not be the best example here, but there are mod characters that are very much depending on their stats, effects, abilities and kits to work within their own scripts and plots - take ... Longer Road Irenicus

The abilities and stats are important for the re-kitted characters too. Say, is there a specific reason why LR Irenicus could not be one of the 8 specialist wizards ? He has the stats for most of them, or even a Sorcerer. The others are also likely going to have similar things... say Tiax class, why not give him a kit too... rat catcher, or something to do with Cyrics clerics, cause in my opinion he is not wise enough to actually be a real cleric.. these are small tweaks that a mod like the NPC_EE can do, without making any of them too OP.

The ShadowKeeper and NI usage has the damaging effect that actually if you use them, the character is likely to going to get a head more than if its class/kit is set by a mod... the reason being that you might not want to reduce the 2 extra hitpoint, notice them and so forth... the whole process is actually very work intense. But if it's done by a mod... you pretty much have to do a good job or your mod get's the OP flag.

 

I give the explanation so you can go and proceed with the bug checking and reporting them here and elsewhere. Yes, this is me: bi.gifAnd respect.

 

The questions I had were not even related to any existing mod but were focussed on some code K4thos was suggesting for an EET conversion...so you are (intenionally?) miles off from the topic.

Link to comment

Roxanne, this has nothing to do with EET, this is a mod all its own. K4thos was just helping me make it fully compatible with the naming convention for BG1 game assets used by EET.

 

As for what this is does: it enables the player to change things in the game. Just like any mod. Including yours. This particular mod is meant to simulate what a lot of people do with ShadowKeeper: change the class or kit of NPCs who join the party. It's more limited than ShadowKeeper, but somewhat more convenient.

 

So, if you want to declare war on mods or tools that change content of other mods, please start with ShadowKeeper. And then move on to Level1NPCs, and Divine Remix and Rogue Rebalancing and Item Revisions and SCS. And come after me when you are finished with those campaigns. ;)

Edited by subtledoctor
Link to comment

I suggest noting in the NPC_EE readme that changing the class/kit of a mod NPC might cause problems if that NPC has a custom script that was written for the original class/kit. I'm not sure how many such mod NPCs are affected by NPC_EE (it requires manual coding, I guess, judging by the snippet above) ... so perhaps this note can be tailored to specific mod NPCs, or alternatively, specific mod NPCs that have such custom scripts can be excluded from NPC_EE.

Link to comment
Pretty much every EXTEND_TOP like the one above for BG2 NPCs is not compatible with a game started in ToB because you only modify non-ToB variants of Override scripts.

This report still hasn't been resolved in the latest release. Also I forgot to inform you about override scripts renaming in EET (although mentioned it in your other mods). Since you are expanding override scripts also in creatures added by mods I'd suggest doing it like this instead of assigning additional variables:

  READ_ASCII 0x248 "script"
  DEFINE_ASSOCIATIVE_ARRAY table_override BEGIN ~%script%~ => ~dummy~ END

and than replace every instance of code that expands scripts, for example:

ACTION_IF FILE_EXISTS_IN_GAME ~coran.bcs~ BEGIN
    EXTEND_BOTTOM ~coran.bcs~ ~npc_ee/npcs/coran/coran_bard.baf~
END

with this:

ACTION_PHP_EACH table_override AS script => dummy BEGIN
    EXTEND_BOTTOM ~%script%.bcs~ ~npc_ee/npcs/coran/coran_bard.baf~
END
ACTION_CLEAR_ARRAY table_override

Than you will be able to add whatever CRE files you like without worrying about attached override scripts.

 

-------

 

out of curiosity - what exactly is wrong with Level 1 NPCs that it can't be updated to EE? Nothing really changed in CRE format, so I can't imagine anything that would need EE engine related changes. Although I didn't check that mod, so maybe I'm missing something.

Edited by K4thos
Link to comment

out of curiosity - what exactly is wrong with Level 1 NPCs that it can't be updated to EE? Nothing really changed in CRE format, so I can't imagine anything that would need EE engine related changes. Although I didn't check that mod, so maybe I'm missing something.

Well, if you look at the code... it's humongous.

And it needs a new option to install to all the BG1EE and BG2EE and BG1:EE:SotD ... and who knows what. And the original authors have goone to ground. Miloch is probably busy with 1000 projects and so on and on. No one has really made a good headway with the NPC wish list either, other than the original authors that dropped out a long time ago. So the mod suffers from being in a limbo of no one taking the reigns.

Edited by Jarno Mikkola
Link to comment

I suggest noting in the NPC_EE readme that changing the class/kit of a mod NPC might cause problems if that NPC has a custom script that was written for the original class/kit. I'm not sure how many such mod NPCs are affected by NPC_EE (it requires manual coding, I guess, judging by the snippet above) ... so perhaps this note can be tailored to specific mod NPCs, or alternatively, specific mod NPCs that have such custom scripts can be excluded from NPC_EE.

The Readme already says that - this is just a tool and the use/mis-use is up to the player.

My questions were just for information and not *to declare war on mods or tools*, but just to see what to expect in the new EET environment.

Anyone is free to change their NPCs in the way they want and use them as they wish. Even NPCs depending on their scripts stats, equipment etc are not excluded, they will simply not work within their mod context anymore but they will work as the thralls the player wants them to be.

Link to comment

they will simply not work within their mod context anymore but they will work as the thralls the player wants them to be.

Meaning ? That sounds very much as "if Imoen is not a mage, I'll kill 90% of this mod content cause I just can." a thread. And not, "If Imoen is not a mage, so what, she'll still talk as if she was."(even though it doesn't really conceptually make a darn sense) -like every one of the other mods do. Cause they don't script idiot checks of the character classes but just checks if the person is in group, if the wished person is conceptually present(via death variable), in what ever incarnations they decide to be in today in this age.

 

Now, don't take that as a bad thing, I just ask for the meaning... I don't see you as evil... I think most of this is just misunderstanding.

Edited by Jarno Mikkola
Link to comment

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...