two separate breakages behind "no achievement, no level up", both checked against the client in IDA. level up: LogicClientAvatar::xpGainHelper adds a gain to exp_points - which is progress WITHIN the level, not a running total - then rolls it into levels: while exp_points >= ExpToNextLevel(level) it subtracts that threshold and increments the level, calling levelUp for the deck slots and diamond reward. our add_exp only grew exp_points, so the bar filled past full and the level never moved. it now rolls over the same way, against the exp_levels table. achievement: the client only offers a claim when progress >= ActionCount (LogicClientAvatar::isAchievementCompleted reads commodity 2), and the claim command re-reads that same commodity - and build_avatar populated none of it, so every claim came back "not completed". build_avatar now serves real progress: findcard from the count of distinct cards owned, reacharena from the arena reached. donate / jointeam / watchtv need social features we do not have and stay at zero. tests cover both and fail without the fixes: 25 exp reaches level 2 with 5 carried, and a completed findcard tier claims once, grants exp, and is rejected the second time.
39 lines
1 KiB
Rust
39 lines
1 KiB
Rust
use std::fmt;
|
|
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
|
pub struct LogicLong {
|
|
pub high: i32,
|
|
pub low: i32,
|
|
}
|
|
impl LogicLong {
|
|
pub const ZERO: LogicLong = LogicLong { high: 0, low: 0 };
|
|
pub const fn new(high: i32, low: i32) -> Self {
|
|
Self { high, low }
|
|
}
|
|
pub const fn from_i64(value: i64) -> Self {
|
|
Self {
|
|
high: (value >> 32) as i32,
|
|
low: value as i32,
|
|
}
|
|
}
|
|
pub const fn to_i64(self) -> i64 {
|
|
((self.high as i64) << 32) | (self.low as u32 as i64)
|
|
}
|
|
pub const fn is_zero(self) -> bool {
|
|
self.high == 0 && self.low == 0
|
|
}
|
|
}
|
|
impl fmt::Display for LogicLong {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
write!(f, "LogicLong({}-{})", self.high, self.low)
|
|
}
|
|
}
|
|
impl From<i64> for LogicLong {
|
|
fn from(value: i64) -> Self {
|
|
Self::from_i64(value)
|
|
}
|
|
}
|
|
impl From<LogicLong> for i64 {
|
|
fn from(value: LogicLong) -> Self {
|
|
value.to_i64()
|
|
}
|
|
}
|