aboutsummaryrefslogtreecommitdiff
path: root/azalea/src/client_impl/attack.rs
diff options
context:
space:
mode:
Diffstat (limited to 'azalea/src/client_impl/attack.rs')
-rw-r--r--azalea/src/client_impl/attack.rs50
1 files changed, 50 insertions, 0 deletions
diff --git a/azalea/src/client_impl/attack.rs b/azalea/src/client_impl/attack.rs
new file mode 100644
index 00000000..f4cac51f
--- /dev/null
+++ b/azalea/src/client_impl/attack.rs
@@ -0,0 +1,50 @@
+use azalea_client::attack::{
+ AttackEvent, AttackStrengthScale, TicksSinceLastAttack, get_attack_strength_delay,
+};
+use azalea_entity::Attributes;
+use bevy_ecs::entity::Entity;
+
+use crate::Client;
+
+impl Client {
+ /// Attack an entity in the world.
+ ///
+ /// This doesn't automatically look at the entity or perform any
+ /// range/visibility checks, so it might trigger anticheats.
+ pub fn attack(&self, entity: Entity) {
+ self.ecs.lock().write_message(AttackEvent {
+ entity: self.entity,
+ target: entity,
+ });
+ }
+
+ /// Whether the player has an attack cooldown.
+ ///
+ /// Also see [`Client::attack_cooldown_remaining_ticks`].
+ pub fn has_attack_cooldown(&self) -> bool {
+ let Some(attack_strength_scale) = self.get_component::<AttackStrengthScale>() else {
+ // they don't even have an AttackStrengthScale so they probably can't even
+ // attack? whatever, just return false
+ return false;
+ };
+ *attack_strength_scale < 1.0
+ }
+
+ /// Returns the number of ticks until we can attack at full strength again.
+ ///
+ /// Also see [`Client::has_attack_cooldown`].
+ pub fn attack_cooldown_remaining_ticks(&self) -> usize {
+ let mut ecs = self.ecs.lock();
+ let Ok((attributes, ticks_since_last_attack)) = ecs
+ .query::<(&Attributes, &TicksSinceLastAttack)>()
+ .get(&ecs, self.entity)
+ else {
+ return 0;
+ };
+
+ let attack_strength_delay = get_attack_strength_delay(attributes);
+ let remaining_ticks = attack_strength_delay - **ticks_since_last_attack as f32;
+
+ remaining_ticks.max(0.).ceil() as usize
+ }
+}