Aller au contenu

Photo

Can anyone point me to a script or utility that removes/merges items from players on log in?


  • Veuillez vous connecter pour répondre
53 réponses à ce sujet

#1
Lazarus Magni

Lazarus Magni
  • Members
  • 1 134 messages
Can anyone point me to a script or utility that removes items from players on log in if they are either: a) no longer in the mod, or B) merges them to conform to what is currently in the mod?

#2
_Knightmare_

_Knightmare_
  • Members
  • 643 messages
I'm not sure exactly what you are asking for here. I'm not sure A is possible (if understood correctly). The player has left the module so there is no PC object that you can have an affect on. For B, no idea what you mean.

#3
Lazarus Magni

Lazarus Magni
  • Members
  • 1 134 messages
I don't mean the player is no longer logged on, I mean if a logged in player has an item that is no longer in the module.

To answer your question about b, I mean say an item was originally incorporated (uploaded) into a module. Later it was determined to be overpowered, or whatever, and the existing version changed to something more reasonable. Is there a way to check on player log in. that their items get changed to what is currently in use?

Basically this is for a PW that is over 8 years old. It has had, as you might imagine, numerous generations of builders, Devs, and players. Some of the content from previous generations is not in alignment with that is currently perceived as "balanced" (*ducks and covers after throwing the B word out...*) So either we can let everything in as is, or wipe everybodys items (which I would also be curious if anyone could point me to some resource for doing this to a player vault items, while leaving their characters and exp in tack, as a back up contingency plan), or handle it on a case by case basis (which would be possible, but hoping some scripting option might save me a TON of work.)

Modifié par Lazarus Magni, 16 juin 2011 - 04:56 .


#4
Greyfort

Greyfort
  • Members
  • 234 messages
Hmm that can be an issue:
1) items that are no longer in the mod: You would need some sort info on all current items to check against...
2) merges to conform to mod: this is dependant on above to make compareisons and then destroy old and give new that is closest to old.

both these require going through pc invy and equiped items, and compareing each item to a list.
then setting var on item that doesn't conform for destruction, then giving item thats equal or close to old one this becomes little harder be cause you are comparing item props.

I would recomend:
If possible have players meet with DM and adjustments made that way.

Other wise strip all gear invy and equiped, getting gold value of each and giveing player gold
so they can equip them selfs. Players may not like it but it solves issue of players haveing that +20 vorpal, time stopping sword ;)

#5
Lazarus Magni

Lazarus Magni
  • Members
  • 1 134 messages

Greyfort wrote...

Other wise strip all gear invy and equiped, getting gold value of each and giveing player gold
so they can equip them selfs. Players may not like it but it solves issue of players haveing that +20 vorpal, time stopping sword ;)


So can you point me to a script of utility that does this? The alternative is, starting with a fresh vault, returning vets requesting characters restored, and then on restoring them loading first as a DM and going through their inv. A big old headache when your talking a guild of 2000+... Hell even 20+ when considering some players have 20+ toons...

Modifié par Lazarus Magni, 16 juin 2011 - 05:08 .


#6
Terrorble

Terrorble
  • Members
  • 193 messages
I could write something for you that loops thru all the player's items, destroys them, and gives them a new version of each. This way, everything they have would match the current blueprints for every item in the mod. If I'm not mistaken, if you try to create a new version for an item that no longer exists at all, then it simply would not be created - which solves any issues of removed items being in the mod.

This is based on one important assumption: when you "balanced" an item, you editted the original version in the palette, rather than creating a new version with a different blueprint resref to replace it. The script would look at the resref of the item, then create that same item on the player after destroying the old one. If an item with a different resref is replacing an item, then everything is considerably harder.

I'm not near the toolset and won't be for a few days if you don't mind waiting.

#7
Lazarus Magni

Lazarus Magni
  • Members
  • 1 134 messages
If there is no such thing already available, and you have the time and desire to create such a script that would certainly be fantastic Terroble. I am guessing having a script fire like this every time a player logs in would probably be rather resource intensive for a server. If it could be made so that an aDMin could run it on a player on an individual basis (like when saids players first get imported into the mod), or to run on the entire server vault a single time, that would probably be preferable.

BTW your assumption is correct for the most part, certain items have been changed over time, but their resref's have not. The ones that have different resrefs could easily be handled on there own I believe.

#8
GhostOfGod

GhostOfGod
  • Members
  • 863 messages
If I'm understanding this correctly you could use something like this for a DM wand/widget. Tag based script. It would loop through all inventory items, all bags in inventory, and all equipped items:

void ResRefMatchReplace(object oItem, object oTarget)
{
    string sResRef = GetResRef(oItem);
    if (sResRef == "blah blah blah1")
    {
        DestroyObject(oItem);
        CreateItemOnObject("res ref of replace item", oTarget);
    }
    if (sResRef == "blah blah blah2")
    {
        DestroyObject(oItem);
        CreateItemOnObject("res ref of replace item", oTarget);
    }
    //etc...
}

void TagMatchReplace(object oItem, object oTarget)
{
    string sTag = GetTag(oItem);
    if (sTag == "blah blah blah1")
    {
        DestroyObject(oItem);
        CreateItemOnObject("res ref of replace item", oTarget);
    }
    if (sTag == "blah blah blah2")
    {
        DestroyObject(oItem);
        CreateItemOnObject("res ref of replace item", oTarget);
    }
    //etc...
}

#include "x2_inc_switches"
void main()
{
    int iEvent = GetUserDefinedItemEventNumber();
    if (iEvent != X2_ITEM_EVENT_ACTIVATE) return;
    object oActivator = GetItemActivator();
    if (!GetIsDM(oActivator)) return;

    object oTarget = GetItemActivatedTarget();
    object oItem = GetFirstItemInInventory(oTarget);
    int iSlot;

    //Get items in inventory and replace if needed
    while (GetIsObjectValid(oItem))
    {
        //if item is a container, loop through items inside
        if (GetHasInventory(oItem))
        {
            object oConItem = GetFirstItemInInventory(oItem);
            while (GetIsObjectValid(oConItem))
            {
                ResRefMatchReplace(oConItem, oTarget);
                //TagMatchReplace(oConItem, oTarget);
                oConItem = GetNextItemInInventory(oItem);
            }
        }
        else
        {
            ResRefMatchReplace(oItem, oTarget);
            //TagMatchReplace(oItem, oTarget);
        }
        oItem = GetNextItemInInventory(oTarget);
    }

    //Get equipped items and replace if necessary
    for (iSlot=0; iSlot<NUM_INVENTORY_SLOTS; iSlot++)
    {
        oItem = GetItemInSlot(iSlot, oTarget);
        if (GetIsObjectValid(oItem))
        {
            ResRefMatchReplace(oItem, oTarget);
            //TagMatchReplace(oItem, oTarget);
        }
    }
}


This is more of a template. You would need to fill in all the tags or resrefs that you need to in the 2 functions above the main sript. Hope it helps. Good luck.

Modifié par GhostOfGod, 16 juin 2011 - 08:37 .


#9
Lazarus Magni

Lazarus Magni
  • Members
  • 1 134 messages
Thank you for the Template Ghost. Is there a simple way to extract the item tags, and resrefs in a Mod though? The mod literally has 1000s of items... Looking each up individually would be nearly a life long endevor...

Modifié par Lazarus Magni, 16 juin 2011 - 08:48 .


#10
FunkySwerve

FunkySwerve
  • Members
  • 1 308 messages
We have an item updater script that does this. When an item's resref is changed, a Version variable is incremented on it, and an entry added into a script. If you haven't been keeping track of changes, you would have to replace everything on the first go-round (tagging pcs that have been updated somehow, via persistent variable or other means), and then start versioning. I can share the code if you like, but it uses nwnx for hashsets.

Funky

#11
GhostOfGod

GhostOfGod
  • Members
  • 863 messages

Lazarus Magni wrote...

Thank you for the Template Ghost. Is there a simple way to extract the item tags, and resrefs in a Mod though? The mod literally has 1000s of items... Looking each up individually would be nearly a life long endevor...


So you have 1000s of items that changed? Or you don't know the tags/res refs that changed? Are you wanting to replace every item the player has? I'm a bit confused.

In those first 2 functions you don't list every item. Just the items that changed that you want to replace with some other item. And you don't have to use both functions. You can just use one if you want. I just left it open so that you could use tags or res refs of the changed items.

#12
Lazarus Magni

Lazarus Magni
  • Members
  • 1 134 messages
The problem is basically threefold. There are 1000's of items, I don't know all of which ones has been changed (although I do know some), and some players have overpowered items in their vault (on their characters or in their item vault) that are not in the mod (either given by previous DMs, or were removed from the mod a while ago.) Does that make sense?

So if I am understanding correctly, the script you wrote Ghost, will work for any items that I know the resrefs and tags for that I want to replace? But there would still be the problem for the unknown items... Is that right?

#13
FunkySwerve

FunkySwerve
  • Members
  • 1 308 messages
