PDA

View Full Version : [TSL] Use of GetNearestObjectByTag


Princess Artemis
04-10-2007, 09:14 PM
A user of my and Jiara's Dustil Recruit mod has encountered a bug that I'd like to fix, but I'm not sure how to go about it. The player is having trouble fixing HK-47 after recruiting Dustil. Well, actually they're having trouble keeping HK from replacing Dustil after the game wigs out on them by having the post-repair-HK conversation with Dustil intead of HK...

What we're trying is a tweaked a_createhk47 script...I figured the reason this person was having a problem with it is because the original version of this script first creates the real HK-47, then grabs any HK, and since technically at the point of the game, there are two HKs (Dustil is tagged "HK47") on the Ebon Hawk, it's grabbing the wrong one.

Unfortunately, when it was tested, the player got into a conversation with the broken HK (which is tagged "DrdParts")...so I'm wondering if I'm using the function GetNearestObjectByTag incorrectly. Here's the script as I've rewritten it...

// Prototypes
void sub2();
void sub1();

void sub2() {
object oPC = GetFirstPC();
object oHK47 = GetNearestObjectByTag("HK47", oPC=OBJECT_SELF, 1);
AssignCommand(oHK47, ClearAllActions());
AssignCommand(oHK47, ActionStartConversation(oPC, "", 0, 0, 1, "", "", "", "", "", "", 0, 0xFFFFFFFF, 0xFFFFFFFF, 0));
}

void sub1() {
object oWP_CREATE_HK47 = GetObjectByTag("WP_CREATE_HK47", 0);
CreateObject(1, "p_hk47", GetLocation(oWP_CREATE_HK47), 0);
}

void main() {
SetGlobalFadeOut(0.5, 1.0, 0.0, 0.0, 0.0);
DelayCommand(0.5, sub1());
SetGlobalNumber("000_HK_Alive", 1);
DelayCommand(0.8, sub2());
}


The original a_createhk47 has this code in place of the yellow above:
object oHK47 = GetObjectByTag("HK47", 0);
object oPC = GetFirstPC();

Am I doing something drastically wrong here?

Pavlos
04-11-2007, 05:11 AM
Hmm... I've no idea if this will work (completely untested) but it is worth a shot.

// Starts the conversation with HK-47 on reactivation
void StartConversations();

// Creates HK-47 and places him at the waypoint "WP_CREATE_HK47"
void CreateHK47PartyMember();


void StartConversations() {
object oPC = GetFirstPC();
object oHK47 = GetNearestObjectByTag("HK47", oPC, 1);
int i = 2;

// I have no idea how many HK47 creatures there are so best to use a while clause
while (GetIsObjectValid(oHK47) && GetName(oHK47) != "HK-47")
{

GetNearestObjectByTag("HK47", oPC, i);
i++;

}

AssignCommand(oHK47, ClearAllActions());
AssignCommand(oHK47, ActionStartConversation(oPC, "", 0, 0, 1, "", "", "", "", "", "", 0, 0xFFFFFFFF, 0xFFFFFFFF, 0));
}

void CreateHK47PartyMember() {
object oWP_CREATE_HK47 = GetObjectByTag("WP_CREATE_HK47", 0);
CreateObject(1, "p_hk47", GetLocation(oWP_CREATE_HK47), 0);
}

void main() {
SetGlobalFadeOut(0.5, 1.0, 0.0, 0.0, 0.0);
DelayCommand(0.5, CreateHK47PartyMember());
SetGlobalNumber("000_HK_Alive", 1);
DelayCommand(0.8, StartConversations());
}

You did want HK to be the one speaking didn't you?

Princess Artemis
04-11-2007, 09:16 AM
Yes, I want the conversation that initially starts when you reactivate HK to actually happen. So definitely HK speaking.

I noticed you don't have an OBJECT_SELF in the GetNearestObjectByTag...could it be that's what I did wrong, that function doesn't need that in it if the oTarget is already taken care of? The functions defined by nwscript lists it like so: object GetNearestObjectByTag(string sTag, object oTarget=OBJECT_SELF, int nNth=1);

Further narrowing it down with the while clause might help, too, since the broken HK is named "Damaged HK Unit".

Unfortunately I can't test it...I've never had this particular thing happen to me, although I understand why it has the potential to happen to anyone :/

Pavlos
04-11-2007, 09:27 AM
I noticed you don't have an OBJECT_SELF in the GetNearestObjectByTag...could it be that's what I did wrong, that function doesn't need that in it if the oTarget is already taken care of? The functions defined by nwscript lists it like so: object GetNearestObjectByTag(string sTag, object oTarget=OBJECT_SELF, int nNth=1);

The "oTarget=OBJECT_SELF" just means that if the parameter is not entered it will default to the caller of the script. If it is in a dialogue, the current speaker calls it. Using oPC ensures that you are finding the nearest creature with the tag "HK47."

