Aller au contenu

Photo

Need help with on death events.


  • Veuillez vous connecter pour répondre
44 réponses à ce sujet

#26
M. Rieder

M. Rieder
  • Members
  • 2 530 messages
Okay, here they are. I warn you, My scripts are not always beautiful...


Player on death:

----------------------------------------------
---------------------------------------------


/*Game ends if PC and blaerdrig and ayale are dead. There is no respawn.

/*Adapted from moonshadows. When player dies there is no respawn.

*/






#include "ginc_debug"
#include "ginc_death"
void GUI()
{


//one more check just to make sure the death screen should pop up.
object oPlayer = OBJECT_SELF;
object oMember = GetFirstFactionMember(oPlayer,FALSE);
while (GetIsObjectValid(oMember))
{
if (!GetIsDead(oMember))
{
return;
}
oMember = GetNextFactionMember(oPlayer,FALSE);
}

DisplayGuiScreen(oPlayer,"SCREEN_PARTY_DEATH",FALSE);
SetGUIObjectDisabled(oPlayer,"SCREEN_PARTY_DEATH","BUTTON_RESPAWN",TRUE);
SetGUIObjectHidden(oPlayer,"SCREEN_PARTY_DEATH","BUTTON_RESPAWN",TRUE);
SetGUIObjectDisabled(oPlayer,"SCREEN_PARTY_DEATH","BUTTON_WAIT_FOR_HELP",TRUE);
SetGUIObjectHidden(oPlayer,"SCREEN_PARTY_DEATH","BUTTON_WAIT_FOR_HELP",TRUE);



// DisplayGuiScreen(GetFirstPC(),"SCREEN_PARTY_DEATH",FALSE);
//SetGUIObjectDisabled(GetFirstPC(),"SCREEN_PARTY_DEATH","BUTTON_RESPAWN",TRUE);
//SetGUIObjectHidden(GetFirstPC(),"SCREEN_PARTY_DEATH","BUTTON_RESPAWN",TRUE);
//SetGUIObjectDisabled(GetFirstPC(),"SCREEN_PARTY_DEATH","BUTTON_WAIT_FOR_HELP",TRUE);
//SetGUIObjectHidden(GetFirstPC(),"SCREEN_PARTY_DEATH","BUTTON_WAIT_FOR_HELP",TRUE);
}

void main()
{
//SetOwnersControlledCompanion(GetFirstPC(FALSE),GetFirstPC());
object oSelf = OBJECT_SELF;
object oPlayer = GetLastPlayerDied();
object oArea2062 = GetObjectByTag("area_2062");
object oBlaerdrig = GetObjectByTag("blaerdrig");
object oAyale = GetObjectByTag("ayale");
//gloabl int is set to 1 in the 2062_first_enter_stadium convo on
//the first node. It is set to 0 on the 2063_after_tournament convo
//in the first node.
int nIsInTournament = GetGlobalInt("IS_IN_2062_TOURNAMENT");
//check to see if oSelf is the owned character or a controlled character
//if not, execute twa_on_companion_death and stop this script.
// FloatingTextStringOnCreature("executing_player_death_script",oPlayer);
//PrettyDebug("executing player death script",30.0);

//prevent auto recussitation
// AssignCommand(oPlayer,KnockOutCreature(oPlayer));

if (!GetIsOwnedByPlayer(oPlayer))
{
// FloatingTextStringOnCreature("not owned, execute comp death",oPlayer);
//PrettyDebug("not owned execute companion death script",30.0);
ExecuteScript("twa_on_companion_death",oPlayer);
return;
}
// if(!GetIsObjectValid(oPlayer))
// {
// FloatingTextStringOnCreature("not valid",GetFirstPC());
// }



if ((GetIsRosterMember(oBlaerdrig))&&
(!GetIsDead(oBlaerdrig)))
{
FloatingTextStringOnCreature("My God, it's full of stars...", oPlayer, FALSE, 3.0);
//FloatingTextStringOnCreature("bla",GetFirstPC());
return;
}

if ((GetIsRosterMember(oAyale))&&
(!GetIsDead(oAyale)))
{
FloatingTextStringOnCreature("My God, it's full of stars...", oPlayer, FALSE, 3.0);
// FloatingTextStringOnCreature("ay",GetFirstPC());
return;
}
//there is no specific check for the golem because the next check will handle it.
//check to see if there are any other PC's alive in party (for multi-play)

object oMember = GetFirstFactionMember(oPlayer,FALSE);
while (GetIsObjectValid(oMember))
{
if (!GetIsDead(oMember))
{
return;
}
oMember = GetNextFactionMember(oPlayer,FALSE);
}



FloatingTextStringOnCreature("My God, it's full of stars...", oPlayer, FALSE, 3.0);
// DelayCommand(3.0, FadeToBlack(oPlayer, FADE_SPEED_SLOW, 0.0, COLOR_RED_DARK));
// DelayCommand(5.0, EndGame(""));


//this code handles the tournament in area_2062
object oArea = GetArea(oPlayer);


//check to make sure oArea is valid
if (!GetIsObjectValid(oArea))
{

oArea = GetArea(oSelf);
}
//check to make sure oArea is valid
if (!GetIsObjectValid(oArea))
{

oArea = GetArea(GetFirstPC(FALSE));
}
//check to make sure oArea is valid
if (!GetIsObjectValid(oArea))
{

oArea = GetArea(GetFirstPC());
}


//if(GetTag(oArea)=="area_2062")
if (nIsInTournament==1)
{

DelayCommand(2.0,ExecuteScript("2062_tournament_defeat",oArea2062));
return;
}


//FloatingTextStringOnCreature("im oSelf",OBJECT_SELF);

//DelayCommand(2.0,GUI());
DelayCommand(2.0,AssignCommand(GetFirstPC(),GUI()));


}