Yes, that sums up the problem accurately, with Ghost's script or any other. This is why I indicated the need for an initial all-items scan. Additionally, if you're using object-based banking, rather than resref-based, you would need to scan/replace all the vaults as well. That's possible, but quite a pain. The alternative, a vault wipe, is a very bad idea, as far as player retention goes.

Here's our item updater code. It fires on client enter, and automatically waits until the player hits the first area of the mod where they spend any amount of time, freezing them in place if the need for any updates is detected:

[code=auto:0]
#include "hg_inc"

#include "ac_itemreq_inc"
#include "ac_copycraft_inc"

#include "fky_chat_inc"
#include "inc_draw"

#include "hg_antidupe_inc"
#include "x2_inc_itemprop"

void ArtifactExplode (object oPC) {
    int i;
    object oItem;
    location lCenter = GetLocation(oPC);
    effect eImpact, eDamage, eLink;

    for (i = 0; i < NUM_INVENTORY_SLOTS; i++) {
        oItem = GetItemInSlot(i, oPC);

        if (GetLocalInt(oItem, "Artifact")) {
            WriteTimestampedLogEntry("ARTIFACT EXPLOSION : " + GetPCPlayerName(oPC) + " : " + GetName(oPC) + " : " + GetName(oItem));
            SetItemStackSize(oItem, 1);
            SetPlotFlag(oItem, FALSE);
            DestroyObject(oItem);
        }
    }

    oItem = GetFirstItemInInventory(oPC);

    while (GetIsObjectValid(oItem)) {
        if (GetLocalInt(oItem, "Artifact")) {
            WriteTimestampedLogEntry("ARTIFACT EXPLOSION : " + GetPCPlayerName(oPC) + " : " + GetName(oPC) + " : " + GetName(oItem));
            SetItemStackSize(oItem, 1);
            SetPlotFlag(oItem, FALSE);
            DestroyObject(oItem);
        }

        oItem = GetNextItemInInventory(oPC);
    }

    ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_SCREEN_SHAKE), lCenter);
    DelayCommand(0.25, DrawSphere(1, 249, lCenter, 0.25, 0.0, 30, 0.0, 0.0, 0.0, "z"));
    DelayCommand(2.75, DrawSpiral(0, 76, lCenter, 0.0, 23.0, 0.0, 60, 13.0, 0.7, 0.0, "z"));
    DelayCommand(2.75, DrawSpiral(0, 469, lCenter, 0.0, 23.0, 0.0, 60, 13.0, 0.7, 0.0, "z"));
    DelayCommand(3.00, DrawCircle(0, 22, lCenter, 5.0, 0.0, 10, 1.0, 0.0, 0.0, "z"));
    DelayCommand(3.50, DrawCircle(0, 22, lCenter, 11.0, 0.0, 13, 1.0, 0.0, 0.0, "z"));
}

void DestroyOriginalItem (object oItem) {
    SetPlotFlag(oItem, FALSE);
    DestroyObject(oItem);
}


void ReplaceItem (object oTarget, object oItem, string sRes) {
    string sName = GetName(oItem);

    string sLog = "UPDATEITEMS : " + GetName(oTarget) + " (" +
        GetPCPlayerName(oTarget) + ") : " + sName + " (" +
        GetResRef(oItem) + ") [v" + IntToString(GetLocalInt(oItem, "Version")) + "] -> ";

    int nCharges = GetItemCharges(oItem);
    string sUniqueID = GetLocalString(oItem, "UNIQUE_ID");

    if (GetLocalInt(oItem, "Artifact") || GetLocalInt(oItem, "Singleton"))
        SetLocalInt(oItem, "NoCopyCrafting", 1);

    DeleteLocalInt(oItem, "Artifact");
    DeleteLocalInt(oItem, "Singleton");
    DeleteLocalString(oItem, "UNIQUE_ID");

    int nBaseType = GetBaseItemType(oItem);

    if (sRes == GetResRef(oItem)                    &&
        !GetLocalInt(oItem, "NoCopyCrafting")       &&
        (nBaseType == BASE_ITEM_ARMOR               ||
         nBaseType == BASE_ITEM_HELMET              ||
         GetItemIsShield(oItem)                     ||
         GetItemIsWeapon(oItem))) {

        AssignCommand(GetModule(), DelayCommand(0.0, DestroyOriginalItem(oItem)));

        object oCopy = CreateItemOnObject(sRes, oTarget, 1);

        if (!GetLocalInt(oCopy, "Artifact")  &&
            !GetLocalInt(oCopy, "Singleton") &&
            !GetLocalInt(oCopy, "NoCopyCrafting")) {
            AssignCommand(GetModule(), DelayCommand(0.0, DestroyOriginalItem(oCopy)));

            oCopy = CopyItemCrafting(oItem, oCopy);
        }

        SetPlotFlag(oItem, FALSE);
        SetLocalInt(oItem, "REPLACED", 1);
        DestroyObject(oItem);

        oItem = oCopy;
    } else if (nBaseType == BASE_ITEM_RING && sRes == "multi_signet") {
        int i, j;

        AssignCommand(GetModule(), DelayCommand(0.0, DestroyOriginalItem(oItem)));

        SetPlotFlag(oItem, FALSE);
        SetLocalInt(oItem, "REPLACED", 1);

        object oRing = CreateItemOnObject(sRes, oTarget, 1);

        /* copy the charges from the last Ring of the Planar Traveler */
        if (GetResRef(oRing) == GetResRef(oItem)) {
            SetLocalInt(oRing, "Charges_", 10);
            SetLocalInt(oRing, "Charges_100", 10);

            for (i = 1; i <= 4; i++) {
                for (j = 1; j <= 9; j++)
                    SetLocalInt(oRing, "Charges_" + IntToString((100 * i) + 10 + j), 10);
            }
        }

        DestroyObject(oItem);

        oItem    = oRing;
        nCharges = 0;
    } else {
        if (nBaseType == BASE_ITEM_MAGICWAND && sRes == "wandoftime" && GetLocalInt(oItem, "Version") < 3 && nCharges <= 5) {
            if ((nCharges = nCharges * 5) > 50)
                nCharges = 50;
        }

        AssignCommand(GetModule(), DelayCommand(0.0, DestroyOriginalItem(oItem)));

        SetPlotFlag(oItem, FALSE);
        SetLocalInt(oItem, "REPLACED", 1);
        DestroyObject(oItem);

        if (GetStringLeft(sRes, 1) == "#") {
            GiveGoldToCreature(oTarget, StringToInt(GetSubString(sRes, 1, 10)));
            sRes  = "DESTROY";
            oItem = OBJECT_INVALID;
        } else
            oItem = CreateItemOnObject(sRes, oTarget, 1);
    }

    if (GetIsObjectValid(oItem)) {
        WriteTimestampedLogEntry(sLog + GetName(oItem) + " (" + sRes + ") [v" +
            IntToString(GetLocalInt(oItem, "Version")) + "] : REPLACED" +
            (GetItemPossessor(oItem) != oTarget ? " AND DROPPED" : ""));

        if (nCharges > 0 && GetItemCharges(oItem) > 0 && !GetLocalInt(oItem, "NoRecharge"))
            SetItemCharges(oItem, nCharges);

        if (sUniqueID != "")
            SetLocalString(oItem, "UNIQUE_ID", sUniqueID);

        SetIdentified(oItem, TRUE);
    } else if (sRes == "DESTROY")
        WriteTimestampedLogEntry(sLog + sRes + " : DESTROYED");
    else
        WriteTimestampedLogEntry(sLog + sRes + " : FAILED");

    if (sRes != "DESTROY" && sRes != "drowdust") {
        FloatingTextStringOnCreature("Your " + sName + " has been replaced with a new version.", oTarget, FALSE);

        if (GetIsObjectValid(oItem) && GetItemPossessor(oItem) != oTarget)
            FloatingTextStringOnCreature(COLOR_RED + "Your new " + sName +
                " is on the ground. Please pick it up.</c>", oTarget, FALSE);
    }
}


