diff --git a/src/core/src/db.rs b/src/core/src/db.rs index e1df989..7341d4b 100644 --- a/src/core/src/db.rs +++ b/src/core/src/db.rs @@ -18,6 +18,16 @@ fn weapon_type_id(weapon_types: &[WeaponType], name: &str) // TODO: read from json/toml config fn get_weapon_types() -> Vec { vec![ + WeaponType { + name: "mortar".to_owned(), + damage: 6, + ap: 2, + accuracy: 5, + max_distance: 5, + min_distance: 1, + is_inderect: true, + reaction_fire: false, + }, WeaponType { name: "cannon".to_owned(), damage: 9, @@ -25,6 +35,8 @@ fn get_weapon_types() -> Vec { accuracy: 5, max_distance: 5, min_distance: 0, + is_inderect: false, + reaction_fire: true, }, WeaponType { name: "rifle".to_owned(), @@ -33,6 +45,8 @@ fn get_weapon_types() -> Vec { accuracy: 5, max_distance: 3, min_distance: 0, + is_inderect: false, + reaction_fire: true, }, ] } @@ -41,6 +55,7 @@ fn get_weapon_types() -> Vec { fn get_unit_types(weapon_types: &[WeaponType]) -> Vec { let cannon_id = weapon_type_id(weapon_types, "cannon"); let rifle_id = weapon_type_id(weapon_types, "rifle"); + let mortar_id = weapon_type_id(weapon_types, "mortar"); vec![ UnitType { name: "mammoth tank".to_owned(), @@ -127,6 +142,23 @@ fn get_unit_types(weapon_types: &[WeaponType]) -> Vec { is_transporter: false, is_big: false, }, + UnitType { + name: "mortar".to_owned(), + class: UnitClass::Infantry, + size: 4, + count: 1, + armor: 1, + toughness: 2, + weapon_skill: 5, + weapon_type_id: mortar_id.clone(), + move_points: MovePoints{n: 3}, + attack_points: AttackPoints{n: 2}, + reactive_attack_points: AttackPoints{n: 0}, + los_range: 6, + cover_los_range: 1, + is_transporter: false, + is_big: false, + }, ] } diff --git a/src/core/src/internal_state.rs b/src/core/src/internal_state.rs index 820fbce..c6cde49 100644 --- a/src/core/src/internal_state.rs +++ b/src/core/src/internal_state.rs @@ -86,16 +86,19 @@ impl InternalState { } /// Converts active ap (attack points) to reactive - fn convert_ap(&mut self, player_id: &PlayerId) { + fn convert_ap(&mut self, db: &Db, player_id: &PlayerId) { for (_, unit) in self.units.iter_mut() { - if unit.player_id == *player_id { - if let Some(ref mut reactive_attack_points) - = unit.reactive_attack_points - { - reactive_attack_points.n += unit.attack_points.n; - } - unit.attack_points.n = 0; + let unit_type = db.unit_type(&unit.type_id); + let weapon_type = db.weapon_type(&unit_type.weapon_type_id); + if unit.player_id != *player_id || !weapon_type.reaction_fire { + continue; + } + if let Some(ref mut reactive_attack_points) + = unit.reactive_attack_points + { + reactive_attack_points.n += unit.attack_points.n; } + unit.attack_points.n = 0; } } @@ -172,7 +175,7 @@ impl GameStateMut for InternalState { }, &CoreEvent::EndTurn{ref new_id, ref old_id} => { self.refresh_units(db, new_id); - self.convert_ap(old_id); + self.convert_ap(db, old_id); }, &CoreEvent::CreateUnit{ref unit_info} => { self.add_unit(db, unit_info, InfoLevel::Full); diff --git a/src/core/src/lib.rs b/src/core/src/lib.rs index d61097f..b84a7d4 100644 --- a/src/core/src/lib.rs +++ b/src/core/src/lib.rs @@ -157,6 +157,7 @@ pub struct AttackInfo { pub suppression: ZInt, pub remove_move_points: bool, pub is_ambush: bool, + pub is_inderect: bool, } #[derive(Clone)] @@ -422,8 +423,10 @@ fn check_attack( if distance(&attacker.pos, &defender.pos) < weapon_type.min_distance { return Err(CommandError::TooClose); } - if !los(state.map(), attacker_type, &attacker.pos.map_pos, &defender.pos.map_pos) { - return Err(CommandError::NoLos); + if !weapon_type.is_inderect { + if !los(state.map(), attacker_type, &attacker.pos.map_pos, &defender.pos.map_pos) { + return Err(CommandError::NoLos); + } } Ok(()) } @@ -739,6 +742,7 @@ impl Core { let soldier_id = self.db.unit_type_id("soldier"); let scout_id = self.db.unit_type_id("scout"); let mammoth_tank_id = self.db.unit_type_id("mammoth tank"); + let mortar_id = self.db.unit_type_id("mortar"); let p_id_0 = PlayerId{id: 0}; let p_id_1 = PlayerId{id: 1}; self.add_unit(&MapPos{v: Vector2{x: 0, y: 1}}, &tank_id, &p_id_0); @@ -749,6 +753,7 @@ impl Core { self.add_unit(&MapPos{v: Vector2{x: 0, y: 5}}, &tank_id, &p_id_0); self.add_unit(&MapPos{v: Vector2{x: 0, y: 6}}, &tank_id, &p_id_0); self.add_unit(&MapPos{v: Vector2{x: 1, y: 4}}, &mammoth_tank_id, &p_id_0); + self.add_unit(&MapPos{v: Vector2{x: 3, y: 4}}, &mortar_id, &p_id_0); self.add_unit(&MapPos{v: Vector2{x: 9, y: 1}}, &tank_id, &p_id_1); self.add_unit(&MapPos{v: Vector2{x: 9, y: 2}}, &soldier_id, &p_id_1); self.add_unit(&MapPos{v: Vector2{x: 9, y: 3}}, &scout_id, &p_id_1); @@ -852,6 +857,8 @@ impl Core { if let Err(..) = check_attack_result { return None; } + let attacker_type = self.db.unit_type(&attacker.type_id); + let weapon_type = self.db.weapon_type(&attacker_type.weapon_type_id); let killed = cmp::min( defender.count, self.get_killed_count(attacker, defender)); let fow = &self.players_info[&defender.player_id].fow; @@ -870,6 +877,7 @@ impl Core { suppression: base_suppression + per_death_suppression * killed, remove_move_points: false, is_ambush: is_ambush, + is_inderect: weapon_type.is_inderect.clone(), }; Some(CoreEvent::AttackUnit{attack_info: attack_info}) } diff --git a/src/core/src/unit.rs b/src/core/src/unit.rs index df5c492..8e1985a 100644 --- a/src/core/src/unit.rs +++ b/src/core/src/unit.rs @@ -33,6 +33,8 @@ pub struct WeaponType { pub accuracy: ZInt, pub max_distance: ZInt, pub min_distance: ZInt, + pub is_inderect: bool, + pub reaction_fire: bool, } #[derive(Clone)] diff --git a/src/visualizer/src/event_visualizer.rs b/src/visualizer/src/event_visualizer.rs index 904fc48..4432075 100644 --- a/src/visualizer/src/event_visualizer.rs +++ b/src/visualizer/src/event_visualizer.rs @@ -187,6 +187,7 @@ pub struct EventAttackUnitVisualizer { move_helper: MoveHelper, shell_move: Option, shell_node_id: Option, + is_inderect: bool, } impl EventAttackUnitVisualizer { @@ -244,6 +245,7 @@ impl EventAttackUnitVisualizer { Box::new(EventAttackUnitVisualizer { defender_node_id: defender_node_id, killed: attack_info.killed.clone(), + is_inderect: attack_info.is_inderect.clone(), is_target_destroyed: is_target_destroyed, move_helper: move_helper, shell_move: shell_move, @@ -268,7 +270,11 @@ impl EventVisualizer for EventAttackUnitVisualizer { fn draw(&mut self, scene: &mut Scene, dtime: &Time) { if let Some(ref mut shell_move) = self.shell_move { let shell_node_id = self.shell_node_id.as_ref().unwrap(); - scene.node_mut(shell_node_id).pos = shell_move.step(dtime); + let mut pos = shell_move.step(dtime); + if self.is_inderect { + pos.v.z += (shell_move.progress() * PI).sin() * 5.0; + } + scene.node_mut(shell_node_id).pos = pos; } let is_shell_ok = if let Some(ref shell_move) = self.shell_move { shell_move.is_finished() diff --git a/src/visualizer/src/tactical_screen.rs b/src/visualizer/src/tactical_screen.rs index 62d2dae..0530938 100644 --- a/src/visualizer/src/tactical_screen.rs +++ b/src/visualizer/src/tactical_screen.rs @@ -244,6 +244,12 @@ fn get_unit_type_visual_info( meshes: &mut Vec, ) -> UnitTypeVisualInfoManager { let mut manager = UnitTypeVisualInfoManager::new(); + let mortar_id = db.unit_type_id("mortar"); + let mortar_mesh_id = add_mesh(meshes, load_object_mesh(zgl, "mortar")); + manager.add_info(&mortar_id, UnitTypeVisualInfo { + mesh_id: mortar_mesh_id, + move_speed: 1.5, + }); let mammoth_tank_id = db.unit_type_id("mammoth tank"); let mammoth_tank_mesh_id = add_mesh(meshes, load_object_mesh(zgl, "mammoth")); manager.add_info(&mammoth_tank_id, UnitTypeVisualInfo {