Two simultaneous ability decrease effects not applying reliably

Going back to the OP again, I’m having no problem reducing both abilities reliably.

Using ##dm_runscript

void bhStats(object oPC, object oNPC)
{
  SendMessageToPC(oPC, "Str=" + IntToString(GetAbilityScore(oNPC, ABILITY_STRENGTH)));
  SendMessageToPC(oPC, "Dex=" + IntToString(GetAbilityScore(oNPC, ABILITY_DEXTERITY)));
}

void main()
{
  object oPC  = GetFirstPC();
  object oNPC = GetObjectByTag("Fred");

  bhStats(oPC, oNPC);
  ApplyEffectToObject(DURATION_TYPE_PERMANENT, 
      SupernaturalEffect(EffectAbilityDecrease(ABILITY_STRENGTH, 3)), oNPC);
  ApplyEffectToObject(DURATION_TYPE_PERMANENT, 
      SupernaturalEffect(EffectAbilityDecrease(ABILITY_DEXTERITY, 1)), oNPC);
  bhStats(oPC, oNPC);
}

Implicitly, the object applying the effect is the module.

I take @Andarian 's point, too - I don’t think items are supposed to have action queues - but no command assignment is necessary in this case.

Yep, but if you have the item be the creator of the effect, you can use the item to remove all effects created by the item (if (GetEffectCreator(eEffect) == oItem) RemoveEffect(eEffect);). It’s a convenient pre-EE-effect-tagging method to make something apply and remove a set of effects.

The alternative to using AssignCommand is to make the inventory item apply the effects via a separate script using ExecuteScript. I’ve switched the restraints scripts to that method, to try and see if it works without the AssignCommands, but it’s made no difference.

There’s a bug report for the Dexterity decrease thing over here.

I’ve found something curious. Following up on Proleric’s lead, I put this in an area OnEnter script:

void DecreaseStats(object oPC)
{
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY, SupernaturalEffect(EffectAbilityDecrease(ABILITY_DEXTERITY, 5)), oPC, 5.0);
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY, SupernaturalEffect(EffectAbilityDecrease(ABILITY_STRENGTH, 5)), oPC, 5.0);

    DelayCommand(7.0, DecreaseStats(oPC));
}

… and called it on the PC at a 3 second delay.

The very first time the effects are applied, only the Strength decrease shows up. Every time after that, it’s both of them. Same thing when it’s in OnClientEnter - but inside an item’s OnActivateItem script, it doesn’t happen.

Putting the ability decreases directly into void main in the area’s OnEnter script (no delay) makes both of them apply. See the absence of a delay in @Proleric’s version, too. :thinking:

If the ApplyEffectToObjects that are directly in void main are delayed via DelayCommand, the first Dexterity decrease doesn’t show up anymore again.

Can you guys check whether delaying makes a difference for you? Also - why on earth are the roles reversed and the Dexterity decrease shows up while the Strength decrease doesn’t, in @squattingmonk’s case?

what is happening here

:question: :question: :question:

Have you tried making this a new spell-like effect [give it a spells.2da entry] and making it available as an item property? You could then manipulate the effect by SpellID, rather than by worrying about if the item is the creator. Not sure if that would help clear up some of the weird behavior you’re seeing, but it might be worth a shot. You could also have a custom TLK entry for when the item is used that is appropriately flavory, too.

-Dave

1 Like

It does say that, yes. But it doesn’t bear out in testing. Assigned commands fire immediately, without regard for the action queue. Consider the following code on a placeable:

void main()
{
    object oPC = GetLastUsedBy();
    AssignCommand(oPC, ActionWait(6.0));
    AssignCommand(oPC, ActionDoCommand(SpeakString("Test string 1")));
    AssignCommand(oPC, SpeakString("Test string 2"));
    DelayCommand(3.0, AssignCommand(oPC, SpeakString("Test string 3")));
}

Event though “Test string 2” is assigned to the PC after “Test string 1”, it is displayed immediately while “Test string 1” is only displayed after the ActionWait() command finishes. To show that the command is not just being inserted at the front of the queue, we delay assigning “Test string 3”, which the PC speaks before the ActionWait() command finishes and without clearing the action queue.

2 Likes