Skip to content

General mod Questions thread

16466686970

Comments

  • The user and all related content has been deleted.
  • argent77argent77 Member Posts: 3,478
    Are you certain the conditions are actually met in all three instances, including sc_kit_class?

    Apart from that, you could replace "~%mc_kits%~ STRING_CONTAINS_REGEXP ~fc~ = 0" by "INDEX(~fc~ ~%mc_kits%~) >= 0" to see if it has any effect.

    Btw, there is no need to wrap numeric variables in %-signs. According to WeiDU documentation this is just one of several ways for putting quotes around text. It works just as well without quotes.
  • lefreutlefreut Member Posts: 1,462
    I have found that I can use Unlock("Container1") in a DLG so that a NPC can unlock a chest for charname. But it will still trigger the guards when you take the object inside it.

    Is there a way to also remove the trap script that calls the guard or reset the 'Container is trapped' flag?
  • kjeronkjeron Member Posts: 2,368
    lefreut wrote: »
    I have found that I can use Unlock("Container1") in a DLG so that a NPC can unlock a chest for charname. But it will still trigger the guards when you take the object inside it.

    Is there a way to also remove the trap script that calls the guard or reset the 'Container is trapped' flag?
    ActionOverride("Container1",RemoveTraps(Myself))
    Should work as long as the trap isn't flagged to reset (I don't think most theft-related traps are though).
  • lefreutlefreut Member Posts: 1,462
    Yay it works \o/

    I guess it shows that I will have a hard time learning how to mod this game (and that I will ask more stupid question in the future, sorry), because I have seen RemoveTraps but it says 'the active creature attempt to disarm the specified trap' so I conclude that it was not useful in my case. I would never have guess that you can use it like this with ActionOverride and Myself.
  • _Luke__Luke_ Member, Mobile Tester Posts: 1,535
    kjeron wrote: »
    Equivalent no. That modified quarterstaff would not receive any damage bonuses (Strength, Bless, Bracers, etc...),...

    Yeah, this is true regardless of the value of BIT0 – 'add strength bonus' (it's probably worth mentioning that these bonuses are listed on the Character Record/Inventory Screen...)

    Separately, what does it happen if my damage output is, say, -1–2 (i.e., 'minus' 1 – 2)?
    Is negative/null damage registered as 0?
  • kjeronkjeron Member Posts: 2,368
    Luke93 wrote: »
    Separately, what does it happen if my damage output is, say, -1–2 (i.e., 'minus' 1 – 2)? Is negative/null damage registered as 0?
    For weapon damage, the minimum is 1, unless it's setup to not deal any damage, then it can deal 0. Note this minimum is calculated before percentage modifiers (resistances/difficulty/op332).

    For direct opcode 12 usage, 'parameter1' can use negative numbers, and increase the targets hit points as expected.
    Dicenumber cannot be negative, as the whole field is not used, it only reads values 0 - 255.
    Dicesize cannot be negative either, but because negative value defaults to '1'.
    So a damage range such as (-16 to -20) must be specified as ( -21 + 1d5).
  • yoboseyoyoboseyo Member Posts: 8
    edited November 2019
    How do you make paladins and rangers cast at their level, and not the level after they get their first spell? How does the game control this?

    BTW, opcode 191 has no effect
    Post edited by yoboseyo on
  • _Luke__Luke_ Member, Mobile Tester Posts: 1,535
    edited November 2019
    kjeron wrote: »
    Luke93 wrote: »
    Separately, what does it happen if my damage output is, say, -1–2 (i.e., 'minus' 1 – 2)? Is negative/null damage registered as 0?
    For weapon damage, the minimum is 1, unless it's setup not to deal any damage, then it can deal 0. Note this minimum is calculated before percentage modifiers (resistances/difficulty/op332).

    Yes, it's about weapon damage.
    Case scenario: suppose you want to penalize the damage dealt by the off-hand weapon via setting DAMAGE_LEFT to "-2" in STYLBONU.2da => if the character in question doesn't have enough Strength, it might end up with a damage output of (-1 to +2) upon dual-wielding daggers.
    If that's the case, then the minimum will never drop below 1 (and will never deal negative or null damage/heal the target), right?
  • kjeronkjeron Member Posts: 2,368
    Luke93 wrote: »
    Yes, it's about weapon damage.
    Case scenario: suppose you want to penalize the damage dealt by the off-hand weapon via editing DAMAGE_LEFT in STYLBONU.2da => if the character in question doesn't have enough Strength, it might end up with a damage output of (-1 to +2) upon dual-wielding daggers.
    If that's the case, then the minimum will never drop below 1 (and will never deal negative damage/heal the target), right?
    Correct. The damage will be 1.
    It will then be modified by difficulty, damage resistance, and op332, the last two of which can turn it negative if setup to do so (though I don't think the base game has any such content).
  • The user and all related content has been deleted.
  • kjeronkjeron Member Posts: 2,368
    Their base casting level is adjusted by a hardcoded amount.
    Rangers in BG have a -7 penalty to priest casting level.
    Paladins in BG have a -8 penalty to priest casting level.
    IWDEE has no penalty to either.

    Not sure why op191 isn't working for you, works fine on my end.
  • [Deleted User][Deleted User] Posts: 0
    edited November 2019
    The user and all related content has been deleted.
  • _Luke__Luke_ Member, Mobile Tester Posts: 1,535
    kjeron wrote: »
    Correct. The damage will be 1.
    It will then be modified by difficulty, damage resistance, and op332, the last two of which can turn it negative if setup to do so (though I don't think the base game has any such content).

    What do you mean exactly by "if setup to do so"? Could you provide an example?
    I mean, if a creature has 'damage resistance' > 100%, then it'll be healed in any case (even if your damage output is strictly positive...)
  • kjeronkjeron Member Posts: 2,368
    Luke93 wrote: »
    I mean, if a creature has 'damage resistance' > 100%, then it'll be healed in any case (even if your damage output is strictly positive...)
    That was more for op332, which is only used to increase damage in the base game, but it can also be given negative values. Every +100 increases damage by 100% of the base, while every -100 reduces damage by 100% of the base. An op332 with a value of -200 would invert the damage amount 1 for 1:
    10 - 10 * 200% = -10
  • yoboseyoyoboseyo Member Posts: 8
    I may have mistakenly installed a mod that disabled quickslot items on Simulacrum clones, or it was patched by the game itself. Is there a way to enable it?
  • The user and all related content has been deleted.
  • yoboseyoyoboseyo Member Posts: 8
    yoboseyo wrote: »
    I may have mistakenly installed a mod that disabled quickslot items on Simulacrum clones, or it was patched by the game itself. Is there a way to enable it?

    You could try editing simulacr.spl in NI or DLTCEP, remove anything involving opcode 144

    Thanks! Looks like that's it. since mods can do it, I figure had to be an override file but i couldn't find anything that points to it. Maybe the project image opcode is hardcoded to the projimag/simulacr filenames.

    Another question, do the thieving skills and turn undead exist as editable spells?
  • kjeronkjeron Member Posts: 2,368
    yoboseyo wrote: »
    Thanks! Looks like that's it. since mods can do it, I figure had to be an override file but i couldn't find anything that points to it. Maybe the project image opcode is hardcoded to the projimag/simulacr filenames.
    Correct, the other is MISLEAD.spl, but they do not cover everything.
    yoboseyo wrote: »
    Another question, do the thieving skills and turn undead exist as editable spells?
    Nope, only Bardsong/Shamandance.
  • yoboseyoyoboseyo Member Posts: 8
    edited November 2019
    Hey, just after some help editing the ai. I'm using the SCSII ease of use AI. Just wondering what file I have to edit to mod it
    Post edited by yoboseyo on
  • _Luke__Luke_ Member, Mobile Tester Posts: 1,535
    edited November 2019
    @Bubb

    Sorry to bother again, but I've got some other questions about AttackReevaluate():
    • Is it true that 'ActionListEmpty()' will always return FALSE if a creature is executing an 'AttackReevaluate()' action?
    • How can I detect if 'ReevaluationPeriod' is up? Unlike 'AttackOneRound()', the combat log doesn't provide any feedback... For instance, let's compare a 'ReevaluationPeriod' of 15 and a 'ReevaluationPeriod' of 600...
  • _Luke__Luke_ Member, Mobile Tester Posts: 1,535
    edited November 2019
    Bubb wrote: »
    @Luke93: Because that target switching case only occurs if the creature is in "chase mode". The kobold won't be moving if it is using a ranged weapon + can still see its target, and thus it won't be "chasing" the target like it would be if it was using melee.

    Fun fact: if you replace 'NearestEnemyOf(Myself)', 'SecondNearestEnemyOf(Myself)', and so forth with object specifiers (e.g., [PC], SecondNearest([PC]), [EVILCUTOFF.PLANT] and so forth), then a ranged creature will switch targets even if it's NOT in "chase mode"...
    Post edited by _Luke_ on
  • BubbBubb Member Posts: 1,005
    edited November 2019
    @Luke93: I'm not ignoring you, just trying to get a good grasp of what I'm saying before I post. This is what I have, I'm going to describe the mechanics in internal engine terms first, and then I'll translate after. This first part is mostly for me / future me:
    The basic mechanism is that when the action is first started up, it CAIObjectType::Decode()'s the object parameter, and stores this decoded version in actee2.

    If the object wasn't an object selector, this decode will store the specific actor that satisfies the object in actee2->Instance. This actor target is "locked in" until:
    • The target dies or becomes otherwise "hard" untargettable, (I.E. doesn't exist)
    • The creature has been chasing target for the reeval param period

    In both of these cases the engine redecodes actee1, "refreshing" actee2->Instance.

    Object selectors are wonky because CAIObjectType::Decode() doesn't do anything with them; it skips over execution if m_SpecialCase[0] == 0. Object selectors kick in when they are directly evaluated, through something like CGameAIBase::GetTargetShareType(), which AttackReevaluate() uses to extract the target from actee2 every update.

    Note that if actee2->Instance is filled, CGameAIBase::GetTargetShareType() simply kicks it back.

    Translation:
    • Conventional object targets are locked in until a reeval has been triggered by chase code, (chasing for ReevaluationPeriod), or the target died / got removed from the game.
    • Object selectors constantly reevaluate the target, not being affected by the ReevaluationPeriod at all.
    • The only natural end condition for the action is if it can't find any valid objects to attack, either initially, or after a reeval has been triggered.

    So,
    Luke93 wrote: »
    Is it true that 'ActionListEmpty()' will always return FALSE if a creature is executing an 'AttackReevaluate()' action?

    That is correct. ActionListEmpty() only returns TRUE when the creature isn't executing an action.
    Luke93 wrote: »
    How can I detect if 'ReevaluationPeriod' is up? Unlike 'AttackOneRound()', the combat log doesn't provide any feedback... For instance, let's compare a 'ReevaluationPeriod' of 15 and a 'ReevaluationPeriod' of 600...

    You can't short of maintaining a separate timer using SetGlobalTimer() and GlobalTimerExpired(). Note that only chase time is considered towards ReevaluationPeriod, so it really won't do you any good to try to track it; you can't accurately.

    If you have any questions about a particular script using AttackReevaluate() I'll be happy to explain exactly why it's doing something unexpected.
  • _Luke__Luke_ Member, Mobile Tester Posts: 1,535
    kjeron wrote: »
    That was more for op332, which is only used to increase damage in the base game, but it can also be given negative values. Every +100 increases damage by 100% of the base, while every -100 reduces damage by 100% of the base. An op332 with a value of -200 would invert the damage amount 1 for 1:
    10 - 10 * 200% = -10

    But again, this would be an issue in any case, even with a strictly positive damage output. Unless I'm missing something, nothing changes if your damage output is, say, "-1 to +2" or "+56 to +62": you will always end up healing your target if you're affected by opcode #332 ('param1' = "-200" or something like that...)

    So, to sum up: you should never set 'param1' of opcode #332 to such negative values...
  • kjeronkjeron Member Posts: 2,368
    Luke93 wrote: »
    So, to sum up: you should never set 'param1' of opcode #332 to such negative values...
    Unless inverting damage is exactly what you're trying to do.
  • _Luke__Luke_ Member, Mobile Tester Posts: 1,535
    @Bubb

    Thanks for providing further details about this topic.

    Well, since I was looking for a way to get creatures (both melee and ranged) to switch targets without making them run around, the most important news for me is the following one:
    • Object selectors constantly reevaluate the target, not being affected by the 'ReevaluationPeriod' at all.

    So, basically, I just need to use object selectors instead of 'NearestEnemyOf(Myself)' and co. and that's it... A noob question though (just to be on the safe side): for a creature whose 'allegiance' is, say, [ENEMY], what's the difference between 'NearestEnemyOf(Myself)' and [GOODCUTOFF]? None, right?

    Moreover:
    I made some testing and it seems that 'AttackOneRound()' and 'AttackReevaluate()' behave the same when using object selectors (i.e., 'ReevaluationPeriod' doesn't play any role). Is that true? If so, is there really a difference between 'AttackOneRound()' and 'AttackReevaluate()' when using object selectors? Maybe the behavior with respect to 'ActionListEmpty()'?
  • BubbBubb Member Posts: 1,005
    edited November 2019
    @Luke93:
    Luke93 wrote: »
    ...for a creature whose 'allegiance' is, say, [ENEMY], what's the difference between 'NearestEnemyOf(Myself)' and [GOODCUTOFF]? None, right?

    That is correct, they eval to the same thing. Here's how NearestEnemyOf() decides 'enemy' EA:
    if (curType.m_EnemyAlly > 30) // GOODCUTOFF
    {
        if (curType.m_EnemyAlly >= 200) // EVILCUTOFF
        {
            return 30 // GOODCUTOFF
        }
        else
        {
            return 0 // NOONE
        }
    }
    else
    {
        return 200 // EVILCUTOFF
    }
    

    That is to say:
    1. EVILCUTOFF EA values attack GOODCUTOFF EA values
    2. GOODCUTOFF EA values attack EVILCUTOFF EA values
    3. The following don't consider anyone an 'enemy':
      31 NOTGOOD
      126 ANYTHING
      128 NEUTRAL
      199 NOTEVIL
      (This is based on the current object's EA. NEUTRAL is really the only valid listing here - as this is a referencing the creature's live type, which should never be a 'combined' EA).

    By the way, if you / anyone is wondering what exactly all the combined EAs include, here's a full listing:
    [ANYONE] =>
    1 INANIMATE
    2 PC
    3 FAMILIAR
    4 ALLY
    5 CONTROLLED
    6 CHARMED
    28 GOODBUTRED
    29 GOODBUTBLUE
    128 NEUTRAL
    201 EVILBUTGREEN
    202 EVILBUTBLUE
    255 ENEMY
    254 CHARMED_PC

    [GOODCUTOFF] =>
    1 INANIMATE
    2 PC
    3 FAMILIAR
    4 ALLY
    5 CONTROLLED
    6 CHARMED
    28 GOODBUTRED
    29 GOODBUTBLUE

    [NOTGOOD] =>
    128 NEUTRAL
    201 EVILBUTGREEN
    202 EVILBUTBLUE
    255 ENEMY
    254 CHARMED_PC

    [ANYTHING] =>
    1 INANIMATE
    2 PC
    3 FAMILIAR
    4 ALLY
    5 CONTROLLED
    6 CHARMED
    28 GOODBUTRED
    29 GOODBUTBLUE
    128 NEUTRAL
    201 EVILBUTGREEN
    202 EVILBUTBLUE
    255 ENEMY
    254 CHARMED_PC

    [NOTEVIL] =>
    1 INANIMATE
    2 PC
    3 FAMILIAR
    4 ALLY
    5 CONTROLLED
    6 CHARMED
    28 GOODBUTRED
    29 GOODBUTBLUE
    128 NEUTRAL

    [EVILCUTOFF] =>
    201 EVILBUTGREEN
    202 EVILBUTBLUE
    255 ENEMY
    254 CHARMED_PC
    Luke93 wrote: »
    I made some testing and it seems that 'AttackOneRound()' and 'AttackReevaluate()' behave the same when using object selectors (i.e., 'ReevaluationPeriod' doesn't play any role). Is that true? If so, is there really a difference between 'AttackOneRound()' and 'AttackReevaluate()' when using object selectors? Maybe the behavior with respect to 'ActionListEmpty()'?

    AttackOneRound() actually shares most of its code with AttackReevaluate(). In fact, it is AttackReevaluate() with an extra hardcoded bit that forces it to terminate after one round. So yes, unlike in AttackReevaluate(), ActionListEmpty() will return TRUE once a round is up – and unless you immediately reinstate AttackOneRound(), the creature won't continue attacking.
  • The user and all related content has been deleted.
  • OlvynChuruOlvynChuru Member Posts: 3,079
    @subtledoctor
    2) Same question about the CON loss when a familiar dies - where should I be looking if I want to mod that?

    When a familiar is created, an opcode 195 effect is automatically added to it. If you want familiars not to lower CON on death, you might be able to do it by giving the familiar's equipment either an effect that removes opcode 195, or an effect that grants protection from opcode 195 (the former is more likely to work, I think, but I haven't tested these).
  • The user and all related content has been deleted.
Sign In or Register to comment.