string GetItemUpdate (object oItem) {
    if (!GetIsObjectValid(oItem))
        return "";

    int nVersion = GetLocalInt(oItem, "Version");
    int nBaseType = GetBaseItemType(oItem);
    string sRes = GetStringLowerCase(GetResRef(oItem));
    string sTag = GetStringLowerCase(GetTag(oItem));


    DeleteLocalInt(oItem, "ZEP_CR_TEMPITEM");

    /* destroy already-replaced items */
    if (GetLocalInt(oItem, "REPLACED"))
        return "DESTROY";

    /* destroy old pet givers */
    if (GetStringLeft(sRes, 10) == "custompet0")
        return "DESTROY";

    /* destroy guild points on relog */
    if (sRes == "newguildpoint" && GetTag(GetArea(GetItemPossessor(oItem))) == "DocksofAscension")
        return "DESTROY";

    /* integrate and destroy guild tokens */
    if (GetStringLeft(sTag, 5) == "guild" && GetStringRight(sTag, 5) == "token") {
        int nGuild;
        string sGuild = GetSubString(sTag, 5, 1);
        object oPC = GetItemPossessor(oItem);

        if (sGuild == "g")
            nGuild = GetLocalInt(oItem, "Guild");
        else
            nGuild = StringToInt(sGuild);

        if (nGuild == GUILD_ETERNAL_ORDER_MERGED_WITH_REDS)
            nGuild = GUILD_ETERNAL_REDS;

        SetLocalInt(oPC, "Guild", nGuild);
        SetPersistentInt(oPC, "Guild", nGuild);

        return "DESTROY";
    }

    /* replace old ammo containers */
    if (GetStringLeft(sRes, 3) == "uaq" || GetStringLeft(sRes, 13) == "quiverofendle") {
        if (sTag != "ac_rng_uacont")
            return sRes;
    }

    /* replace +6 AC mystic weapons with new versions */
    if (GetItemIsMeleeWeapon(oItem)           &&
        GetStringLeft(sRes, 9) == "scorching" &&
        GetItemACValue(oItem) > 0) {

        return sRes;
    }

    /* replace old CEP tridents */
    if (nBaseType == 300)
        return sRes;

    /* replace buggy CEP appearances on armor */
    if (nBaseType == BASE_ITEM_ARMOR &&
        GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_MODEL, ITEM_APPR_ARMOR_MODEL_TORSO) == 175) {

        SetLocalInt(oItem, "NoCopyCrafting", 1);
        return sRes;
    }

    /* replace old PC Scry tools */
    if (sTag == "pclist" && !GetLocalInt(oItem, "New"))
        return sRes;

    /* set FKY_CHAT_INSTANT on PC Scry, Command Targeter, and DM Voice Thrower */
    if (!GetLocalInt(oItem, "FKY_CHAT_INSTANT") &&
        (sRes == "pclist"          ||
         sRes == "autocaster"      ||
         sRes == "fky_chat_target" ||
         sRes == "fky_chat_ventril")) {

        if (sRes == "autocaster") {
            IPRemoveAllItemProperties(oItem, DURATION_TYPE_PERMANENT);

            /* add 'Talk To' and 'Unique Power Self Only' in that order */
            AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyCastSpell(536, 13), oItem);
            AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyCastSpell(335, 13), oItem);

            SetLocalString(oItem, "FKY_CHAT_INSTANT_SCRIPT", "ev_autocaster");
        }

        SetLocalInt(oItem, "FKY_CHAT_INSTANT", 1);
    }

    /* set Artifact local on artifacts that don't have it */
    if (sTag == "ssith5sstadisben" ||
        sTag == "rtyglegendaryhor" ||
        sTag == "theeyeofvecna") {

        SetLocalInt(oItem, "Artifact", 1);
    }

    /* return old honed weapons to normal */
    if (sTag == "assasswpncrit")
        return sRes;

    /* integrate the old Greater Dragon Breath with RDDs */
    if (sTag == "rddbreath") {
        object oRDD = GetItemPossessor(oItem);
        int nRDDLevel = GetLocalInt(oItem, "RDD_Level");

        SetLocalInt(oRDD, "RDDLevel", nRDDLevel);
        SetPersistentInt(oRDD, "RDDLevel", nRDDLevel);

        if (GetPersistentInt(oRDD, "RDDLevel") == nRDDLevel)
            return "DESTROY";
    }

    /* ensure all unlimited heal packs require the Beaker */
    if (sRes == "unlimitedhealpac")
        SetLocalString(oItem, "UnlimitedSourceTag", "bountifulbeaker");


    object oMod = GetModule();

    /* replace items that swap to new resrefs */
    string sNew = HashSetGetLocalString(oMod, "UpdateItemRes", sRes);
    if (sNew != "")
        return sNew;

    /* replace items with new versions */
    int nVer = HashSetGetLocalInt(oMod, "UpdateItemVer", sRes);
    if (nVer > GetLocalInt(oItem, "Version"))
        return sRes;

    if (HashSetGetLocalInt(oMod, "UpdateItemSingleton", sRes) && !GetLocalInt(oItem, "Singleton"))
        return sRes;

    if (HashSetGetLocalInt(oMod, "UpdateItemUndroppable", sRes) && GetItemCursedFlag(oItem)) {
        itemproperty ip;

        for (ip = GetFirstItemProperty(oItem);
             GetIsItemPropertyValid(ip);
             ip = GetNextItemProperty(oItem)) {

            if (GetItemPropertyType(ip) == ITEM_PROPERTY_INVIS_ADDITIONAL &&
                GetItemPropertyCostTableValue(ip) == IP_CONST_ADDITIONAL_UNDROPPABLE)
                break;
        }

        if (!GetIsItemPropertyValid(ip)) {
            ip = ItemPropertyInvisAdditional(IP_CONST_ADDITIONAL_UNDROPPABLE);
            AddItemProperty(DURATION_TYPE_PERMANENT, ip, oItem);
        }
    }

    /* fix broken random weapons with monster damage */
    if (GetStringLeft(sRes, 6) == "randwp" && GetItemHasItemProperty(oItem, ITEM_PROPERTY_MONSTER_DAMAGE))
        return sRes;

    /* update charges on the Ring of the Planar Traveler */
    if (sTag == "multi_signet") {
        string sServer = GetLocalString(oMod, "ServerNumber");

        if (sServer != "")
            SetItemCharges(oItem, 1 + (GetLocalInt(oItem, "Charges_" + sServer) * 2));
    }

    if (sTag == "hellskull" && !GetItemHasItemProperty(oItem, ITEM_PROPERTY_CAST_SPELL)) {
        itemproperty ip = ItemPropertyCastSpell(IP_CONST_CASTSPELL_UNIQUE_POWER_SELF_ONLY,
                                                IP_CONST_CASTSPELL_NUMUSES_UNLIMITED_USE);

        AddItemProperty(DURATION_TYPE_PERMANENT, ip, oItem);
    }

    if (GetLocalString(oItem, "ForgeModifications") != "") {
        SetLocalInt(oItem, "Modified", 1);
        DeleteLocalString(oItem, "ForgeModifications");
    }

    int nModified = GetLocalInt(oItem, "Modified");

    if (nModified & 2) {
        if (nBaseType == BASE_ITEM_ARMOR && !(nModified & 65536))
            return sRes;

        /* fix full Silence immunity on randomized items */
        if (FindSubString(GetLocalString(oItem, "Modifications"), " 2,217,56,0,0,255,0") >= 0) {
            WriteTimestampedLogEntry("UPDATEITEMS : " + GetName(GetItemPossessor(oItem)) + " : " + GetName(oItem) + " : fixing full Silence immunity");

            string sMods = GetLocalString(oItem, "Modifications");

            sMods = ReplaceString(sMods, " 2,217,56,0,0,255,0", " 2,53,0,33,150,255,0", TRUE);
            SetLocalString(oItem, "Modifications", sMods);

            itemproperty ip;

            for (ip = GetFirstItemProperty(oItem); GetIsItemPropertyValid(ip); ip = GetNextItemProperty(oItem)) {
                if (GetItemPropertyType(ip) == 217 && GetItemPropertySubType(ip) == 56)
                    RemoveItemProperty(oItem, ip);
            }

            ip = ItemPropertySpellImmunitySpecific(150);
            AddItemProperty(DURATION_TYPE_PERMANENT, ip, oItem);
        }
    }

    return "";
}


void TagDupes (object oPC, string sUniqueID, int nDupes) {
    int i;
    object oItem;

    for (i = 0; i < NUM_INVENTORY_SLOTS; i++) {
        oItem = GetItemInSlot(i, oPC);

        if (GetIsObjectValid(oItem) && GetLocalString(oItem, "UNIQUE_ID") == sUniqueID) {
            DupeAlert(oPC, oItem);

            if (--nDupes < 1)
                return;
        }
    }

    oItem = GetFirstItemInInventory(oPC);

    while (GetIsObjectValid(oItem)) {
        if (GetLocalString(oItem, "UNIQUE_ID") == sUniqueID) {
            DupeAlert(oPC, oItem);

            if (--nDupes < 1)
                return;
        }

        oItem = GetNextItemInInventory(oPC);
    }
}


