Life after death or Bioware dying, death, and respawn system

Life after death or Bioware dying, death, and Respawn system
There are 5 basic scripts for OnPlayerDying, OnPlayerDeath, and OnPlayerRespawn. They are "nw_o0_dying"(default), "nw_o0_death"(default), "x0_o0_death", "nw_o0_respawn"(default), and "x0_o0_respawn". The 2 starting with "x0" are from the expansions, but in esence are the same as their "nw" counter parts.

Dying
The OnPlayerDying script node is triggered when a PC reaches 0 hit points. The important thing to note about this script, and actually the only thing this script does is kill the player when the PC reaches 0 hitpoints. Lets look at the nw_o0_dying script.

//:://///////////////////////////////////////////// //:: Dying Script //:: NW_O0_DEATH.NSS //:: Copyright (c) 2001 Bioware Corp. //::////////////////////////////////////////////// /*   This script handles the default behavior that occurs when a player is dying. DEFAULT CAMPAIGN: player dies automatically //::////////////////////////////////////////////// //:: Created By: Brent Knowles //:: Created On: November 6, 2001 //::////////////////////////////////////////////// void main {   // AssignCommand(GetLastPlayerDying, ClearAllActions); // AssignCommand(GetLastPlayerDying,SpeakString( "I Dying")); // PopUpGUIPanel(GetLastPlayerDying,GUI_PANEL_PLAYER_DEATH); // * April 14 2002: Hiding the death part from player effect eDeath = EffectDeath(FALSE, FALSE); ApplyEffectToObject(DURATION_TYPE_INSTANT, eDeath, GetLastPlayerDying); }

The 3 commented out lines you see I beleive are debug lines that bio left in. They are not needed. The only lines that matter here are the effect and ApplyEffect lines. This is what actually kills the PC, not the creature they were fighting at the time.

So once your dead, the OnPlayerDeath script fires.

//:://///////////////////////////////////////////// //:: Death Script //:: NW_O0_DEATH.NSS //:: Copyright (c) 2001 Bioware Corp. //::////////////////////////////////////////////// /*   This script handles the default behavior that occurs when a player dies. BK: October 8 2002: Overriden for Expansion //::////////////////////////////////////////////// //:: Created By: Brent Knowles //:: Created On: November 6, 2001 //::////////////////////////////////////////////// /* void ClearAllFactionMembers(object oMember, object oPlayer) { //   AssignCommand(oMember, SpeakString("here")); AdjustReputation(oPlayer, oMember, 100); SetLocalInt(oPlayer, "NW_G_Playerhasbeenbad", 10); // * Player bad object oClear = GetFirstFactionMember(oMember, FALSE); while (GetIsObjectValid(oClear) == TRUE) {       ClearPersonalReputation(oPlayer, oClear); oClear = GetNextFactionMember(oMember, FALSE); } }  */ void Raise(object oPlayer) {       effect eVisual = EffectVisualEffect(VFX_IMP_RESTORATION); effect eBad = GetFirstEffect(oPlayer); ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectResurrection,oPlayer); ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectHeal(GetMaxHitPoints(oPlayer)), oPlayer); //Search for negative effects while(GetIsEffectValid(eBad)) {           if (GetEffectType(eBad) == EFFECT_TYPE_ABILITY_DECREASE ||                GetEffectType(eBad) == EFFECT_TYPE_AC_DECREASE ||                GetEffectType(eBad) == EFFECT_TYPE_ATTACK_DECREASE ||                GetEffectType(eBad) == EFFECT_TYPE_DAMAGE_DECREASE ||                GetEffectType(eBad) == EFFECT_TYPE_DAMAGE_IMMUNITY_DECREASE ||                GetEffectType(eBad) == EFFECT_TYPE_SAVING_THROW_DECREASE ||                GetEffectType(eBad) == EFFECT_TYPE_SPELL_RESISTANCE_DECREASE ||                GetEffectType(eBad) == EFFECT_TYPE_SKILL_DECREASE ||                GetEffectType(eBad) == EFFECT_TYPE_BLINDNESS ||                GetEffectType(eBad) == EFFECT_TYPE_DEAF ||                GetEffectType(eBad) == EFFECT_TYPE_PARALYZE ||                GetEffectType(eBad) == EFFECT_TYPE_NEGATIVELEVEL) {                   //Remove effect if it is negative. RemoveEffect(oPlayer, eBad); }           eBad = GetNextEffect(oPlayer); }       //Fire cast spell at event for the specified target SignalEvent(oPlayer, EventSpellCastAt(OBJECT_SELF, SPELL_RESTORATION, FALSE)); ApplyEffectToObject(DURATION_TYPE_INSTANT, eVisual, oPlayer); } void main {   object oPlayer = GetLastPlayerDied; // * increment global tracking number of times that I died SetLocalInt(oPlayer, "NW_L_PLAYER_DIED", GetLocalInt(oPlayer, "NW_L_PLAYER_DIED") + 1); // * BK: Automation Control. Autopcs ignore death if (GetLocalInt(oPlayer, "NW_L_AUTOMATION") == 10) {       Raise(oPlayer); DelayCommand(1.0, ExecuteScript("crawl", OBJECT_SELF)); return; // Raise and return }

