Author Topic: a few questions about weapon level requirements...  (Read 650 times)

Legacy_zero-feeling

  • Sr. Member
  • ****
  • Posts: 287
  • Karma: +0/-0
a few questions about weapon level requirements...
« on: November 13, 2010, 12:30:41 am »


               so i'm sure theres tons of custom ILR scripts out there, i've seen about 7 (not tested yet), but what one works best?

are there any that can make it so only certain weapons, possibly with tag prefixes (blk_*weapon*) can be made to have level requirements, and not the standard weapons?

can this be done without adding a hak file?

any help is appreciated,
thanks
               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
a few questions about weapon level requirements...
« Reply #1 on: November 13, 2010, 12:37:34 am »


               I do not know if there is one already out there or not.  



Can it be done?   Yes



Can it be done without haks?  Yes.  



Basicly you turn off ILR.  And make a script to check all items that fire the OnEquip event.  if the character /weapon  does not meet the requirements you have the script unequip the weapon.



The only thing you really lose by turning off the ILR and useing a script for your systen is the nice red overlay that lets players know that they can not use the weapon befor buying it or tring to equip it first.  I guess you could always create them a widget that would let them check items in a store before they buy it if that bothers you .
               
               

               
            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
a few questions about weapon level requirements...
« Reply #2 on: November 13, 2010, 09:31:21 am »


               What lightfoot said. We use a variable-based system to do this. The only trick is to use clear all actions to prevent them from avoiding the restrictions (there are common tricks to avoiding such restrictions, though I'm not going to go into specifics, just offer the fix).

Here's the core nugget of code on our module onequip:

    if (!GetItemIsUsable(oItem, oPC)) {
        ForceUnequip(oPC, oItem);
        return;
    }

Here's the ForceUnequip function, which prevents the common tricks to avoid scripted ILR :

void ForceUnequip (object oTarget, object oItem) {
    if (!GetIsObjectValid(oTarget) || GetObjectType(oTarget) != OBJECT_TYPE_CREATURE)
        return;

    if (!GetIsObjectValid(GetArea(oTarget))) {
        DelayCommand(5.0, ForceUnequip(oTarget, oItem));
        return;
    }

    if (GetIsDead(oTarget)) {
        ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectResurrection(), oTarget);
        ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectHeal(GetMaxHitPoints(oTarget)), oTarget);

        DelayCommand(0.1, ForceUnequip(oTarget, oItem));
    } else {
        AssignCommand(oTarget, ClearAllActions(TRUE));

        AssignCommand(oTarget, ActionUnequipItem(oItem));
        AssignCommand(oTarget, ActionDoCommand(SetCommandable(TRUE)));
        AssignCommand(oTarget, SetCommandable(FALSE));
    }
}
I've cut out a few server-specific items, but the core functionality is there.

As for the GetItemIsUsable function, it's an include of it's own. I'm including it to show you a variable-based ILR system that can restrict usage based on numerous factors besides level, like class, ability score, and the like. The code is acaos':


int GetHasItemFeatRequirements (object oItem, object oUser=OBJECT_SELF) {
    int nBaseType = GetBaseItemType(oItem);

    if (nBaseType == BASE_ITEM_SMALLSHIELD ||
        nBaseType == BASE_ITEM_LARGESHIELD ||
        nBaseType == BASE_ITEM_TOWERSHIELD) {

        if (!GetHasFeat(FEAT_SHIELD_PROFICIENCY, oUser)) {
            /* check specifically for the Ur-Ward and Impasse; consider
             * examining the item's properties in the future instead of
             * having a specific resref check */

            string sRes = GetResRef(oItem);

            return (sRes == "randsh104" || sRes == "randsh105");
        }

        return TRUE;
    }

    if (nBaseType == BASE_ITEM_ARMOR) {
        int nBaseAC = GetItemACBase(oItem);

        if (nBaseAC >= 6)
            return GetHasFeat(FEAT_ARMOR_PROFICIENCY_HEAVY, oUser);

        if (nBaseAC >= 4)
            return GetHasFeat(FEAT_ARMOR_PROFICIENCY_MEDIUM, oUser);

        if (nBaseAC >= 1)
            return GetHasFeat(FEAT_ARMOR_PROFICIENCY_LIGHT, oUser);

        return TRUE;
    }

    /* XXX: add support for weapon proficiency feats in the future */

    return TRUE;
}

