mirror of
https://github.com/Cesarus85/ringfall-mjolnir-vr.git
synced 2026-10-17 23:00:26 +02:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7242151017 | ||
|
|
4b8f8dde8b |
No files matched your search
@@ -794,6 +794,12 @@ the eyes reads it. Shown only while it is. */
|
||||
|
||||
#define WRIST_IMAGE_SIZE 512
|
||||
#define CROSSHAIR_IMAGE_SIZE 256
|
||||
/* the names layer: HALO_XR_MAXIMUM_NAMES slots of 4:1, one over another */
|
||||
#define NAMES_IMAGE_WIDTH 512
|
||||
#define NAMES_IMAGE_HEIGHT (NAMES_IMAGE_WIDTH / 4 * HALO_XR_MAXIMUM_NAMES)
|
||||
/* a name's slot, as the game draws it: wider than its image's 4:1 (the
|
||||
game's 640x480 drawn square): the height a slot shows at, to its width */
|
||||
#define NAME_SLOT_ASPECT (30.0f / 160.0f)
|
||||
#define WRIST_BEHIND_PALM 0.05f
|
||||
#define WRIST_DOWN_HANDLE 0.02f
|
||||
#define WRIST_ABOVE_HAND 0.04f
|
||||
@@ -1032,8 +1038,15 @@ int host_xr_initialize(struct halo_xr_info *info, float wanted_refresh_rate)
|
||||
{
|
||||
int size = layer == HALO_XR_LAYER_WRIST || layer == HALO_XR_LAYER_SCOPE ? WRIST_IMAGE_SIZE :
|
||||
layer == HALO_XR_LAYER_CROSSHAIR ? CROSSHAIR_IMAGE_SIZE : 0;
|
||||
int width = size ? size : xr.eye_width;
|
||||
int height = size ? size : xr.eye_height;
|
||||
|
||||
if (!swapchain_create(&xr.swapchains[layer], size ? size : xr.eye_width, size ? size : xr.eye_height))
|
||||
if (layer == HALO_XR_LAYER_NAMES)
|
||||
{
|
||||
width = NAMES_IMAGE_WIDTH;
|
||||
height = NAMES_IMAGE_HEIGHT;
|
||||
}
|
||||
if (!swapchain_create(&xr.swapchains[layer], width, height))
|
||||
return 0;
|
||||
}
|
||||
if (!copy_initialize() || !actions_initialize())
|
||||
@@ -1354,7 +1367,8 @@ int host_xr_end_frame(const struct halo_xr_submit *submit)
|
||||
XrCompositionLayerQuad wrist = { XR_TYPE_COMPOSITION_LAYER_QUAD };
|
||||
XrCompositionLayerQuad scope = { XR_TYPE_COMPOSITION_LAYER_QUAD };
|
||||
XrCompositionLayerQuad crosshair = { XR_TYPE_COMPOSITION_LAYER_QUAD };
|
||||
const XrCompositionLayerBaseHeader *layers[5];
|
||||
XrCompositionLayerQuad names[HALO_XR_MAXIMUM_NAMES];
|
||||
const XrCompositionLayerBaseHeader *layers[5 + HALO_XR_MAXIMUM_NAMES];
|
||||
uint32_t layer_count = 0;
|
||||
int eye;
|
||||
|
||||
@@ -1458,6 +1472,34 @@ int host_xr_end_frame(const struct halo_xr_submit *submit)
|
||||
layers[layer_count++] = (const XrCompositionLayerBaseHeader *)&crosshair;
|
||||
}
|
||||
|
||||
if (xr.frame_state.shouldRender && submit->name_count > 0 && xr.swapchains[HALO_XR_LAYER_NAMES].filled)
|
||||
{
|
||||
struct xr_swapchain *swapchain = &xr.swapchains[HALO_XR_LAYER_NAMES];
|
||||
int slot_height = swapchain->height / HALO_XR_MAXIMUM_NAMES;
|
||||
int name;
|
||||
|
||||
for (name = 0; name < submit->name_count && name < HALO_XR_MAXIMUM_NAMES; name++)
|
||||
{
|
||||
XrCompositionLayerQuad *quad_name = &names[name];
|
||||
|
||||
memset(quad_name, 0, sizeof(*quad_name));
|
||||
quad_name->type = XR_TYPE_COMPOSITION_LAYER_QUAD;
|
||||
quad_name->layerFlags = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
|
||||
quad_name->space = xr.local_space;
|
||||
quad_name->eyeVisibility = XR_EYE_VISIBILITY_BOTH;
|
||||
quad_name->subImage.swapchain = swapchain->handle;
|
||||
/* (slot 0 at the image's top: GL's rows run bottom up) */
|
||||
quad_name->subImage.imageRect.offset.x = 0;
|
||||
quad_name->subImage.imageRect.offset.y = swapchain->height - (name + 1) * slot_height;
|
||||
quad_name->subImage.imageRect.extent.width = swapchain->width;
|
||||
quad_name->subImage.imageRect.extent.height = slot_height;
|
||||
quad_name->size.width = submit->name_widths[name];
|
||||
quad_name->size.height = submit->name_widths[name] * NAME_SLOT_ASPECT;
|
||||
pose_to_xr(&quad_name->pose, &submit->name_poses[name]);
|
||||
layers[layer_count++] = (const XrCompositionLayerBaseHeader *)quad_name;
|
||||
}
|
||||
}
|
||||
|
||||
end.displayTime = xr.frame_state.predictedDisplayTime;
|
||||
end.environmentBlendMode = XR_ENVIRONMENT_BLEND_MODE_OPAQUE;
|
||||
end.layerCount = layer_count;
|
||||
|
||||
@@ -27,7 +27,10 @@ enum
|
||||
HALO_XR_LAYER_WRIST = 3, /* the motion tracker, on the left wrist */
|
||||
HALO_XR_LAYER_SCOPE = 4, /* the zoomed view, a disc over the weapon */
|
||||
HALO_XR_LAYER_CROSSHAIR = 5, /* the weapon's crosshair, where it aims */
|
||||
HALO_XR_LAYER_COUNT = 6,
|
||||
HALO_XR_LAYER_NAMES = 6, /* players' names, each a quad over a head */
|
||||
HALO_XR_LAYER_COUNT = 7,
|
||||
/* the names layer's slots, one a name, stacked from its top */
|
||||
HALO_XR_MAXIMUM_NAMES = 8,
|
||||
|
||||
/* host_xr_copy_layer's clear_alpha: the source's alpha kept, made
|
||||
opaque, or cut to a disc (premultiplied) */
|
||||
@@ -147,6 +150,12 @@ struct halo_xr_submit
|
||||
int crosshair;
|
||||
float crosshair_size;
|
||||
struct halo_xr_pose crosshair_pose;
|
||||
/* the names layer was filled: its first name_count slots, each shown
|
||||
this wide (metres, a slot's height following from its shape), here in
|
||||
LOCAL space, facing the eyes */
|
||||
int name_count;
|
||||
float name_widths[HALO_XR_MAXIMUM_NAMES];
|
||||
struct halo_xr_pose name_poses[HALO_XR_MAXIMUM_NAMES];
|
||||
};
|
||||
|
||||
#endif
|
||||
+22
-333
@@ -32,12 +32,6 @@ In the objective games a bot plays for the objective, fighting on the way:
|
||||
- king of the hill: to the hill, and around in it;
|
||||
- oddball: to the ball (taken as a weapon is), hunting whoever carries it;
|
||||
with it, away from the enemy, striking those who come near.
|
||||
|
||||
In a game of teams a bot plays with its team: it holds its fire while a
|
||||
teammate is in the line of it, takes on first the enemies near its
|
||||
teammates (people above all), escorts a teammate who carries the enemy's
|
||||
flag or the ball, and, with nothing to do, every other bot keeps near the
|
||||
nearest person on its team.
|
||||
*/
|
||||
|
||||
#include "cseries.h"
|
||||
@@ -117,12 +111,6 @@ struct bot
|
||||
real sidestep;
|
||||
/* whether it walks to a point this tick (not only weaving in a fight) */
|
||||
boolean walking;
|
||||
/* the paths to its goal not found in a row, and goals given up for a
|
||||
while on that account: following a person, a thing to pick up */
|
||||
short path_failures;
|
||||
long follow_again_time;
|
||||
long ignored_item_index;
|
||||
long ignored_item_time;
|
||||
real wander_yaw;
|
||||
short weave_phase;
|
||||
/* where it is going, and the way there */
|
||||
@@ -139,8 +127,6 @@ struct bot
|
||||
/* the objective, as it played it this tick: where it goes, whom it
|
||||
hunts first, and whether it carries the flag or ball (no firing) */
|
||||
boolean has_objective;
|
||||
/* the objective is a place to hold (the hill, its own flag's stand) */
|
||||
boolean holding;
|
||||
real_point3d objective;
|
||||
long objective_unit_index;
|
||||
boolean carrying;
|
||||
@@ -246,124 +232,6 @@ static boolean bot_can_see(
|
||||
from, &vector, unit_index, &collision);
|
||||
}
|
||||
|
||||
/* ---------- the team */
|
||||
|
||||
/* whether a player is a person (on a machine of its own, not a bot's) */
|
||||
static boolean bot_player_is_person(
|
||||
struct player_datum const *player)
|
||||
{
|
||||
return !network_game_server_is_bot_machine(player->network_player_data.machine_index);
|
||||
}
|
||||
|
||||
/* how much nearer an enemy at this point counts for being near the bot's
|
||||
teammates: up to 10 world units for one by a person, 6 by a bot */
|
||||
static real bot_threat_to_team(
|
||||
struct player_datum const *player,
|
||||
real_point3d const *enemy)
|
||||
{
|
||||
real threat = 0.0f;
|
||||
short index;
|
||||
|
||||
for (index = 0; index < MAXIMUM_TRACKED_PLAYERS; index++)
|
||||
{
|
||||
struct player_datum *mate = distributed_player(index);
|
||||
long unit_index;
|
||||
real_point3d head;
|
||||
real distance;
|
||||
real most;
|
||||
|
||||
if (!mate || mate == player || mate->team_index != player->team_index)
|
||||
continue;
|
||||
unit_index = distributed_living_unit(mate);
|
||||
if (unit_index == NONE)
|
||||
continue;
|
||||
unit_get_camera_position(unit_index, &head);
|
||||
distance = distance3d(enemy, &head);
|
||||
most = bot_player_is_person(mate) ? 10.0f : 6.0f;
|
||||
if (distance < 12.0f)
|
||||
threat = MAX(threat, most * (1.0f - distance / 12.0f));
|
||||
}
|
||||
return threat;
|
||||
}
|
||||
|
||||
/* whether a teammate stands in the line of fire to a point (nearer than
|
||||
it, within 0.8 world units of the line) */
|
||||
static boolean bot_teammate_in_line(
|
||||
struct player_datum const *player,
|
||||
real_point3d const *eye,
|
||||
real_point3d const *target)
|
||||
{
|
||||
real_vector3d line;
|
||||
real length;
|
||||
short index;
|
||||
|
||||
if (!game_engine_has_teams())
|
||||
return FALSE;
|
||||
vector_from_points3d(eye, target, &line);
|
||||
length = magnitude3d(&line);
|
||||
if (length < 0.01f)
|
||||
return FALSE;
|
||||
for (index = 0; index < MAXIMUM_TRACKED_PLAYERS; index++)
|
||||
{
|
||||
struct player_datum *mate = distributed_player(index);
|
||||
long unit_index;
|
||||
real_point3d center;
|
||||
real_vector3d offset;
|
||||
real along;
|
||||
real_point3d nearest;
|
||||
|
||||
if (!mate || mate == player || mate->team_index != player->team_index)
|
||||
continue;
|
||||
unit_index = distributed_living_unit(mate);
|
||||
if (unit_index == NONE)
|
||||
continue;
|
||||
unit_get_camera_position(unit_index, ¢er);
|
||||
center.z -= 0.25f;
|
||||
vector_from_points3d(eye, ¢er, &offset);
|
||||
along = dot_product3d(&offset, &line) / length;
|
||||
if (along <= 0.0f || along >= length)
|
||||
continue;
|
||||
nearest.x = eye->x + line.i * along / length;
|
||||
nearest.y = eye->y + line.j * along / length;
|
||||
nearest.z = eye->z + line.k * along / length;
|
||||
if (distance3d(&nearest, ¢er) < 0.8f)
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* the nearest person on the bot's team, alive (NONE: none) */
|
||||
static long bot_nearest_person(
|
||||
struct player_datum const *player,
|
||||
real_point3d const *position)
|
||||
{
|
||||
long best = NONE;
|
||||
real best_distance = 40.0f;
|
||||
short index;
|
||||
|
||||
for (index = 0; index < MAXIMUM_TRACKED_PLAYERS; index++)
|
||||
{
|
||||
struct player_datum *mate = distributed_player(index);
|
||||
long unit_index;
|
||||
real_point3d origin;
|
||||
real distance;
|
||||
|
||||
if (!mate || mate == player || mate->team_index != player->team_index || !bot_player_is_person(mate))
|
||||
continue;
|
||||
unit_index = distributed_living_unit(mate);
|
||||
if (unit_index == NONE)
|
||||
continue;
|
||||
object_get_origin(unit_index, &origin);
|
||||
distance = distance3d(position, &origin);
|
||||
if (distance < best_distance)
|
||||
{
|
||||
best_distance = distance;
|
||||
best = unit_index;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
/* the nearest enemy unit the bot can see, or NONE */
|
||||
static long bot_find_target(
|
||||
struct player_datum const *player,
|
||||
@@ -388,11 +256,6 @@ static long bot_find_target(
|
||||
continue;
|
||||
unit_get_camera_position(unit_index, &head);
|
||||
distance = distance3d(eye, &head);
|
||||
if (distance >= bots.sight_range)
|
||||
continue;
|
||||
/* (one near a teammate counts as nearer: helped first) */
|
||||
if (teams)
|
||||
distance -= bot_threat_to_team(player, &head);
|
||||
if (distance < best_distance && bot_can_see(player->unit_index, eye, &head))
|
||||
{
|
||||
best = unit_index;
|
||||
@@ -436,7 +299,6 @@ static boolean bot_find_path(
|
||||
if (goal_surface == NONE)
|
||||
{
|
||||
bots.fail_goal++;
|
||||
bot->path_failures++;
|
||||
return FALSE;
|
||||
}
|
||||
/* (a little wider than a biped: paths that keep off walls and corners) */
|
||||
@@ -471,11 +333,9 @@ static boolean bot_find_path(
|
||||
bot->path.valid = FALSE;
|
||||
bots.paths_failed++;
|
||||
bots.fail_search++;
|
||||
bot->path_failures++;
|
||||
return FALSE;
|
||||
}
|
||||
bots.paths_found += bot->path.valid != FALSE;
|
||||
bot->path_failures = 0;
|
||||
return bot->path.valid;
|
||||
}
|
||||
|
||||
@@ -916,88 +776,6 @@ static boolean bots_ctf_base(
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* near a teammate who carries something, a few world units off on the bot's
|
||||
side of it (an escort, not on the carrier's heels) */
|
||||
static void bot_escort_point(
|
||||
real_point3d const *position,
|
||||
real_point3d const *carried,
|
||||
real_point3d *point)
|
||||
{
|
||||
real dx = position->x - carried->x;
|
||||
real dy = position->y - carried->y;
|
||||
real length = (real)sqrt(dx * dx + dy * dy);
|
||||
|
||||
*point = *carried;
|
||||
if (length > 0.01f)
|
||||
{
|
||||
point->x += dx / length * 2.5f;
|
||||
point->y += dy / length * 2.5f;
|
||||
}
|
||||
}
|
||||
|
||||
/* Bots with one place to go spread out: each has a direction of its own
|
||||
(the golden angle on from the last bot's), a place of its own about a
|
||||
point to hold, and comes to a point from far off by a way of its own,
|
||||
wide of the others', going straight to it only for the last stretch. */
|
||||
|
||||
static real bot_spread_angle(
|
||||
long player_index)
|
||||
{
|
||||
return (real)DATUM_INDEX_TO_ABSOLUTE_INDEX(player_index) * 2.39996f;
|
||||
}
|
||||
|
||||
/* the bot's place about a point (radius: world units) */
|
||||
static void bot_spot_around(
|
||||
real_point3d const *center,
|
||||
long player_index,
|
||||
real radius,
|
||||
real_point3d *spot)
|
||||
{
|
||||
real angle = bot_spread_angle(player_index);
|
||||
|
||||
*spot = *center;
|
||||
spot->x += (real)cos(angle) * radius;
|
||||
spot->y += (real)sin(angle) * radius;
|
||||
}
|
||||
|
||||
/* its place about a point, or the point itself when there is no way to the
|
||||
place (in a wall, past a ledge) */
|
||||
static void bot_hold_spot(
|
||||
struct bot const *bot,
|
||||
real_point3d const *center,
|
||||
real radius,
|
||||
real_point3d *spot)
|
||||
{
|
||||
if (bot->path_failures >= 3)
|
||||
*spot = *center;
|
||||
else
|
||||
bot_spot_around(center, bot->player_index, radius, spot);
|
||||
}
|
||||
|
||||
/* where it heads for a point from where it is: from far off, out to a side
|
||||
of the straight way (its own side and width), in from 10 world units */
|
||||
static void bot_approach(
|
||||
struct bot const *bot,
|
||||
real_point3d const *position,
|
||||
real_point3d const *goal,
|
||||
real_point3d *point)
|
||||
{
|
||||
long index = DATUM_INDEX_TO_ABSOLUTE_INDEX(bot->player_index);
|
||||
real dx = goal->x - position->x;
|
||||
real dy = goal->y - position->y;
|
||||
real distance = (real)sqrt(dx * dx + dy * dy);
|
||||
real side = (index & 1 ? 1.0f : -1.0f) * (3.0f + (real)((index >> 1) % 3) * 1.5f);
|
||||
real share;
|
||||
|
||||
*point = *goal;
|
||||
/* (no way to the side: straight) */
|
||||
if (distance < 10.0f || bot->path_failures >= 2)
|
||||
return;
|
||||
share = MIN((distance - 10.0f) / 10.0f, 1.0f);
|
||||
point->x += -dy / distance * side * share;
|
||||
point->y += dx / distance * side * share;
|
||||
}
|
||||
|
||||
/* what the objective asks of the bot now (bot->has_objective and the rest) */
|
||||
static void bot_play_objective_now(
|
||||
struct bot *bot,
|
||||
@@ -1031,7 +809,6 @@ static void bot_play_objective_now(
|
||||
short index;
|
||||
|
||||
bot->has_objective = FALSE;
|
||||
bot->holding = FALSE;
|
||||
bot->objective_unit_index = NONE;
|
||||
bot->carrying = FALSE;
|
||||
if (type == game_engine_king)
|
||||
@@ -1046,12 +823,13 @@ static void bot_play_objective_now(
|
||||
dx = center.x - position->x;
|
||||
dy = center.y - position->y;
|
||||
bot->has_objective = TRUE;
|
||||
bot->holding = TRUE;
|
||||
/* (near: a place of its own on the hill; far: a way of its own) */
|
||||
if (dx * dx + dy * dy < 6.0f * 6.0f)
|
||||
bot_hold_spot(bot, ¢er, 1.2f, &bot->objective);
|
||||
else
|
||||
bot_approach(bot, position, ¢er, &bot->objective);
|
||||
bot->objective = center;
|
||||
/* (on the hill: about in it, not on its middle) */
|
||||
if (dx * dx + dy * dy < 1.5f * 1.5f)
|
||||
{
|
||||
bot->objective.x += (real)cos(bot->weave_phase * 0.05f) * 1.0f;
|
||||
bot->objective.y += (real)sin(bot->weave_phase * 0.05f) * 1.0f;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1098,42 +876,23 @@ static void bot_play_objective_now(
|
||||
bot->objective = own->position;
|
||||
return;
|
||||
}
|
||||
/* (every third guards its own: about the stand, or, every other one
|
||||
of them, ahead of it towards the enemy's) */
|
||||
/* (every third guards its own) */
|
||||
if ((DATUM_INDEX_TO_ABSOLUTE_INDEX(player_index) % 3) == 2 && bots_ctf_base(player->team_index, &base))
|
||||
{
|
||||
real_point3d enemy_base;
|
||||
|
||||
bot->has_objective = TRUE;
|
||||
bot->holding = TRUE;
|
||||
if (((DATUM_INDEX_TO_ABSOLUTE_INDEX(player_index) / 3) & 1) &&
|
||||
bots_ctf_base((player->team_index + 1) % 2, &enemy_base))
|
||||
bot->objective = base;
|
||||
if (distance3d(position, &base) < 4.0f)
|
||||
{
|
||||
real dx = enemy_base.x - base.x;
|
||||
real dy = enemy_base.y - base.y;
|
||||
real length = (real)sqrt(dx * dx + dy * dy);
|
||||
|
||||
bot->objective = base;
|
||||
if (length > 0.01f)
|
||||
{
|
||||
bot->objective.x += dx / length * 7.0f;
|
||||
bot->objective.y += dy / length * 7.0f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bot_hold_spot(bot, &base, 3.0f, &bot->objective);
|
||||
bot->objective.x += (real)cos(bot->weave_phase * 0.03f) * 3.0f;
|
||||
bot->objective.y += (real)sin(bot->weave_phase * 0.03f) * 3.0f;
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* theirs: to take it, or to escort the teammate carrying it */
|
||||
/* theirs: to take it, or to cover its carrier */
|
||||
if (enemy)
|
||||
{
|
||||
bot->has_objective = TRUE;
|
||||
if (enemy->carrier_player_index != NONE)
|
||||
bot_hold_spot(bot, &enemy->position, 3.0f, &bot->objective);
|
||||
else
|
||||
bot_approach(bot, position, &enemy->position, &bot->objective);
|
||||
bot->objective = enemy->position;
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1152,20 +911,13 @@ static void bot_play_objective_now(
|
||||
bot->carrying = TRUE;
|
||||
return;
|
||||
}
|
||||
/* (one a teammate carries: escorted, not chased) */
|
||||
/* (one a teammate carries: not to be chased) */
|
||||
if (item->carrier_player_index != NONE && game_engine_has_teams())
|
||||
{
|
||||
struct player_datum *carrier = player_try_and_get(item->carrier_player_index);
|
||||
|
||||
if (carrier && carrier->team_index == player->team_index)
|
||||
{
|
||||
if (!nearest)
|
||||
{
|
||||
bot->has_objective = TRUE;
|
||||
bot_hold_spot(bot, &item->position, 3.0f, &bot->objective);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
distance = distance3d(position, &item->position);
|
||||
if (distance < nearest_distance)
|
||||
@@ -1177,7 +929,7 @@ static void bot_play_objective_now(
|
||||
if (nearest)
|
||||
{
|
||||
bot->has_objective = TRUE;
|
||||
bot_approach(bot, position, &nearest->position, &bot->objective);
|
||||
bot->objective = nearest->position;
|
||||
if (nearest->carrier_player_index != NONE)
|
||||
{
|
||||
struct player_datum *carrier = player_try_and_get(nearest->carrier_player_index);
|
||||
@@ -1224,7 +976,6 @@ static void bot_think(
|
||||
real wanted_yaw;
|
||||
real wanted_pitch = 0.0f;
|
||||
boolean firing = FALSE;
|
||||
boolean following = FALSE;
|
||||
real moved;
|
||||
|
||||
csmemset(action, 0, sizeof(*action));
|
||||
@@ -1346,13 +1097,13 @@ static void bot_think(
|
||||
}
|
||||
bot->weave_phase++;
|
||||
/* (a good weapon or powerup close by: taken in the fight too) */
|
||||
if (!bot->carrying && !bot->has_objective && (game_time_get() - bot->item_look_time >= ITEM_LOOK_TICKS / 2 ||
|
||||
if (!bot->carrying && (game_time_get() - bot->item_look_time >= ITEM_LOOK_TICKS / 2 ||
|
||||
game_time_get() < bot->item_look_time))
|
||||
{
|
||||
bot->item_look_time = game_time_get();
|
||||
bot->item_index = bot_find_item(unit, &position, 10.0f, 4.0f);
|
||||
}
|
||||
if (bot->item_index != NONE && !bot->carrying && !bot->has_objective && object_try_and_get(bot->item_index) &&
|
||||
if (bot->item_index != NONE && !bot->carrying && object_try_and_get(bot->item_index) &&
|
||||
bot_item_worth(unit, bot->item_index) > 0.0f)
|
||||
{
|
||||
real_point3d item_position;
|
||||
@@ -1402,13 +1153,6 @@ static void bot_think(
|
||||
firing = !bot->carrying && distance < BOT_FIRE_RANGE &&
|
||||
fabsf(bot_angle_difference(wanted_yaw, bot->yaw)) < BOT_FIRE_CONE &&
|
||||
fabsf(wanted_pitch - bot->pitch) < BOT_FIRE_CONE;
|
||||
/* (a teammate in the line of fire: held, and a step aside for a
|
||||
clear shot) */
|
||||
if (firing && bot_teammate_in_line(player, &eye, &head))
|
||||
{
|
||||
firing = FALSE;
|
||||
action->throttle.j = (bot->weave_phase / 30) & 1 ? 1.0f : -1.0f;
|
||||
}
|
||||
/* (a melee blow when it is upon it) */
|
||||
if (distance < 1.0f)
|
||||
SET_FLAG(action->control_flags, _unit_control_use_equipment_bit, TRUE);
|
||||
@@ -1457,8 +1201,6 @@ static void bot_think(
|
||||
long item = bot_find_item(unit, &position, BOT_ITEM_RANGE, 0.0f);
|
||||
|
||||
bot->item_look_time = game_time_get();
|
||||
if (item == bot->ignored_item_index && game_time_get() - bot->ignored_item_time < 600)
|
||||
item = NONE;
|
||||
if (item != bot->item_index)
|
||||
{
|
||||
bot->item_index = item;
|
||||
@@ -1473,16 +1215,8 @@ static void bot_think(
|
||||
}
|
||||
if (bot->item_index != NONE && !bot->has_objective)
|
||||
{
|
||||
/* (taken or gone, or no way to it: on) */
|
||||
if (bot->path_failures >= 3)
|
||||
{
|
||||
bot->ignored_item_index = bot->item_index;
|
||||
bot->ignored_item_time = game_time_get();
|
||||
bot->path_failures = 0;
|
||||
bot->item_index = NONE;
|
||||
bot->has_goal = FALSE;
|
||||
}
|
||||
else if (!object_try_and_get(bot->item_index) || bot_item_worth(unit, bot->item_index) <= 0.0f)
|
||||
/* (taken or gone: on) */
|
||||
if (!object_try_and_get(bot->item_index) || bot_item_worth(unit, bot->item_index) <= 0.0f)
|
||||
{
|
||||
bot->item_index = NONE;
|
||||
bot->has_goal = FALSE;
|
||||
@@ -1495,56 +1229,12 @@ static void bot_think(
|
||||
bot_take_item(bot, player, unit, action);
|
||||
}
|
||||
}
|
||||
/* (in a team, every other bot with nothing to do keeps near the
|
||||
nearest person on its team) */
|
||||
following = FALSE;
|
||||
if (bot->item_index == NONE && !bot->has_objective && game_engine_has_teams() &&
|
||||
(DATUM_INDEX_TO_ABSOLUTE_INDEX(bot->player_index) & 1) == 0 &&
|
||||
game_time_get() >= bot->follow_again_time)
|
||||
{
|
||||
long person = bot_nearest_person(player, &position);
|
||||
|
||||
if (person != NONE)
|
||||
{
|
||||
real_point3d origin;
|
||||
|
||||
following = TRUE;
|
||||
object_get_origin(person, &origin);
|
||||
/* (near: where it is, not on top of them) */
|
||||
if (distance3d(&position, &origin) > 6.0f)
|
||||
bot_escort_point(&position, &origin, &bot->goal);
|
||||
else
|
||||
bot->goal = position;
|
||||
bot->has_goal = TRUE;
|
||||
bot->goal_time = game_time_get();
|
||||
/* (no way to them, as up where only a teleporter goes: not for
|
||||
ten seconds) */
|
||||
if (bot->path_failures >= 3)
|
||||
{
|
||||
bot->follow_again_time = game_time_get() + 300;
|
||||
bot->path_failures = 0;
|
||||
following = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* hunts, or roams: along its way, looking where it goes */
|
||||
if (bot->item_index == NONE && !bot->has_objective && !following &&
|
||||
(!bot->has_goal || game_time_get() - bot->goal_time > 90 || bot->path_failures >= 3 ||
|
||||
if (bot->item_index == NONE && !bot->has_objective &&
|
||||
(!bot->has_goal || game_time_get() - bot->goal_time > 90 ||
|
||||
distance3d(&position, &bot->goal) < BOT_GOAL_RADIUS))
|
||||
{
|
||||
boolean unreachable = bot->path_failures >= 3;
|
||||
|
||||
bot_choose_goal(bot, player, &position);
|
||||
/* (no way to the last: somewhere near at random instead) */
|
||||
if (unreachable)
|
||||
{
|
||||
real angle = bot_random() * 2.0f * _pi;
|
||||
|
||||
bot->goal = position;
|
||||
bot->goal.x += (real)cos(angle) * 6.0f;
|
||||
bot->goal.y += (real)sin(angle) * 6.0f;
|
||||
}
|
||||
bot->path_failures = 0;
|
||||
}
|
||||
wanted_yaw = bot->wander_yaw;
|
||||
if (bot_next_point(bot, player->unit_index, &position, &point))
|
||||
@@ -1673,7 +1363,6 @@ static struct bot *bot_get(
|
||||
free_bot->player_index = player_index;
|
||||
free_bot->target_unit_index = NONE;
|
||||
free_bot->item_index = NONE;
|
||||
free_bot->ignored_item_index = NONE;
|
||||
}
|
||||
return free_bot;
|
||||
}
|
||||
|
||||
@@ -140,6 +140,15 @@ out (halo_vr_scope_pass). */
|
||||
int halo_vr_scope(short local_player_index, float magnification, float position[3], float forward[3], float up[3],
|
||||
float *vertical_field_of_view);
|
||||
int halo_vr_scope_pass(void);
|
||||
/* Players' names over their heads (hud.c, render.c): whether they are drawn
|
||||
apart this frame; the slot a name is drawn into (left, top, right, bottom
|
||||
of the game's 640x480); a name's place (world units, over the head),
|
||||
giving its slot (-1: no more); and the slots, drawn on the cleared back
|
||||
buffer, taken (it is cleared again) */
|
||||
int halo_vr_names_apart(void);
|
||||
void halo_vr_name_slot(int slot, short bounds[4]);
|
||||
int halo_vr_add_name(const float point[3]);
|
||||
void halo_vr_capture_names(void);
|
||||
/* how much higher than a rifle's the weapon in hand has its scope's disc
|
||||
(metres; render.c, before halo_vr_scope) */
|
||||
void halo_vr_set_scope_raise(float metres);
|
||||
|
||||
@@ -134,6 +134,11 @@ static struct
|
||||
float scope_size;
|
||||
int crosshair;
|
||||
int crosshair_captured; /* this frame (halo_vr_capture_crosshair) */
|
||||
/* players' names this frame (halo_vr_add_name), and whether their
|
||||
slots were taken (halo_vr_capture_names) */
|
||||
int name_count;
|
||||
float name_points[HALO_XR_MAXIMUM_NAMES][3];
|
||||
int names_captured;
|
||||
/* the barrel of the weapon as drawn (halo_vr_set_barrel): where shots,
|
||||
the crosshair and the laser start */
|
||||
float barrel[3];
|
||||
@@ -242,6 +247,7 @@ the target), keeping the size it has in the HUD: this part of the HUD. */
|
||||
static void cross3(const float a[3], const float b[3], float out[3]);
|
||||
static float normalize3(float v[3]);
|
||||
static int crosshair_pose(struct halo_xr_pose *pose, float *size);
|
||||
static int name_pose(const float point[3], struct halo_xr_pose *pose, float *width);
|
||||
static int weapon_hand_tracked(short local_player_index);
|
||||
static void controller_axes(float forward[3], float up[3], float right[3]);
|
||||
static void hand_offset(float out[3]);
|
||||
@@ -1021,6 +1027,8 @@ void halo_vr_frame_begin(void)
|
||||
vr.eyes_captured = 0;
|
||||
vr.scope_captured = 0;
|
||||
vr.crosshair_captured = 0;
|
||||
vr.name_count = 0;
|
||||
vr.names_captured = 0;
|
||||
vr.overlay_mode = HALO_XR_OVERLAY_SCREEN;
|
||||
vr.overlay_blend = 0;
|
||||
if (vr.frame.recentred)
|
||||
@@ -1087,6 +1095,20 @@ void halo_vr_present(unsigned int back_buffer_texture)
|
||||
weapon aims */
|
||||
if (vr.crosshair_captured && vr.overlay_mode == HALO_XR_OVERLAY_HEAD_LOCKED)
|
||||
submit.crosshair = crosshair_pose(&submit.crosshair_pose, &submit.crosshair_size);
|
||||
/* the names, each over its player's head */
|
||||
if (vr.names_captured && submit.eyes && vr.overlay_mode == HALO_XR_OVERLAY_HEAD_LOCKED)
|
||||
{
|
||||
int name;
|
||||
|
||||
for (name = 0; name < vr.name_count; name++)
|
||||
{
|
||||
if (name_pose(vr.name_points[name], &submit.name_poses[submit.name_count],
|
||||
&submit.name_widths[submit.name_count]))
|
||||
{
|
||||
submit.name_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (vr.scope_captured && submit.eyes)
|
||||
{
|
||||
submit.scope = 1;
|
||||
@@ -1947,6 +1969,82 @@ static int crosshair_pose(struct halo_xr_pose *pose, float *size)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ---------- players' names
|
||||
|
||||
Names over the heads (hud.c) are drawn into slots of a region of the back
|
||||
buffer, one under another, before the HUD, and each slot is shown on a quad
|
||||
of its own over its player's head, facing the eyes, as wide as the name
|
||||
looks at the HUD's distance: in VR the HUD is a screen at one distance,
|
||||
where names drawn on it hung before the eyes. */
|
||||
|
||||
#define NAME_SLOT_LEFT 240
|
||||
#define NAME_SLOT_WIDTH 160
|
||||
#define NAME_SLOT_HEIGHT 30
|
||||
/* how large a name looks against the HUD's text (smaller: over a head, not
|
||||
on the screen before the eyes) */
|
||||
#define NAME_SCALE 0.6f
|
||||
|
||||
int halo_vr_names_apart(void)
|
||||
{
|
||||
return vr.active && halo_vr_stereo_frame();
|
||||
}
|
||||
|
||||
void halo_vr_name_slot(int slot, short bounds[4])
|
||||
{
|
||||
bounds[0] = NAME_SLOT_LEFT;
|
||||
bounds[1] = (short)(slot * NAME_SLOT_HEIGHT);
|
||||
bounds[2] = NAME_SLOT_LEFT + NAME_SLOT_WIDTH;
|
||||
bounds[3] = (short)((slot + 1) * NAME_SLOT_HEIGHT);
|
||||
}
|
||||
|
||||
int halo_vr_add_name(const float point[3])
|
||||
{
|
||||
int slot = vr.name_count;
|
||||
|
||||
if (slot >= HALO_XR_MAXIMUM_NAMES)
|
||||
return -1;
|
||||
memcpy(vr.name_points[slot], point, sizeof(vr.name_points[slot]));
|
||||
vr.name_count++;
|
||||
return slot;
|
||||
}
|
||||
|
||||
void halo_vr_capture_names(void)
|
||||
{
|
||||
if (vr.name_count > 0)
|
||||
{
|
||||
vr.names_captured = host_xr_copy_layer_region(HALO_XR_LAYER_NAMES, d3d8_back_buffer_texture(),
|
||||
HALO_XR_COPY_ALPHA, NAME_SLOT_LEFT / 640.0f, 0.0f, (NAME_SLOT_LEFT + NAME_SLOT_WIDTH) / 640.0f,
|
||||
HALO_XR_MAXIMUM_NAMES * NAME_SLOT_HEIGHT / 480.0f);
|
||||
}
|
||||
d3d8_clear_back_buffer(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
static int name_pose(const float point[3], struct halo_xr_pose *pose, float *width)
|
||||
{
|
||||
static const float world_up[3] = { 0.0f, 1.0f, 0.0f };
|
||||
float x[3], y[3], z[3];
|
||||
float distance;
|
||||
float angle;
|
||||
int axis;
|
||||
|
||||
world_to_local(point, pose->position);
|
||||
for (axis = 0; axis < 3; axis++)
|
||||
z[axis] = vr.frame.head.position[axis] - pose->position[axis];
|
||||
distance = normalize3(z);
|
||||
/* (facing the eyes, upright) */
|
||||
if (distance < 0.05f)
|
||||
return 0;
|
||||
cross3(world_up, z, x);
|
||||
if (normalize3(x) < 1e-4f)
|
||||
return 0;
|
||||
cross3(z, x, y);
|
||||
quaternion_from_axes(x, y, z, pose->orientation);
|
||||
/* (as wide as the slot looks on the HUD, smaller) */
|
||||
angle = (float)NAME_SLOT_WIDTH / 640.0f * vr.hud_width / vr.hud_distance * NAME_SCALE;
|
||||
*width = 2.0f * distance * tanf(angle * 0.5f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ---------- the scope
|
||||
|
||||
Zoomed in, the weapon shows its view on a disc over the barrel, like a
|
||||
@@ -2175,6 +2273,10 @@ int halo_vr_scope(short local_player_index, float magnification, float position[
|
||||
return 0;
|
||||
}
|
||||
int halo_vr_scope_pass(void) { return 0; }
|
||||
int halo_vr_names_apart(void) { return 0; }
|
||||
void halo_vr_name_slot(int slot, short bounds[4]) { (void)slot; (void)bounds; }
|
||||
int halo_vr_add_name(const float point[3]) { (void)point; return -1; }
|
||||
void halo_vr_capture_names(void) {}
|
||||
void halo_vr_set_scope_raise(float metres) { (void)metres; }
|
||||
void halo_vr_capture_scope(float left, float top, float right, float bottom)
|
||||
{
|
||||
|
||||
+56
-13
@@ -1033,13 +1033,6 @@ static short hud_player_names_setting(
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HALO_ANDROID
|
||||
/* (the VR port's: in VR the HUD is a screen at a fixed distance before
|
||||
the eyes, so names drawn on it hang there, not over the heads; none
|
||||
until they are drawn into each eye's picture) */
|
||||
if (halo_vr_active())
|
||||
return _player_names_none;
|
||||
#endif
|
||||
return setting;
|
||||
}
|
||||
|
||||
@@ -1134,7 +1127,8 @@ static void hud_draw_player_name(
|
||||
long player_index,
|
||||
boolean ally,
|
||||
boolean indicator,
|
||||
real enemy_range)
|
||||
real enemy_range,
|
||||
boolean vr_apart)
|
||||
{
|
||||
struct player_datum const *player = player_get(player_index);
|
||||
long font_index = hud_get_font_index();
|
||||
@@ -1164,10 +1158,35 @@ static void hud_draw_player_name(
|
||||
/* (where the game draws a teammate's triangle) */
|
||||
head_position.z += 0.30000001f;
|
||||
matrix4x3_transform_point(&render.frustum.world_to_view, &head_position, &view_position);
|
||||
if (!render_camera_view_to_screen(&render.camera, &render.frustum, &view_position, &screen_position))
|
||||
return;
|
||||
x = (short)fast_ftol(screen_position.x) - render.camera.viewport_bounds.x0;
|
||||
y = (short)fast_ftol(screen_position.y) - render.camera.viewport_bounds.y0;
|
||||
#ifdef HALO_ANDROID
|
||||
if (vr_apart)
|
||||
{
|
||||
/* (VR: in a slot of its own, shown over the head: halo_vr.h) */
|
||||
float point[3];
|
||||
short slot_bounds[4];
|
||||
int slot;
|
||||
|
||||
point[0] = head_position.x;
|
||||
point[1] = head_position.y;
|
||||
point[2] = head_position.z + (indicator ? 0.15f : 0.0f);
|
||||
slot = halo_vr_add_name(point);
|
||||
if (slot < 0)
|
||||
return;
|
||||
halo_vr_name_slot(slot, slot_bounds);
|
||||
x = (short)((slot_bounds[0] + slot_bounds[2]) / 2);
|
||||
y = (short)(slot_bounds[3] - 4);
|
||||
/* (an ally's whole at any distance it is drawn at) */
|
||||
view_position.z = -1.0f;
|
||||
indicator = FALSE;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (!render_camera_view_to_screen(&render.camera, &render.frustum, &view_position, &screen_position))
|
||||
return;
|
||||
x = (short)fast_ftol(screen_position.x) - render.camera.viewport_bounds.x0;
|
||||
y = (short)fast_ftol(screen_position.y) - render.camera.viewport_bounds.y0;
|
||||
}
|
||||
if (indicator)
|
||||
{
|
||||
struct bitmap_data *bitmap = bitmap_group_get_bitmap_from_sequence(
|
||||
@@ -1209,8 +1228,32 @@ static void hud_draw_player_name(
|
||||
return;
|
||||
}
|
||||
|
||||
static void hud_draw_player_names_now(
|
||||
boolean vr_apart);
|
||||
|
||||
static void hud_draw_player_names(
|
||||
void)
|
||||
{
|
||||
#ifdef HALO_ANDROID
|
||||
/* (VR: apart, before the HUD: hud_draw_player_names_vr) */
|
||||
if (halo_vr_active())
|
||||
return;
|
||||
#endif
|
||||
hud_draw_player_names_now(FALSE);
|
||||
}
|
||||
|
||||
#ifdef HALO_ANDROID
|
||||
/* VR: the names drawn into their slots, each then shown over its player's
|
||||
head (render.c, before the HUD; halo_vr_names_apart) */
|
||||
void hud_draw_player_names_vr(
|
||||
void)
|
||||
{
|
||||
hud_draw_player_names_now(TRUE);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void hud_draw_player_names_now(
|
||||
boolean vr_apart)
|
||||
{
|
||||
short setting = hud_player_names_setting();
|
||||
long player_index = local_player_get_player_index(render.local_player_index);
|
||||
@@ -1235,7 +1278,7 @@ static void hud_draw_player_names(
|
||||
continue;
|
||||
if ((ally && setting == _player_names_enemies) || (!ally && setting == _player_names_allies))
|
||||
continue;
|
||||
hud_draw_player_name(iterator.datum_index, ally, ally && indicators, enemy_range);
|
||||
hud_draw_player_name(iterator.datum_index, ally, ally && indicators, enemy_range, vr_apart);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
@@ -29,6 +29,11 @@ struct hud_scripted_globals_definition
|
||||
/* ---------- prototypes/HUD.C */
|
||||
|
||||
#ifdef HALO_ANDROID
|
||||
#ifdef HALO_ANDROID
|
||||
/* VR: players' names drawn into their slots (halo_vr_names_apart) */
|
||||
void hud_draw_player_names_vr(
|
||||
void);
|
||||
#endif
|
||||
void hud_draw_crosshair(
|
||||
void);
|
||||
#endif
|
||||
|
||||
@@ -853,6 +853,14 @@ static void render_vr_overlay(
|
||||
parameters.suppress_clear = TRUE;
|
||||
parameters.window_index = render.window_index;
|
||||
|
||||
if (!menus_active && halo_vr_names_apart())
|
||||
{
|
||||
/* the players' names, each to be shown over its head */
|
||||
rasterizer_window_begin(¶meters);
|
||||
hud_draw_player_names_vr();
|
||||
rasterizer_window_end();
|
||||
halo_vr_capture_names();
|
||||
}
|
||||
if (!menus_active && halo_vr_crosshair_apart())
|
||||
{
|
||||
/* the weapon's crosshair alone, taken to where the weapon aims */
|
||||
|
||||
Reference in new issue
Block a user