I have never had to destroy an ipoint speaker when using CreateIPSpeaker. I always, maybe wrongly but it has always worked, given the ipoint speaker the same tag as someone I want to own the conversation, like the boss in this case or a companion or an NPC that’s in the area near the PC.
ActionStartConversation is a lot better to use in most cases, BUT when it comes to firing a conversation where a lot could go wrong, like in this case when all the characters are to stop fighting and whatnot, it isn’t reliable, I’m sad to say. I’ve often wanted to use that function instead but have had to use CreateIPSpeaker to make sure the conversation fires everytime. The big problem is that that like 50 % of the time CreateIPSpeaker fires right away, but if you’re unlucky it can take up to 5 min for it to fire. The good thing is that it ALWAYS fires (ok, I think kevL_s pointed that there are som REALLY rare instances where it can fail, but anyway). That’s why I always go into SetCutsceneMode to make sure the player doesn’t run away and do other stuff, but that makes the player sometimes wondering if the game is buggy and has gotten stuck for some reason.
I bet someone like @Lance_Botelle has some ideas about this, and I would guess has some really complex scripts to make sure that the ActionStartConversation really fires, but this is the way I’ve always done it.
When I can though, I always try to use ActionStartConversation. I have a script that always works for me when the party is running around, enters a trigger and I need a conversation to start between a PC and a companion. That script that I use for that occation never fails (but this is in peaceful situations where the party is just running around in an area and there are no hostiles), but now we’re in the middle of a battle where the game needs to stop everyone from fighting, and then all sorts of stuff can go wrong because (if I may be so bold) how badly programmed this whole game is.
I think I can do that. A moment…
//::///////////////////////////////////////////////
//:: Default On Damaged
//:: NW_C2_DEFAULT6
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
If already fighting then ignore, else determine
combat round
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Oct 16, 2001
//:://////////////////////////////////////////////
#include "hench_i0_ai"
#include "ginc_behavior"
#include "ginc_group"
#include "ginc_ipspeaker"
#include "x0_i0_assoc" // SetAssociateState()
/*
OnDamaged script for the boss.
Stops combat when the boss drops below 10 hitpoints. Starts a dialog.
*/
void main()
{
object oDamager = GetLastDamager();
object oWeaponUsed = GetLastWeaponUsed(oDamager);
object oWeapon = GetObjectByTag("tagofweapon");
int iHp = GetCurrentHitPoints(OBJECT_SELF);
if (iHp < 10 && !GetLocalInt(OBJECT_SELF,"healedonetime"))
{
AssignCommand(OBJECT_SELF, ClearAllActions(TRUE));
int nCurrentHP;
int nHP;
int nHealPercent = 100;
effect eFX;
effect eVisual = EffectNWN2SpecialEffectFile("sp_cure_critical");
SetLocalInt(OBJECT_SELF,"healedonetime",TRUE);
object oPC = GetFirstPC();
FloatingTextStringOnCreature("The boss has healed up.", oPC, FALSE);
nCurrentHP = GetCurrentHitPoints( OBJECT_SELF );
nHP = FloatToInt( IntToFloat(GetMaxHitPoints(OBJECT_SELF)) * IntToFloat(nHealPercent) / 100 ) - nCurrentHP;
eFX = EffectHeal( nHP );
ApplyEffectToObject( DURATION_TYPE_PERMANENT,eFX,OBJECT_SELF );
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVisual, OBJECT_SELF);
return;
}
else if (iHp < 10 && GetLocalInt(OBJECT_SELF,"insidetrigger") && oWeaponUsed == oWeapon)
{
GroupChangeToStandardFaction("group_badguys", STANDARD_FACTION_COMMONER);
ChangeToStandardFaction(OBJECT_SELF, STANDARD_FACTION_COMMONER);
AssignCommand(OBJECT_SELF, ClearAllActions(TRUE));
GroupClearAllActions("group_badguys", TRUE);
object oPC = GetFirstPC(FALSE);
ClearPartyActions(oPC, TRUE);
SetAssociateState(NW_ASC_MODE_STAND_GROUND,TRUE,GetObjectByTag("tagofcompanion"));
SetAssociateState(NW_ASC_MODE_STAND_GROUND,TRUE,GetObjectByTag("tagofcompanion2"));
SetAssociateState(NW_ASC_MODE_STAND_GROUND,TRUE,GetObjectByTag("tagofcompanion3"));
SetAssociateState(NW_ASC_MODE_STAND_GROUND,TRUE,GetObjectByTag("tagofcompanion4"));
CreateIPSpeaker("tagofthisboss", "bossconversation", GetLocation(oPC), 1.f);
return;
}
int iFocused = GetIsFocused();
// I've been damaged so no longer partially focused
if (iFocused == FOCUSED_PARTIAL)
{
SetLocalInt(OBJECT_SELF, VAR_FOCUSED, FOCUSED_STANDARD); // no longer focused
}
if (iFocused == FOCUSED_FULL)
{
// remain focused
}
else if(GetFleeToExit())
{
// We're supposed to run away, do nothing
}
else if (GetSpawnInCondition(NW_FLAG_SET_WARNINGS))
{
// don't do anything?
}
else
{
object oDamager = GetLastDamager();
if (!GetIsObjectValid(oDamager))
{
// don't do anything, we don't have a valid damager
}
else if (!GetIsFighting(OBJECT_SELF))
{
if ((GetLocalInt(OBJECT_SELF, HENCH_HEAL_SELF_STATE) == HENCH_HEAL_SELF_WAIT) &&
(GetPercentageHPLoss(OBJECT_SELF) < 30))
{
// force heal
HenchDetermineCombatRound(OBJECT_INVALID, TRUE);
}
else if (!GetIsObjectValid(GetAttemptedAttackTarget()) && !GetIsObjectValid(GetAttemptedSpellTarget()))
{
// Jug_Debug(GetName(OBJECT_SELF) + " responding to damage");
if (GetBehaviorState(NW_FLAG_BEHAVIOR_SPECIAL))
{
HenchDetermineSpecialBehavior(oDamager);
}
else
{
HenchDetermineCombatRound(oDamager);
}
}
}
}
if(GetSpawnInCondition(NW_FLAG_DAMAGED_EVENT))
{
SignalEvent(OBJECT_SELF, EventUserDefined(EVENT_DAMAGED));
}
}