// * Handle Spirit of the Wood Death string sArea = GetTag(GetArea(oPlayer)); /*   if (sArea == "MAP_M2Q2F2" && GetDistanceBetweenLocations(GetLocation(GetObjectByTag("M2Q2F2_M2Q2G")), GetLocation(oPlayer)) < 5.0 && GetLocalInt(GetModule,"NW_M2Q2E_WoodsFreed") == 0) {       int bValid; Raise(oPlayer); string sDestTag = "WP_M2Q2GtoM2Q2F"; object oSpawnPoint = GetObjectByTag(sDestTag); AssignCommand(oPlayer,JumpToLocation(GetLocation(oSpawnPoint))); return; }   // * in last level of the Sourcestone, move the player to the beginning of the area // * May 16 2002: or the main area of the Snowglobe (to prevent plot logic problems). // * May 21 2002: or Castle Never if (sArea == "M4Q1D2" || sArea == "M3Q3C" || sArea == "MAP_M1Q6A") {       //Raise(oPlayer); //string sDestTag = "M4QD07_ENTER"; //object oSpawnPoint = GetObjectByTag(sDestTag); //       AssignCommand(oPlayer, DelayCommand(1.0, JumpToLocation(GetLocation(oSpawnPoint)))); // * MAY 2002: Just popup the YOU ARE DEAD panel at this point DelayCommand(2.5, PopUpDeathGUIPanel(oPlayer,FALSE, TRUE, 66487)); return; }   // * make friendly to Each of the 3 common factions AssignCommand(oPlayer, ClearAllActions); // * Note: waiting for Sophia to make SetStandardFactionReptuation to clear all personal reputation if (GetStandardFactionReputation(STANDARD_FACTION_COMMONER, oPlayer) <= 10) {  SetLocalInt(oPlayer, "NW_G_Playerhasbeenbad", 10); // * Player bad SetStandardFactionReputation(STANDARD_FACTION_COMMONER, 80, oPlayer); }   if (GetStandardFactionReputation(STANDARD_FACTION_MERCHANT, oPlayer) <= 10) {  SetLocalInt(oPlayer, "NW_G_Playerhasbeenbad", 10); // * Player bad SetStandardFactionReputation(STANDARD_FACTION_MERCHANT, 80, oPlayer); }   if (GetStandardFactionReputation(STANDARD_FACTION_DEFENDER, oPlayer) <= 10) {  SetLocalInt(oPlayer, "NW_G_Playerhasbeenbad", 10); // * Player bad SetStandardFactionReputation(STANDARD_FACTION_DEFENDER, 80, oPlayer); }   DelayCommand(2.5, PopUpGUIPanel(oPlayer,GUI_PANEL_PLAYER_DEATH)); }

This script at first glance seems confusing. One thing to remember is that it has a lot of "left-over" stuff that only pertains to the Original campaign and really doesn't differ from the x0_o0_death script from the Hords Campaign. If we take out all the garbage, we are left with this.