void main () {
    int i, nDupes, nArtifacts = 0, nCount = 0;
    int bDay = GetIsDay();
    string sRes, sUniqueID;
    object oItem, oMod = GetModule(), oArea = GetArea(OBJECT_SELF);

    if (!GetIsObjectValid(OBJECT_SELF) || GetIsDM(OBJECT_SELF))
        return;

    if (!GetIsObjectValid(oArea) || GetTag(oArea) == "voyage") {
        DelayCommand(5.0, main());
        return;
    }

    HashSetDestroy(oMod, "DupeID");
    HashSetCreate(oMod, "DupeID");

    for (i = 0; i < NUM_INVENTORY_SLOTS; i++) {
        oItem = GetItemInSlot(i, OBJECT_SELF);

        if (GetIsObjectValid(oItem)) {
            if (bDay && GetStringLeft(GetTag(oItem), 4) == "asdf")
                sRes = "drowdust";
            else
                sRes = GetItemUpdate(oItem);

            if (sRes != "") {
                ReplaceItem(OBJECT_SELF, oItem, sRes);

                ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectCutsceneImmobilize(), OBJECT_SELF, 2.0);
                DelayCommand(1.0, main());

                return;
            }

            if ((sUniqueID = GetLocalString(oItem, "UNIQUE_ID")) != "")
                HashSetSetLocalInt(oMod, "DupeID", sUniqueID,
                    HashSetGetLocalInt(oMod, "DupeID", sUniqueID) + 1);

            if (GetLocalInt(oItem, "Artifact"))
                nArtifacts++;

        }
    }

    oItem = GetFirstItemInInventory(OBJECT_SELF);

    while (GetIsObjectValid(oItem)) {
        if (!GetItemCursedFlag(oItem) || GetItemIsStackable(oItem))
            nCount++;

        sRes = GetItemUpdate(oItem);

        if (sRes != "") {
            ReplaceItem(OBJECT_SELF, oItem, sRes);

            ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectCutsceneImmobilize(), OBJECT_SELF, 2.0);
            DelayCommand(1.0, main());

            return;
        }

        if ((sUniqueID = GetLocalString(oItem, "UNIQUE_ID")) != "")
            HashSetSetLocalInt(oMod, "DupeID", sUniqueID,
                HashSetGetLocalInt(oMod, "DupeID", sUniqueID) + 1);

        if (GetLocalInt(oItem, "Artifact"))
            nArtifacts += GetItemStackSize(oItem);

        oItem = GetNextItemInInventory(OBJECT_SELF);
    }

    string sKey = HashSetGetFirstKey(oMod, "DupeID");

    while (sKey != "") {
        if ((nDupes = HashSetGetLocalInt(oMod, "DupeID", sKey)) > 1)
            DelayCommand(0.1, TagDupes(OBJECT_SELF, sKey, nDupes - 1));

        sKey = HashSetGetNextKey(oMod, "DupeID");
    }

    HashSetDestroy(oMod, "DupeID");

    if (nArtifacts > 1) {
        DelayCommand(0.0, ArtifactExplode(OBJECT_SELF));
        return;
    }


    if (GetTag(oArea) == "DocksofAscension" || GetTag(oArea) == "TownofAscension") {
        if (nCount > 150 && !VerifyAdminKey(OBJECT_SELF)) {
            location lBurdened = GetLocation(GetWaypointByTag("burdened"));

            DelayCommand(3.0, ForceJump(OBJECT_SELF, lBurdened));
            return;
        }
    }
}
[\\code]

Funky

Modifié par FunkySwerve, 16 juin 2011 - 07:12 .


#14
GhostOfGod

GhostOfGod
  • Members
  • 863 messages
Oooooh. So what you want to do is compare all the items the player has to all the blueprints of the module items. If the player has items that don't match any of the blueprints, then get rid of it?

Ewww. As Funky stated, "quite a pain". Yeah I don't think there is any easy way to do this with vanilla NWN. Maybe NWNx and that would be Funky's department. If you did it without NWNx you would have no choice but to do something with all the items in a list to compare player items to.

One other option if you are more concerned with certain item properties than you are with the items, you could do a one time OnAcquire or a DM widget that could loop through items and remove certain illegal item properties.

#15
Lazarus Magni

Lazarus Magni
  • Members
  • 1 134 messages
Goodness gracious Funky that is some script. Ahh Encumbria, what a wonderful place to visit ;p. Since this would not be for a PoA server obviously alot of the lines in the script would not apply. I take it, Funky, you think I (or more likely a competent scripter) could modify that script to pertain to this particular PW?