--------------------------------------------
--------------------------------------------

companion on death

/*Game ends if PC and blaerdrig and ayale are dead. There is no respawn.

/*Adapted from moonshadows. When player dies there is no respawn.

*/
#include "ginc_debug"
#include "ginc_death"
void GUI()
{


//one more check just to make sure the death screen should pop up.
object oPlayer = OBJECT_SELF;
// int nIsInTournament = GetGlobalInt("IS_IN_2062_TOURNAMENT");
// object oArea2062 = GetObjectByTag("area_2062");
object oMember = GetFirstFactionMember(oPlayer,FALSE);
while (GetIsObjectValid(oMember))
{
if (!GetIsDead(oMember))
{
return;
}
oMember = GetNextFactionMember(oPlayer,FALSE);
}

/*
if (nIsInTournament==1)
{

ExecuteScript("2062_tournament_defeat",oArea2062);
return;
}
*/



DisplayGuiScreen(oPlayer,"SCREEN_PARTY_DEATH",FALSE);
SetGUIObjectDisabled(oPlayer,"SCREEN_PARTY_DEATH","BUTTON_RESPAWN",TRUE);
SetGUIObjectHidden(oPlayer,"SCREEN_PARTY_DEATH","BUTTON_RESPAWN",TRUE);
SetGUIObjectDisabled(oPlayer,"SCREEN_PARTY_DEATH","BUTTON_WAIT_FOR_HELP",TRUE);
SetGUIObjectHidden(oPlayer,"SCREEN_PARTY_DEATH","BUTTON_WAIT_FOR_HELP",TRUE);



// DisplayGuiScreen(GetFirstPC(),"SCREEN_PARTY_DEATH",FALSE);
//SetGUIObjectDisabled(GetFirstPC(),"SCREEN_PARTY_DEATH","BUTTON_RESPAWN",TRUE);
//SetGUIObjectHidden(GetFirstPC(),"SCREEN_PARTY_DEATH","BUTTON_RESPAWN",TRUE);
//SetGUIObjectDisabled(GetFirstPC(),"SCREEN_PARTY_DEATH","BUTTON_WAIT_FOR_HELP",TRUE);
//SetGUIObjectHidden(GetFirstPC(),"SCREEN_PARTY_DEATH","BUTTON_WAIT_FOR_HELP",TRUE);
}

