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
8 changed files with 1191 additions and 71 deletions

No files matched your search

+1103 -10
View File
File diff suppressed because it is too large. Load diff
+1 -11
View File
@@ -813,15 +813,6 @@ In the menus the buttons are the Xbox's by position: A accepts, B goes back. */
int halo_vr_controllers(struct halo_xr_hand hands[HALO_XR_HAND_COUNT], int *menus);
int halo_vr_wheel_held(void);
/* a click that stands for the pad's A (ui_widget.c: the screen where
controllers join by pressing it), held a moment */
static Uint64 vr_pad_a_until;
void halo_vr_pulse_pad_a(void)
{
vr_pad_a_until = SDL_GetTicks() + 120;
}
static SHORT vr_stick(float value)
{
if (value > 1.0f)
@@ -868,8 +859,7 @@ static void vr_gamepad_state(XINPUT_GAMEPAD *pad)
if (abs(value) > abs(pad->sThumbRX)) pad->sThumbRX = value;
value = vr_stick(right->thumbstick[1]);
if (abs(value) > abs(pad->sThumbRY)) pad->sThumbRY = value;
merge_button(pad, XINPUT_GAMEPAD_A, (right->buttons & HALO_XR_BUTTON_A) != 0 ||
SDL_GetTicks() < vr_pad_a_until);
merge_button(pad, XINPUT_GAMEPAD_A, (right->buttons & HALO_XR_BUTTON_A) != 0);
merge_button(pad, XINPUT_GAMEPAD_B, (right->buttons & HALO_XR_BUTTON_B) != 0);
merge_button(pad, XINPUT_GAMEPAD_X, (left->buttons & HALO_XR_BUTTON_A) != 0);
merge_button(pad, XINPUT_GAMEPAD_Y, (left->buttons & HALO_XR_BUTTON_B) != 0);
+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 */
+4 -37
View File
@@ -961,11 +961,6 @@ static void hud_draw_players(
long player_index = local_player_get_player_index(render.local_player_index);
long team_index = player_get(player_index)->team_index;
#ifdef HALO_ANDROID
/* (VR: over the heads, with the names: hud_draw_player_name) */
if (halo_vr_names_apart())
return;
#endif
if (player_index != NONE)
{
/* the native builds' sessions hold more than 16 players */
@@ -1140,7 +1135,6 @@ static void hud_draw_player_name(
long player_index,
boolean ally,
boolean indicator,
boolean name_shown,
real enemy_range,
boolean vr_apart)
{
@@ -1182,7 +1176,7 @@ static void hud_draw_player_name(
point[0] = head_position.x;
point[1] = head_position.y;
point[2] = head_position.z + (indicator ? 0.06f : 0.0f);
point[2] = head_position.z + (indicator ? 0.15f : 0.0f);
slot = halo_vr_add_name(point);
if (slot < 0)
return;
@@ -1191,31 +1185,7 @@ static void hud_draw_player_name(
y = (short)(slot_bounds[3] - 4);
/* (an ally's whole at any distance it is drawn at) */
view_position.z = -1.0f;
if (indicator)
{
/* (a teammate's triangle at the slot's foot, the name over it:
the game's, drawn on the HUD, would hang before the eyes) */
struct bitmap_data *bitmap = bitmap_group_get_bitmap_from_sequence(
interface_get_tag_index(_interface_bitmap_multiplayer_hud), 0, 0);
if (bitmap && _texture_cache_bitmap_get_hardware_format(bitmap, FALSE, TRUE))
{
point2d tip;
real_rectangle2d whole;
tip.x = x;
tip.y = (short)(slot_bounds[3] - 2);
whole.x0 = 0.0f;
whole.x1 = 1.0f;
whole.y0 = 0.0f;
whole.y1 = 1.0f;
interface_draw_bitmap(bitmap, &tip, &whole, 0.6f, 0.0f, 1.0f);
y = (short)(tip.y - bitmap->registration_point.y * 0.6f);
}
}
indicator = FALSE;
if (!name_shown)
return;
}
else
#endif
@@ -1301,8 +1271,7 @@ static void hud_draw_player_names_now(
long team_index;
real enemy_range;
/* (VR: the triangles over teammates go with the names, shown or not) */
if ((setting == _player_names_none && !vr_apart) || player_index == NONE)
if (setting == _player_names_none || player_index == NONE)
return;
team_index = player_get(player_index)->team_index;
indicators = game_engine_display_team_indicators();
@@ -1312,14 +1281,12 @@ static void hud_draw_player_names_now(
{
/* (allies as the game's triangles tell them: the same team) */
boolean ally = player->team_index == team_index;
boolean shown = !(setting == _player_names_none || (ally && setting == _player_names_enemies) ||
(!ally && setting == _player_names_allies));
if (iterator.datum_index == player_index || player->unit_index == NONE)
continue;
if (!shown && !(vr_apart && ally && indicators))
if ((ally && setting == _player_names_enemies) || (!ally && setting == _player_names_allies))
continue;
hud_draw_player_name(iterator.datum_index, ally, ally && indicators, shown, enemy_range, vr_apart);
hud_draw_player_name(iterator.datum_index, ally, ally && indicators, enemy_range, vr_apart);
}
return;
+2 -13
View File
@@ -5836,7 +5836,6 @@ an invite link does (the game shows up in the list once its host is
reached). */
int p2p_join_code(char *text, int size);
void halo_vr_pulse_pad_a(void);
int p2p_join_with_code(char const *typed);
int p2p_join_code_status(void);
void p2p_join_code_clear_status(void);
@@ -6144,13 +6143,6 @@ static boolean ui_join_code_take_pointer(
press.type = _event_type_button;
press.data.button.index = _gamepad_analog_button_a;
press.data.button.value = 1;
/* (the screen where controllers join by their A: a click is the
pad's A, there, not a menu's) */
if (pointer->left_clicks && y < 400 && ui_join_code_screen_active("4way_start2join_screen"))
{
halo_vr_pulse_pad_a();
return TRUE;
}
if (ui_join_code_globals.panel_open)
{
if (x >= 48 && x < 592 && y >= 128 && y < 128 + ONLINE_PANEL_ROWS * 22)
@@ -6323,16 +6315,13 @@ static void ui_join_code_render(
if (ui_join_code_screen_active("server_list_screen"))
{
char const *status = NULL;
real_argb_color hint_color = { 1.0f, 0.85f, 0.85f, 0.85f };
if (ui_join_code_globals.panel_open)
{
ui_join_code_render_panel();
return;
}
/* (in the key bar's free left, and under it: clear of the map's
picture) */
ui_join_code_draw_text(8, 200, 420, "%x-button Online / code", TRUE, 0, &hint_color);
ui_join_code_draw_line(372, "%x-button Online games: public ones, or join by a code", TRUE, FALSE);
switch (p2p_join_code_status())
{
case _join_code_looking: status = "Looking for the game of that code..."; break;
@@ -6355,7 +6344,7 @@ static void ui_join_code_render(
}
}
if (status)
ui_join_code_draw_line(452, status, FALSE, FALSE);
ui_join_code_draw_line(392, status, FALSE, FALSE);
}
else if (ui_join_code_screen_active("connected_pregame_screen") && global_network_game_server_get())
{
+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