Merge pull request #249 from innerhat-dev/vehicle-teleporter-name

This commit is contained in:
MrBruh committed 2026-10-11 11:59:05 +13:00
commit 098ca66a72
3 files changed
+122 -4

No files matched your search

+101 -4
View File
@@ -4662,9 +4662,64 @@ static struct
real_vector3d forward;
real_vector3d up;
long idle_since;
/* (the scenario name the map's scripts teleport; NONE when it had none) */
short name_index;
} game_engine_vehicle_homes[MAXIMUM_VEHICLE_HOMES];
static short game_engine_vehicle_home_count = NONE;
/* still on the pad the map put it on: further than this, and empty, it can
come back */
#define VEHICLE_HOME_AWAY_SQUARED 4.0f
/* the vehicle this home should follow. The recorded one, if it is still
alive. A map script often destroys that one and creates it again under the
same name: that one is this home's vehicle, and a second is not put on the
pad with it. */
static long game_engine_vehicle_home_current(
short home)
{
long object_index = game_engine_vehicle_homes[home].object_index;
struct unit_datum *vehicle = unit_try_and_get(object_index);
long named_index;
struct object_iterator iterator;
if (vehicle && !TEST_FLAG(vehicle->object.damage_flags, _object_dead_bit))
return object_index;
named_index = game_engine_vehicle_homes[home].name_index == NONE ? NONE :
object_index_from_name_index(game_engine_vehicle_homes[home].name_index);
vehicle = unit_try_and_get(named_index);
if (vehicle && !TEST_FLAG(vehicle->object.damage_flags, _object_dead_bit))
{
game_engine_vehicle_homes[home].object_index = named_index;
return named_index;
}
object_iterator_new(&iterator, _object_mask_vehicle, 0);
while (object_iterator_next(&iterator))
{
struct object_datum *object = object_get(iterator.index);
real dx = object->object.position.x - game_engine_vehicle_homes[home].position.x;
real dy = object->object.position.y - game_engine_vehicle_homes[home].position.y;
real dz = object->object.position.z - game_engine_vehicle_homes[home].position.z;
if (TEST_FLAG(object->object.damage_flags, _object_dead_bit) ||
object->definition_index != game_engine_vehicle_homes[home].definition_index ||
dx * dx + dy * dy + dz * dz > VEHICLE_HOME_AWAY_SQUARED)
{
continue;
}
game_engine_vehicle_homes[home].object_index = iterator.index;
if (game_engine_vehicle_homes[home].name_index == NONE)
game_engine_vehicle_homes[home].name_index = object->object.name_index;
else
object_claim_scenario_name(iterator.index, game_engine_vehicle_homes[home].name_index);
return iterator.index;
}
return NONE;
}
static void game_engine_update_vehicle_respawn(
void)
{
@@ -4692,11 +4747,13 @@ static void game_engine_update_vehicle_respawn(
object_get_orientation(iterator.index, &game_engine_vehicle_homes[home].forward,
&game_engine_vehicle_homes[home].up);
game_engine_vehicle_homes[home].idle_since = NONE;
game_engine_vehicle_homes[home].name_index = object->object.name_index;
}
}
for (index = 0; index < game_engine_vehicle_home_count; index++)
{
struct unit_datum *vehicle = unit_try_and_get(game_engine_vehicle_homes[index].object_index);
long object_index = game_engine_vehicle_home_current(index);
struct unit_datum *vehicle = unit_try_and_get(object_index);
boolean waiting = TRUE;
if (vehicle && !TEST_FLAG(vehicle->object.damage_flags, _object_dead_bit))
@@ -4710,7 +4767,7 @@ static void game_engine_update_vehicle_respawn(
/* (empty: no rider among its children, which hold its own
weapons too) */
waiting = vehicle->unit.driver_object_index == NONE && vehicle->unit.gunner_object_index == NONE &&
dx * dx + dy * dy + dz * dz > 4.0f;
dx * dx + dy * dy + dz * dz > VEHICLE_HOME_AWAY_SQUARED;
for (child_index = vehicle->object.first_child_object_index; waiting && child_index != NONE;
child_index = object_get(child_index)->object.next_object_index)
{
@@ -4725,14 +4782,54 @@ static void game_engine_update_vehicle_respawn(
else if (now - game_engine_vehicle_homes[index].idle_since >= respawn_ticks)
{
struct object_placement_data placement_data;
struct object_iterator iterator;
long stale_index = game_engine_vehicle_homes[index].object_index;
long named_index = game_engine_vehicle_homes[index].name_index == NONE ? NONE :
object_index_from_name_index(game_engine_vehicle_homes[index].name_index);
long on_pad = NONE;
if (vehicle)
object_delete(game_engine_vehicle_homes[index].object_index);
/* (a vehicle of this kind is already there: follow that one,
rather than putting another on top of it) */
object_iterator_new(&iterator, _object_mask_vehicle, 0);
while (object_iterator_next(&iterator))
{
struct object_datum *occupant = object_get(iterator.index);
real dx = occupant->object.position.x - game_engine_vehicle_homes[index].position.x;
real dy = occupant->object.position.y - game_engine_vehicle_homes[index].position.y;
real dz = occupant->object.position.z - game_engine_vehicle_homes[index].position.z;
if (iterator.index == object_index ||
TEST_FLAG(occupant->object.damage_flags, _object_dead_bit) ||
occupant->definition_index != game_engine_vehicle_homes[index].definition_index ||
dx * dx + dy * dy + dz * dz > VEHICLE_HOME_AWAY_SQUARED)
{
continue;
}
on_pad = iterator.index;
break;
}
if (on_pad != NONE)
{
game_engine_vehicle_homes[index].object_index = on_pad;
if (game_engine_vehicle_homes[index].name_index == NONE)
game_engine_vehicle_homes[index].name_index = object_get(on_pad)->object.name_index;
else
object_claim_scenario_name(on_pad, game_engine_vehicle_homes[index].name_index);
game_engine_vehicle_homes[index].idle_since = NONE;
continue;
}
if (unit_try_and_get(stale_index))
object_delete(stale_index);
if (named_index != stale_index && unit_try_and_get(named_index))
object_delete(named_index);
object_placement_data_new(&placement_data, game_engine_vehicle_homes[index].definition_index, NONE);
placement_data.position = game_engine_vehicle_homes[index].position;
placement_data.forward = game_engine_vehicle_homes[index].forward;
placement_data.up = game_engine_vehicle_homes[index].up;
game_engine_vehicle_homes[index].object_index = object_new(&placement_data);
object_claim_scenario_name(
game_engine_vehicle_homes[index].object_index,
game_engine_vehicle_homes[index].name_index);
game_engine_vehicle_homes[index].idle_since = NONE;
}
}
+17
View File
@@ -4665,6 +4665,23 @@ static void object_name_list_new(
return;
}
/* the name is free: deleting the vehicle that held it cleared the slot.
A name something else still holds stays with that object. */
void object_claim_scenario_name(
long object_index,
short name_index)
{
if (object_index == NONE ||
!VALID_INDEX(name_index, MIN(global_scenario_get()->object_names.count, MAXIMUM_OBJECT_NAMES_PER_SCENARIO)) ||
object_name_list[name_index] != NONE)
{
return;
}
object_name_list_new(object_index, name_index);
return;
}
static void object_name_list_delete(
long object_index)
{
+4
View File
@@ -432,6 +432,10 @@ void object_permute_region(long object_index, char *permutation_name, short desi
boolean object_get_function_value(long object_index, short function_index, real *value_reference);
short objects_in_clusters_by_indices(unsigned long class_flags, short cluster_count, short const *cluster_indices, short maximum_object_count, long *object_indices);
long object_index_from_name_index(short name_index);
/* port: this object takes a scenario name nobody holds, the way a placed
vehicle does. A respawned vehicle keeps the name of the one it replaces, so
a script that teleports that name still finds it. */
void object_claim_scenario_name(long object_index, short name_index);
void objects_disconnect_from_structure_bsp(void);
boolean object_visible_to_any_player(long object_index);
void object_pvs_activate(long object_index);