void main()
{
//SetOwnersControlledCompanion(GetLastPlayerDied(),GetFirstPC());
//PrettyDebug("executing companion death script",30.0);
//FloatingTextStringOnCreature("on companion death",GetFirstPC(FALSE));
// SendMessageToPC(GetFirstPC(FALSE),"on companion death");
object oPlayer = OBJECT_SELF;
object oSelf = OBJECT_SELF;
object oArea2062 = GetObjectByTag("area_2062");
object oBlaerdrig = GetObjectByTag("blaerdrig");
object oAyale = GetObjectByTag("ayale");
//gloabl int is set to 1 in the 2062_first_enter_stadium convo on
//the first node. It is set to 0 on the 2063_after_tournament convo
//in the first node.
int nIsInTournament = GetGlobalInt("IS_IN_2062_TOURNAMENT");




//prevent auto recussitation
// AssignCommand(oPlayer,KnockOutCreature(oPlayer));


if ((GetIsRosterMember(oBlaerdrig))&&
(!GetIsDead(oBlaerdrig)))
{
FloatingTextStringOnCreature("My God, it's full of stars...", oPlayer, FALSE, 3.0);
//FloatingTextStringOnCreature("bla",GetFirstPC());
return;
}

if ((GetIsRosterMember(oAyale))&&
(!GetIsDead(oAyale)))
{
FloatingTextStringOnCreature("My God, it's full of stars...", oPlayer, FALSE, 3.0);
// FloatingTextStringOnCreature("ay",GetFirstPC());
return;
}
//there is no specific check for the golem because the next check will handle it.
//check to see if there are any other PC's alive in party (for multi-play)

object oMember = GetFirstFactionMember(oPlayer,FALSE);
while (GetIsObjectValid(oMember))
{
if (!GetIsDead(oMember))
{
return;
}
oMember = GetNextFactionMember(oPlayer,FALSE);
}



FloatingTextStringOnCreature("My God, it's full of stars...", oPlayer, FALSE, 3.0);
// DelayCommand(3.0, FadeToBlack(oPlayer, FADE_SPEED_SLOW, 0.0, COLOR_RED_DARK));
// DelayCommand(5.0, EndGame(""));


//DOUBLE CHECK AND RETURN IF FIRST PC IS STILL ALIVE
if (!GetIsDead(GetFirstPC()))
{
return;
}

//this code handles the tournament in area_2062
object oArea = GetArea(oPlayer);
//check to make sure oArea is valid
if (!GetIsObjectValid(oArea))
{

oArea = GetArea(oSelf);
}
//check to make sure oArea is valid
if (!GetIsObjectValid(oArea))
{

oArea = GetArea(GetFirstPC(FALSE));
}
//if(GetTag(oArea)=="area_2062")
if (nIsInTournament==1)
{

ExecuteScript("2062_tournament_defeat",oArea2062);
return;
}



//DelayCommand(2.0,GUI());
DelayCommand(2.0,AssignCommand(GetFirstPC(),GUI()));

}


---------------------------------------
---------------------------------------
Companion Pre-death script - used at an extra check to make sure it doesn't fire inappropriately

/*Checks to see if the PC is dead. If so, game ends.

*/
#include "ginc_death"
void main()
{
object oPlayer = OBJECT_SELF;
object oPC = GetFirstPC();
object oAyale = GetObjectByTag("ayale");
object oBlaerdrig = GetObjectByTag("blaerdrig");
object oGolem = GetObjectByTag("golem_companion");
object oArea = GetArea(oPlayer);
SpeakString("My God it's full of stars...");
//prevent auto recussitation
// AssignCommand(oPlayer,KnockOutCreature(oPlayer));

//SetOwnersControlledCompanion(GetFirstPC(FALSE),GetFirstPC());

if (!GetIsDead(oPC))
{
return;
}

//if ((GetIsRosterMember(oAyale))&&
// (!GetIsDead(oAyale)))
// {
// return;
// }

if ((GetIsRosterMember(oGolem))&&
(!GetIsDead(oGolem)))
{
return;
}

if ((GetIsRosterMember(oBlaerdrig))&&
(!GetIsDead(oBlaerdrig)))
{
return;
}


//if you are in tournament, execute proper script.
//ExecuteScript("twa_on_player_death",GetFirstPC());
//ExecuteScript("twa_on_companion_death",GetFirstPC());
ExecuteScript("twa_on_companion_death",oPlayer);
}
//don't need to check for other players because "twa_on_player_death" does.

/*
if ((GetIsDead(oPC))&&
(GetIsDead(oAyale))&&
(GetIsDead(oGolem)))
{

ExecuteScript("twa_on_player_death",GetFirstPC());
}

*/



Each of my companions has the pre-death script in the on death event and that calls the companion on death script.

#27
kevL

kevL
  • Members
  • 4 052 messages
ahh, three lovely damsels to spend the afternoon with ...

( and as frustrating ;)

#28
kevL

kevL
  • Members
  • 4 052 messages
EDIT, see three posts down.

ya know, Matt, i wonder if it was just a coding error:

when you do the checks for IsOwned/IsDead in these scripts, it's set to RETURN if Object is not the toon in question. So, if a PC or companion *is not dead* the code may exit ( return ) before getting to the juicy parts for the char that *is* dead ...

