//::////////////////////////////////////////////// //:: prc_uni_shift //:: Universal class script for classes that allow shifting //:: (to prevent having to duplicate and install a script like this for each such class) //::////////////////////////////////////////////// #include "prc_inc_shifting" #include "prc_spell_const" #include "prc_inc_onhit" const string SCRIPT_NAME = "prc_uni_shift"; const string SHIFTER_LEVELLING_ARRAY = "PRC_Shifter_Levelling_Array"; const string SHIFTER_SHAPE_LEARNED_LEVEL = "PRC_Shifter_AutoGranted"; void HandleShapeLearning(object oPC) { if (GetLevelByClass(CLASS_TYPE_PNP_SHIFTER, oPC)) { if(!persistant_array_exists(oPC, SHIFTER_LEVELLING_ARRAY)) persistant_array_create(oPC, SHIFTER_LEVELLING_ARRAY); int nLearnedLevel = GetPersistantLocalInt(oPC, SHIFTER_SHAPE_LEARNED_LEVEL); int nShifterLevel = GetLevelByClass(CLASS_TYPE_PNP_SHIFTER, oPC); int nCharacteLevel = GetHitDice(oPC); int i; for(i = nLearnedLevel; i < nShifterLevel; i++) persistant_array_set_int(oPC, SHIFTER_LEVELLING_ARRAY, i, nCharacteLevel - (nShifterLevel-1-i)); } } void AddEvents(object oPC) { if (AddEventScript(oPC, EVENT_ONPLAYERLEVELUP, SCRIPT_NAME, TRUE, FALSE)) { //If we're just adding the level up script, run the level-up function to let it "catch up" if necessary: //the level-up event hook may not be called for Shifter level 1 because the PC isn't a Shifter until //after the level-up for that level has been completed. HandleShapeLearning(oPC); } AddEventScript(oPC, EVENT_ONPLAYERLEVELDOWN, SCRIPT_NAME, TRUE, FALSE); AddEventScript(oPC, EVENT_ONHIT, SCRIPT_NAME, TRUE, FALSE); } void HandleEquip(object oPC, object oEquippedItem) { int bAddOnHitUniquePower = FALSE; if (oEquippedItem == GetItemInSlot(INVENTORY_SLOT_CWEAPON_R, oPC)) bAddOnHitUniquePower = TRUE; else if (oEquippedItem == GetItemInSlot(INVENTORY_SLOT_CWEAPON_L, oPC)) bAddOnHitUniquePower = TRUE; else if (oEquippedItem == GetItemInSlot(INVENTORY_SLOT_CWEAPON_B, oPC)) bAddOnHitUniquePower = TRUE; else if (oEquippedItem == GetItemInSlot(INVENTORY_SLOT_ARMS, oPC)) { //Gloves or bracers (this doesn't actually work for bracers, however: //apparently you can't add an OnHit: Cast Spell property to bracers) bAddOnHitUniquePower = TRUE; } else if (oEquippedItem == GetItemInSlot(INVENTORY_SLOT_CARMOUR, oPC)) bAddOnHitUniquePower = TRUE; if (bAddOnHitUniquePower && !GetLocalInt(oPC, "prc_uni_shift_suppress_onhit")) Add_OnHitUniquePower(oEquippedItem, SCRIPT_NAME); } void HandleUnequip(object oPC, object oUnequippedItem) { //Just call the remove function. If we haven't added, the signature check will prevent the remove. Remove_OnHitUniquePower(oUnequippedItem, SCRIPT_NAME); } void HandleOnHit(object oPC, object oItem, object oTarget) { //Fire all OnHit properties on creature items and skin //(normally just the first will fire) //NOTE: this event only fires for items to which the shifting code //has added the item property On Hit Cast Spell: Unique Power if (GetLocalInt(oItem, PRC_CUSTOM_ONHIT_SIGNATURE + SCRIPT_NAME)) { if (GetLevelByClass(CLASS_TYPE_SOUL_EATER, oPC) && oItem != GetItemInSlot(INVENTORY_SLOT_CARMOUR, oPC)) { SetLocalInt(oItem, "PRC_SOULEATER_ONHIT_ENERGYDRAIN", TRUE); DelayCommand(0.0f, DeleteLocalInt(oItem, "PRC_SOULEATER_ONHIT_ENERGYDRAIN")); CastSpellAtObject(SPELL_SE_ENERGY_DRAIN, oTarget, METAMAGIC_NONE, 0, 0, 0, oItem, oPC); } ApplyAllOnHitCastSpellsOnItemExcludingSubType(IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, oTarget, oItem, oPC); //NOTE: may not work correctly with spells not converted to use PRC functions (as detailed in prc_inc_onhit.nss)? } } void HandleDefault(object oPC) { AddEvents(oPC); if(GetLocalInt(oPC,"ONEQUIP")) //2 = equip, 1 = unequip { if (GetLocalInt(oPC,"ONEQUIP") == 2) HandleEquip(oPC, GetItemLastEquipped()); else if (GetLocalInt(oPC,"ONEQUIP") == 1) HandleUnequip(oPC, GetItemLastUnequipped()); } else if(GetLocalInt(oPC,"ONREST")) { HandleShapeLearning(oPC); //Do this on resting in case it fails to fire where it should for some reason HandleApplyShiftEffects(oPC); } HandleTrueShape(oPC); HandleApplyShiftTemplate(oPC); } void main() { int nEvent = GetRunningEvent(); if(nEvent == FALSE) //We aren't being called from any event, instead from EvalPRCFeats HandleDefault(OBJECT_SELF); else if(nEvent == EVENT_ONPLAYERLEVELUP) HandleShapeLearning(GetPCLevellingUp()); else if(nEvent == EVENT_ONPLAYERLEVELDOWN) HandleShapeLearning(OBJECT_SELF); else if(nEvent == EVENT_ONHIT) HandleOnHit(OBJECT_SELF, PRCGetSpellCastItem(), PRCGetSpellTargetObject()); }