string GetHasItemTagRequirements (object oItem, object oUser=OBJECT_SELF) {
    string sTag = GetTag(oItem);
    string sRes = GetResRef(oItem);

    if (GetStringLeft(sTag, 4) == "rtyg") {
        if (!GetPCAccomplishment(oUser, PCACC_IMMORTAL))
            return "You are not immortal and cannot use that!";

        return "";
    }

    if (sRes == "lolthsmortalcoil" || sRes == "lolthsguard" || sRes == "bandofthedarkque" || sRes == "thespidersignet") {
        if (!GetPCAccomplishment(oUser, PCACC_LOLTH))
            return "You have not banished Lolth from this plane and cannot use that!";

        return "";
    }

    if (GetStringLeft(sRes, 8) == "dachitem") {
        if (!GetPCAccomplishment(oUser, PCACC_DEEPONE))
            return "You have not slain Dach'xilith'az'ichityl and cannot use that!";

        return "";
    }

    if (GetStringLeft(sRes, 6) == "ssith5" && !GetItemIsAmmo(oItem)) {
        if (!GetPCAccomplishment(oUser, PCACC_SSITHRAK))
            return "You have not bathed in the blood of Ssssy'is and cannot use that!";

        return "";
    }

    if (GetStringLeft(sRes, 8) == "dustitem" || GetStringLeft(sRes, 8) == "dustbbow") {
        if (!GetPCAccomplishment(oUser, PCACC_DUSTBONE))
            return "You have not slain Dustbone and cannot use that!";

        return "";
    }

    if (GetStringLeft(sRes, 12) == "illithiditem") {
        if (!GetPCAccomplishment(oUser, PCACC_ILLITHID))
            return "You have not mastered the Overmind and cannot use that!";

        /* don't return because some illithid items have additional checks below */
    }


    int nItemHellLevel = GetLocalInt(oItem, "HL");

    if (nItemHellLevel > 0) {
        if (nItemHellLevel > GetPCAccomplishment(oUser, PCACC_HELLS) || GetHitDiceIncludingLLs(oUser) < 55)
            return "You have not conquered enough layers of the Hells to use that!";
    }


    /*  ---- Sequencers for Casters only---- */
    if (GetItemIsSequencer(oItem) &&
        GetLevelByclass(class_TYPE_WIZARD, oUser) < 1 && GetLevelByclass(class_TYPE_BARD, oUser) < 1 &&
        GetLevelByclass(class_TYPE_CLERIC, oUser) < 1 && GetLevelByclass(class_TYPE_DRUID, oUser) < 1 &&
        GetLevelByclass(class_TYPE_SORCERER, oUser) < 1) {

        return "You lack sufficient magical power to use that!";
    }


    /* Holy Symbols */
    if ((sRes == "illithiditem023") && ((GetLevelByclass(class_TYPE_CLERIC, oUser) < 30) ||
            (GetAlignmentGoodEvil(oUser) != ALIGNMENT_GOOD)))
        return "You lack the faith and heart needed to wield that!";

    if ((sRes == "illithiditem024") && ((GetLevelByclass(class_TYPE_CLERIC, oUser) < 30) ||
            (GetAlignmentGoodEvil(oUser) != ALIGNMENT_EVIL)))
        return "You lack the faith and evil needed to wield thatl!";

    if (sTag == "HolySymbolofCyric" && ((GetAlignmentGoodEvil(oUser) != ALIGNMENT_EVIL) ||
            (GetAlignmentLawChaos(oUser) != ALIGNMENT_CHAOTIC)))
        return "You lack the faith needed to wield that!";

    if (sTag == "HolySymbolofLathander" && ((GetAlignmentGoodEvil(oUser) != ALIGNMENT_GOOD) ||
            (GetAlignmentLawChaos(oUser) != ALIGNMENT_NEUTRAL)))
        return "You lack the faith needed to wield that!";


    /* Exclusive Items */
    int nExclusive = GetLocalInt(oItem, "Exclusive");
    if (nExclusive) {
        int i, nCheckExcl;
        object oCheck;

        for (i = 0; i < NUM_INVENTORY_SLOTS; i++) {
            object oCheck = GetItemInSlot(i, oUser);

            if (!GetIsObjectValid(oCheck = GetItemInSlot(i, oUser)) || oCheck == oItem)
                continue;

            int nCheckExcl = GetLocalInt(oCheck, "Exclusive");
            if (nCheckExcl & nExclusive)
                return "You may not use that in conjunction with your " + GetName(oCheck) + "!";
        }
    }

    /* Ego items and relics */
    int nRelic = GetLocalInt(oItem, "Relic");
    if (nRelic) {
        int i, nCheckRelic;
        object oCheck;

        for (i = 0; i < NUM_INVENTORY_SLOTS; i++) {
            object oCheck = GetItemInSlot(i, oUser);

            if (!GetIsObjectValid(oCheck = GetItemInSlot(i, oUser)) || oCheck == oItem)
                continue;

            int nCheckRelic = GetLocalInt(oCheck, "Relic");
            if (nCheckRelic && (nRelic < 0 || nCheckRelic < 0 || nRelic != nCheckRelic))
                return "You may not use that in conjunction with your " + GetName(oCheck) + "!";
        }
    }


    int nTag = GetLocalInt(oItem, "ITR");
    if (nTag && !GetPCAccomplishment(oUser, nTag))
        return "You do not have the necessary accomplishment to use that!";

    if (GetStringLeft(sRes, 7) == "abyweap") {
        if (!GetPCAccomplishment(oUser, PCACC_ABYSS_DEMOGORGON_MINI1) &&
            !GetPCAccomplishment(oUser, PCACC_ABYSS_GRAZZT_MINI1)     &&
            !GetPCAccomplishment(oUser, PCACC_ABYSS_JUIBLEX_MINI1)    &&
            !GetPCAccomplishment(oUser, PCACC_ABYSS_OBOXOB_MINI1)     &&
            !GetPCAccomplishment(oUser, PCACC_ABYSS_ORCUS_MINI1))
            return "You do not have the necessary accomplishment to use that!";
    }

    return "";
}