eg.
if (!GetIsOwnedByPlayer(oPlayer))
{
return;
}
if (GetIsRosterMember(oBlaerdrig) && !GetIsDead(oBlaerdrig))
{
return;
}
if (GetIsRosterMember(oAyale) && !GetIsDead(oAyale))
{
return;
}

Hence the stuff that follows, such as:

FloatingTextStringOnCreature("My God, it's full of stars...", oPlayer, FALSE, 3.0);
DelayCommand(2.0, AssignCommand(GetFirstPC(), GUI()));

might never fire off, because the script has exited as soon as the engine encounters the first valid condition above. Ie, the CompOnDeath would work for Blaerdrig but not for Ayale; the ModOnDeath would work for the PC but not the companions .....


(barring other quirky behavior) If this is indeed a/the problem, the conditions should be amalgamated into

if (GetIsOwnedByPlayer(oPlayer) && GetIsDead(oPlayer)
|| (GetIsRosterMember(oBlaerdrig) && GetIsDead(oBlaerdrig))
|| (GetIsRosterMember(oAyale) && GetIsDead(oAyale)))
{
// place the juicy bits here.
}
else return;


Ps. I take it you're not actually using any Dying stuff - this matters re. GetIsDead( ) bIgnoreDying argument. If so it's very tempting to just strip the OnDying script out completely,

Modifié par kevL, 17 mars 2012 - 07:33 .


#29
kevL

kevL
  • Members
  • 4 052 messages
Pps. I notice that the function ShowProperDeathScreen( ) in 'ginc_death' uses SetOwnersControlledCompanion( ) first thing, such that the player is controlling GetFirstPC(TRUE), or variant, when ShowDeathScreen( ) is called. suggest:

object oPC = SetOwnersControlledCompanion(OBJECT_SELF);
DisplayGuiScreen(oPC, "SCREEN_PARTY_DEATH", FALSE);

in yer GUI( ) function; i'm still checking flow generally .. the above isn't quite right methinkz

Modifié par kevL, 17 mars 2012 - 07:08 .


#30
M. Rieder

M. Rieder
  • Members
  • 2 530 messages
Thanks for looking at the KevL. If you notice anything else, let me know. I'll get back in there and tweak it and see what we can get running.

#31
kevL

kevL
  • Members
  • 4 052 messages
np, i got coffee

OKAY, now i understand you *want* the script to stop if PC or any companion is still living ... still suspicious about !GetIsOwnedByPlayer( ) return;

#32
M. Rieder

M. Rieder
  • Members
  • 2 530 messages

kevL wrote...

np, i got coffee

OKAY, now i understand you *want* the script to stop if PC or any companion is still living ... still suspicious about !GetIsOwnedByPlayer( ) return;



I was originally having problems with the death script firing when some players are still alive and sometimes not firing when all the players were dead.  Throughout the course of debugging, I messed with it so much and tweaked it here and there that I don't really remember the entire purpose of everything.  That's what I get for not making more careful notes. 

#33
kevL

kevL
  • Members
  • 4 052 messages
hey Matt, i got something to help straigten ya out here

results of the afternoon's foraging ...


If player is controlling a companion, the CompOnDeath script doesn't fire; the ModOnDying does (if applicable damage doesn't outright kill the controlled object). The ModOnDeath script, however, does not fire either. So if player is controlling a companion who gets instantly blown away, yer SOL per deathscripts.

OBJECT_SELF in the ModOnDying/Death scripts is the module object. Use GetLastPlayerDying( ) & GetLastPlayerDead( ) - these return the controlled object, whether controlled PC or controlled, dying Companion.

When an uncontrolled Companion dies, the CompOnDeath script fires. GetLastPlayerDied( ) returns nothing; use OBJECT_SELF for the companion.

When controlling a Companion and the PC dies, both ModOnDying/Death run okay.


The anomaly, as Matt mentioned, will come to the fore when the PC is dead and the last character standing/controlled(?) is a companion (or probably other faction member like a familiar or SoZ created character - no tests were done with the latter two types of objects)

The ModOnDying seems to run okay (if applicable) for an uncontrolled Companion as well as a controlled Companion; again, the ModOnDeath does not run for Companions, only for the PC object. When controlling a dead PC, the CompOnDeath will fire okay, when a Companion dies.

And when controlling a dead companion, and the PC dies, ModOnDying/Death fire okay.



Here are the scripts I used ( parsed ):

