vp_terrain_query
Method call snippet
vp_terrain_query(instance, x, z);
Query a terrain tile.
Parameters
These are the parameters that this method requires:
Parameter | Usage |
---|---|
VPInstance instance |
Pointer to the instance this method call is intended for |
int tile_x |
X tile coordinate (with no terrain scaling, divide coordinates in decameter by 32 to get tile coordinates) |
int tile_z |
Z tile coordinate |
int[4][4] revision |
16 node revision numbers (4x4: revision[z][x]) |
Returns
This method returns a return code integer, which indicates whether the call was successful or errored for any reason:
Return code | Cause |
---|---|
VP_RC_SUCCESS |
Successful call (for methods that have a registered callback, it only means the request has been sent) |
VP_RC_NOT_IN_WORLD |
Bot is not currently in a world |
Behavior
- Upon successfully querying a tile,
VP_EVENT_TERRAIN_NODE
is triggered for each of the terrain nodes in it. Seevp_event_set()
.
Examples
/*
* This example will monitor avatars within the area from 0X 0Z to 32X 32Z and teleport them above ground when they go more than 2 meters below the terrain height.
* Note: The code assumes that the terrain has not been scaled or offset!
*/
float g_heights[32][32]; // All the heights inside the queried terrain tile (in this example it is a square from coordinate 0,0 to 32,32)
void handle_terrain_node(VPInstance sdk)
{
int offset_x, offset_z; // Offset cell x and z for storing current node in g_heights
offset_x = vp_int(sdk, VP_TERRAIN_NODE_X) * 8;
offset_z = vp_int(sdk, VP_TERRAIN_NODE_Z) * 8;
int length; // Not used in this example
vp_terrain_cell_t (*cell)[8][8] = (vp_terrain_cell_t(*)[8][8])vp_data(sdk, VP_TERRAIN_NODE_DATA, &length);
for (int i = 0; i < 8; i++)
for (int j = 0; j < 8; j++)
g_heights[i + offset_z][j + offset_x] = (*cell)[i][j].height;
}
float get_height(double x, double z)
{
int x_cell, z_cell; // Terrain cell coordinate is simply the truncated coordinate in decameters
x_cell = (int)x;
z_cell = (int)z;
if (x_cell < 0 || x_cell > 30) // Check if x coordinate is within the queried tile
return INFINITY;
if (z_cell < 0 || z_cell > 30) // Check if z coordinate is within the queried tile
return INFINITY;
double x_rel, z_rel; // Coordinate within the cell (for calculating the height)
x_rel = x - trunc(x);
z_rel = z - trunc(z);
double base, x_diff, z_diff; // Base height, maximum difference toward x and z.
// Four cases, depending on what cell it is and which half of the cell
if ((x_cell + z_cell) % 2)
{
// Odd cell, diagonal goes from 0,0 to 1,1
if ((1.0 - x_rel) + z_rel > 1)
{
// Upper half of the cell
base = g_heights[z_cell + 1][x_cell];
x_diff = g_heights[z_cell + 1][x_cell + 1] - base;
z_diff = g_heights[z_cell][x_cell] - base;
z_rel = 1.0 - z_rel;
}
else
{
// Lower half of the cell
base = g_heights[z_cell][x_cell + 1];
x_diff = g_heights[z_cell][x_cell] - base;
z_diff = g_heights[z_cell + 1][x_cell + 1] - base;
x_rel = 1.0 - x_rel;
}
}
else
{
// Even cell, diagonal goes from 1,0 to 0,1
if (x_rel + z_rel > 1)
{
// Upper half of the cell
base = g_heights[z_cell + 1][x_cell + 1];
x_diff = g_heights[z_cell + 1][x_cell] - base;
z_diff = g_heights[z_cell][x_cell + 1] - base;
x_rel = 1.0 - x_rel;
z_rel = 1.0 - z_rel;
}
else
{
// Lower half of the cell
base = g_heights[z_cell][x_cell];
x_diff = g_heights[z_cell][x_cell + 1] - base;
z_diff = g_heights[z_cell + 1][x_cell] - base;
}
}
return (float)(base + x_diff * x_rel + z_diff * z_rel);
}
void handle_avatar_change(VPInstance sdk)
{
double x, y, z;
x = vp_double(sdk, VP_AVATAR_X);
y = vp_double(sdk, VP_AVATAR_Y);
z = vp_double(sdk, VP_AVATAR_Z);
float y_calc;
y_calc = get_height(x, z);
if (y_calc != INFINITY) // Inside queried area
{
if (y < y_calc - 0.2) //Below the terrain (assuming avatar is shorter than 2 meters)
{
printf("WARNING: \"%s\" was moving around below the terrain!\n", vp_string(sdk, VP_AVATAR_NAME));
vp_teleport_avatar(sdk,
vp_int(sdk, VP_AVATAR_SESSION),
"",
x,
y_calc,
z,
vp_double(sdk, VP_AVATAR_YAW),
vp_double(sdk, VP_AVATAR_PITCH)); // Teleport avatar up above ground
}
}
}
int main(int argc, const char* argv[])
{
//...
vp_event_set(sdk, VP_EVENT_AVATAR_CHANGE, handle_avatar_change);
vp_event_set(sdk, VP_EVENT_TERRAIN_NODE, handle_terrain_node);
int rev[4][4];
memset(rev, 0, sizeof(rev));
vp_terrain_query(sdk, 0, 0, rev);
//...
}