Author Topic: Equippable Cursed Item  (Read 340 times)

Legacy_Blue Totoro

  • Newbie
  • *
  • Posts: 14
  • Karma: +0/-0
Equippable Cursed Item
« on: January 21, 2011, 07:35:10 am »


               Hello everybody. I'm looking for a script to attach to a module's "OnPlayerUnEquipItem" slot that searches to see if the removed item is a specific item, an amulet with the tag "cursednecklace" and immediately reequips it, or causes nothing to happen if it is not that amulet. This is the only cursed item in the entire module, so there is no conflict and no uneqip/equip loop that occurs when two cursed items are equipped in the same slot. Can anyone give me a script to put here to make this work?
               
               

               
            

Legacy_420

  • Sr. Member
  • ****
  • Posts: 370
  • Karma: +0/-0
Equippable Cursed Item
« Reply #1 on: January 21, 2011, 05:27:49 pm »


               Here is the default OnModuleUnEquip script (x2_mod_def_unequ) with the code you want added at the end:


//::///////////////////////////////////////////////
//:: Example XP2 OnItemEquipped
//:: x2_mod_def_unequ
//:: (c) 2003 Bioware Corp.
//:://////////////////////////////////////////////
/*
    Put into: OnUnEquip Event
*/
//:://////////////////////////////////////////////
//:: Created By: Georg Zoeller
//:: Created On: 2003-07-16
//:://////////////////////////////////////////////
//:: Modified By: Deva Winblood
//:: Modified On: April 15th, 2008
//:: Added Support for Mounted Archery Feat penalties
//:://////////////////////////////////////////////

#include "x2_inc_switches"
#include "x2_inc_intweapon"
#include "x3_inc_horse"

void main()
{
     object oItem = GetPCItemLastUnequipped();
     object oPC   = GetPCItemLastUnequippedBy();

    // -------------------------------------------------------------------------
    //  Intelligent Weapon System
    // -------------------------------------------------------------------------
    if (IPGetIsIntelligentWeapon(oItem))
    {
            IWSetIntelligentWeaponEquipped(oPC,OBJECT_INVALID);
            IWPlayRandomUnequipComment(oPC,oItem);
    }

    // -------------------------------------------------------------------------
    // Mounted benefits control
    // -------------------------------------------------------------------------
    if (GetWeaponRanged(oItem))
    {
        DeleteLocalInt(oPC,"bX3_M_ARCHERY");
        HORSE_SupportAdjustMountedArcheryPenalty(oPC);
    }

    // -------------------------------------------------------------------------
    // Generic Item Script Execution Code
    // If MODULE_SWITCH_EXECUTE_TAGBASED_SCRIPTS is set to TRUE on the module,
    // it will execute a script that has the same name as the item's tag
    // inside this script you can manage scripts for all events by checking against
    // GetUserDefinedItemEventNumber(). See x2_it_example.nss
    // -------------------------------------------------------------------------
    if (GetModuleSwitchValue(MODULE_SWITCH_ENABLE_TAGBASED_SCRIPTS) == TRUE)
    {
        SetUserDefinedItemEventNumber(X2_ITEM_EVENT_UNEQUIP);
        int nRet =   ExecuteScriptAndReturnInt(GetUserDefinedItemEventScriptName(oItem),OBJECT_SELF);
        if (nRet == X2_EXECUTE_SCRIPT_END)
        {
           return;
        }
    }

//Check for cursed amulet
if(GetTag(oItem) == "cursednecklace") AssignCommand(oPC, ActionEquipItem(oItem, INVENTORY_SLOT_NECK));
}

-420
               
               

               
            

Legacy_Blue Totoro

  • Newbie
  • *
  • Posts: 14
  • Karma: +0/-0
Equippable Cursed Item
« Reply #2 on: January 21, 2011, 07:45:19 pm »


               Great, thanks! This works perfectly.
               
               

               
            

Legacy_Krevett

  • Full Member
  • ***
  • Posts: 203
  • Karma: +0/-0
Equippable Cursed Item
« Reply #3 on: January 22, 2011, 01:55:48 pm »


               I'll post in the same subject because my question is about cursed items '<img'>
First i'll give you my scripts and the i'll explain the issue...
onequip script:
#include "inc_functions"
void main()
{
object oPC = GetPCItemLastEquippedBy();
object oItem = GetPCItemLastEquipped();
string sTag = GetTag(oItem);
////////////////////////////////////////////////////////////////////////////////
if (GetIsCursed(oItem)) SetLocalInt(oPC, "cursed", 1);
if (sTag == "grandeepee16") SetBerserk(oPC);
}

