Compare commits

..
Author SHA1 Message Date
Stefan MaierandClaude Opus 5.5 867855d388 Bot drivers see walls and rocks ahead, back off when stuck, go round teammates
Driving a jeep or a scout, a bot looks ahead (farther the faster) along the
way it turns: a wall or a rock there (not ground it can drive up) is passed
on the most open side nearest its way, slower, and boxed in it backs off.
Stuck is now making no way along its heading for a second and a half, which
spinning wheels no longer hide. A teammate in the way is gone round slowly
on the other side instead of waited for.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 13:25:15 +02:00
Stefan MaierandClaude Opus 5.5 9e7fd75f57 Bots: a vehicle left stuck is left alone a while; every third bot follows a person
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 11:41:40 +02:00
Stefan MaierandClaude Opus 5.5 aedf5ff9bc Bot drivers wait for those coming to get in, and brake for teammates
Just in, a bot driver waits up to six seconds while a bot goes for its
vehicle or a person of its team stands near it with a gun's seat free; it
brakes (backing, if fast) for a teammate on foot in its way. A bot takes a
vehicle only when the nearest enemy (or the objective) is a long way off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 11:39:24 +02:00
Stefan MaierandClaude Opus 5.5 fe160e9dbe Bots man turrets while an enemy is about
A turret near a bot (15 world units) is manned while an enemy is within 35
of it, and left once there has been no one to shoot for ten seconds; at it
the bot aims and fires as at a vehicle's gun. The map's vehicles are named
in the log once a game.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 11:23:49 +02:00
Stefan MaierandClaude Opus 5.5 12c97ffa85 Bots take vehicles: drive, man the gun, ride along; and race
A bot whose way is long takes an empty vehicle it can drive near it (a
Warthog, a Ghost, a Scorpion), walking to the driver's door and standing
there until the game offers the seat. Driving, it follows a vehicle's path
(from the vehicle's surface, wider, its steps further apart), turning a
Warthog or a Ghost by facing where it goes and pushing a Scorpion there from
where its gun faces; it runs an enemy down, circles one with a gunner
aboard, fires a Ghost's and a Scorpion's guns, backs off what it is stuck
on, roams between the map's spawn points, and gets out at the objective,
overturned, stuck again and again, or with an enemy close while it stands.
In a game of teams a bot mans the gun of a teammate's vehicle, a person's
first (or rides along with a person), aims and fires it, and gets out once
no one drives. Overturned vehicles near it are turned upright.

In a race a bot heads for the flag it is to touch next
(game_engine_race_next_flag), in a vehicle if it can have one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 16:48:59 +02:00
7 changed files with 1186 additions and 95 deletions

No files matched your search

+1103 -10
View File
File diff suppressed because it is too large. Load diff
+2 -28
View File
@@ -2139,10 +2139,6 @@ static struct
int valid;
float x, y;
float reported_x, reported_y;
/* (a stick moved the menu's choice: the pointer, not moved far from
here since, leaves it be) */
int stick_quiet;
float stick_x, stick_y;
int hand;
int trigger_down[HALO_XR_HAND_COUNT];
int clicks;
@@ -2237,31 +2233,9 @@ int halo_vr_menu_pointer(int *x, int *y, int *click_x, int *click_y, int *moved,
return 0;
*x = (int)menu_pointer.x;
*y = (int)menu_pointer.y;
/* (a stick pushed: what it chooses stays chosen until the pointer
moves well away) */
{
int index;
for (index = 0; index < HALO_XR_HAND_COUNT; index++)
{
const struct halo_xr_hand *hand = &vr.frame.hands[index];
if (hand->active && (fabsf(hand->thumbstick[0]) > 0.4f || fabsf(hand->thumbstick[1]) > 0.4f))
{
menu_pointer.stick_quiet = 1;
menu_pointer.stick_x = menu_pointer.x;
menu_pointer.stick_y = menu_pointer.y;
}
}
if (menu_pointer.stick_quiet && (fabsf(menu_pointer.x - menu_pointer.stick_x) > 25.0f ||
fabsf(menu_pointer.y - menu_pointer.stick_y) > 25.0f))
{
menu_pointer.stick_quiet = 0;
}
}
/* (moved past a hand's tremor: a few pixels) */
*moved = !menu_pointer.stick_quiet && (fabsf(menu_pointer.x - menu_pointer.reported_x) >= 3.0f ||
fabsf(menu_pointer.y - menu_pointer.reported_y) >= 3.0f);
*moved = fabsf(menu_pointer.x - menu_pointer.reported_x) >= 3.0f ||
fabsf(menu_pointer.y - menu_pointer.reported_y) >= 3.0f;
if (*moved)
{
menu_pointer.reported_x = menu_pointer.x;
+37
View File
@@ -1670,3 +1670,40 @@ boolean game_engine_race_read_network_state(
csmemcpy(race_events.best_laps, state.best_laps, sizeof(race_events.best_laps));
return TRUE;
}
boolean game_engine_race_next_flag(
long player_index,
real_point3d const *from,
real_point3d *position)
{
struct scenario *scenario = global_scenario_get();
real best_distance = REAL_MAX;
boolean found = FALSE;
long itr;
if (!scenario || DATUM_INDEX_TO_ABSOLUTE_INDEX(player_index) >= MULTIPLAYER_MAXIMUM_PLAYERS)
return FALSE;
for (itr = 0; itr < scenario->netgame_flags.count; itr++)
{
struct scenario_netgame_flag *flag = TAG_BLOCK_GET_ELEMENT(
&scenario->netgame_flags,
itr,
struct scenario_netgame_flag);
real distance;
if (flag->type != _netgame_flag_race_track ||
!TEST_FLAG(race_globals.lap_completed_value, flag->team_index) ||
!can_touch_team(player_index, flag->team_index))
{
continue;
}
distance = distance3d(from, &flag->position);
if (distance < best_distance)
{
best_distance = distance;
*position = flag->position;
found = TRUE;
}
}
return found;
}
+7
View File
@@ -18,6 +18,13 @@ struct race_globals;
void race_flags_make_unique(
void);
/* port: the race flag a player is to touch next, the one of those it may
touch nearest the point (the VR port's bots, port/linux/game/bots.c);
FALSE: none */
boolean game_engine_race_next_flag(
long player_index,
real_point3d const *from,
real_point3d *position);
/* ---------- globals */
-57
View File
@@ -5751,57 +5751,6 @@ static void ui_mouse_list_directions(
return;
}
#ifdef HALO_ANDROID
/* VR: a click beside a list's slots or a value's box, along the way it
steps, where its arrows are drawn: a step back or on (TRUE: taken) */
static boolean ui_mouse_click_beside_list(
short x,
short y)
{
struct widget_instance *list = NULL;
rectangle2d bounds;
long index;
short back, forward;
boolean across;
for (index = 0; index < ui_mouse_target_count; index++)
{
struct ui_mouse_target const *target = &ui_mouse_targets[index];
struct widget_instance *owner = target->kind == _ui_mouse_target_list_slot ? target->widget->parent :
target->kind == _ui_mouse_target_value ? target->widget : NULL;
if (!owner)
continue;
if (!list)
{
list = owner;
bounds = target->bounds;
}
else if (owner == list)
{
bounds.x0 = MIN(bounds.x0, target->bounds.x0);
bounds.y0 = MIN(bounds.y0, target->bounds.y0);
bounds.x1 = MAX(bounds.x1, target->bounds.x1);
bounds.y1 = MAX(bounds.y1, target->bounds.y1);
}
}
if (!list)
return FALSE;
ui_mouse_list_directions(list, &back, &forward);
across = back == _widget_event_dpad_left;
if (across ? y < bounds.y0 - 24 || y >= bounds.y1 + 24 : x < bounds.x0 - 24 || x >= bounds.x1 + 24)
return FALSE;
ui_mouse_give_focus(list);
if (across ? x < bounds.x0 && x >= bounds.x0 - 80 : y < bounds.y0 && y >= bounds.y0 - 48)
ui_mouse_press(back);
else if (across ? x >= bounds.x1 && x < bounds.x1 + 80 : y >= bounds.y1 && y < bounds.y1 + 48)
ui_mouse_press(forward);
else
return FALSE;
return TRUE;
}
#endif
/* steps a list that shows several items to the one shown in a slot, as
pressing the d-pad that many times would */
static void ui_mouse_step_list_to_slot(
@@ -6591,12 +6540,6 @@ static void ui_widgets_process_mouse(
{
long index;
#ifdef HALO_ANDROID
/* (VR: beside a list, on its arrows) */
if (halo_vr_active() && ui_mouse_click_beside_list(ui_mouse_click_x, ui_mouse_click_y))
index = 0;
else
#endif
/* a screen with nothing to pick (a message to dismiss): the
click is its A */
for (index = 0; index < ui_mouse_target_count; index++)
+21
View File
@@ -853,6 +853,27 @@ done:
return !no_vehicles_moving;
}
short vehicle_bot_drive_kind(
long vehicle_index)
{
struct vehicle_datum *vehicle = vehicle_datum_get(vehicle_index);
struct vehicle_definition *definition = vehicle_specific_definition_get(
vehicle->definition_index);
switch (definition->vehicle_type)
{
case _vehicle_type_human_jeep:
case _vehicle_type_alien_scout:
return _vehicle_bot_drive_facing;
case _vehicle_type_human_tank:
return _vehicle_bot_drive_relative;
case _vehicle_type_turret:
return _vehicle_bot_drive_turret;
default:
return _vehicle_bot_drive_none;
}
}
#ifdef HALO_ANDROID
boolean vehicle_vr_steered_by_facing(
long vehicle_index)
+16
View File
@@ -81,6 +81,22 @@ void vehicle_render_debug(
/* ---------- public code */
/* port: how the VR port's bots (port/linux/game/bots.c) drive a vehicle:
turned to where its driver faces (a jeep, a scout), moved where he pushes
from where he faces (a tank), manned where it stands (a turret), or not
at all (the rest) */
enum
{
_vehicle_bot_drive_none = 0,
_vehicle_bot_drive_facing,
_vehicle_bot_drive_relative,
_vehicle_bot_drive_turret,
};
short vehicle_bot_drive_kind(
long vehicle_index);
boolean vehicle_is_flipped(
long vehicle_index);
#ifdef HALO_ANDROID
/* VR: whether the vehicle's driver steers it by where he faces (the jeep,
boat, plane, scout and fighter: the right stick steers them), as opposed to