int GetItemIsUsable (object oItem, object oUser=OBJECT_SELF, int bFeedback=TRUE) {
    int nItemLevel = GetLocalInt(oItem, "ILR");

    if (nItemLevel > GetHitDiceIncludingLLs(oUser)) {
        if (bFeedback)
            FloatingTextStringOnCreature("<cþ>You must be level " + IntToString(nItemLevel) + " to use that!</c>",
                oUser, FALSE);

        return FALSE;
    }


    string sItemTag = GetHasItemTagRequirements(oItem, oUser);

    if (sItemTag != "") {
        if (bFeedback)
            FloatingTextStringOnCreature("<cþ>" + sItemTag + "</c>", oUser, FALSE);

        return FALSE;
    }


    int nItemUMD = GetLocalInt(oItem, "IUMDR");

    if (nItemUMD > 0 && GetSkillRank(SKILL_USE_MAGIC_DEVICE, oUser, TRUE) >= nItemUMD) {
        if (bFeedback > 0)
            FloatingTextStringOnCreature("<cþ>Your Use Magic Device skill allows you to use this item!></c>", oUser, FALSE);

        return TRUE;
    }


    string sItemclass = GetLocalString(oItem, "ICLR");

    if (sItemclass != "") {
        int i, j, nAndCount, nOrCount;

        nAndCount = GetStringSubStrings(sItemclass);

        for (i = 0; i < nAndCount; i++) {
            int nOr = 0;
            string sAnd = GetStringSubString(sItemclass, i);

            if (FindSubString(sAnd, "<") >= 0) {
                int nclass = StringToInt(GetStringSubString(sAnd, 0, "<"));
                int nRequire = StringToInt(GetStringSubString(sAnd, 1, "<"));

                if (GetLevelByclass(nclass, oUser) >= nRequire) {
                    if (bFeedback)
                        FloatingTextStringOnCreature("<cþ>Your class levels are too high to use that!</c>",
                            oUser, FALSE);

                    return FALSE;
                }

                continue;
            }

            nOr = 0;
            nOrCount = GetStringSubStrings(sAnd, "|");

            for (j = 0; j < nOrCount; j++) {
                string sOr = GetStringSubString(sAnd, j, "|");

                int nclass = StringToInt(GetStringSubString(sOr, 0, "="));
                int nRequire = StringToInt(GetStringSubString(sOr, 1, "="));

                if (GetLevelByclass(nclass, oUser) >= nRequire)
                    nOr++;
            }

            if (nOrCount > 0 && nOr < 1) {
                if (bFeedback)
                    FloatingTextStringOnCreature("<cþ>You do not have the necessary class levels to use that!</c>",
                        oUser, FALSE);

                return FALSE;
            }
        }
    }


    string sItemAbilReq = GetLocalString(oItem, "IAR");

    if (sItemAbilReq != "") {
        int i, j, nOr, nAndCount, nOrCount;

        nAndCount = GetStringSubStrings(sItemAbilReq);

        for (i = 0; i < nAndCount; i++) {
            string sAnd = GetStringSubString(sItemAbilReq, i);

            if (FindSubString(sAnd, "<") >= 0) {
                int nRequire, nAbility = StringToInt(GetStringSubString(sAnd, 0, "<"));
                string sRequire = GetStringSubString(sAnd, 1, "<");

                if (GetStringLeft(sRequire, 1) == "*")
                    nRequire = GetAbilityScore(oUser, StringToInt(GetSubString(sRequire, 1, 1)));
                else
                    nRequire = StringToInt(sRequire);

                if (GetAbilityScore(oUser, nAbility, TRUE) >= nRequire) {
                    if (bFeedback)
                        FloatingTextStringOnCreature("<cþ>Your ability scores are too high to use that!</c>",
                            oUser, FALSE);

                    return FALSE;
                }

                continue;
            }

            nOr = 0;
            nOrCount = GetStringSubStrings(sAnd, "|");

            for (j = 0; j < nOrCount; j++) {
                string sOr = GetStringSubString(sAnd, j, "|");

                int nAbility = StringToInt(GetStringSubString(sOr, 0, "="));
                int nRequire = StringToInt(GetStringSubString(sOr, 1, "="));

                if (GetAbilityScore(oUser, nAbility, TRUE) >= nRequire)
                    nOr++;
            }

            if (nOrCount > 0 && nOr < 1) {
                if (bFeedback)
                    FloatingTextStringOnCreature("<cþ>You do not have the necessary ability scores to use that!</c>",
                        oUser, FALSE);

                return FALSE;
            }
        }
    }


    string sItemFeatReq = GetLocalString(oItem, "IFR");

    if (sItemFeatReq != "") {
        int i, j, nOr, nAndCount, nOrCount;

        nAndCount = GetStringSubStrings(sItemFeatReq);

        for (i = 0; i < nAndCount; i++) {
            string sAnd = GetStringSubString(sItemFeatReq, i);

            nOr = 0;
            nOrCount = GetStringSubStrings(sAnd, "|");

            for (j = 0; j < nOrCount; j++) {
                string sOr = GetStringSubString(sAnd, j, "|");

                int nFeat = StringToInt(sOr);

                if (GetKnowsFeat(nFeat, oUser))
                    nOr++;
            }

            if (nOrCount > 0 && nOr < 1) {
                if (bFeedback)
                    FloatingTextStringOnCreature("<cþ>You do not have the necessary feats to use that!</c>",
                        oUser, FALSE);

                return FALSE;
            }
        }
    }


    string sItemSkillReq = GetLocalString(oItem, "ISR");

    if (sItemSkillReq != "") {
        int i, j, nOr, nAndCount, nOrCount;

        nAndCount = GetStringSubStrings(sItemSkillReq);

        for (i = 0; i < nAndCount; i++) {
            string sAnd = GetStringSubString(sItemSkillReq, i);

            if (FindSubString(sAnd, "<") >= 0) {
                int nSkill = StringToInt(GetStringSubString(sAnd, 0, "<"));
                int nRequire = StringToInt(GetStringSubString(sAnd, 1, "<"));

                if (GetSkillRank(nSkill, oUser, TRUE) >= nRequire) {
                    if (bFeedback)
                        FloatingTextStringOnCreature("<cþ>Your skills are too high to use that!</c>",
                            oUser, FALSE);

                    return FALSE;
                }

                continue;
            }

            nOr = 0;
            nOrCount = GetStringSubStrings(sAnd, "|");

            for (j = 0; j < nOrCount; j++) {
                string sOr = GetStringSubString(sAnd, j, "|");

                int nSkill = StringToInt(GetStringSubString(sOr, 0, "="));
                int nRequire = StringToInt(GetStringSubString(sOr, 1, "="));

                if (GetSkillRank(nSkill, oUser, TRUE) >= nRequire)
                    nOr++;
            }

            if (nOrCount > 0 && nOr < 1) {
                if (bFeedback)
                    FloatingTextStringOnCreature("<cþ>You do not have the necessary skills to use that!</c>",
                        oUser, FALSE);

                return FALSE;
            }
        }
    }


    int nItemQuasi = GetLocalInt(oItem, "IQCR");

    if (nItemQuasi != 0) {
        if (nItemQuasi < 0 && GetQuasiclass(oUser) != 0) {
            if (bFeedback)
                FloatingTextStringOnCreature("<cþ>You cannot use that if you belong to a quasiclass!</c>", oUser, FALSE);

            return FALSE;
        } else if (nItemQuasi > 0 && GetQuasiclass(oUser) != nItemQuasi) {
            if (bFeedback)
                FloatingTextStringOnCreature("<cþ>You do not belong to the right quasiclass to use that!</c>", oUser, FALSE);

            return FALSE;
        }
    }


    int nItemRace = GetLocalInt(oItem, "IRR");

    if (nItemRace != 0) {
        int bExclude = FALSE, nRace = GetRacialType(oUser);

        if (nItemRace < 0) {
            bExclude  = TRUE;
            nItemRace = -nItemRace;
        }

        if (GetStringLowerCase(GetSubRace(oUser)) == "juggernaut" ||
            GetQuasiclass(oUser) == QUASIclass_ACCURSED_PARIAH)
            nRace = RACIAL_TYPE_CONSTRUCT;

        nItemRace -= 1;

        if (bExclude && nRace == nItemRace) {
            if (bFeedback)
                FloatingTextStringOnCreature("<cþ>Your race cannot use that!</c>", oUser, FALSE);

            return FALSE;
        } else if (!bExclude && nRace != nItemRace) {
            if (bFeedback)
                FloatingTextStringOnCreature("<cþ>You do not have the necessary race to use that!</c>", oUser, FALSE);

            return FALSE;
        }
    }


    int nItemAlign = GetLocalInt(oItem, "IAGER");

    if (nItemAlign > 0 && GetAlignmentGoodEvil(oUser) != nItemAlign) {
        if (bFeedback)
            FloatingTextStringOnCreature("<cþ>You do not have the necessary alignment to use that!</c>", oUser, FALSE);

        return FALSE;
    }


    nItemAlign = GetLocalInt(oItem, "IALCR");

    if (nItemAlign > 0 && GetAlignmentLawChaos(oUser) != nItemAlign) {
        if (bFeedback)
            FloatingTextStringOnCreature("<cþ>You do not have the necessary alignment to use that!</c>", oUser, FALSE);

        return FALSE;
    }


    string sItemInv = GetLocalString(oItem, "IIR");
    if (sItemInv != "" && !GetIsObjectValid(GetItemPossessedBy(oUser, sItemInv))) {
        if (bFeedback)
            FloatingTextStringOnCreature("<cþ>You do not have the necessary item in inventory to use that!</c>", oUser, FALSE);

        return FALSE;
    }


    if (GetLocalInt(oItem, "NoOffhand") &&
        oItem == GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oUser)) {

        if (bFeedback)
            FloatingTextStringOnCreature("<cþ>You cannot use that in your off hand!</c>", oUser, FALSE);

        return FALSE;
    }


    int nDisequip = GetLocalInt(oItem, "Disequipped");
    if (nDisequip) {
        int nRealTime = GetLocalInt(GetModule(), "realtime");

        if (nRealTime > 0 && nDisequip > nRealTime) {
            if (bFeedback)
                FloatingTextStringOnCreature("<cþ>You are still recovering that item!</c>", oUser, FALSE);

            return FALSE;
        }
    }


    int nDiseaseBlock = GetLocalInt(oUser, "DiseaseBlockEquip");
    if (nDiseaseBlock && GetIsObjectValid(oItem)) {
        int i;

        for (i = 0; i < 11; i++) {
            if (!(nDiseaseBlock & (1 << i)))
                continue;

            if (oItem == GetItemInSlot(i, oUser)) {
                if (bFeedback)
                    FloatingTextStringOnCreature("<cþ>Your limbs are too rotted to equip that!</c>", oUser, FALSE);

                return FALSE;
            }
        }
    }

    return TRUE;
}

