2020-01-25 13:01:34 -08:00
|
|
|
use std::convert::{From, Into, TryFrom, TryInto};
|
|
|
|
use std::collections::HashMap;
|
|
|
|
|
2020-02-27 23:58:00 -04:00
|
|
|
use libpso::packet::ship::{UpdateConfig, WriteInfoboard};
|
2020-04-20 00:29:23 -03:00
|
|
|
use libpso::character::character::{Character, FullCharacter};
|
2020-03-18 18:21:34 -07:00
|
|
|
use crate::entity::item::tech::Technique;
|
2020-03-29 16:11:14 -07:00
|
|
|
use crate::entity::account::UserAccountId;
|
2019-10-05 17:37:49 -07:00
|
|
|
|
2020-01-25 13:01:34 -08:00
|
|
|
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
|
|
|
|
pub enum CharacterClass {
|
|
|
|
HUmar,
|
|
|
|
HUnewearl,
|
|
|
|
HUcast,
|
|
|
|
HUcaseal,
|
|
|
|
RAmar,
|
|
|
|
RAmarl,
|
|
|
|
RAcast,
|
|
|
|
RAcaseal,
|
|
|
|
FOmar,
|
|
|
|
FOmarl,
|
|
|
|
FOnewm,
|
|
|
|
FOnewearl,
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: TryFrom
|
|
|
|
impl From<u8> for CharacterClass {
|
|
|
|
fn from(f: u8) -> CharacterClass {
|
|
|
|
match f {
|
|
|
|
0 => CharacterClass::HUmar,
|
|
|
|
1 => CharacterClass::HUnewearl,
|
|
|
|
2 => CharacterClass::HUcast,
|
|
|
|
3 => CharacterClass::RAmar,
|
|
|
|
4 => CharacterClass::RAcast,
|
|
|
|
5 => CharacterClass::RAcaseal,
|
|
|
|
6 => CharacterClass::FOmarl,
|
|
|
|
7 => CharacterClass::FOnewm,
|
|
|
|
8 => CharacterClass::FOnewearl,
|
|
|
|
9 => CharacterClass::HUcaseal,
|
2020-03-21 21:44:48 -07:00
|
|
|
10 => CharacterClass::FOmar,
|
|
|
|
11 => CharacterClass::RAmarl,
|
2020-01-25 13:01:34 -08:00
|
|
|
_ => panic!("unknown class")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Into<u8> for CharacterClass {
|
|
|
|
fn into(self) -> u8 {
|
|
|
|
match self {
|
|
|
|
CharacterClass::HUmar => 0,
|
|
|
|
CharacterClass::HUnewearl => 1,
|
|
|
|
CharacterClass::HUcast => 2,
|
|
|
|
CharacterClass::RAmar => 3,
|
|
|
|
CharacterClass::RAcast => 4,
|
|
|
|
CharacterClass::RAcaseal => 5,
|
|
|
|
CharacterClass::FOmarl => 6,
|
|
|
|
CharacterClass::FOnewm => 7,
|
|
|
|
CharacterClass::FOnewearl => 8,
|
|
|
|
CharacterClass::HUcaseal => 9,
|
2020-03-21 21:44:48 -07:00
|
|
|
CharacterClass::FOmar => 10,
|
|
|
|
CharacterClass::RAmarl => 11,
|
2020-01-25 13:01:34 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-03-14 10:44:27 -07:00
|
|
|
#[derive(Copy, Clone, Hash, PartialEq, Eq, derive_more::Display)]
|
2020-01-25 13:01:34 -08:00
|
|
|
pub enum SectionID {
|
|
|
|
Viridia,
|
|
|
|
Greenill,
|
|
|
|
Skyly,
|
|
|
|
Bluefull,
|
|
|
|
Purplenum,
|
|
|
|
Pinkal,
|
|
|
|
Redria,
|
|
|
|
Oran,
|
|
|
|
Yellowboze,
|
|
|
|
Whitill,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<u8> for SectionID {
|
|
|
|
fn from(id: u8) -> SectionID {
|
|
|
|
match id {
|
|
|
|
0 => SectionID::Viridia,
|
|
|
|
1 => SectionID::Greenill,
|
|
|
|
2 => SectionID::Skyly,
|
|
|
|
3 => SectionID::Bluefull,
|
|
|
|
4 => SectionID::Purplenum,
|
|
|
|
5 => SectionID::Pinkal,
|
|
|
|
6 => SectionID::Redria,
|
|
|
|
7 => SectionID::Oran,
|
|
|
|
8 => SectionID::Yellowboze,
|
|
|
|
9 => SectionID::Whitill,
|
|
|
|
_ => panic!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Into<u8> for SectionID {
|
|
|
|
fn into(self) -> u8 {
|
|
|
|
match self {
|
|
|
|
SectionID::Viridia => 0,
|
|
|
|
SectionID::Greenill => 1,
|
|
|
|
SectionID::Skyly => 2,
|
|
|
|
SectionID::Bluefull => 3,
|
|
|
|
SectionID::Purplenum => 4,
|
|
|
|
SectionID::Pinkal => 5,
|
|
|
|
SectionID::Redria => 6,
|
|
|
|
SectionID::Oran => 7,
|
|
|
|
SectionID::Yellowboze => 8,
|
|
|
|
SectionID::Whitill => 9,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, Default)]
|
|
|
|
pub struct CharacterAppearance {
|
|
|
|
pub costume: u16,
|
|
|
|
pub skin: u16,
|
|
|
|
pub face: u16,
|
|
|
|
pub head: u16,
|
|
|
|
pub hair: u16,
|
|
|
|
pub hair_r: u16,
|
|
|
|
pub hair_g: u16,
|
|
|
|
pub hair_b: u16,
|
|
|
|
pub prop_x: f32,
|
|
|
|
pub prop_y: f32,
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
2020-01-25 13:29:01 -08:00
|
|
|
pub struct TechLevel(pub u8);
|
2020-01-25 13:01:34 -08:00
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub struct CharacterTechniques {
|
2020-01-25 13:29:01 -08:00
|
|
|
techs: HashMap<Technique, TechLevel>
|
2020-01-25 13:01:34 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl CharacterTechniques {
|
|
|
|
fn new() -> CharacterTechniques {
|
|
|
|
CharacterTechniques {
|
|
|
|
techs: HashMap::new(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-25 13:29:01 -08:00
|
|
|
pub fn set_tech(&mut self, tech: Technique, level: TechLevel) {
|
2020-01-25 13:01:34 -08:00
|
|
|
self.techs.insert(tech, level);
|
|
|
|
}
|
|
|
|
|
|
|
|
// from_bytes
|
|
|
|
|
2020-01-25 13:29:01 -08:00
|
|
|
pub fn as_bytes(&self) -> [u8; 20] {
|
2020-01-25 13:01:34 -08:00
|
|
|
self.techs.iter()
|
|
|
|
.fold([0xFF; 20], |mut techlist, (tech, level)| {
|
|
|
|
let index = match tech {
|
2020-01-25 13:29:01 -08:00
|
|
|
Technique::Foie => 0,
|
|
|
|
Technique::Gifoie => 1,
|
|
|
|
Technique::Rafoie => 2,
|
|
|
|
Technique::Barta => 3,
|
|
|
|
Technique::Gibarta => 4,
|
|
|
|
Technique::Rabarta => 5,
|
|
|
|
Technique::Zonde => 6,
|
|
|
|
Technique::Gizonde => 7,
|
|
|
|
Technique::Razonde => 8,
|
|
|
|
Technique::Grants => 9,
|
|
|
|
Technique::Deband => 10,
|
|
|
|
Technique::Jellen => 11,
|
|
|
|
Technique::Zalure => 12,
|
|
|
|
Technique::Shifta => 13,
|
|
|
|
Technique::Ryuker => 14,
|
|
|
|
Technique::Resta => 15,
|
|
|
|
Technique::Anti => 16,
|
|
|
|
Technique::Reverser => 17,
|
|
|
|
Technique::Megid => 18,
|
2020-01-25 13:01:34 -08:00
|
|
|
};
|
|
|
|
|
2020-01-25 13:29:01 -08:00
|
|
|
techlist[index] = level.0 - 1;
|
2020-01-25 13:01:34 -08:00
|
|
|
techlist
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct CharacterConfig {
|
|
|
|
raw_data: [u8; 0xE8],
|
|
|
|
}
|
|
|
|
|
|
|
|
impl CharacterConfig {
|
|
|
|
fn new() -> CharacterConfig {
|
|
|
|
CharacterConfig {
|
2020-04-19 23:16:44 -03:00
|
|
|
raw_data: Character::default().config,
|
2020-01-25 13:01:34 -08:00
|
|
|
}
|
|
|
|
}
|
2020-02-24 21:17:59 -04:00
|
|
|
|
|
|
|
pub fn update(&mut self, new_config: &UpdateConfig) {
|
|
|
|
self.raw_data = new_config.config;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn as_bytes(&self) -> [u8; 0xE8] {
|
|
|
|
self.raw_data
|
|
|
|
}
|
2020-01-25 13:01:34 -08:00
|
|
|
}
|
|
|
|
|
2020-02-27 23:58:00 -04:00
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct CharacterInfoboard {
|
|
|
|
board: [u16; 172],
|
|
|
|
}
|
|
|
|
|
|
|
|
impl CharacterInfoboard {
|
|
|
|
fn new() -> CharacterInfoboard {
|
|
|
|
CharacterInfoboard {
|
|
|
|
board: [0; 172]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-01 02:57:18 -04:00
|
|
|
pub fn as_bytes(&self) -> [u16; 172] {
|
2020-02-27 23:58:00 -04:00
|
|
|
self.board
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn update_infoboard(&mut self, new_board: &WriteInfoboard) {
|
|
|
|
self.board = libpso::utf8_to_utf16_array!(new_board.message, 172);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-29 13:27:23 -07:00
|
|
|
#[derive(Clone, Default)]
|
|
|
|
pub struct CharacterGuildCard {
|
|
|
|
pub description: String,
|
|
|
|
}
|
2020-01-25 13:01:34 -08:00
|
|
|
|
2020-04-20 00:29:23 -03:00
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct CharacterTechMenu {
|
|
|
|
pub tech_menu: [u8; 40],
|
|
|
|
}
|
|
|
|
|
|
|
|
impl CharacterTechMenu {
|
|
|
|
fn new() -> CharacterTechMenu {
|
|
|
|
CharacterTechMenu {
|
|
|
|
tech_menu: FullCharacter::default().tech_menu,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn as_bytes(&self) -> [u8; 40] {
|
|
|
|
self.tech_menu
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-29 14:40:24 -07:00
|
|
|
|
|
|
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
|
|
|
pub struct CharacterEntityId(pub u32);
|
|
|
|
|
2020-01-25 13:01:34 -08:00
|
|
|
#[derive(Clone)]
|
2020-03-30 19:28:49 -07:00
|
|
|
pub struct NewCharacterEntity {
|
2020-03-29 16:11:14 -07:00
|
|
|
pub user_id: UserAccountId,
|
2019-10-06 11:22:33 -07:00
|
|
|
pub slot: u32,
|
2020-01-25 13:01:34 -08:00
|
|
|
|
|
|
|
pub name: String,
|
|
|
|
pub exp: u32,
|
|
|
|
|
|
|
|
pub char_class: CharacterClass,
|
|
|
|
pub section_id: SectionID,
|
|
|
|
|
|
|
|
pub appearance: CharacterAppearance,
|
|
|
|
pub techs: CharacterTechniques,
|
|
|
|
pub config: CharacterConfig,
|
2020-02-27 23:58:00 -04:00
|
|
|
pub info_board: CharacterInfoboard,
|
2020-03-29 13:27:23 -07:00
|
|
|
pub guildcard: CharacterGuildCard,
|
2020-04-20 00:29:23 -03:00
|
|
|
|
|
|
|
pub tech_menu: CharacterTechMenu,
|
2020-01-25 13:01:34 -08:00
|
|
|
}
|
|
|
|
|
2020-03-30 19:28:49 -07:00
|
|
|
impl NewCharacterEntity {
|
|
|
|
pub fn new(user: UserAccountId) -> NewCharacterEntity {
|
|
|
|
NewCharacterEntity {
|
2020-03-29 22:00:07 -07:00
|
|
|
user_id: user,
|
2020-01-25 13:01:34 -08:00
|
|
|
slot: 0,
|
|
|
|
name: "".into(),
|
|
|
|
exp: 0,
|
|
|
|
char_class: CharacterClass::HUmar,
|
|
|
|
section_id: SectionID::Viridia,
|
|
|
|
appearance: CharacterAppearance::default(),
|
|
|
|
techs: CharacterTechniques::new(),
|
|
|
|
config: CharacterConfig::new(),
|
2020-02-27 23:58:00 -04:00
|
|
|
info_board: CharacterInfoboard::new(),
|
2020-03-29 13:27:23 -07:00
|
|
|
guildcard: CharacterGuildCard::default(),
|
2020-04-20 00:29:23 -03:00
|
|
|
tech_menu: CharacterTechMenu::new(),
|
2020-01-25 13:01:34 -08:00
|
|
|
}
|
|
|
|
}
|
2019-11-20 22:49:13 -08:00
|
|
|
}
|
2020-03-30 19:28:49 -07:00
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct CharacterEntity {
|
|
|
|
pub id: CharacterEntityId,
|
|
|
|
pub user_id: UserAccountId,
|
|
|
|
pub slot: u32,
|
|
|
|
|
|
|
|
pub name: String,
|
|
|
|
pub exp: u32,
|
|
|
|
|
|
|
|
pub char_class: CharacterClass,
|
|
|
|
pub section_id: SectionID,
|
|
|
|
|
|
|
|
pub appearance: CharacterAppearance,
|
|
|
|
pub techs: CharacterTechniques,
|
|
|
|
pub config: CharacterConfig,
|
|
|
|
pub info_board: CharacterInfoboard,
|
|
|
|
pub guildcard: CharacterGuildCard,
|
2020-04-20 00:29:23 -03:00
|
|
|
|
|
|
|
pub tech_menu: CharacterTechMenu,
|
2020-03-30 19:28:49 -07:00
|
|
|
}
|