//------------------------------------------------------------------------------ /* Use Magic Device Check. Simple use magic device check to prevent abuse of the engine level implementation of use magic device This function is not supposed to mirror the 3E use magic device mechanics. Returns TRUE if the Spell is allowed to be cast, either because the character is allowed to cast it or he has won the required UMD check returns TRUE if ... spell not cast by an item ... item is not a scroll (may be extended) ... caster has levels in wiz, bard, sorc ... caster is no rogue and has no UMD skill ... caster has memorized this spell ... the property corresponding to the spell does not exist (2da inconsistency) ... a UMD check against 25+InnateLevel of the spell is won Note: I am not using the effective level of the spell for DC calculation but instead the lowest possible effective level. This is by design to allow rogues to use most low level scrolls in the game (i.e. light scrolls have an effective level 5 but a lowest effective level of 1 and we want low level rogues to cast these spells..) Setting a Local Interger called X2_SWITCH_CLASSIC_UMD (TRUE) on the Module will result in this function to return TRUE all the time User's can change this default implementation by modifing this file */ //------------------------------------------------------------------------------ #include "x2_inc_switches" #include "x2_inc_itemprop" int X2_UMD() { // if (GetModuleSwitchValue(MODULE_SWITCH_ENABLE_UMD_SCROLLS) == FALSE) // { // return TRUE; // } object oItem = GetSpellCastItem(); object oPC = GetItemPossessor(oItem); string sPC = GetName(oPC); //SpeakString("The item possesors name is "+sPC,TALKVOLUME_TALK); // Spell not cast from an item, exit if (!GetIsObjectValid(oItem)) { return TRUE; // Spell not cast by item, UMD not required } // ------------------------------------------------------------------------- // Only Scrolls are subject to our default UMD Check // ------------------------------------------------------------------------- int nBase = GetBaseItemType(oItem); if ( nBase != BASE_ITEM_SPELLSCROLL) { return TRUE; // spell not cast from a scroll } // ------------------------------------------------------------------------- // Ignore scrolls that have no use limitations (i.e. raise dead) // ------------------------------------------------------------------------- if (!IPGetHasUseLimitation(oItem)) { return TRUE; } object oCaster = OBJECT_SELF; /* // ------------------------------------------------------------------------- // Wizards and Sorcerors are supposed to cast scrolls via spellcraft // ------------------------------------------------------------------------- if (GetLevelByClass(CLASS_TYPE_WIZARD,oCaster) >0 ||GetLevelByClass(CLASS_TYPE_SORCERER,oCaster) >0 || nBard>0) { // ------------------------------------------------------------------------- // We only punish rogues, so other classes cast for free :) // ------------------------------------------------------------------------- return TRUE; } // ------------------------------------------------------------------------- // If the caster used the item and has no UMD Skill and is not a rogue // thus we assume he must be allowed to use it because the engine // prevents people that are not capable of using an item from using it.... // ------------------------------------------------------------------------- if (!GetHasSkill(SKILL_USE_MAGIC_DEVICE, oCaster) && (GetLevelByClass(CLASS_TYPE_ROGUE,oCaster) ==0 ) && (GetLevelByClass(CLASS_TYPE_ASSASSIN,oCaster) ==0 ) && (GetLevelByClass(CLASS_TYPE_SHADOWDANCER,oCaster) ==0 )) { // --------------------------------------------------------------------- //SpeakString("I have no UMD, thus I can cast the spell... "); // --------------------------------------------------------------------- return TRUE; } */ //Deleneated the following Baragg // ------------------------------------------------------------------------- // If scroll class restrictions match caster class, // then there is no need for UMD check // ------------------------------------------------------------------------- // itemproperty ipRestriction = GetFirstItemProperty(oItem); // while (GetIsItemPropertyValid(ipRestriction)) // { // if (GetItemPropertyType(ipRestriction) == ITEM_PROPERTY_USE_LIMITATION_CLASS) // { // if ((GetItemPropertySubType(ipRestriction) == IP_CONST_CLASS_WIZARD && GetLevelByClass(CLASS_TYPE_WIZARD, oCaster) > 0) || // (GetItemPropertySubType(ipRestriction) == IP_CONST_CLASS_SORCERER && GetLevelByClass(CLASS_TYPE_SORCERER, oCaster) > 0) || // (GetItemPropertySubType(ipRestriction) == IP_CONST_CLASS_BARD && GetLevelByClass(CLASS_TYPE_BARD, oCaster) > 0) || // (GetItemPropertySubType(ipRestriction) == IP_CONST_CLASS_CLERIC && (GetLevelByClass(CLASS_TYPE_CLERIC, oCaster) > 0 || GetLevelByClass(CLASS_TYPE_FAVORED_SOUL, oCaster) > 0)) || // (GetItemPropertySubType(ipRestriction) == IP_CONST_CLASS_DRUID && (GetLevelByClass(CLASS_TYPE_DRUID, oCaster) > 0 || GetLevelByClass(CLASS_TYPE_SPIRIT_SHAMAN, oCaster) > 0)) || // (GetItemPropertySubType(ipRestriction) == IP_CONST_CLASS_PALADIN && GetLevelByClass(CLASS_TYPE_PALADIN, oCaster) > 0) || // (GetItemPropertySubType(ipRestriction) == IP_CONST_CLASS_RANGER && GetLevelByClass(CLASS_TYPE_RANGER, oCaster) > 0)) // { // return TRUE; // } // } // ipRestriction = GetNextItemProperty(oItem); // } int nSpellID = GetSpellId(); // ------------------------------------------------------------------------- // if we knew that spell we could also cast it from an item (may be redundant) // ------------------------------------------------------------------------- if(GetHasSpell(nSpellID)>0) { //SpeakString("I have memorized this spell, I must be able to cast it without UMD "); return TRUE; } string sPropID = Get2DAString("des_crft_spells","IPRP_SpellIndex",nSpellID); // ------------------------------------------------------------------------- //I am using des_crft_spells.2da Innate Level column here, not (as would be correct) //the IPPR_Spells.2da InnateLvl column, because some of the scrolls in //the game (i.e. light) would not be useable (DC 30+) // ------------------------------------------------------------------------- int nInnateLevel = StringToInt(Get2DAString("des_crft_spells","Level",nSpellID)); int nSkill = SKILL_USE_MAGIC_DEVICE; string sInnateLevel = Get2DAString("des_crft_spells","Level",nSpellID); //SpeakString("The scrolls innatelevel is "+sInnateLevel,TALKVOLUME_TALK); string sSpellID = IntToString(nSpellID); //SpeakString("Spell Id number is "+sSpellID,TALKVOLUME_TALK); int nPropID = StringToInt(sPropID); if (nPropID == 0) { // SpeakString("***X2UseMagicDevice (Warning): Found no property matching SpellID "+ IntToString(nSpellID)); return TRUE; } //The following by Baragg //blah 4-23-08 int nWiz, nPrst, nRngr, nPally, nDrud, nSorc, nBard, nArcane, nDivine, nPlyrArc, nPlyrDiv, nRog, nAss, nShad; //Establish the caster classes/level/ and weather or not they are arcane //or divine casters. Also establish the Roguely types nRog = GetLevelByClass(CLASS_TYPE_ROGUE, oPC); if(nRog > 0){nRog = 1;} string sRog = IntToString(nRog); nBard = GetLevelByClass(CLASS_TYPE_BARD,oPC); if(nBard > 0){nPlyrArc = 1;} string sBard = IntToString(nBard); if(nBard > 0){nRog = 1;} nWiz = GetLevelByClass(CLASS_TYPE_WIZARD,oPC); if(nWiz > 0){nPlyrArc = 1;} string sWiz = IntToString(nWiz); nPrst = GetLevelByClass(CLASS_TYPE_CLERIC,oPC); if(nPrst > 0){nPlyrDiv = 1;} string sPrst = IntToString(nPrst); nRngr = GetLevelByClass(CLASS_TYPE_RANGER,oPC); if(nRngr > 0){nPlyrDiv = 1;} string sRngr = IntToString(nRngr); nPally = GetLevelByClass(CLASS_TYPE_PALADIN,oPC); if(nPally > 0){nPlyrDiv = 1;} string sPally = IntToString(nPally); nDrud = GetLevelByClass(CLASS_TYPE_DRUID,oPC); if(nDrud > 0){nPlyrDiv = 1;} string sDrud = IntToString(nDrud); nSorc = GetLevelByClass(CLASS_TYPE_SORCERER,oPC); if(nSorc > 0){nPlyrArc = 1;} string sSorc = IntToString(nSorc); // SpeakString("Player Rogue level is "+sRog,TALKVOLUME_TALK); // SpeakString("Player Bard level is "+sBard,TALKVOLUME_TALK); // SpeakString("Player Wizard level is "+sWiz,TALKVOLUME_TALK); // SpeakString("Player Cleric level is "+sPrst,TALKVOLUME_TALK); // SpeakString("Player Ranger level is "+sRngr,TALKVOLUME_TALK); // SpeakString("Player Paladin level is "+sPally,TALKVOLUME_TALK); // SpeakString("Player Druid level is "+sDrud,TALKVOLUME_TALK); // SpeakString("Player Sorcerer level is "+sSorc,TALKVOLUME_TALK); //Establish weather or not the scroll has divine or arcane restrictions //then set an interger indicating which itemproperty ipRestriction1 = GetFirstItemProperty(oItem); while (GetIsItemPropertyValid(ipRestriction1)) { if (GetItemPropertySubType(ipRestriction1) == IP_CONST_CLASS_WIZARD) { nArcane = 1; } if (GetItemPropertySubType(ipRestriction1) == IP_CONST_CLASS_BARD) { nArcane = 1; } if (GetItemPropertySubType(ipRestriction1) == IP_CONST_CLASS_SORCERER) { nArcane = 1; } if (GetItemPropertySubType(ipRestriction1) == IP_CONST_CLASS_CLERIC) { nDivine = 1; } if (GetItemPropertySubType(ipRestriction1) == IP_CONST_CLASS_RANGER) { nDivine = 1; } if (GetItemPropertySubType(ipRestriction1) == IP_CONST_CLASS_PALADIN) { nDivine = 1; } if (GetItemPropertySubType(ipRestriction1) == IP_CONST_CLASS_DRUID) { nDivine = 1; } ipRestriction1 = GetNextItemProperty(oItem); } string sArcane = IntToString(nArcane); string sDivine = IntToString(nDivine); string sPlyrArc = IntToString(nPlyrArc); string sPlyrDiv = IntToString(nPlyrDiv); // SpeakString("Player Arcane set to "+sPlyrArc,TALKVOLUME_TALK); // SpeakString("Player Divine set to "+sPlyrDiv,TALKVOLUME_TALK); // SpeakString("Arcane set to "+sArcane, TALKVOLUME_TALK); // SpeakString("Divine set to "+sDivine, TALKVOLUME_TALK); //This should be where the arcane scrolls get compared to arcanetype //casterlevels if(nArcane == 1) { if(nPlyrArc == 1) { if(nBard >= nInnateLevel) { if(!nInnateLevel < 7) { effect ePuff = EffectVisualEffect(-1); ApplyEffectToObject(DURATION_TYPE_INSTANT,ePuff,oCaster); return FALSE;; } else if(nInnateLevel < 7) { return TRUE; } } if(!nWiz >= nInnateLevel) { effect ePuff = EffectVisualEffect(-1); ApplyEffectToObject(DURATION_TYPE_INSTANT,ePuff,oCaster); return FALSE; } else if(nWiz >= nInnateLevel) { return TRUE; } if(!nSorc >= nInnateLevel) { effect ePuff = EffectVisualEffect(-1); ApplyEffectToObject(DURATION_TYPE_INSTANT,ePuff,oCaster); return FALSE; } else if(nSorc >= nInnateLevel) { return TRUE; } } } //This is where divine scrolls get compared to divinetype casterlevels if(nDivine == 1) { if(nPlyrDiv == 1) { if(!nPrst >= nInnateLevel) { effect ePuff = EffectVisualEffect(-1); ApplyEffectToObject(DURATION_TYPE_INSTANT,ePuff,oCaster); return FALSE; } else if(nPrst >= nInnateLevel) { return TRUE; } if(!nDrud >= nInnateLevel) { effect ePuff = EffectVisualEffect(-1); ApplyEffectToObject(DURATION_TYPE_INSTANT,ePuff,oCaster); return FALSE;; } else if(nDrud >= nInnateLevel) { return TRUE; } if(nRngr >= nInnateLevel) { if(!nInnateLevel <5) { effect ePuff = EffectVisualEffect(-1); ApplyEffectToObject(DURATION_TYPE_INSTANT,ePuff,oCaster); return FALSE; } else if(nInnateLevel < 5) { return TRUE; } } if(nPally >= nInnateLevel) { if(!nInnateLevel <5) { return FALSE; } else if(nInnateLevel < 5) { return TRUE; } } } } //This By Mohobie sets the interger for comparison later int iDC; if (nInnateLevel <= 2) { iDC = 0; } else if (nInnateLevel == 3) { iDC = 15; } else if (nInnateLevel == 4) { iDC = 25; } else if (nInnateLevel == 5) { iDC = 35; } else if (nInnateLevel == 6) { iDC = 45; } else if (nInnateLevel == 7) { iDC = 55; } else if (nInnateLevel == 8) { iDC = 65; } else if (nInnateLevel == 9) { iDC = 75; } // ------------------------------------------------------------------------- // Base DC for casting a spell from a scroll is 25+SpellLevel // We do not have a way to check for misshaps here but GetIsSkillSuccessful /// does not return the required information // ------------------------------------------------------------------------- // SM update is 20+ iDC int nUMD = GetIsSkillSuccessful(oCaster,nSkill, 20+iDC); if(nRog == 1) { if(nUMD == TRUE) { return TRUE; } else { effect ePuff = EffectVisualEffect(-1); ApplyEffectToObject(DURATION_TYPE_INSTANT,ePuff,oCaster); return FALSE; } } else { effect ePuff = EffectVisualEffect(-1); ApplyEffectToObject(DURATION_TYPE_INSTANT,ePuff,oCaster); return FALSE; } } void main() { //-------------------------------------------------------------------------- // Reset //-------------------------------------------------------------------------- if (GetLocalInt(GetModule(),"X2_L_STOP_EXPERTISE_ABUSE") == TRUE) { SetActionMode(OBJECT_SELF,ACTION_MODE_EXPERTISE,FALSE); SetActionMode(OBJECT_SELF,ACTION_MODE_IMPROVED_EXPERTISE,FALSE); } //-------------------------------------------------------------------------- // Do use magic device check //-------------------------------------------------------------------------- int nRet = X2_UMD(); SetExecutedScriptReturnValue (nRet); }