onunequip script:
#include "inc_functions"
void main()
{
object oPC = GetPCItemLastUnequippedBy();
object oItem = GetPCItemLastUnequipped();
////////////////////////////////////////////////////////////////////////////////
if (GetIsCursed(oPC) && GetIsCursed(oItem))
 {
 int nSlot = GetItemSlot(oItem);
 AssignCommand(oPC, ClearAllActions(TRUE));
 AssignCommand(oPC, ActionEquipItem(oItem, nSlot));
 AssignCommand(oPC, ActionSpeakString("Cet objet est maudit!"));
 DelayCommand(0.1, SetCommandable(FALSE, oPC));
 DelayCommand(2.0, SetCommandable(TRUE, oPC));
 }
}

onunacquire script:
#include "inc_functions"
void main()
{
object oPC = GetModuleItemLostBy();
object oItem = GetModuleItemLost();
////////////////////////////////////////////////////////////////////////////////
if (GetIsCursed(oPC) && GetIsCursed(oItem))
 {
 int nSlot = GetItemSlot(oItem);
 AssignCommand(oPC, ClearAllActions(TRUE));
 AssignCommand(oPC, ActionPickUpItem(oItem));
 AssignCommand(oPC, ActionEquipItem(oItem, nSlot));
 AssignCommand(oPC, ActionSpeakString("Cet objet est maudit!"));
 DelayCommand(0.1, SetCommandable(FALSE, oPC));
 DelayCommand(2.0, SetCommandable(TRUE, oPC));
 }
}

GetIsCursed, GetItemSlot and SetBersek are custom functions as you can imagine...Theses scripts work almost perfectly but i ran into one big issue...If the player swaps a cursed item for another cursed in the same inventory slot the loop is infinite! Any idea on how to prevent this?
Thanks in advance script gods!
               
               

               
            

Legacy_420

  • Sr. Member
  • ****
  • Posts: 370
  • Karma: +0/-0
Equippable Cursed Item
« Reply #4 on: January 22, 2011, 06:53:07 pm »


               I'd have to see the GetIsCursed function.

However, you can try something like checking to see if the PC is cursed in the OnEquip script (ie see if the local int "cursed" is already set to one) then set the local int to 2 and check for that local int in the OnEquip script.

Does anyone know the timing on the OnEquip and OnUnEquip events? That's probably essential information to get this to work.

-420
               
               

               


                     Modifié par 420, 22 janvier 2011 - 06:53 .
                     
                  


            

Legacy_Krevett

  • Full Member
  • ***
  • Posts: 203
  • Karma: +0/-0
Equippable Cursed Item
« Reply #5 on: January 22, 2011, 08:40:17 pm »


               The GetIsCursed function just check for the "cursed" local int being different from 0 on an object (player or item)
               
               

               
            

Legacy_ShadowM

  • Hero Member
  • *****
  • Posts: 1373
  • Karma: +0/-0
Equippable Cursed Item
« Reply #6 on: January 22, 2011, 08:56:44 pm »


               You have to make your cursed actions into a function, then make another function that checks if the pc has a cursed item equiped in each of the slots and if true set current equip item with some flag (int) that check in the second function to not treat it as a cursed item. Run this function before your standard curse function. This will allow your previous cursed item to kick out the item normally. Hope this make sense to you. I making this fix in my system right now, I report back how it goes.
               
               

               
            

Legacy_GhostOfGod

  • Hero Member
  • *****
  • Posts: 1490
  • Karma: +0/-0
Equippable Cursed Item
« Reply #7 on: January 23, 2011, 04:12:22 am »


               Just out of curiosity why aren't you using tag based scripting? You could make one script for the cursed item and not alter any of your modules event scripts. Your script could look something like so:

#include "x2_inc_switches"
void main()
{
    int nEvent = GetUserDefinedItemEventNumber();

    if(nEvent == X2_ITEM_EVENT_EQUIP)
    {
        object oPC = GetPCItemLastEquippedBy();
        //Do stuff here
    }

    if (nEvent == X2_ITEM_EVENT_UNEQUIP)
    {
        object oPC = GetPCItemLastUnequippedBy();
        //Do stuff here
    }

    if (nEvent == X2_ITEM_EVENT_UNACQUIRE)
    {
        object oPC = GetModuleItemLostBy();
        //Do stuff here
    }
}
               
               

               


                     Modifié par GhostOfGod, 23 janvier 2011 - 04:13 .
                     
                  


            

Legacy_Krevett

  • Full Member
  • ***
  • Posts: 203
  • Karma: +0/-0
Equippable Cursed Item
« Reply #8 on: January 23, 2011, 08:37:42 am »


               Because I hate having one script for each item with unique power/special abilities I make, so I don't use tag based scripting for items ^^
               
               

               
            

Legacy_Krevett

  • Full Member
  • ***
  • Posts: 203
  • Karma: +0/-0
