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.
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?
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).
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.
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?
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).
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?
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).
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.
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...)
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
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?
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?
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.
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...
@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"...
@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.
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.
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...
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()'?
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:
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.
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).
Comments
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.
Is there a way to also remove the trap script that calls the guard or reset the 'Container is trapped' flag?
Should work as long as the trap isn't flagged to reset (I don't think most theft-related traps are though).
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.
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?
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).
BTW, opcode 191 has no effect
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?
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).
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.
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...)
10 - 10 * 200% = -10
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?
Sorry to bother again, but I've got some other questions about AttackReevaluate():
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"...
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:
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:
So,
That is correct. ActionListEmpty() only returns TRUE when the creature isn't executing an action.
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.
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...
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:
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()'?
That is correct, they eval to the same thing. Here's how NearestEnemyOf() decides 'enemy' EA:
That is to say:
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:
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
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.
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).