feat(engine): retire D-078 overheard conversation system (#848)
Per R-012: delete conversation.rs, both overheard content files, and remove all 6 wire-up points (social_plugin, bridge/types, monologue, voice/integration). Protocol version 22 → 23. Scope confirmed by #842 audit — npc/ and content/global/ untouched. Surviving NPC components (NpcName, NpcColorIndex, NpcConversation) migrated to simulation/npc_components.rs for use by D-080 knowledge propagation. Also applies pre-existing cargo fmt debt (names.rs and 4 others). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -16,8 +16,8 @@ use rand::Rng;
|
||||
use crate::bridge::types::MonologueEvent;
|
||||
use crate::knowledge::{ContradictionDetectedQueue, EntityRegistry};
|
||||
use crate::perception::interpretation::ObservationTrigger;
|
||||
use crate::simulation::conversation::NpcName;
|
||||
use crate::simulation::movement::{PlayerCharacter, TilePosition};
|
||||
use crate::simulation::npc_components::NpcName;
|
||||
use crate::simulation::rng::EntityRng;
|
||||
use crate::simulation::time::SimulationTime;
|
||||
use crate::storyteller::EngagementRecord;
|
||||
@@ -84,15 +84,6 @@ const HEAR_SOUND_LINES: &[(&str, &str)] = &[
|
||||
("hear_sound_03", "Something just happened nearby."),
|
||||
];
|
||||
|
||||
/// Hardcoded v0.1 witness_interaction monologue lines.
|
||||
/// Fire when the player overhears an NPC-to-NPC conversation (D-078).
|
||||
/// Future: move to content pools with trigger="witness_interaction".
|
||||
const WITNESS_INTERACTION_LINES: &[(&str, &str)] = &[
|
||||
("witness_01", "Interesting. Wonder what that was about."),
|
||||
("witness_02", "I should remember what they just said."),
|
||||
("witness_03", "They didn't know I was listening."),
|
||||
];
|
||||
|
||||
/// Hardcoded v0.1 post_conversation monologue lines.
|
||||
/// Fire after a player-NPC dialogue concludes (walk-away or natural end).
|
||||
/// Future: move to content pools with trigger="post_conversation".
|
||||
@@ -375,7 +366,6 @@ fn select_hardcoded_fallback(trigger: &str, rng: &mut impl Rng) -> (String, Stri
|
||||
let lines = match trigger {
|
||||
"observe_npc" => OBSERVE_NPC_LINES,
|
||||
"hear_sound" => HEAR_SOUND_LINES,
|
||||
"witness_interaction" => WITNESS_INTERACTION_LINES,
|
||||
"post_conversation" => POST_CONVERSATION_LINES,
|
||||
unknown => {
|
||||
tracing::warn!(
|
||||
@@ -413,8 +403,7 @@ fn sound_range_tiles(range: &crate::knowledge::types::SoundRange) -> u32 {
|
||||
/// Priority order (first match wins):
|
||||
/// 1. observe_npc (new entity spotted — uses previous-tick observation events)
|
||||
/// 2. hear_sound (non-routine sound: Machinery, Alert)
|
||||
/// 3. witness_interaction (overheard NPC-to-NPC conversation, D-078)
|
||||
/// 4. post_conversation (player-NPC dialogue concluded)
|
||||
/// 3. post_conversation (player-NPC dialogue concluded)
|
||||
///
|
||||
/// System ordering: after all event producers + recognition/anomaly monologue
|
||||
/// systems, before compute_observer_snapshot.
|
||||
@@ -429,7 +418,6 @@ pub fn trigger_event_monologue(
|
||||
&TilePosition,
|
||||
&mut MonologueState,
|
||||
&mut MonologueBuffer,
|
||||
Option<&crate::simulation::conversation::ConversationEventBuffer>,
|
||||
&mut EntityRng,
|
||||
),
|
||||
With<PlayerCharacter>,
|
||||
@@ -441,9 +429,7 @@ pub fn trigger_event_monologue(
|
||||
// Saved for NPC attribution (engagement tracking #570) and trigger detection.
|
||||
let post_conv_npcs: Vec<Entity> = post_conv_queue.drain();
|
||||
|
||||
let Ok((player_pos, mut state, mut buffer, conv_buffer_opt, mut entity_rng)) =
|
||||
query.single_mut()
|
||||
else {
|
||||
let Ok((player_pos, mut state, mut buffer, mut entity_rng)) = query.single_mut() else {
|
||||
return;
|
||||
};
|
||||
|
||||
@@ -468,11 +454,6 @@ pub fn trigger_event_monologue(
|
||||
.unwrap_or(false)
|
||||
{
|
||||
Some("hear_sound")
|
||||
} else if conv_buffer_opt
|
||||
.map(|b| !b.events.is_empty())
|
||||
.unwrap_or(false)
|
||||
{
|
||||
Some("witness_interaction")
|
||||
} else if !post_conv_npcs.is_empty() {
|
||||
Some("post_conversation")
|
||||
} else {
|
||||
@@ -511,7 +492,7 @@ pub fn trigger_event_monologue(
|
||||
);
|
||||
|
||||
// Engagement tracking (#570): attribute monologue_trigger_count to specific NPCs.
|
||||
// Only NPC-context triggers are attributed — hear_sound/witness_interaction are not NPC-specific.
|
||||
// Only NPC-context triggers are attributed — hear_sound is not NPC-specific.
|
||||
match trigger {
|
||||
"observe_npc" => {
|
||||
// Attribute to all NPCs whose NewEntity event triggered this monologue
|
||||
@@ -537,7 +518,7 @@ pub fn trigger_event_monologue(
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {} // hear_sound, witness_interaction: no NPC-specific attribution
|
||||
_ => {} // hear_sound: no NPC-specific attribution
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1345,7 +1326,6 @@ mod tests {
|
||||
use crate::perception::interpretation::{
|
||||
ObservationEvent, ObservationEventQueue, ObservationTrigger,
|
||||
};
|
||||
use crate::simulation::conversation::ConversationEventBuffer;
|
||||
use crate::simulation::sound::{SoundEvent, SoundEventKind, SoundEventQueue};
|
||||
|
||||
fn setup_event_world() -> World {
|
||||
@@ -1366,7 +1346,6 @@ mod tests {
|
||||
TilePosition::new(10, 10, 0),
|
||||
MonologueState::default(),
|
||||
MonologueBuffer::default(),
|
||||
ConversationEventBuffer::default(),
|
||||
))
|
||||
.id()
|
||||
}
|
||||
@@ -1521,36 +1500,6 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn witness_interaction_fires_on_conversation_event() {
|
||||
let mut world = setup_event_world();
|
||||
let player = spawn_event_player(&mut world);
|
||||
|
||||
// Pre-fill ConversationEventBuffer with an overheard conversation
|
||||
world
|
||||
.get_mut::<ConversationEventBuffer>(player)
|
||||
.unwrap()
|
||||
.events
|
||||
.push(crate::simulation::conversation::ConversationEvent {
|
||||
occluded_line: "Keep your head down today.".to_string(),
|
||||
speaker_id: 100,
|
||||
target_id: 101,
|
||||
speaker_name: "Worker".to_string(),
|
||||
target_name: "Courier".to_string(),
|
||||
speaker_color_index: 0,
|
||||
target_color_index: 1,
|
||||
});
|
||||
|
||||
run_event_system(&mut world);
|
||||
|
||||
let buf = world.get::<MonologueBuffer>(player).unwrap();
|
||||
assert!(
|
||||
buf.event.is_some(),
|
||||
"witness_interaction should fire when conversation overheard"
|
||||
);
|
||||
assert!(buf.event.as_ref().unwrap().id.starts_with("witness_"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn post_conversation_fires_on_queue_entry() {
|
||||
let mut world = setup_event_world();
|
||||
@@ -1668,47 +1617,6 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn priority_hear_sound_over_witness_interaction() {
|
||||
let mut world = setup_event_world();
|
||||
let player = spawn_event_player(&mut world);
|
||||
|
||||
// Sound event
|
||||
world
|
||||
.resource_mut::<SoundEventQueue>()
|
||||
.events
|
||||
.push(SoundEvent::at(
|
||||
&TilePosition::new(11, 10, 0),
|
||||
SoundEventKind::Alert,
|
||||
1.0,
|
||||
crate::knowledge::types::SoundRange::Medium,
|
||||
None,
|
||||
));
|
||||
|
||||
// Conversation event
|
||||
world
|
||||
.get_mut::<ConversationEventBuffer>(player)
|
||||
.unwrap()
|
||||
.events
|
||||
.push(crate::simulation::conversation::ConversationEvent {
|
||||
occluded_line: "Test".to_string(),
|
||||
speaker_id: 100,
|
||||
target_id: 101,
|
||||
speaker_name: "A".to_string(),
|
||||
target_name: "B".to_string(),
|
||||
speaker_color_index: 0,
|
||||
target_color_index: 1,
|
||||
});
|
||||
|
||||
run_event_system(&mut world);
|
||||
|
||||
let buf = world.get::<MonologueBuffer>(player).unwrap();
|
||||
assert!(
|
||||
buf.event.as_ref().unwrap().id.starts_with("hear_sound_"),
|
||||
"hear_sound should have priority over witness_interaction"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn event_trigger_updates_last_fired_tick() {
|
||||
let mut world = setup_event_world();
|
||||
@@ -1813,12 +1721,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn hardcoded_lines_all_valid() {
|
||||
for lines in &[
|
||||
OBSERVE_NPC_LINES,
|
||||
HEAR_SOUND_LINES,
|
||||
WITNESS_INTERACTION_LINES,
|
||||
POST_CONVERSATION_LINES,
|
||||
] {
|
||||
for lines in &[OBSERVE_NPC_LINES, HEAR_SOUND_LINES, POST_CONVERSATION_LINES] {
|
||||
assert!(!lines.is_empty());
|
||||
for (id, text) in *lines {
|
||||
assert!(!id.is_empty(), "line id should not be empty");
|
||||
|
||||
Reference in New Issue
Block a user