Howdy, I am once again calling upon the Heroes of the Vault.
I have a placeable that cast a spell at a creature when a player uses it, but when the creature dies, the player doesn’t receive xp. I think it is because the placeable is killing the creature not the player who uses the placeable.
What I think I need is an Ondeath script that will find the nearest PC and their faction members in the same area. Or some way to identify that the PC using the placeable is the killer of the creature.
I don’t know of a way or method, so any experienced scripters who know what I am trying to do, I would greatly appreciate the help.
Sometimes I’m not good at writing scripts from scratch, but maybe this will give you some ideas at least.
I’m sure someone more competent will come around and correct my mistakes here, but at least it’s a start for you.
I was unable to get the script to work, I’m probably just too ignorant on scripting to know how implement it. I think I did everything right… but I couldn’t tell if I did or didn’t.
I have altered the scenario a bit to get the creature in range so that the PC would have a higher percentage chance to get the last hit with melee or spell.
But until some skilled scripter with a kind soul like @andgalf takes pity on me, this is all I got for now.
Pretty sure nwn2 backend is like nwn1… If the pc isn’t doing anything, use their action queue to do the whatever from the placeable (damage, etc) or executescript. Then whatever else is used for xp/creature damage/death stuff should pick up the pc as the actor.
add this to the OnUsed script (using default OnDeath script)
object oLastUser = GetLastUsedBy();
object oTarget // the monster
int iDamage // the damage calculated
effect eDamage = EffectDamage(); // fill out as appropriate
AssignCommand(oLastUser, ApplyEffectToObject(DURATION_TYPE_INSTANT, eDamage, oTarget))
[edit] just had a thought, that the effect itself might need to be constructed by oLastUser. If so do the construction and application together in a subfunction and assign ownership/execution of the subfunction to oLastUser
Here is what I’m going with, but I don’t know if it will give the xp and item to the party faction. take a look see if the puzzle piece look right to you.
Thanks for the help!
//Ondeath sript
//Thanks Andgalf & KevL_s
void main()
{
// object oArea = GetObjectByTag("Area1");
// object oPC = GetFirstObjectInArea(oArea);
object oKiller = GetLocalObject(OBJECT_SELF, "weaponuser");
object oFM = GetFirstFactionMember(oKiller, FALSE);
if (GetIsObjectValid(oKiller) && !GetAssociateType(oFM) && GetArea(oKiller) == GetArea(oFM))
{
GiveXPToCreature(oFM, 1200); // change to appropriate XP
CreateItemOnObject("quest_sea_monster_scale", oFM); // <-- put your item's resref here
FloatingTextStringOnCreature("**You pick up one of the creature's scales.**", oFM);
}
}
@kevL_s Gotta look into the whole SetLocalObject function which I still have a hard time wrapping my head around for some reason. SetLocalInt and SetGlobalInt is much more logical to me, even though I know that SetLocalObject should be equally logical. Sometimes I wonder how my brain is wired…
EDIT: Ok, reading the lexicon now…So…You store an object on another object and then give the whole thing a name? That way, you can store another object, like a creature, on a another creature, then in the script if you use GetLocalObject, you check on the original object who/what the other object is by checking the variable/name? I can hardly understand what I myself am saying, but I think I got it kind of right, lol.
EDIT2: The explanation in the Script Assist in NWN2 Toolset is a bit confusing to me, as nValue isn’t present:
// Set oObject's local object variable sVarName to nValue
void SetLocalObject(object oObject, string sVarName, object oValue);
And what confuses me a bit in the Lexicon is that the object put on the other object is considered a variable. I still think my own explanation, for my own messy brain, seems about right.
PC is the killer (per the OnUsed script)
and you can assume that PC will be in the area with the monster
and he won’t be an associate (unless familiars can use the placeable, not so sure than they can…)
and i guess the user will be valid (since he just used the placeable) … so →
object oKiller = GetLocalObject(OBJECT_SELF, "weaponuser");
GiveXPToCreature(oKiller, 1200);
CreateItemOnObject("quest_sea_monster_scale", oKiller);
FloatingTextStringOnCreature("**You pick up one of the creature's scales.**", oKiller);
but i don’t know if you want to divide the XP up with Companions, or if you want to handle the possibility of a Companion using the placeable (said companion would get the item and XP)
the thing that’s a bit confusing is that when you store a local_int, the value of the int is stored directly.
But when a local_object is stored it’s merely a pointer to the object itself … (you aren’t making a copy of the object and storing that, you’re just storing a pointer to an object)
So sometimes when retrieving the object, for example, it should be checked if its still a valid object ingame. In contrast, you never have to check the validity of a local_int (it can never go invalid, but a local_object could go invalid)
@kevL_s - Ah, I think it’s a bit clearer now. Like I said in my editing of my previous post though, I find the explanation in the Script Assist and the Lexicon to be adding to the confusion rather than clearing things up for me. Just by calling the other object oValue makes me think…“Eh…what?”.
And it’s totally logical to me, just as you said, that you must check if the object is invalid or not. I mean, the object could have been destroyed or killed, who knows.