/*void ClearAllFactionMembers(object oMember, object oPlayer) {   // AssignCommand(oMember, SpeakString("here")); AdjustReputation(oPlayer, oMember, 100); SetLocalInt(oPlayer, "NW_G_Playerhasbeenbad", 10); // * Player bad object oClear = GetFirstFactionMember(oMember, FALSE); while (GetIsObjectValid(oClear) == TRUE) {       ClearPersonalReputation(oPlayer, oClear); oClear = GetNextFactionMember(oMember, FALSE); } }  */ void Raise(object oPlayer) {       effect eVisual = EffectVisualEffect(VFX_IMP_RESTORATION); effect eBad = GetFirstEffect(oPlayer); ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectResurrection,oPlayer); ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectHeal(GetMaxHitPoints(oPlayer)), oPlayer); //Search for negative effects while(GetIsEffectValid(eBad)) {           if (GetEffectType(eBad) == EFFECT_TYPE_ABILITY_DECREASE ||                GetEffectType(eBad) == EFFECT_TYPE_AC_DECREASE ||                GetEffectType(eBad) == EFFECT_TYPE_ATTACK_DECREASE ||                GetEffectType(eBad) == EFFECT_TYPE_DAMAGE_DECREASE ||                GetEffectType(eBad) == EFFECT_TYPE_DAMAGE_IMMUNITY_DECREASE ||                GetEffectType(eBad) == EFFECT_TYPE_SAVING_THROW_DECREASE ||                GetEffectType(eBad) == EFFECT_TYPE_SPELL_RESISTANCE_DECREASE ||                GetEffectType(eBad) == EFFECT_TYPE_SKILL_DECREASE ||                GetEffectType(eBad) == EFFECT_TYPE_BLINDNESS ||                GetEffectType(eBad) == EFFECT_TYPE_DEAF ||                GetEffectType(eBad) == EFFECT_TYPE_PARALYZE ||                GetEffectType(eBad) == EFFECT_TYPE_NEGATIVELEVEL) {                   //Remove effect if it is negative. RemoveEffect(oPlayer, eBad); }           eBad = GetNextEffect(oPlayer); }       //Fire cast spell at event for the specified target SignalEvent(oPlayer, EventSpellCastAt(OBJECT_SELF, SPELL_RESTORATION, FALSE)); ApplyEffectToObject(DURATION_TYPE_INSTANT, eVisual, oPlayer); } void main {   object oPlayer = GetLastPlayerDied; // * increment global tracking number of times that I died SetLocalInt(oPlayer, "NW_L_PLAYER_DIED", GetLocalInt(oPlayer, "NW_L_PLAYER_DIED") + 1); // * BK: Automation Control. Autopcs ignore death if (GetLocalInt(oPlayer, "NW_L_AUTOMATION") == 10) {       Raise(oPlayer); DelayCommand(1.0, ExecuteScript("crawl", OBJECT_SELF)); return; // Raise and return }   // * make friendly to Each of the 3 common factions AssignCommand(oPlayer, ClearAllActions); // * Note: waiting for Sophia to make SetStandardFactionReptuation to clear all personal reputation if (GetStandardFactionReputation(STANDARD_FACTION_COMMONER, oPlayer) <= 10) {  SetLocalInt(oPlayer, "NW_G_Playerhasbeenbad", 10); // * Player bad SetStandardFactionReputation(STANDARD_FACTION_COMMONER, 80, oPlayer); }   if (GetStandardFactionReputation(STANDARD_FACTION_MERCHANT, oPlayer) <= 10) {  SetLocalInt(oPlayer, "NW_G_Playerhasbeenbad", 10); // * Player bad SetStandardFactionReputation(STANDARD_FACTION_MERCHANT, 80, oPlayer); }   if (GetStandardFactionReputation(STANDARD_FACTION_DEFENDER, oPlayer) <= 10) {  SetLocalInt(oPlayer, "NW_G_Playerhasbeenbad", 10); // * Player bad SetStandardFactionReputation(STANDARD_FACTION_DEFENDER, 80, oPlayer); }   DelayCommand(2.5, PopUpGUIPanel(oPlayer,GUI_PANEL_PLAYER_DEATH)); }

