combat system 2nd pass - multiattacks for natural attackers
This commit is contained in:
parent
42113ad6a4
commit
a17a2c8f11
7 changed files with 247 additions and 174 deletions
|
|
@ -127,7 +127,7 @@
|
|||
"id": "horse_little",
|
||||
"name": "pony",
|
||||
"renderable": { "glyph": "u", "fg": "#b36c29", "bg": "#000000", "order": 1 },
|
||||
"flags": ["BYSTANDER", "BLOCKS_TILE"],
|
||||
"flags": ["BYSTANDER", "BLOCKS_TILE", "MULTIATTACK"],
|
||||
"level": 3,
|
||||
"bac": 6,
|
||||
"vision_range": 8,
|
||||
|
|
@ -140,7 +140,7 @@
|
|||
"id": "horse",
|
||||
"name": "horse",
|
||||
"renderable": { "glyph": "u", "fg": "#744d29", "bg": "#000000", "order": 1 },
|
||||
"flags": ["MONSTER", "BLOCKS_TILE"],
|
||||
"flags": ["MONSTER", "BLOCKS_TILE", "MULTIATTACK"],
|
||||
"level": 5,
|
||||
"bac": 5,
|
||||
"vision_range": 8,
|
||||
|
|
@ -153,7 +153,7 @@
|
|||
"id": "horse_large",
|
||||
"name": "warhorse",
|
||||
"renderable": { "glyph": "u", "fg": "#8a3520", "bg": "#000000", "order": 1 },
|
||||
"flags": ["MONSTER", "BLOCKS_TILE"],
|
||||
"flags": ["MONSTER", "BLOCKS_TILE", "MULTIATTACK"],
|
||||
"level": 7,
|
||||
"bac": 4,
|
||||
"vision_range": 8,
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@
|
|||
{ "id": "goblin_chieftain", "weight": 1, "difficulty": 3},
|
||||
{ "id": "ogre", "weight": 1, "difficulty": 4},
|
||||
{ "id": "horse_little", "weight": 2, "difficulty": 4},
|
||||
{ "id": "dog", "weight": 1, "difficulty": 5},
|
||||
{ "id": "dog", "weight": 1, "difficulty": 5},
|
||||
{ "id": "wolf", "weight": 2, "difficulty": 6},
|
||||
{ "id": "dog_large", "weight": 1, "difficulty": 7},
|
||||
{ "id": "horse", "weight": 2, "difficulty": 7},
|
||||
|
|
|
|||
|
|
@ -320,3 +320,6 @@ pub struct EntryTrigger {}
|
|||
|
||||
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct EntityMoved {}
|
||||
|
||||
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct MultiAttack {}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ mod rex_assets;
|
|||
extern crate lazy_static;
|
||||
|
||||
//Consts
|
||||
pub const SHOW_MAPGEN: bool = true;
|
||||
pub const SHOW_MAPGEN: bool = false;
|
||||
|
||||
#[derive(PartialEq, Copy, Clone)]
|
||||
pub enum RunState {
|
||||
|
|
@ -558,6 +558,7 @@ fn main() -> rltk::BError {
|
|||
gs.ecs.register::<Hidden>();
|
||||
gs.ecs.register::<EntryTrigger>();
|
||||
gs.ecs.register::<EntityMoved>();
|
||||
gs.ecs.register::<MultiAttack>();
|
||||
gs.ecs.register::<ParticleLifetime>();
|
||||
gs.ecs.register::<SimpleMarker<SerializeMe>>();
|
||||
gs.ecs.register::<SerializationHelper>();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use super::{
|
||||
gamelog, gamesystem, ArmourClassBonus, Attributes, EquipmentSlot, Equipped, HungerClock, HungerState, MeleeWeapon,
|
||||
Name, NaturalAttacks, ParticleBuilder, Pools, Position, Skill, Skills, SufferDamage, WantsToMelee, WeaponAttribute,
|
||||
MultiAttack, Name, NaturalAttack, NaturalAttacks, ParticleBuilder, Pools, Position, Skill, Skills, SufferDamage,
|
||||
WantsToMelee, WeaponAttribute,
|
||||
};
|
||||
use specs::prelude::*;
|
||||
|
||||
|
|
@ -23,6 +24,7 @@ impl<'a> System<'a> for MeleeCombatSystem {
|
|||
ReadStorage<'a, NaturalAttacks>,
|
||||
ReadStorage<'a, ArmourClassBonus>,
|
||||
ReadStorage<'a, HungerClock>,
|
||||
ReadStorage<'a, MultiAttack>,
|
||||
WriteExpect<'a, rltk::RandomNumberGenerator>,
|
||||
);
|
||||
|
||||
|
|
@ -43,6 +45,7 @@ impl<'a> System<'a> for MeleeCombatSystem {
|
|||
natural_attacks,
|
||||
ac,
|
||||
hunger_clock,
|
||||
multi_attackers,
|
||||
mut rng,
|
||||
) = data;
|
||||
|
||||
|
|
@ -64,201 +67,214 @@ impl<'a> System<'a> for MeleeCombatSystem {
|
|||
for (entity, wants_melee, name, attacker_attributes, attacker_skills, attacker_pools) in
|
||||
(&entities, &wants_melee, &names, &attributes, &skills, &pools).join()
|
||||
{
|
||||
let target_pools = pools.get(wants_melee.target).unwrap();
|
||||
let target_attributes = attributes.get(wants_melee.target).unwrap();
|
||||
let target_skills = skills.get(wants_melee.target).unwrap();
|
||||
|
||||
if attacker_pools.hit_points.current <= 0 {
|
||||
break;
|
||||
// Create blank vector of attacks being attempted.
|
||||
let mut attacks: Vec<(MeleeWeapon, String)> = Vec::new();
|
||||
let mut multi_attack = false;
|
||||
// Check if attacker can multi-attack.
|
||||
if let Some(_) = multi_attackers.get(entity) {
|
||||
multi_attack = true;
|
||||
}
|
||||
if target_pools.hit_points.current <= 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
let target_name = names.get(wants_melee.target).unwrap();
|
||||
|
||||
let mut weapon_info = MeleeWeapon {
|
||||
attribute: WeaponAttribute::Strength,
|
||||
hit_bonus: 0,
|
||||
damage_n_dice: 1,
|
||||
damage_die_type: 4,
|
||||
damage_bonus: 0,
|
||||
};
|
||||
let mut attack_verb = "hits";
|
||||
|
||||
if let Some(nat) = natural_attacks.get(entity) {
|
||||
if !nat.attacks.is_empty() {
|
||||
let attack_index = if nat.attacks.len() == 1 {
|
||||
0
|
||||
} else {
|
||||
rng.roll_dice(1, nat.attacks.len() as i32) as usize - 1
|
||||
};
|
||||
weapon_info.hit_bonus = nat.attacks[attack_index].hit_bonus;
|
||||
weapon_info.damage_n_dice = nat.attacks[attack_index].damage_n_dice;
|
||||
weapon_info.damage_die_type = nat.attacks[attack_index].damage_die_type;
|
||||
weapon_info.damage_bonus = nat.attacks[attack_index].damage_bonus;
|
||||
attack_verb = &nat.attacks[attack_index].name;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if attacker is using a weapon.
|
||||
let mut using_weapon = false;
|
||||
for (wielded, melee) in (&equipped, &melee_weapons).join() {
|
||||
if wielded.owner == entity && wielded.slot == EquipmentSlot::Melee {
|
||||
weapon_info = melee.clone();
|
||||
using_weapon = get_weapon_attack(wielded, melee, entity, &mut attacks);
|
||||
}
|
||||
}
|
||||
|
||||
// Get all offensive bonuses
|
||||
let d20 = rng.roll_dice(1, 20);
|
||||
let attribute_hit_bonus = attacker_attributes.dexterity.bonus;
|
||||
let skill_hit_bonus = gamesystem::skill_bonus(Skill::Melee, &*attacker_skills);
|
||||
let weapon_hit_bonus = weapon_info.hit_bonus;
|
||||
let mut status_hit_bonus = 0;
|
||||
let hc = hunger_clock.get(entity);
|
||||
if let Some(hc) = hc {
|
||||
match hc.state {
|
||||
HungerState::Satiated => {
|
||||
status_hit_bonus += 1;
|
||||
}
|
||||
HungerState::Weak => {
|
||||
status_hit_bonus -= 1;
|
||||
}
|
||||
HungerState::Fainting => {
|
||||
status_hit_bonus -= 2;
|
||||
}
|
||||
_ => {}
|
||||
// If not using a weapon, get natural attacks. If we
|
||||
// are a multiattacker, get every natural attack. If
|
||||
// not, just pick one at random.
|
||||
if !using_weapon {
|
||||
if let Some(nat) = natural_attacks.get(entity) {
|
||||
get_natural_attacks(&mut rng, nat.clone(), multi_attack, &mut attacks);
|
||||
} else {
|
||||
attacks.push((
|
||||
MeleeWeapon {
|
||||
attribute: WeaponAttribute::Strength,
|
||||
hit_bonus: 0,
|
||||
damage_n_dice: 1,
|
||||
damage_die_type: 4,
|
||||
damage_bonus: 0,
|
||||
},
|
||||
"punches".to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
let attacker_bonuses =
|
||||
attacker_pools.level + attribute_hit_bonus + skill_hit_bonus + weapon_hit_bonus + status_hit_bonus;
|
||||
|
||||
// Get armour class
|
||||
let bac = target_pools.bac;
|
||||
let attribute_ac_bonus = target_attributes.dexterity.bonus;
|
||||
let skill_ac_bonus = gamesystem::skill_bonus(Skill::Defence, &*target_skills);
|
||||
let mut armour_ac_bonus = 0;
|
||||
for (wielded, ac) in (&equipped, &ac).join() {
|
||||
if wielded.owner == wants_melee.target {
|
||||
armour_ac_bonus += ac.amount;
|
||||
// For every attack, do combat calcs. Break if someone dies.
|
||||
for attack in attacks {
|
||||
let target_pools = pools.get(wants_melee.target).unwrap();
|
||||
let target_attributes = attributes.get(wants_melee.target).unwrap();
|
||||
let target_skills = skills.get(wants_melee.target).unwrap();
|
||||
if attacker_pools.hit_points.current <= 0 {
|
||||
break;
|
||||
}
|
||||
if target_pools.hit_points.current <= 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
let actual_armour_class = bac - attribute_ac_bonus - skill_ac_bonus - armour_ac_bonus;
|
||||
let mut armour_class_roll = actual_armour_class;
|
||||
|
||||
if actual_armour_class < 0 {
|
||||
// Invert armour class so we can roll 1d(AC)
|
||||
armour_class_roll = rng.roll_dice(1, -actual_armour_class);
|
||||
// Invert result so it's a negative again
|
||||
armour_class_roll = -armour_class_roll;
|
||||
}
|
||||
let weapon_info = attack.0;
|
||||
let attack_verb = attack.1;
|
||||
|
||||
let target_number = 10 + armour_class_roll + attacker_bonuses;
|
||||
|
||||
if COMBAT_LOGGING {
|
||||
rltk::console::log(format!(
|
||||
"ATTACKLOG: {} *{}* {}: rolled ({}) 1d20 vs. {} (10 + {}AC + {}to-hit)",
|
||||
&name.name, attack_verb, &target_name.name, d20, target_number, armour_class_roll, attacker_bonuses
|
||||
));
|
||||
}
|
||||
|
||||
if d20 < target_number {
|
||||
// Target hit!
|
||||
let base_damage = rng.roll_dice(weapon_info.damage_n_dice, weapon_info.damage_die_type);
|
||||
let skill_damage_bonus = gamesystem::skill_bonus(Skill::Melee, &*attacker_skills);
|
||||
let mut attribute_damage_bonus = weapon_info.damage_bonus;
|
||||
match weapon_info.attribute {
|
||||
WeaponAttribute::Dexterity => attribute_damage_bonus += attacker_attributes.dexterity.bonus,
|
||||
WeaponAttribute::Strength => attribute_damage_bonus += attacker_attributes.strength.bonus,
|
||||
WeaponAttribute::Finesse => {
|
||||
if attacker_attributes.dexterity.bonus > attacker_attributes.strength.bonus {
|
||||
attribute_damage_bonus += attacker_attributes.dexterity.bonus;
|
||||
} else {
|
||||
attribute_damage_bonus += attacker_attributes.strength.bonus;
|
||||
// Get all offensive bonuses
|
||||
let d20 = rng.roll_dice(1, 20);
|
||||
let attribute_hit_bonus = attacker_attributes.dexterity.bonus;
|
||||
let skill_hit_bonus = gamesystem::skill_bonus(Skill::Melee, &*attacker_skills);
|
||||
let weapon_hit_bonus = weapon_info.hit_bonus;
|
||||
let mut status_hit_bonus = 0;
|
||||
let hc = hunger_clock.get(entity);
|
||||
if let Some(hc) = hc {
|
||||
match hc.state {
|
||||
HungerState::Satiated => {
|
||||
status_hit_bonus += 1;
|
||||
}
|
||||
HungerState::Weak => {
|
||||
status_hit_bonus -= 1;
|
||||
}
|
||||
HungerState::Fainting => {
|
||||
status_hit_bonus -= 2;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
let mut damage = i32::max(0, base_damage + skill_damage_bonus + attribute_damage_bonus);
|
||||
let attacker_bonuses =
|
||||
attacker_pools.level + attribute_hit_bonus + skill_hit_bonus + weapon_hit_bonus + status_hit_bonus;
|
||||
|
||||
// Get armour class
|
||||
let bac = target_pools.bac;
|
||||
let attribute_ac_bonus = target_attributes.dexterity.bonus;
|
||||
let skill_ac_bonus = gamesystem::skill_bonus(Skill::Defence, &*target_skills);
|
||||
let mut armour_ac_bonus = 0;
|
||||
for (wielded, ac) in (&equipped, &ac).join() {
|
||||
if wielded.owner == wants_melee.target {
|
||||
armour_ac_bonus += ac.amount;
|
||||
}
|
||||
}
|
||||
let actual_armour_class = bac - attribute_ac_bonus - skill_ac_bonus - armour_ac_bonus;
|
||||
let mut armour_class_roll = actual_armour_class;
|
||||
|
||||
if actual_armour_class < 0 {
|
||||
// Invert armour class so we can roll 1d(AC)
|
||||
armour_class_roll = rng.roll_dice(1, -actual_armour_class);
|
||||
// Invert result so it's a negative again
|
||||
armour_class_roll = -armour_class_roll;
|
||||
}
|
||||
|
||||
let target_number = 10 + armour_class_roll + attacker_bonuses;
|
||||
|
||||
let target_name = names.get(wants_melee.target).unwrap();
|
||||
if COMBAT_LOGGING {
|
||||
rltk::console::log(format!(
|
||||
"ATTACKLOG: {} HIT for {} ({}[{}d{}]+{}[skill]+{}[attr])",
|
||||
"ATTACKLOG: {} *{}* {}: rolled ({}) 1d20 vs. {} (10 + {}AC + {}to-hit)",
|
||||
&name.name,
|
||||
damage,
|
||||
base_damage,
|
||||
weapon_info.damage_n_dice,
|
||||
weapon_info.damage_die_type,
|
||||
skill_damage_bonus,
|
||||
attribute_damage_bonus
|
||||
attack_verb,
|
||||
&target_name.name,
|
||||
d20,
|
||||
target_number,
|
||||
armour_class_roll,
|
||||
attacker_bonuses
|
||||
));
|
||||
}
|
||||
|
||||
if actual_armour_class < 0 {
|
||||
let ac_damage_reduction = rng.roll_dice(1, -actual_armour_class);
|
||||
damage = i32::min(1, damage - ac_damage_reduction);
|
||||
if d20 < target_number {
|
||||
// Target hit!
|
||||
let base_damage = rng.roll_dice(weapon_info.damage_n_dice, weapon_info.damage_die_type);
|
||||
let skill_damage_bonus = gamesystem::skill_bonus(Skill::Melee, &*attacker_skills);
|
||||
let mut attribute_damage_bonus = weapon_info.damage_bonus;
|
||||
match weapon_info.attribute {
|
||||
WeaponAttribute::Dexterity => attribute_damage_bonus += attacker_attributes.dexterity.bonus,
|
||||
WeaponAttribute::Strength => attribute_damage_bonus += attacker_attributes.strength.bonus,
|
||||
WeaponAttribute::Finesse => {
|
||||
if attacker_attributes.dexterity.bonus > attacker_attributes.strength.bonus {
|
||||
attribute_damage_bonus += attacker_attributes.dexterity.bonus;
|
||||
} else {
|
||||
attribute_damage_bonus += attacker_attributes.strength.bonus;
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut damage = i32::max(0, base_damage + skill_damage_bonus + attribute_damage_bonus);
|
||||
|
||||
if COMBAT_LOGGING {
|
||||
rltk::console::log(format!(
|
||||
"ATTACKLOG: {} reduced their damage taken by {} (1dAC), and took {} hp damage.",
|
||||
&target_name.name, ac_damage_reduction, damage
|
||||
"ATTACKLOG: {} HIT for {} ({}[{}d{}]+{}[skill]+{}[attr])",
|
||||
&name.name,
|
||||
damage,
|
||||
base_damage,
|
||||
weapon_info.damage_n_dice,
|
||||
weapon_info.damage_die_type,
|
||||
skill_damage_bonus,
|
||||
attribute_damage_bonus
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
let pos = positions.get(wants_melee.target);
|
||||
if let Some(pos) = pos {
|
||||
particle_builder.damage_taken(pos.x, pos.y)
|
||||
}
|
||||
SufferDamage::new_damage(&mut inflict_damage, wants_melee.target, damage, entity == *player_entity);
|
||||
if entity == *player_entity {
|
||||
gamelog::Logger::new() // You hit the <name>.
|
||||
.append("You hit the")
|
||||
.npc_name_n(&target_name.name)
|
||||
.period()
|
||||
.log();
|
||||
} else if wants_melee.target == *player_entity {
|
||||
gamelog::Logger::new() // <name> hits you!
|
||||
.append("The")
|
||||
.npc_name(&name.name)
|
||||
.append(attack_verb)
|
||||
.append("you!")
|
||||
.log();
|
||||
} else {
|
||||
gamelog::Logger::new() // <name> misses the <target>.
|
||||
.append("The")
|
||||
.npc_name(&name.name)
|
||||
.append(attack_verb)
|
||||
.append("the")
|
||||
.npc_name_n(&target_name.name)
|
||||
.period()
|
||||
.log();
|
||||
}
|
||||
} else {
|
||||
if COMBAT_LOGGING {
|
||||
rltk::console::log(format!("ATTACKLOG: {} *MISSED*", &name.name));
|
||||
}
|
||||
if actual_armour_class < 0 {
|
||||
let ac_damage_reduction = rng.roll_dice(1, -actual_armour_class);
|
||||
damage = i32::min(1, damage - ac_damage_reduction);
|
||||
if COMBAT_LOGGING {
|
||||
rltk::console::log(format!(
|
||||
"ATTACKLOG: {} reduced their damage taken by {} (1dAC), and took {} hp damage.",
|
||||
&target_name.name, ac_damage_reduction, damage
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
let pos = positions.get(wants_melee.target);
|
||||
if let Some(pos) = pos {
|
||||
particle_builder.attack_miss(pos.x, pos.y)
|
||||
}
|
||||
if entity == *player_entity {
|
||||
gamelog::Logger::new() // You miss.
|
||||
.append("You miss.")
|
||||
.log();
|
||||
} else if wants_melee.target == *player_entity {
|
||||
gamelog::Logger::new() // <name> misses!
|
||||
.append("The")
|
||||
.npc_name(&name.name)
|
||||
.colour(rltk::WHITE)
|
||||
.append("misses!")
|
||||
.log();
|
||||
let pos = positions.get(wants_melee.target);
|
||||
if let Some(pos) = pos {
|
||||
particle_builder.damage_taken(pos.x, pos.y)
|
||||
}
|
||||
SufferDamage::new_damage(&mut inflict_damage, wants_melee.target, damage, entity == *player_entity);
|
||||
if entity == *player_entity {
|
||||
gamelog::Logger::new() // You hit the <name>.
|
||||
.append("You hit the")
|
||||
.npc_name_n(&target_name.name)
|
||||
.period()
|
||||
.log();
|
||||
} else if wants_melee.target == *player_entity {
|
||||
gamelog::Logger::new() // <name> hits you!
|
||||
.append("The")
|
||||
.npc_name(&name.name)
|
||||
.append(attack_verb)
|
||||
.append("you!")
|
||||
.log();
|
||||
} else {
|
||||
gamelog::Logger::new() // <name> misses the <target>.
|
||||
.append("The")
|
||||
.npc_name(&name.name)
|
||||
.append(attack_verb)
|
||||
.append("the")
|
||||
.npc_name_n(&target_name.name)
|
||||
.period()
|
||||
.log();
|
||||
}
|
||||
} else {
|
||||
gamelog::Logger::new() // <name> misses the <target>.
|
||||
.append("The")
|
||||
.npc_name(&name.name)
|
||||
.colour(rltk::WHITE)
|
||||
.append("misses the")
|
||||
.npc_name_n(&target_name.name)
|
||||
.period()
|
||||
.log();
|
||||
if COMBAT_LOGGING {
|
||||
rltk::console::log(format!("ATTACKLOG: {} *MISSED*", &name.name));
|
||||
}
|
||||
|
||||
let pos = positions.get(wants_melee.target);
|
||||
if let Some(pos) = pos {
|
||||
particle_builder.attack_miss(pos.x, pos.y)
|
||||
}
|
||||
if entity == *player_entity {
|
||||
gamelog::Logger::new() // You miss.
|
||||
.append("You miss.")
|
||||
.log();
|
||||
} else if wants_melee.target == *player_entity {
|
||||
gamelog::Logger::new() // <name> misses!
|
||||
.append("The")
|
||||
.npc_name(&name.name)
|
||||
.colour(rltk::WHITE)
|
||||
.append("misses!")
|
||||
.log();
|
||||
} else {
|
||||
gamelog::Logger::new() // <name> misses the <target>.
|
||||
.append("The")
|
||||
.npc_name(&name.name)
|
||||
.colour(rltk::WHITE)
|
||||
.append("misses the")
|
||||
.npc_name_n(&target_name.name)
|
||||
.period()
|
||||
.log();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -266,3 +282,53 @@ impl<'a> System<'a> for MeleeCombatSystem {
|
|||
wants_melee.clear();
|
||||
}
|
||||
}
|
||||
|
||||
fn get_natural_attacks(
|
||||
rng: &mut rltk::RandomNumberGenerator,
|
||||
nat: NaturalAttacks,
|
||||
multi_attack: bool,
|
||||
attacks: &mut Vec<(MeleeWeapon, String)>,
|
||||
) {
|
||||
if !nat.attacks.is_empty() {
|
||||
if multi_attack {
|
||||
for a in nat.attacks.iter() {
|
||||
attacks.push((
|
||||
MeleeWeapon {
|
||||
attribute: WeaponAttribute::Strength,
|
||||
hit_bonus: a.hit_bonus,
|
||||
damage_n_dice: a.damage_n_dice,
|
||||
damage_die_type: a.damage_die_type,
|
||||
damage_bonus: a.damage_bonus,
|
||||
},
|
||||
a.name.to_string(),
|
||||
));
|
||||
}
|
||||
} else {
|
||||
let attack_index =
|
||||
if nat.attacks.len() == 1 { 0 } else { rng.roll_dice(1, nat.attacks.len() as i32) as usize - 1 };
|
||||
attacks.push((
|
||||
MeleeWeapon {
|
||||
attribute: WeaponAttribute::Strength,
|
||||
hit_bonus: nat.attacks[attack_index].hit_bonus,
|
||||
damage_n_dice: nat.attacks[attack_index].damage_n_dice,
|
||||
damage_die_type: nat.attacks[attack_index].damage_die_type,
|
||||
damage_bonus: nat.attacks[attack_index].damage_bonus,
|
||||
},
|
||||
nat.attacks[attack_index].name.to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_weapon_attack(
|
||||
wielded: &Equipped,
|
||||
melee: &MeleeWeapon,
|
||||
entity: Entity,
|
||||
attacks: &mut Vec<(MeleeWeapon, String)>,
|
||||
) -> bool {
|
||||
if wielded.owner == entity && wielded.slot == EquipmentSlot::Melee {
|
||||
attacks.push((melee.clone(), "hits".to_string()));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -209,6 +209,7 @@ pub fn spawn_named_mob(
|
|||
"BLOCKS_TILE" => eb = eb.with(BlocksTile {}),
|
||||
"BYSTANDER" => eb = eb.with(Bystander {}),
|
||||
"MONSTER" => eb = eb.with(Monster {}),
|
||||
"MULTIATTACK" => eb = eb.with(MultiAttack {}),
|
||||
_ => rltk::console::log(format!("Unrecognised flag: {}", flag.as_str())),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ pub fn save_game(ecs: &mut World) {
|
|||
MeleeWeapon,
|
||||
Mind,
|
||||
Monster,
|
||||
MultiAttack,
|
||||
NaturalAttacks,
|
||||
Name,
|
||||
ParticleLifetime,
|
||||
|
|
@ -175,6 +176,7 @@ pub fn load_game(ecs: &mut World) {
|
|||
MeleeWeapon,
|
||||
Mind,
|
||||
Monster,
|
||||
MultiAttack,
|
||||
NaturalAttacks,
|
||||
Name,
|
||||
ParticleLifetime,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue