mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Add events and achievement items for killing players and npcs.
This commit is contained in:
parent
fb8590fac7
commit
e607ec498d
@ -1,4 +1,7 @@
|
||||
use crate::comp::item::{Consumable, Item, ItemKind};
|
||||
use crate::comp::{
|
||||
self,
|
||||
item::{Consumable, Item, ItemKind},
|
||||
};
|
||||
use specs::{Component, FlaggedStorage};
|
||||
use specs_idvs::IDVStorage;
|
||||
|
||||
@ -7,25 +10,23 @@ pub enum AchievementEvent {
|
||||
None,
|
||||
CollectedItem(Item),
|
||||
LevelUp(u32),
|
||||
KilledPlayer,
|
||||
KilledNpc,
|
||||
}
|
||||
|
||||
/// The types of achievements available in game
|
||||
///
|
||||
/// Some potential additions in the future:
|
||||
/// - ReachCoordinate
|
||||
/// - CollectCurrency
|
||||
/// - KillPlayers
|
||||
/// - OpenChests
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub enum AchievementAction {
|
||||
None,
|
||||
CollectConsumable(Consumable),
|
||||
ReachLevel,
|
||||
KillPlayers,
|
||||
KillNpcs,
|
||||
}
|
||||
|
||||
/// Information about an achievement. This differs from a complete
|
||||
/// [`Achievement`](struct.Achievement.html) in that it describes the
|
||||
/// achievement without any information about progress
|
||||
/// achievement without any information about progress or completion status
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub struct AchievementItem {
|
||||
pub title: String,
|
||||
@ -36,6 +37,8 @@ pub struct AchievementItem {
|
||||
impl AchievementItem {
|
||||
pub fn matches_event(&self, event: AchievementEvent) -> bool {
|
||||
match event {
|
||||
AchievementEvent::KilledNpc => self.action == AchievementAction::KillNpcs,
|
||||
AchievementEvent::KilledPlayer => self.action == AchievementAction::KillPlayers,
|
||||
AchievementEvent::LevelUp(_) => self.action == AchievementAction::ReachLevel,
|
||||
AchievementEvent::CollectedItem(item) => match self.action {
|
||||
AchievementAction::CollectConsumable(consumable) => {
|
||||
@ -47,6 +50,7 @@ impl AchievementItem {
|
||||
},
|
||||
_ => false,
|
||||
},
|
||||
AchievementEvent::None => false,
|
||||
_ => {
|
||||
tracing::warn!(
|
||||
?event,
|
||||
@ -158,7 +162,7 @@ impl AchievementUpdate {
|
||||
}
|
||||
|
||||
impl Component for AchievementUpdate {
|
||||
type Storage = FlaggedStorage<Self, IDVStorage<Self>>;
|
||||
type Storage = IDVStorage<Self>;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -1,12 +1,52 @@
|
||||
[
|
||||
(
|
||||
title: "Collect 5 Apples",
|
||||
title: "Collect 10 apples",
|
||||
action: CollectConsumable(Apple),
|
||||
target: 5
|
||||
target: 10
|
||||
),
|
||||
(
|
||||
title: "Collect 7 Apples",
|
||||
title: "Collect 50 apples",
|
||||
action: CollectConsumable(Apple),
|
||||
target: 7
|
||||
target: 50
|
||||
),
|
||||
(
|
||||
title: "Pick a mushroom",
|
||||
action: CollectConsumable(Mushroom),
|
||||
target: 1
|
||||
),
|
||||
(
|
||||
title: "Kill an NPC",
|
||||
action: KillNpcs,
|
||||
target: 1
|
||||
),
|
||||
(
|
||||
title: "Kill 10 NPCs",
|
||||
action: KillNpcs,
|
||||
target: 10
|
||||
),
|
||||
(
|
||||
title: "Kill 100 NPCs",
|
||||
action: KillNpcs,
|
||||
target: 100
|
||||
),
|
||||
(
|
||||
title: "Kill another player",
|
||||
action: KillPlayers,
|
||||
target: 1
|
||||
),
|
||||
(
|
||||
title: "Kill 10 players",
|
||||
action: KillPlayers,
|
||||
target: 10
|
||||
),
|
||||
(
|
||||
title: "Find a Velorite fragment",
|
||||
action: CollectConsumable(VeloriteFrag),
|
||||
target: 1
|
||||
),
|
||||
(
|
||||
title: "Find Velorite",
|
||||
action: CollectConsumable(Velorite),
|
||||
target: 1
|
||||
)
|
||||
]
|
@ -2,8 +2,8 @@ use crate::{client::Client, Server, SpawnPoint, StateExt};
|
||||
use common::{
|
||||
assets,
|
||||
comp::{
|
||||
self, item::lottery::Lottery, object, AchievementEvent, Body, HealthChange, HealthSource,
|
||||
Player, Stats,
|
||||
self, item::lottery::Lottery, object, AchievementEvent, Alignment, Body, HealthChange,
|
||||
HealthSource, Player, Stats,
|
||||
},
|
||||
msg::{PlayerListUpdate, ServerMsg},
|
||||
state::BlockChange,
|
||||
@ -58,6 +58,7 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
|
||||
{
|
||||
// Give EXP to the killer if entity had stats
|
||||
let mut stats = state.ecs().write_storage::<Stats>();
|
||||
|
||||
if let Some(entity_stats) = stats.get(entity).cloned() {
|
||||
if let HealthSource::Attack { by } | HealthSource::Projectile { owner: Some(by) } =
|
||||
cause
|
||||
@ -73,6 +74,27 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
|
||||
as i64,
|
||||
);
|
||||
}
|
||||
|
||||
// Write an associated AchievementEvent for this kill
|
||||
if let Some(event) = match (
|
||||
state.ecs().read_storage::<Player>().get(entity),
|
||||
state.ecs().read_storage::<Alignment>().get(entity),
|
||||
) {
|
||||
(Some(_), _) => Some(AchievementEvent::KilledPlayer),
|
||||
(None, Some(alignment)) => {
|
||||
if alignment == &comp::Alignment::Npc {
|
||||
Some(AchievementEvent::KilledNpc)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
_ => None,
|
||||
} {
|
||||
let _ = state
|
||||
.ecs()
|
||||
.write_storage()
|
||||
.insert(entity, comp::AchievementUpdate::new(event));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user