436 lines
15 KiB
Plaintext
436 lines
15 KiB
Plaintext
//------------------------------------------------------------------------------
|
|
/*
|
|
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);
|
|
}
|