// Module OnDying
void main()
{
	SendMessageToPC(GetFirstPC(FALSE), ". Run ( mr_mod_dying )");

	object oDying = GetLastPlayerDying();

	SendMessageToPC(GetFirstPC(FALSE), ". . LastDying = " + GetName(oDying));

	effect eDeath = EffectDeath(FALSE, FALSE, TRUE);
	ApplyEffectToObject(DURATION_TYPE_INSTANT, eDeath, oDying);
}


// Module OnDeath
void main()
{
	SendMessageToPC(GetFirstPC(FALSE), ". Run ( mr_mod_death )");

	object oDead = GetLastPlayerDied();

	SendMessageToPC(GetFirstPC(FALSE), ". . LastDied = " + GetName(oDead));

	if (!GetIsOwnedByPlayer(oDead)) // || !GetIsRosterMember(oSelf))
	{
		SendMessageToPC(GetFirstPC(FALSE), ". . . not Owned Character, EXIT");
		return;
	}

	// if anyone in the PC faction is still alive, EXIT
	object oFM = GetFirstFactionMember(oDead, FALSE);
	while (GetIsObjectValid(oFM))
	{
		SendMessageToPC(GetFirstPC(FALSE), ". . . checking Faction Members, LOOP");
		// nb. could/should use advanced functions from 'ginc_death' here
		if (!GetIsDead(oFM))
		{
			SendMessageToPC(GetFirstPC(FALSE), ". . . . found Living FM, EXIT");
			return;
		}
		oFM = GetNextFactionMember(oDead, FALSE);
	}
	SendMessageToPC(GetFirstPC(FALSE), ". . . . no Living FM");

	// global_int "mr_iGlobalInt" is set TRUE on entering area
	int iGlobalInt = GetGlobalInt("mr_iGlobalInt");
	SendMessageToPC(GetFirstPC(FALSE), ". . GlobalInt is " + IntToString(iGlobalInt));

	if (iGlobalInt)
	{
		SendMessageToPC(GetFirstPC(FALSE), ". . . we are in the Tournament, no death screen pls,"
				+ " Execute Special Script, EXIT");
		return;
	}
	else
	{
		SendMessageToPC(GetFirstPC(FALSE), ". . . we are *not* in the Tournament, show DeathScreen");
		DelayCommand(2.f, GUI(oDead));
	}
}


// Companion OnDeath
void main()
{
	SendMessageToPC(GetFirstPC(FALSE), ". Run ( mr_comp_death )");

	object oSelf = OBJECT_SELF;

	SendMessageToPC(GetFirstPC(FALSE), ". . ObjectSelf = " + GetName(oSelf));

	// if Companion is not in the Roster, EXIT
	if (!GetIsRosterMember(oSelf))
	{
		SendMessageToPC(GetFirstPC(FALSE), ". . . not on Roster, EXIT");
		return;
	}

	// if anyone in the Companion/PC faction is still alive, EXIT
	object oFM = GetFirstFactionMember(oSelf, FALSE);
	while (GetIsObjectValid(oFM))
	{
		SendMessageToPC(GetFirstPC(FALSE), ". . . checking Faction Members, LOOP");
		// nb. could/should use advanced functions from 'ginc_death' here
		if (!GetIsDead(oFM))
		{
			SendMessageToPC(GetFirstPC(FALSE), ". . . . found Living FM, EXIT");
			return;
		}
		oFM = GetNextFactionMember(oSelf, FALSE);
	}
	SendMessageToPC(GetFirstPC(FALSE), ". . . . no Living FM");

	// global_int "mr_iGlobalInt" is set TRUE on entering area
	int iGlobalInt = GetGlobalInt("mr_iGlobalInt");
	SendMessageToPC(GetFirstPC(FALSE), ". . GlobalInt is " + IntToString(iGlobalInt));

	if (iGlobalInt)
	{
		SendMessageToPC(GetFirstPC(FALSE), ". . . we are in the Tournament, no death screen pls,"
				+ " Execute Special Script, EXIT");
		return;
	}
	else
	{
		SendMessageToPC(GetFirstPC(FALSE), ". . . we are *not* in the Tournament, show DeathScreen");
		DelayCommand(2.f, GUI(oSelf));
	}
}


+ my rework of Matt's DeathGUI( )