Funky
               
               

               
            

Legacy_zero-feeling

  • Sr. Member
  • ****
  • Posts: 287
  • Karma: +0/-0
a few questions about weapon level requirements...
« Reply #3 on: November 13, 2010, 02:39:08 pm »


               holy hell man!!!
not really sure what to do with all this, it just puts more questions into my head 'Image gonna have to go over it a few times, but i'm sure i'll be able to figure out whats going on.

i do have one question, theres a certain server named "three towns" i've played on for a long time that has level requirements set and still has the red showing if you can't use the item, is this what this script does? that is basicly what i'd like for my server, the red glow to still be there. 'Image

the main reason for this question is to restrict the use of certain weapons to a higher level than the base requirements set them to. such items would have set prefixes like tpst_ or blk_. i just want to make sure i've explained what i'm looking for in enough detail, seems i tend to notdo this sometimes. 'Image

thanks
               
               

               
            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
a few questions about weapon level requirements...
« Reply #4 on: November 13, 2010, 06:29:29 pm »


               No, the only way to get the red is via a hak the players would have to download, or an engine hack, one that hasn't been done yet to my knowledge.



As for what to do with this, it's simply an example of variable-based ILR. The tags of the items just don't matter. If you wanted to restrict an item to level 30 or above, you would simply set the int ILR to a value of 30 on the item. This is convenient in that it frees up tags for other uses, and requires less script redundancy.



