tengu_api/state/
shogun.rs1use steel::*;
2
3pub const BARRACKS_SLOT_EMPTY: u64 = u64::MAX;
5
6#[repr(C)]
8#[derive(Clone, Copy, Debug, Default, PartialEq, bytemuck::Pod, bytemuck::Zeroable)]
9pub struct Shogun {
10 pub dojo: Pubkey,
11 pub index: u64,
12 pub rarity: u64,
13 pub element: u64,
14 pub spirit_power: u64,
15 pub prestige: u64,
16 pub chakra_max: u64,
17 pub chakra_remaining: u64,
18 pub assigned_barracks_slot: u64,
19 pub last_used_slot: u64,
20 pub level: u64,
21 pub buffer1: u64,
22 pub buffer2: u64,
23}
24
25impl Shogun {
26 pub fn rarity_from_hash(hash: &[u8; 32]) -> u64 {
27 let v = u64::from_le_bytes(hash[0..8].try_into().unwrap()) % 1000;
28 if v < crate::consts::DROP_N {
29 0
30 } else if v < crate::consts::DROP_N + crate::consts::DROP_R {
31 1
32 } else if v < crate::consts::DROP_N + crate::consts::DROP_R + crate::consts::DROP_SR {
33 2
34 } else if v
35 < crate::consts::DROP_N
36 + crate::consts::DROP_R
37 + crate::consts::DROP_SR
38 + crate::consts::DROP_SSR
39 {
40 3
41 } else {
42 4
43 }
44 }
45
46 pub fn element_from_hash(hash: &[u8; 32]) -> u64 {
47 u64::from_le_bytes(hash[8..16].try_into().unwrap()) % 5
48 }
49
50 pub fn spirit_power_by_rarity(rarity: u64) -> u64 {
51 match rarity {
52 0 => crate::consts::SP_N,
53 1 => crate::consts::SP_R,
54 2 => crate::consts::SP_SR,
55 3 => crate::consts::SP_SSR,
56 4 => crate::consts::SP_UR,
57 _ => crate::consts::SP_N,
58 }
59 }
60
61 pub fn effective_spirit_power(rarity: u64, level: u64, prestige: u64) -> u64 {
62 let base = Self::spirit_power_by_rarity(rarity);
63 let lvl = level.max(1);
64 let prst = prestige.max(1);
65 let level_mult = 100u64.saturating_add((lvl - 1).saturating_mul(10));
66 let prestige_mult = Self::prestige_multiplier(prst);
67 base.saturating_mul(level_mult).saturating_mul(prestige_mult) / 10_000
68 }
69
70 pub fn prestige_multiplier(prestige: u64) -> u64 {
72 let p = prestige.max(1);
73 if p <= 5 {
74 [100u64, 125, 156, 195, 244][(p - 1) as usize]
75 } else {
76 244u64.saturating_add((p - 5).saturating_mul(50))
77 }
78 }
79
80 pub fn prestige_dupes_required(current_prestige: u64) -> u64 {
82 let p = current_prestige.max(1);
83 if p == 1 {
84 1
85 } else {
86 (p - 1).saturating_mul(2)
87 }
88 }
89
90 pub fn level_up_cost(level: u64) -> u64 {
92 let lvl = level.max(1).min(crate::consts::MAX_SHOGUN_LEVEL);
93 crate::consts::LEVEL_UP_COST_BASE
94 .saturating_add(
95 crate::consts::LEVEL_UP_COST_INCREMENT.saturating_mul(lvl.saturating_sub(1)),
96 )
97 }
98
99 pub fn is_assigned(&self) -> bool {
100 self.assigned_barracks_slot != 0
101 }
102
103 pub fn slot_index(&self) -> u64 {
104 self.assigned_barracks_slot.saturating_sub(1)
105 }
106
107 pub fn is_empty(&self) -> bool {
108 self.rarity == 0 && self.level == 0 && self.spirit_power == 0
109 }
110}