Further narrowing it down with the while clause might help, too, since the broken HK is named "Damaged HK Unit".

Unless you have changed the p_hk47.utc file that shouldn't be necessary - the standard game resource has a name of "HK-47" - I think. I'm presuming that the game destroys the broken HK in another script.

***

It could be that GetNearestObjectByTag() is bugged - I have no idea, I've never tried to use it. If this is the case you could search for the creature with the name HK-47 using GetFirstObjectInArea() and GetNextObjectInArea(), or you could simply use GetObjectByTag() and specify a number in parameter two.

stoffe
04-11-2007, 09:29 AM
I noticed you don't have an OBJECT_SELF in the GetNearestObjectByTag...could it be that's what I did wrong, that function doesn't need that in it if the oTarget is already taken care of? The functions defined by nwscript lists it like so: object GetNearestObjectByTag(string sTag, object oTarget=OBJECT_SELF, int nNth=1);

The object oTarget=OBJECT_SELF part in the parameter list of the GetNearestObjectByTag() function declaration is assigning a default value. It says that "if this parameter is left out, set its value to OBJECT_SELF automatically".


// This...
GetNearestObjectByTag("mytag", OBJECT_SELF);

//...is the same as this:
GetNearestObjectByTag("mytag");

//...and as this:
object oTarget = OBJECT_SELF;
GetNearestObjectByTag("mytag", oTarget);


I.e. you do not write out that part when you assign a parameter value to a function call. If you do you make an assignment instead, in your case setting the value of the oPC variable to OBJECT_SELF. Which isn't what you wanted to do. :)

Consider this script being run by HK-47:

object oPC = GetFirstPC();
object oNPC = GetNearestObjectByTag("Mira", oPC = OBJECT_SELF);

SendMessageToPC(GetPartyLeader(), "My name is " + GetName(oPC));


This would get the "Mira" closest to HK47 and print "My name is HK47" to the Feedback log, and not "My name is The Exile", since you overwrite the initial assignment of the main character to oPC with OBJECT_SELF (the object running the script) on the second line.



If I remember correctly another oddity with GetNearestObjectByTag() is that it won't return the oTarget object, or an object occupying the exact same coordinates as oTarget, even if the tags do match. Apparently being in the same spot as the source of comparison isn't considered to be "near" by this function. :)

Princess Artemis
04-11-2007, 09:49 AM
Agh, putting in the OBJECT_SELF probably made the script do Bad Things then. a_createhk47 is fired from the dialogue drdparts...it's 'owned', presumably, by Damaged HK Unit. That's probably why the poor soul who is having the problem I'm trying to fix ended up in a conversation with the broken HK rather than the real HK. I couldn't figure out how the script could have possibly caused the player to get in a conversation with an object tagged "DrdParts"...but that explains it; I accidentally told DrdParts to start a conversation with itself. Head, meet desk.

I'll pull it out and send a new version to 'em to test. I do know that once the real HK-47 is created, he's the closest "HK47", so that should work.

Damaged HK Unit is destroyed during the initial conversation with the real HK in hk47.dlg.

It could be that GetNearestObjectByTag() is bugged - I have no idea, I've never tried to use it. If this is the case you could search for the creature with the name HK-47 using GetFirstObjectInArea() and GetNextObjectInArea(), or you could simply use GetObjectByTag() and specify a number in parameter two.

If I put a 1 in parameter two of GetObjectByTag(), does that tell it to pick up the nearest "HK47"? And if I put a 2, would that tell it to grab the second nearest "HK47"? Nice to know there are more choices that might work if my actually writing the script correctly fails :)

stoffe
04-11-2007, 10:02 AM
If I put a 1 in parameter two of GetObjectByTag(), does that tell it to pick up the nearest "HK47"? And if I put a 2, would that tell it to grab the second nearest "HK47"? Nice to know there are more choices that might work if my actually writing the script correctly fails :)

It picks the first, and the second, object with that tag in the module's object list. It could be right next to you or in the opposite side of the area. You can make your own "get nearest" function by looping through the object list (though that should be avoided if GetNearestObjectByTag() works since it will be much slower) like:


object ST_GetNearest(string sTag, object oSource=OBJECT_SELF) {
int iIdx = 0;
object oFind = GetObjectByTag(sTag, iIdx);
object oCurr = oFind;
float fCurr = GetDistanceBetween2D(oFind, oSource);

while (GetIsObjectValid(oFind)) {
float fDist = GetDistanceBetween2D(oFind, oSource);
if (fDist < fCurr) {
fCurr = fDist;
oCurr = oFind;
}
oFind = GetObjectByTag(sTag, ++iIdx);
}

return oCurr;
}

Princess Artemis
04-11-2007, 10:10 AM
Reports are in that the unbungled GetNearestObjectByTag() version of the script worked, so many thanks on helping me understand it better!