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.
79 lines
3.3 KiB
Rust
79 lines
3.3 KiB
Rust
use std::path::Path;
|
|
use std::sync::Arc;
|
|
use game_service::home::build_avatar;
|
|
use logic::commands::COMMODITY_ACHIEVEMENT_PROGRESS;
|
|
use logic::{CommandOutcome, LogicClaimAchievementRewardCommand, LogicCommandHeader};
|
|
use logic::data::{table, LogicDataRef, LogicDataTables};
|
|
use logic::home::LogicHomeMode;
|
|
use logic::model::LogicClientHome;
|
|
fn tables() {
|
|
let root = Path::new(env!("CARGO_MANIFEST_DIR")).join("../../assets");
|
|
if let Ok(t) = LogicDataTables::load_from_dir(&root) {
|
|
LogicDataTables::install(Arc::new(t));
|
|
}
|
|
}
|
|
#[test]
|
|
fn adding_exp_rolls_over_into_levels() {
|
|
tables();
|
|
let mut home = LogicHomeMode::new(LogicClientHome::default(), Default::default(), 0);
|
|
home.avatar_mut().exp_level = 1;
|
|
home.avatar_mut().exp_points = 0;
|
|
home.add_exp(25);
|
|
assert_eq!(home.avatar().exp_level, 2, "25 exp should reach level 2");
|
|
assert_eq!(home.avatar().exp_points, 5, "5 exp should carry into level 2");
|
|
home.add_exp(50);
|
|
assert_eq!(home.avatar().exp_level, 3, "another 50 should reach level 3");
|
|
assert_eq!(home.avatar().exp_points, 5);
|
|
}
|
|
#[test]
|
|
fn a_completed_findcard_achievement_can_be_claimed() {
|
|
tables();
|
|
let tabs = LogicDataTables::instance();
|
|
let achievements = tabs.table(table::ACHIEVEMENTS).unwrap();
|
|
let (name, required) = (0..achievements.count())
|
|
.filter_map(|i| achievements.get_at(i))
|
|
.find(|row| row.string("Action") == "findcard")
|
|
.map(|row| (row.string("Name").to_owned(), row.int("ActionCount")))
|
|
.expect("a findcard achievement exists");
|
|
let root = Path::new(env!("CARGO_MANIFEST_DIR")).join("../../assets");
|
|
let catalog = game_service::Catalog::load(Some(&root));
|
|
let mut profile = game_service::store::PlayerProfile::starter(
|
|
service_rpc::AccountRef::new(0, 5),
|
|
&game_service::StarterProfile::default(),
|
|
&catalog,
|
|
);
|
|
profile.collection.clear();
|
|
profile.deck.clear();
|
|
let tabs2 = LogicDataTables::instance();
|
|
let cards = tabs2.table(table::CHARACTERS).unwrap();
|
|
for i in 0..(required.max(1) as usize) {
|
|
let row = cards.get_at(i % cards.count()).unwrap();
|
|
profile.collection.push(game_service::store::OwnedCard {
|
|
card: LogicDataRef::Resolved(Arc::clone(row)),
|
|
level_index: 0,
|
|
count: 1,
|
|
});
|
|
}
|
|
let avatar = build_avatar(&profile);
|
|
let progress = avatar
|
|
.commodities
|
|
.types
|
|
.get(COMMODITY_ACHIEVEMENT_PROGRESS)
|
|
.map(|slots| slots.iter().filter(|s| s.count >= required).count())
|
|
.unwrap_or(0);
|
|
assert!(progress > 0, "the served progress should complete a findcard tier");
|
|
let mut home = LogicHomeMode::new(LogicClientHome::default(), avatar, 0);
|
|
let before_level = home.avatar().exp_level;
|
|
let before_points = home.avatar().exp_points;
|
|
let command = LogicClaimAchievementRewardCommand {
|
|
achievement: LogicDataRef::by_name(table::ACHIEVEMENTS, &name),
|
|
header: LogicCommandHeader::default(),
|
|
};
|
|
let outcome = home.execute(&command);
|
|
assert_eq!(outcome, CommandOutcome::Applied, "the claim should be accepted");
|
|
assert!(
|
|
home.avatar().exp_points != before_points || home.avatar().exp_level != before_level,
|
|
"claiming should have granted exp"
|
|
);
|
|
assert!(matches!(home.execute(&command), CommandOutcome::Rejected(_)));
|
|
}
|