use std::ops::{Index, IndexMut};
use shared::{CCallback, OwnedPtr};
use vtable_rs::VPtr;
use crate::{DLVector, dlkr::DLRunnableVmt};
#[repr(C)]
#[shared::singleton("CSTrophy")]
pub struct CSTrophyImp {
vtable: isize,
pub trophy_platform: OwnedPtr<CSTrophyPlatformImp_forSteam>,
unk10: isize,
unk18: u8,
}
#[repr(C)]
pub struct CSTrophyPlatformImp {
vftable: VPtr<dyn CSTrophyPlatformImpVmt, Self>,
pub trophy_title_info: OwnedPtr<CSTrophyTitleInfo>,
unk10: DLVector<()>,
unk30: isize,
}
#[vtable_rs::vtable]
trait CSTrophyPlatformImpVmt: DLRunnableVmt {
fn unk10(&mut self);
fn unk18(&mut self);
fn unk20(&mut self);
fn award_achievement(&mut self, achievement_id: &AchievementId);
fn unk30(&mut self);
}
#[repr(C)]
pub struct CSTrophyTitleInfo {
pub vftable: VPtr<dyn CSTrophyTitleInfoVmt, Self>,
}
#[vtable_rs::vtable]
pub trait CSTrophyTitleInfoVmt {
fn destructor(&mut self);
fn max_achievement_id(&self) -> u32;
fn unk10(&mut self);
fn achievement_name_for_id(&self, achievement_id: &AchievementId) -> *const u8;
fn achievement_key_for_id(&self, achievement_id: &AchievementId) -> *const u8;
}
#[allow(non_camel_case_types)]
#[repr(C)]
pub struct CSTrophyPlatformImp_forSteam {
pub base: CSTrophyPlatformImp,
pub steam_app_id: isize,
pub achievements: OwnedPtr<[CSTrophyPlatformImp_forSteamAchievementItem; 42]>,
pub unlocked_count: u32,
pub is_initialized: u8,
pub is_master_unlocked: bool,
pub on_user_stats_received_cb: CCallback<Self, [u8; 0x18]>,
pub on_user_stats_stored_cb: CCallback<Self, [u8; 0x10]>,
pub on_user_achievement_stored_cb: CCallback<Self, [u8; 0x98]>,
}
#[allow(non_camel_case_types)]
#[repr(C)]
pub struct CSTrophyPlatformImp_forSteamAchievementItem {
pub unlocked: bool,
title: [u16; 0x80],
}
impl CSTrophyPlatformImp_forSteamAchievementItem {
pub fn title(&self) -> String {
let length = self
.title
.iter()
.position(|c| *c == 0)
.unwrap_or(self.title.len());
String::from_utf16(&self.title[..length]).unwrap()
}
}
impl Index<AchievementId> for [CSTrophyPlatformImp_forSteamAchievementItem; 42] {
type Output = CSTrophyPlatformImp_forSteamAchievementItem;
fn index(&self, index: AchievementId) -> &Self::Output {
&self[index as usize]
}
}
impl IndexMut<AchievementId> for [CSTrophyPlatformImp_forSteamAchievementItem; 42] {
fn index_mut(&mut self, index: AchievementId) -> &mut Self::Output {
&mut self[index as usize]
}
}
#[repr(u32)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum AchievementId {
EldenRing = 0, EldenLord = 1, AgeOfTheStars = 2, LordOfFrenziedFlame = 3, ShardbearerGodrick = 4, ShardbearerRadahn = 5, ShardbearerMorgott = 6, ShardbearerRykard = 7, ShardbearerMalenia = 8, ShardbearerMohg = 9, MalikethTheBlackBlade = 10, HoarahLouxTheWarrior = 11, DragonlordPlacidusax = 12, GodSlayingArmament = 13, LegendaryArmaments = 14, LegendaryAshenRemains = 15, LegendarySorceriesAndIncantations = 16, LegendaryTalismans = 17, RennalaQueenOfTheFullMoon = 18, LichdragonFortissax = 19, GodskinDuo = 20, FireGiant = 21, DragonkinSoldierOfNokstella = 22, RegalAncestorSpirit = 23, ValiantGargoyle = 24, MargitTheFellOmen = 25, RedWolfOfRadagon = 26, GodskinNoble = 27, MagmaWyrmMakar = 28, GodfreyTheFirstLord = 29, MohgTheOmen = 30, MimicTear = 31, LorettaKnightOfTheHaligtree = 32, AstelNaturalbornOfTheVoid = 33, LeonineMisbegotten = 34, RoyalKnightLoretta = 35, ElemerOfTheBriar = 36, AncestorSpirit = 37, CommanderNiall = 38, RoundtableHold = 39, GreatRune = 40, ErdtreeAflame = 41, }
#[cfg(test)]
mod test {
use super::*;
use std::mem::size_of;
#[test]
fn proper_sizes() {
assert_eq!(0x20, size_of::<CSTrophyImp>());
assert_eq!(0x38, size_of::<CSTrophyPlatformImp>());
assert_eq!(0x8, size_of::<CSTrophyTitleInfo>());
assert_eq!(0xb0, size_of::<CSTrophyPlatformImp_forSteam>());
}
}