mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Deduplicate pvp-checks
This commit is contained in:
@ -323,6 +323,7 @@ impl ChatCommand {
|
|||||||
true for overwrite to alter an existing ban..",
|
true for overwrite to alter an existing ban..",
|
||||||
Some(Moderator),
|
Some(Moderator),
|
||||||
),
|
),
|
||||||
|
#[rustfmt::skip]
|
||||||
ChatCommand::BattleMode => cmd(
|
ChatCommand::BattleMode => cmd(
|
||||||
vec![Enum(
|
vec![Enum(
|
||||||
"battle mode",
|
"battle mode",
|
||||||
|
@ -12,13 +12,13 @@ use crate::{
|
|||||||
},
|
},
|
||||||
poise::PoiseChange,
|
poise::PoiseChange,
|
||||||
skills::SkillGroupKind,
|
skills::SkillGroupKind,
|
||||||
Body, CharacterState, Combo, Energy, EnergyChange, EnergySource, Health, HealthChange,
|
Alignment, Body, CharacterState, Combo, Energy, EnergyChange, EnergySource, Health,
|
||||||
HealthSource, Inventory, Ori, Player, Poise, SkillSet, Stats,
|
HealthChange, HealthSource, Inventory, Ori, Player, Poise, SkillSet, Stats,
|
||||||
},
|
},
|
||||||
event::ServerEvent,
|
event::ServerEvent,
|
||||||
outcome::Outcome,
|
outcome::Outcome,
|
||||||
states::utils::StageSection,
|
states::utils::StageSection,
|
||||||
uid::Uid,
|
uid::{Uid, UidAllocator},
|
||||||
util::Dir,
|
util::Dir,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ use rand::{thread_rng, Rng};
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use specs::Entity as EcsEntity;
|
use specs::{saveload::MarkerAllocator, Entity as EcsEntity, ReadStorage};
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use std::{ops::MulAssign, time::Duration};
|
use std::{ops::MulAssign, time::Duration};
|
||||||
#[cfg(not(target_arch = "wasm32"))] use vek::*;
|
#[cfg(not(target_arch = "wasm32"))] use vek::*;
|
||||||
@ -469,14 +469,56 @@ impl Attack {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Says if we should allow negative effects from one player to another
|
/// Function that checks for unintentional PvP between players.
|
||||||
///
|
///
|
||||||
/// NOTE: this function doesn't handle pets or friendly-fire, you will need to
|
/// Returns `false` if attack will create unintentional conflict,
|
||||||
/// figure it out on call-side.
|
/// e.g. if player with PvE mode will harm pets of other players
|
||||||
pub fn may_harm(attacker: Option<&Player>, target: Option<&Player>) -> bool {
|
/// or other players will do the same to such player.
|
||||||
attacker
|
///
|
||||||
.zip(target)
|
/// If both players have PvP mode enabled, interact with NPC and
|
||||||
.map_or(true, |(attacker, target)| attacker.may_harm(target))
|
/// in any other case, this function will return `true`
|
||||||
|
// TODO: add parameter for doing self-harm?
|
||||||
|
pub fn may_harm(
|
||||||
|
alignments: &ReadStorage<Alignment>,
|
||||||
|
players: &ReadStorage<Player>,
|
||||||
|
uid_allocator: &UidAllocator,
|
||||||
|
attacker: Option<EcsEntity>,
|
||||||
|
target: EcsEntity,
|
||||||
|
) -> bool {
|
||||||
|
// Return owner entity if pet,
|
||||||
|
// or just return entity back otherwise
|
||||||
|
let owner_if_pet = |entity| {
|
||||||
|
let alignment = alignments.get(entity).copied();
|
||||||
|
if let Some(Alignment::Owned(uid)) = alignment {
|
||||||
|
// return original entity
|
||||||
|
// if can't get owner
|
||||||
|
uid_allocator
|
||||||
|
.retrieve_entity_internal(uid.into())
|
||||||
|
.unwrap_or(entity)
|
||||||
|
} else {
|
||||||
|
entity
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Just return ok if attacker is unknown, it's probably
|
||||||
|
// environment or command.
|
||||||
|
let attacker = match attacker {
|
||||||
|
Some(attacker) => attacker,
|
||||||
|
None => return true,
|
||||||
|
};
|
||||||
|
|
||||||
|
// "Dereference" to owner if this is a pet.
|
||||||
|
let attacker = owner_if_pet(attacker);
|
||||||
|
let target = owner_if_pet(target);
|
||||||
|
|
||||||
|
// Get player components
|
||||||
|
let attacker_info = players.get(attacker);
|
||||||
|
let target_info = players.get(target);
|
||||||
|
|
||||||
|
// Return `true` if not players.
|
||||||
|
attacker_info
|
||||||
|
.zip(target_info)
|
||||||
|
.map_or(true, |(a, t)| a.may_harm(t))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
@ -3,10 +3,10 @@ use crate::{
|
|||||||
path::Chaser,
|
path::Chaser,
|
||||||
rtsim::RtSimController,
|
rtsim::RtSimController,
|
||||||
trade::{PendingTrade, ReducedInventory, SiteId, SitePrices, TradeId, TradeResult},
|
trade::{PendingTrade, ReducedInventory, SiteId, SitePrices, TradeId, TradeResult},
|
||||||
uid::{Uid, UidAllocator},
|
uid::Uid,
|
||||||
};
|
};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use specs::{saveload::MarkerAllocator, Component, Entity as EcsEntity};
|
use specs::{Component, Entity as EcsEntity};
|
||||||
use specs_idvs::IdvStorage;
|
use specs_idvs::IdvStorage;
|
||||||
use std::{collections::VecDeque, fmt};
|
use std::{collections::VecDeque, fmt};
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
@ -34,15 +34,6 @@ pub enum Alignment {
|
|||||||
Passive,
|
Passive,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to get owner
|
|
||||||
pub fn owner_of(alignment: Option<Alignment>, uid_allocator: &UidAllocator) -> Option<EcsEntity> {
|
|
||||||
if let Some(Alignment::Owned(uid)) = alignment {
|
|
||||||
uid_allocator.retrieve_entity_internal(uid.into())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
pub enum Mark {
|
pub enum Mark {
|
||||||
Merchant,
|
Merchant,
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use common::{
|
use common::{
|
||||||
combat,
|
combat,
|
||||||
comp::{
|
comp::{
|
||||||
agent::owner_of,
|
|
||||||
aura::{AuraChange, AuraKey, AuraKind, AuraTarget},
|
aura::{AuraChange, AuraKey, AuraKind, AuraTarget},
|
||||||
buff::{Buff, BuffCategory, BuffChange, BuffSource},
|
buff::{Buff, BuffCategory, BuffChange, BuffSource},
|
||||||
group::Group,
|
group::Group,
|
||||||
@ -178,7 +177,7 @@ fn activate_aura(
|
|||||||
// Which means that you can't apply debuffs on you and your group
|
// Which means that you can't apply debuffs on you and your group
|
||||||
// even if it's intented mechanic.
|
// even if it's intented mechanic.
|
||||||
//
|
//
|
||||||
// Not that we have this for now, but think about this
|
// We don't have this for now, but think about this
|
||||||
// when we will add this.
|
// when we will add this.
|
||||||
let may_harm = || {
|
let may_harm = || {
|
||||||
let owner = match source {
|
let owner = match source {
|
||||||
@ -187,18 +186,12 @@ fn activate_aura(
|
|||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
let owner_if_pet = |entity| {
|
|
||||||
// Return owner entity if pet,
|
|
||||||
// or just return entity back otherwise
|
|
||||||
owner_of(
|
|
||||||
read_data.alignments.get(entity).copied(),
|
|
||||||
&read_data.uid_allocator,
|
|
||||||
)
|
|
||||||
.unwrap_or(entity)
|
|
||||||
};
|
|
||||||
combat::may_harm(
|
combat::may_harm(
|
||||||
owner.and_then(|owner| read_data.players.get(owner_if_pet(owner))),
|
&read_data.alignments,
|
||||||
read_data.players.get(owner_if_pet(target)),
|
&read_data.players,
|
||||||
|
&read_data.uid_allocator,
|
||||||
|
owner,
|
||||||
|
target,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use common::{
|
use common::{
|
||||||
combat::{self, AttackOptions, AttackSource, AttackerInfo, TargetInfo},
|
combat::{self, AttackOptions, AttackSource, AttackerInfo, TargetInfo},
|
||||||
comp::{
|
comp::{
|
||||||
agent::{owner_of, Sound, SoundKind},
|
agent::{Sound, SoundKind},
|
||||||
Alignment, Beam, BeamSegment, Body, CharacterState, Combo, Energy, Group, Health,
|
Alignment, Beam, BeamSegment, Body, CharacterState, Combo, Energy, Group, Health,
|
||||||
HealthSource, Inventory, Ori, Player, Pos, Scale, Stats,
|
HealthSource, Inventory, Ori, Player, Pos, Scale, Stats,
|
||||||
},
|
},
|
||||||
@ -216,18 +216,12 @@ impl<'a> System<'a> for Sys {
|
|||||||
|
|
||||||
|
|
||||||
// PvP check
|
// PvP check
|
||||||
let owner_if_pet = |entity| {
|
|
||||||
// Return owner entity if pet,
|
|
||||||
// or just return entity back otherwise
|
|
||||||
owner_of(
|
|
||||||
read_data.alignments.get(entity).copied(),
|
|
||||||
&read_data.uid_allocator,
|
|
||||||
)
|
|
||||||
.unwrap_or(entity)
|
|
||||||
};
|
|
||||||
let may_harm = combat::may_harm(
|
let may_harm = combat::may_harm(
|
||||||
beam_owner.and_then(|owner| read_data.players.get(owner_if_pet(owner))),
|
&read_data.alignments,
|
||||||
read_data.players.get(owner_if_pet(target)),
|
&read_data.players,
|
||||||
|
&read_data.uid_allocator,
|
||||||
|
beam_owner,
|
||||||
|
target,
|
||||||
);
|
);
|
||||||
let attack_options = AttackOptions {
|
let attack_options = AttackOptions {
|
||||||
// No luck with dodging beams
|
// No luck with dodging beams
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use common::{
|
use common::{
|
||||||
combat::{self, AttackOptions, AttackSource, AttackerInfo, TargetInfo},
|
combat::{self, AttackOptions, AttackSource, AttackerInfo, TargetInfo},
|
||||||
comp::{
|
comp::{
|
||||||
agent::{owner_of, Sound, SoundKind},
|
agent::{Sound, SoundKind},
|
||||||
Alignment, Body, CharacterState, Combo, Energy, Group, Health, Inventory, Melee, Ori,
|
Alignment, Body, CharacterState, Combo, Energy, Group, Health, Inventory, Melee, Ori,
|
||||||
Player, Pos, Scale, Stats,
|
Player, Pos, Scale, Stats,
|
||||||
},
|
},
|
||||||
@ -165,18 +165,12 @@ impl<'a> System<'a> for Sys {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// PvP check
|
// PvP check
|
||||||
let owner_if_pet = |entity| {
|
|
||||||
// Return owner entity if pet,
|
|
||||||
// or just return entity back otherwise
|
|
||||||
owner_of(
|
|
||||||
read_data.alignments.get(entity).copied(),
|
|
||||||
&read_data.uid_allocator,
|
|
||||||
)
|
|
||||||
.unwrap_or(entity)
|
|
||||||
};
|
|
||||||
let may_harm = combat::may_harm(
|
let may_harm = combat::may_harm(
|
||||||
read_data.players.get(owner_if_pet(attacker)),
|
&read_data.alignments,
|
||||||
read_data.players.get(owner_if_pet(target)),
|
&read_data.players,
|
||||||
|
&read_data.uid_allocator,
|
||||||
|
Some(attacker),
|
||||||
|
target,
|
||||||
);
|
);
|
||||||
|
|
||||||
let attack_options = AttackOptions {
|
let attack_options = AttackOptions {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use common::{
|
use common::{
|
||||||
combat::{self, AttackOptions, AttackSource, AttackerInfo, TargetInfo},
|
combat::{self, AttackOptions, AttackSource, AttackerInfo, TargetInfo},
|
||||||
comp::{
|
comp::{
|
||||||
agent::{owner_of, Sound, SoundKind},
|
agent::{Sound, SoundKind},
|
||||||
projectile, Alignment, Body, CharacterState, Combo, Energy, Group, Health, HealthSource,
|
projectile, Alignment, Body, CharacterState, Combo, Energy, Group, Health, HealthSource,
|
||||||
Inventory, Ori, PhysicsState, Player, Pos, Projectile, Stats, Vel,
|
Inventory, Ori, PhysicsState, Player, Pos, Projectile, Stats, Vel,
|
||||||
},
|
},
|
||||||
@ -301,18 +301,12 @@ fn dispatch_hit(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PvP check
|
// PvP check
|
||||||
let owner_if_pet = |entity| {
|
|
||||||
// Return owner entity if pet,
|
|
||||||
// or just return entity back otherwise
|
|
||||||
owner_of(
|
|
||||||
read_data.alignments.get(entity).copied(),
|
|
||||||
&read_data.uid_allocator,
|
|
||||||
)
|
|
||||||
.unwrap_or(entity)
|
|
||||||
};
|
|
||||||
let may_harm = combat::may_harm(
|
let may_harm = combat::may_harm(
|
||||||
owner.and_then(|owner| read_data.players.get(owner_if_pet(owner))),
|
&read_data.alignments,
|
||||||
read_data.players.get(owner_if_pet(target)),
|
&read_data.players,
|
||||||
|
&read_data.uid_allocator,
|
||||||
|
owner,
|
||||||
|
target,
|
||||||
);
|
);
|
||||||
|
|
||||||
let attack_options = AttackOptions {
|
let attack_options = AttackOptions {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use common::{
|
use common::{
|
||||||
combat::{self, AttackOptions, AttackSource, AttackerInfo, TargetInfo},
|
combat::{self, AttackOptions, AttackSource, AttackerInfo, TargetInfo},
|
||||||
comp::{
|
comp::{
|
||||||
agent::{owner_of, Sound, SoundKind},
|
agent::{Sound, SoundKind},
|
||||||
Alignment, Body, CharacterState, Combo, Energy, Group, Health, HealthSource, Inventory,
|
Alignment, Body, CharacterState, Combo, Energy, Group, Health, HealthSource, Inventory,
|
||||||
Ori, PhysicsState, Player, Pos, Scale, Shockwave, ShockwaveHitEntities, Stats,
|
Ori, PhysicsState, Player, Pos, Scale, Shockwave, ShockwaveHitEntities, Stats,
|
||||||
},
|
},
|
||||||
@ -211,19 +211,12 @@ impl<'a> System<'a> for Sys {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// PvP check
|
// PvP check
|
||||||
let owner_if_pet = |entity| {
|
|
||||||
// Return owner entity if pet,
|
|
||||||
// or just return entity back otherwise
|
|
||||||
owner_of(
|
|
||||||
read_data.alignments.get(entity).copied(),
|
|
||||||
&read_data.uid_allocator,
|
|
||||||
)
|
|
||||||
.unwrap_or(entity)
|
|
||||||
};
|
|
||||||
let may_harm = combat::may_harm(
|
let may_harm = combat::may_harm(
|
||||||
shockwave_owner
|
&read_data.alignments,
|
||||||
.and_then(|owner| read_data.players.get(owner_if_pet(owner))),
|
&read_data.players,
|
||||||
read_data.players.get(owner_if_pet(target)),
|
&read_data.uid_allocator,
|
||||||
|
shockwave_owner,
|
||||||
|
target,
|
||||||
);
|
);
|
||||||
let attack_options = AttackOptions {
|
let attack_options = AttackOptions {
|
||||||
// Trying roll during earthquake isn't the best idea
|
// Trying roll during earthquake isn't the best idea
|
||||||
|
@ -31,7 +31,7 @@ use common::{
|
|||||||
event::{EventBus, ServerEvent},
|
event::{EventBus, ServerEvent},
|
||||||
generation::EntityInfo,
|
generation::EntityInfo,
|
||||||
npc::{self, get_npc_name},
|
npc::{self, get_npc_name},
|
||||||
resources::{PlayerPhysicsSettings, TimeOfDay, BattleMode},
|
resources::{BattleMode, PlayerPhysicsSettings, TimeOfDay},
|
||||||
terrain::{Block, BlockKind, SpriteKind, TerrainChunkSize},
|
terrain::{Block, BlockKind, SpriteKind, TerrainChunkSize},
|
||||||
uid::Uid,
|
uid::Uid,
|
||||||
vol::RectVolSize,
|
vol::RectVolSize,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
client::Client,
|
client::Client,
|
||||||
comp::{
|
comp::{
|
||||||
agent::{owner_of, Agent, AgentEvent, Sound, SoundKind},
|
agent::{Agent, AgentEvent, Sound, SoundKind},
|
||||||
biped_large, bird_large, quadruped_low, quadruped_medium, quadruped_small,
|
biped_large, bird_large, quadruped_low, quadruped_medium, quadruped_small,
|
||||||
skills::SkillGroupKind,
|
skills::SkillGroupKind,
|
||||||
theropod, BuffKind, BuffSource, PhysicsState,
|
theropod, BuffKind, BuffSource, PhysicsState,
|
||||||
@ -945,15 +945,12 @@ pub fn handle_explosion(server: &Server, pos: Vec3<f32>, explosion: Explosion, o
|
|||||||
};
|
};
|
||||||
|
|
||||||
// PvP check
|
// PvP check
|
||||||
let owner_if_pet = |entity| {
|
|
||||||
// Return owner entity if pet,
|
|
||||||
// or just return entity back otherwise
|
|
||||||
owner_of(alignments.get(entity).copied(), uid_allocator)
|
|
||||||
.unwrap_or(entity)
|
|
||||||
};
|
|
||||||
let may_harm = combat::may_harm(
|
let may_harm = combat::may_harm(
|
||||||
owner_entity.and_then(|owner| players.get(owner_if_pet(owner))),
|
alignments,
|
||||||
players.get(owner_if_pet(entity_b)),
|
players,
|
||||||
|
uid_allocator,
|
||||||
|
owner_entity,
|
||||||
|
entity_b,
|
||||||
);
|
);
|
||||||
let attack_options = combat::AttackOptions {
|
let attack_options = combat::AttackOptions {
|
||||||
// cool guyz maybe don't look at explosions
|
// cool guyz maybe don't look at explosions
|
||||||
@ -994,27 +991,22 @@ pub fn handle_explosion(server: &Server, pos: Vec3<f32>, explosion: Explosion, o
|
|||||||
1.0 - distance_squared / explosion.radius.powi(2)
|
1.0 - distance_squared / explosion.radius.powi(2)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Player check only accounts for PvP/PvE flag.
|
// Player check only accounts for PvP/PvE flag, but bombs
|
||||||
|
// are intented to do friendly fire.
|
||||||
//
|
//
|
||||||
// But bombs are intented to do
|
// What exactly is friendly fire is subject to discussion.
|
||||||
// friendly fire.
|
|
||||||
//
|
|
||||||
// What exactly friendly fire is subject to discussion.
|
|
||||||
// As we probably want to minimize possibility of being dick
|
// As we probably want to minimize possibility of being dick
|
||||||
// even to your group members, the only exception is when
|
// even to your group members, the only exception is when
|
||||||
// you want to harm yourself.
|
// you want to harm yourself.
|
||||||
//
|
//
|
||||||
// This can be changed later.
|
// This can be changed later.
|
||||||
// PvP check
|
|
||||||
let owner_if_pet = |entity| {
|
|
||||||
// Return owner entity if pet,
|
|
||||||
// or just return entity back otherwise
|
|
||||||
owner_of(alignments.get(entity).copied(), uid_allocator).unwrap_or(entity)
|
|
||||||
};
|
|
||||||
let may_harm = || {
|
let may_harm = || {
|
||||||
combat::may_harm(
|
combat::may_harm(
|
||||||
owner_entity.and_then(|owner| players.get(owner_if_pet(owner))),
|
alignments,
|
||||||
players.get(owner_if_pet(entity_b)),
|
players,
|
||||||
|
uid_allocator,
|
||||||
|
owner_entity,
|
||||||
|
entity_b,
|
||||||
) || owner_entity.map_or(true, |entity_a| entity_a == entity_b)
|
) || owner_entity.map_or(true, |entity_a| entity_a == entity_b)
|
||||||
};
|
};
|
||||||
if strength > 0.0 {
|
if strength > 0.0 {
|
||||||
|
Reference in New Issue
Block a user