Note that the function "ClearAllFactionMembers" is still commented out, but left in. This function, if used will clear the hostility of oMember towards oPlayer for custom Factions, just as it does for the standard factions. For example, if a PC attacks a faction that is not normally hostile to the PC, and the PC dies. When the Player respawns that faction will still be hostile towards them. This function can be used to clear that state so the faction is no longer hostile when the PC re-spawns. To demonstrate this we will need to alter the OnPlayerDying script as well. Remember that the Module kills the player in the OnPlayer Dying and to use the ClearAllFactionMembers function we will need the object of the Players NPC killer. Functions like GetLastkiller or GetLastHostileActor are going to return the module object and not the NPC killer. More on this later.

The next function is the Raise function. This is used to "Re-spawn" the PC if the Automation control is set on the Player object. Looking further down in the script, under the void main, the first IF statment checks to see if the variable "NW_L_AUTOMATION" is set to 10, if so, then auto-respawn the PC. We can test that now if you like. Enter a Module and in the chat bar type ##DebugMode 1 and hit enter, then type ##dm_setvarint NW_L_AUTOMATION 10 and hit enter. The curser will change to a "targeter", click on your PC. Now attack something that you know can kill your PC. YOU WON'T DIE!

After the Rasie function we come to the void main. First the script gets the player that just died, then sets a variable int on that player tracking the number of times that player died. So if you ever want to know how much a PC died during that game session, you can use int iDied = GetLocalInt(oPlayer, "NW_L_PLAYER_DIED"); where oPlayer is the PC object in question. This was used in certain features of Hords I believe. If you don't need it, you can safely take it out.

Next is the If statment we just discussed, it checks to see if the PC auto-respawn is turned on. This mainly comes in handy for testing. This too can be removed if not in use. Note that this block also runs a script called "crawl". This script does not exsist so nothing is called.

Further down we see 3 if blocks these set "NW_G_Playerhasbeenbad" on the Player if they became hostile to either the Commoner, Defender, or Merchant factions then resets these factions to friendly. This is so if the player attacks a guard for example, and gets killed, the Player can re-spawn and not get re-attacked by the guards.

Then finaly we have the delay to pop up the player GUI panel. This is the panel that gives the player a choice of "Load", "Respawn", "Exit". Load will allow the Player to re-load or load a different module. Exit takes the player back to the game startup screen and Respawn will, of course, run the OnPlayerRespawn script node.

Before we move on to the OnPlayerRespawn script, lets revisit the ClearAllFactionMembers function and what must be done to make it work. This will also show how to "get" the object that killed the PC instead of the Module. The quickest way is to simply remove the OnPlayerDiying script or comment out the ApplyEffect line. This will allow us to use GetLastHostileActor in the OnDeath script. I should also mention here that doing so means that the player will become "unconsious" at 0 and not die until they reach -11 but there are ways around that as well. Now we can alter the OnPlayerDeath script like this,