Equippable Cursed Item
« Reply #9 on: January 23, 2011, 09:35:34 am »


               Here are my current scripts and after some tests, the infinite loop when swapping items is not initiated (maybe the scripts only fire once when the items are swapped but being equipped back immediatly does not fire the onunequip event for the item we just tried to equip)

onequip event:
#include "inc_functions"
void main()
{
object oPC = GetPCItemLastEquippedBy();
object oItem = GetPCItemLastEquipped();
string sTag = GetTag(oItem);
////////////////////////////////////////////////////////////////////////////////
if (!GetIsCursed(oPC) && sTag == "grandeepee16")
 {
 SetLocalInt(oPC, "cursed", 1);
 SetBerserk(oPC);
 }
if (GetIsCursed(oItem))
 {
 SetLocalInt(oPC, "cursed", 1);
 SetLocalInt(oItem, "cursed", 2);
 }
}

onunequip event:
#include "inc_functions"
void main()
{
object oPC = GetPCItemLastUnequippedBy();
object oItem = GetPCItemLastUnequipped();
////////////////////////////////////////////////////////////////////////////////
if (GetIsCursed(oPC) && GetIsCursed(oItem))
 {
 int nSlot = GetItemSlot(oItem);
 AssignCommand(oPC, ClearAllActions(TRUE));
 AssignCommand(oPC, ActionEquipItem(oItem, nSlot));
 AssignCommand(oPC, ActionSpeakString("Cet objet est maudit!"));
 DelayCommand(0.1, SetCommandable(FALSE, oPC));
 DelayCommand(2.0, SetCommandable(TRUE, oPC));
 }
if (!GetIsCursed(oPC) && GetIsCursed(oItem)) SetLocalInt(oItem, "cursed", 1);
}

onunacquire event:
#include "inc_functions"
void main()
{
object oPC = GetModuleItemLostBy();
object oItem = GetModuleItemLost();
////////////////////////////////////////////////////////////////////////////////
if (GetIsCursed(oPC) && GetLocalInt(oItem, "cursed") == 2)
 {
 int nSlot = GetItemSlot(oItem);
 AssignCommand(oPC, ClearAllActions(TRUE));
 AssignCommand(oPC, ActionPickUpItem(oItem));
 AssignCommand(oPC, ActionEquipItem(oItem, nSlot));
 AssignCommand(oPC, ActionSpeakString("Cet objet est maudit!"));
 DelayCommand(0.1, SetCommandable(FALSE, oPC));
 DelayCommand(2.0, SetCommandable(TRUE, oPC));
 }
}

