Ok, there are two approaches, and these approached depend on how frequently you wish to move the object and how vital precision is. The first approach is discussed on the wiki
here.
This approach is a reasonable approach, except it will be slow for any decent level of precision (remember that this system will need to start off with an initial cube size large enough to cover your map, then subdivide down to the player position - whilst this grows at a rate of log(n), each step still adds hard disk read for loading in the subdivision entity of that size). The bad new is
this approach would require altering to get it to work with the "Player" entity - and i don't know how much work that would be. If you wish to use this approach with the player and cannot alter the code yourself i would probably be able to write up a version which supports "Player", but i'm probably going to be busy so i might not get around to it for some time.
The other approach i have worked on today, and acts a little differently. You can get the sample map
here .
This map sample contains the map and script demo, as well as a python script for generating expObjs (which can be loaded into the level editor using file->Import objects) and a generated expobj.
The actual finding a position has very little performance overhead, and will be able to track the position of a huge amount of objects to an arbitrary level of precision. The downside is that this will bloat your map file size significantly - but this is still a fairly favorable trade-off.
Firstly, you will need to download and install
python 2.7 and run
this script (This script is also included in the sample map folder). I used the following parameters:
scale factor (x/z):1
scale factor (y):5
x-length:20
y-length:10
z-length:20
filename:t.expobj
This generates an expobj file containing a grid of script areas covering the specified x/y/z range with a step-size equal to the scale factor. The python script can be extended to include lookat callbacks along with other things pretty trivially. You then import the object into your map file and move the grid to the appropriate location.
You can then copy & paste
this script into your script file. This script will then let you use the following functions:
Grid_Initiate(float originX, float originY, float originZ, float scaleFactorX, float scaleFactorY, float scaleFactorZ)
Grid_StartTracking(string &in asEntity)
float[] Grid_GetTrackedObjectPosition(string &in asEntity)
string Grid_WorldCoordToGrid(float x, float y, float z)
There is also a callback called "_cb_Grid_OnMove" which determines if an object has moved, you can tweak this to act as a trigger for if the player has moved if you so wish.
To use this functions, firstly call "Grid_Initiate" in the OnStart() event - the Origin parameters are the X/Y/Z coordinates of the script area called "SAGrid_(0.000,0.000,0.000)", and the scale values are the x/y/z scale of this script area. After this, at any point you can call "Grid_StartTracking" to begin tracking an entity (E.g. "Player"). To get the coordinates of this entity call "Grid_GetTrackedObjectPosition" and specify the entity, a float array of 3 elements will be returned. E.g.
void OnStart()
{
Grid_Initiate(-8.75f,2.5f,-10.75f,1,5,1);
Grid_StartTracking("Player");
}
void SomeEvent()
{
float[] position = Grid_GetTrackedObjectPosition("Player");
AddDebugMessage("Player's X-Position is: " + position[0],false);
AddDebugMessage("Player's Y-Position is: " + position[1],false);
AddDebugMessage("Player's Z-Position is: " + position[2],false);
}
Like with the previous approach, you can just use AddAttachedPropToProp to attach the entity you wish to make appear. However, if you want a "billboard" effect you could also just create the billboard as a particle system.
If you want to use the particle system approach (or you want your entity to collide and be physically active) then you can use the last function: Grid_WorldCoordToGrid - where the x/y/z represent where in the world you want to place your object. You can then use CreateEntityAtArea (or the equivalent PS function) with the returned value. E.g.
void SomeEvent()
{
//Get player position
float[] position = Grid_GetTrackedObjectPosition("Player");
//Create a barrel above the player's head & drop it on him
string gridObject = Grid_WorldCoordToGrid(position[0],position[1]+5,position[2]);
CreateEntityAtArea("Barrel_Drop","barrel01.ent",gridObject,false);
}