flatland_presentation/
player_states.rs1pub const PLAYER_PRESENTATION_STATES: &[(&str, &str)] = &[
5 ("combat", "Combat — in melee range or casting"),
6 ("pursue", "Pursue — has target, out of attack range"),
7 ("sprinting", "Sprinting — fast movement"),
8 ("walking", "Walking — normal movement"),
9 ("harvesting", "Harvesting — gathering a resource node"),
10 ("crafting", "Crafting — timed blueprint craft"),
11 ("talking", "Talking — open NPC conversation"),
12 ("chatting", "Chatting — recent nearby / whisper-stone chat"),
13 ("idle", "Idle — stationary"),
14 ("telegraph", "Telegraph — attack or cast wind-up"),
15];
16
17#[derive(Debug, Clone, Copy)]
19pub struct PlayerPresentationInput {
20 pub harvesting: bool,
21 pub crafting: bool,
22 pub talking: bool,
23 pub chatting: bool,
24 pub in_combat: bool,
25 pub pursue: bool,
26 pub in_attack_range: bool,
27 pub is_moving: bool,
28 pub sprinting: bool,
29 pub telegraph_active: bool,
30}
31
32pub fn resolve_player_presentation_key(input: PlayerPresentationInput) -> &'static str {
33 if input.telegraph_active {
34 return "telegraph";
35 }
36 if input.harvesting {
37 return "harvesting";
38 }
39 if input.crafting {
40 return "crafting";
41 }
42 if input.talking {
43 return "talking";
44 }
45 if input.chatting {
46 return "chatting";
47 }
48 if input.in_combat && input.in_attack_range {
49 return "combat";
50 }
51 if input.pursue || (input.in_combat && !input.in_attack_range) {
52 return "pursue";
53 }
54 if input.in_combat {
55 return "combat";
56 }
57 if input.is_moving && input.sprinting {
58 return "sprinting";
59 }
60 if input.is_moving {
61 return "walking";
62 }
63 "idle"
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 #[test]
71 fn player_harvesting_wins() {
72 let key = resolve_player_presentation_key(PlayerPresentationInput {
73 harvesting: true,
74 crafting: false,
75 talking: false,
76 chatting: false,
77 in_combat: true,
78 pursue: false,
79 in_attack_range: true,
80 is_moving: true,
81 sprinting: true,
82 telegraph_active: false,
83 });
84 assert_eq!(key, "harvesting");
85 }
86
87 #[test]
88 fn player_talking_over_walking() {
89 let key = resolve_player_presentation_key(PlayerPresentationInput {
90 harvesting: false,
91 crafting: false,
92 talking: true,
93 chatting: false,
94 in_combat: false,
95 pursue: false,
96 in_attack_range: false,
97 is_moving: true,
98 sprinting: false,
99 telegraph_active: false,
100 });
101 assert_eq!(key, "talking");
102 }
103
104 #[test]
105 fn player_pursue_out_of_range() {
106 let key = resolve_player_presentation_key(PlayerPresentationInput {
107 harvesting: false,
108 crafting: false,
109 talking: false,
110 chatting: false,
111 in_combat: true,
112 pursue: false,
113 in_attack_range: false,
114 is_moving: true,
115 sprinting: true,
116 telegraph_active: false,
117 });
118 assert_eq!(key, "pursue");
119 }
120}