So…I did my own clunky script based on some old script I got from Lance Botelle. It seems to kind of work, but…well, not entirely. When testing I saw some companion ingame getting bumped clearly by the running NPC, but it wasn’t that companion the script thought were the closest to the NPC. I guess it depends on if the NPC happens to bump the companion that millisecond when the script is running for it to be correct. Anyway, please be kind, here’s my very clunky script:
const string sROSTER_KELLIE = "kellie"; // note: this needs to be the *roster* string-id
const string sROSTER_ASTRID = "astrid"; // note: this needs to be the *roster* string-id
const string sROSTER_BACHAR = "bachar"; // note: this needs to be the *roster* string-id
const string sROSTER_GENEVIEVE = "genevieve"; // note: this needs to be the *roster* string-id
const string sROSTER_NAERTITA = "naertita"; // note: this needs to be the *roster* string-id
const string sROSTER_UWIZHE = "uwizhe"; // note: this needs to be the *roster* string-id
const string sROSTER_GYMETHON = "gymethon"; // note: this needs to be the *roster* string-id
// Pseudo heartbeat check (based on proximity)
void CheckProximity(object oNPC, object oPC, float fCheckDistance)
{
object oKellie = GetObjectFromRosterName(sROSTER_KELLIE);
object oAstrid = GetObjectFromRosterName(sROSTER_ASTRID);
object oBachar = GetObjectFromRosterName(sROSTER_BACHAR);
object oGenevieve = GetObjectFromRosterName(sROSTER_GENEVIEVE);
object oNaertita = GetObjectFromRosterName(sROSTER_NAERTITA);
object oUwizhe = GetObjectFromRosterName(sROSTER_UWIZHE);
object oGymethon = GetObjectFromRosterName(sROSTER_GYMETHON);
object oFM = GetFirstFactionMember(oPC, FALSE);
while (oFM != OBJECT_INVALID)
{
float fDisA = GetDistanceBetween(oNPC, oFM);
if(fDisA < fCheckDistance)
{
//DeleteLocalInt(oMod, "Proximitycheck");
fCheckDistance = fDisA;
if (oFM == oKellie)
{
SetLocalInt(oKellie,"noterunner",TRUE);
DeleteLocalInt(oAstrid,"noterunner");
DeleteLocalInt(oBachar,"noterunner");
DeleteLocalInt(oGenevieve,"noterunner");
DeleteLocalInt(oNaertita,"noterunner");
DeleteLocalInt(oUwizhe,"noterunner");
DeleteLocalInt(oGymethon,"noterunner");
}
else if (oFM == oAstrid)
{
SetLocalInt(oAstrid,"noterunner",TRUE);
DeleteLocalInt(oKellie,"noterunner");
DeleteLocalInt(oBachar,"noterunner");
DeleteLocalInt(oGenevieve,"noterunner");
DeleteLocalInt(oNaertita,"noterunner");
DeleteLocalInt(oUwizhe,"noterunner");
DeleteLocalInt(oGymethon,"noterunner");
}
else if (oFM == oBachar)
{
SetLocalInt(oBachar,"noterunner",TRUE);
DeleteLocalInt(oKellie,"noterunner");
DeleteLocalInt(oAstrid,"noterunner");
DeleteLocalInt(oGenevieve,"noterunner");
DeleteLocalInt(oNaertita,"noterunner");
DeleteLocalInt(oUwizhe,"noterunner");
DeleteLocalInt(oGymethon,"noterunner");
}
else if (oFM == oGenevieve)
{
SetLocalInt(oGenevieve,"noterunner",TRUE);
DeleteLocalInt(oKellie,"noterunner");
DeleteLocalInt(oAstrid,"noterunner");
DeleteLocalInt(oBachar,"noterunner");
DeleteLocalInt(oNaertita,"noterunner");
DeleteLocalInt(oUwizhe,"noterunner");
DeleteLocalInt(oGymethon,"noterunner");
}
else if (oFM == oNaertita)
{
SetLocalInt(oNaertita,"noterunner",TRUE);
DeleteLocalInt(oKellie,"noterunner");
DeleteLocalInt(oAstrid,"noterunner");
DeleteLocalInt(oBachar,"noterunner");
DeleteLocalInt(oGenevieve,"noterunner");
DeleteLocalInt(oUwizhe,"noterunner");
DeleteLocalInt(oGymethon,"noterunner");
}
else if (oFM == oUwizhe)
{
SetLocalInt(oUwizhe,"noterunner",TRUE);
DeleteLocalInt(oKellie,"noterunner");
DeleteLocalInt(oAstrid,"noterunner");
DeleteLocalInt(oBachar,"noterunner");
DeleteLocalInt(oGenevieve,"noterunner");
DeleteLocalInt(oNaertita,"noterunner");
DeleteLocalInt(oGymethon,"noterunner");
}
else if (oFM == oGymethon)
{
SetLocalInt(oGymethon,"noterunner",TRUE);
DeleteLocalInt(oKellie,"noterunner");
DeleteLocalInt(oAstrid,"noterunner");
DeleteLocalInt(oBachar,"noterunner");
DeleteLocalInt(oGenevieve,"noterunner");
DeleteLocalInt(oNaertita,"noterunner");
DeleteLocalInt(oUwizhe,"noterunner");
}
}
oFM = GetNextFactionMember(oPC, FALSE);
}
if(GetIsDead(oPC) || GetArea(oNPC) != GetArea(oPC))
{
DeleteLocalInt(oPC, "Proximitycheck"); return;
}
else
{
// Check proximity every 0.2 seconds once detected (adjust according to performance & need)
DelayCommand(0.1, CheckProximity(oNPC,oPC, fCheckDistance));
}
}
#include "ginc_ipspeaker"
void main()
{
// Assumes single player game only (no dm)
// Change according to hook type. eg: object oPC = GetFirstEnteringPC(); for on client area enter
object oPC = GetFirstPC();
// Track on module
//object oMod = GetModule();
//int iCheck = GetLocalInt(oMod, "Proximitycheck");
int iCheck = GetLocalInt(oPC, "Proximitycheck");
// These objects cannot die or it will break the code
object oNPC = GetObjectByTag("runner");
if((GetArea(oNPC) == GetArea(oPC)) && iCheck == 0)
{
// Track pseudo started
SetLocalInt(oPC, "Proximitycheck", 1);
// USing 2.0, but you could provide any value here by a local float
// Experiment with this value to get the "bump" distance you require
float fCheckDistance = 100000.0f;
//CheckProximity(oNPC, oPC, fCheckDistance, oMod);
CheckProximity(oNPC, oPC, fCheckDistance);
}
}