diff --git a/code/game/machinery/computer/HolodeckControl.dm b/code/game/machinery/computer/HolodeckControl.dm
index 604ac3f02f3..d3edc588e2d 100644
--- a/code/game/machinery/computer/HolodeckControl.dm
+++ b/code/game/machinery/computer/HolodeckControl.dm
@@ -460,6 +460,12 @@
desc = "Here's your chance, do your dance at the Space Jam."
w_class = WEIGHT_CLASS_BULKY //Stops people from hiding it in their bags/pockets
+/obj/item/beach_ball/holoball/baseball
+ icon_state = "baseball"
+ name = "baseball"
+ item_state = "baseball"
+ desc = "Take me out to the ball game."
+
/obj/structure/holohoop
name = "basketball hoop"
desc = "Boom, Shakalaka!"
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 9dbb02553ca..8390ed664f1 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -331,7 +331,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
else
return ..()
-/obj/item/proc/hit_reaction(mob/living/carbon/human/owner, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
+/obj/item/proc/hit_reaction(mob/living/carbon/human/owner, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, atom/movable/AM)
SEND_SIGNAL(src, COMSIG_ITEM_HIT_REACT, args)
if(prob(final_block_chance))
owner.visible_message("[owner] blocks [attack_text] with [src]!")
diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm
index b759139dba6..f42decd4363 100644
--- a/code/game/objects/items/weapons/weaponry.dm
+++ b/code/game/objects/items/weapons/weaponry.dm
@@ -157,6 +157,8 @@
icon = 'icons/obj/items.dmi'
icon_state = "baseball_bat"
item_state = "baseball_bat"
+ var/deflectmode = FALSE // deflect small/medium thrown objects
+ var/lastdeflect
force = 10
throwforce = 12
attack_verb = list("beat", "smacked")
@@ -169,14 +171,54 @@
desc = "This thing looks dangerous... Dangerously good at baseball, that is."
homerun_able = 1
+/obj/item/melee/baseball_bat/hit_reaction(mob/living/carbon/human/owner, attack_text, final_block_chance, damage, attack_type, atom/movable/AM)
+ . = ..()
+ if(!istype(AM, /obj/item) || attack_type != THROWN_PROJECTILE_ATTACK)
+ return FALSE
+ var/obj/item/I = AM
+ if(I.w_class <= WEIGHT_CLASS_NORMAL || istype(I, /obj/item/beach_ball)) // baseball bat deflecting
+ if(deflectmode)
+ if(prob(10))
+ visible_message("[owner] Deflects [I] directly back at the thrower! It's a home run!", "You deflect the [I] directly back at the thrower! It's a home run!")
+ playsound(get_turf(owner), 'sound/weapons/homerun.ogg', 100, 1)
+ do_attack_animation(I, ATTACK_EFFECT_DISARM)
+ I.throw_at(I.thrownby, 20, 20, owner)
+ deflectmode = FALSE
+ if(!istype(I, /obj/item/beach_ball))
+ lastdeflect = world.time + 3000
+ return TRUE
+ else if(prob(30))
+ visible_message("[owner] swings! And [p_they()] miss[p_es()]! How embarassing.", "You swing! You miss! Oh no!")
+ playsound(get_turf(owner), 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
+ do_attack_animation(get_step(owner, pick(alldirs)), ATTACK_EFFECT_DISARM)
+ deflectmode = FALSE
+ if(!istype(I, /obj/item/beach_ball))
+ lastdeflect = world.time + 3000
+ return FALSE
+ else
+ visible_message("[owner] swings and deflects [I]!", "You swing and deflect the [I]!")
+ playsound(get_turf(owner), 'sound/weapons/baseball_hit.ogg', 50, 1, -1)
+ do_attack_animation(I, ATTACK_EFFECT_DISARM)
+ I.throw_at(get_edge_target_turf(owner, pick(cardinal)), rand(8,10), 14, owner)
+ deflectmode = FALSE
+ if(!istype(I, /obj/item/beach_ball))
+ lastdeflect = world.time + 3000
+ return TRUE
+
/obj/item/melee/baseball_bat/attack_self(mob/user)
if(!homerun_able)
- ..()
- return
+ if(!deflectmode && world.time >= lastdeflect)
+ to_chat(user, "You prepare to deflect objects thrown at you. You cannot attack during this time.")
+ deflectmode = TRUE
+ else if(deflectmode && world.time >= lastdeflect)
+ to_chat(user, "You no longer deflect objects thrown at you. You can attack during this time")
+ deflectmode = FALSE
+ else
+ to_chat(user, "You need to wait until you can deflect again. The ability will be ready in [time2text(lastdeflect - world.time, "m:ss")]")
+ return ..()
if(homerun_ready)
to_chat(user, "You're already ready to do a home run!")
- ..()
- return
+ return ..()
to_chat(user, "You begin gathering strength...")
playsound(get_turf(src), 'sound/magic/lightning_chargeup.ogg', 65, 1)
if(do_after(user, 90, target = user))
@@ -185,6 +227,9 @@
..()
/obj/item/melee/baseball_bat/attack(mob/living/target, mob/living/user)
+ if(deflectmode)
+ to_chat(user, "You cannot attack in deflect mode!")
+ return
. = ..()
var/atom/throw_target = get_edge_target_turf(target, user.dir)
if(homerun_ready)
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index b95920e688b..d172fabef00 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -141,19 +141,19 @@ emp_act
if(l_hand && !istype(l_hand, /obj/item/clothing))
var/final_block_chance = l_hand.block_chance - (Clamp((armour_penetration-l_hand.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example
- if(l_hand.hit_reaction(src, attack_text, final_block_chance, damage, attack_type))
+ if(l_hand.hit_reaction(src, attack_text, final_block_chance, damage, attack_type, AM))
return 1
if(r_hand && !istype(r_hand, /obj/item/clothing))
var/final_block_chance = r_hand.block_chance - (Clamp((armour_penetration-r_hand.armour_penetration)/2,0,100)) + block_chance_modifier //Need to reset the var so it doesn't carry over modifications between attempts
- if(r_hand.hit_reaction(src, attack_text, final_block_chance, damage, attack_type))
+ if(r_hand.hit_reaction(src, attack_text, final_block_chance, damage, attack_type, AM))
return 1
if(wear_suit)
var/final_block_chance = wear_suit.block_chance - (Clamp((armour_penetration-wear_suit.armour_penetration)/2,0,100)) + block_chance_modifier
- if(wear_suit.hit_reaction(src, attack_text, final_block_chance, damage, attack_type))
+ if(wear_suit.hit_reaction(src, attack_text, final_block_chance, damage, attack_type, AM))
return 1
if(w_uniform)
var/final_block_chance = w_uniform.block_chance - (Clamp((armour_penetration-w_uniform.armour_penetration)/2,0,100)) + block_chance_modifier
- if(w_uniform.hit_reaction(src, attack_text, final_block_chance, damage, attack_type))
+ if(w_uniform.hit_reaction(src, attack_text, final_block_chance, damage, attack_type, AM))
return 1
return 0
@@ -525,4 +525,4 @@ emp_act
if(head)
to_chat(src, "Your [head.name] protects you from the [hot ? "hot" : "cold"] liquid!")
return FALSE
- return TRUE
\ No newline at end of file
+ return TRUE
diff --git a/icons/obj/basketball.dmi b/icons/obj/basketball.dmi
index a26c3935719..7b34fda1a32 100644
Binary files a/icons/obj/basketball.dmi and b/icons/obj/basketball.dmi differ
diff --git a/sound/weapons/baseball_hit.ogg b/sound/weapons/baseball_hit.ogg
new file mode 100644
index 00000000000..6530945b6c1
Binary files /dev/null and b/sound/weapons/baseball_hit.ogg differ