Zitat von
Tentarr
This Feature sounds amazing. Will there be many Dialog possibilities?
I am not sure if I understand your question
Are you asking if there will be multiple dialog options in my mod? Well .. so far I have only 2 cases - Lares & Roscoe and then Baal Cadar & his students, in the future I would like to add more.
If you would be interested in how this works - here is code with some notes - it should not be too difficult to follow what is happening there. Writing this kind of dialogues is more complicated in comparison with standard dialog.
Code:
//--- Global variable
var int SpellControlDialog;
//--- HOOK
//00699F70 .text Debug data ?IsSpellActive@oCNpc@@QAEPAVoCSpell@@H@Z
const int oCNpc__IsSpellActive_G1 = 6922096;
//0x0073D340 public: class oCSpell * __thiscall oCNpc::IsSpellActive(int)
const int oCNpc__IsSpellActive_G2 = 7590720;
FUNC VOID _HOOK_NPC_ISSPELLACTIVE ()
{
var oCNPC slf;
slf = _^ (ECX);
var int SpellID;
SpellID = MEM_ReadInt (ESP + 4);
if (NPC_IsPlayer (slf))
{
if (SpellID == SPL_CONTROL)
{
//If SpellControlDialog == TRUE - prevent player from 'Control' spell releasing
if (SpellControlDialog == TRUE)
{
MEM_WriteInt (ESP + 4, -1);
};
};
};
};
HookEngine (MEMINT_SwitchG1G2 (oCNpc__IsSpellActive_G1, oCNpc__IsSpellActive_G2), 8, "_HOOK_NPC_ISSPELLACTIVE");
Other required functions:
Code:
/***
Call this function in a condition function of dialog
***/
FUNC VOID PC_Prevent_SpellControl_Release ()
{
SpellControlDialog = TRUE;
};
/***
Call this function in a 'exit' dialog
***/
FUNC VOID PC_Allow_SpellControl_Release ()
{
SpellControlDialog = FALSE;
};
FUNC INT NPC_HasBodyStateModifier (var int slfInstance, var int BS_Modifier)
{
//006B8250 .text Debug data ?HasBodyStateModifier@oCNpc@@QAEHH@Z
const int oCNPC__HasBodyStateModifier_G1 = 7045712;
//0x0075EBF0 public: int __thiscall oCNpc::HasBodyStateModifier(int)
const int oCNPC__HasBodyStateModifier_G2 = 7728112;
var C_NPC slf;
slf = Hlp_GetNPC (slfInstance);
CALL_IntParam (BS_Modifier);
CALL__thiscall (MEM_InstToPtr (slf), MEMINT_SwitchG1G2 (oCNPC__HasBodyStateModifier_G1, oCNPC__HasBodyStateModifier_G2));
return CALL_RetValAsInt ();
};
FUNC INT NPC_IsControlled (var int slfInstance)
{
return NPC_HasBodyStateModifier (slfInstance, BS_MOD_CONTROLLED);
};
B_AssessTalk.d has to be adjusted:
Code:
/***
You have to specify which NPCs can talk to each other here
***/
FUNC INT PC_Controlled_Can_Talk (var C_NPC slf, var C_NPC oth)
{
if (NPC_IsControlled (oth))
{
//Lares & Roscoe
if (oth.ID == 840) //Roscoe
&& (slf.ID == 801) //Lares
{
return TRUE;
};
};
...
return FALSE;
};
FUNC VOID B_AssessTalk ()
{
...
//Allow ZS_Talk for player
if ((Hlp_GetInstanceID (her) == Hlp_GetInstanceID (other)) || (Hlp_GetInstanceID (rock) == Hlp_GetInstanceID (other)))
//Allow ZS_Talk for NPC's that can talk if controlled
|| (PC_Controlled_Can_Talk (self, other))
...
};
Example of dialogue between Lares & Roscoe:
Code:
INSTANCE DIA_Lares_Controlled (C_Info)
{
nr = 1;
npc = Org_801_Lares;
condition = DIA_Lares_Controlled_Condition;
information = DIA_Lares_Controlled_Info;
permanent = TRUE; //Dialog has to be permanent
important = TRUE; //Dialog has to be important - to override all other dialogs, which NPC has with 'hero'
};
FUNC INT DIA_Lares_Controlled_Condition ()
{
//Are we talking ?
if (NPC_IsInState (self, ZS_Talk))
{
//Is other Roscoe ?
if (other.ID == 840)
{
//Don't allow player to release 'control' spell
PC_Prevent_SpellControl_Release ();
return TRUE;
};
};
return FALSE;
};
FUNC VOID DIA_Lares_Controlled_Exit_Dialog ()
{
//Allow player to release 'control' spell
PC_Allow_SpellControl_Release ();
//Clear all choices
Info_ClearChoices (DIA_Lares_Controlled);
//Exit Dialog
AI_StopProcessInfos (self);
};
//Since further dialogs are only dialog choices we have to use variables to identify dialogs, which were already finished
var int DIA_Lares_Controlled_Weed_KnowsInfo;
var int DIA_Lares_Controlled_Ore_KnowsInfo;
FUNC VOID DIA_Lares_Controlled_Info ()
{
//Add dialog choices for Roscoe
Info_ClearChoices (DIA_Lares_Controlled);
//Exit dialog (permanent option)
Info_AddChoice (DIA_Lares_Controlled, DIALOG_ENDE, DIA_Lares_Controlled_Exit_Dialog);
//Onetime dialog
if (DIA_Lares_Controlled_Weed_KnowsInfo == FALSE) {
Info_AddChoice (DIA_Lares_Controlled, "Can you remind me - where do we have all the weed?", DIA_Lares_Controlled_Weed);
};
//Onetime dialog
if (DIA_Lares_Controlled_Ore_KnowsInfo == FALSE) {
Info_AddChoice (DIA_Lares_Controlled, "I would like to borrow some ore from you.", DIA_Lares_Controlled_Ore);
};
};
FUNC VOID DIA_Lares_Controlled_Weed ()
{
AI_Output (other, self, "DIA_Lares_Controlled_Weed_10_00"); //Can you remind me - where do we have all the weed?
AI_Output (self, other, "DIA_Lares_Controlled_Weed_11_01"); //bla bla bla ...
DIA_Lares_Controlled_Weed_KnowsInfo = TRUE;
DIA_Lares_Controlled_Info ()
};
FUNC VOID DIA_Lares_Controlled_Ore ()
{
AI_Output (other, self, "DIA_Lares_Controlled_Ore_10_00"); //I would like to borrow some ore from you.
AI_Output (self, other, "DIA_Lares_Controlled_Ore_11_01"); //bla bla bla ...
/***
Just a note:
In my mod - player is able to access inventory of controlled NPC ;) So this kind of interaction, where Roscoe would borrow some ore from Lares makes sense.
As player can drop that ore from inventory and then let 'hero' to pick it up.
There are also other limitations - as this kind of skill is a little bit OP.
***/
DIA_Lares_Controlled_Ore_KnowsInfo = TRUE;
DIA_Lares_Controlled_Info ()
};