Also by "indicating the need for an initial all items scan" are you refering to that script or something else? And I am fairly certain that the item banking is resref based. It wont store items if it doesn't have a blueprint for them, and already has a function for updating them to the current state. Subsequently it is the items on PC's that are more of the problem now that I think on it. Which also gives me an idea, that perhaps given how the item bank already functions, when I first import a players characters into the server vault (fromthe old one to a new one) I could somehow dump all their items in the item vault, thereby updating them (and removing any that don't have blueprints)?

Alternatively short of a full server vault wipe, I wonder if it is possible to do just an item wipe on the server vault?

Ghost, yes that is what I was thinking based off of Terrorble's idea. I do have NWNX installed locally, and when I put the mod on a server it will also, as well as a MySQL database. (FYI, this is a WIP currently, but I have found a server host (I think), and am in the process of getting the Mod ready prior to launching.

A DM widget is an interesting idea also, and would work for some things like removing improved evasion, however for others it is more complicated in that the property is allowed, but only at a certain level (e.g. only 10% vs one dmg type is allowed on an item, but some people have gear with much more than that.)

Modifié par Lazarus Magni, 16 juin 2011 - 08:09 .


#16
FunkySwerve

FunkySwerve
  • Members
  • 1 308 messages
Yes, you could modify that script, or make one like GoGs. If you're going to do a full-reset on the items, something simple like GoG's might be just the trick, since you will have a low number of resrefs to check against to start (none). The initial update is easy enough - you just cycle and replace all their items one by one; the only difficulty is making sure it only happens once - some kind of persistent variable on the pc is probably best for that (one other option being one Version var per item, but that would greatly increase bic size and therefore servervault size - much better to have the default Version be 0, with no int on the item needing to be set). You could also set some kind of marker in the bic file itself - we do pc versioning very similar to item versioning tracking tag and unique id in the bic's tag field (accomplishable via either nwnx_letoscript or nwnx_funcs). Other unused fields are available, as well, like BodyBag.

The only thing our script really needs nwnx for is the hashset plugin. Here's the primer script, if you're curious. It holds all the item update info from all the items we've changed (some of them have up to version 6 from repeated editing/updating). You don't need to store this stuff in a hash, you can easily hold it in a function as GoG's version does.

(this runs from modload to load up the hashset)
#include "hg_inc"

/* All item updates performed are logged; grep for UPDATEITEMS in the
 * server log. */

void main () {
    object oMod = GetModule();

    if (HashSetValid(oMod, "UpdateItems"))
        return;

    HashSetCreate(oMod, "UpdateItems");
    HashSetCreate(oMod, "UpdateItemRes");
    HashSetCreate(oMod, "UpdateItemVer");
    HashSetCreate(oMod, "UpdateItemSingleton");

    /* update Rings of the Planar Traveler */
    HashSetSetLocalString(oMod, "UpdateItemRes", "galadriemsign001", "multi_signet");
    HashSetSetLocalInt(oMod, "UpdateItemVer", "multi_signet", 4);

    /* destroy old combat autocasters, End Shapestrong Rage, Way of the Staff, Greater Smite */
    HashSetSetLocalString(oMod, "UpdateItemRes", "combatcaster",     "DESTROY");
    HashSetSetLocalString(oMod, "UpdateItemRes", "barbshape001",     "DESTROY");
    HashSetSetLocalString(oMod, "UpdateItemRes", "qc_waystaff",      "DESTROY");
    HashSetSetLocalString(oMod, "UpdateItemRes", "fa_greatersmite",  "DESTROY");
    HashSetSetLocalString(oMod, "UpdateItemRes", "smiteabilitypala", "DESTROY");
    HashSetSetLocalString(oMod, "UpdateItemRes", "ca_rdd_buffet", "DESTROY");
    HashSetSetLocalString(oMod, "UpdateItemRes", "ca_rdd_fearaura", "DESTROY");

    /* destroy Brena's Magic Tulip */
    HashSetSetLocalString(oMod, "UpdateItemRes", "magictulip", "DESTROY");

    /* destroy unslagged BBoDs */
    HashSetSetLocalString(oMod, "UpdateItemRes", "x2_it_wpblkblade", "DESTROY");

    /* destroy tournament points, gems, and wands */
    HashSetSetLocalString(oMod, "UpdateItemRes", "newssithrgem",     "DESTROY");
    HashSetSetLocalString(oMod, "UpdateItemRes", "setteam1wand",     "DESTROY");
    HashSetSetLocalString(oMod, "UpdateItemRes", "setteam2wand",     "DESTROY");
    HashSetSetLocalString(oMod, "UpdateItemRes", "setteam3wand",     "DESTROY");
    HashSetSetLocalString(oMod, "UpdateItemRes", "setteam4wand",     "DESTROY");

    /* destroy old pet givers */
    HashSetSetLocalString(oMod, "UpdateItemRes", "bottlebehold",     "DESTROY");
    HashSetSetLocalString(oMod, "UpdateItemRes", "summonhook",       "DESTROY");
    HashSetSetLocalString(oMod, "UpdateItemRes", "summonbuddy",      "DESTROY");
    HashSetSetLocalString(oMod, "UpdateItemRes", "summonsaga",       "DESTROY");
    HashSetSetLocalString(oMod, "UpdateItemRes", "summonguardian",   "DESTROY");
    HashSetSetLocalString(oMod, "UpdateItemRes", "diamongsfetchtoy", "DESTROY");
    HashSetSetLocalString(oMod, "UpdateItemRes", "scalpel1",         "DESTROY");
    HashSetSetLocalString(oMod, "UpdateItemRes", "goobaby",          "DESTROY");

    /* destroy old trap maker traps and refund their cost, and replace old trap makers */
    HashSetSetLocalString(oMod, "UpdateItemRes", "ct0001",           "#5000");
    HashSetSetLocalString(oMod, "UpdateItemRes", "ct0002",           "#5000");
    HashSetSetLocalString(oMod, "UpdateItemRes", "ct0003",           "#5000");
    HashSetSetLocalString(oMod, "UpdateItemRes", "ct0004",           "#5000");
    HashSetSetLocalString(oMod, "UpdateItemRes", "ct0005",           "#5000");
    HashSetSetLocalString(oMod, "UpdateItemRes", "ct0006",           "#150000");
    HashSetSetLocalString(oMod, "UpdateItemRes", "ct0007",           "#150000");
    HashSetSetLocalString(oMod, "UpdateItemRes", "ct0008",           "#150000");
    HashSetSetLocalString(oMod, "UpdateItemRes", "ct0009",           "#150000");
    HashSetSetLocalString(oMod, "UpdateItemRes", "ct0010",           "#150000");
    HashSetSetLocalString(oMod, "UpdateItemRes", "ct0011",           "#150000");
    HashSetSetLocalString(oMod, "UpdateItemRes", "ct0012",           "#150000");
    HashSetSetLocalString(oMod, "UpdateItemRes", "ct0013",           "#150000");
    HashSetSetLocalString(oMod, "UpdateItemRes", "ct0014",           "#150000");
    HashSetSetLocalString(oMod, "UpdateItemRes", "ct0014",           "#150000");
    HashSetSetLocalString(oMod, "UpdateItemRes", "trapkitmkr001",    "hgt_maker_17");   /* Cold         */
    HashSetSetLocalString(oMod, "UpdateItemRes", "trapkitmkr002",    "hgt_maker_4");    /* Fire         */
    HashSetSetLocalString(oMod, "UpdateItemRes", "trapkitmkr003",    "hgt_maker_3");    /* Acid         */
    HashSetSetLocalString(oMod, "UpdateItemRes", "trapkitmkr004",    "hgt_maker_5");    /* Elec         */
    HashSetSetLocalString(oMod, "UpdateItemRes", "trapkitmkr005",    "hgt_maker_18");   /* Sonic        */
    HashSetSetLocalString(oMod, "UpdateItemRes", "trapkitmkr006",    "hgt_maker_21");   /* Negative     */
    HashSetSetLocalString(oMod, "UpdateItemRes", "trapkitmkr007",    "hgt_maker_22");   /* Positive     */
    HashSetSetLocalString(oMod, "UpdateItemRes", "trapkitmkr008",    "hgt_maker_19");   /* Divine       */
    HashSetSetLocalString(oMod, "UpdateItemRes", "trapkitmkr009",    "hgt_maker_20");   /* Magical      */

    /* replace old artifact/class/feat/race/skill abilities */
    HashSetSetLocalString(oMod, "UpdateItemRes", "assassinscabbard", "ca_asn_scabbard");
    HashSetSetLocalString(oMod, "UpdateItemRes", "barbshape",        "ca_bbn_shape");
    HashSetSetLocalString(oMod, "UpdateItemRes", "blessingofmidnig", "aa_spellpen");
    HashSetSetLocalString(oMod, "UpdateItemRes", "bs_stillsound",    "ca_brd_stillsnd");
    HashSetSetLocalString(oMod, "UpdateItemRes", "cot_auraofglory",  "ca_dc_nimvictory");
    HashSetSetLocalString(oMod, "UpdateItemRes", "defensiveshieldd", "ca_dwd_defense");
    HashSetSetLocalString(oMod, "UpdateItemRes", "dragonorbbreath",  "aa_con");
    HashSetSetLocalString(oMod, "UpdateItemRes", "gemofcalling",     "fa_sum_dragon");
    HashSetSetLocalString(oMod, "UpdateItemRes", "gemofcalling001",  "fa_sum_fiend");
    HashSetSetLocalString(oMod, "UpdateItemRes", "gemofcalling002",  "fa_sum_shadow");
    HashSetSetLocalString(oMod, "UpdateItemRes", "gemofcalling003",  "fa_sum_mummy");
    HashSetSetLocalString(oMod, "UpdateItemRes", "gemofcalling004",  "fa_sum_dracolich");
    HashSetSetLocalString(oMod, "UpdateItemRes", "greaterdisarm",    "ca_ftr_g_disarm");
    HashSetSetLocalString(oMod, "UpdateItemRes", "greaterknockdown", "ca_ftr_g_kd");
    HashSetSetLocalString(oMod, "UpdateItemRes", "greaterparry",     "ca_ftr_g_parry");
    HashSetSetLocalString(oMod, "UpdateItemRes", "guardianangel",    "ca_pal_grdangel");
    HashSetSetLocalString(oMod, "UpdateItemRes", "jewelofevernight", "ca_bg_evernight");
    HashSetSetLocalString(oMod, "UpdateItemRes", "kireflection",     "ca_wm_kireflect");
    HashSetSetLocalString(oMod, "UpdateItemRes", "lichsong",         "ca_pm_lichsong");
    HashSetSetLocalString(oMod, "UpdateItemRes", "massresurrection", "ca_clr_massrez");
    HashSetSetLocalString(oMod, "UpdateItemRes", "massvamptouch",    "ca_pm_lifeblight");
    HashSetSetLocalString(oMod, "UpdateItemRes", "palemoonlight",    "aa_speed");
    HashSetSetLocalString(oMod, "UpdateItemRes", "pipesofgeshtak",   "ca_brd_lichlyr");
    HashSetSetLocalString(oMod, "UpdateItemRes", "pm_soulgem",       "ca_pm_soulgem");
    HashSetSetLocalString(oMod, "UpdateItemRes", "pyramidhp",        "aa_wis");
    HashSetSetLocalString(oMod, "UpdateItemRes", "rddaura",          "ca_rdd_fearaura");
    HashSetSetLocalString(oMod, "UpdateItemRes", "rddbuffet",        "ca_rdd_buffet");
    HashSetSetLocalString(oMod, "UpdateItemRes", "shadowdecoy",      "ca_sd_decoy");
    HashSetSetLocalString(oMod, "UpdateItemRes", "shadowrift",       "ca_sd_rift");
    HashSetSetLocalString(oMod, "UpdateItemRes", "stoneoftheearthm", "sa_animalemp");
    HashSetSetLocalString(oMod, "UpdateItemRes", "sunefireshield",   "aa_cha");
    HashSetSetLocalString(oMod, "UpdateItemRes", "thewayofthes",     "qc_waystaff");
    HashSetSetLocalString(oMod, "UpdateItemRes", "treantshrink",     "ra_treant_shrink");
    HashSetSetLocalString(oMod, "UpdateItemRes", "tymorasluck",      "aa_saves");
    HashSetSetLocalString(oMod, "UpdateItemRes", "vecnadeathtouch",  "aa_str");
    HashSetSetLocalString(oMod, "UpdateItemRes", "vecnadominate",    "aa_int");
    HashSetSetLocalString(oMod, "UpdateItemRes", "vhaerundarkness",  "aa_dex");
    HashSetSetLocalString(oMod, "UpdateItemRes", "warriorswhetst",   "ca_ftr_whetstone");

    /* destroy old legendary XP trackers and empty skins */
    HashSetSetLocalString(oMod, "UpdateItemRes", "legendaryxptrack", "DESTROY");
    HashSetSetLocalString(oMod, "UpdateItemRes", "x2_it_emptyskin",  "DESTROY");

    /* destroy old Abyss plot items */
    HashSetSetLocalString(oMod, "UpdateItemRes", "aby_plot1",        "DESTROY");
    HashSetSetLocalString(oMod, "UpdateItemRes", "aby_plot2",        "DESTROY");
    HashSetSetLocalString(oMod, "UpdateItemRes", "aby_plot3",        "DESTROY");
    HashSetSetLocalString(oMod, "UpdateItemRes", "aby_plot4",        "DESTROY");
    HashSetSetLocalString(oMod, "UpdateItemRes", "aby_plot5",        "DESTROY");
    HashSetSetLocalString(oMod, "UpdateItemRes", "aby_relic",        "aby_vestige");

    /* replace old guild activators and AC dropper */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "dropacguild", 3);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "activatorguild1", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "activatorguild2", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "activatorguild3", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "activatorguild4", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "activatorguild5", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "activatorguild6", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "activatorguild7", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "activatorguild8", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "activatorguild9", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "activatorguil003", 2);
    HashSetSetLocalString(oMod, "UpdateItemRes", "activatorguil004", "activatorguil003");

    /* replace old race books, feat books, and level books */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "libramofgolden", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "libramofineffabl", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "libramofsilverli", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "featbk_esf_abjur", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "featbk_esf_conj", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "featbk_esf_div", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "featbk_esf_ench", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "featbk_esf_evo", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "featbk_esf_illus", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "featbk_esf_necro", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "featbk_esf_trans", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "featbk_esp", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellbk_sresist", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_anarch", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_atomie", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_baseborn", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_battlerag", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_chaosgnom", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_dopplegan", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_dragonblo", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_erinyes", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_fallenan", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_furchin", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_genie", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_halfcele", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_halffiend", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_halfguard", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_halfkyton", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_houndarch", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_howler", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_juggernau", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_kolyarut", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_lycan", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_maelephan", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_minotaur", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_negatai", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_oneeyed", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_planewalk", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_radianceg", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_rilminai", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_salamande", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_shard", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_spelljamm", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_stargazer", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_stinger", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_thrikreen", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_treant", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_undying", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_yukio", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "racebk_zenythri", 2);

    HashSetSetLocalString(oMod, "UpdateItemRes", "hellbk_sfist", "hellbk_sresist");


    /* update stat artifacts to new statartifact script */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "lockofsunefireha", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "sigilofmystra", 4);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "tearofselune", 3);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "theeyeofvecna", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "thehandofvecna", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "themaskofvhaerun", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "theorbofdrago", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "thepyramidener", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "tymorasluckychar", 4);

    /* update epic spells to new charged versions */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_aegis",         3);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_annihilation",  3);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_armor_earth",   4);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_bigbyswarm",    3);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_call_earthchi", 3);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_callingoftheh", 3);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_chantofwardin", 3);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_contingency",   3);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_conversion",    4);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_cryoftheheave", 3);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_deathofmagic",  3);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_dirgeofthedea", 3);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_dust_to_dust",  3);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_element_shunt", 3);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_ensnare_trude", 3);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_eternalreturn", 3);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_gird_faith",    3);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_hearmeroar",    3);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_immutable_for", 3);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_instr_faith",   3);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_massspelldest", 3);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_miracle",       4);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_missilemirage", 3);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_natures_frail", 3);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_planar_beckon", 3);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_possumsfarce",  3);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_primal_catacl", 3);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_primalforce",   3);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_safe_box",      3);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_shroud_nature", 3);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_unbowedunbent", 3);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "es_winteriscomin", 3);

    HashSetSetLocalInt(oMod, "UpdateItemVer", "qc_dw_bchant1", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "qc_dw_bchant2", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "qc_dw_bchant3", 3);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "qc_dw_dchant1", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "qc_dw_dchant2", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "qc_dw_dchant3", 3);


    /* replace version 2 items */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "abosetam002", 2);        /* Primordial Heart */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "abosetbracer001", 2);    /* Spellguards of Netheril */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "abosetbracer003", 2);    /* Bracers of Many Eyes */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "abosethelm002", 2);      /* Nightglass Crown */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "abosetmisc003", 2);      /* Temporal Autocaster */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "abosetring002", 2);      /* Signet of Phelgethos */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "abosetring003", 2);      /* Stygian Band */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "abosetring004", 2);      /* Jewel of Minauros */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "abosetst001", 2);        /* Staff of Forsaken Sorcery */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "abosettr003", 2);        /* Runestaff of Abjuration */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "abosettr004", 2);        /* Runestaff of Conjuration */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "abosettr005", 2);        /* Runestaff of Divination */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "abosettr006", 2);        /* Runestaff of Enchantment */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "abosettr007", 2);        /* Runestaff of Evocation */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "abosettr008", 2);        /* Runestaff of Illusion */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "abosettr009", 2);        /* Runestaff of Necromancy */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "abosettr010", 2);        /* Runestaff of Transmutation */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "abysetarm001", 2);       /* Molted Scales of Obox-ob */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "abysetboot010", 2);      /* Corruption of the Mind */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "abysettr001", 2);        /* Sign of Orcus */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "arakinscasement", 2);    /* Arakin's Casement */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "asmoset005", 2);         /* The Serpent's Coil */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "asmoset006", 2);         /* Styxwalkers */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "asmoset012", 2);         /* Styxwalkers */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "asmoset013", 2);         /* Styxwalkers */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "asmoset014", 2);         /* Styxwalkers */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "asmoset015", 2);         /* Styxwalkers */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "asmoset016", 2);         /* Styxwalkers */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "asmoset017", 2);         /* Styxwalkers */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "asmoset018", 2);         /* Styxwalkers */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "biorejuvenator", 2);     /* Biorejuventor */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "bloodsport", 2);         /* Blood Sport */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "bloodthirst", 2);        /* Bloodthirst (AC longsword) */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "bootsofthetartar", 2);   /* Anklets of the Tartarian */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "bpfhiraikos", 2);        /* Breastplate of Hiraikos */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "ca_pm_lichsong", 2);     /* Lichsong */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "ca_sd_rift", 2);         /* Shadow Rift */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "callandor001", 2);       /* Callandor (AC longsword) */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "crownofradiance", 2);    /* Crown of Radiance */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "daggerofshieldin", 2);   /* Dagger of Shielding (AC dagger) */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "defendingblade", 2);     /* Defending Blade (AC katana) */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "duelistdagger", 2);      /* Duelist Dagger (AC dagger) */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "dulsethelm001", 2);      /* Helm of Darkened Vision */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "dustitem015", 2);        /* Halaster's Madness */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "dustitem026", 2);        /* Nixie's Lash */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "earthmothersrage", 2);   /* Earth Mother's Rage */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "elyhidcraft002", 2);     /* Elysian Flower */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "elyhiduse006", 2);       /* Greater Scabbard of Blessing */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "elysetarm001", 2);       /* Starfall Cassock */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "elysetarm004", 2);       /* Forestweave Jerkin */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "elysetbelt001", 2);      /* Inviolate Cincture */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "elysetboot003", 2);      /* Treads of the Exalted */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "elysetbracer001", 2);    /* Indomitable Bracers */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "elysetcl001", 2);        /* Amorian Drape */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "elysethelm006", 2);      /* Empyrean Lenses */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "elysetring001", 2);      /* Elysium Breach Ring */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "elysetring002", 2);      /* Elysium Breach Ring */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "elysetring003", 2);      /* Elysium Breach Ring */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "elysetring004", 2);      /* Elysium Breach Ring */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "elysetring005", 2);      /* Elysium Breach Ring */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "elysetsh005", 2);        /* Undying Flame */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "focus", 2);              /* Focus (AC rapier) */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "focus001", 2);           /* Focus (AC rapier) */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "greaterdefending", 2);   /* Greater Defending Blade (AC katana) */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "harperboots", 2);        /* Boots of the Wanderer */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellbow001", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellbow002", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellbow003", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellbow004", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellbow005", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellhidcraft011", 2);    /* Avernan Dragonblood Flowers */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellhidcraft012", 2);    /* Avernan Dragonblood Flowers */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellhidcraft013", 2);    /* Avernan Dragonblood Flowers */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellhiduse001", 2);      /* Abhorrent Vacuum */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellhiduse002", 2);      /* Infernal Weapon Item */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellhiduse003", 2);      /* Infernal Weapon Item */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellhiduse004", 2);      /* Infernal Weapon Item */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellhiduse008", 2);      /* Infernal Weapon Item */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellhidweap002", 2);     /* Mammon's Wrath */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellsetam002", 2);       /* Amulet of Unbroken Balance */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellsetarm006", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellsetarm007", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellsetarm010", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellsetarm016", 2);      /* Silks of the Arachill */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellsetarm017", 2);      /* Dance of Blades */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellsetbelt002", 2);     /* Obi of the Geisha */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellsetboot001", 2);     /* Nightmare Hooves */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellsetcl002", 2);       /* Folds of Fury */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellsetmisc002", 2);     /* Deck of Walls */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellsetweap010", 2);     /* Screaming Gale */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellsh001", 2);          /* Trappings of the Weave */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellsh002", 2);          /* Teardrop */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellsh003", 2);          /* Arcane Lustre */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellsh004", 2);          /* Effervescent Aura */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellweap039", 2);        /* Vitiarch's Talon */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellweap040", 2);        /* Stone Eater */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellweap041", 2);        /* Camizu's Strike */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellweap042", 2);        /* Deathcry */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellweap043", 2);        /* Offering of Asmodeus */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellweap044", 2);        /* Narzugon's Lance */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hellweap045", 2);        /* Circle of Unending Pain */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hivsetuse001", 2);       /* Hive Venom */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hivsetuse002", 2);       /* Hive Venom */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "hivsetuse003", 2);       /* Hive Venom */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "illithiditem004", 2);    /* Penumbrium Plate */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "illithiditem009", 2);    /* Prescient's Guard */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "illithiditem010", 2);    /* Mask of Mystra */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "illithiditem011", 2);    /* Psi Actuator */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "illithiditem013", 2);    /* Stoic Faith */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "illithiditem016", 2);    /* Rano's Vendetta */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "illithiditem017", 2);    /* Exo-array */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "illithiditem018", 2);    /* Rune of Return */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "illithiditem019", 2);    /* Amulet of Adaptation */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "illithiditem020", 2);    /* Belt of Bestial Resilience */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "illithiditem025", 2);    /* Ring of Windworking */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "illithiditem028", 2);    /* Psiforger's Boots */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "item100", 2);            /* Melf's Magnificent Mantle */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "item101", 2);            /* Balagarn's Barrier */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "item103", 2);            /* Sharantyr's Silks */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "item106", 2);            /* The Leadfoot */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "keynariprotectiv", 2);   /* Keynari Protective Fungus */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "kmfphide", 2);           /* Ka'Mrioga's Hide */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "locsethelm003", 2);      /* Blessed Silence */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "locsetsh003", 2);        /* Guardian Beneath the Sea */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "locsetuse002", 2);        /* Locathah Essence of the Whirlpool */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "locsetuse007", 2);       /* Epodes of Form Mastery */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "locsetuse008", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "locsetuse009", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "locsetuse010", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "locsetuse011", 2);
    HashSetSetLocalInt(oMod, "UpdateItemVer", "masksmischief", 2);      /* Mask's Mischief */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "moadweap001", 2);        /* MoaD weapons */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "moadweap002", 2);        /* MoaD weapons */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "moadweap003", 2);        /* MoaD weapons */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "moadweap004", 2);        /* MoaD weapons */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "moadweap005", 2);        /* MoaD weapons */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "moadweap007", 2);        /* MoaD weapons */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "moadweap008", 2);        /* MoaD weapons */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "moadweap009", 2);        /* MoaD weapons */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "moadweap010", 2);        /* MoaD weapons */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "moadweap011", 2);        /* MoaD weapons */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "moadweap012", 2);        /* MoaD weapons */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "moadweap013", 2);        /* MoaD weapons */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "moadweap014", 2);        /* MoaD weapons */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "moadweap015", 2);        /* MoaD weapons */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "moadweap016", 2);        /* MoaD weapons */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "moadweap017", 2);        /* MoaD weapons */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "moadweap018", 2);        /* MoaD weapons */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "moadweap019", 2);        /* MoaD weapons */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "moadweap020", 2);        /* MoaD weapons */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "moadweap021", 2);        /* MoaD weapons */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "moadweap022", 2);        /* MoaD weapons */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "moadweap023", 2);        /* MoaD weapons */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "moadweap024", 2);        /* MoaD weapons */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "moadweap025", 2);        /* MoaD weapons */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "moadweap026", 2);        /* MoaD weapons */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "moadweap027", 2);        /* MoaD weapons */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "moadweap028", 2);        /* MoaD weapons */
    HashSetSetLocalInt(oMod, "UpdateItemVer", "moadweap029", 2);        /* MoaD weapons */
