Page 1 of 1
Spawn.NearestSpawn.Distance returns wrong distance
Posted: Mon Sep 27, 2004 8:39 pm
by Marze
${Spawn[whatever].NearestSpawn[1 npc].Distance} returns the distance to you, not the distance from the original Spawn. Workaround is to save the location of both spawns and calculate the distance between two points yourself.
Posted: Mon Sep 27, 2004 9:28 pm
by wassup
Did you try using NearestSpawn correctly?
spawn NearestSpawn[n,search]
Find the nth nearest spawn matching this search, to this spawn (most efficient on yourself)
Separate the 1 and npc with a comma.
If it doesn't work then come back again.
Posted: Mon Sep 27, 2004 10:00 pm
by SlimFastForYou
I can confirm this behavior. A while ago (I'd say right before OOW came out), I tried to make my AcquireTarget routine take advantage of this, but it would always give the distance to the player. I thought that maybe it was just me, because nobody else had complained about it.
My target is a decaying skeleton, and on the map it's label is red. I am the arrow pointing northeast near the bottom-center of the map.
Between commands, the decaying skeleton moved southwest a little towards me (the arrow close to the bottom center of the map is me). So when I typed the second command (took me about 5-10 sec), the decaying skeleton had already moved a tiny bit. You can easily tell though that if the decaying skeleton is ~1000 from me, the closest NPC shouldnt also be ~1000.
Now that I know I'm not the only one I might look the code over sometime (after I get MQ2Perl to compile, argh!).
Posted: Tue Sep 28, 2004 3:37 am
by wassup
Try it this way...
Code: Select all
${Spawn[whatever].NearestSpawn[1, npc radius 150].Distance}
I always notice some oddities, but as it says, it's more effective when used with Me.
To check on a static spawn you have to use radius also or it doesn not work.
y and x might be reversed. This is just off the top of my head.
Posted: Tue Sep 28, 2004 5:35 am
by SlimFastForYou
(Note: I consider myself merely an intermediate C++ coder, so consider my input on this with an appropriate grain of salt)
Well I found the reason it behaves this way. Take a look at some things:
Here you can see what happens when you do ${Target.Distance}. This is also what happens when you do ${Target.NearestSpawn[1,npc].Distance}. This function is found in MQ2DataTypes.cpp. Please note that pSpawn is whatever spawn is currently being evaluated - whether it is ${Target} or ${Target.NearestSpawn[1,npc]}.
Code: Select all
bool MQ2SpawnType::GetMember(MQ2VARPTR VarPtr, PCHAR Member, PCHAR Index, MQ2TYPEVAR &Dest)
{
.
.
.
case Distance:
Dest.Float=GetDistance(pSpawn->X,pSpawn->Y);
Dest.Type=pFloatType;
return true;
.
.
.
}
Now, let's examine the GetDistance function. When we go to examine the GetDistance function found in MQ2Inlines.h, we find two different definitions (hurray for polymorphism :) !)
Code: Select all
static inline FLOAT GetDistance(FLOAT X1,FLOAT Y1)
{
FLOAT dX=X1-((PSPAWNINFO)pCharSpawn)->X;
FLOAT dY=Y1-((PSPAWNINFO)pCharSpawn)->Y;
return sqrtf(dX*dX + dY*dY);
}
static inline FLOAT GetDistance(FLOAT X1,FLOAT Y1,FLOAT X2,FLOAT Y2)
{
FLOAT dX=X1-X2;
FLOAT dY=Y1-Y2;
return sqrtf(dX*dX + dY*dY);
}
Currently, the first GetDistance function is called, irregardless of whether it is ${Target} or ${Target.NearestSpawn[1,npc]}.
So, to adjust the code in order to fix this problem, somehow we would have to get the parent spawn's X and Y attributes (when I say parent, I mean the parent of NearestSpawn whether it be the implied ${Me} or a ${Target} across the map) and use those to make a function call to the second definition of GetDistance - not the first which defaultly uses ${Me}. That would be up to the devs to decide how they would want to do this. I can't really think of an easy way to do this besides either doing a significant modification or creating a global variable for the CurrentParent spawn. But I think I identified the cause.
Please let me know if that made any sense or if you strongly suspect me of being on crack :-).
Posted: Tue Sep 28, 2004 11:38 am
by blueninja
${Target} is a Spawn, ${Target.NearestSpawn} is just another Spawn. If Spawn.Distance returns the distance between you and the spawn in one case it will also do so in the second case. Think of it this way: if you compare it to ${Target.Name} and ${Target.NearestSpawn[].Name}, would you expect them to return anything other than the name of the two different spawns?
I realize what you want to do but this is not how you should do it. ${Math.Distance[]} is what you're looking for. Something along these lines. Either that or add a new member to the Spawn type, like Spawn.DistanceToSpawn[].
Code: Select all
/varset SpawnID ${Spawn[whatever].ID}
/varset NearSpawnID ${Spawn[id ${SpawnID}].NearestSpawn[].ID}
/echo Distance: ${Math.Distance[${Spawn[id ${SpawnID}].Y},${Spawn[id ${SpawnID}].Y}:${Spawn[id ${NearSpawnID}].Y},${Spawn[id ${NearSpawnID}].Y}]}
Posted: Tue Sep 28, 2004 12:45 pm
by SlimFastForYou
I thought about it last night, and although both me and Marze would love it if MQ did that for us, it probably wasn't intended to be so.
In other words, how would one find the distance between a player and the nearest spawn to the target? That's what this function is for. So it really isn't a bug when you think about it. That also explains why I witnessed the same behavior like 5 zips ago and nobody reported it as a bug until now

.
Adding a new member like ${Spawn.NearestSpawnDistance[n,search]} would be useful IMHO. But I could also use a whole bunch of math calculations. My AcquireTarget has already been written, tested and it works. There are features I would like to add to it, and although it would probably go faster if Macroquest was able to naturally calculate distances between spawns, that would really be up to the devs whether to include that or not.
I'll probably whip up a test-of-concept function sometime later today.
Posted: Tue Sep 28, 2004 3:08 pm
by Night Hawk
a^2+b^2=c^2

Posted: Tue Sep 28, 2004 4:51 pm
by SlimFastForYou
Night Hawk wrote:a^2+b^2=c^2

Not quite. If you want to check the distances of the nearest 10 mobs against the nearest 15 mobs (I found ways to simplify this).
Code: Select all
Check to see the distance between Candidate and CheckMob (to be used in a loop):
${Math.Sqrt[${Math.Calc[${Math.Calc[${NearestSpawn[${CheckMob},npc].X}-${NearestSpawn[${Candidate},npc].X}]}*${Math.Calc[${NearestSpawn[${CheckMob},npc].X}-${NearestSpawn[${Candidate},npc].X}]}]}+${Math.Calc[${Math.Calc[${NearestSpawn[${CheckMob},npc].Y}-${NearestSpawn[${Candidate},npc].Y}]}+${Math.Calc[${NearestSpawn[${CheckMob},npc].Y}-${NearestSpawn[${Candidate},npc].Y}]}]}]}
Also known as c = sqrt ( (x-x1)^2 + (y-y1)^2 )
I had something like this in my AcquireTarget routine initally. But it was such a mindfuck and I did find ways of simplifying this using various tricks.
Would be more elegant to have
Code: Select all
${NearestSpawn[${Candidate},npc].NearestSpawnDistance[${CheckMob},npc]}
Just MHO, and I found ways to simplify this. Plus, it would be somewhat faster for MacroQuest to natively handle this. Whether this is included as a new feature or not really doesn't matter to me - I believe it would be un-necessary but at the same time nice to have.