void ClearAllFactionMembers(object oMember, object oPlayer) {   // AssignCommand(oMember, SpeakString("here")); AdjustReputation(oPlayer, oMember, 80); SetLocalInt(oPlayer, "NW_G_Playerhasbeenbad", 10); // * Player bad object oClear = GetFirstFactionMember(oMember, FALSE); while (GetIsObjectValid(oClear) == TRUE) {       ClearPersonalReputation(oPlayer, oClear); oClear = GetNextFactionMember(oMember, FALSE); } } void Raise(object oPlayer) {       effect eVisual = EffectVisualEffect(VFX_IMP_RESTORATION); effect eBad = GetFirstEffect(oPlayer); ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectResurrection,oPlayer); ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectHeal(GetMaxHitPoints(oPlayer)), oPlayer); //Search for negative effects while(GetIsEffectValid(eBad)) {           if (GetEffectType(eBad) == EFFECT_TYPE_ABILITY_DECREASE ||                GetEffectType(eBad) == EFFECT_TYPE_AC_DECREASE ||                GetEffectType(eBad) == EFFECT_TYPE_ATTACK_DECREASE ||                GetEffectType(eBad) == EFFECT_TYPE_DAMAGE_DECREASE ||                GetEffectType(eBad) == EFFECT_TYPE_DAMAGE_IMMUNITY_DECREASE ||                GetEffectType(eBad) == EFFECT_TYPE_SAVING_THROW_DECREASE ||                GetEffectType(eBad) == EFFECT_TYPE_SPELL_RESISTANCE_DECREASE ||                GetEffectType(eBad) == EFFECT_TYPE_SKILL_DECREASE ||                GetEffectType(eBad) == EFFECT_TYPE_BLINDNESS ||                GetEffectType(eBad) == EFFECT_TYPE_DEAF ||                GetEffectType(eBad) == EFFECT_TYPE_PARALYZE ||                GetEffectType(eBad) == EFFECT_TYPE_NEGATIVELEVEL) {                   //Remove effect if it is negative. RemoveEffect(oPlayer, eBad); }           eBad = GetNextEffect(oPlayer); }       //Fire cast spell at event for the specified target SignalEvent(oPlayer, EventSpellCastAt(OBJECT_SELF, SPELL_RESTORATION, FALSE)); ApplyEffectToObject(DURATION_TYPE_INSTANT, eVisual, oPlayer); } void main {   object oPlayer = GetLastPlayerDied; // * increment global tracking number of times that I died SetLocalInt(oPlayer, "NW_L_PLAYER_DIED", GetLocalInt(oPlayer, "NW_L_PLAYER_DIED") + 1); // * BK: Automation Control. Autopcs ignore death if (GetLocalInt(oPlayer, "NW_L_AUTOMATION") == 10) {       Raise(oPlayer); DelayCommand(1.0, ExecuteScript("crawl", OBJECT_SELF)); return; // Raise and return }   // * make friendly to Each of the 3 common factions AssignCommand(oPlayer, ClearAllActions); // * Note: waiting for Sophia to make SetStandardFactionReptuation to clear all personal reputation if (GetStandardFactionReputation(STANDARD_FACTION_COMMONER, oPlayer) <= 10) {  SetLocalInt(oPlayer, "NW_G_Playerhasbeenbad", 10); // * Player bad SetStandardFactionReputation(STANDARD_FACTION_COMMONER, 80, oPlayer); }   if (GetStandardFactionReputation(STANDARD_FACTION_MERCHANT, oPlayer) <= 10) {  SetLocalInt(oPlayer, "NW_G_Playerhasbeenbad", 10); // * Player bad SetStandardFactionReputation(STANDARD_FACTION_MERCHANT, 80, oPlayer); }   if (GetStandardFactionReputation(STANDARD_FACTION_DEFENDER, oPlayer) <= 10) {  SetLocalInt(oPlayer, "NW_G_Playerhasbeenbad", 10); // * Player bad SetStandardFactionReputation(STANDARD_FACTION_DEFENDER, 80, oPlayer); }   object oKiller = GetLastHostileActor(oPlayer); ClearAllFactionMembers(oKiller,oPlayer); DelayCommand(2.5, PopUpGUIPanel(oPlayer,GUI_PANEL_PLAYER_DEATH)); }

Notice I changed the ammount in the ClearAllFactionMembers function from 100 to 80. setting it at 100 will make that faction 100% (green) to the PC and if the game is set on Non-PVP settings, the PC will not be allowed to attack that faction again. Also I added 2 lines just before the last line - DelayCommand. The First line gets the last object takeing hostile actions towards the PC and assigns it to the variable oKiller, the second line calles the ClearAllFactionMembers function and it uses the custom faction of the NPC oKiller, and adjust it back to neutral towards the PC. This function too will set the NW_G_Playerhasbeenbad variable for your custom factions if you choose to use it. Note that care must be taken if useing this function becouse it will set any faction to "like" the PC, includeing hostile factions that should remaine hostile. This can be handeled by checking the faction of the killer first and skip the Clear.

Now, oKiller will be the last creature that killed the PC and not the module. Also, when the PC dies the faction will clear just as it does for the standard factions. Note that I used GetLastHostileActor(oPlayer); instead of GetLastKiller; This is because GetLastKiller only returns a valid object to the caller of the script. Since the OnPlayerDeath script is attached to the module, the module is the caller. Nothing killed the module therfore GetLastKiller will be invalid. However, GetLastKiller can be used if we make the player that died call the OnDeath script via the ExecuteScript function, but thats for more advanced scripting

Now I will cover the OnPlayerRespawn script and cover what happens when the Player hits the "Respawn" button. Again there is a lot of "left Over" stuff from the OC. Here I will post a Respawn script with a lot of the junk stripped out.

// * Applies an XP and GP penalty // * to the player respawning void ApplyPenalty(object oDead) {   int nXP = GetXP(oDead); int nPenalty = 50 * GetHitDice(oDead); int nHD = GetHitDice(oDead); // * You can not lose a level with this respawning int nMin = ((nHD * (nHD - 1)) / 2) * 1000; int nNewXP = nXP - nPenalty; if (nNewXP < nMin) nNewXP = nMin; SetXP(oDead, nNewXP); int nGoldToTake =   FloatToInt(0.10 * GetGold(oDead)); // * a cap of 10 000gp taken from you if (nGoldToTake > 10000) {       nGoldToTake = 10000; }   AssignCommand(oDead, TakeGoldFromCreature(nGoldToTake, oDead, TRUE)); DelayCommand(4.0, FloatingTextStrRefOnCreature(58299, oDead, FALSE)); DelayCommand(4.8, FloatingTextStrRefOnCreature(58300, oDead, FALSE)); } void main {   object oRespawner = GetLastRespawnButtonPresser; ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectResurrection,oRespawner); ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectHeal(GetMaxHitPoints(oRespawner)), oRespawner); RemoveEffects(oRespawner); //* Return PC to temple string sDestTag = "NW_DEATH_TEMPLE"; if (GetIsObjectValid(GetObjectByTag(sDestTag))) {       if (sDestTag == "NW_DEATH_TEMPLE") {           object oPriest = GetObjectByTag("NW_DEATH_CLERIC"); //SetLocalInt(oPriest, "NW_L_SAYONELINER", 10); //AssignCommand(oPriest, DelayCommand(3.0,ActionStartConversation(oRespawner))); AssignCommand(oPriest, DelayCommand(2.1, PlayVoiceChat(VOICE_CHAT_TALKTOME, oPriest))); SetLocalLocation(oRespawner, "NW_L_I_DIED_HERE", GetLocation(GetLastRespawnButtonPresser)); SetLocalInt(oRespawner, "NW_L_I_DIED", 1); SetLocalObject(oPriest, "NW_L_LASTDIED", GetLastRespawnButtonPresser); // * April 2002: Moved penalty here, only when going back to the death temple ApplyPenalty(oRespawner); }       object oSpawnPoint = GetObjectByTag(sDestTag); AssignCommand(oRespawner,JumpToLocation(GetLocation(oSpawnPoint))); // * mak }   // else do nothing, just 'res where you are. }
 * 1) include "nw_i0_plot"

First we see a include file "#include "nw_i0_plot". This file holds the function RemoveEffects which removes all negative effects on the Player, much like the Raise function in the OnPlayerDeath script. Then we see a function called ApplyPenalty. This function is used if the NW_DEATH_TEMPLE object is placed in your module, more on that in a bit. Next we see that the player is rasied and healed and all bad effects are removed.

In the OC game, when you respawned, the PC would transport to the temple. This can be done in your own module as well simply by placeing a waypoint, or any object for that matter with a tag of "NW_DEATH_TEMPLE". If this object is valid, then the player will be teleported to it on respawn AND givein a respawn penalty by the ApplyPenalty function. If you want the player to port here, but no penalty, then simply comment out the line ApplyPenalty. If this object is not valid, nothing happens and the PC respawns where they died. The object oPriest and other variables within that if block can be used if wanted but a part of the OC and can be taken out as well. If you want to Apply the penalty without useing the NW_DEATH_TEMPLE then add else ApplyPenalty(oRespawner); between the last 2 "}" at the end of the script.

Thats the basics of how the bioware Death and respawn system works. By altering these 3 scripts, you can do just about anything for players dying, death, and re-spawn. Hopefully this information was helpful, enjoy