*snip*

Truncated, too long for forum. And yes, this runs almost instantaneously, no perceptible lag, thanks in part to being hashset-based.

Funky

Modifié par FunkySwerve, 16 juin 2011 - 08:42 .


#17
GhostOfGod

GhostOfGod
  • Members
  • 863 messages
After rereading this and giving this a bit more thought:

Lazarus Magni wrote...

BTW your assumption is correct for the most part, certain items have been changed over time, but their resref's have not.


I suppose all you'd have to do is destroy all the items the player has and replace it with the item of the same res ref. If the item doesn't get recreated then that res ref is no longer there. Seems simple enough if my thinking is correct. Something like I posted above but simplified:

void ResRefMatchReplace(object oItem, object oTarget)
{
    string sResRef = GetResRef(oItem);
    DestroyObject(oItem);
    object oReplacement = CreateItemOnObject("sResRef", oTarget);
    if (!GetIsObjectValid(oReplacement))
    {
        //do stuff if there is no item with matching res ref.
    }
}

#include "x2_inc_switches"
void main()
{
    int iEvent = GetUserDefinedItemEventNumber();
    if (iEvent != X2_ITEM_EVENT_ACTIVATE) return;
    object oActivator = GetItemActivator();
    if (!GetIsDM(oActivator)) return;

    object oTarget = GetItemActivatedTarget();
    object oItem = GetFirstItemInInventory(oTarget);
    int iSlot;

    //Get items in inventory and replace if needed
    while (GetIsObjectValid(oItem))
    {
        //if item is a container, loop through items inside
        if (GetHasInventory(oItem))
        {
            object oConItem = GetFirstItemInInventory(oItem);
            while (GetIsObjectValid(oConItem))
            {
                ResRefMatchReplace(oConItem, oTarget);
                oConItem = GetNextItemInInventory(oItem);
            }
        }
        else
        {
            ResRefMatchReplace(oItem, oTarget);
        }
        oItem = GetNextItemInInventory(oTarget);
    }

    //Get equipped items and replace if necessary
    for (iSlot=0; iSlot<NUM_INVENTORY_SLOTS; iSlot++)
    {
        oItem = GetItemInSlot(iSlot, oTarget);
        if (GetIsObjectValid(oItem))
        {
            ResRefMatchReplace(oItem, oTarget);
        }
    }
}