Setting the variable to 2 on the item prevents a cursed item from being auto equipped if we try to drop it while being already cursed by another equipped item.
The few issues are encountered when swapping items in very specific case (ie having a cursed one handed weapon and a cursed shield and swapping for a two handed weapon unequip the one handed weapon but the shield remains in its slot...The two handed weapon is put back in your inventory but 50% of the time you'll have it equipped with the shield in your character sheet!!)
               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Equippable Cursed Item
« Reply #10 on: January 23, 2011, 02:51:38 pm »


               

Krevett wrote...
...
Here are my current scripts and after some tests, the infinite loop when swapping items is not initiated (maybe
onunequip event:
#include "inc_functions"
void main()
{
object oPC = GetPCItemLastUnequippedBy();
object oItem = GetPCItemLastUnequipped();
////////////////////////////////////////////////////////////////////////////////
if (GetIsCursed(oPC) && GetIsCursed(oItem))
 {
 int nSlot = GetItemSlot(oItem);
 AssignCommand(oPC, ClearAllActions(TRUE));
 AssignCommand(oPC, ActionEquipItem(oItem, nSlot));
 AssignCommand(oPC, ActionSpeakString("Cet objet est maudit!"));
 DelayCommand(0.1, SetCommandable(FALSE, oPC));
 DelayCommand(2.0, SetCommandable(TRUE, oPC));
 }
if (!GetIsCursed(oPC) && GetIsCursed(oItem)) SetLocalInt(oItem, "cursed", 1);
}
...

This would be better done using all actions.  Once it is all actions a short ActionWait befor making the PC commandable again will stop the infinite loop.


void main()
{
object oPC = GetPCItemLastUnequippedBy();
object oItem = GetPCItemLastUnequipped();
////////////////////////////////////////////////////////////////////////////////
if (GetIsCursed(oPC) && GetIsCursed(oItem))
 {
   int nSlot = GetItemSlot(oItem);
   AssignCommand(oPC, ClearAllActions(TRUE));
   AssignCommand(oPC, ActionEquipItem(oItem, nSlot));
   AssignCommand(oPC, ActionSpeakString("Cet objet est maudit!"));
   AssignCommand(oPC, ActionWait(0.5));
   AssignCommand(oPC,ActionDoCommand(SetCommandable(TRUE, oPC)));
   AssignCommand(oPC,SetCommandable(FALSE, oPC));
 }
if (!GetIsCursed(oPC) && GetIsCursed(oItem)) SetLocalInt(oItem, "cursed", 1);
}




...
onunacquire event:
#include "inc_functions"
void main()
{
object oPC = GetModuleItemLostBy();
object oItem = GetModuleItemLost();
////////////////////////////////////////////////////////////////////////////////
if (GetIsCursed(oPC) && GetLocalInt(oItem, "cursed") == 2)
 {
 int nSlot = GetItemSlot(oItem);
 AssignCommand(oPC, ClearAllActions(TRUE));
 AssignCommand(oPC, ActionPickUpItem(oItem));
 AssignCommand(oPC, ActionEquipItem(oItem, nSlot));
 AssignCommand(oPC, ActionSpeakString("Cet objet est maudit!"));
 DelayCommand(0.1, SetCommandable(FALSE, oPC));
 DelayCommand(2.0, SetCommandable(TRUE, oPC));
 }
}

All Of this is reall not needed. Simply setting the cursed flag on the item when it is Acquired should stop the item from ever being dropped. 


...
int oItem =GetModuleItemAcquired();
...
SetItemCursedFlag(oItem,TRUE);
...

If you need a better understanding between an action and a delayed command post back and let me know.
               
               

               


                     Modifié par Lightfoot8, 23 janvier 2011 - 02:55 .
                     
                  


            

Legacy_Krevett

  • Full Member
  • ***
  • Posts: 203
  • Karma: +0/-0
Equippable Cursed Item
« Reply #11 on: January 23, 2011, 03:10:06 pm »


               Of course I could set the cursed flag on the item but I want my players to be able to drop them if they don't equip it...And yes I'd like you to better explain me the differences between actions and delayed command, I'm always eager to learn tips from advanced scripters ^^ thanks for you help L8
               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Equippable Cursed Item
« Reply #12 on: January 23, 2011, 05:13:07 pm »


               Commands get executed by the Object as soon as it gets told to do it.
If the command is delayed, It gets executed after the given amount of time.
Action get added to the objects action Que and do not get executed until the actions in the Que before it are finished.  Note: Actions can only be added to the Que If the object is commandable.
When the Objects turn come up to do something it will check its action Que and do the first thing in the list then remove it from the list and then do the next.  
Assigned Commands don't get executed until after the current script is finished running.
 
Now lets look at your script.

[color=green] // assigned happens right after the script is finished.[/color]
AssignCommand(oPC, ClearAllActions(TRUE)); 

 [color=green]// assigned action gets added to the Que right after the clear all actions. [/color]
 AssignCommand(oPC, ActionEquipItem(oItem, nSlot));

[color=green] // assigned action: gets added to the Que to happen after the item is equipped. [/color]
 AssignCommand(oPC, ActionSpeakString("Cet objet est maudit!"));

[color=green] // Delayed command setting the PC uncommandable.[/color]
// A lot of scripts can run during that 0.1 sec
 DelayCommand(0.1, SetCommandable(FALSE, oPC));

 DelayCommand(2.0, SetCommandable(TRUE, oPC));
Instead of guess about when to do something using a delay, It is often easier to just make your commands into actions using the ActionDoCommand(oCommand) function.  All this function really does is add a command to the action Que instead of executing it right away.
The only thing I really did to your script was add your delays to the action Que instead of delay them. Oh and added a short wait so nothing else could get added to the Que to stop your loop.


...
   [color=green] // Don't let anything get added to my action Que for another half sec.[/color] 
   AssignCommand(oPC, ActionWait(0.5));

   [color=green] // Assigned command. Last thing added to my Que is to return to a commandable state.[/color].
   AssignCommand(oPC,ActionDoCommand(SetCommandable(TRUE, oPC)));

  [color=green]  // Assigned command. Set my self uncommandable when this script finishes and also
   // after all the other actions/commands are added to my que. 
   // Note: If this line was Simply SetCommandable(FALSE, oPC);
   // It would happen before the script finished running and all of the actions.
   // I added to the que with AssignCommand would be blocked for being added. [/color] 
   AssignCommand(oPC,SetCommandable(FALSE, oPC));

I hope this is helpfull.
L8
               
               

               


                     Modifié par Lightfoot8, 23 janvier 2011 - 05:17 .
                     
                  


            

Legacy_ShadowM

  • Hero Member
  • *****
  • Posts: 1373
  • Karma: +0/-0
Equippable Cursed Item
« Reply #13 on: January 23, 2011, 06:08:38 pm »


               Thanks Lightfoot8 I adjusted the timing a little with the SetCommandable and everything seem to be working in my system '<img'> well except they still can switch out weapons with three cursed ones, but that no biggy
               
               

               


                     Modifié par ShadowM, 23 janvier 2011 - 07:54 .