diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm
index 55165724caa..ad993433eac 100644
--- a/code/__DEFINES/dcs/signals.dm
+++ b/code/__DEFINES/dcs/signals.dm
@@ -347,6 +347,8 @@
#define COMSIG_MOB_THROW "mob_throw"
///called when a user willingly drops something (i.e. keybind, or UI action)
#define COMSIG_MOB_WILLINGLY_DROP "mob_willingly_drop"
+///called when a user is getting new weapon and we want to remove previous weapon to clear hands
+#define COMSIG_MOB_WEAPON_APPEARS "mob_weapon_appears"
///from base of /mob/verb/examinate(): (atom/target)
#define COMSIG_MOB_EXAMINATE "mob_examinate"
///from base of /mob/update_sight(): ()
diff --git a/code/datums/spells/alien_spells/basetype_alien_touch.dm b/code/datums/spells/alien_spells/basetype_alien_touch.dm
index af15f280143..24141fe3a4c 100644
--- a/code/datums/spells/alien_spells/basetype_alien_touch.dm
+++ b/code/datums/spells/alien_spells/basetype_alien_touch.dm
@@ -25,10 +25,6 @@
to_chat(user, "You withdraw your [src].")
..()
-/obj/effect/proc_holder/spell/touch/alien_spell/cast(list/targets, mob/living/carbon/user)
- user.add_plasma(plasma_cost)
- ..()
-
/obj/effect/proc_holder/spell/touch/alien_spell/write_custom_logs(list/targets, mob/user)
user.create_log(ATTACK_LOG, "Cast the spell [name]")
diff --git a/code/datums/spells/mime.dm b/code/datums/spells/mime.dm
index 6c3769364f0..e40dd88df96 100644
--- a/code/datums/spells/mime.dm
+++ b/code/datums/spells/mime.dm
@@ -99,17 +99,32 @@
action_icon_state = "fingergun"
action_background_icon_state = "bg_mime"
var/gun = /obj/item/gun/projectile/revolver/fingergun
+ var/obj/item/gun/projectile/revolver/fingergun/current_gun
/obj/effect/proc_holder/spell/mime/fingergun/cast(list/targets, mob/user = usr)
for(var/mob/living/carbon/human/C in targets)
- if(!istype(C.get_active_hand(), gun) && !istype(C.get_inactive_hand(), gun))
+ if(!current_gun)
to_chat(user, "You draw your fingers!")
+ current_gun = new gun(get_turf(user), src)
C.drop_item()
- C.put_in_hands(new gun)
+ C.put_in_hands(current_gun)
+ RegisterSignal(C, COMSIG_MOB_WILLINGLY_DROP, PROC_REF(holster_hand))
else
- to_chat(user, "Holster your fingers first.")
+ holster_hand(user, TRUE)
revert_cast(user)
+
+/obj/effect/proc_holder/spell/mime/fingergun/Destroy()
+ current_gun = null
+ return ..()
+
+/obj/effect/proc_holder/spell/mime/fingergun/proc/holster_hand(atom/target, any=FALSE)
+ SIGNAL_HANDLER
+ if(!current_gun || !any && action.owner.get_active_hand() != current_gun)
+ return
+ to_chat(action.owner, "You holster your fingers. Another time perhaps...")
+ QDEL_NULL(current_gun)
+
/obj/effect/proc_holder/spell/mime/fingergun/fake
desc = "Pretend you're shooting bullets out of your fingers! 3 bullets available per cast. Use your fingers to holster them manually."
gun = /obj/item/gun/projectile/revolver/fingergun/fake
diff --git a/code/datums/spells/touch_attacks.dm b/code/datums/spells/touch_attacks.dm
index 3611c0c1353..fc10eeb27e0 100644
--- a/code/datums/spells/touch_attacks.dm
+++ b/code/datums/spells/touch_attacks.dm
@@ -9,26 +9,14 @@
/obj/effect/proc_holder/spell/touch/Click(mob/user = usr)
if(attached_hand)
- qdel(attached_hand)
- cooldown_handler.revert_cast()
- attached_hand = null
- if(on_remove_message)
- to_chat(user, "You draw the power out of your hand.")
+ discharge_hand(user, TRUE)
return FALSE
- ..()
+ charge_hand(user)
-/obj/effect/proc_holder/spell/touch/cast(list/targets, mob/user = usr)
- for(var/mob/living/carbon/target in targets)
- if(!attached_hand)
- if(!ChargeHand(target))
- return FALSE
- while(attached_hand) //hibernate untill the spell is actually used
- cooldown_handler.recharge_time++ // adds a tick onto the cooldown each tick
- sleep(1)
-
-/obj/effect/proc_holder/spell/touch/proc/ChargeHand(mob/living/carbon/user)
+/obj/effect/proc_holder/spell/touch/proc/charge_hand(mob/living/carbon/user)
var/hand_handled = 1
attached_hand = new hand_path(src)
+ RegisterSignal(user, COMSIG_MOB_WILLINGLY_DROP, PROC_REF(discharge_hand))
if(isalien(user))
user.put_in_hands(attached_hand)
return
@@ -42,13 +30,23 @@
hand_handled = 0
if(!hand_handled)
qdel(attached_hand)
- cooldown_handler.revert_cast()
attached_hand = null
to_chat(user, "Your hands are full!")
return 0
to_chat(user, "You channel the power of the spell to your hand.")
return 1
+/obj/effect/proc_holder/spell/touch/proc/discharge_hand(atom/target, any = FALSE)
+ SIGNAL_HANDLER
+ var/mob/living/carbon/user = action.owner
+ if(!istype(attached_hand))
+ return
+ if(!any && attached_hand != user.get_active_hand())
+ return
+ QDEL_NULL(attached_hand)
+ if(on_remove_message)
+ to_chat(user, "You draw the power out of your hand.")
+
/obj/effect/proc_holder/spell/touch/disintegrate
name = "Disintegrate"
diff --git a/code/game/gamemodes/wizard/godhand.dm b/code/game/gamemodes/wizard/godhand.dm
index 42eafd0fd3a..86a590c3e51 100644
--- a/code/game/gamemodes/wizard/godhand.dm
+++ b/code/game/gamemodes/wizard/godhand.dm
@@ -17,6 +17,12 @@
attached_spell = spell
..()
+/obj/item/melee/touch_attack/Destroy()
+ if(attached_spell)
+ attached_spell.attached_hand = null
+ attached_spell.UnregisterSignal(attached_spell.action.owner, COMSIG_MOB_WILLINGLY_DROP)
+ return ..()
+
/obj/item/melee/touch_attack/attack(mob/target, mob/living/carbon/user)
if(!iscarbon(user)) //Look ma, no hands
return
@@ -28,14 +34,10 @@
/obj/item/melee/touch_attack/afterattack(atom/target, mob/user, proximity)
if(catchphrase)
user.say(catchphrase)
- playsound(get_turf(user), on_use_sound,50,1)
- attached_spell.attached_hand = null
- qdel(src)
-
-/obj/item/melee/touch_attack/Destroy()
+ playsound(get_turf(user), on_use_sound, 50, 1)
if(attached_spell)
- attached_spell.attached_hand = null
- return ..()
+ attached_spell.perform(list())
+ qdel(src)
/obj/item/melee/touch_attack/disintegrate
name = "disintegrating touch"
diff --git a/code/modules/antagonists/changeling/powers/mutations.dm b/code/modules/antagonists/changeling/powers/mutations.dm
index cf445b96e3c..30dbaeb3b7f 100644
--- a/code/modules/antagonists/changeling/powers/mutations.dm
+++ b/code/modules/antagonists/changeling/powers/mutations.dm
@@ -18,28 +18,40 @@
var/weapon_name_simple
/datum/action/changeling/weapon/try_to_sting(mob/user, mob/target)
- if(istype(user.l_hand, weapon_type)) //Not the nicest way to do it, but eh
- qdel(user.l_hand)
- if(!silent)
- user.visible_message("With a sickening crunch, [user] reforms [user.p_their()] [weapon_name_simple] into an arm!", "We assimilate the [weapon_name_simple] back into our body.", "You hear organic matter ripping and tearing!")
- user.update_inv_l_hand()
- return
- if(istype(user.r_hand, weapon_type))
- qdel(user.r_hand)
- if(!silent)
- user.visible_message("With a sickening crunch, [user] reforms [user.p_their()] [weapon_name_simple] into an arm!", "We assimilate the [weapon_name_simple] back into our body.", "You hear organic matter ripping and tearing!")
- user.update_inv_r_hand()
+ if(istype(user.l_hand, weapon_type) || istype(user.r_hand, weapon_type))
+ retract(user, TRUE)
return
..(user, target)
/datum/action/changeling/weapon/sting_action(mob/user)
+ SEND_SIGNAL(user, COMSIG_MOB_WEAPON_APPEARS)
if(!user.drop_item())
to_chat(user, "[user.get_active_hand()] is stuck to your hand, you cannot grow a [weapon_name_simple] over it!")
return FALSE
- var/obj/item/W = new weapon_type(user, silent)
+ var/obj/item/W = new weapon_type(user, silent, src)
user.put_in_hands(W)
+ RegisterSignal(user, COMSIG_MOB_WILLINGLY_DROP, PROC_REF(retract), override = TRUE)
+ RegisterSignal(user, COMSIG_MOB_WEAPON_APPEARS, PROC_REF(retract), override = TRUE)
return W
+/datum/action/changeling/weapon/proc/retract(atom/target, any_hand = FALSE)
+ SIGNAL_HANDLER
+ if(!ischangeling(owner))
+ return
+ if(!any_hand && !istype(owner.get_active_hand(), weapon_type))
+ return
+ var/done = FALSE
+ if(istype(owner.l_hand, weapon_type))
+ qdel(owner.l_hand)
+ owner.update_inv_l_hand()
+ done = TRUE
+ if(istype(owner.r_hand, weapon_type))
+ qdel(owner.r_hand)
+ owner.update_inv_r_hand()
+ done = TRUE
+ if(done && !silent)
+ owner.visible_message("With a sickening crunch, [owner] reforms [owner.p_their()] [weapon_name_simple] into an arm!", "We assimilate the [weapon_name_simple] back into our body.", "You hear organic matter ripping and tearing!")
+
//Parent to space suits and armor.
/datum/action/changeling/suit
name = "Organic Suit"
@@ -122,11 +134,20 @@
throwforce = 0 //Just to be on the safe side
throw_range = 0
throw_speed = 0
+ var/datum/action/changeling/weapon/parent_action
-/obj/item/melee/arm_blade/Initialize(mapload)
+/obj/item/melee/arm_blade/Initialize(mapload, silent, new_parent_action)
. = ..()
+ parent_action = new_parent_action
ADD_TRAIT(src, TRAIT_FORCES_OPEN_DOORS_ITEM, ROUNDSTART_TRAIT)
+/obj/item/melee/arm_blade/Destroy()
+ if(parent_action)
+ parent_action.UnregisterSignal(parent_action.owner, COMSIG_MOB_WILLINGLY_DROP)
+ parent_action.UnregisterSignal(parent_action.owner, COMSIG_MOB_WEAPON_APPEARS)
+ parent_action = null
+ return ..()
+
/obj/item/melee/arm_blade/afterattack(atom/target, mob/user, proximity)
if(!proximity)
return
@@ -139,7 +160,6 @@
var/obj/machinery/computer/C = target
C.attack_alien(user) //muh copypasta
-
/***************************************\
|***********COMBAT TENTACLES*************|
\***************************************/
@@ -177,15 +197,24 @@
throwforce = 0 //Just to be on the safe side
throw_range = 0
throw_speed = 0
+ var/datum/action/changeling/weapon/parent_action
-/obj/item/gun/magic/tentacle/Initialize(mapload, silent)
+/obj/item/gun/magic/tentacle/Initialize(mapload, silent, new_parent_action)
. = ..()
+ parent_action = new_parent_action
if(ismob(loc))
if(!silent)
loc.visible_message("[loc.name]\'s arm starts stretching inhumanly!", "Our arm twists and mutates, transforming it into a tentacle.", "You hear organic matter ripping and tearing!")
else
to_chat(loc, "You prepare to extend a tentacle.")
+/obj/item/gun/magic/tentacle/Destroy()
+ if(parent_action)
+ parent_action.UnregisterSignal(parent_action.owner, COMSIG_MOB_WILLINGLY_DROP)
+ parent_action.UnregisterSignal(parent_action.owner, COMSIG_MOB_WEAPON_APPEARS)
+ parent_action = null
+ return ..()
+
/obj/item/gun/magic/tentacle/shoot_with_empty_chamber(mob/living/user as mob|obj)
to_chat(user, "[src] is not ready yet.")
@@ -382,7 +411,6 @@
remaining_uses--
return ..()
-
/***************************************\
|*********SPACE SUIT + HELMET***********|
\***************************************/
diff --git a/code/modules/antagonists/vampire/vampire_powers/hemomancer_powers.dm b/code/modules/antagonists/vampire/vampire_powers/hemomancer_powers.dm
index 19fe443e467..9737d5d37a3 100644
--- a/code/modules/antagonists/vampire/vampire_powers/hemomancer_powers.dm
+++ b/code/modules/antagonists/vampire/vampire_powers/hemomancer_powers.dm
@@ -13,9 +13,23 @@
user.drop_r_hand()
else
to_chat(user, "Large blades of blood spring from your fingers!")
- var/obj/item/twohanded/required/vamp_claws/claws = new /obj/item/twohanded/required/vamp_claws(user.loc)
+ var/obj/item/twohanded/required/vamp_claws/claws = new /obj/item/twohanded/required/vamp_claws(user.loc, src)
+ RegisterSignal(user, COMSIG_MOB_WILLINGLY_DROP, PROC_REF(dispel))
user.put_in_hands(claws)
+/obj/effect/proc_holder/spell/vampire/self/vamp_claws/proc/dispel()
+ SIGNAL_HANDLER
+ var/mob/living/carbon/human/user = action.owner
+ if(user.mind.has_antag_datum(/datum/antagonist/vampire))
+ return
+ var/current
+ if(istype(user.l_hand, /obj/item/twohanded/required/vamp_claws))
+ current = user.l_hand
+ if(istype(user.r_hand, /obj/item/twohanded/required/vamp_claws))
+ current = user.r_hand
+ if(current)
+ qdel(current)
+ to_chat(user, "You dispel your claws!")
/obj/effect/proc_holder/spell/vampire/self/vamp_claws/can_cast(mob/user, charge_check, show_message)
var/mob/living/L = user
@@ -40,6 +54,17 @@
var/durability = 15
var/blood_drain_amount = 15
var/blood_absorbed_amount = 5
+ var/obj/effect/proc_holder/spell/vampire/self/vamp_claws/parent_spell
+
+/obj/item/twohanded/required/vamp_claws/Initialize(mapload, new_parent_spell)
+ . = ..()
+ parent_spell = new_parent_spell
+
+/obj/item/twohanded/required/vamp_claws/Destroy()
+ if(parent_spell)
+ parent_spell.UnregisterSignal(parent_spell.action.owner, COMSIG_MOB_WILLINGLY_DROP)
+ parent_spell = null
+ return ..()
/obj/item/twohanded/required/vamp_claws/afterattack(atom/target, mob/user, proximity)
if(!proximity)
@@ -72,8 +97,8 @@
user.changeNext_move(CLICK_CD_MELEE * 0.5)
/obj/item/twohanded/required/vamp_claws/attack_self(mob/user)
- to_chat(user, "You dispel your claws!")
qdel(src)
+ to_chat(user, "You dispel your claws!")
/obj/effect/proc_holder/spell/vampire/blood_tendrils
name = "Blood Tendrils (10)"
diff --git a/code/modules/mob/inventory_procs.dm b/code/modules/mob/inventory_procs.dm
index d0cb1b47637..b871d35e75a 100644
--- a/code/modules/mob/inventory_procs.dm
+++ b/code/modules/mob/inventory_procs.dm
@@ -125,7 +125,7 @@
return unEquip(r_hand, force) //Why was this not calling unEquip in the first place jesus fuck.
//Drops the item in our active hand.
-/mob/proc/drop_item() //THIS. DOES. NOT. NEED. AN. ARGUMENT.
+/mob/proc/drop_item()
if(hand)
return drop_l_hand()
else
diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid_inventory.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid_inventory.dm
index d4b7ca7c9ca..223736b3668 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/humanoid_inventory.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid_inventory.dm
@@ -1,6 +1,6 @@
//unequip
/mob/living/carbon/alien/humanoid/unEquip(obj/item/I, force, silent = FALSE)
- . = ..(I, force)
+ . = ..()
if(!. || !I)
return
diff --git a/code/modules/projectiles/guns/projectile/revolver.dm b/code/modules/projectiles/guns/projectile/revolver.dm
index 5f1a5e45168..8dae5f84ed2 100644
--- a/code/modules/projectiles/guns/projectile/revolver.dm
+++ b/code/modules/projectiles/guns/projectile/revolver.dm
@@ -108,13 +108,22 @@
trigger_guard = TRIGGER_GUARD_ALLOW_ALL
clumsy_check = FALSE //Stole your uplink! Honk!
needs_permit = FALSE //go away beepsky
+ var/obj/effect/proc_holder/spell/mime/fingergun/parent_spell
+
+/obj/item/gun/projectile/revolver/fingergun/Destroy()
+ if(parent_spell)
+ parent_spell.current_gun = null
+ parent_spell.UnregisterSignal(parent_spell.action.owner, COMSIG_MOB_WILLINGLY_DROP)
+ parent_spell = null
+ return ..()
/obj/item/gun/projectile/revolver/fingergun/fake
desc = "Pew pew pew!"
mag_type = /obj/item/ammo_box/magazine/internal/cylinder/rev38/invisible/fake
-/obj/item/gun/projectile/revolver/fingergun/Initialize(mapload)
+/obj/item/gun/projectile/revolver/fingergun/Initialize(mapload, new_parent_spell)
. = ..()
+ parent_spell = new_parent_spell
verbs -= /obj/item/gun/projectile/revolver/verb/spin
/obj/item/gun/projectile/revolver/fingergun/shoot_with_empty_chamber(/*mob/living/user as mob|obj*/)