mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Make friendly creatures defend each other.
This commit is contained in:
parent
c946e945cf
commit
82273f0f36
@ -78,6 +78,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Changed the way light strength is rendered by moving processing from shader code (GPU) to CPU code
|
- Changed the way light strength is rendered by moving processing from shader code (GPU) to CPU code
|
||||||
- Bumped tracing-subscriber to resolve [RUSTSEC-2022-0006](https://rustsec.org/advisories/RUSTSEC-2022-0006)
|
- Bumped tracing-subscriber to resolve [RUSTSEC-2022-0006](https://rustsec.org/advisories/RUSTSEC-2022-0006)
|
||||||
- Made /home command a mod+ exclusive
|
- Made /home command a mod+ exclusive
|
||||||
|
- Friendly creatures will now defend each other
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
|
@ -153,6 +153,69 @@ impl<
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Body {
|
impl Body {
|
||||||
|
pub fn is_same_species_as(&self, other: &Body) -> bool {
|
||||||
|
match self {
|
||||||
|
Body::Humanoid(b1) => match other {
|
||||||
|
Body::Humanoid(b2) => b1.species == b2.species,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
Body::QuadrupedSmall(b1) => match other {
|
||||||
|
Body::QuadrupedSmall(b2) => b1.species == b2.species,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
Body::QuadrupedMedium(b1) => match other {
|
||||||
|
Body::QuadrupedMedium(b2) => b1.species == b2.species,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
Body::BirdMedium(b1) => match other {
|
||||||
|
Body::BirdMedium(b2) => b1.species == b2.species,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
Body::BirdLarge(b1) => match other {
|
||||||
|
Body::BirdLarge(b2) => b1.species == b2.species,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
Body::FishMedium(b1) => match other {
|
||||||
|
Body::FishMedium(b2) => b1.species == b2.species,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
Body::Dragon(b1) => match other {
|
||||||
|
Body::Dragon(b2) => b1.species == b2.species,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
Body::FishSmall(b1) => match other {
|
||||||
|
Body::FishSmall(b2) => b1.species == b2.species,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
Body::BipedLarge(b1) => match other {
|
||||||
|
Body::BipedLarge(b2) => b1.species == b2.species,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
Body::BipedSmall(b1) => match other {
|
||||||
|
Body::BipedSmall(b2) => b1.species == b2.species,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
Body::Object(_) => false,
|
||||||
|
Body::Golem(b1) => match other {
|
||||||
|
Body::Golem(b2) => b1.species == b2.species,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
Body::Theropod(b1) => match other {
|
||||||
|
Body::Theropod(b2) => b1.species == b2.species,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
Body::QuadrupedLow(b1) => match other {
|
||||||
|
Body::QuadrupedLow(b2) => b1.species == b2.species,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
Body::Arthropod(b1) => match other {
|
||||||
|
Body::Arthropod(b2) => b1.species == b2.species,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
Body::Ship(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_humanoid(&self) -> bool { matches!(self, Body::Humanoid(_)) }
|
pub fn is_humanoid(&self) -> bool { matches!(self, Body::Humanoid(_)) }
|
||||||
|
|
||||||
pub fn is_campfire(&self) -> bool { matches!(self, Body::Object(object::Body::CampfireLit)) }
|
pub fn is_campfire(&self) -> bool { matches!(self, Body::Object(object::Body::CampfireLit)) }
|
||||||
|
@ -1452,6 +1452,7 @@ impl<'a> AgentData<'a> {
|
|||||||
inventory,
|
inventory,
|
||||||
read_data.alignments.get(entity),
|
read_data.alignments.get(entity),
|
||||||
read_data.char_states.get(entity),
|
read_data.char_states.get(entity),
|
||||||
|
read_data.bodies.get(entity),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
@ -1502,16 +1503,28 @@ impl<'a> AgentData<'a> {
|
|||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
let guard_defending_villager = |e_health: &Health, e_alignment: Option<&Alignment>| {
|
let guard_other = |e_health: &Health,
|
||||||
|
e_body: Option<&Body>,
|
||||||
|
e_alignment: Option<&Alignment>| {
|
||||||
let i_am_a_guard = read_data
|
let i_am_a_guard = read_data
|
||||||
.stats
|
.stats
|
||||||
.get(*self.entity)
|
.get(*self.entity)
|
||||||
.map_or(false, |stats| stats.name == "Guard");
|
.map_or(false, |stats| stats.name == "Guard");
|
||||||
let other_is_a_villager = matches!(e_alignment, Some(Alignment::Npc));
|
let other_is_a_villager = matches!(e_alignment, Some(Alignment::Npc));
|
||||||
let villager_has_taken_damage = read_data.time.0 - e_health.last_change.time.0 < 5.0;
|
let we_are_friendly: bool = self.alignment.map_or(false, |ma| {
|
||||||
|
e_alignment.map_or(false, |ea| !ea.hostile_towards(*ma))
|
||||||
|
});
|
||||||
|
let we_share_species: bool = self.body.map_or(false, |mb| {
|
||||||
|
e_body.map_or(false, |eb| {
|
||||||
|
eb.is_same_species_as(mb) || (eb.is_humanoid() && mb.is_humanoid())
|
||||||
|
})
|
||||||
|
});
|
||||||
|
let other_has_taken_damage = read_data.time.0 - e_health.last_change.time.0 < 5.0;
|
||||||
let attacker_of = |health: &Health| health.last_change.damage_by();
|
let attacker_of = |health: &Health| health.last_change.damage_by();
|
||||||
|
|
||||||
let i_should_defend = i_am_a_guard && other_is_a_villager && villager_has_taken_damage;
|
let i_should_defend = other_has_taken_damage
|
||||||
|
&& ((we_are_friendly && we_share_species) || (i_am_a_guard && other_is_a_villager));
|
||||||
|
|
||||||
i_should_defend
|
i_should_defend
|
||||||
.then(|| {
|
.then(|| {
|
||||||
attacker_of(e_health)
|
attacker_of(e_health)
|
||||||
@ -1519,10 +1532,20 @@ impl<'a> AgentData<'a> {
|
|||||||
get_entity_by_id(damage_contributor.uid().0, read_data)
|
get_entity_by_id(damage_contributor.uid().0, read_data)
|
||||||
})
|
})
|
||||||
.and_then(|attacker| {
|
.and_then(|attacker| {
|
||||||
read_data
|
read_data.alignments.get(attacker).and_then(|aa| {
|
||||||
.positions
|
self.alignment.and_then({
|
||||||
.get(attacker)
|
|ma| {
|
||||||
.map(|a_pos| (attacker, *a_pos))
|
if !ma.passive_towards(*aa) {
|
||||||
|
read_data
|
||||||
|
.positions
|
||||||
|
.get(attacker)
|
||||||
|
.map(|a_pos| (attacker, *a_pos))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.flatten()
|
.flatten()
|
||||||
@ -1583,36 +1606,45 @@ impl<'a> AgentData<'a> {
|
|||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
let possible_target =
|
let possible_target = |(
|
||||||
|(entity, e_pos, e_health, e_stats, e_inventory, e_alignment, e_char_state): (
|
entity,
|
||||||
EcsEntity,
|
e_pos,
|
||||||
&Pos,
|
e_health,
|
||||||
&Health,
|
e_stats,
|
||||||
&Stats,
|
e_inventory,
|
||||||
&Inventory,
|
e_alignment,
|
||||||
Option<&Alignment>,
|
e_char_state,
|
||||||
Option<&CharacterState>,
|
e_body,
|
||||||
)| {
|
): (
|
||||||
let can_target = within_reach(e_pos, e_char_state, e_inventory)
|
EcsEntity,
|
||||||
&& entity != *self.entity
|
&Pos,
|
||||||
&& !e_health.is_dead
|
&Health,
|
||||||
&& !is_invulnerable(entity, read_data);
|
&Stats,
|
||||||
|
&Inventory,
|
||||||
|
Option<&Alignment>,
|
||||||
|
Option<&CharacterState>,
|
||||||
|
Option<&Body>,
|
||||||
|
)| {
|
||||||
|
let can_target = within_reach(e_pos, e_char_state, e_inventory)
|
||||||
|
&& entity != *self.entity
|
||||||
|
&& !e_health.is_dead
|
||||||
|
&& !is_invulnerable(entity, read_data);
|
||||||
|
|
||||||
if !can_target {
|
if !can_target {
|
||||||
None
|
None
|
||||||
} else if is_owner_hostile(e_alignment) {
|
} else if is_owner_hostile(e_alignment) {
|
||||||
Some((entity, *e_pos))
|
Some((entity, *e_pos))
|
||||||
} else if let Some(villain_info) = guard_defending_villager(e_health, e_alignment) {
|
} else if let Some(villain_info) = guard_other(e_health, e_body, e_alignment) {
|
||||||
aggro_on = true;
|
aggro_on = true;
|
||||||
Some(villain_info)
|
Some(villain_info)
|
||||||
} else if rtsim_remember(e_stats, agent, event_emitter)
|
} else if rtsim_remember(e_stats, agent, event_emitter)
|
||||||
|| npc_sees_cultist(e_stats, e_inventory, agent, event_emitter)
|
|| npc_sees_cultist(e_stats, e_inventory, agent, event_emitter)
|
||||||
{
|
{
|
||||||
Some((entity, *e_pos))
|
Some((entity, *e_pos))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Search area
|
// Search area
|
||||||
// TODO choose target by more than just distance
|
// TODO choose target by more than just distance
|
||||||
|
Loading…
Reference in New Issue
Block a user