P.S. This could easily be converted into an OnEnter type script as well. And only be done once by adding variable to the player after first run, as per Funky's suggestion.

Modifié par GhostOfGod, 16 juin 2011 - 09:30 .


#18
Lazarus Magni

Lazarus Magni
  • Members
  • 1 134 messages
Well guys thank you all for your help and suggestions. It is apparent to me I am going to have to try to recruit a scripter (idealy a whole team eventually) since my abilities in that department are minimul at best. It sounds like there are some pretty viable options here for someone who is a decent scripter to work with. I might pick you all's brains some more if you don't mind once I get closer to actually needing to impliment some of these things (once it's it near ready to launch, which hopefully won't be too long from now.)
Cheers, m8s!

#19
Greyfort

Greyfort
  • Members
  • 234 messages
// pc_update_v1
// created by: GhostOfGod
// altered by: Greyfort
//
/*
This code can be used by a DM item or placed in a triger in the very first
area a pc will enter mod. This will insure that a PC wont run around a
world with a +20 vorpal time stoping sword...
*/
void ResRefMatchReplace(object oItem, object oTarget)
{
string sResRef = GetResRef(oItem);
SetLocalInt(oItem,"Destroy",TRUE);
// orginal script destroy object
//DestroyObject(oItem);
object oReplacement = CreateItemOnObject("sResRef", oTarget);
if (!GetIsObjectValid(oReplacement))
{
//do stuff if there is no item with matching res ref.
// if item doesn't have resref dont destroy, flag PC for DM intervention
SetLocalInt(oItem,"Destroy",FALSE);
SetLocalInt(oItem,"DM_intrvn",TRUE);
}
// now check item flaged for destruction and destroy
if( GetLocalInt(oItem,"Destroy")==TRUE ){DestroyObject(oItem);}
}

#include "x2_inc_switches"
void main()
{
// NOTE: this is code for a tool by GhostOfGod
/*
int iEvent = GetUserDefinedItemEventNumber();
if (iEvent != X2_ITEM_EVENT_ACTIVATE) return;
object oActivator = GetItemActivator();
if (!GetIsDM(oActivator)) return;

object oTarget = GetItemActivatedTarget();
object oItem = GetFirstItemInInventory(oTarget);
*/
// NOTE: this is code for trigger, trigers work better at clearing equiped gear.
// so I have found Greyfort
// here you will have to decide what DB you are using nwn_db or nwnx_db
// example useing nwn_db
string sDM_Name = "Help_Script_MOD";//""+GetModuleName()+"_"+"SaVE_LOC";

object oTarget = GetEnteringObject();
object oItem = GetFirstItemInInventory(oTarget);

object oBadArea = GetObjectByTag("");
vector vBadVec = Vector(0.0,0.0,0.0);
location lbadloc = Location(oBadArea,vBadVec,0.0);

location lSave_Loc = GetCampaignLocation( sDM_Name,"Save_Loc",oTarget );
object oDflt_Start = GetObjectByTag("WP_oDflt_Start");
object oDM_Thrpy = GetNearestObjectByTag( "WP_oDM_Thrpy",oTarget );

int iSlot;
//------------------------------------------------------------------------------
// added check for update variable if false update if true jump to loc
// if update false update
if( GetCampaignInt(sDM_Name,"Gear_updtd")==0 )
{

//Get items in inventory and replace if needed
while (GetIsObjectValid(oItem))
{
//if item is a container, loop through items inside
if (GetHasInventory(oItem))
{
object oConItem = GetFirstItemInInventory(oItem);
while (GetIsObjectValid(oConItem))
{
ResRefMatchReplace(oConItem, oTarget);
oConItem = GetNextItemInInventory(oItem);
}
}
else
{
ResRefMatchReplace(oItem, oTarget);
}
oItem = GetNextItemInInventory(oTarget);
}

//Get equipped items and replace if necessary
for (iSlot=0; iSlot<NUM_INVENTORY_SLOTS; iSlot++)
{
oItem = GetItemInSlot(iSlot, oTarget);
if (GetIsObjectValid(oItem))
{
ResRefMatchReplace(oItem, oTarget);
}
}

// now if player flagged for DM intervention jump play to DM Therepy...
if ( GetLocalInt(oItem,"DM_intrvn")==TRUE)
{
// flag player not updated here:
SetCampaignInt(sDM_Name,"Gear_updtd",0);
// jump to DM_area
AssignCommand(oTarget,ClearAllActions(TRUE));
AssignCommand(oTarget,ActionJumpToObject( oDM_Thrpy ));
}

// now if player not flagged for DM intervention jump player to default start,
// or saved loc
if ( GetLocalInt(oItem,"DM_intrvn")==FALSE)
{

//jump to save loc if valid else jump to default start
if (lSave_Loc != lbadloc)
{
// flag player updated here:
SetCampaignInt(sDM_Name,"Gear_updtd",1);
// jump to save_lov
AssignCommand(oTarget,ClearAllActions(TRUE));
AssignCommand(oTarget,JumpToLocation( lSave_Loc ));
}
else
{
// flag player updated here:
SetCampaignInt(sDM_Name,"Gear_updtd",1);
// jump to default start
AssignCommand(oTarget,ClearAllActions(TRUE));
AssignCommand(oTarget,ActionJumpToObject( oDflt_Start ));
}
}
}//ENDO OF if( SetCampaignInt(sDM_Name,"Gear_updtd")==FALSE )

//------------------------------------------------------------------------------
// if update TRUE DONT update
if( GetCampaignInt(sDM_Name,"Gear_updtd")==1 )
{

//jump to save loc if valid else jump to default start
if (lSave_Loc != lbadloc)
{
// flag player updated here:
SetCampaignInt(sDM_Name,"Gear_updtd",TRUE);
// jump to save_lov
AssignCommand(oTarget,ClearAllActions(TRUE));
AssignCommand(oTarget,JumpToLocation( lSave_Loc ));
}
else
{
// flag player updated here:
SetCampaignInt(sDM_Name,"Gear_updtd",TRUE);
// jump to default start
AssignCommand(oTarget,ClearAllActions(TRUE));
AssignCommand(oTarget,ActionJumpToObject( oDflt_Start ));
}

}//END if( SetCampaignInt(sDM_Name,"Gear_updtd")==TRUE )

//[END OF SCRIPT//]
}

