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];
15
16#[derive(Debug, Clone, Copy)]
18pub struct PlayerPresentationInput {
19 pub harvesting: bool,
20 pub crafting: bool,
21 pub talking: bool,
22 pub chatting: bool,
23 pub in_combat: bool,
24 pub pursue: bool,
25 pub in_attack_range: bool,
26 pub is_moving: bool,
27 pub sprinting: bool,
28}
29
30pub fn resolve_player_presentation_key(input: PlayerPresentationInput) -> &'static str {
31 if input.harvesting {
32 return "harvesting";
33 }
34 if input.crafting {
35 return "crafting";
36 }
37 if input.talking {
38 return "talking";
39 }
40 if input.chatting {
41 return "chatting";
42 }
43 if input.in_combat && input.in_attack_range {
44 return "combat";
45 }
46 if input.pursue || (input.in_combat && !input.in_attack_range) {
47 return "pursue";
48 }
49 if input.in_combat {
50 return "combat";
51 }
52 if input.is_moving && input.sprinting {
53 return "sprinting";
54 }
55 if input.is_moving {
56 return "walking";
57 }
58 "idle"
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64
65 #[test]
66 fn player_harvesting_wins() {
67 let key = resolve_player_presentation_key(PlayerPresentationInput {
68 harvesting: true,
69 crafting: false,
70 talking: false,
71 chatting: false,
72 in_combat: true,
73 pursue: false,
74 in_attack_range: true,
75 is_moving: true,
76 sprinting: true,
77 });
78 assert_eq!(key, "harvesting");
79 }
80
81 #[test]
82 fn player_talking_over_walking() {
83 let key = resolve_player_presentation_key(PlayerPresentationInput {
84 harvesting: false,
85 crafting: false,
86 talking: true,
87 chatting: false,
88 in_combat: false,
89 pursue: false,
90 in_attack_range: false,
91 is_moving: true,
92 sprinting: false,
93 });
94 assert_eq!(key, "talking");
95 }
96
97 #[test]
98 fn player_pursue_out_of_range() {
99 let key = resolve_player_presentation_key(PlayerPresentationInput {
100 harvesting: false,
101 crafting: false,
102 talking: false,
103 chatting: false,
104 in_combat: true,
105 pursue: false,
106 in_attack_range: false,
107 is_moving: true,
108 sprinting: true,
109 });
110 assert_eq!(key, "pursue");
111 }
112}