//:://///////////////////////////////////////////// //:: skin include //:: prc_inc_skin //:://///////////////////////////////////////////// /** @file This include contains GetPCSkin(). If only using this function please include this directly and not via the entire spell engine :p Is included by inc_persist_loca for persistent local variables */ //::////////////////////////////////////////////// //:: Created By: fluffyamoeba //:: Created On: 2008-4-23 //::////////////////////////////////////////////// ////////////////////////////////////////////////// /* Function prototypes */ ////////////////////////////////////////////////// /** * Sets up the pcskin object on oPC. * If it already exists, simply return it. Otherwise, create and equip it. * * @param oPC The creature whose skin object to look for. * @return Either the skin found or the skin created. */ object GetPCSkin(object oPC); ////////////////////////////////////////////////// /* Includes */ ////////////////////////////////////////////////// #include "inc_debug" ////////////////////////////////////////////////// /* private functions */ ////////////////////////////////////////////////// // to duplicate ForceEquip() from inc_utility void _ForceEquipSkin(object oPC, object oSkin, int nThCall = 0) { // Make sure that the object we are attempting equipping is the latest one to be ForceEquipped into this slot if(GetIsObjectValid(GetLocalObject(oPC, "ForceEquipToSlot_17")) && GetLocalObject(oPC, "ForceEquipToSlot_17") != oSkin) return; // Fail on non-commandable NPCs after ~1min if(!GetIsPC(oPC) && !GetCommandable(oPC) && nThCall > 60) { WriteTimestampedLogEntry("ForceEquip() failed on non-commandable NPC: " + DebugObject2Str(oPC) + " for item: " + DebugObject2Str(oSkin)); return; } float fDelay; // Check if the equipping has already happened if(GetItemInSlot(INVENTORY_SLOT_CARMOUR, oPC) != oSkin) { // Test and increment the control counter if(nThCall++ == 0) { // First, try to do the equipping non-intrusively and give the target a reasonable amount of time to do it AssignCommand(oPC, ActionEquipItem(oSkin, INVENTORY_SLOT_CARMOUR)); fDelay = 1.0f; // Store the item to be equipped in a local variable to prevent contest between two different calls to ForceEquip SetLocalObject(oPC, "ForceEquipToSlot_17", oSkin); } else { // Nuke the target's action queue. This should result in "immediate" equipping of the item if(GetIsPC(oPC) || nThCall > 5) // Skip nuking NPC action queue at first, since that can cause problems. 5 = magic number here. May need adjustment { if(!GetIsObjectValid(oSkin)) { oSkin = GetPCSkin(oPC); return; } else { AssignCommand(oPC, ClearAllActions()); AssignCommand(oPC, ActionEquipItem(oSkin, INVENTORY_SLOT_CARMOUR)); } } // Use a lenghtening delay in order to attempt handling lag and possible other interference. From 0.1s to 1s fDelay = (nThCall < 10 ? nThCall : 10) / 10.0f; // yes this is the same as min(nThCall, 10) } // Loop DelayCommand(fDelay, _ForceEquipSkin(oPC, oSkin, nThCall)); } // It has, so clean up else DeleteLocalObject(oPC, "ForceEquipToSlot_17"); } ////////////////////////////////////////////////// /* Function defintions */ ////////////////////////////////////////////////// object GetPCSkin(object oPC) { // According to a bug report, this is being called on non-creature objects. This should catch the culprit if(DEBUG) Assert(GetObjectType(oPC) == OBJECT_TYPE_CREATURE, "GetObjectType(oPC) == OBJECT_TYPE_CREATURE", "GetPRCSkin() called on non-creature object: " + DebugObject2Str(oPC), "prc_inc_skin", "object GetPCSkin(object oPC)"); object oSkin = GetItemInSlot(INVENTORY_SLOT_CARMOUR, oPC); if(!GetIsObjectValid(oSkin)) { //oSkin = GetLocalObject(oPC, "PRCSkinCache"); //if(!GetIsObjectValid(oSkin)) { //Added this check to prevent creation of extra skins on module entry oSkin = GetItemPossessedBy(oPC, "base_prc_skin"); if(GetIsObjectValid(oSkin)) { _ForceEquipSkin(oPC, oSkin, INVENTORY_SLOT_CARMOUR); //AssignCommand(oPC, ActionEquipItem(oSkin, INVENTORY_SLOT_CARMOUR)); } else { oSkin = CreateItemOnObject("base_prc_skin", oPC); _ForceEquipSkin(oPC, oSkin, INVENTORY_SLOT_CARMOUR); //AssignCommand(oPC, ActionEquipItem(oSkin, INVENTORY_SLOT_CARMOUR)); // The skin should not be droppable SetDroppableFlag(oSkin, FALSE); // other scripts should not be able to destroy the skin AssignCommand(oSkin, SetIsDestroyable(FALSE)); } // Cache the skin reference for further lookups during the same script //SetLocalObject(oPC, "PRCSkinCache", oSkin); //DelayCommand(0.0f, DeleteLocalObject(oPC, "PRCSkinCache")); } } return oSkin; }