void GUI(object oDeath)
{
	// the controlled character of the player whose faction includes the death
	object oPlayer = GetFactionLeader(oDeath);
	// the OwnedCharacter, the PC itself !
	object oPC = SetOwnersControlledCompanion(oPlayer);

	SendMessageToPC(GetFirstPC(FALSE), ". . . . GUI( ) Deceased = " + GetName(oDeath));
	SendMessageToPC(GetFirstPC(FALSE), ". . . . GUI( ) FactionLeader = " + GetName(oPlayer));
	SendMessageToPC(GetFirstPC(FALSE), ". . . . GUI( ) OwnedCharacter = " + GetName(oPC));

	// kL, give 'em the deathGUI, not modal, no respawn, no wait for help.
	DisplayGuiScreen(oPC, "SCREEN_PARTY_DEATH", FALSE);
	SetGUIObjectDisabled(oPC, "SCREEN_PARTY_DEATH", "BUTTON_RESPAWN", TRUE);
	SetGUIObjectHidden(oPC, "SCREEN_PARTY_DEATH", "BUTTON_RESPAWN", TRUE);
	SetGUIObjectDisabled(oPC, "SCREEN_PARTY_DEATH", "BUTTON_WAIT_FOR_HELP", TRUE);
	SetGUIObjectHidden(oPC, "SCREEN_PARTY_DEATH","BUTTON_WAIT_FOR_HELP", TRUE);
}


However, none of this overcomes the issue of *no death script* gets called on the death of a controlled companion. If someone can verify/dispute/workaround this that'd be welcome.

#34
kevL

kevL
  • Members
  • 4 052 messages
that's odd .. I just reloaded my old scripts and the deathscreen popped up okay, when controlling the RosterCompanion and PC was already gonzo ..... searching ....


Edit, control got popped from the companion back into the dead PC auto.

Modifié par kevL, 18 mars 2012 - 12:40 .


#35
kevL

kevL
  • Members
  • 4 052 messages
yet something other than the ModOnDying/Death or CompOnDeath scripts is doing the auto-pop back to PC. Because when the controlled Companion is killed outright, none of those scripts fire.