here is a altered script of ghosts it will check pcs gear and flagg if need dm intervention and update all others and then set var on pc updated or dm therpy. this would solve a one time issue and any grump from players losing items.

#20
Lazarus Magni

Lazarus Magni
  • Members
  • 1 134 messages
That's fantastic Grey, thank you! Just so I am clear on how to include this in a module open up the mod in the toolset:
go to tools, script editor to create a new script. Delete the initial (default) lines (1 void main, or whatever), Cut and paste, then save giving it a name. So now I have it in my mod. Then to get to run when players log in go to edit, module properties, events, and edit the on client enter event, and at the top of that put in a line like #include "script name"? Would that work?

Modifié par Lazarus Magni, 17 juin 2011 - 08:57 .


#21
GhostOfGod

GhostOfGod
  • Members
  • 863 messages
Just a heads up with Grey's version. If the player ends up with items that are no longer in the module, it will port them to the DM intervention waypoint if one exists. If you don't have a lot of DMs on or if there will be long periods of time without any DMs, you might want to make sure that the player won't just be stuck in some area until a DM logs on. You will also need a separate script to delete the items that are flagged for deletion since his version does not destroy the items that are obsolete.

You could make the area automated. Have a sign that explains why they are there with an object or a trigger or something that will delete the flagged items and then send the player on his/her way.

Just some thoughts.

#22
Lazarus Magni

Lazarus Magni
  • Members
  • 1 134 messages
Hmm ok, that's not going to work for me then, but still mighty handy I am sure for some. What seems like the simplest solution would be a systhesis of alot of these ideas. A script that fires once the first time a player logs in a particular PC, and then flags them so that it doesn't run on subsequent logins with that same PC, which updates all of their items to the current blueprints, and destorys any items that don't have blueprints.

#23
Failed.Bard

Failed.Bard
  • Members
  • 774 messages
  GhostOfGod's last script he posted would do essentially what you wanted, just his was based on an item activation, as opposed to an on enter.
  If you plan on doing a full item recreation of every player once, you'll need to make an area specifically for it to be done in, since they're likely to end up with items on the floor if their inventory was packed to begin with.

  I had written up one as well just to see mainly how I would do it compared to the other posters.  Mine requires a specifically tagged container in the area the player gets ported to in order to hold their "new" items, and due to the external storage method used in it cannot be used to remake "plot" items.

  The chest tag and validation ints stored on the item could be set to whatever you wanted.  All you would need to add to make mine run is a script that checks the player on entered to see if they've been "validated" yet.  The chest itself should be given a script that ports the player out of the area once all the items are removed from it.


// (6/16/2011) Failed Bard

void CreateNew (object oPC, object oItem);
void main()
{
 object oPC = GetEnteringObject();
 object oChest = GetNearestObjectByTag ("VALIDATION_CHEST");
 object oBagItem, oItem, oNewItem;
 int nSlot;
 int nCounter = 0;
 while (nCounter <= 13)
    {
     //nSlot = GetLootingSlot (nCounter);
     // oItem = GetItemInSlot  (nSlot, oPC);
     oItem = GetItemInSlot  (nCounter, oPC);
     if (!GetLocalInt (oItem, "VALID_6/16/2011"))
        {
         CreateNew (oChest, oItem);
        }
     nCounter ++;
    }
 oItem = GetFirstItemInInventory(oPC);
 while (GetIsObjectValid(oItem))
    {
     if (GetHasInventory (oItem))
        {
         oBagItem = GetFirstItemInInventory (oItem);
         if (!GetLocalInt (oBagItem, "VALID_6/16/2011"))
            {
             CreateNew (oChest, oBagItem);
            }
         oBagItem = GetNextItemInInventory (oItem);
        }
     if (!GetLocalInt (oItem, "VALID_6/16/2011"))
        {
         CreateNew (oChest, oItem);
        }
     oItem = GetNextItemInInventory(oPC);
    }
}
void CreateNew (object oPC, object oItem)
{
 if (GetPlotFlag (oItem))
    {
     SetLocalInt (oItem, "VALID_6/16/2011", TRUE);
    }
 else
    {
     object oNewItem = CreateItemOnObject (GetResRef (oItem), oPC, GetItemStackSize(oItem));
     SetLocalInt (oNewItem, "VALID_6/16/2011", TRUE);
     DestroyObject (oItem, 0.1);
    }
}

#24
GhostOfGod

GhostOfGod
  • Members
  • 863 messages
Ok. This should do everything that you want so far. It will require that each player have a "non drop database item" (though it could be altered to use the NWNdatabase or what not as well). Just plug you database item tag in the top of this script where it say "Tag of database item here". You will want to run this using the ExecuteScript function from your modules OnClientEnter script or the OnEnter of a trigger,etc..:

const string DATABASE_ITEM = "Tag of database item here";

void ResRefMatchReplace(object oItem, object oPC)
{
    string sResRef = GetResRef(oItem);
    if (GetTag(oItem) != DATABASE_ITEM)
    {
        object oReplacement = CreateItemOnObject("sResRef", oPC);
        if (!GetIsObjectValid(oReplacement))
        {
            //Do stuff if there is no item with matching res ref.
            //~Give the player some gold or XP for the inconvenience.
            //~Give the player some other item for the inconvenience.
            //~Send the player a message each time one of these items is destroyed.
            //~Do a combination of any of these.
            //~Etc..
            DestroyObject(oItem);
        }
        else
        {
            DestroyObject(oItem);
        }
    }
}

#include "x2_inc_switches"
void main()
{
    object oPC = GetEnteringObject();
    if (!GetIsPC(oPC)) return;
    object oDatabaseItem = GetItemPossessedBy(oPC, DATABASE_ITEM);
    if (GetLocalInt(oDatabaseItem, "FULL_ITEM_CHECK")) return;
    object oItem = GetFirstItemInInventory(oPC);
    int iSlot;

    //Get items in inventory and replace if needed
    while (GetIsObjectValid(oItem))
    {
        //if item is a container, loop through items inside
        if (GetHasInventory(oItem))
        {
            object oConItem = GetFirstItemInInventory(oItem);
            while (GetIsObjectValid(oConItem))
            {
                ResRefMatchReplace(oConItem, oPC);
                oConItem = GetNextItemInInventory(oItem);
            }
        }
        else
        {
            ResRefMatchReplace(oItem, oPC);
        }
        oItem = GetNextItemInInventory(oPC);
    }

    //Get equipped items and replace if necessary
    for (iSlot=0; iSlot<NUM_INVENTORY_SLOTS; iSlot++)
    {
        oItem = GetItemInSlot(iSlot, oPC);
        if (GetIsObjectValid(oItem))
        {
            ResRefMatchReplace(oItem, oPC);
        }
    }
    SetLocalInt(oDatabaseItem, "FULL_ITEM_CHECK", TRUE);
    ExportSingleCharacter(oPC);
}


Hopefully this works out for ya. Good luck.

Modifié par GhostOfGod, 18 juin 2011 - 07:57 .


#25
Lazarus Magni

Lazarus Magni
  • Members
  • 1 134 messages
First of all, thank you all so much for all the input and work. Sadly I am not sure if I will be able to get this project off the ground, but even if I don't hopefully these scripts will be of use to someone so that all this work was not for nothing.

Secondly Ghost could you elaborate on what a "non drop database item" is? Do you mean just a new item (and it's associated tag) created in the mod (via the toolset)?