Pets no longer drop loot on death. Code to determine targeting of pets is less hacky and now takes into account alignment of their owner.

This commit is contained in:
Sam 2021-03-23 18:41:17 -04:00
parent 8e4aeff705
commit f9835e78da
4 changed files with 52 additions and 36 deletions

View File

@ -8,7 +8,7 @@ BasicSummon(
species: Darkhound,
body_type: Male,
)),
scale: None,
scale: Some((2.0)),
health_scaling: 30,
loadout_config: None,
skillset_config: None,

View File

@ -92,12 +92,6 @@ impl CharacterBehavior for Data {
)
.build();
let alignment = if matches!(data.alignment, Some(comp::Alignment::Enemy)) {
comp::Alignment::Enemy
} else {
comp::Alignment::Owned(*data.uid)
};
update.server_events.push_front(ServerEvent::CreateNpc {
pos: *data.pos,
stats,
@ -109,7 +103,7 @@ impl CharacterBehavior for Data {
loadout,
body,
agent: Some(comp::Agent::new(None, false, None, &body, true)),
alignment,
alignment: comp::Alignment::Owned(*data.uid),
scale: self
.static_data
.summon_info

View File

@ -329,7 +329,14 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
.insert(entity, comp::CharacterState::default());
false
} else if state.ecs().read_storage::<comp::Agent>().contains(entity) {
} else if state.ecs().read_storage::<comp::Agent>().contains(entity)
&& !matches!(
state.ecs().read_storage::<comp::Alignment>().get(entity),
Some(comp::Alignment::Owned(_))
)
{
// Only drop loot if entity has agency (not a player), and if it is not owned by
// another entity (not a pet)
use specs::Builder;
// Decide for a loot drop before turning into a lootbag

View File

@ -1115,7 +1115,7 @@ impl<'a> AgentData<'a> {
|| e_pos.0.distance_squared(self.pos.0) < listen_dist.powi(2)) // TODO implement proper sound system for agents
&& e != self.entity
&& !e_health.is_dead
&& (self.alignment.and_then(|a| e_alignment.map(|b| a.hostile_towards(*b))).unwrap_or(false) || (
&& (try_owner_alignment(self.alignment, &read_data).and_then(|a| try_owner_alignment(*e_alignment, &read_data).map(|b| a.hostile_towards(*b))).unwrap_or(false) || (
if let Some(rtsim_entity) = &self.rtsim_entity {
if rtsim_entity.brain.remembers_fight_with_character(&e_stats.name) {
agent.rtsim_controller.events.push(
@ -1302,7 +1302,7 @@ impl<'a> AgentData<'a> {
// depending on the distance from the agent to the target
match tactic {
Tactic::Melee => {
if dist_sqrd < (min_attack_dist * self.scale).powi(2) {
if dist_sqrd < min_attack_dist.powi(2) {
controller
.actions
.push(ControlAction::basic_input(InputKind::Primary));
@ -1337,7 +1337,7 @@ impl<'a> AgentData<'a> {
}
},
Tactic::Axe => {
if dist_sqrd < (min_attack_dist * self.scale).powi(2) {
if dist_sqrd < min_attack_dist.powi(2) {
controller.inputs.move_dir = Vec2::zero();
if agent.action_timer > 6.0 {
controller
@ -1395,7 +1395,7 @@ impl<'a> AgentData<'a> {
}
},
Tactic::Hammer => {
if dist_sqrd < (min_attack_dist * self.scale).powi(2) {
if dist_sqrd < min_attack_dist.powi(2) {
controller.inputs.move_dir = Vec2::zero();
if agent.action_timer > 4.0 {
controller
@ -1471,7 +1471,7 @@ impl<'a> AgentData<'a> {
}
},
Tactic::Sword => {
if dist_sqrd < (min_attack_dist * self.scale).powi(2) {
if dist_sqrd < min_attack_dist.powi(2) {
controller.inputs.move_dir = Vec2::zero();
if self
.stats
@ -1535,7 +1535,7 @@ impl<'a> AgentData<'a> {
},
Tactic::Bow => {
if self.body.map(|b| b.is_humanoid()).unwrap_or(false)
&& dist_sqrd < (2.0 * min_attack_dist * self.scale).powi(2)
&& dist_sqrd < (2.0 * min_attack_dist).powi(2)
{
controller
.actions
@ -1628,12 +1628,12 @@ impl<'a> AgentData<'a> {
},
Tactic::Staff => {
if self.body.map(|b| b.is_humanoid()).unwrap_or(false)
&& dist_sqrd < (min_attack_dist * self.scale).powi(2)
&& dist_sqrd < min_attack_dist.powi(2)
{
controller
.actions
.push(ControlAction::basic_input(InputKind::Roll));
} else if dist_sqrd < (5.0 * min_attack_dist * self.scale).powi(2) {
} else if dist_sqrd < (5.0 * min_attack_dist).powi(2) {
if agent.action_timer < 1.5 {
controller.inputs.move_dir = (tgt_pos.0 - self.pos.0)
.xy()
@ -1727,7 +1727,7 @@ impl<'a> AgentData<'a> {
}
},
Tactic::StoneGolemBoss => {
if dist_sqrd < (min_attack_dist * self.scale).powi(2) {
if dist_sqrd < min_attack_dist.powi(2) {
// 2.0 is temporary correction factor to allow them to melee with their
// large hitbox
controller.inputs.move_dir = Vec2::zero();
@ -1777,19 +1777,18 @@ impl<'a> AgentData<'a> {
radius,
circle_time,
} => {
if dist_sqrd < (min_attack_dist * self.scale).powi(2) && thread_rng().gen_bool(0.5)
{
if dist_sqrd < min_attack_dist.powi(2) && thread_rng().gen_bool(0.5) {
controller.inputs.move_dir = Vec2::zero();
controller
.actions
.push(ControlAction::basic_input(InputKind::Primary));
} else if dist_sqrd < (radius as f32 * min_attack_dist * self.scale).powi(2) {
} else if dist_sqrd < (radius as f32 * min_attack_dist).powi(2) {
controller.inputs.move_dir = (self.pos.0 - tgt_pos.0)
.xy()
.try_normalized()
.unwrap_or_else(Vec2::unit_y);
} else if dist_sqrd < ((radius as f32 + 1.0) * min_attack_dist * self.scale).powi(2)
&& dist_sqrd > (radius as f32 * min_attack_dist * self.scale).powi(2)
} else if dist_sqrd < ((radius as f32 + 1.0) * min_attack_dist).powi(2)
&& dist_sqrd > (radius as f32 * min_attack_dist).powi(2)
{
if agent.action_timer < circle_time as f32 {
controller.inputs.move_dir = (tgt_pos.0 - self.pos.0)
@ -1839,7 +1838,7 @@ impl<'a> AgentData<'a> {
}
},
Tactic::QuadLowRanged => {
if dist_sqrd < (3.0 * min_attack_dist * self.scale).powi(2) {
if dist_sqrd < (3.0 * min_attack_dist).powi(2) {
controller.inputs.move_dir = (tgt_pos.0 - self.pos.0)
.xy()
.try_normalized()
@ -1897,7 +1896,7 @@ impl<'a> AgentData<'a> {
}
},
Tactic::TailSlap => {
if dist_sqrd < (1.5 * min_attack_dist * self.scale).powi(2) {
if dist_sqrd < (1.5 * min_attack_dist).powi(2) {
if agent.action_timer > 4.0 {
controller
.actions
@ -1940,13 +1939,13 @@ impl<'a> AgentData<'a> {
}
},
Tactic::QuadLowQuick => {
if dist_sqrd < (1.5 * min_attack_dist * self.scale).powi(2) {
if dist_sqrd < (1.5 * min_attack_dist).powi(2) {
controller.inputs.move_dir = Vec2::zero();
controller
.actions
.push(ControlAction::basic_input(InputKind::Secondary));
} else if dist_sqrd < (3.0 * min_attack_dist * self.scale).powi(2)
&& dist_sqrd > (2.0 * min_attack_dist * self.scale).powi(2)
} else if dist_sqrd < (3.0 * min_attack_dist).powi(2)
&& dist_sqrd > (2.0 * min_attack_dist).powi(2)
{
controller
.actions
@ -1977,7 +1976,7 @@ impl<'a> AgentData<'a> {
}
},
Tactic::QuadLowBasic => {
if dist_sqrd < (1.5 * min_attack_dist * self.scale).powi(2) {
if dist_sqrd < (1.5 * min_attack_dist).powi(2) {
controller.inputs.move_dir = Vec2::zero();
if agent.action_timer > 5.0 {
agent.action_timer = 0.0;
@ -2013,12 +2012,12 @@ impl<'a> AgentData<'a> {
}
},
Tactic::QuadMedJump => {
if dist_sqrd < (1.5 * min_attack_dist * self.scale).powi(2) {
if dist_sqrd < (1.5 * min_attack_dist).powi(2) {
controller.inputs.move_dir = Vec2::zero();
controller
.actions
.push(ControlAction::basic_input(InputKind::Secondary));
} else if dist_sqrd < (5.0 * min_attack_dist * self.scale).powi(2) {
} else if dist_sqrd < (5.0 * min_attack_dist).powi(2) {
controller
.actions
.push(ControlAction::basic_input(InputKind::Ability(0)));
@ -2051,7 +2050,7 @@ impl<'a> AgentData<'a> {
}
},
Tactic::QuadMedBasic => {
if dist_sqrd < (min_attack_dist * self.scale).powi(2) {
if dist_sqrd < min_attack_dist.powi(2) {
controller.inputs.move_dir = Vec2::zero();
if agent.action_timer < 2.0 {
controller
@ -2087,12 +2086,12 @@ impl<'a> AgentData<'a> {
}
},
Tactic::Lavadrake | Tactic::QuadLowBeam => {
if dist_sqrd < (2.5 * min_attack_dist * self.scale).powi(2) {
if dist_sqrd < (2.5 * min_attack_dist).powi(2) {
controller.inputs.move_dir = Vec2::zero();
controller
.actions
.push(ControlAction::basic_input(InputKind::Secondary));
} else if dist_sqrd < (7.0 * min_attack_dist * self.scale).powi(2) {
} else if dist_sqrd < (7.0 * min_attack_dist).powi(2) {
if agent.action_timer < 2.0 {
controller.inputs.move_dir = (tgt_pos.0 - self.pos.0)
.xy()
@ -2142,7 +2141,7 @@ impl<'a> AgentData<'a> {
}
},
Tactic::Theropod => {
if dist_sqrd < (2.0 * min_attack_dist * self.scale).powi(2) {
if dist_sqrd < (2.0 * min_attack_dist).powi(2) {
controller.inputs.move_dir = Vec2::zero();
controller
.actions
@ -2207,7 +2206,7 @@ impl<'a> AgentData<'a> {
const MINDFLAYER_ATTACK_DIST: f32 = 15.0;
let mindflayer_is_far = dist_sqrd > MINDFLAYER_ATTACK_DIST.powi(2);
let health_fraction = self.health.map_or(0.5, |h| h.fraction());
if mindflayer_is_far && agent.action_timer / health_fraction > 10.0 {
if mindflayer_is_far && agent.action_timer > 5.0 / health_fraction {
// Summon minions if time has passed and no one is close for other attacks. Less
// often when at low health.
if !self.char_state.is_attack() {
@ -2296,3 +2295,19 @@ fn should_stop_attacking(health: Option<&Health>, buffs: Option<&Buffs>) -> bool
health.map_or(true, |a| a.is_dead)
|| buffs.map_or(false, |b| b.kinds.contains_key(&BuffKind::Invulnerability))
}
/// Attempts to get alignment of owner if entity has Owned alignment
fn try_owner_alignment<'a>(
alignment: Option<&'a Alignment>,
read_data: &'a ReadData,
) -> Option<&'a Alignment> {
if let Some(Alignment::Owned(owner_uid)) = alignment {
if let Some(owner) = read_data
.uid_allocator
.retrieve_entity_internal(owner_uid.id())
{
return read_data.alignments.get(owner);
}
}
alignment
}