Jump to content

Grammarsalad

Modders
  • Posts

    664
  • Joined

  • Last visited

Posts posted by Grammarsalad

  1. Book casting is especially cool. I had planned to do a ritual thing where certain spells are able to be cast 'as a ritual' for priests and mages (and prob bards) if known but not currently memorized.

    I wanted to do it only with 'certain spells' because, as you point out, this can be abused if broadly applied (even if coding the thing would be easier). 

    Applying fatigue is a nice touch. I think I'll borrow that idea.

  2. Is there is a reason this version isn't pinned or linked in the pinned version? I see a mention of possible crash on exit. Is this version considered 'stable'?

    Trying to figure out if I should update from version 7.7.

  3. Update, it looks like it works, but I had to make a slight change. I know you said not to read the cols but it freaked out and so I just used some of the original code to make it work again. I'm going to go back and see if I can strip out what isn't necessary, but for now this works:

     

    ACTION_PHP_EACH clabz AS der_clab => der_levs BEGIN
      ACTION_IF (%der_levs% > 0) BEGIN
        OUTER_SET patch_row = 0
        COPY_EXISTING ~%der_clab%.2da~ ~override~
          PATCH_IF (FILE_CONTAINS_EVALUATED(~%der_clab%.2da~ ~SCRLCRFT~)) BEGIN
            // COUNT_2DA_COLS cols // ** don't bother counting cols
            READ_2DA_ENTRIES_NOW rows 2
            FOR (row = 0; row < rows; ++row) BEGIN
              FOR (col = 0; col < cols; ++col) BEGIN
                READ_2DA_ENTRY_FORMER rows row col ~row_title~
              PATCH_PRINT "What is %row_title%?"
              PATCH_IF (~%row_title%~ STRING_EQUAL_CASE ~SCRLCRFT~) BEGIN
                SET patch_row = row
              END
              END
            END
            PATCH_IF (patch_row > 0) BEGIN
              SET_2DA_ENTRY patch_row (%der_levs%) 2 ~GA_B_SCRIB~ //   b_scrib
            END
          END
        BUT_ONLY
      END
    END

     

  4. 7 hours ago, subtledoctor said:

    Ah that makes sense - append the row, then check the .ini before setting which level the GA_ should be at. In that case, try this:

    ACTION_PHP_EACH clabz AS der_clab => der_levs BEGIN
      ACTION_IF (%der_levs% > 0) BEGIN
        OUTER_SET patch_row = 0
        COPY_EXISTING ~%der_clab%.2da~ ~override~
          PATCH_IF (FILE_CONTAINS_EVALUATED(~%der_clab%.2da~ ~SCRLCRFT~)) BEGIN
            // COUNT_2DA_COLS cols // ** don't bother counting cols
            READ_2DA_ENTRIES_NOW rows 2
            FOR (row = 0; row < rows; ++row) BEGIN
              // FOR (col = 0; col < cols; ++col) BEGIN // don't need to check every column
              READ_2DA_ENTRY row 0 row_title
              PATCH_IF (~%row_title%~ STRING_EQUAL_CASE ~SCRLCRFT~) BEGIN
                SET patch_row = row
              END
            END
            PATCH_IF (patch_row > 0) BEGIN
              PATCH_PRINT "Row is %row% or %rows%. col is %col%. And line is %line%."
              SET_2DA_ENTRY patch_row (%der_levs%) 2 ~GA_B_SCRIB~ //   b_scrib
            END
          END
        BUT_ONLY
      END
    END

    Rationales:

    1. CLAB files can have crazy column counts on each row, so don't rely on it
    2. If for whatever reason the patch_row isn't identified, we don't want to use the variable value from the last iteration, so set it to 0 at the start of every PHP_EACH and set it to > 0 inside each CLAB patch, and only apply the change if it is > 0
    3. No need for S2ELater/S2ENow if you're only doing one patch
    4. I think the %der_levs% value should line up with the level number you want it to be, since the CLAB title column is col 0 and the level 1 column is col 1. But you might need to play around with that value in the patch

    I haven't tested that at all so YMMV.

    Awesome! Thanks!  I'll give it a try

  5. 14 minutes ago, subtledoctor said:

    Out of curiosity, why does it need to be in a particular row? Why not APPEND a whole new row? AFAIK the number of rows a CLAB table can process is functionally unlimited, and the column count doesn't even need to be consistent, so you can completely sidestep the "40 cols vs. 50 cols" problem. (I just always append rows with 50 columns.)

    Well, I'm specifying the level that the char gets the ability by ini (so that the player can change it). 

     

    I actually do append a new row earlier in the code(headed by "SCRLCRFT"). My original solution was to find that newly appended line (i.e. by the text SCRLCRFT) and append at that particular line. 

    In the php above, "der_levs" is taken from the ini for the level to be applied. 
     

    There is probably a better way to do it but I can't think of one atm. Any ideas?

  6. Hello.  I'm trying to add a special ability to a particular row at a particular level that is specified in an ini.  

    I have no problem getting the code to add the GA_ ability at the designated level, but it is not consistently adding the ability to the specified row.  That is, it seems to add the ability to the correct line where the clab goes up to level 50, but adds the ability to the first line (the "ABILITY1" line) when the clab goes up to level 40.  I don't quite have my head wrapped around FOR loops, so I am not quite sure what is the issue. Here is the relevant code: 

     

    ACTION_PHP_EACH clabz AS der_clab => der_levs BEGIN
     ACTION_IF (%der_levs% > 0) BEGIN
      COPY_EXISTING ~%der_clab%.2da~ ~override~
          PATCH_IF (FILE_CONTAINS_EVALUATED(~%der_clab%.2da~ ~SCRLCRFT~)) BEGIN
                COUNT_2DA_COLS cols
                READ_2DA_ENTRIES_NOW rows cols
                FOR (row = 0; row < rows; ++row) BEGIN
                  FOR (col = 0; col < cols; ++col) BEGIN
                      READ_2DA_ENTRY_FORMER rows row col ~line~
                         PATCH_IF (~%line%~ STRING_EQUAL_CASE ~SCRLCRFT~) BEGIN
                            PATCH_PRINT "Row is %row% or %rows%. col is %col%. And line is %line%."
                            SET_2DA_ENTRY_LATER ~s2el_mng~ (%row% +3) (%der_levs% - 1) GA_B_SCRIB //   b_scrib
                            SET_2DA_ENTRIES_NOW s2el_mng 1
                         END //Scroll line
                  END //for
                END  //for
          END
          BUT_ONLY
     END
    END

    What I am doing is beginning the line with "SCRLCRFT" (i.e. where you would normally see "ABILITYx") and my plan is to add to that particular line.  As you can see, I am "adding 3" to the row num because that worked when I first tested it (but, again, just with clabs that go up to level 50). 

    I'm not sure what I'm doing wrong...

     

  7. 23 hours ago, Graion Dilach said:

    because the random item will not be evaulated inside the shop inventory

    Oh, that's too bad. 

     

    But, 

    23 hours ago, Graion Dilach said:

    You can probably make a Pandora's Priest Scroll out from this

    lol, one door closes and another opens.


    Thanks

  8. On 8/11/2022 at 12:47 PM, Graion Dilach said:

    On EEs, add a new line to rndtres.2da for your intermediary item and add it to the monsters you want it to carry. This allows that item to be randomized to what you want. Also see https://gibberlings3.github.io/iesdp/files/2da/2da_bgee/rndtres.htm. Note that this doesn't work well in shops/bags of holding though. This debuted with IWD(EE).

    There's also the other rnd 2DAs, but those are more hardcoded and I wouldn't suggest messing with those ones.

    Sorry, so when you say that this doesn't work well in shops, are you saying that I definitely shouldn't use this to randomize items sold in shops, or that there are things i should be careful about? If the latter, could you share? 

  9. On 8/11/2022 at 11:54 AM, subtledoctor said:

    I agree with you in substance, I just don't see why the same result cannot be achieved by simply designating Stinking Cloud and Earthquake as knockdowns

    The main issue here that I can think of is undead. Undead don't breathe and shouldn't be affected by stinking cloud. But, corporeal undead at least should be knocked down by an earthquake.

  10. 3 hours ago, Graion Dilach said:

    On EEs, add a new line to rndtres.2da for your intermediary item and add it to the monsters you want it to carry. This allows that item to be randomized to what you want. Also see https://gibberlings3.github.io/iesdp/files/2da/2da_bgee/rndtres.htm. Note that this doesn't work well in shops/bags of holding though. This debuted with IWD(EE).

    There's also the other rnd 2DAs, but those are more hardcoded and I wouldn't suggest messing with those ones.

    Awesome! Thanks

  11. It can be something like, 
    "if it sells potion of healing, then it should sell at least level 1 scrolls. If it sells (idk) a protection scroll against undead, then it should sell 'good' spells." Something like that. 

  12. On 8/2/2022 at 9:48 PM, Endarire said:

    High Hedge and Sorcerous Sundries could still sell divine scrolls.  Remember that characters would sell things to vendors they didn't already have.  Insect swarm isn't specifically Clerical, but is plausibly stocked by temples.

    I'm going to be doing something more general (which allows me to capture mod added stores and has a more general application).  You will be happy to know that this will be EET compatible right out of the gate.  

    What I need is suggestions about what other sort of items would be appropriate for what kind of scrolls.  So, right now I have a (very general) thing where I would add level 1 scrolls to stores that also sell the potion of healing (the weakest version). 

    So, that's the question: what specific item should be sold alongside scrolls of a given type? 

  13. On 7/26/2022 at 10:34 AM, DavidW said:

    Here's a function that should work:

    DEFINE_PATCH_FUNCTION item_in_store
    	STR_VAR item=""
    	RET value
    BEGIN
    	value=0
    	GET_OFFSET_ARRAY itm_arr STO_V10_ITEMS_SOLD
    	PHP_EACH itm_arr AS itm_ind=>itm_off BEGIN
    		PATCH_IF !value BEGIN
    		READ_ASCII itm_off resref 
    			value = ("%resref%" STR_EQ "%item%")? 1: 0
    		END
    	END
    END

    Originally I coded a two-step one that checked for the string first, but that's overkill given how fast it is just to check stores this way.

    Awesome! Thanks, Dave

  14. Okay, question: how would I check a store for a particular item.  This is what I have right now: 

     

    //let's create a list of relevant vendors:
    COPY ~%folder%/lib/lists/store_list.tpa~ ~override~
    
    COPY_EXISTING_REGEXP GLOB ~^.+\.sto$~ ~override~ // Load all stores BEG CAMCODE:
      READ_BYTE 0x0008 type //Spell type
         PATCH_IF type = 3 OR 2 BEGIN   //temple or inn type
         	READ_BYTE 0x10 "flags" //ELSE 0
                PATCH_IF (("%flags%" BAND 0b00100001) = 0b00100001) BEGIN // if cures available and sells stuff; also filters out invalid files
                 INNER_PATCH_SAVE store_name ~%SOURCE_RES%~ BEGIN  END
                 INNER_ACTION BEGIN
    		COPY_EXISTING ~store_list.tpa~ ~override~
    		REPLACE_TEXTUALLY "BEGIN" "BEGIN
    %store_name% => ~church~"
                 END
                END
                PATCH_IF (("%flags%" BAND 0b00100011) = 0b000000011) BEGIN // if buys and sells
                READ_LONG 0x18 "buy_mark"
                  PATCH_IF buy_mark > 0 BEGIN
                  READ_LONG 	0x34	it_off			// items Offset
    	      READ_LONG	        0x38	it_num			// Number of items
    
    
                     INNER_PATCH_SAVE store_name ~%SOURCE_RES%~ BEGIN  END
                     INNER_ACTION BEGIN
    		  COPY_EXISTING ~store_list.tpa~ ~override~
    		  REPLACE_TEXTUALLY "BEGIN" "BEGIN
    %store_name% => ~inn~"
                     END
    
                  END
                END
         END
         BUT_ONLY

    Basically, I'm creating a list to use later. In the second check, I have these two: 

    Quote

    READ_LONG     0x34    it_off            // items Offset
    READ_LONG            0x38    it_num            // Number of items

    I just have these there because I know they have something to do with the items actually sold by the store.  What I would like to do is check each item, and if it, say, has a filename "SCRLPET"*, then I would add the store to a particular list. Etc.  

    But, I'm not sure how to actually check for that... It feels 'loopy', but not sure how to do the actual check.  Any advice? 

    * the stone to flesh scroll. Etc.

  15. 2 hours ago, subtledoctor said:

    I would have whatsername, next to the Friendly Arm Inn, sell druid scrolls with a wink and a nod. 

    Maybe also the Shadow Druids in Cloakwood Forest?

    Thanks. That makes sense (I don't quite remember whatshername, but definitely the shadow druids)

  16. Hello party people.  I have a functional mod that creates priest scrolls for the game.  I'm kinda proud of it; it adds scrolls for mod-added spells,  it creates any scrolls not in the game, adds a generic icon for the scroll if none is found in game (it also copies over all existing icons that are only in...BGEE iirc? Maybe it's bg2ee.  It's been a while. Anyway, it copies them over if needed and then references them in the scroll file.)  

    One thing I'm a bit stuck on is scroll placement.  Again, I want to do this in a (more or less) dynamic way. 

    I have (and/or am creating) lists that differentiate universal spell scrolls, druid exclusive spell scrolls, and cleric exclusive spell scrolls. Same with scroll levels.  

    I also have a list of temples that sell items.  I was thinking that if game_is BGEE, then temples can sell scrolls levels 1-3 or so.  I might go a little more fine grained, and do it by the actual temple.  For example, it seems unlikely that the temple of helm would sell druid scrolls (actually, I'm not sure what to do, exactly, with druid scrolls...) 

    So, long story short, I'm looking for ideas on how best to distribute the scrolls in game. Any ideas?

  17. On 6/26/2022 at 2:15 PM, subtledoctor said:

    Honestly I think that you should come up with a more concrete idea of what you want to do. Like, if you could sing a bard song from the stealth button then like all bard songs it would have a delayed effect, which you said you want to avoid. If you want a non-shadowdancer to be able to hide in plain sight… honestly you could just let them go invisible, which amounts to the same thing. (Tying the success to your stealth skill would be a bit tedious but totally doable.)

    I generally see more specific questions lead to more helpful answers. To answer your most recent specific question, I have no experience messing with buttons. I have seen a spell, made by @Grammarsalad, that summons an invisible creature which can script the caster to hide like a thief. It would be easy enough to put that in an innate ability; so maybe it would be easier to make a bard who can hide, than a thief who can sing. (Always good to step back and look at other route to your goal.)

    Oh yeah. It's actually pretty easy to do iirc. I have at least two spells that do think. Hold on.

     

    Here is the script. It could probably be improved but this could get you started:

     

    https://github.com/UnearthedArcana/B_Spells/blob/master/B_Spells/data/new_spells/ranger_1/B_CAMO.baf

  18. On 6/26/2022 at 2:15 PM, subtledoctor said:

    Honestly I think that you should come up with a more concrete idea of what you want to do. Like, if you could sing a bard song from the stealth button then like all bard songs it would have a delayed effect, which you said you want to avoid. If you want a non-shadowdancer to be able to hide in plain sight… honestly you could just let them go invisible, which amounts to the same thing. (Tying the success to your stealth skill would be a bit tedious but totally doable.)

    I generally see more specific questions lead to more helpful answers. To answer your most recent specific question, I have no experience messing with buttons. I have seen a spell, made by @Grammarsalad, that summons an invisible creature which can script the caster to hide like a thief. It would be easy enough to put that in an innate ability; so maybe it would be easier to make a bard who can hide, than a thief who can sing. (Always good to step back and look at other route to your goal.)

    Oh yeah. It's actually pretty easy to do iirc. I have at least two spells that do think. Hold on

×
×
  • Create New...