Funky
               
               

               
            

Legacy_zero-feeling

  • Sr. Member
  • ****
  • Posts: 287
  • Karma: +0/-0
a few questions about weapon level requirements...
« Reply #5 on: November 13, 2010, 08:35:59 pm »


               i see, well i ask cause the above mentioned server has no haks, still has the red, and has items set to certain levels. i tried to ask one of thier dev team, but got nothing.i was thinking there was maybe a way to do this via NWNX2 or something, seems anything else can be.

thanks for the script and the help, i will have to think about what my next step s now.
               
               

               
            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
a few questions about weapon level requirements...
« Reply #6 on: November 13, 2010, 09:39:41 pm »


               The other possiblility is that they set the item levels by adjusting costs - that's certainly doable serverside, but far less practical, in my book - our players just don't miss the red that much, in my experience, and it's a fair bit more work than a simple var set (nevermind that it can only do ILR, not other restrictions, like feat requirements, class level requirements, and so on). Eh, to each his own.



Funky
               
               

               
            

Legacy_Baragg

  • Sr. Member
  • ****
  • Posts: 496
  • Karma: +0/-0
a few questions about weapon level requirements...
« Reply #7 on: November 14, 2010, 02:12:02 am »


               If it is a store couldn't you basically have the store load items for sale from a db, but have this happen when the store is opened by the PC, get he pc level on opening then as the store is loaded if the pc is too low a level to acquire the item change the color of the name of the item at that time?
               
               

               
            

Legacy_zero-feeling

  • Sr. Member
  • ****
  • Posts: 287
  • Karma: +0/-0
a few questions about weapon level requirements...
« Reply #8 on: November 16, 2010, 07:21:37 pm »


               well, thanks for the help, still not sure what i will do about this right now, but at least now i have an idea what i can do.

thanks again.