Help with a simple script
Hello, i'm totally new to scripting and i'm basically starting by reading someone else scripts and trying to change em and merge them to see what happens (usually bad things!)
//
// CONSTANTS
//
const string HC_RES_SKINNING_MEAT = "it_mmidmisc006";
const string HC_RES_SKINNING_MEAT2 = "it_mmidmisc007";
//
// FUNCTIONS
//
void HC_ActionButcherAnimal()
{
object oPC = OBJECT_SELF;
FloatingTextStringOnCreature("*" + GetName(oPC) + SKINNING, oPC);
CreateObject(OBJECT_TYPE_ITEM, HC_RES_SKINNING_MEAT, GetLocation(oPC));
}
This is a script which fires when a PC use an item (skinning knife) on an animal corpse. HC_RES_SKINNING_MEAT = "it_mmidmisc006" is the item he obtain from that action. I would like the PC to obtain additional items based on the creature name (or tag, or resref). Something like IF the creature is X then drop also Y. The bold part hes been added by me..
hope you can help me!
//
// CONSTANTS
//
const string HC_RES_SKINNING_MEAT = "it_mmidmisc006";
const string HC_RES_SKINNING_MEAT2 = "it_mmidmisc007";
//
// FUNCTIONS
//
void HC_ActionButcherAnimal()
{
object oPC = OBJECT_SELF;
FloatingTextStringOnCreature("*" + GetName(oPC) + SKINNING, oPC);
CreateObject(OBJECT_TYPE_ITEM, HC_RES_SKINNING_MEAT, GetLocation(oPC));
}
This is a script which fires when a PC use an item (skinning knife) on an animal corpse. HC_RES_SKINNING_MEAT = "it_mmidmisc006" is the item he obtain from that action. I would like the PC to obtain additional items based on the creature name (or tag, or resref). Something like IF the creature is X then drop also Y. The bold part hes been added by me..
hope you can help me!
0
Comments
void HC_ActionButcherAnimal() { object oPC = OBJECT_SELF; // Define the animal object being targeted with the skinning knife. object oTarget = GetSpellTargetObject(); FloatingTextStringOnCreature("*" + GetName(oPC) + SKINNING, oPC); // Check what the tag of the animal is. if(GetTag(oTarget) == "TagNameHere") { CreateObject(OBJECT_TYPE_ITEM, HC_RES_SKINNING_MEAT, GetLocation(oPC)); // You can also give item 2 here if that's more what you wanted. } if(GetTag(oTarget) == "TagName2Here") { CreateObject(OBJECT_TYPE_ITEM, HC_RES_SKINNING_MEAT2, GetLocation(oPC)); } }This should give you a start. Feel free to plaster me with questions.
void HC_ActionButcherAnimal()
{
object oPC = OBJECT_SELF;
FloatingTextStringOnCreature("*" + GetName(oPC) + SKINNING, oPC);
CreateObject(OBJECT_TYPE_ITEM, HC_RES_SKINNING_MEAT, GetLocation(oPC));
if(GetTag(oTarget) == "TagNameHere")
{
CreateObject(OBJECT_TYPE_ITEM, HC_RES_SKINNING_MEAT2, GetLocation(oPC));
}
Would this little adjustment make it work as i imagine it should?
Another way to go about it would be use variables. This would be pretty easy if you're using all custom versions of animals that can be skinned.
In the Advanced tab on the creatures properties, there is a button near the bottom where you can define them. Then in your script you can check for them using GetLocalInt() and the like.
If not, then yes. You would have to make an exception for each animal that should drop something else too.
Edit: I did a simple test and leaves lootable corpse does have the same tag as the creature.
In your original post, 'SKINNING' is undefined. Would that be part of it?
OnActivate event script for skinning knife item. */ // ---------------------------------------------------------------------------- /* 26 July 2004 - Sunjammer - rewritten */ // ---------------------------------------------------------------------------- #include "hc_inc_npccorpse" #include "hc_text_activate" // ---------------------------------------------------------------------------- // CONSTANTS // ---------------------------------------------------------------------------- const string HC_RES_SKINNING_MEAT = "it_mmidmisc006"; // ---------------------------------------------------------------------------- // FUNCTIONS // ---------------------------------------------------------------------------- void HC_ActionButcherAnimal() { object oPC = OBJECT_SELF; FloatingTextStringOnCreature("*" + GetName(oPC) + SKINNING, oPC); CreateObject(OBJECT_TYPE_ITEM, HC_RES_SKINNING_MEAT, GetLocation(oPC)); } // ---------------------------------------------------------------------------- // MAIN // ---------------------------------------------------------------------------- void main() { object oPC = OBJECT_SELF; object oCorpse = GetLocalObject(oPC, "OTHER"); object oBody = GetLocalObject(oCorpse, HC_VAR_NPCCORPSE_BODY); DeleteLocalObject(oPC, "OTHER"); // pre-emptive abort for invalid objects if(GetIsObjectValid(oCorpse) == FALSE || GetIsObjectValid(oBody) == FALSE) { return; } // the body must be an animal, must be dead and must be within 3m to be // successfully skinned. if(GetRacialType(oBody) != RACIAL_TYPE_ANIMAL) { SendMessageToPC(oPC, ANIMALONLY); return; } if(GetIsDead(oBody) == FALSE) { SendMessageToPC(oPC, NOTDEAD); return; } if(GetDistanceBetween(oPC, oBody) > 3.0) { SendMessageToPC(oPC, MOVECLOSER); return; } // skin the body: animate the PC, create the product and destroy the body AssignCommand(oPC, ActionMoveToLocation(GetLocation(oBody))); AssignCommand(oPC, DelayCommand(1.0, ActionPlayAnimation(ANIMATION_LOOPING_GET_LOW, 1.0, 1.0))); AssignCommand(oPC, DelayCommand(2.0, HC_ActionButcherAnimal())); HC_NPCCorpse_CleanUp(oCorpse); }skinning is part of "hc_text_activate" and is just a text string that will float, inside hc_text_activate the author placed every text spoken by his script to help others with translation or if someone wants to change the phrase, smart i'd say! It contains lot of strings like this one: string SKINNING= " Skins Animal*";
I think (from reading "hc_inc_npccorpse") that this script is not using the standard nwn cropses but is creating his own corspes thru "hc_inc_npccorpse". I've tryed to run the script with animal creatues with "leave lootable corpse" unchecked and those still generate a corpse!
Totally doable though. In this scrips I can see At this point, both those objects have been created and stored. All you have to do is find where SetLocalObject(<oPC>, HC_VAR_NPCCORPSE_BODY, <someObject>); is called. You can SetLocalInt on the line before it... it's still weird. Why is the object being stored on oPC at all? I think I would need a look at hc_inc_npccorpse to understand that.
On my favorite server (Lala Land [Gone now]), they had a similar skinning system. Animals would leave lootable corpses. If you had a skinning knife equipped, it would play an animation and give you a pelt or whatever depending on what animal it was. After so many times, your skinning knife would get destroyed from being used up. This system you've got here seems like it's maybe trying to be like that, but I'm not seeing any advantages so far.
// ---------------------------------------------------------------------------- // CONSTANTS: CONFIGURATION // ---------------------------------------------------------------------------- // Sets an override for standard Bioware creatures (NW_*) to enable them to drop // items not flagged as droppable (such as weapons). Creature items and no-drop // items will still not drop. const int HC_NPCCORPSE_DROP_IF_BIOWARE = FALSE; // Sets limitations on the above override. // *_BW_PLOT: items will not drop if they are flagged as plot // *_BW_STOLEN: items will not drop if they are flagged as stolen const int HC_NPCCORPSE_SKIP_IF_BW_PLOT = FALSE; const int HC_NPCCORPSE_SKIP_IF_BW_STOLEN = FALSE; // Modes available controlling how an NPC's "visible" items are handled. // *_NONE: item remains on NPC even if droppable // *_MOVE: item removed from NPC, appears in corpse // *_COPY: item remains on NPC, a copy appears in corpse // *_DROP: item removed from NPC, a copy appears on ground nearby (hands only) const int HC_NPCCORPSE_DROP_MODE_NONE = 1; const int HC_NPCCORPSE_DROP_MODE_MOVE = 2; const int HC_NPCCORPSE_DROP_MODE_COPY = 3; const int HC_NPCCORPSE_DROP_MODE_DROP = 4; // Sets the mode controlling how an NPC's "visible" items are handled. Use a // HC_NPCCORPSE_DROP_MODE_* constant from the list above for each *_MODE_*. const int HC_NPCCORPSE_DROP_MODE_FOR_CHEST = HC_NPCCORPSE_DROP_MODE_COPY; const int HC_NPCCORPSE_DROP_MODE_FOR_HANDS = HC_NPCCORPSE_DROP_MODE_COPY; const int HC_NPCCORPSE_DROP_MODE_FOR_HEAD = HC_NPCCORPSE_DROP_MODE_COPY; // Modes available for the controling the clean up process. // *_NEVER: clean up is never initiated // *_EMPTY: clean up is initiated when corpse is emptied (checked OnClose) // *_TIMED: clean up is intiated after HC_NPCCORPSE_CLEANUP_DELAY minutes // *_COMBO: clean up is intiated after the earlier of EMPTY or TIMED const int HC_NPCCORPSE_CLEANUP_MODE_NEVER = 1; const int HC_NPCCORPSE_CLEANUP_MODE_EMPTY = 2; const int HC_NPCCORPSE_CLEANUP_MODE_TIMED = 3; const int HC_NPCCORPSE_CLEANUP_MODE_COMBO = 4; // Sets the mode and time (in minutes) controling the clean up process. Use a // HC_NPCCORPSE_CLEANUP_MODE_* constant from the list above for *_MODE. const int HC_NPCCORPSE_CLEANUP_MODE = 3; const int HC_NPCCORPSE_CLEANUP_DELAY = 5; // Controls if a blood pool should form under the NPC. const int HC_NPCCORPSE_USE_BLOOD = TRUE; // Sets an override for animals to enable them to persist until skinned. This // is mainly for use with EMPTY or COMBO modes for cleanup. Cleanup is handled // in the appropriate OnActivateItem script. const int HC_NPCCORPSE_USE_SKINNING = TRUE; // ---------------------------------------------------------------------------- // CONSTANTS: SYSTEM // ---------------------------------------------------------------------------- // blueprints for the placeable elements const string HC_RES_NPCCORPSE_CORPSE = "invis_corpse_obj"; const string HC_RES_NPCCORPSE_BLOOD = "plc_bloodstain"; // tags for the placeable elements const string HC_TAG_NPCCORPSE_CORPSE = "HC_NPCCorpse_Corpse"; // name of variables to register elements with corpse const string HC_VAR_NPCCORPSE_BLOOD = "HC_NPCCorpse_Blood"; [b]const string HC_VAR_NPCCORPSE_BODY = "HC_NPCCorpse_Body";[/b] // name of variables for various system flags // *_CHECKED: identifies checked items to prevents duplication on transfer // *_CLEANUP: creature override for clean up mode // *_COPIED: identifies coppied items for clean up on distrubed // *_DROPPED: identifies dropped items (e.g. weapons) for clean up // *_PRESERVE: prevents deletion of coprse elements (on body, dual purpose) // *_PREVENT: prevents creation of corpse elements (on body) const string HC_VAR_NPCCORPSE_CHECKED = HC_VAR_TRANSFER_CHECKED; const string HC_VAR_NPCCORPSE_CLEANUP = "HC_NPCCorpse_CleanUp"; const string HC_VAR_NPCCORPSE_COPIED = "HC_NPCCorpse_Copied"; const string HC_VAR_NPCCORPSE_DROPPED = "HC_NPCCorpse_Dropped"; const string HC_VAR_NPCCORPSE_PRESERVE = "HC_NPCCorpse_Preserve"; const string HC_VAR_NPCCORPSE_PREVENT = "HC_NPCCorpse_Prevent"; //const string HC_VAR_NPCCORPSE_PRESERVE = "Dead"; // legacy //const string HC_VAR_NPCCORPSE_PREVENT = "NORMALCORPSE"; // legacy // ---------------------------------------------------------------------------- // PROTOTYPES // ---------------------------------------------------------------------------- // Creates the corpse components for the NPC, drops items as appropriate and // handles initial clean up/scheduling. // - oBody: a dead NPC/creature void HC_NPCCorpse_CreateCorpse(object oBody); // Destroys the corpse components. Will not destroy the NPC if it has been // revived between corpse creation and clean up. // - oCorpse: a invisible corpse object void HC_NPCCorpse_CleanUp(object oCorpse); // Returns the clean up mode associated with the NPC. // - oBody: a dead NPC/creature int HC_NPCCoprse_GetCleanUpMode(object oBody); // Returns the drop mode for the "visible" item in nSlot. // - nSlot: one of the visible INVENTORY_SLOT_* constants int HC_NPCCorpse_GetDropMode(int nSlot); // Returns TRUE if oCreature can bleed. int HC_NPCCorpse_GetIsBleeder(object oCreature); // Returns TRUE if oItem is "droppable" according to system settings. int HC_NPCCorpse_GetIsDroppable(object oItem); // Returns TRUE if oCorpse is empty AND there are no associated dropped items // remaining on the ground. // - oCorpse: an invisible corpse object int HC_NPCCorpse_GetIsEmpty(object oCorpse); // Returns TRUE if any of the *_DROP_MODE_FOR_* settings are *_DROP_MODE_COPY. int HC_NPCCorpse_GetIsUsingCopyMode(); // Generates a location beneath the NPC's body. // - oBody: a dead NPC/creature location HC_NPCCorpse_GetLocationForCorpse(object oBody); // Generates a location appropriate for an item that has dropped to the ground // from an NPC's hand. // - oBody: a dead NPC/creature // - nSlot: one of the INVENTORY_SLOT_*HAND constants location HC_NPCCorpse_GetLocationForDropped(object oBody, int nSlot); // Destroys any associated dropped items remaining on the ground. // - oCorpse: an invisible corpse object // - nSlot: one of the visible INVENTORY_SLOT_* constants void HC_NPCCorpse_DestroyDropped(object oCorpse, int nSlot); // Destroys all items that remain equiped on oBody. void HC_NPCCorpse_DestroyEquipment(object oBody); // Destroys all items in oContainers inventory. void HC_NPCCorpse_DestroyInventory(object oContainer); // Transfers all "droppable" equipped items oBody to oCorpse except "visible" // items, namely those in the *_CHEST, *_HEAD, *_LEFTHAND and *_RIGHTHAND // inventory slots. // - oBody: a dead NPC/creature // - oCorpse: an invisible corpse object void HC_NPCCorpse_DropEquipment(object oBody, object oCorpse); // Transfers all "droppable" inventory items from oBody to oCorpse. // - oBody: a dead NPC/creature // - oCorpse: an invisible corpse object void HC_NPCCorpse_DropInventory(object oBody, object oCorpse); // Transfers or drops all "visible", "droppable" equipted items form oBody to // oCorpse. In other words those items in the *_CHEST, *_HEAD, *_LEFTHAND and // *_RIGHTHAND inventory slots. // - oBody: a dead NPC/creature // - oCorpse: an invisible corpse object // - nSlot: one of the visible INVENTORY_SLOT_* constants void HC_NPCCorpse_DropVisible(object oBody, object oCorpse, int nSlot); // ---------------------------------------------------------------------------- // FUNCTIONS // ---------------------------------------------------------------------------- void HC_NPCCorpse_CreateCorpse(object oBody) { // pre-emptive abort: the body has a normal corpse override flag or or has // an ATS, a CNR or a legacy no-corpse tag string sTag = GetTag(oBody); if(GetLocalInt(oBody, HC_VAR_NPCCORPSE_PREVENT) || HC_GetIsInString(sTag, "NC_") || HC_GetIsInString(sTag, "ATS_") || HC_GetIsInString(sTag, "cnra")) { return; } // ------------------------------------------------------------------------- // Part 1: Create the Components // ------------------------------------------------------------------------- // prevent the body from decaying AssignCommand(oBody, SetIsDestroyable(FALSE)); // create the lootable container location lCorpse = HC_NPCCorpse_GetLocationForCorpse(oBody); object oCorpse = CreateObject(OBJECT_TYPE_PLACEABLE, HC_RES_NPCCORPSE_CORPSE, lCorpse, FALSE, HC_TAG_NPCCORPSE_CORPSE); // register the body with the corpse [b] SetLocalObject(oCorpse, HC_VAR_NPCCORPSE_BODY, oBody);[/b] // create a blood stain for effect if required/appropriate if(HC_NPCCORPSE_USE_BLOOD && HC_NPCCorpse_GetIsBleeder(oBody)) { // create the blood and register it with the corpse object oBlood = CreateObject(OBJECT_TYPE_PLACEABLE, HC_RES_NPCCORPSE_BLOOD, GetLocation(oBody)); SetLocalObject(oCorpse, HC_VAR_NPCCORPSE_BLOOD, oBlood); } // ------------------------------------------------------------------------- // Part 2: Drop or Transfer Items // ------------------------------------------------------------------------- // drop the gold HC_Transfer_MoveGold(oBody, oCorpse); // drop visible items, i.e. those affecting appearance on dynamic models HC_NPCCorpse_DropVisible(oBody, oCorpse, INVENTORY_SLOT_HEAD); HC_NPCCorpse_DropVisible(oBody, oCorpse, INVENTORY_SLOT_CHEST); HC_NPCCorpse_DropVisible(oBody, oCorpse, INVENTORY_SLOT_LEFTHAND); HC_NPCCorpse_DropVisible(oBody, oCorpse, INVENTORY_SLOT_RIGHTHAND); // drop residual equipment HC_NPCCorpse_DropEquipment(oBody, oCorpse); // drop all other items HC_NPCCorpse_DropInventory(oBody, oCorpse); // ------------------------------------------------------------------------- // Part 3: Arrange Clean Up // ------------------------------------------------------------------------- int nMode = HC_NPCCoprse_GetCleanUpMode(oBody); // NOTE: given the duality of applciation all three of these must be checked if(nMode == HC_NPCCORPSE_CLEANUP_MODE_COMBO || nMode == HC_NPCCORPSE_CLEANUP_MODE_EMPTY) { // clean up if empty, otherwise clean up via OnClose if(HC_NPCCorpse_GetIsEmpty(oCorpse)) { HC_NPCCorpse_CleanUp(oCorpse); } } if(nMode == HC_NPCCORPSE_CLEANUP_MODE_COMBO || nMode == HC_NPCCORPSE_CLEANUP_MODE_TIMED) { // schedule clean up after delay (converted to seconds) float fDelay = IntToFloat(HC_NPCCORPSE_CLEANUP_DELAY * 60); DelayCommand(fDelay, HC_NPCCorpse_CleanUp(oCorpse)); } if(nMode == HC_NPCCORPSE_CLEANUP_MODE_NEVER || nMode == HC_NPCCORPSE_CLEANUP_MODE_TIMED) { // prevent premature clean up via OnClose SetLocalInt(oBody, HC_VAR_NPCCORPSE_PRESERVE, TRUE); } } void HC_NPCCorpse_CleanUp(object oCorpse) { // get the elements registered with the corpse object oBody = GetLocalObject(oCorpse, HC_VAR_NPCCORPSE_BODY); object oBlood = GetLocalObject(oCorpse, HC_VAR_NPCCORPSE_BLOOD); // clean up blood DestroyObject(oBlood); // destroy items to prevent "remains", clean up corpse HC_NPCCorpse_DestroyInventory(oCorpse); DestroyObject(oCorpse); // destroy items dropped and not yet picked up (hands only) if(HC_NPCCORPSE_DROP_MODE_FOR_HANDS == HC_NPCCORPSE_DROP_MODE_DROP) { HC_NPCCorpse_DestroyDropped(oCorpse, INVENTORY_SLOT_LEFTHAND); HC_NPCCorpse_DestroyDropped(oCorpse, INVENTORY_SLOT_RIGHTHAND); } // ONLY clean up Body and retained weapons IF STILL DEAD if(GetIsDead(oBody)) { // destroy items to prevent "remains" HC_NPCCorpse_DestroyEquipment(oBody); HC_NPCCorpse_DestroyInventory(oBody); // clean up body: no need to use DestroyObject as SetIsDestroyable will // cause it to fade after a short delay AssignCommand(oBody, SetIsDestroyable(TRUE)); } } int HC_NPCCoprse_GetCleanUpMode(object oBody) { // assume default mode will apply int nRet = HC_NPCCORPSE_CLEANUP_MODE; //[b] override if it is an animal and using skinning so it can be skinned[/b] if(HC_NPCCORPSE_USE_SKINNING && GetRacialType(oBody) == RACIAL_TYPE_ANIMAL) { nRet = HC_NPCCORPSE_CLEANUP_MODE_NEVER; } // override if body is flagged or tagged to leave a permanent corpse if(GetLocalInt(oBody, HC_VAR_NPCCORPSE_PRESERVE) || HC_GetIsInString(GetTag(oBody), HC_VAR_NPCCORPSE_PRESERVE)) { nRet = HC_NPCCORPSE_CLEANUP_MODE_NEVER; } // check body for creature override int nOverride = GetLocalInt(oBody, HC_VAR_NPCCORPSE_CLEANUP); if(nOverride) return nOverride; // return mode return nRet; } int HC_NPCCorpse_GetDropMode(int nSlot) { int nRet; // parse the inventory slot for the corresponding mode switch(nSlot) { case INVENTORY_SLOT_CHEST: nRet = HC_NPCCORPSE_DROP_MODE_FOR_CHEST; break; case INVENTORY_SLOT_HEAD: nRet = HC_NPCCORPSE_DROP_MODE_FOR_HEAD; break; case INVENTORY_SLOT_LEFTHAND: case INVENTORY_SLOT_RIGHTHAND: nRet = HC_NPCCORPSE_DROP_MODE_FOR_HANDS; break; } // return mode return nRet; } int HC_NPCCorpse_GetIsBleeder(object oCreature) { int nRace = GetRacialType(oCreature); // constructs, elementals, oozes and the undead don't bleed if(nRace == RACIAL_TYPE_CONSTRUCT || nRace == RACIAL_TYPE_ELEMENTAL || nRace == RACIAL_TYPE_OOZE || nRace == RACIAL_TYPE_UNDEAD) { // creature doesn't bleed return FALSE; } // creature bleeds return TRUE; } int HC_NPCCorpse_GetIsDroppable(object oItem) { string sTag; if(GetDroppableFlag(oItem) == FALSE) { // if not droppable check override ... if(HC_NPCCORPSE_DROP_IF_BIOWARE) { // ... and check it is a Bioware creature sTag = GetTag(GetItemPossessor(oItem)); if(HC_GetIsInString(sTag, "nw_") || HC_GetIsInString(sTag, "x0_") || HC_GetIsInString(sTag, "x2_")) { // skipping plot items? if(HC_NPCCORPSE_SKIP_IF_BW_PLOT && GetPlotFlag(oItem)) { return FALSE; } // skipping stolen items? if(HC_NPCCORPSE_SKIP_IF_BW_STOLEN && GetStolenFlag(oItem)) { return FALSE; } // always skip creature/henchmen weapons // NOTE: not relevant to custom creature as creator has ability // to choose if such items are droppable sTag = GetTag(oItem); if(HC_GetIsInString(sTag, "_it_cre") || HC_GetIsInString(sTag, "_hen_") || HC_GetIsInString(sTag, "_wdrow") || HC_GetIsInString(sTag, "_wduer") || HC_GetIsInString(sTag, "_it_rakstaff") || HC_GetIsInString(sTag, "_manti_spikes") || HC_GetIsInString(sTag, "_it_frzdrowbld")) { return FALSE; } } } else { // not droppable and override doesn't apply return FALSE; } } // always skip no-drop items if(HC_GetIsItemNoDrop(oItem)) { return FALSE; } // passed all checks return TRUE; } int HC_NPCCorpse_GetIsEmpty(object oCorpse) { // any items in corpse? if(GetIsObjectValid(GetFirstItemInInventory(oCorpse))) { return FALSE; } // if using DROP mode, any items on ground? int nMode = HC_NPCCorpse_GetDropMode(INVENTORY_SLOT_LEFTHAND); if(nMode == HC_NPCCORPSE_DROP_MODE_DROP) { string sItem; object oItem, oOwner; // if object from LEFT hand is valid it must have a possessor sItem = HC_VAR_NPCCORPSE_DROPPED + IntToString(INVENTORY_SLOT_LEFTHAND); oItem = GetLocalObject(oCorpse, sItem); if(GetIsObjectValid(oItem)) { if(GetIsObjectValid(GetItemPossessor(oItem)) == FALSE) { return FALSE; } } // if object from RIGHT hand is valid it must have a possessor sItem = HC_VAR_NPCCORPSE_DROPPED + IntToString(INVENTORY_SLOT_RIGHTHAND); oItem = GetLocalObject(oCorpse, sItem); if(GetIsObjectValid(oItem)) { if(GetIsObjectValid(GetItemPossessor(oItem)) == FALSE) { return FALSE; } } } // no items found return TRUE; } int HC_NPCCorpse_GetIsUsingCopyMode() { // check all modes and return TRUE if any are *_COPY if(HC_NPCCORPSE_DROP_MODE_FOR_CHEST == HC_NPCCORPSE_DROP_MODE_COPY || HC_NPCCORPSE_DROP_MODE_FOR_HANDS == HC_NPCCORPSE_DROP_MODE_COPY || HC_NPCCORPSE_DROP_MODE_FOR_HEAD == HC_NPCCORPSE_DROP_MODE_COPY) { return TRUE; } return FALSE; } location HC_NPCCorpse_GetLocationForCorpse(object oBody) { vector vBody = GetPosition(oBody); // get co-ordingates of a point just below vBody float fZ = vBody.z - 0.1; // return the location return Location(GetArea(oBody), Vector(vBody.x, vBody.y, fZ), 0.0); } location HC_NPCCorpse_GetLocationForDropped(object oBody, int nSlot) { vector vBody = GetPosition(oBody); // get the offsets appropriate to the hand the item is falling from float fFacing = (nSlot == INVENTORY_SLOT_LEFTHAND) ? 45.0f : -45.0f; float fWeapon = (nSlot == INVENTORY_SLOT_LEFTHAND) ? -20.0f : 20.0f; // add a random element to facings and direction, values are arbitray fFacing += GetFacing(oBody) + IntToFloat(d20()); fWeapon += GetFacing(oBody) - IntToFloat(d20(2)); float fDistance = 0.5f + (IntToFloat(d10())/10); // get co-ordinates of a point fDistance meters away at fFacing degrees float fX = vBody.x + cos(fFacing) * fDistance; float fY = vBody.y + sin(fFacing) * fDistance; // return the location return Location(GetArea(oBody), Vector(fX, fY, vBody.z), fWeapon); } void HC_NPCCorpse_DropEquipment(object oBody, object oCorpse) { location lCorpse = GetLocation(oCorpse); int n; for(n = 0; n < HC_NUM_PC_INVENTORY_SLOTS; n++) { object oItem = GetItemInSlot(n, oBody); // if valid and droppable and as yet unchecked if(GetIsObjectValid(oItem) && HC_NPCCorpse_GetIsDroppable(oItem) && GetLocalInt(oItem, HC_VAR_NPCCORPSE_CHECKED) == FALSE) { // copy item to corpse, destroy original CopyObject(oItem, lCorpse, oCorpse); DestroyObject(oItem); } } } void HC_NPCCorpse_DropVisible(object oBody, object oCorpse, int nSlot) { object oCopy; object oItem = GetItemInSlot(nSlot, oBody); // pre-emptive aborts: object is not valid or is not droppable if(GetIsObjectValid(oItem) == FALSE || HC_NPCCorpse_GetIsDroppable(oItem) == FALSE) { return; } // flag as checked to avoid duplication SetLocalInt(oItem, HC_VAR_NPCCORPSE_CHECKED, TRUE); // parse drop mode int nMode = HC_NPCCorpse_GetDropMode(nSlot); if(nMode == HC_NPCCORPSE_DROP_MODE_MOVE) { // copy item to corpse, destroy original oCopy = CopyObject(oItem, GetLocation(oCorpse), oCorpse); DestroyObject(oItem); } else if(nMode == HC_NPCCORPSE_DROP_MODE_COPY) { // copy item to corpse, register as copy, keep original oCopy = CopyObject(oItem, GetLocation(oCorpse), oCorpse); SetLocalInt(oCopy, HC_VAR_NPCCORPSE_COPIED, nSlot); } else if(nMode == HC_NPCCORPSE_DROP_MODE_DROP) { // copy item to ground, register with corpse, destroy original oCopy = CopyObject(oItem, HC_NPCCorpse_GetLocationForDropped(oBody, nSlot)); SetLocalObject(oCorpse, HC_VAR_NPCCORPSE_DROPPED + IntToString(nSlot), oCopy); DestroyObject(oItem); } } void HC_NPCCorpse_DropInventory(object oBody, object oCorpse) { location lCorpse = GetLocation(oCorpse); // check each item object oItem = GetFirstItemInInventory(oBody); while(GetIsObjectValid(oItem)) { // if droppable and as yet unchecked ... if(HC_NPCCorpse_GetIsDroppable(oItem) && GetLocalInt(oItem, HC_VAR_NPCCORPSE_CHECKED) == FALSE) { // copy item to corpse, destroy original CopyObject(oItem, lCorpse, oCorpse); DestroyObject(oItem); } oItem = GetNextItemInInventory(oBody); } } void HC_NPCCorpse_DestroyDropped(object oCorpse, int nSlot) { // get item and owner (local object released when corpse destroyed) object oItem = GetLocalObject(oCorpse, HC_VAR_NPCCORPSE_DROPPED + IntToString(nSlot)); object oOwner = GetItemPossessor(oItem); // if valid or held by someone valid if(GetIsObjectValid(oOwner) == FALSE) { DestroyObject(oItem); } } void HC_NPCCorpse_DestroyEquipment(object oBody) { int n; for(n = 0; n < HC_NUM_PC_INVENTORY_SLOTS; n++) { // destroy any items left on the body object oItem = GetItemInSlot(n, oBody); if(GetIsObjectValid(oItem)) { DestroyObject(oItem); } } } void HC_NPCCorpse_DestroyInventory(object oContainer) { // destroy each item in turn object oItem = GetFirstItemInInventory(oContainer); while(GetIsObjectValid(oItem)) { DestroyObject(oItem); oItem = GetNextItemInInventory(oContainer); } } //void main(){}I've bolded the part where it sets corpse obody and another one about skinning (i guess that second one is just about decaying time of the corpse but i'm not that sure). I think this sistem works pretty similar to the one you described! I'm not sure what should i do when i set local int before SetLocalObject(<oPC>, HC_VAR_NPCCORPSE_BODY. I mean after that how do I change or modify the item dropped by the action "skinning"?
So really I think the change is in the first script you shared, but seeing that big one helped me decide what's going on. (I still wonder where it calls SetLocalObject(oPc, "Other", corpse))
Anyway, here's the script modified to take a string. You can use that as a start.
/* OnActivate event script for skinning knife item. */ // ---------------------------------------------------------------------------- /* 26 July 2004 - Sunjammer - rewritten */ // ---------------------------------------------------------------------------- #include "hc_inc_npccorpse" #include "hc_text_activate" // ---------------------------------------------------------------------------- // CONSTANTS // ---------------------------------------------------------------------------- const string HC_RES_SKINNING_MEAT = "it_mmidmisc006"; const string HC_RES_SKINNING_MEAT2 = "it_mmidmisc007"; // ---------------------------------------------------------------------------- // FUNCTIONS // ---------------------------------------------------------------------------- void HC_ActionButcherAnimal(string sTag) { object oPC = OBJECT_SELF; FloatingTextStringOnCreature("*" + GetName(oPC) + SKINNING, oPC); CreateObject(OBJECT_TYPE_ITEM, HC_RES_SKINNING_MEAT, GetLocation(oPC)); // Here's your bit you added. if(sTag == "TagNameHere") { CreateObject(OBJECT_TYPE_ITEM, HC_RES_SKINNING_MEAT2, GetLocation(oPC)); } } // ---------------------------------------------------------------------------- // MAIN // ---------------------------------------------------------------------------- void main() { object oPC = OBJECT_SELF; object oCorpse = GetLocalObject(oPC, "OTHER"); object oBody = GetLocalObject(oCorpse, HC_VAR_NPCCORPSE_BODY); DeleteLocalObject(oPC, "OTHER"); // pre-emptive abort for invalid objects if(GetIsObjectValid(oCorpse) == FALSE || GetIsObjectValid(oBody) == FALSE) { return; } // the body must be an animal, must be dead and must be within 3m to be // successfully skinned. if(GetRacialType(oBody) != RACIAL_TYPE_ANIMAL) { SendMessageToPC(oPC, ANIMALONLY); return; } if(GetIsDead(oBody) == FALSE) { SendMessageToPC(oPC, NOTDEAD); return; } if(GetDistanceBetween(oPC, oBody) > 3.0) { SendMessageToPC(oPC, MOVECLOSER); return; } // skin the body: animate the PC, create the product and destroy the body AssignCommand(oPC, ActionMoveToLocation(GetLocation(oBody))); AssignCommand(oPC, DelayCommand(1.0, ActionPlayAnimation(ANIMATION_LOOPING_GET_LOW, 1.0, 1.0))); // If you wanted to go the variable route, you could pass in GetLocalString/int(oBody) instead. // Pass in the tag AssignCommand(oPC, DelayCommand(2.0, HC_ActionButcherAnimal(GetTag(oBody)))); HC_NPCCorpse_CleanUp(oCorpse); }