Say WHAT?! My log is telling me that 'gb_comp_death' fires when my PC dies (companion is controlled, but her deathscript is set to 'mr_comp_death', and it still doesn't fire when she is controlled onDeath), like so:

Tiera the wood Elf: [Talk] Hello.
[kevL's] Calen Wyle: [Talk] Can you join me?
Tiera the wood Elf: [Talk] Sure stuff, Sir !
[kevL's] Calen Wyle: [Talk] Ok, let's go then !!
...
RUNSCRIPT: [2531576] gb_comp_death [54] Tiera the wood Elf kg_ct_Tiera ( 03/17/2012 ) - [ 19:04:55 ]
gb_comp_death: Tiera the wood Elf executing OnDeath event
** ginc_death: Tiera the wood Elf's party wiped. displaying death screen
[Sat Mar 17 19:04:55] Tiera the wood Elf Died
RUNSCRIPT: [2531576] gb_comp_usrdef [54] Tiera the wood Elf kg_ct_Tiera ( 03/17/2012 ) - [ 19:04:55 ]
RUNSCRIPT: [2531576] gb_player_ud [2147483647] Calen Wyle ( 03/17/2012 ) - [ 19:04:55 ]

--
RUNSCRIPT: [7653417] gb_comp_death [2147483647] Calen Wyle ( 03/17/2012 ) - [ 19:31:26 ]
gb_comp_death: Calen Wyle executing OnDeath event
** gb_comp_death: Calen Wyle is owned by a player. ABORT!
[Sat Mar 17 19:31:26] Calen Wyle(PC) Died

RUNSCRIPT: [7653718] gb_comp_death [54] Tiera the wood Elf kg_ct_Tiera ( 03/17/2012 ) - [ 19:31:42 ]
gb_comp_death: Tiera the wood Elf executing OnDeath event
** ginc_death: Tiera the wood Elf's party wiped. displaying death screen
[Sat Mar 17 19:31:42] Tiera the wood Elf Died
RUNSCRIPT: [7653718] gb_comp_usrdef [54] Tiera the wood Elf kg_ct_Tiera ( 03/17/2012 ) - [ 19:31:42 ]
RUNSCRIPT: [7653718] gb_player_ud [2147483647] Calen Wyle ( 03/17/2012 ) - [ 19:31:42 ]


nb. Tiera's onDeath script is set as 'mr_comp_death', which does fire when she dies uncontrolled. ( Yet the engine is firing 'gb_comp_death' when she dies controlled )

- glancing at some of those scripts tells me this is getting into TonyK's territory ........

I *did* get a deathscreen when Tiera was the last faction member standing (& controlled), but it does not seem to be called from her OnDeath for sure, and i can't figure how control is getting popped back to the (dead) PC, just as that deathGUI appears; the tack indicates it involves 'gb_comp_usrdef' (Tiera/companion) -> 'gb_player_ud' (Calen/PC)

(it might also involve 'gb_comp_conv', & of course 'gb_comp_death')

get a load of this little note I came across:
// gb_player_heart
/*
Script that runs when a player controls a companion
*/

So, is there an extra-hidden set of scripts that come into play when 'a player controls a companion'? i could find only two gb_player_* scripts (heartbeat & userdefined) -- i needa packa smokes.

#36
kevL

kevL
  • Members
  • 4 052 messages
to summarize so far _~


script              fired by            not by
------              --------            ------
Module OnDying      cPC, uPC, cC, uC
Module OnDeath      cPC, uPC            cC, uC
Companion OnDeath   uC                  cC

where,
c = controlled, u = uncontrolled
PC = PlayerCharacter, C = Companion

There is, logically, some sort of onDeath event that fires when a controlled companion is slain. It bypasses custom conditions, however, that are set via the usual events; that's why checking for things like global_ints may fail, or you might get a different deathGUI than what was spec'd w/ Module Properties or Companion Properties.

Again, my tests are showing that when the last living faction member is a controlled companion, these deathscripts do not run when the party is finally wiped; there is another script(s) somewhere ... I'm getting a different popup Gui, the same deathGUI that appears after "wait for help" is pressed (which is neither the Gui in Companion OnDeath nor Module OnDeath).


yep, found it. 'gb_comp_death' gets called, probably through TonyK's AI but don't quote me. It ends up calling ShowProperDeathScreen( ) ( see 'ginc_death' ), which uses SetOwnersControlledCompanion( ) and specifies what buttons to display on the deathGUI. Under these circumstances whatever checks and niceties are in either module or companion events, get ignored


at least on my system,

#37
kevL

kevL
  • Members
  • 4 052 messages
ps. Gratz on the release, Matt. What I'm describing here pertains to all modules and is hardly a unique drawback :)

#38
M. Rieder

M. Rieder
  • Members
  • 2 530 messages
Wow! That was very thorough. You know, I tried an override of gb_comp_death, just in case, but couldn' get it to work. I'll keep that in mind when I get back into this stuff.

#39
kevL

kevL
  • Members
  • 4 052 messages
ok. I'm going to pin the 'gb_comp_death' script here for peeps/us to look at & refer to if wanted (this is from 'scripts_x2.zip' in \\Data).

// gb_comp_death
/*
  OnDeath handler to queue KnockOut script for companions
*/
// ChazM 8/17/05
// BMA-OEI 12/19/05 knock out death system
// BMA-OEI 1/26/06 exit if owned and controlled
// BMA-OEI 2/27/06 DeathScript support, exit if not in PC faction
// BMA-OEI 2/28/06
// NLC 7/14/08 - Increased NX2's hardcore quotient.

#include "ginc_companion"
#include "ginc_death"
#include "ginc_debug"
#include "x2_inc_switches"

const string VAR_GLOBAL_NX2_TRANSITIONS = "bNX2_TRANSITIONS";

void main()
{
  SendMessageToPC(GetFirstPC(FALSE), ". Run ( gb_comp_death )");    // kL add

  object oDead = OBJECT_SELF;
  PrintString( "gb_comp_death: " + GetName(oDead) + " executing OnDeath event" );

  // Abort if dying character is owned PC (owned PCs should fire module OnDeath)
  if ( GetIsOwnedByPlayer( oDead ) == TRUE )
  {
    PrintString( "** gb_comp_death: " + GetName(oDead) + " is owned by a player. ABORT!" );
    return;
  }

  // Check for additional death script
  string sDeathScript = GetLocalString( oDead, "DeathScript" );
  if ( sDeathScript != "" ) ExecuteScript( sDeathScript, oDead );

  // Abort if dying character is not in PC faction
  if ( GetIsObjectInParty( oDead ) == FALSE )
  {
    PrintString( "** gb_comp_death: " + GetName(oDead) + " not in " + GetName(GetFirstPC()) + "'s party. ABORT!" );
    return;
  }
  if( !GetGlobalInt( VAR_GLOBAL_NX2_TRANSITIONS ) )
  {
    //NX2 is HARDCORE! No auto-ressing!
    AssignCommand( oDead, KnockOutCreature( oDead ) );
  }
  else
  {
    if ( GetIsDeathPopUpDisplayed(oDead) == FALSE )
    {
      if ( GetIsPartyPossessible(oDead) == FALSE )
      {
        PrettyDebug( "** ginc_death: " + GetName(oDead) + "'s party wiped. displaying death screen", 30.0 );
        ShowProperDeathScreen( oDead );
      }
    }
  }
}

notice my add right after Main( ). By specifying the companion OnDeath event as some other script ( viz. your Comp_OnDeath ) with its own debug right after Main( ), i found this script still getting called when controlling a companion as it died and not the other script. The other script gets called as expected when not controlling a companion.

As further evidence, notice in the quotes from my .Log lines like

gb_comp_death: Tiera the wood Elf executing OnDeath event
** ginc_death: Tiera the wood Elf's party wiped. displaying death screen

these sure look like they come from 'gb_comp_death' above. Of further interest, 'gb_comp_death' also gets called on death of a PC:

gb_comp_death: Calen Wyle executing OnDeath event
** gb_comp_death: Calen Wyle is owned by a player. ABORT!


It looks like 'gb_comp_death' is being used by the engine as some sort of a safety onDeath script. But to make your Tournament area robust in the event of a party wipe ... my belief at this point is that it *does* need a custom 'gb_comp_death' in override or hak or just the module itself.


no worries, i bet you got a lot of stuff to deal with about now :)

#40
Lugaid of the Red Stripes

Lugaid of the Red Stripes
  • Members
  • 955 messages
I don't really know much about companions, but I did notice that calls to the companion AI scripts are scattered though-out the other event scripts and even some of the big include files. I'll keep an eye out as I mess around with things, but I have a WAG that the script call is buried in some combat-related script.

#41
kevL

kevL
  • Members
  • 4 052 messages
but doesn't that beg the question, What 'event' starts the call that ends up mysteriously at gb_comp_death ?

i just did a search for "gb_comp_death" throughout all game & official campaign scripts, to see what other script might be executing it, and all that turned up is 'gb_pcai_death' - but that's described as a placeholder script (from 2005), and also has ActionSpeakStrings that would appear, depending, if this method was getting used ....

- also did a search through my Override, which has TonyK's add-on, and nothing unusual turns up there : a couple of .Utc's and nwn2_scriptsets.2da.


btw, this is about more than companion scripts: 'gb_comp_death' fires on PC death also, something to keep in mind if it needs to be adulterated for special cases,

#42
kevL

kevL
  • Members
  • 4 052 messages
... What 'event' starts the call that ends up mysteriously at gb_comp_death ?

putting 2+2 together ...


while stumbling around in nwscript.nss, I came across the SCRIPTSET_* constants and Lo

// These are the default scripts that are loaded onto the player character
int SCRIPTSET_PLAYER_DEFAULT = 3;

That refers to nwn2_scriptsets.2da -- by default the PC apparently gets the companion scriptsets assigned, and row 4 seems to assign events to player-controlled objects, hence 'gb_comp_death' gets called onDeath of that last player-controlled companion ( even if the companion does not have 'gb_comp_death' slotted )

#43
Lugaid of the Red Stripes

Lugaid of the Red Stripes
  • Members
  • 955 messages
This should be in blinking lights somewhere.

#44
M. Rieder

M. Rieder
  • Members
  • 2 530 messages

kevL wrote...

by default the PC apparently gets the companion scriptsets assigned, and row 4 seems to assign events to player-controlled objects, hence 'gb_comp_death' gets called onDeath of that last player-controlled companion ( even if the companion does not have 'gb_comp_death' slotted )


Based on my testing with on death events, this seems right.  I have decided to throw out my custom on death scripts and just use the canned ones.  Safer that way.

#45
Lance Botelle

Lance Botelle
  • Members
  • 1 480 messages
Hi Matt,

Save me reading through everything, did you manage to sort your problem out?

I have done some very extensive work with OnDeath scripts to work with companions in both a SP and MP environment and so I believe I have them fully under control now, so I may be able to answer some questions of you still have them?

EDIT: From the bit I did read through, are you aware that the companions fire their own OnDeath scripts? These can be modified by editing the NWN2_ScriptSets.2da.  I had to edit that 2da to get the correct scripts in place. I added a line and used it for my own companions, but I have made a lot of AI changes for them.

Cheers!

Lance.

Modifié par Lance Botelle, 18 mai 2012 - 10:22 .