ActionMoveAwayFromObject not giving me consistent results [EE]

What I’m trying to do is have my PC tell an associate to move 5 feet away and then tell me how far away he is from my PC. Once I get this working, I will create 10’, 15’, 20’, 10 yard, 15 yard, and 20 yard versions. This is part of my forthcoming update to my True Vision and Light EE project. The following script appears on the action tab of the PC.

void main()
{
    object oPC = GetPCSpeaker();
    float fDist  = GetDistanceToObject(oPC);
    string sDist = FloatToString(fDist);

    ClearAllActions();
    ActionMoveAwayFromObject(oPC, TRUE, 1.524f);
    ActionSpeakString("I am " + sDist + " away.");
    ActionSpeakString("Am I 1.524 metres away?");
}

What happens is that the creature moves but then reports a different distance from the PC. The creature has the default “monster” X2_* scripts rather than the henchman scripts because I don’t want the creature running back to the PC. I do however, have the PC hire the creature so that I can use the Nu Minion tool to bring him back within convo distance.

Any suggestions?

I guess I’m confused. You’re getting the distance from the creature to the PC before any movement so it will report whatever distance they had when the script was run. So I’d expect it to be some other value than 1.524. You’d need to run the GetDistanceToObject() call from a script after the move. Maybe make a routine and put an ActionDoCommand() in the queue after the ActionMoveAway,

2 Likes

You’re reporting the distance you saved in fDist before you started moving.

You probably want something like this:

void ReportDistanceToPC(object oNPC, object oPC)
{
	SendMessageToPC(oPC, GetName(oNPC) + " is now " +
		FloatToString(GetDistanceBetween(oPC, oNPC), 0, 2) +
		" m away from you");
}

void MoveAwayFromPC(object oNPC, object oPC, float fDistance)
{
	AssignCommand(oNPC, ClearAllActions());
	AssignCommand(oNPC, ActionMoveAwayFromObject(oPC, TRUE, fDistance));
	AssignCommand(oNPC, ActionDoCommand(ReportDistanceToPC(oNPC, oPC)));
}

Note however that ActionMoveAwayFromObject is wonky. If you make X move D meters away from Y, nothing will happen if dist(X,Y)>=D, but X will move by D meters from Y if dist(X,Y)<D. In other words you cannot use this function to make X stop at exactly distance D from Y.

1 Like

Thanks @meaglyn and @NWShacker. I wasn’t thinking clearly to grab the distance first (facepalm).

I now call the second script as an ActionDoCommand and it “works” . . . but it is indeed inconsistent. For example:

Expected distance is 1.524 meters (5’)
Trial 1 Reported: 2.924880743
Trial 2 Reported: 2.768646479
Trial 3 Reported: 2.616382599

Any other suggestions on how in a convo (or rod) I can tell a creature to move exactly 1.524 meters from me (the PC) and get consistent results of 1.524 meters?

Why you’re getting inconsistent results is explained at the end of my last post. Unless somebody has a better idea, I see two possible solutions kludges:

  1. Calculate a vector from PC to NPC. Increase its length by 1.524 m. Make NPC move to PC position + that position.
  2. Apply a custom AOE (EffectAreaOfEffect(), edit vfx_persistent.2da) to the PC with radius equal to 1.524. Then apply CAA to the NPC in OnExit script of this AOE and destroy the AOE.

Caveats: #1 does not guarantee that the target position will be walkable or even within level geom, but will easily accept any distance from the input. #2 has no such issues but is inflexible (you need one 2da row per distance), needs 2da edits and is a bigger resource hog.

Sounds like ActionMoveAwayFromObject needs to follow a GetDistanceBetween check first.

void ReportDistanceToPC(object oNPC, object oPC)
{
	SendMessageToPC(oPC, GetName(oNPC) + " is now " +
		FloatToString(GetDistanceBetween(oPC, oNPC), 0, 2) +
		" m away from you");
}
void main()
{
    object oPC = GetPCSpeaker();
    float fDist  = GetDistanceToObject(oPC);
    float fDistN = 1.524 - fDist;//Here we get the difference the NPC is from the 
//distance you want

    ClearAllActions();
    ActionMoveAwayFromObject(oPC, TRUE, fDistN);//Make them move the difference
//I think if they are further than the distance, 
//this will make them come to you instead since it is negative?
    fDist  = GetDistanceToObject(oPC);
    string sDist = FloatToString(fDist);
    AssignCommand(oNPC, ActionDoCommand(ReportDistanceToPC(oNPC, oPC)));
}

@Mannast - Sorry, still getting inconsistent results.

Everyone – Buddha on the NWN Discord channel was kind enough to create a couple of placeables (5’ and 5 m in length). After several hours of testing, I think his placeables are good enough in that between their length and the difficulty in placing the PC exactly where he needs to be, the accuracy is probably +/- 3 inches. At least it appears to be that way.

So rather than devoting any more time to getting a script to work, I think the placeable solution is good enough.

Thank you all very much for your help!