Note: LucasForums Archive Project
The content here was reconstructed by scraping the Wayback Machine in an effort to restore some of what was lost when LF went down. The LucasForums Archive Project claims no ownership over the content or assets that were archived on archive.org.

This project is meant for research purposes only.

Two NEW Const Functions..

Page: 1 of 1
 Dak Vesser
02-10-2006, 12:11 PM
#1
Original Thread (http://www.lucasforums.com/showthread.php?t=160261)
------------------

Just a small #include script, that I whipped up creating these two functions.

void FPM_FollowLeader();
void FPM_Debug();

Here’s a description.
FPM_FollowLeader: You can use this const function if you want the creature to follow the current party leader. Unlike “void ActionMoveToObject()”, This one will make a much smoother, less jittery movement. Using this new function, the creature can now walk, if close enough, run if too far, and back away if too close also will turn to follow whoever was switched to take lead.

FPM_Debug; When adding this function along with FPM_FollowLeader(), It’ll send messages to the pc, reporting the current movement changes, plus the distances, and time. It’ll also send a barkString, showing the reports right in the game. However, you’ll need to type <CUSTOM210> in four StrRef slots in your dialog.tlk: 10865, 10866, 10867, and 10868. Otherwise you’ll see a blank barkstring repeating over again. I used this function for adjusting distances and changes.

Updated Feb 11, 2006
Added:

void FollowAccurate(); This function will force FPM_FollowLeader to fire 36 times in one heartbeat, making the creature respond to the pc's movements much faster.

void FPM_DebugFastRF() This function will force a refresh rate increase in FPM_Debug.


// k_inc_fpm Udated Feb 11, 2006
//
// Fake Party Member
// Created by Dak Vesser
// Note:
// This is a preprocessor/Include file which was created to co-function with a creature's
// main AI HeartBeat script for SWKotOR/SWKotOR2 TSL..
// This file does NOT go to your Override folder
// Place it in the folder where your nwnnsscomp.exe is located.
// So you can use these fuctions in your main script files
///////////////////////////////////////////////////////////////////////////////////////////////////
#include "k_inc_generic"
#include "k_inc_utility"

//Sets a creature to follow
//the current party leader.
void FPM_FollowLeader();

//displays a barkstring with reports of
//the creature's current movement changes.
void FPM_Debug();

//Forces FPM_Debug to refresh the
//BarStrings faster.
void FPM_DebugFastRF();

//This Function increases the creature's response
//timing in following the PC's movement
void FollowAccurate();


//Edited
//If FPM_Debug has been added
//to your main script along with FPM_FollowLeader,
//then this integer will allow the FPM_Debug
//function to automatically detect your changes
//in distance settings from the FPM_FollowLeader
//function & trigger the debug messages to
//fire based on your new changes. This
//will save us allot of time in debugging our mods, for sure!!!
int nDebugMark = 0;


///////////////////////////////////////////////////////////////////////////////////////////////////
//Function 1..
//FPM_FollowLeader() will allow a creature to follow the partyleader without being
//added to the table. Unlike "ActionMoveToObject()", this will be a more smoother,
//less shaky durring movement. Plus the creature using this function, will be able to
//walk if close enough, run if too far, or back away if too close to the PC.
///////////////////////////////////////////////////////////////////////////////////////////////////

void FPM_FollowLeader(){
//object oLdr = GetFirstPC(); // follows only the pc.
object oLdr = GetPartyMemberByIndex(0);// follows whoever takes lead.
object oEnemy = GetNearestCreature(CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN,
OBJECT_SELF, 1, CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY);

vector vLdr = GetPosition(oLdr);
float fLength = (GetDistanceBetween(OBJECT_SELF, oLdr));
int nRun = IsRunning(oLdr);// Returns 0= walking, 1= running.

if(nRun == 0 && fLength >= 2.4 && fLength <= 8.8){
nDebugMark = 1;
ActionForceMoveToObject(oLdr, FALSE, 1.7, 9.0);
}
if(nRun == 1){
nDebugMark = 2;
ActionForceMoveToObject(oLdr, TRUE, 1.5);
}
if(fLength >= 1.2 && fLength <= 2.3 &&
!GN_GetIsFighting(OBJECT_SELF) && !GetIsObjectValid(oEnemy)){
ClearAllActions();
nDebugMark = 3;
SetFacingPoint(vLdr);
}
if(fLength <= 1.1){
nDebugMark = 4;
ActionMoveAwayFromObject(oLdr, TRUE, 1.4);
}
if(fLength >= 8.9){
nDebugMark = 2;
ActionDoCommand(ActionForceMoveToObject(oLdr, TRUE, 3.5, 5.0));
}
}


///////////////////////////////////////////////////////////////////////////////////////////////////
//If you decide to use this funtion, then you'll need to add "<CUSTOM210>" into your dialog.tlk
//slots: 10867, 10868, 10866, and 10865. Otherwise you'll end up seeing an empty BarkString
//continuously popping up.
//This Function is for the purpose of adjusting distances, timing, and movement changing
//over to the void FPM_FollowLeader const. Tweak it to your own liking.
///////////////////////////////////////////////////////////////////////////////////////////////////

void FPM_Debug()
{
string sMinute;
string sTime;

//The clock
int nMinByHour = FloatToInt(HoursToSeconds(1)) / 60;
int nHour = GetTimeHour();
int nMinute = (60 / nMinByHour) * GetTimeMinute();
int nSecond = GetTimeSecond();

nMinute = nMinute + nSecond / nMinByHour;

if (nMinute <= 9)
sMinute = "0" + IntToString(nMinute);
if (nMinute >= 10)
sMinute = IntToString(nMinute);

sTime = "SWTime: " + IntToString(nHour) + "h:" + sMinute + "m ";

//object oLdr = GetFirstPC();
object oLdr = GetPartyMemberByIndex(0);
float fLength = (GetDistanceBetween(OBJECT_SELF, oLdr));

int CUSTOM210 = 210;
string sDebug;


if(nDebugMark == 1)
{
SendMessageToPC(oLdr, sTime + GetName(OBJECT_SELF)+
" is now in Walk Mode, following " +GetName(oLdr) +"."
+" Distance: "+ FloatToString(fLength,0,2));

sDebug = sTime + GetName(OBJECT_SELF)+
" is now in WALK Mode. Following " +GetName(oLdr)
+"."+" Distance: "+FloatToString(fLength,0,2);

SetCustomToken(CUSTOM210, sDebug);
BarkString(oLdr,10867);// Add <CUSTOM210> to slot 10867 in your k2's dialog.tlk
}
if(nDebugMark == 2)
{
SendMessageToPC(oLdr, sTime + GetName(OBJECT_SELF)+
" is now in Run Mode, following " +GetName(oLdr)+ "."
+" Distance: "+ FloatToString(fLength,0,2));

sDebug = sTime + GetName(OBJECT_SELF)+
" is now in RUN Mode. Following " +GetName(oLdr)
+"."+" Distance: "+ FloatToString(fLength,0,2);

SetCustomToken(CUSTOM210, sDebug);
BarkString(oLdr,10868);// Add <CUSTOM210> to slot 10868 in your k2's dialog.tlk
}
if(nDebugMark == 3)
{
SendMessageToPC(oLdr,sTime + GetName(OBJECT_SELF)+
" is now in STOP Mode, pending " +GetName(oLdr)+
"'s next movement."
+" Distance: "+ FloatToString(fLength,0,2));

sDebug = sTime + GetName(OBJECT_SELF)+
" is now in STOP Mode. Following " +GetName(oLdr)
+"."+" Distance: "+ FloatToString(fLength,0,2);

SetCustomToken(CUSTOM210,sDebug);
BarkString(oLdr, 10866);// Add <CUSTOM210> to slot 10866 in your k2's dialog.tlk
}
if(nDebugMark == 4)
{
SendMessageToPC(oLdr,sTime + GetName(OBJECT_SELF)+
" is now in Reverse Mode, getting out of "
+GetName(oLdr)+"'s way."
+" Distance: "+ FloatToString(fLength,0,2));

sDebug = sTime + GetName(OBJECT_SELF)+
" is now in BACK Mode. Following " +GetName(oLdr)
+"."+" Distance: "+ FloatToString(fLength,0,2);

SetCustomToken(CUSTOM210,sDebug);
BarkString(oLdr, 10865);// Add <CUSTOM210> to slot 10865 in your k2's dialog.tlk
}
}

///////////////////////////////////////////////////////////////////////////////////////////////////
// Use this function if you wish to see a faster refresh
// rate in the range numbers. Speed x60(2 millisec interval)
// per heart beat click.
///////////////////////////////////////////////////////////////////////////////////////////////////
void FPM_DebugFastRF()
{
FPM_Debug(); // Starts on heart beat.
DelayCommand(0.2,FPM_Debug());
DelayCommand(0.4,FPM_Debug());
DelayCommand(0.6,FPM_Debug());
DelayCommand(0.8,FPM_Debug());
DelayCommand(1.0,FPM_Debug());
DelayCommand(1.2,FPM_Debug());
DelayCommand(1.4,FPM_Debug());
DelayCommand(1.6,FPM_Debug());
DelayCommand(1.8,FPM_Debug());
DelayCommand(2.0,FPM_Debug());
DelayCommand(2.2,FPM_Debug());
DelayCommand(2.4,FPM_Debug());
DelayCommand(2.6,FPM_Debug());
DelayCommand(2.8,FPM_Debug());
DelayCommand(3.0,FPM_Debug());
DelayCommand(3.2,FPM_Debug());
DelayCommand(3.4,FPM_Debug());// Next Heart Beat
DelayCommand(3.6,FPM_Debug());// starts around here.
DelayCommand(3.8,FPM_Debug());// Give or take a few MilliSeconds
DelayCommand(4.0,FPM_Debug());// Overlaps around here.
DelayCommand(4.2,FPM_Debug());
DelayCommand(4.4,FPM_Debug());
DelayCommand(4.6,FPM_Debug());
DelayCommand(4.8,FPM_Debug());
DelayCommand(5.0,FPM_Debug());
DelayCommand(5.2,FPM_Debug());
DelayCommand(5.4,FPM_Debug());
DelayCommand(5.6,FPM_Debug());
DelayCommand(5.8,FPM_Debug());
DelayCommand(6.0,FPM_Debug());
}

///////////////////////////////////////////////////////////////////////////////////////////////////
//Use this function if you want the creature to respond faster
//in it's movement changes. This funtion fires FPM_FolowLeader
//Speed = x36(1 millisec interval) per heart beat click
///////////////////////////////////////////////////////////////////////////////////////////////////
void FollowAccurate()
{
//Speed = x36(1 millisec interval) per heart beat
FPM_FollowLeader();
DelayCommand(0.1,FPM_FollowLeader());
DelayCommand(0.2,FPM_FollowLeader());
DelayCommand(0.3,FPM_FollowLeader());
DelayCommand(0.4,FPM_FollowLeader());
DelayCommand(0.5,FPM_FollowLeader());
DelayCommand(0.6,FPM_FollowLeader());
DelayCommand(0.7,FPM_FollowLeader());
DelayCommand(0.8,FPM_FollowLeader());
DelayCommand(0.9,FPM_FollowLeader());
DelayCommand(1.0,FPM_FollowLeader());
DelayCommand(1.1,FPM_FollowLeader());
DelayCommand(1.2,FPM_FollowLeader());
DelayCommand(1.3,FPM_FollowLeader());
DelayCommand(1.4,FPM_FollowLeader());
DelayCommand(1.5,FPM_FollowLeader());
DelayCommand(1.6,FPM_FollowLeader());
DelayCommand(1.7,FPM_FollowLeader());
DelayCommand(1.8,FPM_FollowLeader());
DelayCommand(1.9,FPM_FollowLeader());
DelayCommand(2.0,FPM_FollowLeader());
DelayCommand(2.1,FPM_FollowLeader());
DelayCommand(2.2,FPM_FollowLeader());
DelayCommand(2.3,FPM_FollowLeader());
DelayCommand(2.4,FPM_FollowLeader());
DelayCommand(2.5,FPM_FollowLeader());
DelayCommand(2.6,FPM_FollowLeader());
DelayCommand(2.7,FPM_FollowLeader());
DelayCommand(2.8,FPM_FollowLeader());
DelayCommand(2.9,FPM_FollowLeader());
DelayCommand(3.0,FPM_FollowLeader());
DelayCommand(3.1,FPM_FollowLeader());
DelayCommand(3.2,FPM_FollowLeader());
DelayCommand(3.3,FPM_FollowLeader());
DelayCommand(3.4,FPM_FollowLeader());
DelayCommand(3.5,FPM_FollowLeader());
DelayCommand(3.6,FPM_FollowLeader());
}

Use these functions in your creature's main HeartBeat script. Make sure to add #include "k_inc_fpm" in it so your compiler won't error....

Do not use these functions on a party member, or a creature that you're going to add to the party table.

It's better to add these functions to a modified "k_hen_heartbt", not a "k_def_heartbt" script, since the intention is to make a creature "act" like a party member, or somewhat...

hope you guys enjoy this...

===============================

Here's an example of how these new const functions would be applied to a modified henchmen heart beat script:

#include "k_inc_generic"
#include "k_inc_switch"
#include "k_inc_utility"
#include "k_inc_fpm"

void main()
{
object oEnemy = GetNearestCreature(CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN,
OBJECT_SELF, 1, CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY);

if(!GN_GetSpawnInCondition(SW_FLAG_AI_OFF) && !GetSoloMode())
{
if(GetPartyMemberByIndex(0) != OBJECT_SELF)
{
if(GetCurrentAction(OBJECT_SELF) != ACTION_WAIT &&
!GetIsConversationActive() &&
!GN_GetSpawnInCondition(SW_FLAG_SPECTATOR_STATE) &&
GetCommandable())
{
if(!GN_GetIsFighting(OBJECT_SELF) && !GetIsObjectValid(oEnemy))

ClearAllActions();
FollowAccurate();
FPM_DebugFastRF();
}
}
}
else if(GetSoloMode() && GetCurrentAction(OBJECT_SELF) == ACTION_FOLLOWLEADER)
{
ClearAllActions();
}
if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_HEARTBE AT))
{
SignalEvent(OBJECT_SELF, EventUserDefined(1001));
}


}

Very simple as we can see.. :)
Page: 1 of 1