diff --git a/crates/game-service/src/battle.rs b/crates/game-service/src/battle.rs index 57da1ec..10bf0c7 100644 --- a/crates/game-service/src/battle.rs +++ b/crates/game-service/src/battle.rs @@ -2,16 +2,18 @@ use std::path::{Path, PathBuf}; use logic::battle::{ LogicBattle, LogicCharacter, LogicCharacterBuffComponent, LogicCombatComponent, LogicComponent, LogicGameMode, LogicGameObject, LogicGameObjectEntry, LogicGameObjectManager, - LogicGameObjectRef, LogicHitpointComponent, LogicObjectBody, LogicSummoner, LogicTilemap, + LogicGameObjectRef, LogicHitpointComponent, LogicObjectBody, LogicSummoner, LogicSummonerDeck, + LogicTilemap, LogicTime, LogicVector2, BATTLE_TYPE_NPC, CHARACTER_OBJECT_TYPE, DIRECTION_BOTTOM, DIRECTION_TOP, SUBTILE_UNITS, }; use logic::model::{LogicClientAvatar, LogicSpellDeck}; -use logic::{table, LogicDataRef, LogicDataTables, LogicRandom}; +use logic::{table, LogicDataRef, LogicDataTables, LogicGlobals, LogicRandom}; pub const LOCATION_FILE_COLUMN: &str = "FileName"; pub const CHARACTER_KING_TOWER: &str = "KingTower"; pub const CHARACTER_PRINCESS_TOWER: &str = "PrincessTower"; pub const BUFF_ARRAY_TABLE: i32 = table::DAMAGE_TYPES; +pub const START_MANA_GLOBAL: &str = "START_MANA"; pub struct TowerSpec { pub data: LogicDataRef, pub instance: i32, @@ -20,10 +22,12 @@ pub struct TowerSpec { pub level_index: i32, pub is_leader: bool, pub summoner: bool, + pub deck_slots: usize, } pub struct BattleBuilder { root: PathBuf, buff_type_count: usize, + start_mana: i32, } fn tile_to_units(tile: i32) -> i32 { tile.saturating_mul(SUBTILE_UNITS) @@ -54,6 +58,7 @@ impl BattleBuilder { Self { root: root.as_ref().to_path_buf(), buff_type_count, + start_mana: LogicGlobals::number(START_MANA_GLOBAL), } } pub fn buff_type_count(&self) -> usize { @@ -78,6 +83,7 @@ impl BattleBuilder { level_index, is_leader, summoner, + deck_slots, } = spec; let hitpoints = data .data() @@ -105,6 +111,8 @@ impl BattleBuilder { let body = if summoner { LogicObjectBody::Summoner(Box::new(LogicSummoner { character, + deck: Some(LogicSummonerDeck::starting(deck_slots)), + mana: self.start_mana, ..LogicSummoner::default() })) } else { @@ -145,6 +153,10 @@ impl BattleBuilder { "no KingTower row in the character tables", )); } + let deck_slots = [ + decks[0].as_ref().map(LogicSpellDeck::filled_slot_count).unwrap_or(0), + decks[1].as_ref().map(LogicSpellDeck::filled_slot_count).unwrap_or(0), + ]; let mut objects = LogicGameObjectManager::default(); let mut leaders = [LogicGameObjectRef::NONE; 2]; let mut towers: [Vec; 2] = [Vec::new(), Vec::new()]; @@ -159,6 +171,7 @@ impl BattleBuilder { level_index: 0, is_leader: true, summoner: true, + deck_slots: deck_slots[owner], }); leaders[owner] = entry.global_id; objects.push(entry); @@ -175,6 +188,7 @@ impl BattleBuilder { level_index: 0, is_leader: false, summoner: false, + deck_slots: 0, }); towers[owner].push(entry.global_id); objects.push(entry); diff --git a/crates/logic/src/battle/logic_character.rs b/crates/logic/src/battle/logic_character.rs index 186d446..dd6e58d 100644 --- a/crates/logic/src/battle/logic_character.rs +++ b/crates/logic/src/battle/logic_character.rs @@ -3,6 +3,7 @@ use crate::battle::logic_game_object::{LogicGameObject, LogicVector2}; pub const DIRECTION_TOP: i32 = 256; pub const DIRECTION_BOTTOM: i32 = -256; pub const DEFAULT_SIZE: i32 = 100; +pub const SUMMONER_HAND_SIZE: usize = 4; #[derive(Debug, Clone, PartialEq, Eq)] pub struct LogicCharacter { pub level_index: i32, @@ -92,26 +93,39 @@ pub struct LogicSummoner { #[derive(Debug, Clone, PartialEq, Eq)] pub struct LogicSummonerDeck { pub field_220: i32, - pub hand: [i32; 4], + pub hand: [i32; SUMMONER_HAND_SIZE], pub draw_pile: Vec, pub used_pile: Vec, pub last_used_index: i32, - pub field_248: i32, + pub spell_cooldown: i32, pub field_240: i32, } impl Default for LogicSummonerDeck { fn default() -> Self { Self { field_220: 0, - hand: [-1; 4], + hand: [-1; SUMMONER_HAND_SIZE], draw_pile: Vec::new(), used_pile: Vec::new(), last_used_index: -1, - field_248: 0, + spell_cooldown: 0, field_240: 0, } } } +impl LogicSummonerDeck { + pub fn starting(slot_count: usize) -> Self { + let mut hand = [-1; SUMMONER_HAND_SIZE]; + for (slot, index) in hand.iter_mut().zip(0..slot_count as i32) { + *slot = index; + } + Self { + hand, + draw_pile: (SUMMONER_HAND_SIZE as i32..slot_count as i32).collect(), + ..Self::default() + } + } +} impl LogicSummoner { pub fn encode(&self, writer: &mut ByteStreamWriter) -> Result<()> { self.character.encode(writer)?; @@ -132,7 +146,7 @@ impl LogicSummoner { writer.write_vint(*value); } writer.write_vint(deck.last_used_index); - writer.write_vint(deck.field_248); + writer.write_vint(deck.spell_cooldown); writer.write_vint(deck.field_240); } }