mirror of
https://github.com/Cesarus85/ringfall-mjolnir-vr.git
synced 2026-10-23 13:00:35 +02:00
Recover AI communication start from Opus wave
This commit is contained in:
1 parent
1cc83929d2
commit
75bbaee4c4
4 files changed
+446
-7
No files matched your search
+2
-2
@@ -572,10 +572,10 @@
|
||||
{ "file_offset": 204416, "flags": 32, "name": "_code_00031e80" },
|
||||
{ "file_offset": 204848, "flags": 32, "name": "_code_00032030" },
|
||||
{ "file_offset": 205504, "flags": 32, "name": "_code_000322c0" },
|
||||
{ "file_offset": 205552, "flags": 32, "name": "_code_000322f0" },
|
||||
{ "file_offset": 205552, "flags": 32, "name": "_actor_reset_idle_vocalization_timer" },
|
||||
{ "file_offset": 205760, "flags": 32, "name": "_actor_communication_update" },
|
||||
{ "file_offset": 206000, "flags": 32, "name": "_code_000324b0" },
|
||||
{ "file_offset": 206128, "flags": 32, "name": "_code_00032530" },
|
||||
{ "file_offset": 206128, "flags": 32, "name": "_ai_communication_update_speech_timers" },
|
||||
{ "file_offset": 206800, "flags": 32, "name": "_ai_communication_get_player_rating" },
|
||||
{ "file_offset": 207632, "flags": 32, "name": "_ai_conversation_stop" },
|
||||
{ "file_offset": 207776, "flags": 32, "name": "_ai_conversation_actor_deleted" },
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
# Opus 44,928-byte wave canonical reconciliation (2026-09-02)
|
||||
|
||||
## Purpose
|
||||
|
||||
This ledger reconciles the reported `+44,928` padded-byte Claude/Opus session on
|
||||
`claude/breakable-surfaces-20260830` at `617703d2e` against canonical
|
||||
`jonas/ai-debug-integration-20260829` at `1cc83929d`. It answers a narrower and
|
||||
more useful question than comparing branch totals: which January code sections
|
||||
were strict exact in Opus but were not strict exact in canonical?
|
||||
|
||||
The comparison used rename-stable keys of `unit + target code-section ordinal`.
|
||||
That is important because canonical has replaced many `code_...` names with
|
||||
evidence-backed semantic names. The frozen inputs are:
|
||||
|
||||
- `scratch/opus-617703d2e-stable.json`: 8,246 sections, 4,982 strict exact;
|
||||
- `scratch/canonical-1cc83929d-stable.json`: 8,245 sections, 5,309 strict exact.
|
||||
|
||||
Canonical has 375 strict-exact sections absent from the older Opus snapshot.
|
||||
Opus has only 48 strict-exact sections, totaling 15,696 padded bytes, which are
|
||||
not strict exact in that canonical snapshot. Therefore the reported 44,928-byte
|
||||
session gain is not a 44,928-byte canonical deficit.
|
||||
|
||||
## Reconciliation result
|
||||
|
||||
| Disposition at the frozen canonical baseline | Functions | Padded bytes |
|
||||
| --- | ---: | ---: |
|
||||
| Truthful ordinary-C implementation retained as a measured residual | 25 | 11,456 |
|
||||
| Credible strict-exact recovery admitted in this wave | 1 | 704 |
|
||||
| Deliberately not emitted pending a real owner/caller or credible source | 22 | 3,536 |
|
||||
| **Total Opus-only strict set audited** | **48** | **15,696** |
|
||||
|
||||
The 25 residual functions are not lost source progress. Canonical deliberately
|
||||
keeps their semantic implementation and refuses only the Opus spelling that
|
||||
made the bytes exact through assembly, forced inlining, `noinline`, volatile or
|
||||
barrier steering, false BSS/type ownership, duplicate inline-helper bodies, or
|
||||
other unsupported source shapes. Their detailed evidence remains in the object
|
||||
ledgers cited below.
|
||||
|
||||
## Recovered exception: `ai_communication_started`
|
||||
|
||||
`_ai_communication_started` is the credible exception. The Opus body is
|
||||
ordinary typed C, contains no compiler-steering construct, and compiles to all
|
||||
704 January bytes with all 48 relocation identities. Its normalized SHA-256 is
|
||||
`eed6aa664227288ffe15a7f7c3c51791dbe88c42ef947d279e9a66c5422a0cd8`
|
||||
for both target and candidate.
|
||||
|
||||
The genuine call graph also emits the 672-byte speech-timer helper. Independent
|
||||
HCEA source names that helper `ai_communication_update_speech_timers`, and names
|
||||
the already-exact 208-byte reset helper
|
||||
`actor_reset_idle_vocalization_timer`. Those semantic names replace
|
||||
`code_00032530` and `code_000322f0` in source and `config/symbols.json`; neither
|
||||
address-based name is retained.
|
||||
|
||||
The speech-timer helper itself is an honest residual: target and candidate are
|
||||
both 672 padded bytes with 43 relocations, with target normalized SHA-256
|
||||
`91999fda75815c6638478824f3efa53ee6717572f365530362cbec00e78a50ac`
|
||||
and candidate SHA-256
|
||||
`885fdb81966284acf5ba7138a4bbbd2221e7c61c89114fdd6f53b96ba89b81a0`.
|
||||
Objdiff reports 97.68 percent similarity. The remaining differences are the
|
||||
previously documented natural register/lifetime schedule; no register hint,
|
||||
volatile access, barrier, pragma, assembly, false alias, or inert dependency is
|
||||
introduced. The typed implementation is retained and fuzzy-parked.
|
||||
|
||||
The public `ai_communication_started` declaration is placed in its owner header,
|
||||
`source/ai/ai_communication.h`. The two private helper declarations remain in
|
||||
their owner translation unit. Typed object access uses `unit_get` and
|
||||
`actor_get`; tag-block access uses `TAG_BLOCK_GET_ELEMENT`.
|
||||
|
||||
## Already retained as credible residuals
|
||||
|
||||
These 25 Opus-exact sections, totaling 11,456 padded bytes, already exist in
|
||||
canonical as ordinary-C residual implementations:
|
||||
|
||||
- AI: `action_converse_perform`, `actor_combat_find_nearby_target`,
|
||||
`actor_combat_check_collateral_damage`, `infection_swarm_aim_jump`, and
|
||||
`find_turning_point`;
|
||||
- platform/camera/cutscene: `get_mutex_from_pool`, `dead_camera_update`, and
|
||||
`recorded_animation_play_internal`;
|
||||
- game engine: `game_engine_verify_current_map`;
|
||||
- players: `unit_should_autopick_weapon`, `player_set_action_result`,
|
||||
`player_handle_powerup`, `player_handle_powerup_minor`,
|
||||
`player_update_powerups`, `player_teleport_on_bsp_switch`,
|
||||
`players_reconnect_to_structure_bsp`, `player_examine_nearby_vehicle`,
|
||||
`player_examine_nearby_device`, `player_examine_nearby_item`, and
|
||||
`player_examine_nearby_objects`;
|
||||
- memory: `lrar_allocate`;
|
||||
- object lights: `light_unmarked`, `light_mark`,
|
||||
`find_point_lights_for_object_in_cluster`, and `light_reconnect_to_map`.
|
||||
|
||||
The exact Opus forms are intentionally not restored. In particular:
|
||||
|
||||
- `action_converse_perform` used gameplay inline assembly to force a register;
|
||||
- `actor_combat_find_nearby_target` disturbed the protected
|
||||
`point_from_line3d` inline schedule;
|
||||
- `actor_combat_check_collateral_damage` requires an owner-header shape that
|
||||
regresses `units.obj` from 189/189;
|
||||
- `game_engine_verify_current_map` and `lrar_allocate` depended on unsupported
|
||||
`noinline`/manual helper expansion;
|
||||
- the Players group used combinations of copied helpers, dead emitters,
|
||||
volatile/barrier steering, duplicate fetches, and representation tricks;
|
||||
- `recorded_animation_play_internal` reached exact only with false BSS
|
||||
ownership; and
|
||||
- the Object Lights forms relied on duplicate bodies, false linkage, or helpers
|
||||
without a genuine emitting caller.
|
||||
|
||||
## Deliberately unwritten boundaries
|
||||
|
||||
The remaining 22 Opus-exact sections total 3,536 padded bytes. They stay
|
||||
unwritten until their authentic source owner naturally emits them:
|
||||
|
||||
- `midpoint3d` (64): a fake standalone duplicate of the shared real-math inline;
|
||||
- Decals helpers (704 total): `projection_from_vector3d`, `project_point2d`,
|
||||
`triple_product3d`, `plane2d_from_points`,
|
||||
`plane3d_from_point_and_normal`, and
|
||||
`bsp3d_get_plane_from_designator`; these were unowned standalone copies of
|
||||
shared inline/macro behavior;
|
||||
- `player_examine_nearby_unit` (16): no truthful source form currently emits
|
||||
the target-only leaf;
|
||||
- Weapons (1,632 total): `animation_update` has an unresolved authentic COMDAT
|
||||
grouping; `weapon_trigger_get_charged_fraction` and
|
||||
`weapon_export_function_values` atomically introduce a candidate-owned float
|
||||
constant that January treats as external; and
|
||||
`weapon_handle_potential_inventory_item` depended on a layout-only surrogate
|
||||
contradicting authenticated fields;
|
||||
- Object Lights (1,056 total): the two anonymous 32-byte leaves,
|
||||
`render_debug_light`, `light_get_bounding_sphere`, `sample_lightmap`, and
|
||||
`sample_diffuse_texture` still lack a credible complete owner/caller graph;
|
||||
- four Active Camouflage XDK wrappers (64 total): the targets are correctly
|
||||
named `IDirect3DDevice8` wrappers, but must be instantiated by the real typed
|
||||
cache/draw functions rather than copied, assembled, or emitted by a dummy
|
||||
anchor.
|
||||
|
||||
## Validation and provenance
|
||||
|
||||
The isolated gate moved `ai_communication.obj` from 36 exact / 0 residual / 12
|
||||
unwritten to 37 exact / 1 residual / 10 unwritten. Every inherited exact section
|
||||
remained exact. The exact recovery and helper were compiled from the complete
|
||||
translation unit; no proof-only caller or dormant emission anchor is retained.
|
||||
|
||||
Primary local evidence:
|
||||
|
||||
- `docs/object_matching_logs/claude_wave_small_exact_batch_20260831.md`;
|
||||
- `docs/object_matching_logs/players_obj_january_safe_harvest_20260902.md`;
|
||||
- `docs/object_matching_logs/object_lights_obj_small_family_recovery_20260902.md`;
|
||||
- `docs/object_matching_logs/game_engine_obj_jonas_no_fake_inline_cleanup_20260831.md`;
|
||||
- `docs/object_matching_logs/thread_win32_obj_house_rule_correction_20260831.md`;
|
||||
- `docs/object_matching_logs/action_converse_obj_jonas_ordinary_c_fuzzy_park_20260830.md`;
|
||||
- `docs/object_matching_logs/actor_combat_obj_collateral_damage_rejected_20260831.md`;
|
||||
- `docs/object_matching_logs/recorded_animations_obj_natural_recovery_20260830.md`;
|
||||
- `docs/object_matching_logs/weapons_obj_jonas_safe_trio_and_charged_export_blocker_20260901.md`;
|
||||
- `docs/object_matching_logs/lrar_cache_obj_jonas_no_fake_inline_cleanup_20260831.md`;
|
||||
- `docs/object_matching_logs/rasterizer_xbox_active_camouflage_obj_jonas_credibility_recovery_20260830.md`;
|
||||
- HCEA `src/blam/ai/ai_communication_started.c`,
|
||||
`ai_communication_update_speech_timers.c`, and
|
||||
`actor_reset_idle_vocalization_timer.c`.
|
||||
|
||||
January's Halo CE Xbox COFF remains the sole byte-admission authority. Donor
|
||||
source supplies names, types, and control-flow evidence only.
|
||||
@@ -59,13 +59,13 @@ symbols in this file:
|
||||
000322C0 0030:
|
||||
_code_000322c0 (0000)
|
||||
000322F0 00d0:
|
||||
_code_000322f0 (0000)
|
||||
_actor_reset_idle_vocalization_timer (0000)
|
||||
000323C0 00f0:
|
||||
_actor_communication_update (0000)
|
||||
000324B0 0080:
|
||||
_code_000324b0 (0000)
|
||||
00032530 02a0:
|
||||
_code_00032530 (0000)
|
||||
_ai_communication_update_speech_timers (0000)
|
||||
000327D0 0340:
|
||||
_ai_communication_get_player_rating (0000)
|
||||
00032B10 0090:
|
||||
@@ -549,6 +549,7 @@ symbols in this file:
|
||||
#include "actor_definitions.h"
|
||||
#include "actors.h"
|
||||
#include "actor_types.h"
|
||||
#include "ai_scenario_definitions.h"
|
||||
#include "game/game.h"
|
||||
#include "main/console.h"
|
||||
#include "memory/data.h"
|
||||
@@ -557,6 +558,7 @@ symbols in this file:
|
||||
#include "scenario/scenario.h"
|
||||
#include "scenario/scenario_definitions.h"
|
||||
#include "tag_files/tag_files.h"
|
||||
#include "units/dialogue_definitions.h"
|
||||
#include "units/units.h"
|
||||
|
||||
/* ---------- constants */
|
||||
@@ -597,6 +599,7 @@ enum
|
||||
_ai_sound_volume_shout = 3,
|
||||
_ai_communication_team_human = 0,
|
||||
_ai_communication_team_covenant = 1,
|
||||
NUMBER_OF_AI_COMMUNICATION_TEAMS = 2,
|
||||
};
|
||||
|
||||
#define COMMUNICATION_CLOSE_DISTANCE 5.0f
|
||||
@@ -911,12 +914,18 @@ static struct scenario_conversation_definition_view *code_000322c0(
|
||||
long conversation_index);
|
||||
boolean actor_is_fighting(
|
||||
long actor_index);
|
||||
static void code_000322f0(
|
||||
static void actor_reset_idle_vocalization_timer(
|
||||
long actor_index);
|
||||
static void code_000324b0(
|
||||
long actor_index,
|
||||
long prop_index,
|
||||
struct ai_information_packet *information);
|
||||
static void ai_communication_update_speech_timers(
|
||||
long unit_index,
|
||||
short priority,
|
||||
short vocalization_type,
|
||||
short dialogue_type_index,
|
||||
short reply_table_index);
|
||||
short unit_test_speech(
|
||||
long unit_index,
|
||||
short priority,
|
||||
@@ -2088,7 +2097,7 @@ short ai_conversation_status(
|
||||
return status;
|
||||
}
|
||||
|
||||
static void code_000322f0(
|
||||
static void actor_reset_idle_vocalization_timer(
|
||||
long actor_index)
|
||||
{
|
||||
struct actor_datum *actor;
|
||||
@@ -2331,7 +2340,7 @@ void actor_communication_update(
|
||||
if (actor->control.idle_vocalization_timer == 0 ||
|
||||
actor->control.idle_vocalization_combat != in_combat)
|
||||
{
|
||||
code_000322f0(actor_index);
|
||||
actor_reset_idle_vocalization_timer(actor_index);
|
||||
}
|
||||
|
||||
if (actor->control.idle_vocalization_timer > 0 &&
|
||||
@@ -2406,6 +2415,273 @@ static void code_000324b0(
|
||||
return;
|
||||
}
|
||||
|
||||
static void ai_communication_update_speech_timers(
|
||||
long unit_index,
|
||||
short priority,
|
||||
short vocalization_type,
|
||||
short dialogue_type_index,
|
||||
short reply_table_index)
|
||||
{
|
||||
struct unit_datum *unit = unit_get(unit_index);
|
||||
struct actor_datum *actor;
|
||||
long time;
|
||||
long notification_time;
|
||||
|
||||
if (unit->unit.actor_index == NONE)
|
||||
{
|
||||
actor = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
actor = actor_get(unit->unit.actor_index);
|
||||
}
|
||||
|
||||
time = game_time_get();
|
||||
notification_time = time +
|
||||
MAX(0, unit->unit.speech.sound_timer - communication_overlap_time_modifier);
|
||||
unit->unit.speech.last_speech_finished_time = notification_time;
|
||||
|
||||
if (actor)
|
||||
{
|
||||
short communication_team;
|
||||
|
||||
actor_reset_idle_vocalization_timer(unit->unit.actor_index);
|
||||
communication_team = actor_communication_team(unit->unit.actor_index);
|
||||
if (communication_team != NONE)
|
||||
{
|
||||
if (priority <= _unit_speech_shout)
|
||||
{
|
||||
ai_globals->last_chatter_time[communication_team] = MAX(
|
||||
ai_globals->last_chatter_time[communication_team],
|
||||
notification_time);
|
||||
if (priority >= _unit_speech_talk)
|
||||
{
|
||||
ai_globals->last_talk_time[communication_team] = MAX(
|
||||
ai_globals->last_talk_time[communication_team],
|
||||
notification_time);
|
||||
}
|
||||
if (priority >= _unit_speech_shout)
|
||||
{
|
||||
ai_globals->last_shout_time[communication_team] = MAX(
|
||||
ai_globals->last_shout_time[communication_team],
|
||||
notification_time);
|
||||
}
|
||||
|
||||
if (ai_debug.print_speech_timers)
|
||||
{
|
||||
char const *team_name =
|
||||
global_communication_team_names[communication_team * 2];
|
||||
|
||||
error(
|
||||
2,
|
||||
"%s %s %d/%s: %s %d",
|
||||
team_name,
|
||||
unit_get_speech_priority_name(priority),
|
||||
dialogue_type_index,
|
||||
dialogue_get_vocalization_name(vocalization_type, TRUE),
|
||||
priority >= _unit_speech_talk ? "talk" : "chatter",
|
||||
notification_time - time);
|
||||
}
|
||||
}
|
||||
|
||||
if (dialogue_type_index != NONE)
|
||||
{
|
||||
struct dialogue_event_status *event;
|
||||
struct dialogue_usage const *usage;
|
||||
|
||||
match_assert(
|
||||
"c:\\halo\\SOURCE\\ai\\ai_communication.c",
|
||||
0xC9C,
|
||||
(dialogue_type_index >= 0) && (dialogue_type_index < global_dialogue_event_count));
|
||||
usage = &global_dialogue_table[dialogue_type_index];
|
||||
event = &global_dialogue_events[
|
||||
dialogue_type_index * NUMBER_OF_AI_COMMUNICATION_TEAMS + communication_team];
|
||||
event->last_time_spoken = time;
|
||||
if (game_connection() ||
|
||||
!ai_debug.communication_timeout_disabled)
|
||||
{
|
||||
if (usage->repeat_delay > 0.0f)
|
||||
{
|
||||
event->disable_until_time = (long)(
|
||||
usage->repeat_delay * TICKS_PER_SECOND +
|
||||
notification_time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (reply_table_index != NONE)
|
||||
{
|
||||
struct dialogue_event_status *event;
|
||||
struct reply_usage const *usage;
|
||||
|
||||
match_assert(
|
||||
"c:\\halo\\SOURCE\\ai\\ai_communication.c",
|
||||
0xCAF,
|
||||
(reply_table_index >= 0) && (reply_table_index < global_reply_event_count));
|
||||
usage = &global_reply_table[reply_table_index];
|
||||
event = &global_reply_events[
|
||||
reply_table_index * NUMBER_OF_AI_COMMUNICATION_TEAMS + communication_team];
|
||||
event->last_time_spoken = time;
|
||||
if (game_connection() ||
|
||||
!ai_debug.communication_timeout_disabled)
|
||||
{
|
||||
if (usage->repeat_delay > 0.0f)
|
||||
{
|
||||
event->disable_until_time = (long)(
|
||||
usage->repeat_delay * TICKS_PER_SECOND +
|
||||
notification_time);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void ai_communication_started(
|
||||
long unit_index,
|
||||
short priority,
|
||||
short vocalization_type,
|
||||
struct ai_information_packet *information)
|
||||
{
|
||||
switch (priority)
|
||||
{
|
||||
case _unit_speech_none:
|
||||
case _unit_speech_idle:
|
||||
case _unit_speech_pain:
|
||||
case _unit_speech_involuntary:
|
||||
case _unit_speech_death:
|
||||
break;
|
||||
|
||||
default:
|
||||
if (ai_debug.print_vocalizations)
|
||||
{
|
||||
char string[1024];
|
||||
char name[256];
|
||||
struct unit_datum *unit = unit_get(unit_index);
|
||||
|
||||
if (unit->unit.actor_index != NONE)
|
||||
{
|
||||
struct actor_datum *actor = actor_get(unit->unit.actor_index);
|
||||
|
||||
if (actor->meta.encounter_index == NONE)
|
||||
{
|
||||
csstrcpy(name, "<no encounter>");
|
||||
}
|
||||
else
|
||||
{
|
||||
struct encounter_definition *encounter = TAG_BLOCK_GET_ELEMENT(
|
||||
&global_scenario_get()->ai_encounters,
|
||||
DATUM_INDEX_TO_ABSOLUTE_INDEX(actor->meta.encounter_index),
|
||||
struct encounter_definition);
|
||||
|
||||
sprintf(
|
||||
name,
|
||||
"%s/%s",
|
||||
encounter->name,
|
||||
TAG_BLOCK_GET_ELEMENT(
|
||||
&encounter->squads,
|
||||
actor->meta.squad_index,
|
||||
struct squad_definition)->name);
|
||||
}
|
||||
|
||||
sprintf(
|
||||
string,
|
||||
"%s/%s: ",
|
||||
name,
|
||||
actor_type_get_name(actor->meta.type));
|
||||
}
|
||||
else if (unit->object.name_index != NONE)
|
||||
{
|
||||
sprintf(
|
||||
string,
|
||||
"%s: ",
|
||||
TAG_BLOCK_GET_ELEMENT(
|
||||
&global_scenario_get()->object_names,
|
||||
unit->object.name_index,
|
||||
struct scenario_object_name)->name);
|
||||
}
|
||||
else if (unit->unit.player_index != NONE)
|
||||
{
|
||||
sprintf(
|
||||
string,
|
||||
"player %d: ",
|
||||
DATUM_INDEX_TO_ABSOLUTE_INDEX(unit->unit.player_index));
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(
|
||||
string,
|
||||
"unit %04X: ",
|
||||
DATUM_INDEX_TO_ABSOLUTE_INDEX(unit_index));
|
||||
}
|
||||
|
||||
sprintf(
|
||||
temporary,
|
||||
"%s %s",
|
||||
unit_get_speech_priority_name(priority),
|
||||
vocalization_type == NONE ?
|
||||
"non-voc" :
|
||||
dialogue_get_vocalization_name(vocalization_type, FALSE));
|
||||
csstrcat(string, temporary);
|
||||
|
||||
if (information &&
|
||||
information->dialogue_type_index != NONE)
|
||||
{
|
||||
sprintf(
|
||||
temporary,
|
||||
" [%d/%s]",
|
||||
information->dialogue_type_index,
|
||||
ai_communication_get_type_name(
|
||||
global_dialogue_table[information->dialogue_type_index].communication_type));
|
||||
csstrcat(string, temporary);
|
||||
}
|
||||
|
||||
console_printf(FALSE, string);
|
||||
}
|
||||
|
||||
if (ai_debug.print_speech)
|
||||
{
|
||||
struct unit_datum *unit = unit_get(unit_index);
|
||||
|
||||
if (unit->unit.speech.current.priority > _unit_speech_none)
|
||||
{
|
||||
char actor_string[512];
|
||||
char speech_string[512];
|
||||
|
||||
error(
|
||||
2,
|
||||
"%s: %s",
|
||||
ai_debug_describe_actor(
|
||||
unit->unit.actor_index,
|
||||
unit_index,
|
||||
FALSE,
|
||||
actor_string,
|
||||
sizeof(actor_string)),
|
||||
unit_describe_speech(
|
||||
unit_index,
|
||||
TRUE,
|
||||
sizeof(speech_string),
|
||||
speech_string));
|
||||
}
|
||||
}
|
||||
|
||||
if (!information->updated_dialogue_timers)
|
||||
{
|
||||
ai_communication_update_speech_timers(
|
||||
unit_index,
|
||||
priority,
|
||||
vocalization_type,
|
||||
information->dialogue_type_index,
|
||||
NONE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void ai_communication_notify(
|
||||
long unit_index,
|
||||
short priority,
|
||||
|
||||
@@ -119,6 +119,11 @@ void ai_communication_dispose_from_old_map(
|
||||
void);
|
||||
void ai_communication_packet_new(
|
||||
struct ai_information_packet *information);
|
||||
void ai_communication_started(
|
||||
long unit_index,
|
||||
short priority,
|
||||
short vocalization_type,
|
||||
struct ai_information_packet *information);
|
||||
void actor_communication_update(
|
||||
long actor_index);
|
||||
void actor_handle_communication(
|
||||
|
||||
Reference in new issue
Block a user