Author Topic: Help with a Death System  (Read 395 times)

Legacy_JediMindTrix

  • Sr. Member
  • ****
  • Posts: 383
  • Karma: +0/-0
Help with a Death System
« on: February 04, 2013, 04:02:18 am »


               

//::///////////////////////////////////////////////
//:: Death Script
//:: NW_O0_DEATH.NSS
//:: Copyright © 2008 Bioware Corp.
//:://////////////////////////////////////////////
/*
    This script handles the default behavior
    that occurs when a player dies.

    BK: October 8 2002: Overriden for Expansion

    Deva Winblood:  April 21th, 2008: Modified to
    handle dismounts when PC dies while mounted.

*/
//:://////////////////////////////////////////////
//:: Created By: Brent Knowles
//:: Created On: November 6, 2001
//:://////////////////////////////////////////////

#include "x3_inc_horse"

 /*
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);
}


///////////////////////////////////////////////////////////////[ MAIN ]/////////
void main()
{
//Information Gathering
object oPlayer = GetLastPlayerDied();
int iCurrentHour = GetTimeHour();
int iCurrentMinute = GetTimeMinute();
int iCurrentSecond = GetTimeSecond();
int iCurrentMilli = GetTimeMillisecond();

//Fade To Black
ActionDoCommand(FadeToBlack(oPlayer, FADE_SPEED_MEDIUM));

//Clear surrounding hostiles

//Advance CLock

SetTime(8 + iCurrentHour, 0 + iCurrentMinute, 0 + iCurrentSecond, 0 + iCurrentMilli);

//Raise the dead
Raise (oPlayer);

//Fade From Black
ActionDoCommand(FadeFromBlack(oPlayer, FADE_SPEED_MEDIUM));
}


This is my death script.
I'm trying to figure out a way to destroy hostile objects that surround a player, without destroying all hostile objects in an entire area or without having to use triggers, using the same radius that 'can't rest when hostile creature's are near' scheme.

My OnDying script I am utterly cluess on how how to begin.

I want to have a player character stay in the OnDying stage (preferablly at 0HP, or -1HP) until all Henchman fall. If Henchman win the battle, then the player character survives and comes back from 'unconsciousness'. If not, then he dies and the above script kicks in.
I also want the reverse to be true for Henchman.

Unfortunately, without a good working knowledge of script functions I am a little lost on how to proceed =/ Can anyone help?
               
               

               
            

Legacy_Squatting Monk

  • Hero Member
  • *****
  • Posts: 776
  • Karma: +0/-0
Help with a Death System
« Reply #1 on: February 04, 2013, 06:19:05 am »


               

NineCoronas2021 wrote...

I'm trying to figure out a way to destroy hostile objects that surround a player, without destroying all hostile objects in an entire area or without having to use triggers, using the same radius that 'can't rest when hostile creature's are near' scheme.

You can use GetFirstObjectInShape() and GetNextObjectInShape() to loop through nearby creatures, destroying the ones that ping as hostile. Alternatively, loop GetNearestCreature() and test each creature's distance from the PC.
               
               

               


                     Modifié par Squatting Monk, 04 février 2013 - 06:19 .
                     
                  


            

Legacy_Squatting Monk

  • Hero Member
  • *****
  • Posts: 776
  • Karma: +0/-0
Help with a Death System
« Reply #2 on: February 04, 2013, 06:59:43 am »


               

NineCoronas2021 wrote...

My OnDying script I am utterly cluess on how how to begin.

I want to have a player character stay in the OnDying stage (preferablly at 0HP, or -1HP) until all Henchman fall. If Henchman win the battle, then the player character survives and comes back from 'unconsciousness'. If not, then he dies and the above script kicks in.
I also want the reverse to be true for Henchman.

Unfortunately, without a good working knowledge of script functions I am a little lost on how to proceed =/ Can anyone help?

Here's the way NWN2 does it (it's not directly translateable into NWN1, but it does give you an idea for how to begin). The OnPlayerDeath script runs KnockOutCreature(), which runs a pseudo-heartbeat. Every three seconds, it checks to see if it's safe to wake the player up. The conditions for wakeup:

- The PC must have at least one living henchman
- No members of the party may be in combat
- No hostile creature with a line of sight to the PC may be within 15 meters of the PC

If all those conditions are met, it rezzes the PC.
               
               

               
            

Legacy_JediMindTrix

  • Sr. Member
  • ****
  • Posts: 383
  • Karma: +0/-0
Help with a Death System
« Reply #3 on: February 05, 2013, 03:35:06 pm »


               

object oPlayer = GetLastPlayerDying();
object oHench1 = GetHenchman(oPlayer, 1);
object oHench2 = GetHenchman(oPlayer, 2);
location lPlayerDying = GetLocation(oPlayer);
effect eDeath = EffectDeath(FALSE, FALSE);

void main()
{
  SetPlotFlag(oPlayer, TRUE);
//Set Plot To Prevent Further Damage          (DEV NOTE: If this doesn't work, alternatively confer massive damage reduction?)
//Heal to -1 HP, unless already at -1 HP
  switch (GetCurrentHitPoints(oPlayer)) //This switch runs through the various possible hp combo's and then will heal the player back to -1 in theory.
  {
   case -1:
   {
   SendMessageToPC(oPlayer, "No Hitpoint Change");
   break;
   }
   case -2:
   {
   EffectHeal(1);
   SendMessageToPC(oPlayer, "1 HP");
   break;
   }
   case -3:
   {
   EffectHeal(2);
   SendMessageToPC(oPlayer, "2 HP");
   break;
   }
   case -4:
   {
   EffectHeal(3);
   SendMessageToPC(oPlayer, "3 HP");
   break;
   }
   case -5:
   {
   EffectHeal(4);
   SendMessageToPC(oPlayer, "4 HP");
   break;
   }
   case -6:
   {
   EffectHeal(5);
   SendMessageToPC(oPlayer, "5 HP");
   break;
   }
   case -7:
   {
   EffectHeal(6);
   SendMessageToPC(oPlayer, "6 HP");
   break;
   }
   case -8:
   {
   EffectHeal(7);
   SendMessageToPC(oPlayer, "7 HP");
   break;
   }
   case -9:
   {
   EffectHeal(8);
   SendMessageToPC(oPlayer, "8 HP");
   break;
   }
   case 0:
   {
   EffectDamage(1, DAMAGE_TYPE_MAGICAL, DAMAGE_POWER_NORMAL);
   SendMessageToPC(oPlayer, "-1 HP");
   break;
   }
 }


 BloodSpatter(oPlayer, lPlayerDying);
//Vampire Regeneration Effect removal





//If possible, "disinterest" attacking monsters, (change faction temporarily of Player to Hostile?)


//Check to see if Henchmen are still alive

if (GetCurrentHitPoints(oHench1) <= 0 || GetCurrentHitPoints(oHench2) <= 0)
{//If not, remove immortality and initiate player death
SetPlotFlag(oPlayer, FALSE);
ApplyEffectToObject(DURATION_TYPE_INSTANT, eDeath, oPlayer);
}


I've bolded the part I can't seem to finangle into submission.

I can't figure out why the events inside the if script (Remove plot, kill player character) keep firing even with one or two henchman who have above 1hp. It erratically works with two henchman, always fires with only one (and obviously none).

What am I doing wrong here? O.o
               
               

               


                     Modifié par NineCoronas2021, 05 février 2013 - 03:54 .
                     
                  


            

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0
Help with a Death System
« Reply #4 on: February 05, 2013, 03:54:47 pm »


               perhaps the || should be &&

Question:
Is your goal only to execute the last block of code when both henchmen 1 and 2 are unconscious?

If yes, I'd go with the &&.
               
               

               
            

Legacy_JediMindTrix

  • Sr. Member
  • ****
  • Posts: 383
  • Karma: +0/-0
Help with a Death System
« Reply #5 on: February 05, 2013, 03:58:19 pm »


               

henesua wrote...

perhaps the || should be &&

Question:
Is your goal only to execute the last block of code when both henchmen 1 and 2 are unconscious?

If yes, I'd go with the &&.


For now, yes. I'm trying to get the core of the script to work before I put in sanity checks such as checking to see if the player has only 1 henchman or no henchman, etc.

My next goal is to figure out why:

object oHostile = GetFirstObjectInShape(SHAPE_SPHERE, 17.0, lPlayerDeath, TRUE, OBJECT_TYPE_CREATURE);
while(GetIsObjectValid(oHostile))
{
   if(GetIsReactionTypeHostile(oHostile))
   {
   if (!GetLocalInt(oHostile, "en_noclear"))
    {
    DestroyObject(oHostile); //Should stop the destruction of a creature if it has this integer on it.
    }
   }
   //Select the next target within the spell shape.
   oHostile = GetNextObjectInShape(SHAPE_SPHERE, 17.0, lPlayerDeath, TRUE, OBJECT_TYPE_CREATURE);
}


Refuses to destroy anything within 17 meters.
               
               

               
            

Legacy_MagicalMaster

  • Hero Member
  • *****
  • Posts: 2712
  • Karma: +0/-0
Help with a Death System
« Reply #6 on: February 05, 2013, 04:24:13 pm »


               I mostly skimmed this, but have you considered doing the following:

1, make a visual effect at lPlayerDeath to make sure it's actually on the player and not somewhere else

2, send a debugging message to the PC for each object it finds, something like (this is sloppy semi-psuedocode but you get the idea)

object oHostile = GetFirstObjectInShape(SHAPE_SPHERE, 17.0, lPlayerDeath, TRUE, OBJECT_TYPE_CREATURE);
while(GetIsObjectValid(oHostile))
{
   FloatingTextString("Found " + GetName(oHostile), oPlayer);
  if(GetIsReactionTypeHostile(oHostile))
  {
   FloatingTextString(GetName(oHostile) + " is hostile!", oPlayer);
  if (!GetLocalInt(oHostile, "en_noclear"))
   {
   FloatingTextString("Destroying" + GetName(oHostile), oPlayer);
   DestroyObject(oHostile); //Should stop the destruction of a creature if it has this integer on it.
   }
  }
  //Select the next target within the spell shape.
  oHostile = GetNextObjectInShape(SHAPE_SPHERE, 17.0, lPlayerDeath, TRUE, OBJECT_TYPE_CREATURE);
}


               
               

               
            

Legacy_JediMindTrix

  • Sr. Member
  • ****
  • Posts: 383
  • Karma: +0/-0
Help with a Death System
« Reply #7 on: February 05, 2013, 04:44:08 pm »


               Following your advice:

1) Location is correct, vfx appears where player dies.

2) The script appears to be running through and getting all the names, but it stops once it comes time to see if they are hostile or not. I've toyed with commenting out the "if" that checks for an integer to no effect.
               
               

               
            

Legacy_JediMindTrix

  • Sr. Member
  • ****
  • Posts: 383
  • Karma: +0/-0
Help with a Death System
« Reply #8 on: February 05, 2013, 05:41:28 pm »


               After a little research I've found that DestroyObject doesn't actually destroy anything until the script completes. Since this is a loop, could that have impact on it?
You'd think though, the messages would still be sending >.<

EDIT: It seems to work if the check to see if the creature is hostile is removed.

EDIT EDIT: Solved.
               
               

               


                     Modifié par NineCoronas2021, 05 février 2013 - 05:59 .