CalcSafeLocation() doesn't seem to fit the bill, but maybe it does. Anyone have any luck making a script to do this?
Is there a function to calculate the nearest safe location to another location within a certain radius?
Débuté par
M. Rieder
, nov. 12 2011 07:15
#1
Posté 12 novembre 2011 - 07:15
#2
Posté 12 novembre 2011 - 07:41
CalcSafeLocation's lTestPosition does not have to be the location of the caller of the script. It should be able to be fed an alternate location, and do what you want. I've never used it though.
#3
Posté 12 novembre 2011 - 08:35
these are a couple of little routines that have been running successfully re. dragon scripts:
the first calculates a position for a thrown weapon (tailslap) & the second makes the dragon do a deek-out move around an (ethereal) opponent -
might not be exactly what you want, but hope it fires some neurons for yez
the first calculates a position for a thrown weapon (tailslap) & the second makes the dragon do a deek-out move around an (ethereal) opponent -
// kL, randomize where oItem gets thrown to
location lTarget;
int bValidLoc = FALSE;
while (!bValidLoc)
{
SendMessageToPC(oTarget, ". ( nw_s1_dragtslap ) finding valid location . . .");
// lTarget = GetRandomLocation(GetArea(oTarget), oTarget, IntToFloat(d10()));
lTarget = GetBehindLocation(oTarget, IntToFloat(Random(9)));
bValidLoc = GetIsLocationValid(lTarget);
}
object oThrownItem = CopyObject(oItem, lTarget);
//----//
location lMoveTo;
if (!Random(2))
{
lMoveTo = GetAheadRightLocation(oValidTarget);
}
else lMoveTo = GetAheadLeftLocation(oValidTarget);
// Returns TRUE if the location is a valid, walkable location.
if (!GetIsLocationValid(lMoveTo))
{
lMoveTo = CalcSafeLocation(OBJECT_SELF, lMoveTo, 5.0f, FALSE, FALSE);
}
ActionMoveToLocation(lMoveTo, TRUE);might not be exactly what you want, but hope it fires some neurons for yez
#4
Posté 12 novembre 2011 - 11:02
Thanks for the responses they have helped me refine my question. A better question for me to ask is when I use CalcSafeLocation() in a loop, will it give me the same location every time or will it randomize? I want to make a loop that checks locations around an object and will return the closest one to the PC that is withing 40 meters of the target.
#5
Posté 12 novembre 2011 - 11:12
ooh, yeh i imagine it could be used to do that. So could GetRandomLocation() i imagine ..
- but would it get complicated: you'd have to do a whileLoop, temporarily storing the returned distances(oPC, oLocation), perhaps setting a set # of passes so it doesn't get out of control, then use an algorithm that finds the closest and return that! unless there's an easier way ....
To answer your question (directly) i have no idea ... 'd have to do a test debugging the vectors returned
edit, sort of, i see your predicament is a bit different.
- but would it get complicated: you'd have to do a whileLoop, temporarily storing the returned distances(oPC, oLocation), perhaps setting a set # of passes so it doesn't get out of control, then use an algorithm that finds the closest and return that! unless there's an easier way ....
To answer your question (directly) i have no idea ... 'd have to do a test debugging the vectors returned
edit, sort of, i see your predicament is a bit different.
Modifié par kevL, 12 novembre 2011 - 11:17 .
#6
Posté 12 novembre 2011 - 11:21
make sure you exclude the current location (and any location less than x) in that loop, since if it's called from a safe location the nearest safe location would be where you already were.
#7
Posté 13 novembre 2011 - 12:38
this is the idea (taking kamal_'s advice, if you go w/ CalcSafe instead of GetRandomLocation):
if that works i'll eat a kobold (edit, update, upd 2)
#include "x0_i0_position"
location GetCloseLoc(object oPC, object oTarget)
{
//location lTarget = GetLocation(oTarget);
int iRepeatLoop;
location lLoc;
object oLoc;
for (iRepeatLoop = 1; iRepeatLoop <= 15; iRepeatLoop ++)
{
//lLoc = CalcSafeLocation(oPC, lTarget, 40.0f, FALSE, TRUE);
lLoc = GetRandomLocation(GetArea(oTarget), oTarget, IntToFloat(Random(40)));
if (GetIsLocationValid(lLoc))
{
//lLoc = CalcSafeLocation(oPC, lTarget, 40.0f, FALSE, TRUE); <- disregard this.
oLoc = CreateObject(OBJECT_TYPE_WAYPOINT, "wp_poi", lLoc, FALSE, "wp_poi_getcloseloc");
}
// Could probably stick this in here instead of the second for() loop:
//DelayCommand(0.1f, DestroyObject(oLoc));
}
location lReturn = GetLocation(GetNearestObjectByTag("wp_poi_getcloseloc", oPC));
for (iRepeatLoop = 1; iRepeatLoop <= 15; iRepeatLoop ++)
{
DestroyObject(GetNearestObjectByTag("wp_poi_getcloseloc", oTarget, iRepeatLoop));
}
return lReturn;
}if that works i'll eat a kobold (edit, update, upd 2)
Modifié par kevL, 13 novembre 2011 - 01:12 .
#8
Posté 13 novembre 2011 - 01:02
Yeah. That's what I was thinking of doing. Either that or make a script that takes points along different angles at various distances and checks them with the algorithm. I don't know if it would make a difference. I think I'm going to start working on this and see what happens.
#9
Posté 13 novembre 2011 - 01:15
luck sir
#10
Posté 13 novembre 2011 - 01:31
Okay, I did a few modifications, such as storing the location as a local location instead of creating a waypoint. I modified the imput to work with the rest of my scripting and I changed the number of iterations to 100 since not much else is going on in the area and the resources should be fine. Otherwise it is basically what you sent me, KevL. Everything compiles, but is untested. Testing now...
location FindNearestValidLocation(object oTarget,float fDistance)
{
//location lTarget = GetLocation(oTarget);
object oSelf = OBJECT_SELF;
int iRepeatLoop;
location lNewLocation;
location lStoredLocation;
location lSelf = GetLocation(oSelf);
location lReturn;
float fDistanceToNewLocation;
float fDistanceToStoredLocation;
for (iRepeatLoop = 1; iRepeatLoop <= 100; iRepeatLoop ++)
{
//lLoc = CalcSafeLocation(oPC, lTarget, 40.0f, FALSE, TRUE);
lStoredLocation=GetLocalLocation(oSelf,"lStoredLocation");
lNewLocation = GetRandomLocation(GetArea(oTarget), oTarget, fDistance);
fDistanceToNewLocation=GetDistanceBetweenLocations(lSelf,lNewLocation);
fDistanceToStoredLocation=GetDistanceBetweenLocations(lSelf,lStoredLocation);
if((!GetIsLocationValid(lStoredLocation))||
(fDistanceToNewLocation<fDistanceToStoredLocation))
{
SetLocalLocation(oSelf,"lStoredLocation",lNewLocation);
}
}
lReturn=GetLocalLocation(oSelf,"lStoredLocation");
return lReturn;
}
location FindNearestValidLocation(object oTarget,float fDistance)
{
//location lTarget = GetLocation(oTarget);
object oSelf = OBJECT_SELF;
int iRepeatLoop;
location lNewLocation;
location lStoredLocation;
location lSelf = GetLocation(oSelf);
location lReturn;
float fDistanceToNewLocation;
float fDistanceToStoredLocation;
for (iRepeatLoop = 1; iRepeatLoop <= 100; iRepeatLoop ++)
{
//lLoc = CalcSafeLocation(oPC, lTarget, 40.0f, FALSE, TRUE);
lStoredLocation=GetLocalLocation(oSelf,"lStoredLocation");
lNewLocation = GetRandomLocation(GetArea(oTarget), oTarget, fDistance);
fDistanceToNewLocation=GetDistanceBetweenLocations(lSelf,lNewLocation);
fDistanceToStoredLocation=GetDistanceBetweenLocations(lSelf,lStoredLocation);
if((!GetIsLocationValid(lStoredLocation))||
(fDistanceToNewLocation<fDistanceToStoredLocation))
{
SetLocalLocation(oSelf,"lStoredLocation",lNewLocation);
}
}
lReturn=GetLocalLocation(oSelf,"lStoredLocation");
return lReturn;
}
Modifié par M. Rieder, 13 novembre 2011 - 01:31 .
#11
Posté 13 novembre 2011 - 02:06
Had to switch to CalcSafeLocation() instead of GetRandomLocation() because I want to be able to plot a course to it. Re-testing...
#12
Posté 13 novembre 2011 - 03:22
The script seems okay, but i'm having troubles inserting a custom non-action function into the action queue.
#13
Posté 13 novembre 2011 - 03:36
//nice. May i parse it down ...
#include "x0_i0_position"
location FindNearestValidLocation(object oTarget, float fDistance)
{
object oSelf = OBJECT_SELF;
location lSelf = GetLocation(oSelf);
location lLocation;
location lReturn;
float fDistanceToLocation;
float fDistanceToReturn;
int i;
for (i = 1; i <= 100; i ++)
{
lLocation = GetRandomLocation(GetArea(oTarget), oTarget, fDistance);
fDistanceToLocation = GetDistanceBetweenLocations(lSelf, lLocation);
fDistanceToReturn = GetDistanceBetweenLocations(lSelf, lReturn);
if (!GetIsLocationValid(lReturn) || (GetIsLocationValid(lLocation) && fDistanceToLocation < fDistanceToReturn))
{
lReturn = lLocation;
}
}
return lReturn;
}
void main(){}ActionDoCommand(?)M. Rieder wrote...
The script seems okay, but i'm having troubles inserting a custom non-action function into the action queue.
#14
Posté 13 novembre 2011 - 04:22
Thanks KevL. I'm a self-taught scripter, so I have all sorts of funny ways of writing code. ActionDoCommand() was the fix. Problem is that the function ActionMoveToLocation() does not play well in the action queue apparently, so I filled the area with waypoints and used GetNearestObjectToLocation() to get the nearest waypoint so that I can use ActionMoveToObject() which does play nicely in the action queue.
Right now I'm just trying to figure out how to work my code so the movement happens before the other action. I think I just have to get my ActionDoCommand() in the right place. I'll keep you posted.
I have about 10 custom functions in the script so figuring out where to make the functions go into the queue is confusing. I'm expecting a lot of trial and error..... mostly error.
Right now I'm just trying to figure out how to work my code so the movement happens before the other action. I think I just have to get my ActionDoCommand() in the right place. I'll keep you posted.
I have about 10 custom functions in the script so figuring out where to make the functions go into the queue is confusing. I'm expecting a lot of trial and error..... mostly error.
Modifié par M. Rieder, 13 novembre 2011 - 04:23 .
#15
Posté 13 novembre 2011 - 04:29
ya, so am i
but i find scripts such a thing of Beauty ... i go over and over them until it's the Heisenberg Uncertainty Principle
- mostly error.
but i find scripts such a thing of Beauty ... i go over and over them until it's the Heisenberg Uncertainty Principle
- mostly error.
#16
Posté 13 novembre 2011 - 02:39
I did some testing and it actually appears that GetRandomLocation() actually only generates locations that are valid and walkable from the caller. This is the test script I used:
#include "x0_i0_position"
void main()
{
object oSelf=OBJECT_SELF;
location lSelf = GetLocation(oSelf);
string sTemplate = "plc_mc_soulhouse4";
int nCounter=1;
location lLocation;
while (nCounter<=150)
{
lLocation=GetRandomLocation(GetArea(oSelf),oSelf,IntToFloat(d10(1)));
// lLocation=CalcSafeLocation(oSelf,lLocation,1.0,TRUE,TRUE);
CreateObject(OBJECT_TYPE_PLACEABLE,sTemplate,lLocation);
nCounter++;
}
}
I put the PC next to some non-walkable terrain and some terrain that was walkable but not accessible to the PC, then made the PC call the script. When I used only GetRandomLocation, the soul housings only appeared in valid locations that the PC could path to. When I used GetRandomLocation() as well as CalcSafeLocation() the soul housings would appear in all valid locations, even If the PC could path to them or not.
Also, if I only used CalcSafeLocation(), the script produced the same location in each iteration of the loop, so I had to add GetRandomLocation() to generate some variation.
Also, GetRandomLocation() appears to take terrain into consideration but not the edge of the walkable area.
#include "x0_i0_position"
void main()
{
object oSelf=OBJECT_SELF;
location lSelf = GetLocation(oSelf);
string sTemplate = "plc_mc_soulhouse4";
int nCounter=1;
location lLocation;
while (nCounter<=150)
{
lLocation=GetRandomLocation(GetArea(oSelf),oSelf,IntToFloat(d10(1)));
// lLocation=CalcSafeLocation(oSelf,lLocation,1.0,TRUE,TRUE);
CreateObject(OBJECT_TYPE_PLACEABLE,sTemplate,lLocation);
nCounter++;
}
}
I put the PC next to some non-walkable terrain and some terrain that was walkable but not accessible to the PC, then made the PC call the script. When I used only GetRandomLocation, the soul housings only appeared in valid locations that the PC could path to. When I used GetRandomLocation() as well as CalcSafeLocation() the soul housings would appear in all valid locations, even If the PC could path to them or not.
Also, if I only used CalcSafeLocation(), the script produced the same location in each iteration of the loop, so I had to add GetRandomLocation() to generate some variation.
Also, GetRandomLocation() appears to take terrain into consideration but not the edge of the walkable area.
Modifié par M. Rieder, 13 novembre 2011 - 02:47 .
#17
Posté 13 novembre 2011 - 07:49
So, GetRandomLocation() that's yer ticket .....
Are you saying that GRL() will place objects outside the walkable area? maybe the CalcSafe() could be fashioned into a subroutine that, if so, prevents that ...
Edit, rather GetIsLocationValid()
and just chuck inValid locs away. Like FindNearestValidLocation() should already do ..
i *think* i read something about a 2meter height difference, max, somewhere. (but that could well be something entirely different, can't find it)M. Rieder wrote...
Also, GetRandomLocation() appears to take terrain into consideration but not the edge of the walkable area.
Are you saying that GRL() will place objects outside the walkable area? maybe the CalcSafe() could be fashioned into a subroutine that, if so, prevents that ...
Edit, rather GetIsLocationValid()
and just chuck inValid locs away. Like FindNearestValidLocation() should already do ..
Modifié par kevL, 13 novembre 2011 - 07:56 .
#18
Posté 13 novembre 2011 - 09:14
Hey, I got everything working properly. I built a grid of waypoints in the area I'm using, then when I generate the location I want, I get the nearest waypoint to that location and the NPC runst to it, then does what it is supposed to do. Everything works quite well. Thanks for the help. When I release The Wizard's Apprentice II in a few months, you'll be able to see what this was all for. It's a bit of a "wizard's maze".
#19
Posté 13 novembre 2011 - 10:08
great! WizzApps are high on my list





Retour en haut






