mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-21 03:59:59 +01:00
Afterattack is dead, long live Afterattack (#83818)
## About The Pull Request - Afterattack is a very simple proc now: All it does is this, and all it's used for is for having a convenient place to put effects an item does after a successful attack (IE, the attack was not blocked)  - An overwhelming majority of afterattack implementations have been moved to `interact_with_atom` or the new `ranged_interact_with_atom` I have manually tested many of the refactored procs but there was 200+ so it's kinda hard ## Why It's Good For The Game Afterattack is one of the worst parts of the attack chain, as it simultaneously serves as a way of doing random interactions NOT AT ALL related to attacks (despite the name) while ALSO serving as the defacto way to do a ranged interaction with an item This means careless coders (most of them) may throw stuff in afterattack without realizing how wide reaching it is, which causes bugs. By making two well defined, separate procs for handing adjacent vs ranged interactions, it becomes WAY WAY WAY more easy to develop for. If you want to do something when you click on something else and you're adjacent, use `interact_with_atom` If you want to do something when you click on something else and you're not adjacent, use 'ranged_interact_with_atom` This does result in some instances of boilerplate as shown here:  But I think it's acceptable, feel free to oppose if you don't I'm sure we can think of another solution ~~Additionally it makes it easier to implement swing combat. That's a bonus I guess~~ ## Changelog 🆑 Melbert refactor: Over 200 item interactions have been refactored to use a newer, easier-to-use system. Report any oddities with using items on other objects you may see (such as surgery, reagent containers like cups and spray bottles, or construction devices), especially using something at range (such as guns or chisels) refactor: Item-On-Modsuit interactions have changed slightly. While on combat mode, you will attempt to "use" the item on the suit instead of inserting it into the suit's storage. This means being on combat mode while the suit's panel is open will block you from inserting items entirely via click (but other methods such as hotkey, clicking on the storage boxes, and mousedrop will still work). refactor: The detective's scanner will now be inserted into storage items if clicked normally, and will scan the storage item if on combat mode /🆑
This commit is contained in:
@@ -63,14 +63,8 @@
|
||||
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/abductor/gizmo/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
// Proximity is already handled via the interact_with_atom proc
|
||||
if(proximity_flag)
|
||||
return
|
||||
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
interact_with_atom(target, user)
|
||||
/obj/item/abductor/gizmo/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
return interact_with_atom(interacting_with, user, modifiers)
|
||||
|
||||
/obj/item/abductor/gizmo/proc/scan(atom/target, mob/living/user)
|
||||
if(ishuman(target))
|
||||
@@ -117,14 +111,8 @@
|
||||
radio_off(interacting_with, user)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/abductor/silencer/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
// Proximity is already handled via the interact_with_atom proc
|
||||
if(proximity_flag)
|
||||
return
|
||||
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
interact_with_atom(target, user)
|
||||
/obj/item/abductor/silencer/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
return interact_with_atom(interacting_with, user, modifiers)
|
||||
|
||||
/obj/item/abductor/silencer/proc/radio_off(atom/target, mob/living/user)
|
||||
if( !(user in (viewers(7,target))) )
|
||||
@@ -167,17 +155,19 @@
|
||||
icon_state = "mind_device_message"
|
||||
to_chat(user, span_notice("You switch the device to [mode == MIND_DEVICE_MESSAGE? "TRANSMISSION": "COMMAND"] MODE"))
|
||||
|
||||
/obj/item/abductor/mind_device/afterattack(atom/target, mob/living/user, flag, params)
|
||||
. = ..()
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
/obj/item/abductor/mind_device/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
return interact_with_atom(interacting_with, user, modifiers)
|
||||
|
||||
/obj/item/abductor/mind_device/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!ScientistCheck(user))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
switch(mode)
|
||||
if(MIND_DEVICE_CONTROL)
|
||||
mind_control(target, user)
|
||||
mind_control(interacting_with, user)
|
||||
if(MIND_DEVICE_MESSAGE)
|
||||
mind_message(target, user)
|
||||
mind_message(interacting_with, user)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/abductor/mind_device/proc/mind_control(atom/target, mob/living/user)
|
||||
if(iscarbon(target))
|
||||
|
||||
@@ -218,17 +218,13 @@
|
||||
effectiveness = 80, \
|
||||
)
|
||||
|
||||
/obj/item/melee/arm_blade/afterattack(atom/target, mob/user, proximity)
|
||||
. = ..()
|
||||
if(!proximity)
|
||||
return
|
||||
/obj/item/melee/arm_blade/afterattack(atom/target, mob/user, click_parameters)
|
||||
if(istype(target, /obj/structure/table))
|
||||
var/obj/structure/table/T = target
|
||||
T.deconstruct(FALSE)
|
||||
var/obj/smash = target
|
||||
smash.deconstruct(FALSE)
|
||||
|
||||
else if(istype(target, /obj/machinery/computer))
|
||||
var/obj/machinery/computer/C = target
|
||||
C.attack_alien(user) //muh copypasta
|
||||
target.attack_alien(user) //muh copypasta
|
||||
|
||||
else if(istype(target, /obj/machinery/door/airlock))
|
||||
var/obj/machinery/door/airlock/opening = target
|
||||
|
||||
@@ -376,7 +376,7 @@
|
||||
return ..()
|
||||
|
||||
/obj/item/melee/blood_magic/attack_self(mob/living/user)
|
||||
afterattack(user, user, TRUE)
|
||||
cast_spell(user, user)
|
||||
|
||||
/obj/item/melee/blood_magic/attack(mob/living/M, mob/living/carbon/user)
|
||||
if(!iscarbon(user) || !IS_CULTIST(user))
|
||||
@@ -387,9 +387,18 @@
|
||||
SSblackbox.record_feedback("tally", "cult_spell_invoke", 1, "[name]")
|
||||
M.lastattacker = user.real_name
|
||||
M.lastattackerckey = user.ckey
|
||||
cast_spell(M, user)
|
||||
|
||||
/obj/item/melee/blood_magic/afterattack(atom/target, mob/living/carbon/user, proximity)
|
||||
. = ..()
|
||||
/obj/item/melee/blood_magic/attack_atom(atom/attacked_atom, mob/living/user, params)
|
||||
if(!iscarbon(user) || !IS_CULTIST(user))
|
||||
uses = 0
|
||||
qdel(src)
|
||||
return
|
||||
log_combat(user, attacked_atom, "used a cult spell on", source.name, "")
|
||||
SSblackbox.record_feedback("tally", "cult_spell_invoke", 1, "[name]")
|
||||
cast_spell(attacked_atom, user)
|
||||
|
||||
/obj/item/melee/blood_magic/proc/cast_spell(atom/target, mob/living/carbon/user)
|
||||
if(invocation)
|
||||
user.whisper(invocation, language = /datum/language/common)
|
||||
if(health_cost)
|
||||
@@ -411,41 +420,41 @@
|
||||
color = RUNE_COLOR_RED
|
||||
invocation = "Fuu ma'jin!"
|
||||
|
||||
/obj/item/melee/blood_magic/stun/afterattack(mob/living/target, mob/living/carbon/user, proximity)
|
||||
if(!isliving(target) || !proximity)
|
||||
return
|
||||
if(IS_CULTIST(target))
|
||||
/obj/item/melee/blood_magic/stun/cast_spell(mob/living/target, mob/living/carbon/user)
|
||||
if(!istype(target) || IS_CULTIST(target))
|
||||
return
|
||||
var/datum/antagonist/cult/cultist = IS_CULTIST(user)
|
||||
if(!isnull(cultist))
|
||||
var/datum/team/cult/cult_team = cultist.get_team()
|
||||
var/effect_coef = 1 - (cult_team.cult_risen ? 0.4 : 0) - (cult_team.cult_ascendent ? 0.5 : 0)
|
||||
user.visible_message(span_warning("[user] holds up [user.p_their()] hand, which explodes in a flash of red light!"), \
|
||||
span_cult_italic("You attempt to stun [target] with the spell!"))
|
||||
user.mob_light(range = 1.1, power = 2, color = LIGHT_COLOR_BLOOD_MAGIC, duration = 0.2 SECONDS)
|
||||
if(IS_HERETIC(target))
|
||||
to_chat(user, span_warning("Some force greater than you intervenes! [target] is protected by the Forgotten Gods!"))
|
||||
to_chat(target, span_warning("You are protected by your faith to the Forgotten Gods."))
|
||||
var/old_color = target.color
|
||||
target.color = rgb(0, 128, 0)
|
||||
animate(target, color = old_color, time = 1 SECONDS, easing = EASE_IN)
|
||||
else if(target.can_block_magic())
|
||||
to_chat(user, span_warning("The spell had no effect!"))
|
||||
else
|
||||
to_chat(user, span_cult_italic("In a brilliant flash of red, [target] falls to the ground!"))
|
||||
target.Paralyze(16 SECONDS * effect_coef)
|
||||
target.flash_act(1, TRUE)
|
||||
if(issilicon(target))
|
||||
var/mob/living/silicon/silicon_target = target
|
||||
silicon_target.emp_act(EMP_HEAVY)
|
||||
else if(iscarbon(target))
|
||||
var/mob/living/carbon/carbon_target = target
|
||||
carbon_target.adjust_silence(12 SECONDS * effect_coef)
|
||||
carbon_target.adjust_stutter(30 SECONDS * effect_coef)
|
||||
carbon_target.adjust_timed_status_effect(30 SECONDS * effect_coef, /datum/status_effect/speech/slurring/cult)
|
||||
carbon_target.set_jitter_if_lower(30 SECONDS * effect_coef)
|
||||
uses--
|
||||
..()
|
||||
var/datum/team/cult/cult_team = cultist.get_team()
|
||||
var/effect_coef = 1 - (cult_team.cult_risen ? 0.4 : 0) - (cult_team.cult_ascendent ? 0.5 : 0)
|
||||
user.visible_message(
|
||||
span_warning("[user] holds up [user.p_their()] hand, which explodes in a flash of red light!"),
|
||||
span_cult_italic("You attempt to stun [target] with the spell!"),
|
||||
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
|
||||
)
|
||||
user.mob_light(range = 1.1, power = 2, color = LIGHT_COLOR_BLOOD_MAGIC, duration = 0.2 SECONDS)
|
||||
if(IS_HERETIC(target))
|
||||
to_chat(user, span_warning("Some force greater than you intervenes! [target] is protected by the Forgotten Gods!"))
|
||||
to_chat(target, span_warning("You are protected by your faith to the Forgotten Gods."))
|
||||
var/old_color = target.color
|
||||
target.color = rgb(0, 128, 0)
|
||||
animate(target, color = old_color, time = 1 SECONDS, easing = EASE_IN)
|
||||
else if(target.can_block_magic())
|
||||
to_chat(user, span_warning("The spell had no effect!"))
|
||||
else
|
||||
to_chat(user, span_cult_italic("In a brilliant flash of red, [target] falls to the ground!"))
|
||||
target.Paralyze(16 SECONDS * effect_coef)
|
||||
target.flash_act(1, TRUE)
|
||||
if(issilicon(target))
|
||||
var/mob/living/silicon/silicon_target = target
|
||||
silicon_target.emp_act(EMP_HEAVY)
|
||||
else if(iscarbon(target))
|
||||
var/mob/living/carbon/carbon_target = target
|
||||
carbon_target.adjust_silence(12 SECONDS * effect_coef)
|
||||
carbon_target.adjust_stutter(30 SECONDS * effect_coef)
|
||||
carbon_target.adjust_timed_status_effect(30 SECONDS * effect_coef, /datum/status_effect/speech/slurring/cult)
|
||||
carbon_target.set_jitter_if_lower(30 SECONDS * effect_coef)
|
||||
uses--
|
||||
return ..()
|
||||
|
||||
//Teleportation
|
||||
/obj/item/melee/blood_magic/teleport
|
||||
@@ -454,47 +463,50 @@
|
||||
desc = "Will teleport a cultist to a teleport rune on contact."
|
||||
invocation = "Sas'so c'arta forbici!"
|
||||
|
||||
/obj/item/melee/blood_magic/teleport/afterattack(atom/target, mob/living/carbon/user, proximity)
|
||||
var/mob/mob_target = target
|
||||
if(istype(mob_target) && !IS_CULTIST(mob_target) || !proximity)
|
||||
to_chat(user, span_warning("You can only teleport adjacent cultists with this spell!"))
|
||||
/obj/item/melee/blood_magic/teleport/cast_spell(mob/living/target, mob/living/carbon/user)
|
||||
if(!istype(target) || !IS_CULTIST(target))
|
||||
to_chat(user, span_warning("You can only teleport cultists with this spell!"))
|
||||
return
|
||||
if(IS_CULTIST(user))
|
||||
var/list/potential_runes = list()
|
||||
var/list/teleportnames = list()
|
||||
for(var/obj/effect/rune/teleport/teleport_rune as anything in GLOB.teleport_runes)
|
||||
potential_runes[avoid_assoc_duplicate_keys(teleport_rune.listkey, teleportnames)] = teleport_rune
|
||||
|
||||
if(!length(potential_runes))
|
||||
to_chat(user, span_warning("There are no valid runes to teleport to!"))
|
||||
return
|
||||
var/list/potential_runes = list()
|
||||
var/list/teleportnames = list()
|
||||
for(var/obj/effect/rune/teleport/teleport_rune as anything in GLOB.teleport_runes)
|
||||
potential_runes[avoid_assoc_duplicate_keys(teleport_rune.listkey, teleportnames)] = teleport_rune
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
if(is_away_level(T.z))
|
||||
to_chat(user, span_cult_italic("You are not in the right dimension!"))
|
||||
return
|
||||
|
||||
var/input_rune_key = tgui_input_list(user, "Rune to teleport to", "Teleportation Target", potential_runes) //we know what key they picked
|
||||
if(isnull(input_rune_key))
|
||||
return
|
||||
if(isnull(potential_runes[input_rune_key]))
|
||||
to_chat(user, span_warning("You must pick a valid rune!"))
|
||||
return
|
||||
var/obj/effect/rune/teleport/actual_selected_rune = potential_runes[input_rune_key] //what rune does that key correspond to?
|
||||
if(QDELETED(src) || !user || !user.is_holding(src) || user.incapacitated() || !actual_selected_rune || !proximity)
|
||||
return
|
||||
var/turf/dest = get_turf(actual_selected_rune)
|
||||
if(dest.is_blocked_turf(TRUE))
|
||||
to_chat(user, span_warning("The target rune is blocked. You cannot teleport there."))
|
||||
return
|
||||
uses--
|
||||
var/turf/origin = get_turf(user)
|
||||
var/mob/living/L = target
|
||||
if(do_teleport(L, dest, channel = TELEPORT_CHANNEL_CULT))
|
||||
origin.visible_message(span_warning("Dust flows from [user]'s hand, and [user.p_they()] disappear[user.p_s()] with a sharp crack!"), \
|
||||
span_cult_italic("You speak the words of the talisman and find yourself somewhere else!"), "<i>You hear a sharp crack.</i>")
|
||||
dest.visible_message(span_warning("There is a boom of outrushing air as something appears above the rune!"), null, "<i>You hear a boom.</i>")
|
||||
..()
|
||||
if(!length(potential_runes))
|
||||
to_chat(user, span_warning("There are no valid runes to teleport to!"))
|
||||
return
|
||||
var/turf/T = get_turf(src)
|
||||
if(is_away_level(T.z))
|
||||
to_chat(user, span_cult_italic("You are not in the right dimension!"))
|
||||
return
|
||||
var/input_rune_key = tgui_input_list(user, "Rune to teleport to", "Teleportation Target", potential_runes) //we know what key they picked
|
||||
if(isnull(input_rune_key))
|
||||
return
|
||||
if(isnull(potential_runes[input_rune_key]))
|
||||
to_chat(user, span_warning("You must pick a valid rune!"))
|
||||
return
|
||||
var/obj/effect/rune/teleport/actual_selected_rune = potential_runes[input_rune_key] //what rune does that key correspond to?
|
||||
if(QDELETED(src) || !user || !user.is_holding(src) || user.incapacitated() || !actual_selected_rune)
|
||||
return
|
||||
var/turf/dest = get_turf(actual_selected_rune)
|
||||
if(dest.is_blocked_turf(TRUE))
|
||||
to_chat(user, span_warning("The target rune is blocked. You cannot teleport there."))
|
||||
return
|
||||
uses--
|
||||
var/turf/origin = get_turf(user)
|
||||
if(do_teleport(target, dest, channel = TELEPORT_CHANNEL_CULT))
|
||||
origin.visible_message(
|
||||
span_warning("Dust flows from [user]'s hand, and [user.p_they()] disappear[user.p_s()] with a sharp crack!"),
|
||||
span_cult_italic("You speak the words of the talisman and find yourself somewhere else!"),
|
||||
span_hear("You hear a sharp crack."),
|
||||
)
|
||||
dest.visible_message(
|
||||
span_warning("There is a boom of outrushing air as something appears above the rune!"),
|
||||
null,
|
||||
span_hear("You hear a boom."),
|
||||
)
|
||||
return ..()
|
||||
|
||||
//Shackles
|
||||
/obj/item/melee/blood_magic/shackles
|
||||
@@ -503,15 +515,17 @@
|
||||
invocation = "In'totum Lig'abis!"
|
||||
color = COLOR_BLACK // black
|
||||
|
||||
/obj/item/melee/blood_magic/shackles/afterattack(atom/target, mob/living/carbon/user, proximity)
|
||||
if(IS_CULTIST(user) && iscarbon(target) && proximity)
|
||||
var/mob/living/carbon/C = target
|
||||
if(C.canBeHandcuffed())
|
||||
CuffAttack(C, user)
|
||||
else
|
||||
user.visible_message(span_cult_italic("This victim doesn't have enough arms to complete the restraint!"))
|
||||
return
|
||||
..()
|
||||
/obj/item/melee/blood_magic/shackles/cast_spell(atom/target, mob/living/carbon/user)
|
||||
if(!iscarbon(target))
|
||||
return
|
||||
var/mob/living/carbon/C = target
|
||||
if(IS_CULTIST(C))
|
||||
return
|
||||
if(!C.canBeHandcuffed())
|
||||
user.visible_message(span_cult_italic("This victim doesn't have enough arms to complete the restraint!"))
|
||||
return
|
||||
CuffAttack(C, user)
|
||||
return ..()
|
||||
|
||||
/obj/item/melee/blood_magic/shackles/proc/CuffAttack(mob/living/carbon/C, mob/living/user)
|
||||
if(!C.handcuffed)
|
||||
@@ -564,90 +578,95 @@
|
||||
Purified soulstones (and any shades inside) into cultist soulstones\n
|
||||
Airlocks into brittle runed airlocks after a delay (harm intent)"}
|
||||
|
||||
/obj/item/melee/blood_magic/construction/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
if(proximity_flag && IS_CULTIST(user))
|
||||
if(channeling)
|
||||
to_chat(user, span_cult_italic("You are already invoking twisted construction!"))
|
||||
/obj/item/melee/blood_magic/construction/cast_spell(atom/target, mob/living/carbon/user)
|
||||
if(channeling)
|
||||
to_chat(user, span_cult_italic("You are already invoking twisted construction!"))
|
||||
return
|
||||
|
||||
var/turf/T = get_turf(target)
|
||||
if(istype(target, /obj/item/stack/sheet/iron))
|
||||
var/obj/item/stack/sheet/candidate = target
|
||||
if(!candidate.use(IRON_TO_CONSTRUCT_SHELL_CONVERSION))
|
||||
to_chat(user, span_warning("You need [IRON_TO_CONSTRUCT_SHELL_CONVERSION] iron to produce a construct shell!"))
|
||||
return
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
var/turf/T = get_turf(target)
|
||||
if(istype(target, /obj/item/stack/sheet/iron))
|
||||
var/obj/item/stack/sheet/candidate = target
|
||||
if(candidate.use(IRON_TO_CONSTRUCT_SHELL_CONVERSION))
|
||||
uses--
|
||||
to_chat(user, span_warning("A dark cloud emanates from your hand and swirls around the iron, twisting it into a construct shell!"))
|
||||
new /obj/structure/constructshell(T)
|
||||
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
|
||||
else
|
||||
to_chat(user, span_warning("You need [IRON_TO_CONSTRUCT_SHELL_CONVERSION] iron to produce a construct shell!"))
|
||||
return
|
||||
else if(istype(target, /obj/item/stack/sheet/plasteel))
|
||||
var/obj/item/stack/sheet/plasteel/candidate = target
|
||||
var/quantity = candidate.amount
|
||||
if(candidate.use(quantity))
|
||||
uses --
|
||||
new /obj/item/stack/sheet/runed_metal(T,quantity)
|
||||
to_chat(user, span_warning("A dark cloud emanates from you hand and swirls around the plasteel, transforming it into runed metal!"))
|
||||
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
|
||||
else if(istype(target,/mob/living/silicon/robot))
|
||||
var/mob/living/silicon/robot/candidate = target
|
||||
if(candidate.mmi || candidate.shell)
|
||||
channeling = TRUE
|
||||
user.visible_message(span_danger("A dark cloud emanates from [user]'s hand and swirls around [candidate]!"))
|
||||
playsound(T, 'sound/machines/airlock_alien_prying.ogg', 80, TRUE)
|
||||
var/prev_color = candidate.color
|
||||
candidate.color = "black"
|
||||
if(do_after(user, 9 SECONDS, target = candidate))
|
||||
candidate.undeploy()
|
||||
candidate.emp_act(EMP_HEAVY)
|
||||
var/construct_class = show_radial_menu(user, src, GLOB.construct_radial_images, custom_check = CALLBACK(src, PROC_REF(check_menu), user), require_near = TRUE, tooltips = TRUE)
|
||||
if(!check_menu(user))
|
||||
return
|
||||
if(QDELETED(candidate))
|
||||
channeling = FALSE
|
||||
return
|
||||
candidate.grab_ghost()
|
||||
user.visible_message(span_danger("The dark cloud recedes from what was formerly [candidate], revealing a\n [construct_class]!"))
|
||||
make_new_construct_from_class(construct_class, THEME_CULT, candidate, user, FALSE, T)
|
||||
uses--
|
||||
qdel(candidate)
|
||||
channeling = FALSE
|
||||
else
|
||||
channeling = FALSE
|
||||
candidate.color = prev_color
|
||||
return
|
||||
else
|
||||
uses--
|
||||
to_chat(user, span_warning("A dark cloud emanates from you hand and swirls around [candidate] - twisting it into a construct shell!"))
|
||||
new /obj/structure/constructshell(T)
|
||||
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
|
||||
qdel(candidate)
|
||||
else if(istype(target,/obj/machinery/door/airlock))
|
||||
uses--
|
||||
to_chat(user, span_warning("A dark cloud emanates from your hand and swirls around the iron, twisting it into a construct shell!"))
|
||||
new /obj/structure/constructshell(T)
|
||||
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
|
||||
return ..()
|
||||
|
||||
if(istype(target, /obj/item/stack/sheet/plasteel))
|
||||
var/obj/item/stack/sheet/plasteel/candidate = target
|
||||
var/quantity = candidate.amount
|
||||
if(!candidate.use(quantity))
|
||||
return
|
||||
|
||||
uses--
|
||||
new /obj/item/stack/sheet/runed_metal(T,quantity)
|
||||
to_chat(user, span_warning("A dark cloud emanates from you hand and swirls around the plasteel, transforming it into runed metal!"))
|
||||
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
|
||||
return ..()
|
||||
|
||||
if(istype(target,/mob/living/silicon/robot))
|
||||
var/mob/living/silicon/robot/candidate = target
|
||||
if(candidate.mmi || candidate.shell)
|
||||
channeling = TRUE
|
||||
playsound(T, 'sound/machines/airlockforced.ogg', 50, TRUE)
|
||||
do_sparks(5, TRUE, target)
|
||||
if(do_after(user, 5 SECONDS, target = user))
|
||||
if(QDELETED(target))
|
||||
channeling = FALSE
|
||||
return
|
||||
target.narsie_act()
|
||||
uses--
|
||||
user.visible_message(span_warning("Black ribbons suddenly emanate from [user]'s hand and cling to the airlock - twisting and corrupting it!"))
|
||||
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
|
||||
channeling = FALSE
|
||||
else
|
||||
user.visible_message(span_danger("A dark cloud emanates from [user]'s hand and swirls around [candidate]!"))
|
||||
playsound(T, 'sound/machines/airlock_alien_prying.ogg', 80, TRUE)
|
||||
var/prev_color = candidate.color
|
||||
candidate.color = "black"
|
||||
if(!do_after(user, 9 SECONDS, target = candidate))
|
||||
channeling = FALSE
|
||||
candidate.color = prev_color
|
||||
return
|
||||
else if(istype(target,/obj/item/soulstone))
|
||||
var/obj/item/soulstone/candidate = target
|
||||
if(candidate.corrupt())
|
||||
uses--
|
||||
to_chat(user, span_warning("You corrupt [candidate]!"))
|
||||
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
|
||||
else
|
||||
to_chat(user, span_warning("The spell will not work on [target]!"))
|
||||
candidate.undeploy()
|
||||
candidate.emp_act(EMP_HEAVY)
|
||||
var/construct_class = show_radial_menu(user, src, GLOB.construct_radial_images, custom_check = CALLBACK(src, PROC_REF(check_menu), user), require_near = TRUE, tooltips = TRUE)
|
||||
if(!check_menu(user) || QDELETED(candidate))
|
||||
channeling = FALSE
|
||||
candidate.color = prev_color
|
||||
return
|
||||
candidate.grab_ghost()
|
||||
user.visible_message(span_danger("The dark cloud recedes from what was formerly [candidate], revealing a\n [construct_class]!"))
|
||||
make_new_construct_from_class(construct_class, THEME_CULT, candidate, user, FALSE, T)
|
||||
uses--
|
||||
qdel(candidate)
|
||||
channeling = FALSE
|
||||
return ..()
|
||||
|
||||
uses--
|
||||
to_chat(user, span_warning("A dark cloud emanates from you hand and swirls around [candidate] - twisting it into a construct shell!"))
|
||||
new /obj/structure/constructshell(T)
|
||||
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
|
||||
qdel(candidate)
|
||||
return ..()
|
||||
|
||||
if(istype(target,/obj/machinery/door/airlock))
|
||||
channeling = TRUE
|
||||
playsound(T, 'sound/machines/airlockforced.ogg', 50, TRUE)
|
||||
do_sparks(5, TRUE, target)
|
||||
if(!do_after(user, 5 SECONDS, target = user) && !QDELETED(target))
|
||||
channeling = FALSE
|
||||
return
|
||||
return . | ..()
|
||||
|
||||
target.narsie_act()
|
||||
uses--
|
||||
user.visible_message(span_warning("Black ribbons suddenly emanate from [user]'s hand and cling to the airlock - twisting and corrupting it!"))
|
||||
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
|
||||
channeling = FALSE
|
||||
return ..()
|
||||
|
||||
if(istype(target,/obj/item/soulstone))
|
||||
var/obj/item/soulstone/candidate = target
|
||||
if(!candidate.corrupt())
|
||||
return
|
||||
|
||||
uses--
|
||||
to_chat(user, span_warning("You corrupt [candidate]!"))
|
||||
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
|
||||
return ..()
|
||||
|
||||
to_chat(user, span_warning("The spell will not work on [target]!"))
|
||||
|
||||
/obj/item/melee/blood_magic/construction/proc/check_menu(mob/user)
|
||||
if(!istype(user))
|
||||
@@ -663,21 +682,21 @@
|
||||
desc = "Will equip cult combat gear onto a cultist on contact."
|
||||
color = "#33cc33" // green
|
||||
|
||||
/obj/item/melee/blood_magic/armor/afterattack(atom/target, mob/living/carbon/user, proximity)
|
||||
/obj/item/melee/blood_magic/armor/cast_spell(mob/living/target, mob/living/carbon/user)
|
||||
if(!iscarbon(target) || !IS_CULTIST(target))
|
||||
return
|
||||
uses--
|
||||
var/mob/living/carbon/carbon_target = target
|
||||
if(istype(carbon_target) && IS_CULTIST(carbon_target) && proximity)
|
||||
uses--
|
||||
var/mob/living/carbon/C = target
|
||||
C.visible_message(span_warning("Otherworldly armor suddenly appears on [C]!"))
|
||||
C.equip_to_slot_or_del(new /obj/item/clothing/under/color/black,ITEM_SLOT_ICLOTHING)
|
||||
C.equip_to_slot_or_del(new /obj/item/clothing/suit/hooded/cultrobes/alt(user), ITEM_SLOT_OCLOTHING)
|
||||
C.equip_to_slot_or_del(new /obj/item/clothing/shoes/cult/alt(user), ITEM_SLOT_FEET)
|
||||
C.equip_to_slot_or_del(new /obj/item/storage/backpack/cultpack(user), ITEM_SLOT_BACK)
|
||||
if(C == user)
|
||||
qdel(src) //Clears the hands
|
||||
C.put_in_hands(new /obj/item/melee/cultblade/dagger(user))
|
||||
C.put_in_hands(new /obj/item/restraints/legcuffs/bola/cult(user))
|
||||
..()
|
||||
carbon_target.visible_message(span_warning("Otherworldly armor suddenly appears on [carbon_target]!"))
|
||||
carbon_target.equip_to_slot_or_del(new /obj/item/clothing/under/color/black,ITEM_SLOT_ICLOTHING)
|
||||
carbon_target.equip_to_slot_or_del(new /obj/item/clothing/suit/hooded/cultrobes/alt(user), ITEM_SLOT_OCLOTHING)
|
||||
carbon_target.equip_to_slot_or_del(new /obj/item/clothing/shoes/cult/alt(user), ITEM_SLOT_FEET)
|
||||
carbon_target.equip_to_slot_or_del(new /obj/item/storage/backpack/cultpack(user), ITEM_SLOT_BACK)
|
||||
if(carbon_target == user)
|
||||
qdel(src) //Clears the hands
|
||||
carbon_target.put_in_hands(new /obj/item/melee/cultblade/dagger(user))
|
||||
carbon_target.put_in_hands(new /obj/item/restraints/legcuffs/bola/cult(user))
|
||||
return ..()
|
||||
|
||||
/obj/item/melee/blood_magic/manipulator
|
||||
name = "Blood Rite Aura"
|
||||
@@ -698,10 +717,7 @@
|
||||
*
|
||||
* '/obj/item/melee/blood_magic/manipulator/proc/blood_draw' handles blood pools/trails and does not affect parent proc
|
||||
*/
|
||||
/obj/item/melee/blood_magic/manipulator/afterattack(atom/target, mob/living/carbon/human/user, proximity)
|
||||
if(!proximity)
|
||||
return
|
||||
|
||||
/obj/item/melee/blood_magic/manipulator/cast_spell(mob/living/target, mob/living/carbon/user)
|
||||
if((isconstruct(target) || isshade(target)) && !heal_construct(target, user))
|
||||
return
|
||||
if(istype(target, /obj/effect/decal/cleanable/blood) || istype(target, /obj/effect/decal/cleanable/trail_holder) || isturf(target))
|
||||
@@ -714,12 +730,11 @@
|
||||
if(human_bloodbag.stat == DEAD)
|
||||
human_bloodbag.balloon_alert(user, "dead!")
|
||||
return
|
||||
|
||||
if(IS_CULTIST(human_bloodbag) && !heal_cultist(human_bloodbag, user))
|
||||
return
|
||||
if(!IS_CULTIST(human_bloodbag) && !drain_victim(human_bloodbag, user))
|
||||
return
|
||||
..()
|
||||
return ..()
|
||||
|
||||
/**
|
||||
* handles blood rites usage on constructs
|
||||
|
||||
@@ -639,49 +639,49 @@ Striking a noncultist, however, will tear their flesh."}
|
||||
var/charges = 5
|
||||
start_on = TRUE
|
||||
|
||||
/obj/item/flashlight/flare/culttorch/afterattack(atom/movable/A, mob/user, proximity)
|
||||
if(!proximity)
|
||||
return
|
||||
if(!IS_CULTIST(user))
|
||||
to_chat(user, "That doesn't seem to do anything useful.")
|
||||
return
|
||||
/obj/item/flashlight/flare/culttorch/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
var/datum/antagonist/cult/cult = user.mind.has_antag_datum(/datum/antagonist/cult)
|
||||
var/datum/team/cult/cult_team = cult?.get_team()
|
||||
if(isnull(cult_team))
|
||||
to_chat(user, span_warning("That doesn't seem to do anything useful."))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
if(!isitem(A))
|
||||
..()
|
||||
to_chat(user, span_warning("\The [src] can only transport items!"))
|
||||
return
|
||||
if(!isitem(interacting_with))
|
||||
to_chat(user, span_warning("[src] can only transport items!"))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
var/list/mob/living/cultists = list()
|
||||
for(var/datum/mind/cult_mind as anything in cult_team.members)
|
||||
if(cult_mind == user.mind)
|
||||
continue
|
||||
if(cult_mind.current?.stat != DEAD)
|
||||
cultists |= cult_mind.current
|
||||
|
||||
var/list/cultists = list()
|
||||
for(var/datum/mind/M as anything in get_antag_minds(/datum/antagonist/cult))
|
||||
if(M.current && M.current.stat != DEAD)
|
||||
cultists |= M.current
|
||||
var/mob/living/cultist_to_receive = tgui_input_list(user, "Who do you wish to call to [src]?", "Followers of the Geometer", (cultists - user))
|
||||
if(!Adjacent(user) || !src || QDELETED(src) || user.incapacitated())
|
||||
return
|
||||
if(QDELETED(src) || loc != user || user.incapacitated())
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(isnull(cultist_to_receive))
|
||||
to_chat(user, "<span class='cult italic'>You require a destination!</span>")
|
||||
log_game("[key_name(user)]'s Void torch failed - no target.")
|
||||
return
|
||||
to_chat(user, span_cult_italic("You require a destination!"))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(cultist_to_receive.stat == DEAD)
|
||||
to_chat(user, "<span class='cult italic'>[cultist_to_receive] has died!</span>")
|
||||
log_game("[key_name(user)]'s Void torch failed - target died.")
|
||||
return
|
||||
if(!IS_CULTIST(cultist_to_receive))
|
||||
to_chat(user, "<span class='cult italic'>[cultist_to_receive] is not a follower of the Geometer!</span>")
|
||||
log_game("[key_name(user)]'s Void torch failed - target was deconverted.")
|
||||
return
|
||||
if(A in user.get_all_contents())
|
||||
to_chat(user, "<span class='cult italic'>[A] must be on a surface in order to teleport it!</span>")
|
||||
return
|
||||
to_chat(user, "<span class='cult italic'>You ignite [A] with \the [src], turning it to ash, but through the torch's flames you see that [A] has reached [cultist_to_receive]!</span>")
|
||||
user.log_message("teleported [A] to [cultist_to_receive] with \the [src].", LOG_GAME)
|
||||
cultist_to_receive.put_in_hands(A)
|
||||
to_chat(user, span_cult_italic("[cultist_to_receive] has died!"))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(!(cultist_to_receive.mind in cult_team.members))
|
||||
to_chat(user, span_cult_italic("[cultist_to_receive] is not a follower of the Geometer!"))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(!isturf(interacting_with.loc))
|
||||
to_chat(user, span_cult_italic("[interacting_with] must be on a surface in order to teleport it!"))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
to_chat(user, span_cult_italic("You ignite [interacting_with] with [src], turning it to ash, \
|
||||
but through the torch's flames you see that [interacting_with] has reached [cultist_to_receive]!"))
|
||||
user.log_message("teleported [interacting_with] to [cultist_to_receive] with [src].", LOG_GAME)
|
||||
cultist_to_receive.put_in_hands(interacting_with)
|
||||
charges--
|
||||
to_chat(user, "\The [src] now has [charges] charge\s.")
|
||||
if(charges == 0)
|
||||
to_chat(user, span_notice("[src] now has [charges] charge\s."))
|
||||
if(charges <= 0)
|
||||
qdel(src)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/melee/cultblade/halberd
|
||||
name = "bloody halberd"
|
||||
@@ -859,31 +859,33 @@ Striking a noncultist, however, will tear their flesh."}
|
||||
ADD_TRAIT(src, TRAIT_NODROP, CULT_TRAIT)
|
||||
|
||||
|
||||
/obj/item/blood_beam/afterattack(atom/A, mob/living/user, proximity_flag, clickparams)
|
||||
. = ..()
|
||||
/obj/item/blood_beam/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
return ranged_interact_with_atom(interacting_with, user, modifiers)
|
||||
|
||||
/obj/item/blood_beam/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(firing || charging)
|
||||
return
|
||||
if(ishuman(user))
|
||||
angle = get_angle(user, A)
|
||||
else
|
||||
qdel(src)
|
||||
return . | AFTERATTACK_PROCESSED_ITEM
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(!ishuman(user))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
angle = get_angle(user, interacting_with)
|
||||
charging = TRUE
|
||||
INVOKE_ASYNC(src, PROC_REF(charge), user)
|
||||
if(do_after(user, 9 SECONDS, target = user))
|
||||
firing = TRUE
|
||||
ADD_TRAIT(user, TRAIT_IMMOBILIZED, CULT_TRAIT)
|
||||
INVOKE_ASYNC(src, PROC_REF(pewpew), user, clickparams)
|
||||
var/params = list2params(modifiers)
|
||||
INVOKE_ASYNC(src, PROC_REF(pewpew), user, params)
|
||||
var/obj/structure/emergency_shield/cult/weak/N = new(user.loc)
|
||||
if(do_after(user, 9 SECONDS, target = user))
|
||||
user.Paralyze(40)
|
||||
to_chat(user, "<span class='cult italic'>You have exhausted the power of this spell!</span>")
|
||||
to_chat(user, span_cult_italic("You have exhausted the power of this spell!"))
|
||||
REMOVE_TRAIT(user, TRAIT_IMMOBILIZED, CULT_TRAIT)
|
||||
firing = FALSE
|
||||
if(N)
|
||||
qdel(N)
|
||||
qdel(src)
|
||||
charging = FALSE
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/blood_beam/proc/charge(mob/user)
|
||||
var/obj/O
|
||||
|
||||
@@ -230,7 +230,7 @@
|
||||
GLOB.reality_smash_track.add_tracked_mind(owner)
|
||||
|
||||
RegisterSignals(our_mob, list(COMSIG_MOB_BEFORE_SPELL_CAST, COMSIG_MOB_SPELL_ACTIVATED), PROC_REF(on_spell_cast))
|
||||
RegisterSignal(our_mob, COMSIG_MOB_ITEM_AFTERATTACK, PROC_REF(on_item_afterattack))
|
||||
RegisterSignal(our_mob, COMSIG_USER_ITEM_INTERACTION, PROC_REF(on_item_use))
|
||||
RegisterSignal(our_mob, COMSIG_MOB_LOGIN, PROC_REF(fix_influence_network))
|
||||
RegisterSignal(our_mob, COMSIG_LIVING_POST_FULLY_HEAL, PROC_REF(after_fully_healed))
|
||||
|
||||
@@ -245,7 +245,7 @@
|
||||
UnregisterSignal(our_mob, list(
|
||||
COMSIG_MOB_BEFORE_SPELL_CAST,
|
||||
COMSIG_MOB_SPELL_ACTIVATED,
|
||||
COMSIG_MOB_ITEM_AFTERATTACK,
|
||||
COMSIG_USER_ITEM_INTERACTION,
|
||||
COMSIG_MOB_LOGIN,
|
||||
COMSIG_LIVING_POST_FULLY_HEAL,
|
||||
))
|
||||
@@ -286,26 +286,25 @@
|
||||
return SPELL_CANCEL_CAST
|
||||
|
||||
/*
|
||||
* Signal proc for [COMSIG_MOB_ITEM_AFTERATTACK].
|
||||
* Signal proc for [COMSIG_USER_ITEM_INTERACTION].
|
||||
*
|
||||
* If a heretic is holding a pen in their main hand,
|
||||
* and have mansus grasp active in their offhand,
|
||||
* they're able to draw a transmutation rune.
|
||||
*/
|
||||
/datum/antagonist/heretic/proc/on_item_afterattack(mob/living/source, atom/target, obj/item/weapon, proximity_flag, click_parameters)
|
||||
/datum/antagonist/heretic/proc/on_item_use(mob/living/source, atom/target, obj/item/weapon, click_parameters)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!is_type_in_typecache(weapon, scribing_tools))
|
||||
return
|
||||
if(!isturf(target) || !isliving(source) || !proximity_flag)
|
||||
return
|
||||
return NONE
|
||||
if(!isturf(target) || !isliving(source))
|
||||
return NONE
|
||||
|
||||
var/obj/item/offhand = source.get_inactive_held_item()
|
||||
if(QDELETED(offhand) || !istype(offhand, /obj/item/melee/touch_attack/mansus_fist))
|
||||
return
|
||||
return NONE
|
||||
|
||||
try_draw_rune(source, target, additional_checks = CALLBACK(src, PROC_REF(check_mansus_grasp_offhand), source))
|
||||
return COMPONENT_CANCEL_ATTACK_CHAIN
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/**
|
||||
* Attempt to draw a rune on [target_turf].
|
||||
|
||||
@@ -45,20 +45,16 @@
|
||||
AddElement(/datum/element/heretic_focus)
|
||||
update_weight_class(WEIGHT_CLASS_NORMAL)
|
||||
|
||||
/obj/item/codex_cicatrix/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(!proximity_flag)
|
||||
return
|
||||
|
||||
/obj/item/codex_cicatrix/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
var/datum/antagonist/heretic/heretic_datum = IS_HERETIC(user)
|
||||
if(!heretic_datum)
|
||||
return
|
||||
|
||||
if(isopenturf(target))
|
||||
var/obj/effect/heretic_influence/influence = locate(/obj/effect/heretic_influence) in target
|
||||
return NONE
|
||||
if(isopenturf(interacting_with))
|
||||
var/obj/effect/heretic_influence/influence = locate(/obj/effect/heretic_influence) in interacting_with
|
||||
if(!influence?.drain_influence_with_codex(user, src))
|
||||
heretic_datum.try_draw_rune(user, target, drawing_time = 8 SECONDS)
|
||||
return TRUE
|
||||
heretic_datum.try_draw_rune(user, interacting_with, drawing_time = 8 SECONDS)
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
return NONE
|
||||
|
||||
/// Plays a little animation that shows the book opening and closing.
|
||||
/obj/item/codex_cicatrix/proc/open_animation()
|
||||
|
||||
@@ -24,14 +24,19 @@
|
||||
attack_verb_simple = list("attack", "slash", "stab", "slice", "tear", "lacerate", "rip", "dice", "rend")
|
||||
var/after_use_message = ""
|
||||
|
||||
/obj/item/melee/sickly_blade/attack(mob/living/M, mob/living/user)
|
||||
/obj/item/melee/sickly_blade/pre_attack(atom/A, mob/living/user, params)
|
||||
. = ..()
|
||||
if(.)
|
||||
return .
|
||||
if(!IS_HERETIC_OR_MONSTER(user))
|
||||
to_chat(user, span_danger("You feel a pulse of alien intellect lash out at your mind!"))
|
||||
var/mob/living/carbon/human/human_user = user
|
||||
human_user.AdjustParalyzed(5 SECONDS)
|
||||
user.AdjustParalyzed(5 SECONDS)
|
||||
return TRUE
|
||||
return .
|
||||
|
||||
return ..()
|
||||
/obj/item/melee/sickly_blade/afterattack(atom/target, mob/user, click_parameters)
|
||||
if(isliving(target))
|
||||
SEND_SIGNAL(user, COMSIG_HERETIC_BLADE_ATTACK, target, src)
|
||||
|
||||
/obj/item/melee/sickly_blade/attack_self(mob/user)
|
||||
var/turf/safe_turf = find_safe_turf(zlevels = z, extended_safety_checks = TRUE)
|
||||
@@ -45,15 +50,10 @@
|
||||
playsound(src, SFX_SHATTER, 70, TRUE) //copied from the code for smashing a glass sheet onto the ground to turn it into a shard
|
||||
qdel(src)
|
||||
|
||||
/obj/item/melee/sickly_blade/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(!isliving(target))
|
||||
return
|
||||
|
||||
if(proximity_flag)
|
||||
SEND_SIGNAL(user, COMSIG_HERETIC_BLADE_ATTACK, target, src)
|
||||
else
|
||||
SEND_SIGNAL(user, COMSIG_HERETIC_RANGED_BLADE_ATTACK, target, src)
|
||||
/obj/item/melee/sickly_blade/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(isliving(interacting_with))
|
||||
SEND_SIGNAL(user, COMSIG_HERETIC_RANGED_BLADE_ATTACK, interacting_with, src)
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
/obj/item/melee/sickly_blade/examine(mob/user)
|
||||
. = ..()
|
||||
|
||||
@@ -171,20 +171,17 @@
|
||||
playsound(drop_location(),'sound/items/eatfood.ogg', rand(10,50), TRUE)
|
||||
access += card.access
|
||||
|
||||
/obj/item/card/id/advanced/heretic/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(!proximity_flag || !IS_HERETIC(user))
|
||||
return
|
||||
/obj/item/card/id/advanced/heretic/interact_with_atom(atom/target, mob/living/user, list/modifiers)
|
||||
if(!IS_HERETIC(user))
|
||||
return NONE
|
||||
if(istype(target, /obj/effect/lock_portal))
|
||||
clear_portals()
|
||||
return
|
||||
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
if(!istype(target, /obj/machinery/door))
|
||||
return
|
||||
|
||||
return NONE
|
||||
var/reference_resolved = link?.resolve()
|
||||
if(reference_resolved == target)
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
if(reference_resolved)
|
||||
make_portal(user, reference_resolved, target)
|
||||
@@ -194,6 +191,7 @@
|
||||
else
|
||||
link = WEAKREF(target)
|
||||
balloon_alert(user, "link 1/2")
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/card/id/advanced/heretic/Destroy()
|
||||
QDEL_LIST_ASSOC(fused_ids)
|
||||
|
||||
@@ -41,24 +41,29 @@
|
||||
. += span_hypnophrase("Materializes a barrier upon any tile in sight, which only you can pass through. Lasts 8 seconds.")
|
||||
. += span_hypnophrase("It has <b>[uses]</b> uses left.")
|
||||
|
||||
/obj/item/heretic_labyrinth_handbook/afterattack(atom/target, mob/user, proximity_flag)
|
||||
. = ..()
|
||||
if(IS_HERETIC(user))
|
||||
var/turf/turf_target = get_turf(target)
|
||||
if(locate(barrier_type) in turf_target)
|
||||
user.balloon_alert(user, "already occupied!")
|
||||
return
|
||||
turf_target.visible_message(span_warning("A storm of paper materializes!"))
|
||||
new /obj/effect/temp_visual/paper_scatter(turf_target)
|
||||
playsound(turf_target, 'sound/magic/smoke.ogg', 30)
|
||||
new barrier_type(turf_target, user)
|
||||
uses--
|
||||
if(uses <= 0)
|
||||
to_chat(user, span_warning("[src] falls apart, turning into ash and dust!"))
|
||||
qdel(src)
|
||||
return
|
||||
var/mob/living/carbon/human/human_user = user
|
||||
to_chat(human_user, span_userdanger("Your mind burns as you stare deep into the book, a headache setting in like your brain is on fire!"))
|
||||
human_user.adjustOrganLoss(ORGAN_SLOT_BRAIN, 30, 190)
|
||||
human_user.add_mood_event("gates_of_mansus", /datum/mood_event/gates_of_mansus)
|
||||
human_user.dropItemToGround(src)
|
||||
/obj/item/heretic_labyrinth_handbook/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
return interact_with_atom(interacting_with, user, modifiers)
|
||||
|
||||
/obj/item/heretic_labyrinth_handbook/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!IS_HERETIC(user))
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/human_user = user
|
||||
to_chat(human_user, span_userdanger("Your mind burns as you stare deep into the book, a headache setting in like your brain is on fire!"))
|
||||
human_user.adjustOrganLoss(ORGAN_SLOT_BRAIN, 30, 190)
|
||||
human_user.add_mood_event("gates_of_mansus", /datum/mood_event/gates_of_mansus)
|
||||
human_user.dropItemToGround(src)
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
var/turf/turf_target = get_turf(interacting_with)
|
||||
if(locate(barrier_type) in turf_target)
|
||||
user.balloon_alert(user, "already occupied!")
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
turf_target.visible_message(span_warning("A storm of paper materializes!"))
|
||||
new /obj/effect/temp_visual/paper_scatter(turf_target)
|
||||
playsound(turf_target, 'sound/magic/smoke.ogg', 30)
|
||||
new barrier_type(turf_target, user)
|
||||
uses--
|
||||
if(uses <= 0)
|
||||
to_chat(user, span_warning("[src] falls apart, turning into ash and dust!"))
|
||||
qdel(src)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
@@ -45,21 +45,14 @@
|
||||
var/potion_string = span_info("\tThe " + initial(trap.name) + " - " + initial(trap.carver_tip))
|
||||
. += potion_string
|
||||
|
||||
/obj/item/melee/rune_carver/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(!proximity_flag)
|
||||
return
|
||||
|
||||
/obj/item/melee/rune_carver/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!IS_HERETIC_OR_MONSTER(user))
|
||||
return
|
||||
return NONE
|
||||
if(!isopenturf(interacting_with) || is_type_in_typecache(interacting_with, blacklisted_turfs))
|
||||
return NONE
|
||||
|
||||
if(!isopenturf(target))
|
||||
return
|
||||
|
||||
if(is_type_in_typecache(target, blacklisted_turfs))
|
||||
return
|
||||
|
||||
INVOKE_ASYNC(src, PROC_REF(try_carve_rune), target, user)
|
||||
INVOKE_ASYNC(src, PROC_REF(try_carve_rune), interacting_with, user)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/*
|
||||
* Begin trying to carve a rune. Go through a few checks, then call do_carve_rune if successful.
|
||||
|
||||
@@ -44,12 +44,11 @@
|
||||
spark_system.set_up(5, 0, src)
|
||||
spark_system.attach(src)
|
||||
|
||||
/obj/item/energy_katana/afterattack_secondary(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN)
|
||||
return
|
||||
if(!target.density)
|
||||
jaunt?.teleport(user, target)
|
||||
/obj/item/energy_katana/ranged_interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!interacting_with.density)
|
||||
jaunt?.teleport(user, interacting_with)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
return NONE
|
||||
|
||||
/obj/item/energy_katana/equipped(mob/user, slot, initial)
|
||||
. = ..()
|
||||
|
||||
@@ -47,15 +47,16 @@
|
||||
return
|
||||
detonation_area = objective.detonation_location
|
||||
|
||||
/obj/item/grenade/c4/ninja/afterattack(atom/movable/target, mob/ninja, flag)
|
||||
if(!IS_SPACE_NINJA(ninja))
|
||||
/obj/item/grenade/c4/ninja/plant_c4(atom/bomb_target, mob/living/user)
|
||||
if(!IS_SPACE_NINJA(user))
|
||||
say("Access denied.")
|
||||
return
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
if (!check_loc(ninja))
|
||||
return .
|
||||
detonator = WEAKREF(ninja)
|
||||
return . | ..()
|
||||
return FALSE
|
||||
if(!check_loc(user))
|
||||
return FALSE
|
||||
if(!..())
|
||||
return FALSE
|
||||
detonator = WEAKREF(user)
|
||||
return TRUE
|
||||
|
||||
/obj/item/grenade/c4/ninja/detonate(mob/living/lanced_by)
|
||||
if(!check_loc(detonator.resolve())) // if its moved, deactivate the c4
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
/obj/machinery/nuclearbomb/beer/attackby(obj/item/weapon, mob/user, params)
|
||||
if(weapon.is_refillable())
|
||||
weapon.afterattack(keg, user, TRUE) // redirect refillable containers to the keg, allowing them to be filled
|
||||
weapon.interact_with_atom(keg, user) // redirect refillable containers to the keg, allowing them to be filled
|
||||
return TRUE // pretend we handled the attack, too.
|
||||
|
||||
if(istype(weapon, /obj/item/nuke_core_container))
|
||||
|
||||
@@ -243,28 +243,24 @@
|
||||
objective_weakref = null
|
||||
return ..()
|
||||
|
||||
/obj/item/grenade/c4/es8/afterattack(atom/movable/target, mob/user, flag)
|
||||
if(!user.mind)
|
||||
return
|
||||
|
||||
/obj/item/grenade/c4/es8/plant_c4(atom/bomb_target, mob/living/user)
|
||||
if(!IS_TRAITOR(user))
|
||||
to_chat(user, span_warning("You can't seem to find a way to detonate the charge."))
|
||||
return
|
||||
return FALSE
|
||||
|
||||
var/datum/traitor_objective/locate_weakpoint/objective = objective_weakref.resolve()
|
||||
|
||||
if(!objective || objective.objective_state == OBJECTIVE_STATE_INACTIVE || objective.handler.owner != user.mind)
|
||||
to_chat(user, span_warning("You don't think it would be wise to use [src]."))
|
||||
return
|
||||
return FALSE
|
||||
|
||||
var/area/target_area = get_area(target)
|
||||
var/area/target_area = get_area(bomb_target)
|
||||
if (target_area.type != objective.weakpoint_area)
|
||||
to_chat(user, span_warning("[src] can only be detonated in [initial(objective.weakpoint_area.name)]."))
|
||||
return
|
||||
return FALSE
|
||||
|
||||
if(!isfloorturf(target) && !iswallturf(target))
|
||||
if(!isfloorturf(bomb_target) && !iswallturf(bomb_target))
|
||||
to_chat(user, span_warning("[src] can only be planted on a wall or the floor!"))
|
||||
return
|
||||
return FALSE
|
||||
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -277,28 +277,26 @@ GLOBAL_DATUM_INIT(steal_item_handler, /datum/objective_item_handler, new())
|
||||
. += span_notice("This device must be placed by <b>clicking on the [initial(target_object_type.name)]</b> with it.")
|
||||
. += span_notice("Remember, you may leave behind fingerprints or fibers on the device. Use <b>soap</b> or similar to scrub it clean to be safe!")
|
||||
|
||||
/obj/item/traitor_bug/afterattack(atom/movable/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(!target_object_type)
|
||||
return
|
||||
if(!user.Adjacent(target))
|
||||
return
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
/obj/item/traitor_bug/interact_with_atom(atom/movable/target, mob/living/user, list/modifiers)
|
||||
if(!target_object_type || !ismovable(target))
|
||||
return NONE
|
||||
|
||||
var/result = SEND_SIGNAL(src, COMSIG_TRAITOR_BUG_PRE_PLANTED_OBJECT, target)
|
||||
if(!(result & COMPONENT_FORCE_PLACEMENT))
|
||||
if(result & COMPONENT_FORCE_FAIL_PLACEMENT || !istype(target, target_object_type))
|
||||
balloon_alert(user, "you can't attach this onto here!")
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(!do_after(user, deploy_time, src, hidden = TRUE))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(planted_on)
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
forceMove(target)
|
||||
target.vis_contents += src
|
||||
vis_flags |= VIS_INHERIT_PLANE
|
||||
planted_on = target
|
||||
RegisterSignal(planted_on, COMSIG_QDELETING, PROC_REF(handle_planted_on_deletion))
|
||||
SEND_SIGNAL(src, COMSIG_TRAITOR_BUG_PLANTED_OBJECT, target)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/traitor_bug/proc/handle_planted_on_deletion()
|
||||
planted_on = null
|
||||
@@ -318,5 +316,5 @@ GLOBAL_DATUM_INIT(steal_item_handler, /datum/objective_item_handler, new())
|
||||
UnregisterSignal(planted_on, COMSIG_QDELETING)
|
||||
planted_on = null
|
||||
|
||||
/obj/item/traitor_bug/attackby_storage_insert(datum/storage, atom/storage_holder, mob/user)
|
||||
/obj/item/traitor_bug/storage_insert_on_interaction(datum/storage, atom/storage_holder, mob/user)
|
||||
return !istype(storage_holder, target_object_type)
|
||||
|
||||
@@ -431,43 +431,45 @@
|
||||
COMSIG_ITEM_MAGICALLY_CHARGED = PROC_REF(on_magic_charge),
|
||||
)
|
||||
|
||||
/obj/item/runic_vendor_scepter/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
/obj/item/runic_vendor_scepter/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
return interact_with_atom(interacting_with, user, modifiers)
|
||||
|
||||
/obj/item/runic_vendor_scepter/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(scepter_is_busy_recharging)
|
||||
user.balloon_alert(user, "busy!")
|
||||
return
|
||||
if(!check_allowed_items(target, not_inside = TRUE))
|
||||
return
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
var/turf/afterattack_turf = get_turf(target)
|
||||
if(istype(target, /obj/machinery/vending/runic_vendor))
|
||||
var/obj/machinery/vending/runic_vendor/runic_explosion_target = target
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(!check_allowed_items(interacting_with, not_inside = TRUE))
|
||||
return NONE
|
||||
if(istype(interacting_with, /obj/machinery/vending/runic_vendor))
|
||||
var/obj/machinery/vending/runic_vendor/runic_explosion_target = interacting_with
|
||||
runic_explosion_target.runic_explosion()
|
||||
return
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
var/turf/afterattack_turf = get_turf(interacting_with)
|
||||
var/obj/machinery/vending/runic_vendor/vendor_on_turf = locate() in afterattack_turf
|
||||
if(vendor_on_turf)
|
||||
vendor_on_turf.runic_explosion()
|
||||
return
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
if(!summon_vendor_charges)
|
||||
user.balloon_alert(user, "no charges!")
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(get_dist(afterattack_turf,src) > max_summon_range)
|
||||
user.balloon_alert(user, "too far!")
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(get_turf(src) == afterattack_turf)
|
||||
user.balloon_alert(user, "too close!")
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(scepter_is_busy_summoning)
|
||||
user.balloon_alert(user, "already summoning!")
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(afterattack_turf.is_blocked_turf(TRUE))
|
||||
user.balloon_alert(user, "blocked!")
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(summoning_time)
|
||||
scepter_is_busy_summoning = TRUE
|
||||
user.balloon_alert(user, "summoning...")
|
||||
if(!do_after(user, summoning_time, target = target))
|
||||
if(!do_after(user, summoning_time, target = interacting_with))
|
||||
scepter_is_busy_summoning = FALSE
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
scepter_is_busy_summoning = FALSE
|
||||
if(summon_vendor_charges)
|
||||
playsound(src,'sound/weapons/resonator_fire.ogg',50,TRUE)
|
||||
@@ -475,8 +477,8 @@
|
||||
new /obj/machinery/vending/runic_vendor(afterattack_turf)
|
||||
summon_vendor_charges--
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
return
|
||||
return ..()
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
return NONE
|
||||
|
||||
/obj/item/runic_vendor_scepter/attack_self(mob/user, modifiers)
|
||||
. = ..()
|
||||
@@ -489,17 +491,20 @@
|
||||
scepter_is_busy_recharging = FALSE
|
||||
summon_vendor_charges = RUNIC_SCEPTER_MAX_CHARGES
|
||||
|
||||
/obj/item/runic_vendor_scepter/afterattack_secondary(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
var/turf/afterattack_secondary_turf = get_turf(target)
|
||||
/obj/item/runic_vendor_scepter/ranged_interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
return interact_with_atom_secondary(interacting_with, user, modifiers)
|
||||
|
||||
/obj/item/runic_vendor_scepter/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
var/turf/afterattack_secondary_turf = get_turf(interacting_with)
|
||||
var/obj/machinery/vending/runic_vendor/vendor_on_turf = locate() in afterattack_secondary_turf
|
||||
if(istype(target, /obj/machinery/vending/runic_vendor))
|
||||
var/obj/machinery/vending/runic_vendor/vendor_being_throw = target
|
||||
vendor_being_throw.throw_at(get_edge_target_turf(target, get_cardinal_dir(src, target)), 4, 20, user)
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
if(istype(interacting_with, /obj/machinery/vending/runic_vendor))
|
||||
var/obj/machinery/vending/runic_vendor/vendor_being_throw = interacting_with
|
||||
vendor_being_throw.throw_at(get_edge_target_turf(interacting_with, get_cardinal_dir(src, interacting_with)), 4, 20, user)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
if(vendor_on_turf)
|
||||
vendor_on_turf.throw_at(get_edge_target_turf(target, get_cardinal_dir(src, target)), 4, 20, user)
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
vendor_on_turf.throw_at(get_edge_target_turf(interacting_with, get_cardinal_dir(src, interacting_with)), 4, 20, user)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
/obj/item/runic_vendor_scepter/proc/on_magic_charge(datum/source, datum/action/cooldown/spell/charge/spell, mob/living/caster)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
whatever spark it once held long extinguished."
|
||||
|
||||
///signal called whenever a soulstone is smacked by a bible
|
||||
/obj/item/soulstone/proc/on_bible_smacked(datum/source, mob/living/user, direction)
|
||||
/obj/item/soulstone/proc/on_bible_smacked(datum/source, mob/living/user, ...)
|
||||
SIGNAL_HANDLER
|
||||
INVOKE_ASYNC(src, PROC_REF(attempt_exorcism), user)
|
||||
|
||||
|
||||
@@ -55,28 +55,21 @@
|
||||
var/datum/status_effect/teleport_flux/perma/permaflux = user.has_status_effect(/datum/status_effect/teleport_flux/perma)
|
||||
permaflux?.delayed_remove(src)
|
||||
|
||||
/obj/item/teleport_rod/afterattack(atom/target, mob/living/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(!isliving(user))
|
||||
return
|
||||
if(proximity_flag) // assuming you don't want to teleport 1 tile away
|
||||
return
|
||||
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
|
||||
/obj/item/teleport_rod/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
. = ITEM_INTERACT_BLOCKING
|
||||
var/turf/start_turf = get_turf(user)
|
||||
var/turf/target_turf = get_turf(target)
|
||||
var/turf/target_turf = get_turf(interacting_with)
|
||||
if(get_dist(start_turf, target_turf) > max_tp_range)
|
||||
user.balloon_alert(user, "too far!")
|
||||
return
|
||||
return .
|
||||
|
||||
if(!(target_turf in view(user, user.client?.view || world.view)))
|
||||
user.balloon_alert(user, "out of view!")
|
||||
return
|
||||
return .
|
||||
|
||||
if(target_turf.is_blocked_turf(exclude_mobs = TRUE, source_atom = user))
|
||||
user.balloon_alert(user, "obstructed!")
|
||||
return
|
||||
return .
|
||||
|
||||
var/tp_result = do_teleport(
|
||||
teleatom = user,
|
||||
@@ -88,7 +81,9 @@
|
||||
|
||||
if(!tp_result)
|
||||
user.balloon_alert(user, "teleport failed!")
|
||||
return
|
||||
return .
|
||||
|
||||
. = ITEM_INTERACT_SUCCESS
|
||||
|
||||
var/sound/teleport_sound = sound('sound/magic/summonitems_generic.ogg')
|
||||
teleport_sound.pitch = 0.5
|
||||
@@ -101,7 +96,7 @@
|
||||
user.changeNext_move(CLICK_CD_SLOW * 1.2)
|
||||
|
||||
if(!apply_debuffs)
|
||||
return
|
||||
return .
|
||||
|
||||
// Teleporting leaves some of your reagents behind!
|
||||
// (Primarily a way to prevent cheese with damage healing chem mixes,
|
||||
@@ -110,13 +105,14 @@
|
||||
user.reagents?.remove_all(0.33, relative = TRUE)
|
||||
user_stomach?.reagents?.remove_all(0.33, relative = TRUE)
|
||||
if(user.has_status_effect(/datum/status_effect/teleport_flux/perma))
|
||||
return
|
||||
return .
|
||||
|
||||
if(user.has_status_effect(/datum/status_effect/teleport_flux))
|
||||
// The status effect handles the damage, but we'll add a special pop up for rod usage specifically
|
||||
user.balloon_alert(user, "too soon!")
|
||||
|
||||
user.apply_status_effect(/datum/status_effect/teleport_flux)
|
||||
return .
|
||||
|
||||
/// Temp visual displayed on both sides of a teleport rod teleport
|
||||
/obj/effect/temp_visual/teleport_flux
|
||||
|
||||
+15
-15
@@ -310,12 +310,11 @@ Point with the chisel at the target to choose what to sculpt or hit block to cho
|
||||
Hit block again to start sculpting.
|
||||
Moving interrupts
|
||||
*/
|
||||
/obj/item/chisel/pre_attack(atom/target, mob/living/user, params)
|
||||
. = ..()
|
||||
/obj/item/chisel/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(sculpting)
|
||||
return TRUE
|
||||
if(istype(target, /obj/structure/carving_block))
|
||||
var/obj/structure/carving_block/sculpt_block = target
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(istype(interacting_with, /obj/structure/carving_block))
|
||||
var/obj/structure/carving_block/sculpt_block = interacting_with
|
||||
|
||||
if(sculpt_block.completion) // someone already started sculpting this so just finish
|
||||
set_block(sculpt_block, user, silent = TRUE)
|
||||
@@ -326,19 +325,20 @@ Moving interrupts
|
||||
set_block(sculpt_block, user)
|
||||
else if(sculpt_block == prepared_block)
|
||||
show_generic_statues_prompt(user)
|
||||
return TRUE
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
else if(prepared_block) //We're aiming at something next to us with block prepared
|
||||
prepared_block.set_target(target, user)
|
||||
return TRUE
|
||||
prepared_block.set_target(interacting_with, user)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
return NONE
|
||||
|
||||
// We aim at something distant.
|
||||
/obj/item/chisel/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
|
||||
if (!sculpting && prepared_block && ismovable(target) && prepared_block.completion == 0)
|
||||
prepared_block.set_target(target,user)
|
||||
|
||||
return . | AFTERATTACK_PROCESSED_ITEM
|
||||
/obj/item/chisel/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if (!sculpting && prepared_block && ismovable(interacting_with) && prepared_block.completion == 0)
|
||||
prepared_block.set_target(interacting_with, user)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
/// Starts or continues the sculpting action on the carving block material
|
||||
/obj/item/chisel/proc/start_sculpting(mob/living/user)
|
||||
|
||||
+14
-14
@@ -5,29 +5,27 @@
|
||||
icon_state = "hypernoblium_crystal"
|
||||
var/uses = 1
|
||||
|
||||
/obj/item/hypernoblium_crystal/afterattack(obj/target_object, mob/user, proximity)
|
||||
. = ..()
|
||||
if(!proximity)
|
||||
return
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
var/obj/machinery/portable_atmospherics/atmos_device = target_object
|
||||
/obj/item/hypernoblium_crystal/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
var/obj/machinery/portable_atmospherics/atmos_device = interacting_with
|
||||
var/obj/item/clothing/worn_item = interacting_with
|
||||
if(!istype(worn_item) && !istype(atmos_device))
|
||||
to_chat(user, span_warning("The crystal can only be used on clothing and portable atmospheric devices!"))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
if(istype(atmos_device))
|
||||
if(atmos_device.nob_crystal_inserted)
|
||||
to_chat(user, span_warning("[atmos_device] already has a hypernoblium crystal inserted in it!"))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
atmos_device.nob_crystal_inserted = TRUE
|
||||
to_chat(user, span_notice("You insert the [src] into [atmos_device]."))
|
||||
var/obj/item/clothing/worn_item = target_object
|
||||
if(!istype(worn_item) && !istype(atmos_device))
|
||||
to_chat(user, span_warning("The crystal can only be used on clothing and portable atmospheric devices!"))
|
||||
return
|
||||
|
||||
if(istype(worn_item))
|
||||
if(istype(worn_item, /obj/item/clothing/suit/space))
|
||||
to_chat(user, span_warning("The [worn_item] is already pressure-resistant!"))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(worn_item.min_cold_protection_temperature == SPACE_SUIT_MIN_TEMP_PROTECT && worn_item.clothing_flags & STOPSPRESSUREDAMAGE)
|
||||
to_chat(user, span_warning("[worn_item] is already pressure-resistant!"))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
to_chat(user, span_notice("You see how the [worn_item] changes color, it's now pressure proof."))
|
||||
worn_item.name = "pressure-resistant [worn_item.name]"
|
||||
worn_item.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
|
||||
@@ -35,6 +33,8 @@
|
||||
worn_item.min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT
|
||||
worn_item.cold_protection = worn_item.body_parts_covered
|
||||
worn_item.clothing_flags |= STOPSPRESSUREDAMAGE
|
||||
|
||||
uses--
|
||||
if(!uses)
|
||||
if(uses <= 0)
|
||||
qdel(src)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
@@ -173,31 +173,37 @@
|
||||
user.swap_hand(user.get_held_index_of_item(src))
|
||||
playsound(src, 'sound/items/basketball_bounce.ogg', 75, FALSE)
|
||||
|
||||
/obj/item/toy/basketball/afterattack(atom/target, mob/living/user)
|
||||
. = ..()
|
||||
if(!user.combat_mode)
|
||||
user.throw_item(target)
|
||||
/obj/item/toy/basketball/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
return interact_with_atom(interacting_with, user, modifiers)
|
||||
|
||||
/obj/item/toy/basketball/afterattack_secondary(atom/aim_target, mob/living/baller, proximity_flag, click_parameters)
|
||||
// dunking negates shooting
|
||||
if(istype(aim_target, /obj/structure/hoop) && baller.Adjacent(aim_target))
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
/obj/item/toy/basketball/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(user.combat_mode)
|
||||
user.throw_item(interacting_with)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
return NONE
|
||||
|
||||
/obj/item/toy/basketball/ranged_interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
return interact_with_atom_secondary(interacting_with, user, modifiers)
|
||||
|
||||
/obj/item/toy/basketball/interact_with_atom_secondary(atom/interacting_with, mob/living/baller, list/modifiers)
|
||||
if(istype(interacting_with, /obj/structure/hoop) && baller.Adjacent(interacting_with))
|
||||
return NONE // Do hoop stuff
|
||||
|
||||
baller.adjustStaminaLoss(STAMINA_COST_SHOOTING)
|
||||
|
||||
var/dunk_dir = get_dir(baller, aim_target)
|
||||
var/dunk_dir = get_dir(baller, interacting_with)
|
||||
var/dunk_pixel_y = dunk_dir & SOUTH ? -16 : 16
|
||||
var/dunk_pixel_x = dunk_dir & EAST && 16 || dunk_dir & WEST && -16 || 0
|
||||
|
||||
animate(baller, pixel_x = dunk_pixel_x, pixel_y = dunk_pixel_y, time = 5, easing = BOUNCE_EASING|EASE_IN|EASE_OUT)
|
||||
if(do_after(baller, 0.5 SECONDS))
|
||||
pass_flags |= PASSMOB
|
||||
baller.throw_item(aim_target)
|
||||
baller.throw_item(interacting_with)
|
||||
animate(baller, pixel_x = 0, pixel_y = 0, time = 3)
|
||||
return SECONDARY_ATTACK_CONTINUE_CHAIN
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
animate(baller, pixel_x = 0, pixel_y = 0, time = 3)
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
/obj/item/toy/basketball/throw_impact(mob/living/carbon/target, datum/thrownthing/throwingdatum)
|
||||
playsound(src, 'sound/items/basketball_bounce.ogg', 75, FALSE)
|
||||
|
||||
@@ -58,17 +58,16 @@
|
||||
icon_state = "[choice]"
|
||||
playsound(src, 'sound/machines/click.ogg', 40, TRUE)
|
||||
|
||||
/obj/item/universal_scanner/afterattack(obj/object, mob/user, proximity)
|
||||
. = ..()
|
||||
if(!istype(object) || !proximity)
|
||||
return
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
/obj/item/universal_scanner/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!isobj(interacting_with))
|
||||
return NONE
|
||||
if(scanning_mode == SCAN_EXPORTS)
|
||||
export_scan(object, user)
|
||||
return .
|
||||
export_scan(interacting_with, user)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
if(scanning_mode == SCAN_PRICE_TAG)
|
||||
price_tag(target = object, user = user)
|
||||
return .
|
||||
price_tag(interacting_with, user)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
return NONE
|
||||
|
||||
/obj/item/universal_scanner/attackby(obj/item/attacking_item, mob/user, params)
|
||||
. = ..()
|
||||
|
||||
@@ -43,25 +43,24 @@
|
||||
. += span_red("<b>Left click</b> will stealthily scan a target up to [scan_range] meters away and upload their getup as a custom outfit for you to use.")
|
||||
. += span_red("<b>Right click</b> will do the same, but instantly equip the outfit you obtain.")
|
||||
|
||||
/obj/item/chameleon_scanner/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(scan_target(target, user))
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
return .
|
||||
/obj/item/chameleon_scanner/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
return scan_target(interacting_with, user) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_BLOCKING
|
||||
|
||||
/obj/item/chameleon_scanner/afterattack_secondary(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN)
|
||||
return .
|
||||
/obj/item/chameleon_scanner/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
return interact_with_atom(interacting_with, user, modifiers)
|
||||
|
||||
var/list/scanned_outfit = scan_target(target, user)
|
||||
/obj/item/chameleon_scanner/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
var/list/scanned_outfit = scan_target(interacting_with, user)
|
||||
if(length(scanned_outfit))
|
||||
var/datum/outfit/empty_outfit = new()
|
||||
var/datum/action/chameleon_outfit/outfit_action = locate() in user.actions
|
||||
outfit_action?.apply_outfit(empty_outfit, scanned_outfit.Copy())
|
||||
qdel(empty_outfit)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
return SECONDARY_ATTACK_CONTINUE_CHAIN // no normal afterattack
|
||||
/obj/item/chameleon_scanner/ranged_interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
return interact_with_atom_secondary(interacting_with, user, modifiers)
|
||||
|
||||
/**
|
||||
* Attempts to scan a human's outfit
|
||||
|
||||
@@ -39,18 +39,20 @@
|
||||
icon = 'icons/obj/clothing/gloves.dmi'
|
||||
icon_state = "sprayoncan"
|
||||
|
||||
/obj/item/toy/sprayoncan/afterattack(atom/target, mob/living/carbon/user, proximity)
|
||||
if(iscarbon(target) && proximity)
|
||||
var/mob/living/carbon/C = target
|
||||
var/mob/living/carbon/U = user
|
||||
var/success = C.equip_to_slot_if_possible(new /obj/item/clothing/gloves/color/yellow/sprayon, ITEM_SLOT_GLOVES, qdel_on_fail = TRUE, disable_warning = TRUE)
|
||||
if(success)
|
||||
if(C == user)
|
||||
C.visible_message(span_notice("[U] sprays their hands with glittery rubber!"))
|
||||
else
|
||||
C.visible_message(span_warning("[U] sprays glittery rubber on the hands of [C]!"))
|
||||
/obj/item/toy/sprayoncan/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!iscarbon(interacting_with))
|
||||
return NONE
|
||||
var/mob/living/carbon/C = interacting_with
|
||||
var/mob/living/carbon/U = user
|
||||
var/success = C.equip_to_slot_if_possible(new /obj/item/clothing/gloves/color/yellow/sprayon, ITEM_SLOT_GLOVES, qdel_on_fail = TRUE, disable_warning = TRUE)
|
||||
if(success)
|
||||
if(C == user)
|
||||
C.visible_message(span_notice("[U] sprays their hands with glittery rubber!"))
|
||||
else
|
||||
C.visible_message(span_warning("The rubber fails to stick to [C]'s hands!"))
|
||||
C.visible_message(span_warning("[U] sprays glittery rubber on the hands of [C]!"))
|
||||
else
|
||||
C.visible_message(span_warning("The rubber fails to stick to [C]'s hands!"))
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/clothing/gloves/color/yellow/sprayon
|
||||
desc = "How're you gonna get 'em off, nerd?"
|
||||
|
||||
@@ -60,20 +60,22 @@
|
||||
add_atom_colour(newcolor, FIXED_COLOUR_PRIORITY)
|
||||
update_appearance()
|
||||
|
||||
/obj/item/clothing/head/wig/afterattack(mob/living/carbon/human/target, mob/user)
|
||||
. = ..()
|
||||
if(!istype(target))
|
||||
return
|
||||
/obj/item/clothing/head/wig/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
return interact_with_atom(interacting_with, user, modifiers)
|
||||
|
||||
/obj/item/clothing/head/wig/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!ishuman(interacting_with) || interacting_with == user)
|
||||
return NONE
|
||||
var/mob/living/carbon/human/target = interacting_with
|
||||
if(target.head)
|
||||
var/obj/item/clothing/head = target.head
|
||||
if((head.flags_inv & HIDEHAIR) && !istype(head, /obj/item/clothing/head/wig))
|
||||
to_chat(user, span_warning("You can't get a good look at [target.p_their()] hair!"))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
var/obj/item/bodypart/head/noggin = target.get_bodypart(BODY_ZONE_HEAD)
|
||||
if(!noggin)
|
||||
to_chat(user, span_warning("[target.p_They()] have no head!"))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
var/selected_hairstyle = null
|
||||
var/selected_hairstyle_color = null
|
||||
@@ -90,6 +92,7 @@
|
||||
add_atom_colour(selected_hairstyle_color, FIXED_COLOUR_PRIORITY)
|
||||
hairstyle = selected_hairstyle
|
||||
update_appearance()
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/clothing/head/wig/random/Initialize(mapload)
|
||||
hairstyle = pick(SSaccessories.hairstyles_list - "Bald") //Don't want invisible wig
|
||||
|
||||
@@ -476,25 +476,21 @@
|
||||
selling = !selling
|
||||
to_chat(user, span_notice("[src] has been set to [selling ? "'Sell'" : "'Get Price'"] mode."))
|
||||
|
||||
/obj/item/clothing/neck/necklace/dope/merchant/afterattack(obj/item/I, mob/user, proximity)
|
||||
. = ..()
|
||||
if(!proximity)
|
||||
return
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
var/datum/export_report/ex = export_item_and_contents(I, delete_unsold = selling, dry_run = !selling)
|
||||
/obj/item/clothing/neck/necklace/dope/merchant/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
var/datum/export_report/ex = export_item_and_contents(interacting_with, delete_unsold = selling, dry_run = !selling)
|
||||
var/price = 0
|
||||
for(var/x in ex.total_amount)
|
||||
price += ex.total_value[x]
|
||||
|
||||
if(price)
|
||||
var/true_price = round(price*profit_scaling)
|
||||
to_chat(user, span_notice("[selling ? "Sold" : "Getting the price of"] [I], value: <b>[true_price]</b> credits[I.contents.len ? " (exportable contents included)" : ""].[profit_scaling < 1 && selling ? "<b>[round(price-true_price)]</b> credit\s taken as processing fee\s." : ""]"))
|
||||
to_chat(user, span_notice("[selling ? "Sold" : "Getting the price of"] [interacting_with], value: <b>[true_price]</b> credits[interacting_with.contents.len ? " (exportable contents included)" : ""].[profit_scaling < 1 && selling ? "<b>[round(price-true_price)]</b> credit\s taken as processing fee\s." : ""]"))
|
||||
if(selling)
|
||||
new /obj/item/holochip(get_turf(user), true_price)
|
||||
else
|
||||
to_chat(user, span_warning("There is no export value for [I] or any items within it."))
|
||||
to_chat(user, span_warning("There is no export value for [interacting_with] or any items within it."))
|
||||
|
||||
return .
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
/obj/item/clothing/neck/beads
|
||||
name = "plastic bead necklace"
|
||||
|
||||
@@ -8,12 +8,11 @@
|
||||
inhand_icon_state = ""
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
|
||||
/obj/item/evidencebag/afterattack(obj/item/I, mob/user,proximity)
|
||||
. = ..()
|
||||
if(!proximity || loc == I)
|
||||
return
|
||||
evidencebagEquip(I, user)
|
||||
return . | AFTERATTACK_PROCESSED_ITEM
|
||||
/obj/item/evidencebag/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(interacting_with == loc)
|
||||
return NONE
|
||||
evidencebagEquip(interacting_with, user)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/evidencebag/attackby(obj/item/I, mob/user, params)
|
||||
if(evidencebagEquip(I, user))
|
||||
|
||||
@@ -74,14 +74,16 @@
|
||||
// Clear the logs
|
||||
log = list()
|
||||
|
||||
/obj/item/detective_scanner/pre_attack_secondary(atom/A, mob/user, params)
|
||||
safe_scan(user, atom_to_scan = A)
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
/obj/item/detective_scanner/storage_insert_on_interaction(datum/storage, atom/storage_holder, mob/living/user)
|
||||
return !user.combat_mode
|
||||
|
||||
/obj/item/detective_scanner/afterattack(atom/A, mob/user, params)
|
||||
. = ..()
|
||||
safe_scan(user, atom_to_scan = A)
|
||||
return . | AFTERATTACK_PROCESSED_ITEM
|
||||
/obj/item/detective_scanner/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
safe_scan(user, interacting_with)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/detective_scanner/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
safe_scan(user, interacting_with)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/**
|
||||
* safe_scan - a wrapper proc for scan()
|
||||
|
||||
@@ -89,16 +89,12 @@
|
||||
/**
|
||||
* Provides feedback when an item isn't related to an experiment, and has fully passed the attack chain
|
||||
*/
|
||||
/datum/component/experiment_handler/proc/ignored_handheld_experiment_attempt(datum/source, atom/target, mob/user, proximity_flag, params)
|
||||
/datum/component/experiment_handler/proc/ignored_handheld_experiment_attempt(datum/source, atom/target, mob/user, params)
|
||||
SIGNAL_HANDLER
|
||||
if (!proximity_flag)
|
||||
if ((isnull(selected_experiment) && !(config_flags & EXPERIMENT_CONFIG_ALWAYS_ACTIVE)) || (config_flags & EXPERIMENT_CONFIG_SILENT_FAIL))
|
||||
return
|
||||
. |= COMPONENT_AFTERATTACK_PROCESSED_ITEM
|
||||
if ((selected_experiment == null && !(config_flags & EXPERIMENT_CONFIG_ALWAYS_ACTIVE)) || config_flags & EXPERIMENT_CONFIG_SILENT_FAIL)
|
||||
return .
|
||||
playsound(user, 'sound/machines/buzz-sigh.ogg', 25)
|
||||
to_chat(user, span_notice("[target] is not related to your currently selected experiment."))
|
||||
return .
|
||||
|
||||
/**
|
||||
* Checks that an experiment can be run using the provided target, used for preventing the cancellation of the attack chain inappropriately
|
||||
|
||||
@@ -167,19 +167,18 @@ GLOBAL_LIST_INIT(adventure_loot_generator_index,generate_generator_index())
|
||||
/obj/item/firelance/get_cell()
|
||||
return cell
|
||||
|
||||
/obj/item/firelance/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
if(!HAS_TRAIT(src,TRAIT_WIELDED))
|
||||
to_chat(user,span_notice("You need to wield [src] in two hands before you can fire it."))
|
||||
return
|
||||
/obj/item/firelance/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
. = ITEM_INTERACT_BLOCKING
|
||||
if(!HAS_TRAIT(src, TRAIT_WIELDED))
|
||||
to_chat(user, span_notice("You need to wield [src] in two hands before you can fire it."))
|
||||
return .
|
||||
if(LAZYACCESS(user.do_afters, "firelance"))
|
||||
return
|
||||
return .
|
||||
if(!cell.use(0.2 * STANDARD_CELL_CHARGE))
|
||||
to_chat(user,span_warning("[src] battery ran dry!"))
|
||||
return
|
||||
to_chat(user,span_warning("[src]'s battery ran dry!"))
|
||||
return .
|
||||
ADD_TRAIT(user, TRAIT_IMMOBILIZED, REF(src))
|
||||
to_chat(user,span_notice("You begin to charge [src]"))
|
||||
to_chat(user,span_notice("You begin to charge [src]..."))
|
||||
inhand_icon_state = "firelance_charging"
|
||||
user.update_held_items()
|
||||
if(do_after(user,windup_time,interaction_key="firelance",extra_checks = CALLBACK(src, PROC_REF(windup_checks))))
|
||||
@@ -189,9 +188,11 @@ GLOBAL_LIST_INIT(adventure_loot_generator_index,generate_generator_index())
|
||||
for(var/turf/turf_to_melt in get_line(start_turf,last_turf))
|
||||
if(turf_to_melt.density)
|
||||
turf_to_melt.Melt()
|
||||
. = ITEM_INTERACT_SUCCESS
|
||||
inhand_icon_state = initial(inhand_icon_state)
|
||||
user.update_held_items()
|
||||
REMOVE_TRAIT(user, TRAIT_IMMOBILIZED, REF(src))
|
||||
return .
|
||||
|
||||
/// Additional windup checks
|
||||
/obj/item/firelance/proc/windup_checks()
|
||||
|
||||
@@ -78,31 +78,29 @@
|
||||
return CONTEXTUAL_SCREENTIP_SET
|
||||
return NONE
|
||||
|
||||
/obj/item/fish_analyzer/afterattack(atom/target, mob/user, proximity)
|
||||
. = ..()
|
||||
if(!proximity || !user.can_read(src) || user.is_blind())
|
||||
return
|
||||
/obj/item/fish_analyzer/interact_with_atom(atom/target, mob/living/user, list/modifiers)
|
||||
if(!isfish(target) && !isaquarium(target))
|
||||
return NONE
|
||||
if(!user.can_read(src) || user.is_blind())
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
if(isfish(target))
|
||||
balloon_alert(user, "analyzing stats")
|
||||
|
||||
user.visible_message(span_notice("[user] analyzes [target]."), span_notice("You analyze [target]."))
|
||||
analyze_status(target, user)
|
||||
else if(istype(target, /obj/structure/aquarium))
|
||||
scan_aquarium(target, user)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
|
||||
/obj/item/fish_analyzer/afterattack_secondary(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
if(!isfish(target))
|
||||
return
|
||||
|
||||
if(!proximity_flag || !user.can_read(src) || user.is_blind())
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
/obj/item/fish_analyzer/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!isfish(interacting_with))
|
||||
return NONE
|
||||
if(!user.can_read(src) || user.is_blind())
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
balloon_alert(user, "analyzing traits")
|
||||
|
||||
analyze_traits(target, user)
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
analyze_traits(interacting_with, user)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
///Instantiates the radial menu, populates the list of choices, shows it and register signals on the aquarium.
|
||||
/obj/item/fish_analyzer/proc/scan_aquarium(obj/structure/aquarium/aquarium, mob/user)
|
||||
|
||||
@@ -145,16 +145,6 @@
|
||||
. = ..()
|
||||
ui_interact(user)
|
||||
|
||||
/obj/item/fishing_rod/pre_attack(atom/targeted_atom, mob/living/user, params)
|
||||
. = ..()
|
||||
/// Reel in if able
|
||||
if(currently_hooked)
|
||||
reel(user)
|
||||
return TRUE
|
||||
if(!hook)
|
||||
balloon_alert(user, "install a hook first!")
|
||||
SEND_SIGNAL(targeted_atom, COMSIG_PRE_FISHING)
|
||||
|
||||
/// Generates the fishing line visual from the current user to the target and updates inhands
|
||||
/obj/item/fishing_rod/proc/create_fishing_line(atom/movable/target, target_py = null)
|
||||
if(!display_fishing_line)
|
||||
@@ -205,22 +195,26 @@
|
||||
qdel(source)
|
||||
return BEAM_CANCEL_DRAW
|
||||
|
||||
/obj/item/fishing_rod/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
/obj/item/fishing_rod/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
return ranged_interact_with_atom(interacting_with, user, modifiers)
|
||||
|
||||
/// Reel in if able
|
||||
/obj/item/fishing_rod/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!hook)
|
||||
balloon_alert(user, "install a hook first!")
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
// Reel in if able
|
||||
if(currently_hooked)
|
||||
reel(user)
|
||||
return .
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
cast_line(target, user, proximity_flag)
|
||||
SEND_SIGNAL(interacting_with, COMSIG_PRE_FISHING)
|
||||
cast_line(interacting_with, user)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
return .
|
||||
|
||||
///Called by afterattack(). If the line to whatever that is is clear and we're not already busy, try fishing in it
|
||||
/obj/item/fishing_rod/proc/cast_line(atom/target, mob/user, proximity_flag)
|
||||
if(casting || currently_hooked || proximity_flag)
|
||||
/// If the line to whatever that is is clear and we're not already busy, try fishing in it
|
||||
/obj/item/fishing_rod/proc/cast_line(atom/target, mob/user)
|
||||
if(casting || currently_hooked)
|
||||
return
|
||||
if(!hook)
|
||||
balloon_alert(user, "install a hook first!")
|
||||
@@ -230,8 +224,6 @@
|
||||
return
|
||||
if(!COOLDOWN_FINISHED(src, casting_cd))
|
||||
return
|
||||
/// Annoyingly pre attack is only called in melee
|
||||
SEND_SIGNAL(target, COMSIG_PRE_FISHING)
|
||||
casting = TRUE
|
||||
var/obj/projectile/fishing_cast/cast_projectile = new(get_turf(src))
|
||||
cast_projectile.range = cast_range
|
||||
|
||||
@@ -36,40 +36,33 @@
|
||||
user.balloon_alert(user, "[activated ? "activated" : "deactivated"]")
|
||||
return TRUE
|
||||
|
||||
/obj/item/bee_smoker/afterattack(atom/attacked_atom, mob/living/user, proximity)
|
||||
. = ..()
|
||||
|
||||
if(!proximity)
|
||||
return
|
||||
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
|
||||
/obj/item/bee_smoker/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!activated)
|
||||
user.balloon_alert(user, "not activated!")
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
if(current_herb_fuel < single_use_cost)
|
||||
user.balloon_alert(user, "not enough fuel!")
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
current_herb_fuel -= single_use_cost
|
||||
playsound(src, 'sound/effects/spray2.ogg', 100, TRUE)
|
||||
var/turf/target_turf = get_turf(attacked_atom)
|
||||
var/turf/target_turf = get_turf(interacting_with)
|
||||
new /obj/effect/temp_visual/mook_dust(target_turf)
|
||||
|
||||
for(var/mob/living/basic/bee/friend in target_turf)
|
||||
if(friend.flags_1 & HOLOGRAM_1)
|
||||
continue
|
||||
friend.befriend(user)
|
||||
|
||||
if(!istype(attacked_atom, /obj/structure/beebox))
|
||||
return
|
||||
if(!istype(interacting_with, /obj/structure/beebox))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
var/obj/structure/beebox/hive = attacked_atom
|
||||
var/obj/structure/beebox/hive = interacting_with
|
||||
for(var/mob/living/bee as anything in hive.bees)
|
||||
if(bee.flags_1 & HOLOGRAM_1)
|
||||
continue
|
||||
bee.befriend(user)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/bee_smoker/attackby(obj/item/herb, mob/living/carbon/human/user, list/modifiers)
|
||||
. = ..()
|
||||
|
||||
@@ -76,24 +76,9 @@
|
||||
return
|
||||
|
||||
/// Signal proc for [COMSIG_ITEM_AFTERATTACK] that allows for effects after an attack is done
|
||||
/datum/plant_gene/trait/attack/proc/after_plant_attack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters)
|
||||
/datum/plant_gene/trait/attack/proc/after_plant_attack(obj/item/source, atom/target, mob/user, click_parameters)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!proximity_flag)
|
||||
return
|
||||
|
||||
if(!ismovable(target))
|
||||
return
|
||||
|
||||
. |= COMPONENT_AFTERATTACK_PROCESSED_ITEM
|
||||
|
||||
if(isobj(target))
|
||||
var/obj/object_target = target
|
||||
if(!(object_target.obj_flags & CAN_BE_HIT))
|
||||
return .
|
||||
|
||||
INVOKE_ASYNC(src, PROC_REF(after_attack_effect), source, target, user)
|
||||
return .
|
||||
|
||||
/*
|
||||
* Effects done when we hit people with our plant, AFTER the attack is done.
|
||||
|
||||
@@ -269,49 +269,48 @@ GLOBAL_LIST_INIT(bibleitemstates, list(
|
||||
playsound(target_mob, SFX_PUNCH, 25, TRUE, -1)
|
||||
log_combat(user, target_mob, "attacked", src)
|
||||
|
||||
/obj/item/book/bible/attackby_storage_insert(datum/storage, atom/storage_holder, mob/user)
|
||||
/obj/item/book/bible/storage_insert_on_interaction(datum/storage, atom/storage_holder, mob/user)
|
||||
return !istype(storage_holder, /obj/item/book/bible)
|
||||
|
||||
/obj/item/book/bible/afterattack(atom/bible_smacked, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(!proximity_flag)
|
||||
return
|
||||
if(SEND_SIGNAL(bible_smacked, COMSIG_BIBLE_SMACKED, user, proximity_flag, click_parameters) & COMSIG_END_BIBLE_CHAIN)
|
||||
return . | AFTERATTACK_PROCESSED_ITEM
|
||||
/obj/item/book/bible/interact_with_atom(atom/bible_smacked, mob/living/user, list/modifiers)
|
||||
if(SEND_SIGNAL(bible_smacked, COMSIG_BIBLE_SMACKED, user) & COMSIG_END_BIBLE_CHAIN)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
if(isfloorturf(bible_smacked))
|
||||
if(user.mind?.holy_role)
|
||||
var/area/current_area = get_area(bible_smacked)
|
||||
if(!GLOB.chaplain_altars.len && istype(current_area, /area/station/service/chapel))
|
||||
make_new_altar(bible_smacked, user)
|
||||
return
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
for(var/obj/effect/rune/nearby_runes in range(2, user))
|
||||
nearby_runes.SetInvisibility(INVISIBILITY_NONE, id=type, priority=INVISIBILITY_PRIORITY_BASIC_ANTI_INVISIBILITY)
|
||||
bible_smacked.balloon_alert(user, "floor smacked!")
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
if(user.mind?.holy_role)
|
||||
if(bible_smacked.reagents && bible_smacked.reagents.has_reagent(/datum/reagent/water)) // blesses all the water in the holder
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
if(bible_smacked.reagents?.has_reagent(/datum/reagent/water)) // blesses all the water in the holder
|
||||
bible_smacked.balloon_alert(user, "blessed")
|
||||
var/water2holy = bible_smacked.reagents.get_reagent_amount(/datum/reagent/water)
|
||||
bible_smacked.reagents.del_reagent(/datum/reagent/water)
|
||||
bible_smacked.reagents.add_reagent(/datum/reagent/water/holywater,water2holy)
|
||||
if(bible_smacked.reagents && bible_smacked.reagents.has_reagent(/datum/reagent/fuel/unholywater)) // yeah yeah, copy pasted code - sue me
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
. = ITEM_INTERACT_SUCCESS
|
||||
if(bible_smacked.reagents?.has_reagent(/datum/reagent/fuel/unholywater)) // yeah yeah, copy pasted code - sue me
|
||||
bible_smacked.balloon_alert(user, "purified")
|
||||
var/unholy2holy = bible_smacked.reagents.get_reagent_amount(/datum/reagent/fuel/unholywater)
|
||||
bible_smacked.reagents.del_reagent(/datum/reagent/fuel/unholywater)
|
||||
bible_smacked.reagents.add_reagent(/datum/reagent/water/holywater,unholy2holy)
|
||||
. = ITEM_INTERACT_SUCCESS
|
||||
if(istype(bible_smacked, /obj/item/book/bible) && !istype(bible_smacked, /obj/item/book/bible/syndicate))
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
bible_smacked.balloon_alert(user, "converted")
|
||||
var/obj/item/book/bible/other_bible = bible_smacked
|
||||
other_bible.name = name
|
||||
other_bible.icon_state = icon_state
|
||||
other_bible.inhand_icon_state = inhand_icon_state
|
||||
other_bible.deity_name = deity_name
|
||||
. = ITEM_INTERACT_SUCCESS
|
||||
if(.)
|
||||
return .
|
||||
|
||||
if(istype(bible_smacked, /obj/item/cult_bastard) && !IS_CULTIST(user))
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
var/obj/item/cult_bastard/sword = bible_smacked
|
||||
bible_smacked.balloon_alert(user, "exorcising...")
|
||||
playsound(src,'sound/hallucinations/veryfar_noise.ogg',40,TRUE)
|
||||
@@ -333,6 +332,9 @@ GLOBAL_LIST_INIT(bibleitemstates, list(
|
||||
new /obj/item/nullrod/claymore(get_turf(sword))
|
||||
user.visible_message(span_notice("[user] exorcises [sword]!"))
|
||||
qdel(sword)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
return NONE
|
||||
|
||||
/obj/item/book/bible/booze
|
||||
desc = "To be applied to the head repeatedly."
|
||||
|
||||
@@ -320,21 +320,23 @@
|
||||
icon = 'icons/obj/mining_zones/artefacts.dmi'
|
||||
icon_state = "prison_cube"
|
||||
|
||||
/obj/item/prisoncube/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(!proximity_flag || !isliving(target))
|
||||
return
|
||||
var/mob/living/victim = target
|
||||
var/mob/living/carbon/carbon_victim = victim
|
||||
/obj/item/prisoncube/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!isliving(interacting_with))
|
||||
return NONE
|
||||
|
||||
var/mob/living/carbon/carbon_victim = interacting_with
|
||||
//Handcuffed or unconscious
|
||||
if(istype(carbon_victim) && carbon_victim.handcuffed || victim.stat != CONSCIOUS)
|
||||
if(!puzzle_imprison(target))
|
||||
to_chat(user,span_warning("[src] does nothing."))
|
||||
return
|
||||
to_chat(user,span_warning("You trap [victim] in the prison cube!"))
|
||||
if(istype(carbon_victim) && (carbon_victim.handcuffed || carbon_victim.stat != CONSCIOUS))
|
||||
user.do_attack_animation(carbon_victim)
|
||||
if(!puzzle_imprison(carbon_victim))
|
||||
to_chat(user, span_warning("[src] does nothing."))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
to_chat(user, span_warning("You trap [carbon_victim] in the prison cube!"))
|
||||
qdel(src)
|
||||
else
|
||||
to_chat(user,span_notice("[src] only accepts restrained or unconscious prisoners."))
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
to_chat(user, span_notice("[src] only accepts restrained or unconscious prisoners."))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
/proc/puzzle_imprison(mob/living/prisoner)
|
||||
var/turf/T = get_turf(prisoner)
|
||||
|
||||
@@ -36,18 +36,17 @@
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
hitsound = 'sound/weapons/bladeslice.ogg'
|
||||
|
||||
/obj/item/knife/envy/afterattack(atom/movable/AM, mob/living/carbon/human/user, proximity)
|
||||
. = ..()
|
||||
if(!proximity)
|
||||
/obj/item/knife/envy/afterattack(atom/target, mob/living/carbon/human/user, click_parameters)
|
||||
if(!istype(user) || !ishuman(target))
|
||||
return
|
||||
if(!istype(user))
|
||||
|
||||
var/mob/living/carbon/human/H = target
|
||||
if(user.real_name == H.dna.real_name)
|
||||
return
|
||||
if(ishuman(AM))
|
||||
var/mob/living/carbon/human/H = AM
|
||||
if(user.real_name != H.dna.real_name)
|
||||
user.real_name = H.dna.real_name
|
||||
H.dna.transfer_identity(user, transfer_SE=1)
|
||||
user.updateappearance(mutcolor_update=1)
|
||||
user.domutcheck()
|
||||
user.visible_message(span_warning("[user]'s appearance shifts into [H]'s!"), \
|
||||
span_boldannounce("[H.p_They()] think[H.p_s()] [H.p_theyre()] <i>sooo</i> much better than you. Not anymore, [H.p_they()] won't."))
|
||||
|
||||
user.real_name = H.dna.real_name
|
||||
H.dna.transfer_identity(user, transfer_SE=1)
|
||||
user.updateappearance(mutcolor_update=1)
|
||||
user.domutcheck()
|
||||
user.visible_message(span_warning("[user]'s appearance shifts into [H]'s!"), \
|
||||
span_boldannounce("[H.p_They()] think[H.p_s()] [H.p_theyre()] <i>sooo</i> much better than you. Not anymore, [H.p_they()] won't."))
|
||||
|
||||
@@ -524,14 +524,12 @@ GLOBAL_VAR_INIT(hhMysteryRoomNumber, rand(1, 999999))
|
||||
icon_state = "hilbertsanalyzer"
|
||||
worn_icon_state = "analyzer"
|
||||
|
||||
/obj/item/analyzer/hilbertsanalyzer/afterattack(atom/target, mob/user, proximity)
|
||||
. = ..()
|
||||
if(istype(target, /obj/item/hilbertshotel))
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
if(!proximity)
|
||||
/obj/item/analyzer/hilbertsanalyzer/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(istype(interacting_with, /obj/item/hilbertshotel))
|
||||
if(!Adjacent(interacting_with))
|
||||
to_chat(user, span_warning("It's to far away to scan!"))
|
||||
return .
|
||||
var/obj/item/hilbertshotel/sphere = target
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
var/obj/item/hilbertshotel/sphere = interacting_with
|
||||
if(sphere.activeRooms.len)
|
||||
to_chat(user, "Currently Occupied Rooms:")
|
||||
for(var/roomnumber in sphere.activeRooms)
|
||||
@@ -544,7 +542,8 @@ GLOBAL_VAR_INIT(hhMysteryRoomNumber, rand(1, 999999))
|
||||
to_chat(user, roomnumber)
|
||||
else
|
||||
to_chat(user, "No vacated rooms.")
|
||||
return .
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
return ..()
|
||||
|
||||
/obj/effect/landmark/transport/transport_id/hilbert
|
||||
specific_transport_id = HILBERT_LINE_1
|
||||
|
||||
@@ -35,26 +35,22 @@
|
||||
zipline_sound = new(src)
|
||||
update_appearance()
|
||||
|
||||
/obj/item/grapple_gun/afterattack(atom/target, mob/living/user, proximity)
|
||||
. = ..()
|
||||
|
||||
/obj/item/grapple_gun/ranged_interact_with_atom(atom/target, mob/living/user, list/modifiers)
|
||||
if(isgroundlessturf(target))
|
||||
return
|
||||
return NONE
|
||||
if(target == user || !hooked)
|
||||
return NONE
|
||||
|
||||
if(!lavaland_equipment_pressure_check(get_turf(user)))
|
||||
user.balloon_alert(user, "gun mechanism wont work here!")
|
||||
return
|
||||
|
||||
if(target == user || !hooked)
|
||||
return
|
||||
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(get_dist(user, target) > 9)
|
||||
user.balloon_alert(user, "too far away!")
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
var/turf/attacked_atom = get_turf(target)
|
||||
if(isnull(attacked_atom))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
var/list/turf_list = (get_line(user, attacked_atom) - get_turf(src))
|
||||
for(var/turf/singular_turf as anything in turf_list)
|
||||
@@ -66,9 +62,7 @@
|
||||
break
|
||||
|
||||
if(user.CanReach(attacked_atom))
|
||||
return
|
||||
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
var/atom/bullet = fire_projectile(/obj/projectile/grapple_hook, attacked_atom, 'sound/weapons/zipline_fire.ogg')
|
||||
zipline = user.Beam(bullet, icon_state = "zipline_hook", maxdistance = 9, layer = BELOW_MOB_LAYER)
|
||||
@@ -77,6 +71,7 @@
|
||||
RegisterSignal(bullet, COMSIG_PREQDELETED, PROC_REF(on_grapple_fail))
|
||||
zipliner = WEAKREF(user)
|
||||
update_appearance()
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/grapple_gun/proc/on_grapple_hit(datum/source, atom/movable/firer, atom/target, Angle)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
@@ -83,27 +83,24 @@
|
||||
crusher_trophy.remove_from(src, user)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/kinetic_crusher/attack(mob/living/target, mob/living/carbon/user)
|
||||
if(!HAS_TRAIT(src, TRAIT_WIELDED))
|
||||
user.balloon_alert(user, "must be wielded!")
|
||||
return
|
||||
var/datum/status_effect/crusher_damage/crusher_damage_effect = target.has_status_effect(/datum/status_effect/crusher_damage)
|
||||
if(!crusher_damage_effect)
|
||||
crusher_damage_effect = target.apply_status_effect(/datum/status_effect/crusher_damage)
|
||||
var/target_health = target.health
|
||||
..()
|
||||
for(var/obj/item/crusher_trophy/crusher_trophy as anything in trophies)
|
||||
if(!QDELETED(target))
|
||||
crusher_trophy.on_melee_hit(target, user)
|
||||
if(!QDELETED(crusher_damage_effect) && !QDELETED(target))
|
||||
crusher_damage_effect.total_damage += target_health - target.health //we did some damage, but let's not assume how much we did
|
||||
|
||||
/obj/item/kinetic_crusher/afterattack(mob/living/target, mob/living/user, proximity_flag, clickparams)
|
||||
/obj/item/kinetic_crusher/pre_attack(atom/A, mob/living/user, params)
|
||||
. = ..()
|
||||
if(.)
|
||||
return TRUE
|
||||
if(!HAS_TRAIT(src, TRAIT_WIELDED))
|
||||
user.balloon_alert(user, "must be wielded!")
|
||||
return TRUE
|
||||
return .
|
||||
|
||||
/obj/item/kinetic_crusher/afterattack(mob/living/target, mob/living/user, clickparams)
|
||||
if(!isliving(target))
|
||||
return
|
||||
if(!proximity_flag || !isliving(target))
|
||||
// Melee effect
|
||||
for(var/obj/item/crusher_trophy/crusher_trophy as anything in trophies)
|
||||
crusher_trophy.on_melee_hit(target, user)
|
||||
if(QDELETED(target))
|
||||
return
|
||||
// Clear existing marks
|
||||
var/valid_crusher_attack = FALSE
|
||||
for(var/datum/status_effect/crusher_mark/crusher_mark_effect as anything in target.get_all_status_effect_of_id(/datum/status_effect/crusher_mark))
|
||||
//this will erase ALL crusher marks, not only ones by you.
|
||||
@@ -113,9 +110,8 @@
|
||||
break
|
||||
if(!valid_crusher_attack)
|
||||
return
|
||||
var/datum/status_effect/crusher_damage/crusher_damage_effect = target.has_status_effect(/datum/status_effect/crusher_damage)
|
||||
if(!crusher_damage_effect)
|
||||
crusher_damage_effect = target.apply_status_effect(/datum/status_effect/crusher_damage)
|
||||
// Detonation effect
|
||||
var/datum/status_effect/crusher_damage/crusher_damage_effect = target.has_status_effect(/datum/status_effect/crusher_damage) || target.apply_status_effect(/datum/status_effect/crusher_damage)
|
||||
var/target_health = target.health
|
||||
for(var/obj/item/crusher_trophy/crusher_trophy as anything in trophies)
|
||||
crusher_trophy.on_mark_detonation(target, user)
|
||||
@@ -128,6 +124,7 @@
|
||||
var/combined_damage = detonation_damage
|
||||
var/backstab_dir = get_dir(user, target)
|
||||
var/def_check = target.getarmor(type = BOMB)
|
||||
// Backstab bonus
|
||||
if((user.dir & backstab_dir) && (target.dir & backstab_dir))
|
||||
backstabbed = TRUE
|
||||
combined_damage += backstab_bonus
|
||||
@@ -137,24 +134,23 @@
|
||||
SEND_SIGNAL(user, COMSIG_LIVING_CRUSHER_DETONATE, target, src, backstabbed)
|
||||
target.apply_damage(combined_damage, BRUTE, blocked = def_check)
|
||||
|
||||
/obj/item/kinetic_crusher/attack_secondary(atom/target, mob/living/user, clickparams)
|
||||
return SECONDARY_ATTACK_CONTINUE_CHAIN
|
||||
|
||||
/obj/item/kinetic_crusher/afterattack_secondary(atom/target, mob/living/user, proximity_flag, click_parameters)
|
||||
/obj/item/kinetic_crusher/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!HAS_TRAIT(src, TRAIT_WIELDED))
|
||||
balloon_alert(user, "wield it first!")
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
if(target == user)
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(interacting_with == user)
|
||||
balloon_alert(user, "can't aim at yourself!")
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
fire_kinetic_blast(target, user, click_parameters)
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
fire_kinetic_blast(interacting_with, user, modifiers)
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/kinetic_crusher/proc/fire_kinetic_blast(atom/target, mob/living/user, click_parameters)
|
||||
/obj/item/kinetic_crusher/ranged_interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
return interact_with_atom_secondary(interacting_with, user, modifiers)
|
||||
|
||||
/obj/item/kinetic_crusher/proc/fire_kinetic_blast(atom/target, mob/living/user, list/modifiers)
|
||||
if(!charged)
|
||||
return
|
||||
var/modifiers = params2list(click_parameters)
|
||||
var/turf/proj_turf = user.loc
|
||||
if(!isturf(proj_turf))
|
||||
return
|
||||
|
||||
@@ -25,27 +25,25 @@
|
||||
///So you can't revive boss monsters or robots with it
|
||||
var/revive_type = SENTIENCE_ORGANIC
|
||||
|
||||
/obj/item/lazarus_injector/afterattack(atom/target, mob/user, proximity_flag)
|
||||
. = ..()
|
||||
if(!loaded || !proximity_flag)
|
||||
return
|
||||
|
||||
/obj/item/lazarus_injector/interact_with_atom(atom/target, mob/living/user, list/modifiers)
|
||||
if(!loaded)
|
||||
return NONE
|
||||
if(SEND_SIGNAL(target, COMSIG_ATOM_ON_LAZARUS_INJECTOR, src, user) & LAZARUS_INJECTOR_USED)
|
||||
return
|
||||
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
if(!isliving(target))
|
||||
return
|
||||
return NONE
|
||||
|
||||
var/mob/living/target_animal = target
|
||||
if(!target_animal.compare_sentience_type(revive_type)) // Will also return false if not a basic or simple mob, which are the only two we want anyway
|
||||
balloon_alert(user, "invalid creature!")
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(target_animal.stat != DEAD)
|
||||
balloon_alert(user, "it's not dead!")
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
target_animal.lazarus_revive(user, malfunctioning)
|
||||
expend(target_animal, user)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/lazarus_injector/proc/expend(atom/revived_target, mob/user)
|
||||
user.visible_message(span_notice("[user] injects [revived_target] with [src], reviving it."))
|
||||
|
||||
@@ -8,24 +8,21 @@
|
||||
desc = "Inject certain types of monster organs with this stabilizer to prevent their rapid decay."
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
|
||||
/obj/item/mining_stabilizer/afterattack(obj/item/organ/target_organ, mob/user, proximity)
|
||||
. = ..()
|
||||
if (!proximity)
|
||||
return
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
|
||||
var/obj/item/organ/internal/monster_core/target_core = target_organ
|
||||
if (!istype(target_core, /obj/item/organ/internal/monster_core))
|
||||
/obj/item/mining_stabilizer/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!isorgan(interacting_with))
|
||||
return NONE
|
||||
var/obj/item/organ/internal/monster_core/target_core = interacting_with
|
||||
if (!istype(target_core))
|
||||
balloon_alert(user, "invalid target!")
|
||||
return .
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
if (!target_core.preserve())
|
||||
balloon_alert(user, "organ decayed!")
|
||||
return .
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
balloon_alert(user, "organ stabilized")
|
||||
qdel(src)
|
||||
return .
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/**
|
||||
* Useful organs which drop as loot from a mining creature.
|
||||
@@ -135,12 +132,9 @@
|
||||
icon_state = initial(icon_state)
|
||||
return ..()
|
||||
|
||||
/obj/item/organ/internal/monster_core/afterattack(atom/target, mob/user, proximity_flag)
|
||||
. = ..()
|
||||
if (!proximity_flag)
|
||||
return
|
||||
try_apply(target, user)
|
||||
return . | AFTERATTACK_PROCESSED_ITEM
|
||||
/obj/item/organ/internal/monster_core/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
try_apply(interacting_with, user)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/organ/internal/monster_core/attack_self(mob/user)
|
||||
if (!user.can_perform_action(src, FORBID_TELEKINESIS_REACH|ALLOW_RESTING))
|
||||
|
||||
@@ -51,36 +51,33 @@ GLOBAL_LIST_EMPTY(total_extraction_beacons)
|
||||
beacon_ref = WEAKREF(chosen_beacon)
|
||||
balloon_alert(user, "linked!")
|
||||
|
||||
/obj/item/extraction_pack/afterattack(atom/movable/thing, mob/living/carbon/human/user, proximity_flag, params)
|
||||
. = ..()
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
/obj/item/extraction_pack/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!ismovable(interacting_with))
|
||||
return NONE
|
||||
if(!isturf(interacting_with.loc)) // no extracting stuff inside other stuff
|
||||
return NONE
|
||||
var/atom/movable/thing = interacting_with
|
||||
if(thing.anchored)
|
||||
return NONE
|
||||
|
||||
. = ITEM_INTERACT_BLOCKING
|
||||
var/obj/structure/extraction_point/beacon = beacon_ref?.resolve()
|
||||
if(isnull(beacon))
|
||||
balloon_alert(user, "not linked")
|
||||
balloon_alert(user, "not linked!")
|
||||
beacon_ref = null
|
||||
return
|
||||
|
||||
return .
|
||||
if(!can_use_indoors)
|
||||
var/area/area = get_area(thing)
|
||||
if(!area.outdoors)
|
||||
balloon_alert(user, "not outdoors")
|
||||
return
|
||||
|
||||
if(!proximity_flag || !istype(thing))
|
||||
return
|
||||
|
||||
balloon_alert(user, "not outdoors!")
|
||||
return .
|
||||
if(!safe_for_living_creatures && check_for_living_mobs(thing))
|
||||
to_chat(user, span_warning("[src] is not safe for use with living creatures, they wouldn't survive the trip back!"))
|
||||
balloon_alert(user, "not safe!")
|
||||
return
|
||||
|
||||
if(!isturf(thing.loc)) // no extracting stuff inside other stuff
|
||||
return
|
||||
if(thing.anchored || (thing.move_resist > max_force_fulton))
|
||||
return .
|
||||
if(thing.move_resist > max_force_fulton)
|
||||
balloon_alert(user, "too heavy!")
|
||||
return
|
||||
|
||||
return .
|
||||
balloon_alert_to_viewers("attaching...")
|
||||
playsound(thing, 'sound/items/zip.ogg', vol = 50, vary = TRUE)
|
||||
if(isliving(thing))
|
||||
@@ -89,11 +86,12 @@ GLOBAL_LIST_EMPTY(total_extraction_beacons)
|
||||
to_chat(thing, span_userdanger("You are being extracted! Stand still to proceed."))
|
||||
|
||||
if(!do_after(user, 5 SECONDS, target = thing))
|
||||
return
|
||||
return .
|
||||
|
||||
balloon_alert_to_viewers("extracting!")
|
||||
if(loc == user)
|
||||
user.back?.atom_storage?.attempt_insert(src, user, force = STORAGE_SOFT_LOCKED)
|
||||
if(loc == user && ishuman(user))
|
||||
var/mob/living/carbon/human/human_user = user
|
||||
human_user.back?.atom_storage?.attempt_insert(src, user, force = STORAGE_SOFT_LOCKED)
|
||||
uses_left--
|
||||
|
||||
if(uses_left <= 0)
|
||||
@@ -180,6 +178,7 @@ GLOBAL_LIST_EMPTY(total_extraction_beacons)
|
||||
qdel(holder_obj)
|
||||
if(uses_left <= 0)
|
||||
qdel(src)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/fulton_core
|
||||
name = "extraction beacon assembly kit"
|
||||
|
||||
@@ -99,14 +99,14 @@
|
||||
blink_activated = !blink_activated
|
||||
to_chat(user, span_notice("You [blink_activated ? "enable" : "disable"] the blink function on [src]."))
|
||||
|
||||
/obj/item/hierophant_club/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
/obj/item/hierophant_club/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
// If our target is the beacon and the hierostaff is next to the beacon, we're trying to pick it up.
|
||||
if((target == beacon) && target.Adjacent(src))
|
||||
return
|
||||
if(interacting_with == beacon)
|
||||
return NONE
|
||||
if(blink_activated)
|
||||
blink.teleport(user, target)
|
||||
blink.teleport(user, interacting_with)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
return NONE
|
||||
|
||||
/obj/item/hierophant_club/update_icon_state()
|
||||
icon_state = inhand_icon_state = "hierophant_club[blink?.current_charges > 0 ? "_ready":""][(!QDELETED(beacon)) ? "":"_beacon"]"
|
||||
@@ -795,40 +795,43 @@
|
||||
var/timer = 0
|
||||
var/static/list/banned_turfs = typecacheof(list(/turf/open/space, /turf/closed))
|
||||
|
||||
/obj/item/lava_staff/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
/obj/item/lava_staff/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
return interact_with_atom(interacting_with, user, modifiers)
|
||||
|
||||
/obj/item/lava_staff/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(timer > world.time)
|
||||
return
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
if(is_type_in_typecache(target, banned_turfs))
|
||||
return
|
||||
if(target in view(user.client.view, get_turf(user)))
|
||||
var/turf/open/T = get_turf(target)
|
||||
if(!istype(T))
|
||||
return
|
||||
if(!islava(T))
|
||||
var/obj/effect/temp_visual/lavastaff/L = new /obj/effect/temp_visual/lavastaff(T)
|
||||
L.alpha = 0
|
||||
animate(L, alpha = 255, time = create_delay)
|
||||
user.visible_message(span_danger("[user] points [src] at [T]!"))
|
||||
timer = world.time + create_delay + 1
|
||||
if(do_after(user, create_delay, target = T))
|
||||
var/old_name = T.name
|
||||
if(T.TerraformTurf(turf_type, flags = CHANGETURF_INHERIT_AIR))
|
||||
user.visible_message(span_danger("[user] turns \the [old_name] into [transform_string]!"))
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] fired the lava staff at [ADMIN_VERBOSEJMP(T)]")
|
||||
user.log_message("fired the lava staff at [AREACOORD(T)].", LOG_ATTACK)
|
||||
timer = world.time + create_cooldown
|
||||
playsound(T,'sound/magic/fireball.ogg', 200, TRUE)
|
||||
else
|
||||
timer = world.time
|
||||
qdel(L)
|
||||
else
|
||||
return NONE
|
||||
if(is_type_in_typecache(interacting_with, banned_turfs))
|
||||
return NONE
|
||||
if(!(interacting_with in view(user.client.view, get_turf(user))))
|
||||
return NONE
|
||||
var/turf/open/T = get_turf(interacting_with)
|
||||
if(!istype(T))
|
||||
return NONE
|
||||
if(!islava(T))
|
||||
var/obj/effect/temp_visual/lavastaff/L = new /obj/effect/temp_visual/lavastaff(T)
|
||||
L.alpha = 0
|
||||
animate(L, alpha = 255, time = create_delay)
|
||||
user.visible_message(span_danger("[user] points [src] at [T]!"))
|
||||
timer = world.time + create_delay + 1
|
||||
if(do_after(user, create_delay, target = T))
|
||||
var/old_name = T.name
|
||||
if(T.TerraformTurf(reset_turf_type, flags = CHANGETURF_INHERIT_AIR))
|
||||
user.visible_message(span_danger("[user] turns \the [old_name] into [reset_string]!"))
|
||||
timer = world.time + reset_cooldown
|
||||
if(T.TerraformTurf(turf_type, flags = CHANGETURF_INHERIT_AIR))
|
||||
user.visible_message(span_danger("[user] turns \the [old_name] into [transform_string]!"))
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] fired the lava staff at [ADMIN_VERBOSEJMP(T)]")
|
||||
user.log_message("fired the lava staff at [AREACOORD(T)].", LOG_ATTACK)
|
||||
timer = world.time + create_cooldown
|
||||
playsound(T,'sound/magic/fireball.ogg', 200, TRUE)
|
||||
else
|
||||
timer = world.time
|
||||
qdel(L)
|
||||
else
|
||||
var/old_name = T.name
|
||||
if(T.TerraformTurf(reset_turf_type, flags = CHANGETURF_INHERIT_AIR))
|
||||
user.visible_message(span_danger("[user] turns \the [old_name] into [reset_string]!"))
|
||||
timer = world.time + reset_cooldown
|
||||
playsound(T,'sound/magic/fireball.ogg', 200, TRUE)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/effect/temp_visual/lavastaff
|
||||
icon_state = "lavastaff_warn"
|
||||
@@ -1028,23 +1031,27 @@
|
||||
affected_weather.wind_down()
|
||||
user.log_message("has dispelled a storm at [AREACOORD(user_turf)].", LOG_GAME)
|
||||
|
||||
/obj/item/storm_staff/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
/obj/item/storm_staff/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
return thunder_blast(interacting_with, user) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_BLOCKING
|
||||
|
||||
/obj/item/storm_staff/afterattack(atom/target, mob/user, click_parameters)
|
||||
thunder_blast(target, user)
|
||||
|
||||
/obj/item/storm_staff/proc/thunder_blast(atom/target, mob/user)
|
||||
if(!thunder_charges)
|
||||
balloon_alert(user, "needs to charge!")
|
||||
return
|
||||
return FALSE
|
||||
var/turf/target_turf = get_turf(target)
|
||||
var/area/target_area = get_area(target)
|
||||
if(!target_turf || !target_area || (is_type_in_list(target_area, excluded_areas)))
|
||||
balloon_alert(user, "can't bolt here!")
|
||||
return
|
||||
return FALSE
|
||||
if(target_turf in targeted_turfs)
|
||||
balloon_alert(user, "already targeted!")
|
||||
return
|
||||
return FALSE
|
||||
if(HAS_TRAIT(user, TRAIT_PACIFISM))
|
||||
balloon_alert(user, "you don't want to harm!")
|
||||
return
|
||||
return FALSE
|
||||
var/power_boosted = FALSE
|
||||
for(var/datum/weather/weather as anything in SSweather.processing)
|
||||
if(weather.stage != MAIN_STAGE)
|
||||
@@ -1060,6 +1067,7 @@
|
||||
thunder_charges--
|
||||
addtimer(CALLBACK(src, PROC_REF(recharge)), thunder_charge_time)
|
||||
user.log_message("fired the staff of storms at [AREACOORD(target_turf)].", LOG_ATTACK)
|
||||
return TRUE
|
||||
|
||||
/obj/item/storm_staff/proc/recharge(mob/user)
|
||||
thunder_charges = min(thunder_charges + 1, max_thunder_charges)
|
||||
|
||||
@@ -646,20 +646,18 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
|
||||
continue
|
||||
target_airlock.lock()
|
||||
|
||||
/obj/item/coin/eldritch/afterattack(atom/target_atom, mob/user, proximity)
|
||||
. = ..()
|
||||
if(!proximity)
|
||||
return
|
||||
/obj/item/coin/eldritch/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!istype(interacting_with, /obj/machinery/door/airlock))
|
||||
return NONE
|
||||
if(!IS_HERETIC(user))
|
||||
var/mob/living/living_user = user
|
||||
living_user.adjustBruteLoss(5)
|
||||
living_user.adjustFireLoss(5)
|
||||
return
|
||||
if(istype(target_atom, /obj/machinery/door/airlock))
|
||||
var/obj/machinery/door/airlock/target_airlock = target_atom
|
||||
to_chat(user, span_warning("You insert [src] into the airlock."))
|
||||
target_airlock.emag_act(user, src)
|
||||
qdel(src)
|
||||
user.adjustBruteLoss(5)
|
||||
user.adjustFireLoss(5)
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
var/obj/machinery/door/airlock/target_airlock = interacting_with
|
||||
to_chat(user, span_warning("You insert [src] into the airlock."))
|
||||
target_airlock.emag_act(user, src)
|
||||
qdel(src)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
#undef GIBTONITE_QUALITY_HIGH
|
||||
#undef GIBTONITE_QUALITY_LOW
|
||||
|
||||
@@ -215,10 +215,10 @@
|
||||
balloon_alert(user, "now [combat_mode ? "attacking wildlife" : "collecting loose ore"]")
|
||||
return CLICK_ACTION_SUCCESS
|
||||
|
||||
/mob/living/basic/mining_drone/RangedAttack(atom/target)
|
||||
/mob/living/basic/mining_drone/RangedAttack(atom/target, list/modifiers)
|
||||
if(!combat_mode)
|
||||
return
|
||||
stored_gun.afterattack(target, src)
|
||||
stored_gun.try_fire_gun(target, src, list2params(modifiers))
|
||||
|
||||
/mob/living/basic/mining_drone/UnarmedAttack(atom/attack_target, proximity_flag, list/modifiers)
|
||||
. = ..()
|
||||
|
||||
@@ -43,22 +43,22 @@
|
||||
user.client?.mouse_override_icon = 'icons/effects/mouse_pointers/weapon_pointer.dmi'
|
||||
user.update_mouse_pointer()
|
||||
|
||||
/obj/item/minebot_remote_control/afterattack(atom/attacked_atom, mob/living/user, proximity)
|
||||
. = ..()
|
||||
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
/obj/item/minebot_remote_control/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
return ranged_interact_with_atom(interacting_with, user, modifiers)
|
||||
|
||||
/obj/item/minebot_remote_control/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!primed)
|
||||
user.balloon_alert(user, "not primed!")
|
||||
return
|
||||
var/turf/target_turf = get_turf(attacked_atom)
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
var/turf/target_turf = get_turf(interacting_with)
|
||||
if(isnull(target_turf) || isclosedturf(target_turf) || isgroundlessturf(target_turf))
|
||||
user.balloon_alert(user, "invalid target!")
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
playsound(src, 'sound/machines/beep.ogg', 30)
|
||||
clear_priming()
|
||||
new /obj/effect/temp_visual/minebot_target(target_turf)
|
||||
COOLDOWN_START(src, bomb_timer, BOMB_COOLDOWN)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/effect/temp_visual/minebot_target
|
||||
name = "Rocket Target"
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
icon = 'icons/obj/devices/circuitry_n_data.dmi'
|
||||
item_flags = NOBLUDGEON
|
||||
|
||||
/obj/item/mine_bot_upgrade/afterattack(mob/living/basic/mining_drone/minebot, mob/user, proximity)
|
||||
. = ..()
|
||||
if(!istype(minebot) || !proximity)
|
||||
return
|
||||
upgrade_bot(minebot, user)
|
||||
/obj/item/mine_bot_upgrade/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!istype(interacting_with, /mob/living/basic/mining_drone))
|
||||
return NONE
|
||||
upgrade_bot(interacting_with, user)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/mine_bot_upgrade/proc/upgrade_bot(mob/living/basic/mining_drone/minebot, mob/user)
|
||||
if(minebot.melee_damage_upper != initial(minebot.melee_damage_upper))
|
||||
@@ -90,4 +90,3 @@
|
||||
icon = 'icons/mob/silicon/aibots.dmi'
|
||||
icon_state = "minebot_shield_bottom_layer"
|
||||
layer = BELOW_MOB_LAYER
|
||||
|
||||
|
||||
@@ -18,18 +18,17 @@
|
||||
/mob/living/basic/guardian,
|
||||
))
|
||||
|
||||
/obj/item/fugu_gland/afterattack(atom/target, mob/user, proximity_flag)
|
||||
. = ..()
|
||||
if(!proximity_flag || !isanimal_or_basicmob(target) || fugu_blacklist[target.type])
|
||||
return
|
||||
var/mob/living/animal = target
|
||||
/obj/item/fugu_gland/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!isanimal_or_basicmob(interacting_with) || fugu_blacklist[interacting_with.type])
|
||||
return NONE
|
||||
var/mob/living/animal = interacting_with
|
||||
|
||||
if(animal.stat == DEAD || HAS_TRAIT(animal, TRAIT_FAKEDEATH))
|
||||
balloon_alert(user, "it's dead!")
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(HAS_TRAIT(animal, TRAIT_FUGU_GLANDED))
|
||||
balloon_alert(user, "already large!")
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
ADD_TRAIT(animal, TRAIT_FUGU_GLANDED, type)
|
||||
animal.AddComponent(/datum/component/seethrough_mob)
|
||||
@@ -41,3 +40,4 @@
|
||||
animal.AddElement(/datum/element/wall_tearer)
|
||||
to_chat(user, span_info("You increase the size of [animal], giving [animal.p_them()] a surge of strength!"))
|
||||
qdel(src)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
@@ -352,18 +352,18 @@
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/food/deadmouse/afterattack(obj/target, mob/living/user, proximity_flag)
|
||||
. = ..()
|
||||
if(proximity_flag && reagents && target.is_open_container())
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
// is_open_container will not return truthy if target.reagents doesn't exist
|
||||
var/datum/reagents/target_reagents = target.reagents
|
||||
var/trans_amount = reagents.maximum_volume - reagents.total_volume * (4 / 3)
|
||||
if(target_reagents.has_reagent(/datum/reagent/fuel) && target_reagents.trans_to(src, trans_amount))
|
||||
to_chat(user, span_notice("You dip [src] into [target]."))
|
||||
else
|
||||
to_chat(user, span_warning("That's a terrible idea."))
|
||||
return .
|
||||
/obj/item/food/deadmouse/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(isnull(reagents) || !interacting_with.is_open_container())
|
||||
return NONE
|
||||
|
||||
// is_open_container will not return truthy if target.reagents doesn't exist
|
||||
var/datum/reagents/target_reagents = interacting_with.reagents
|
||||
var/trans_amount = reagents.maximum_volume - reagents.total_volume * (4 / 3)
|
||||
if(target_reagents.has_reagent(/datum/reagent/fuel) && target_reagents.trans_to(src, trans_amount))
|
||||
to_chat(user, span_notice("You dip [src] into [interacting_with]."))
|
||||
else
|
||||
to_chat(user, span_warning("That's a terrible idea."))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
/obj/item/food/deadmouse/moldy
|
||||
name = "moldy dead mouse"
|
||||
|
||||
@@ -23,15 +23,14 @@
|
||||
QDEL_NULL(dna)
|
||||
GLOB.carbon_list -= src
|
||||
|
||||
/mob/living/carbon/item_tending(mob/living/user, obj/item/tool, list/modifiers)
|
||||
/mob/living/carbon/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
|
||||
. = ..()
|
||||
if(. & ITEM_INTERACT_ANY_BLOCKER)
|
||||
return .
|
||||
|
||||
// Needs to happen after parent call otherwise wounds are prioritized over surgery
|
||||
for(var/datum/wound/wound as anything in shuffle(all_wounds))
|
||||
if(wound.try_treating(tool, user))
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
return .
|
||||
|
||||
/mob/living/carbon/CtrlShiftClick(mob/user)
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
if(!can_unarmed_attack())
|
||||
return
|
||||
if(internal_ext)
|
||||
internal_ext.afterattack(A, src)
|
||||
internal_ext.interact_with_atom(A, src, modifiers)
|
||||
else
|
||||
return ..()
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
if(!(bot_mode_flags & BOT_MODE_ON))
|
||||
return
|
||||
if(internal_ext)
|
||||
internal_ext.afterattack(A, src)
|
||||
internal_ext.interact_with_atom(A, src, modifiers)
|
||||
else
|
||||
return ..()
|
||||
|
||||
@@ -289,7 +289,7 @@
|
||||
flick("firebots_use", user)
|
||||
else
|
||||
flick("firebot1_use", user)
|
||||
internal_ext.afterattack(target, user, null)
|
||||
internal_ext.interact_with_atom(target, src)
|
||||
|
||||
/mob/living/simple_animal/bot/firebot/update_icon_state()
|
||||
. = ..()
|
||||
|
||||
@@ -368,26 +368,26 @@ While using this makes the system rely on OnFire, it still gives options for tim
|
||||
throw_speed = 3
|
||||
throw_range = 5
|
||||
|
||||
/obj/item/tumor_shard/afterattack(atom/target, mob/user, proximity_flag)
|
||||
. = ..()
|
||||
if(istype(target, /mob/living/simple_animal/hostile/asteroid/elite) && proximity_flag)
|
||||
var/mob/living/simple_animal/hostile/asteroid/elite/E = target
|
||||
if(E.stat != DEAD || E.sentience_type != SENTIENCE_BOSS || !E.key)
|
||||
user.visible_message(span_notice("It appears [E] is unable to be revived right now. Perhaps try again later."))
|
||||
return
|
||||
E.faction = list("[REF(user)]")
|
||||
E.revive(HEAL_ALL)
|
||||
user.visible_message(span_notice("[user] stabs [E] with [src], reviving it."))
|
||||
E.playsound_local(get_turf(E), 'sound/effects/magic.ogg', 40, 0)
|
||||
to_chat(E, "<span class='userdanger'>You have been revived by [user]. While you can't speak to them, you owe [user] a great debt. Assist [user.p_them()] in achieving [user.p_their()] goals, regardless of risk.</span>")
|
||||
to_chat(E, "<span class='big bold'>Note that you now share the loyalties of [user]. You are expected not to intentionally sabotage their faction unless commanded to!</span>")
|
||||
E.maxHealth = E.maxHealth * 0.4
|
||||
E.health = E.maxHealth
|
||||
E.desc = "[E.desc] However, this one appears to be less wild in nature, and calmer around people."
|
||||
E.sentience_type = SENTIENCE_ORGANIC
|
||||
qdel(src)
|
||||
else
|
||||
to_chat(user, span_info("[src] only works on the corpse of a sentient lavaland elite."))
|
||||
/obj/item/tumor_shard/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!istype(interacting_with, /mob/living/simple_animal/hostile/asteroid/elite))
|
||||
return NONE
|
||||
|
||||
var/mob/living/simple_animal/hostile/asteroid/elite/E = interacting_with
|
||||
if(E.stat != DEAD || E.sentience_type != SENTIENCE_BOSS || !E.key)
|
||||
user.visible_message(span_notice("It appears [E] is unable to be revived right now. Perhaps try again later."))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
E.faction = list("[REF(user)]")
|
||||
E.revive(HEAL_ALL)
|
||||
user.visible_message(span_notice("[user] stabs [E] with [src], reviving it."))
|
||||
E.playsound_local(get_turf(E), 'sound/effects/magic.ogg', 40, 0)
|
||||
to_chat(E, "<span class='userdanger'>You have been revived by [user]. While you can't speak to them, you owe [user] a great debt. Assist [user.p_them()] in achieving [user.p_their()] goals, regardless of risk.</span>")
|
||||
to_chat(E, "<span class='big bold'>Note that you now share the loyalties of [user]. You are expected not to intentionally sabotage their faction unless commanded to!</span>")
|
||||
E.maxHealth = E.maxHealth * 0.4
|
||||
E.health = E.maxHealth
|
||||
E.desc = "[E.desc] However, this one appears to be less wild in nature, and calmer around people."
|
||||
E.sentience_type = SENTIENCE_ORGANIC
|
||||
qdel(src)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/effect/temp_visual/elite_tumor_wall
|
||||
name = "magic wall"
|
||||
|
||||
@@ -142,6 +142,9 @@
|
||||
if(active)
|
||||
. += span_notice("Charge: [core ? "[get_charge_percent()]%" : "No core"].")
|
||||
. += span_notice("Selected module: [selected_module || "None"].")
|
||||
if(atom_storage)
|
||||
. += span_notice("<i>While the suit's panel is open, \
|
||||
being on <b>combat mode</b> will prevent you from inserting items into it when clicking on it.</i>")
|
||||
if(!open && !active)
|
||||
if(!wearer)
|
||||
. += span_notice("You could equip it to turn it on.")
|
||||
@@ -239,33 +242,28 @@
|
||||
return ..()
|
||||
|
||||
/obj/item/mod/control/wrench_act(mob/living/user, obj/item/wrench)
|
||||
if(..())
|
||||
return TRUE
|
||||
if(seconds_electrified && get_charge() && shock(user))
|
||||
return TRUE
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(open)
|
||||
if(!core)
|
||||
balloon_alert(user, "no core!")
|
||||
return TRUE
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
balloon_alert(user, "removing core...")
|
||||
wrench.play_tool_sound(src, 100)
|
||||
if(!wrench.use_tool(src, user, 3 SECONDS) || !open)
|
||||
balloon_alert(user, "interrupted!")
|
||||
return TRUE
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
wrench.play_tool_sound(src, 100)
|
||||
balloon_alert(user, "core removed")
|
||||
core.forceMove(drop_location())
|
||||
return TRUE
|
||||
return ..()
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
return NONE
|
||||
|
||||
/obj/item/mod/control/screwdriver_act(mob/living/user, obj/item/screwdriver)
|
||||
. = ..()
|
||||
if(.)
|
||||
return TRUE
|
||||
if(active || activating || ai_controller)
|
||||
balloon_alert(user, "deactivate suit first!")
|
||||
playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
|
||||
return FALSE
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
balloon_alert(user, "[open ? "closing" : "opening"] cover...")
|
||||
screwdriver.play_tool_sound(src, 100)
|
||||
if(screwdriver.use_tool(src, user, 1 SECONDS))
|
||||
@@ -276,21 +274,21 @@
|
||||
open = !open
|
||||
else
|
||||
balloon_alert(user, "interrupted!")
|
||||
return TRUE
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/mod/control/crowbar_act(mob/living/user, obj/item/crowbar)
|
||||
. = ..()
|
||||
if(!open)
|
||||
balloon_alert(user, "open the cover first!")
|
||||
playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
|
||||
return FALSE
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(!allowed(user))
|
||||
balloon_alert(user, "insufficient access!")
|
||||
playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(SEND_SIGNAL(src, COMSIG_MOD_MODULE_REMOVAL, user) & MOD_CANCEL_REMOVAL)
|
||||
playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
|
||||
return FALSE
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(length(modules))
|
||||
var/list/removable_modules = list()
|
||||
for(var/obj/item/mod/module/module as anything in modules)
|
||||
@@ -299,52 +297,64 @@
|
||||
removable_modules += module
|
||||
var/obj/item/mod/module/module_to_remove = tgui_input_list(user, "Which module to remove?", "Module Removal", removable_modules)
|
||||
if(!module_to_remove?.mod)
|
||||
return FALSE
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
uninstall(module_to_remove)
|
||||
module_to_remove.forceMove(drop_location())
|
||||
crowbar.play_tool_sound(src, 100)
|
||||
SEND_SIGNAL(src, COMSIG_MOD_MODULE_REMOVED, user)
|
||||
return TRUE
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
balloon_alert(user, "no modules!")
|
||||
playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
|
||||
return FALSE
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
/obj/item/mod/control/attackby(obj/item/attacking_item, mob/living/user, params)
|
||||
/obj/item/mod/control/storage_insert_on_interacted_with(datum/storage, obj/item/inserted, mob/living/user)
|
||||
if(user.combat_mode)
|
||||
// Block all item-click-inserts when we're open
|
||||
// Other form of insertion will still function (mousedrop, hotkey)
|
||||
if(open)
|
||||
return FALSE
|
||||
// ...You have to open it up somehow though
|
||||
if(inserted.tool_behaviour == TOOL_SCREWDRIVER)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/item/mod/control/item_interaction(mob/living/user, obj/item/attacking_item, list/modifiers)
|
||||
if(istype(attacking_item, /obj/item/pai_card))
|
||||
if(!open)
|
||||
balloon_alert(user, "open the cover first!")
|
||||
return FALSE
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
insert_pai(user, attacking_item)
|
||||
return TRUE
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
if(istype(attacking_item, /obj/item/mod/module))
|
||||
if(!open)
|
||||
balloon_alert(user, "open the cover first!")
|
||||
playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
|
||||
return FALSE
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
install(attacking_item, user)
|
||||
SEND_SIGNAL(src, COMSIG_MOD_MODULE_ADDED, user)
|
||||
return TRUE
|
||||
else if(istype(attacking_item, /obj/item/mod/core))
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
if(istype(attacking_item, /obj/item/mod/core))
|
||||
if(!open)
|
||||
balloon_alert(user, "open the cover first!")
|
||||
playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
|
||||
return FALSE
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(core)
|
||||
balloon_alert(user, "core already installed!")
|
||||
playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
|
||||
return FALSE
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
var/obj/item/mod/core/attacking_core = attacking_item
|
||||
attacking_core.install(src)
|
||||
balloon_alert(user, "core installed")
|
||||
playsound(src, 'sound/machines/click.ogg', 50, TRUE, SILENCED_SOUND_EXTRARANGE)
|
||||
return TRUE
|
||||
else if(is_wire_tool(attacking_item) && open)
|
||||
wires.interact(user)
|
||||
return TRUE
|
||||
else if(open && attacking_item.GetID())
|
||||
update_access(user, attacking_item.GetID())
|
||||
return TRUE
|
||||
return ..()
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
if(open)
|
||||
if(is_wire_tool(attacking_item))
|
||||
wires.interact(user)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
if(attacking_item.GetID())
|
||||
update_access(user, attacking_item.GetID())
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
return NONE
|
||||
|
||||
/obj/item/mod/control/get_cell()
|
||||
var/obj/item/stock_parts/cell/cell = get_charge_source()
|
||||
|
||||
@@ -104,7 +104,7 @@
|
||||
return ..()
|
||||
|
||||
/obj/structure/filingcabinet/attack_self_tk(mob/user)
|
||||
. = COMPONENT_CANCEL_ATTACK_CHAIN
|
||||
. = ITEM_INTERACT_BLOCKING
|
||||
if(contents.len)
|
||||
if(prob(40 + contents.len * 5))
|
||||
var/obj/item/I = pick(contents)
|
||||
@@ -203,4 +203,3 @@ GLOBAL_LIST_EMPTY(employmentCabinets)
|
||||
fillCurrent()
|
||||
virgin = FALSE
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@
|
||||
labels_left = initial(labels_left) //Yes, it's capped at its initial value
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/hand_labeler/attackby_storage_insert(datum/storage, atom/storage_holder, mob/user)
|
||||
/obj/item/hand_labeler/storage_insert_on_interaction(datum/storage, atom/storage_holder, mob/user)
|
||||
return !mode
|
||||
|
||||
/obj/item/hand_labeler/borg
|
||||
|
||||
@@ -501,22 +501,22 @@
|
||||
. += span_notice("To initiate the surrender prompt, simply click on an individual within your proximity.")
|
||||
|
||||
//Code from the medical penlight
|
||||
/obj/item/pen/red/security/afterattack(atom/target, mob/living/user, proximity)
|
||||
. = ..()
|
||||
/obj/item/pen/red/security/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!COOLDOWN_FINISHED(src, holosign_cooldown))
|
||||
balloon_alert(user, "not ready!")
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
var/target_turf = get_turf(target)
|
||||
var/turf/target_turf = get_turf(interacting_with)
|
||||
var/mob/living/living_target = locate(/mob/living) in target_turf
|
||||
|
||||
if(!living_target || (living_target == user))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
living_target.apply_status_effect(/datum/status_effect/surrender_timed)
|
||||
to_chat(living_target, span_userdanger("[user] requests your immediate surrender! You are given 30 seconds to comply!"))
|
||||
new /obj/effect/temp_visual/security_holosign(target_turf, user) //produce a holographic glow
|
||||
COOLDOWN_START(src, holosign_cooldown, 30 SECONDS)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/effect/temp_visual/security_holosign
|
||||
name = "security holosign"
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
. += "It has [pictures_left] photos left."
|
||||
|
||||
//user can be atom or mob
|
||||
/obj/item/camera/proc/can_target(atom/target, mob/user, prox_flag)
|
||||
/obj/item/camera/proc/can_target(atom/target, mob/user)
|
||||
if(!on || blending || !pictures_left)
|
||||
return FALSE
|
||||
var/turf/T = get_turf(target)
|
||||
@@ -128,24 +128,30 @@
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/item/camera/afterattack(atom/target, mob/user, flag)
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
/obj/item/camera/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
return ranged_interact_with_atom(interacting_with, user, modifiers)
|
||||
|
||||
/obj/item/camera/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if (disk)
|
||||
if(ismob(target))
|
||||
if(ismob(interacting_with))
|
||||
if (disk.record)
|
||||
QDEL_NULL(disk.record)
|
||||
|
||||
disk.record = new
|
||||
var/mob/M = target
|
||||
var/mob/M = interacting_with
|
||||
disk.record.caller_name = M.name
|
||||
disk.record.set_caller_image(M)
|
||||
else
|
||||
to_chat(user, span_warning("Invalid holodisk target."))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
if(!can_target(target, user, flag))
|
||||
return
|
||||
if(!can_target(interacting_with, user))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(!photo_taken(interacting_with, user))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/camera/proc/photo_taken(atom/target, mob/user)
|
||||
|
||||
on = FALSE
|
||||
addtimer(CALLBACK(src, PROC_REF(cooldown)), cooldown)
|
||||
@@ -153,7 +159,7 @@
|
||||
icon_state = state_off
|
||||
|
||||
INVOKE_ASYNC(src, PROC_REF(captureimage), target, user, picture_size_x - 1, picture_size_y - 1)
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/item/camera/proc/cooldown()
|
||||
UNTIL(!blending)
|
||||
|
||||
@@ -354,24 +354,23 @@ All the important duct code:
|
||||
duct_color = new_color
|
||||
add_atom_colour(GLOB.pipe_paint_colors[new_color], FIXED_COLOUR_PRIORITY)
|
||||
|
||||
/obj/item/stack/ducts/afterattack(atom/target, user, proximity)
|
||||
. = ..()
|
||||
if(!proximity)
|
||||
return
|
||||
if(istype(target, /obj/machinery/duct))
|
||||
var/obj/machinery/duct/duct = target
|
||||
/obj/item/stack/ducts/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(istype(interacting_with, /obj/machinery/duct))
|
||||
var/obj/machinery/duct/duct = interacting_with
|
||||
if(duct.anchored)
|
||||
to_chat(user, span_warning("The duct must be unanchored before it can be picked up."))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
// Turn into a duct stack and then merge to the in-hand stack.
|
||||
var/obj/item/stack/ducts/stack = new(duct.loc, 1, FALSE)
|
||||
qdel(duct)
|
||||
if(stack.can_merge(src))
|
||||
stack.merge(src)
|
||||
return
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
check_attach_turf(interacting_with)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
check_attach_turf(target)
|
||||
|
||||
/obj/item/stack/ducts/proc/check_attach_turf(atom/target)
|
||||
if(isopenturf(target) && use(1))
|
||||
|
||||
@@ -304,10 +304,6 @@
|
||||
/obj/item/stock_parts/cell/get_part_rating()
|
||||
return maxcharge * 10 + charge
|
||||
|
||||
/obj/item/stock_parts/cell/attackby_storage_insert(datum/storage, atom/storage_holder, mob/user)
|
||||
var/obj/item/mod/control/mod = storage_holder
|
||||
return !(istype(mod) && mod.open)
|
||||
|
||||
/* Cell variants*/
|
||||
/obj/item/stock_parts/cell/empty
|
||||
empty = TRUE
|
||||
|
||||
@@ -501,11 +501,12 @@
|
||||
. = ..()
|
||||
ADD_TRAIT(src, TRAIT_NODROP, ABSTRACT_ITEM_TRAIT)
|
||||
|
||||
/obj/item/turret_control/afterattack(atom/targeted_atom, mob/user, proxflag, clickparams)
|
||||
. = ..()
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
/obj/item/turret_control/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
return ranged_interact_with_atom(interacting_with, user, modifiers)
|
||||
|
||||
/obj/item/turret_control/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
var/obj/machinery/power/emitter/emitter = user.buckled
|
||||
emitter.setDir(get_dir(emitter,targeted_atom))
|
||||
emitter.setDir(get_dir(emitter, interacting_with))
|
||||
user.setDir(emitter.dir)
|
||||
switch(emitter.dir)
|
||||
if(NORTH)
|
||||
@@ -541,7 +542,7 @@
|
||||
user.pixel_x = 8
|
||||
user.pixel_y = -12
|
||||
|
||||
emitter.last_projectile_params = calculate_projectile_angle_and_pixel_offsets(user, null, clickparams)
|
||||
emitter.last_projectile_params = calculate_projectile_angle_and_pixel_offsets(user, null, list2params(modifiers))
|
||||
|
||||
if(emitter.charge >= 10 && world.time > delay)
|
||||
emitter.charge -= 10
|
||||
@@ -549,6 +550,7 @@
|
||||
delay = world.time + 10
|
||||
else if (emitter.charge < 10)
|
||||
playsound(src,'sound/machines/buzz-sigh.ogg', 50, TRUE)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/machinery/power/emitter/ctf
|
||||
name = "Energy Cannon"
|
||||
|
||||
@@ -248,30 +248,66 @@
|
||||
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
|
||||
/obj/item/gun/afterattack_secondary(mob/living/victim, mob/living/user, proximity_flag, click_parameters)
|
||||
if(!isliving(victim) || !IN_GIVEN_RANGE(user, victim, GUNPOINT_SHOOTER_STRAY_RANGE))
|
||||
return ..() //if they're out of range, just shootem.
|
||||
if(!can_hold_up)
|
||||
return ..()
|
||||
/obj/item/gun/pre_attack(atom/A, mob/living/user, params)
|
||||
. = ..()
|
||||
if(.)
|
||||
return .
|
||||
if(isnull(bayonet) || !user.combat_mode)
|
||||
return .
|
||||
return bayonet.melee_attack_chain(user, A, params)
|
||||
|
||||
/obj/item/gun/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
|
||||
if(user.combat_mode)
|
||||
return NONE
|
||||
|
||||
if(istype(tool, /obj/item/knife))
|
||||
var/obj/item/knife/new_stabber = tool
|
||||
if(!can_bayonet || !new_stabber.bayonet || !isnull(bayonet)) //ensure the gun has an attachment point available, and that the knife is compatible with it.
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(!user.transferItemToLoc(new_stabber, src))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
to_chat(user, span_notice("You attach [new_stabber] to [src]'s bayonet lug."))
|
||||
bayonet = new_stabber
|
||||
update_appearance()
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
return NONE
|
||||
|
||||
/obj/item/gun/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(user.combat_mode && isliving(interacting_with))
|
||||
return ITEM_INTERACT_SKIP_TO_ATTACK // Gun bash / bayonet attack
|
||||
if(try_fire_gun(interacting_with, user, list2params(modifiers)))
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
return NONE
|
||||
|
||||
/obj/item/gun/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!can_hold_up || !isliving(interacting_with))
|
||||
return interact_with_atom(interacting_with, user, modifiers)
|
||||
|
||||
var/datum/component/gunpoint/gunpoint_component = user.GetComponent(/datum/component/gunpoint)
|
||||
if (gunpoint_component)
|
||||
if(gunpoint_component.target == victim)
|
||||
balloon_alert(user, "already holding them up!")
|
||||
else
|
||||
balloon_alert(user, "already holding someone up!")
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
if (user == victim)
|
||||
balloon_alert(user, "already holding [gunpoint_component.target == interacting_with ? "them" : "someone"] up!")
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if (user == interacting_with)
|
||||
balloon_alert(user, "can't hold yourself up!")
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
if(do_after(user, 0.5 SECONDS, victim))
|
||||
user.AddComponent(/datum/component/gunpoint, victim, src)
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
if(do_after(user, 0.5 SECONDS, interacting_with))
|
||||
user.AddComponent(/datum/component/gunpoint, interacting_with, src)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/gun/afterattack(atom/target, mob/living/user, flag, params)
|
||||
..()
|
||||
fire_gun(target, user, flag, params)
|
||||
return AFTERATTACK_PROCESSED_ITEM
|
||||
/obj/item/gun/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(try_fire_gun(interacting_with, user, list2params(modifiers)))
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
/obj/item/gun/ranged_interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(IN_GIVEN_RANGE(user, interacting_with, GUNPOINT_SHOOTER_STRAY_RANGE))
|
||||
return interact_with_atom_secondary(interacting_with, user, modifiers)
|
||||
return ..()
|
||||
|
||||
/obj/item/gun/proc/try_fire_gun(atom/target, mob/living/user, params)
|
||||
return fire_gun(target, user, user.Adjacent(target), params)
|
||||
|
||||
/obj/item/gun/proc/fire_gun(atom/target, mob/living/user, flag, params)
|
||||
if(QDELETED(target))
|
||||
@@ -466,39 +502,6 @@
|
||||
/obj/item/gun/proc/reset_semicd()
|
||||
semicd = FALSE
|
||||
|
||||
/obj/item/gun/attack(mob/M, mob/living/user)
|
||||
if(user.combat_mode) //Flogging
|
||||
if(bayonet)
|
||||
M.attackby(bayonet, user)
|
||||
return
|
||||
else
|
||||
return ..()
|
||||
return
|
||||
|
||||
/obj/item/gun/attack_atom(obj/O, mob/living/user, params)
|
||||
if(user.combat_mode)
|
||||
if(bayonet)
|
||||
O.attackby(bayonet, user)
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/item/gun/attackby(obj/item/I, mob/living/user, params)
|
||||
if(user.combat_mode)
|
||||
return ..()
|
||||
|
||||
else if(istype(I, /obj/item/knife))
|
||||
var/obj/item/knife/K = I
|
||||
if(!can_bayonet || !K.bayonet || bayonet) //ensure the gun has an attachment point available, and that the knife is compatible with it.
|
||||
return ..()
|
||||
if(!user.transferItemToLoc(I, src))
|
||||
return
|
||||
to_chat(user, span_notice("You attach [K] to [src]'s bayonet lug."))
|
||||
bayonet = K
|
||||
update_appearance()
|
||||
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/gun/screwdriver_act(mob/living/user, obj/item/I)
|
||||
. = ..()
|
||||
if(.)
|
||||
|
||||
@@ -159,17 +159,18 @@
|
||||
underbarrel = new /obj/item/gun/ballistic/revolver/grenadelauncher/unrestricted(src)
|
||||
update_appearance()
|
||||
|
||||
/obj/item/gun/ballistic/automatic/m90/afterattack_secondary(atom/target, mob/living/user, proximity_flag, click_parameters)
|
||||
underbarrel.afterattack(target, user, proximity_flag, click_parameters)
|
||||
return SECONDARY_ATTACK_CONTINUE_CHAIN
|
||||
/obj/item/gun/ballistic/automatic/m90/try_fire_gun(atom/target, mob/living/user, params)
|
||||
if(LAZYACCESS(params2list(params), RIGHT_CLICK))
|
||||
return underbarrel.try_fire_gun(target, user, params)
|
||||
return ..()
|
||||
|
||||
/obj/item/gun/ballistic/automatic/m90/attackby(obj/item/A, mob/user, params)
|
||||
if(isammocasing(A))
|
||||
if(istype(A, underbarrel.magazine.ammo_type))
|
||||
/obj/item/gun/ballistic/automatic/m90/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
|
||||
if(isammocasing(tool))
|
||||
if(istype(tool, underbarrel.magazine.ammo_type))
|
||||
underbarrel.attack_self(user)
|
||||
underbarrel.attackby(A, user, params)
|
||||
else
|
||||
..()
|
||||
underbarrel.attackby(tool, user, list2params(modifiers))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
return ..()
|
||||
|
||||
/obj/item/gun/ballistic/automatic/tommygun
|
||||
name = "\improper Thompson SMG"
|
||||
@@ -276,15 +277,15 @@
|
||||
. += "l6_door_[cover_open ? "open" : "closed"]"
|
||||
|
||||
|
||||
/obj/item/gun/ballistic/automatic/l6_saw/afterattack(atom/target as mob|obj|turf, mob/living/user as mob|obj, flag, params)
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
|
||||
/obj/item/gun/ballistic/automatic/l6_saw/try_fire_gun(atom/target, mob/living/user, params)
|
||||
if(cover_open)
|
||||
balloon_alert(user, "close the cover!")
|
||||
return
|
||||
else
|
||||
. |= ..()
|
||||
return FALSE
|
||||
|
||||
. = ..()
|
||||
if(.)
|
||||
update_appearance()
|
||||
return .
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/item/gun/ballistic/automatic/l6_saw/attack_hand(mob/user, list/modifiers)
|
||||
|
||||
@@ -63,14 +63,13 @@
|
||||
playsound(src, 'sound/weapons/gun/bow/bow_draw.ogg', 25, TRUE)
|
||||
update_appearance()
|
||||
|
||||
/obj/item/gun/ballistic/bow/afterattack(atom/target, mob/living/user, flag, params, passthrough = FALSE)
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
/obj/item/gun/ballistic/bow/try_fire_gun(atom/target, mob/living/user, params)
|
||||
if(!chambered)
|
||||
return
|
||||
return FALSE
|
||||
if(!drawn)
|
||||
to_chat(user, span_warning("Without drawing the bow, the arrow uselessly falls to the ground."))
|
||||
drop_arrow()
|
||||
return
|
||||
return FALSE
|
||||
return ..() //fires, removing the arrow
|
||||
|
||||
/obj/item/gun/ballistic/bow/equipped(mob/user, slot, initial)
|
||||
|
||||
@@ -89,8 +89,10 @@
|
||||
This one has been fitted with a special backblast diverter to prevent 'friendly' fire 'accidents' during use."
|
||||
backblast = FALSE
|
||||
|
||||
/obj/item/gun/ballistic/rocketlauncher/afterattack()
|
||||
/obj/item/gun/ballistic/rocketlauncher/try_fire_gun(atom/target, mob/living/user, params)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
magazine.get_round(FALSE) //Hack to clear the mag after it's fired
|
||||
|
||||
/obj/item/gun/ballistic/rocketlauncher/attack_self_tk(mob/user)
|
||||
|
||||
@@ -85,21 +85,20 @@
|
||||
QDEL_NULL(underbarrel)
|
||||
return ..()
|
||||
|
||||
/obj/item/gun/ballistic/automatic/pistol/clandestine/fisher/afterattack_secondary(atom/target, mob/living/user, proximity_flag, click_parameters)
|
||||
underbarrel.afterattack(target, user, proximity_flag, click_parameters)
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
/obj/item/gun/ballistic/automatic/pistol/clandestine/fisher/try_fire_gun(atom/target, mob/living/user, params)
|
||||
if(LAZYACCESS(params2list(params), RIGHT_CLICK))
|
||||
return underbarrel.try_fire_gun(target, user, params)
|
||||
return ..()
|
||||
|
||||
/obj/item/gun/ballistic/automatic/pistol/clandestine/fisher/afterattack(atom/target, mob/living/user, flag, params)
|
||||
// mirrors what the standalone fisher does when you hit people with it
|
||||
. = ..()
|
||||
if(user.Adjacent(target))
|
||||
var/obj/projectile/energy/fisher/melee/simulated_hit = new
|
||||
simulated_hit.firer = user
|
||||
simulated_hit.on_hit(target)
|
||||
/obj/item/gun/ballistic/automatic/pistol/clandestine/fisher/afterattack(atom/target, mob/user, click_parameters)
|
||||
var/obj/projectile/energy/fisher/melee/simulated_hit = new
|
||||
simulated_hit.firer = user
|
||||
simulated_hit.on_hit(target)
|
||||
|
||||
/obj/item/gun/ballistic/automatic/pistol/clandestine/fisher/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
|
||||
// as above comment, mirrors what the standalone fisher does when you hit people with it
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
var/obj/projectile/energy/fisher/melee/simulated_hit = new
|
||||
simulated_hit.firer = throwingdatum.get_thrower()
|
||||
simulated_hit.on_hit(hit_atom)
|
||||
|
||||
@@ -218,26 +218,24 @@
|
||||
toggle_magazine()
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
|
||||
/obj/item/gun/ballistic/shotgun/bulldog/afterattack_secondary(mob/living/victim, mob/living/user, proximity_flag, click_parameters)
|
||||
/obj/item/gun/ballistic/shotgun/bulldog/ranged_interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(secondary_magazine)
|
||||
toggle_magazine()
|
||||
return SECONDARY_ATTACK_CALL_NORMAL
|
||||
return ..()
|
||||
|
||||
/obj/item/gun/ballistic/shotgun/bulldog/attackby_secondary(obj/item/weapon, mob/user, params)
|
||||
if(!istype(weapon, secondary_magazine_type))
|
||||
balloon_alert(user, "[weapon.name] doesn't fit!")
|
||||
return SECONDARY_ATTACK_CALL_NORMAL
|
||||
if(!user.transferItemToLoc(weapon, src))
|
||||
to_chat(user, span_warning("You cannot seem to get [src] out of your hands!"))
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
/obj/item/gun/ballistic/shotgun/bulldog/item_interaction_secondary(mob/living/user, obj/item/tool, list/modifiers)
|
||||
if(!istype(tool, secondary_magazine_type))
|
||||
return ..()
|
||||
if(!user.transferItemToLoc(tool, src))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
var/obj/item/ammo_box/magazine/old_mag = secondary_magazine
|
||||
secondary_magazine = weapon
|
||||
secondary_magazine = tool
|
||||
if(old_mag)
|
||||
user.put_in_hands(old_mag)
|
||||
balloon_alert(user, "secondary [magazine_wording] loaded")
|
||||
playsound(src, load_empty_sound, load_sound_volume, load_sound_vary)
|
||||
update_appearance()
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/gun/ballistic/shotgun/bulldog/click_alt_secondary(mob/user)
|
||||
if(secondary_magazine)
|
||||
@@ -338,6 +336,7 @@
|
||||
. = ..()
|
||||
. += span_notice("Right-click to shoot the hook.")
|
||||
|
||||
/obj/item/gun/ballistic/shotgun/hook/afterattack_secondary(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
hook.afterattack(target, user, proximity_flag, click_parameters)
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
/obj/item/gun/ballistic/shotgun/hook/try_fire_gun(atom/target, mob/living/user, params)
|
||||
if(LAZYACCESS(params2list(params), RIGHT_CLICK))
|
||||
return hook.try_fire_gun(target, user, params)
|
||||
return ..()
|
||||
|
||||
@@ -328,26 +328,27 @@
|
||||
sync_ammo()
|
||||
var/atom/target = source.mouse_object_ref?.resolve()
|
||||
if(target)
|
||||
INVOKE_ASYNC(src, PROC_REF(afterattack), target, source.mob, FALSE, source.mouseParams, passthrough = TRUE)
|
||||
INVOKE_ASYNC(src, PROC_REF(try_fire_gun), target, source.mob, source.mouseParams, TRUE)
|
||||
stop_aiming()
|
||||
QDEL_LIST(current_tracers)
|
||||
|
||||
/obj/item/gun/energy/beam_rifle/afterattack(atom/target, mob/living/user, flag, params, passthrough = FALSE)
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
if(flag) //It's adjacent, is the user, or is on the user's person
|
||||
/obj/item/gun/energy/beam_rifle/try_fire_gun(atom/target, mob/living/user, params, passthrough = FALSE)
|
||||
if(user.Adjacent(target)) //It's adjacent, is the user, or is on the user's person
|
||||
if(target in user.contents) //can't shoot stuff inside us.
|
||||
return
|
||||
return FALSE
|
||||
if(!ismob(target) || user.combat_mode) //melee attack
|
||||
return
|
||||
return FALSE
|
||||
if(target == user && user.zone_selected != BODY_ZONE_PRECISE_MOUTH) //so we can't shoot ourselves (unless mouth selected)
|
||||
return
|
||||
return FALSE
|
||||
if(!passthrough && (aiming_time > aiming_time_fire_threshold))
|
||||
return
|
||||
return FALSE
|
||||
if(lastfire > world.time + delay)
|
||||
return
|
||||
return FALSE
|
||||
if(!..())
|
||||
return FALSE
|
||||
lastfire = world.time
|
||||
. = ..()
|
||||
stop_aiming()
|
||||
return TRUE
|
||||
|
||||
/obj/item/gun/energy/beam_rifle/proc/sync_ammo()
|
||||
for(var/obj/item/ammo_casing/energy/beam_rifle/AC in contents)
|
||||
|
||||
@@ -149,10 +149,11 @@
|
||||
cell.give(transferred)
|
||||
|
||||
|
||||
/obj/item/gun/energy/minigun/afterattack(atom/target, mob/living/user, flag, params)
|
||||
/obj/item/gun/energy/minigun/try_fire_gun(atom/target, mob/living/user, params)
|
||||
if(!ammo_pack || ammo_pack.loc != user)
|
||||
to_chat(user, span_warning("You need the backpack power source to fire the gun!"))
|
||||
. = ..()
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/item/stock_parts/cell/minigun
|
||||
name = "gatling gun fusion core"
|
||||
|
||||
@@ -156,13 +156,13 @@
|
||||
While some would argue that this is a really terrible design choice, others argue that it is very funny to be able to shoot at light sources.<br>\
|
||||
Caveat emptor.")
|
||||
|
||||
/obj/item/gun/energy/recharge/fisher/afterattack(atom/target, mob/living/user, flag, params)
|
||||
// you should just shoot them, but in case you can't/wont
|
||||
/obj/item/gun/energy/recharge/fisher/attack(mob/living/target_mob, mob/living/user, params)
|
||||
. = ..()
|
||||
if(user.Adjacent(target))
|
||||
var/obj/projectile/energy/fisher/melee/simulated_hit = new
|
||||
simulated_hit.firer = user
|
||||
simulated_hit.on_hit(target)
|
||||
if(.)
|
||||
return
|
||||
var/obj/projectile/energy/fisher/melee/simulated_hit = new
|
||||
simulated_hit.firer = user
|
||||
simulated_hit.on_hit(target_mob)
|
||||
|
||||
/obj/item/gun/energy/recharge/fisher/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
|
||||
// ...you reeeeeally just shoot them, but in case you can't/won't
|
||||
|
||||
@@ -231,17 +231,15 @@
|
||||
if(istype(WH))
|
||||
WH.gun = WEAKREF(src)
|
||||
|
||||
/obj/item/gun/energy/wormhole_projector/afterattack(atom/target, mob/living/user, flag, params)
|
||||
if(select == AMMO_SELECT_ORANGE) //Last fired in right click mode. Switch to blue wormhole (left click).
|
||||
select_fire()
|
||||
/obj/item/gun/energy/wormhole_projector/try_fire_gun(atom/target, mob/living/user, params)
|
||||
if(LAZYACCESS(params2list(params), RIGHT_CLICK))
|
||||
if(select == AMMO_SELECT_BLUE) //Last fired in left click mode. Switch to orange wormhole (right click).
|
||||
select_fire()
|
||||
else
|
||||
if(select == AMMO_SELECT_ORANGE) //Last fired in right click mode. Switch to blue wormhole (left click).
|
||||
select_fire()
|
||||
return ..()
|
||||
|
||||
/obj/item/gun/energy/wormhole_projector/afterattack_secondary(atom/target, mob/living/user, flag, params)
|
||||
if(select == AMMO_SELECT_BLUE) //Last fired in left click mode. Switch to orange wormhole (right click).
|
||||
select_fire()
|
||||
fire_gun(target, user, flag, params)
|
||||
return SECONDARY_ATTACK_CONTINUE_CHAIN
|
||||
|
||||
/obj/item/gun/energy/wormhole_projector/proc/on_portal_destroy(obj/effect/portal/P)
|
||||
SIGNAL_HANDLER
|
||||
if(P == p_blue)
|
||||
@@ -408,13 +406,15 @@
|
||||
coin_count++
|
||||
COOLDOWN_START(src, coin_regen_cd, coin_regen_rate)
|
||||
|
||||
/obj/item/gun/energy/marksman_revolver/afterattack_secondary(atom/target, mob/living/user, params)
|
||||
if(!CAN_THEY_SEE(target, user))
|
||||
/obj/item/gun/energy/marksman_revolver/try_fire_gun(atom/target, mob/living/user, params)
|
||||
if(!LAZYACCESS(params2list(params), RIGHT_CLICK))
|
||||
return ..()
|
||||
if(!CAN_THEY_SEE(target, user))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
if(max_coins && coin_count <= 0)
|
||||
to_chat(user, span_warning("You don't have any coins right now!"))
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
if(max_coins)
|
||||
START_PROCESSING(SSobj, src)
|
||||
@@ -426,5 +426,4 @@
|
||||
var/obj/projectile/bullet/coin/new_coin = new(get_turf(user), target_turf, user)
|
||||
new_coin.preparePixelProjectile(target_turf, user)
|
||||
new_coin.fire()
|
||||
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
@@ -33,24 +33,23 @@
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/gun/magic/wand/afterattack(atom/target, mob/living/user)
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
/obj/item/gun/magic/wand/try_fire_gun(atom/target, mob/living/user, params)
|
||||
if(!charges)
|
||||
shoot_with_empty_chamber(user)
|
||||
return
|
||||
return FALSE
|
||||
if(target == user)
|
||||
if(no_den_usage)
|
||||
var/area/A = get_area(user)
|
||||
if(istype(A, /area/centcom/wizard_station))
|
||||
to_chat(user, span_warning("You know better than to violate the security of The Den, best wait until you leave to use [src]."))
|
||||
return
|
||||
else
|
||||
no_den_usage = 0
|
||||
if(no_den_usage && istype(get_area(user), /area/centcom/wizard_station))
|
||||
to_chat(user, span_warning("You know better than to violate the security of The Den, best wait until you leave to use [src]."))
|
||||
return FALSE
|
||||
zap_self(user)
|
||||
else
|
||||
. |= ..()
|
||||
update_appearance()
|
||||
. = TRUE
|
||||
|
||||
else
|
||||
. = ..()
|
||||
|
||||
if(.)
|
||||
update_appearance()
|
||||
return .
|
||||
|
||||
/obj/item/gun/magic/wand/proc/zap_self(mob/living/user)
|
||||
user.visible_message(span_danger("[user] zaps [user.p_them()]self with [src]."))
|
||||
|
||||
@@ -110,10 +110,8 @@
|
||||
update_appearance()
|
||||
return TRUE
|
||||
|
||||
/obj/item/gun/blastcannon/afterattack(atom/target, mob/user, flag, params)
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
|
||||
if((!bomb && bombcheck) || !target || (get_dist(get_turf(target), get_turf(user)) <= 2))
|
||||
/obj/item/gun/blastcannon/try_fire_gun(atom/target, mob/living/user, params)
|
||||
if((!bomb && bombcheck) || isnull(target) || (get_dist(get_turf(target), get_turf(user)) <= 2))
|
||||
return ..()
|
||||
|
||||
cached_target = WEAKREF(target)
|
||||
@@ -123,12 +121,12 @@
|
||||
span_danger("[user] points [src] at [target]!"),
|
||||
span_danger("You point [src] at [target]!")
|
||||
)
|
||||
return
|
||||
return FALSE
|
||||
|
||||
cached_firer = WEAKREF(user)
|
||||
if(!bomb)
|
||||
fire_debug(target, user, flag, params)
|
||||
return
|
||||
fire_debug(target, user, params)
|
||||
return TRUE
|
||||
|
||||
playsound(src, dry_fire_sound, 30, TRUE) // *click
|
||||
user.visible_message(
|
||||
@@ -141,8 +139,7 @@
|
||||
user.log_message("opened blastcannon transfer valve at [AREACOORD(current_turf)] while aiming at [AREACOORD(target_turf)] (target).", LOG_GAME)
|
||||
bomb.toggle_valve()
|
||||
update_appearance()
|
||||
return
|
||||
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Channels an internal explosion into a blastwave projectile.
|
||||
|
||||
@@ -37,29 +37,36 @@
|
||||
balloon_alert(user, "not enough gold")
|
||||
|
||||
// Siphon gold from a victim, recharging our gun & removing their Midas Blight debuff in the process.
|
||||
/obj/item/gun/magic/midas_hand/afterattack_secondary(mob/living/victim, mob/living/user, proximity_flag, click_parameters)
|
||||
if(!isliving(victim) || !IN_GIVEN_RANGE(user, victim, gold_suck_range))
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
if(victim == user)
|
||||
balloon_alert(user, "can't siphon from self")
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
if(!victim.reagents)
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
/obj/item/gun/magic/midas_hand/ranged_interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!isliving(interacting_with) || !IN_GIVEN_RANGE(user, interacting_with, gold_suck_range))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(interacting_with == user)
|
||||
balloon_alert(user, "can't siphon from self!")
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(!interacting_with.reagents)
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
var/gold_amount = victim.reagents.get_reagent_amount(/datum/reagent/gold, type_check = REAGENT_SUB_TYPE)
|
||||
var/gold_amount = interacting_with.reagents.get_reagent_amount(/datum/reagent/gold, type_check = REAGENT_SUB_TYPE)
|
||||
if(!gold_amount)
|
||||
balloon_alert(user, "no gold in bloodstream")
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
var/gold_beam = user.Beam(victim, icon_state="drain_gold")
|
||||
if(!do_after(user = user, delay = 1 SECONDS, target = victim, timed_action_flags = (IGNORE_USER_LOC_CHANGE | IGNORE_TARGET_LOC_CHANGE), extra_checks = CALLBACK(src, PROC_REF(check_gold_range), user, victim)))
|
||||
balloon_alert(user, "no gold in bloodstream!")
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
var/mob/living/victim = interacting_with
|
||||
var/gold_beam = user.Beam(victim, icon_state = "drain_gold")
|
||||
if(!do_after(
|
||||
user = user,
|
||||
delay = 1 SECONDS,
|
||||
target = victim,
|
||||
timed_action_flags = (IGNORE_USER_LOC_CHANGE | IGNORE_TARGET_LOC_CHANGE),
|
||||
extra_checks = CALLBACK(src, PROC_REF(check_gold_range), user, victim),
|
||||
))
|
||||
qdel(gold_beam)
|
||||
balloon_alert(user, "link broken")
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
balloon_alert(user, "link broken!")
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
handle_gold_charges(user, gold_amount)
|
||||
victim.reagents.remove_reagent(/datum/reagent/gold, gold_amount, include_subtypes = TRUE)
|
||||
victim.remove_status_effect(/datum/status_effect/midas_blight)
|
||||
qdel(gold_beam)
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
// If we botch a shot, we have to start over again by inserting gold coins into the gun. Can only be done if it has no charges or gold.
|
||||
/obj/item/gun/magic/midas_hand/attackby(obj/item/I, mob/living/user, params)
|
||||
|
||||
@@ -77,23 +77,23 @@
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/item/gun/syringe/attackby(obj/item/A, mob/user, params, show_msg = TRUE)
|
||||
if(istype(A, /obj/item/reagent_containers/syringe/bluespace))
|
||||
balloon_alert(user, "[A.name] is too big!")
|
||||
return TRUE
|
||||
if(istype(A, /obj/item/reagent_containers/syringe))
|
||||
/obj/item/gun/syringe/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
|
||||
if(istype(tool, /obj/item/reagent_containers/syringe/bluespace))
|
||||
balloon_alert(user, "[tool.name] is too big!")
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(istype(tool, /obj/item/reagent_containers/syringe))
|
||||
if(syringes.len < max_syringes)
|
||||
if(!user.transferItemToLoc(A, src))
|
||||
return FALSE
|
||||
balloon_alert(user, "[A.name] loaded")
|
||||
syringes += A
|
||||
if(!user.transferItemToLoc(tool, src))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
balloon_alert(user, "[tool.name] loaded")
|
||||
syringes += tool
|
||||
recharge_newshot()
|
||||
update_appearance()
|
||||
playsound(loc, load_sound, 40)
|
||||
return TRUE
|
||||
else
|
||||
balloon_alert(user, "it's already full!")
|
||||
return FALSE
|
||||
playsound(src, load_sound, 40)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
balloon_alert(user, "it's full!")
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
return NONE
|
||||
|
||||
/obj/item/gun/syringe/update_overlays()
|
||||
. = ..()
|
||||
@@ -158,24 +158,24 @@
|
||||
. = ..()
|
||||
chambered = new /obj/item/ammo_casing/dnainjector(src)
|
||||
|
||||
/obj/item/gun/syringe/dna/attackby(obj/item/A, mob/user, params, show_msg = TRUE)
|
||||
if(istype(A, /obj/item/dnainjector))
|
||||
var/obj/item/dnainjector/D = A
|
||||
/obj/item/gun/syringe/dna/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
|
||||
if(istype(tool, /obj/item/dnainjector))
|
||||
var/obj/item/dnainjector/D = tool
|
||||
if(D.used)
|
||||
balloon_alert(user, "[D.name] is used up!")
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(syringes.len < max_syringes)
|
||||
if(!user.transferItemToLoc(D, src))
|
||||
return FALSE
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
balloon_alert(user, "[D.name] loaded")
|
||||
syringes += D
|
||||
recharge_newshot()
|
||||
update_appearance()
|
||||
playsound(loc, load_sound, 40)
|
||||
return TRUE
|
||||
else
|
||||
balloon_alert(user, "it's already full!")
|
||||
return FALSE
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
balloon_alert(user, "it's already full!")
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
return NONE
|
||||
|
||||
/obj/item/gun/syringe/blowgun
|
||||
name = "blowgun"
|
||||
|
||||
@@ -25,32 +25,31 @@
|
||||
if(isgun(newloc))
|
||||
gun = newloc
|
||||
|
||||
/obj/item/firing_pin/afterattack(atom/target, mob/user, proximity_flag)
|
||||
. = ..()
|
||||
if(proximity_flag)
|
||||
if(isgun(target))
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
var/obj/item/gun/targeted_gun = target
|
||||
var/obj/item/firing_pin/old_pin = targeted_gun.pin
|
||||
if(old_pin?.pin_removable && (force_replace || old_pin.pin_hot_swappable))
|
||||
if(Adjacent(user))
|
||||
user.put_in_hands(old_pin)
|
||||
else
|
||||
old_pin.forceMove(targeted_gun.drop_location())
|
||||
old_pin.gun_remove(user)
|
||||
/obj/item/firing_pin/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!isgun(interacting_with))
|
||||
return NONE
|
||||
|
||||
if(!targeted_gun.pin)
|
||||
if(!user.temporarilyRemoveItemFromInventory(src))
|
||||
return .
|
||||
if(gun_insert(user, targeted_gun))
|
||||
if(old_pin)
|
||||
balloon_alert(user, "swapped firing pin")
|
||||
else
|
||||
balloon_alert(user, "inserted firing pin")
|
||||
else
|
||||
to_chat(user, span_notice("This firearm already has a firing pin installed."))
|
||||
var/obj/item/gun/targeted_gun = interacting_with
|
||||
var/obj/item/firing_pin/old_pin = targeted_gun.pin
|
||||
if(old_pin?.pin_removable && (force_replace || old_pin.pin_hot_swappable))
|
||||
if(Adjacent(user))
|
||||
user.put_in_hands(old_pin)
|
||||
else
|
||||
old_pin.forceMove(targeted_gun.drop_location())
|
||||
old_pin.gun_remove(user)
|
||||
|
||||
if(!targeted_gun.pin)
|
||||
if(!user.temporarilyRemoveItemFromInventory(src))
|
||||
return .
|
||||
if(gun_insert(user, targeted_gun))
|
||||
if(old_pin)
|
||||
balloon_alert(user, "swapped firing pin")
|
||||
else
|
||||
balloon_alert(user, "inserted firing pin")
|
||||
else
|
||||
to_chat(user, span_notice("This firearm already has a firing pin installed."))
|
||||
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/firing_pin/emag_act(mob/user, obj/item/card/emag/emag_card)
|
||||
if(obj_flags & EMAGGED)
|
||||
@@ -190,13 +189,15 @@
|
||||
fail_message = "dna check failed!"
|
||||
var/unique_enzymes = null
|
||||
|
||||
/obj/item/firing_pin/dna/afterattack(atom/target, mob/user, proximity_flag)
|
||||
. = ..()
|
||||
if(proximity_flag && iscarbon(target))
|
||||
var/mob/living/carbon/M = target
|
||||
/obj/item/firing_pin/dna/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(iscarbon(interacting_with))
|
||||
var/mob/living/carbon/M = interacting_with
|
||||
if(M.dna && M.dna.unique_enzymes)
|
||||
unique_enzymes = M.dna.unique_enzymes
|
||||
balloon_alert(user, "dna lock set")
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
return ..()
|
||||
|
||||
/obj/item/firing_pin/dna/pin_auth(mob/living/carbon/user)
|
||||
if(user && user.dna && user.dna.unique_enzymes)
|
||||
|
||||
@@ -78,20 +78,20 @@
|
||||
///If the paper was used, and therefore cannot change color again
|
||||
var/used = FALSE
|
||||
|
||||
/obj/item/ph_paper/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
if(!is_reagent_container(target))
|
||||
return
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
var/obj/item/reagent_containers/cont = target
|
||||
if(used == TRUE)
|
||||
to_chat(user, span_warning("[src] has already been used!"))
|
||||
/obj/item/ph_paper/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!is_reagent_container(interacting_with))
|
||||
return
|
||||
var/obj/item/reagent_containers/cont = interacting_with
|
||||
if(!LAZYLEN(cont.reagents.reagent_list))
|
||||
return
|
||||
return NONE
|
||||
if(used)
|
||||
to_chat(user, span_warning("[src] has already been used!"))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
CONVERT_PH_TO_COLOR(round(cont.reagents.ph, 1), color)
|
||||
desc += " The paper looks to be around a pH of [round(cont.reagents.ph, 1)]"
|
||||
name = "used [name]"
|
||||
used = TRUE
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/*
|
||||
* pH meter that will give a detailed or truncated analysis of all the reagents in of an object with a reagents datum attached to it. Only way of detecting purity for now.
|
||||
@@ -113,18 +113,16 @@
|
||||
to_chat(user, span_notice("You switch the chemical analyzer to not include reagent descriptions in it's report."))
|
||||
scanmode = SHORTENED_CHEM_OUTPUT
|
||||
|
||||
/obj/item/ph_meter/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(!is_reagent_container(target))
|
||||
return
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
var/obj/item/reagent_containers/cont = target
|
||||
if(LAZYLEN(cont.reagents.reagent_list) == null)
|
||||
return
|
||||
/obj/item/ph_meter/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!is_reagent_container(interacting_with))
|
||||
return NONE
|
||||
var/obj/item/reagent_containers/cont = interacting_with
|
||||
if(!LAZYLEN(cont.reagents.reagent_list))
|
||||
return NONE
|
||||
var/list/out_message = list()
|
||||
to_chat(user, "<i>The chemistry meter beeps and displays:</i>")
|
||||
out_message += "<span class='notice'><b>Total volume: [round(cont.volume, 0.01)] Current temperature: [round(cont.reagents.chem_temp, 0.1)]K Total pH: [round(cont.reagents.ph, 0.01)]\n"
|
||||
out_message += "Chemicals found in [target.name]:</b>\n"
|
||||
out_message += "Chemicals found in [interacting_with.name]:</b>\n"
|
||||
if(cont.reagents.is_reacting)
|
||||
out_message += "[span_warning("A reaction appears to be occuring currently.")]<span class='notice'>\n"
|
||||
for(var/datum/reagent/reagent in cont.reagents.reagent_list)
|
||||
@@ -137,6 +135,7 @@
|
||||
out_message += "<b>Analysis:</b> [reagent.description]\n"
|
||||
to_chat(user, "[out_message.Join()]</span>")
|
||||
desc = "An electrode attached to a small circuit box that will display details of a solution. Can be toggled to provide a description of each of the reagents. The screen currently displays detected vol: [round(cont.volume, 0.01)] detected pH:[round(cont.reagents.ph, 0.1)]."
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/burner
|
||||
name = "burner"
|
||||
@@ -187,24 +186,25 @@
|
||||
set_lit(TRUE)
|
||||
user.visible_message(span_notice("[user] lights up the [src]."))
|
||||
|
||||
/obj/item/burner/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(lit)
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
if(is_reagent_container(target))
|
||||
var/obj/item/reagent_containers/container = target
|
||||
container.reagents.expose_temperature(get_temperature())
|
||||
to_chat(user, span_notice("You heat up the [src]."))
|
||||
playsound(user.loc, 'sound/chemistry/heatdam.ogg', 50, TRUE)
|
||||
return .
|
||||
else if(isitem(target))
|
||||
var/obj/item/item = target
|
||||
if(item.heat > 1000)
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
set_lit(TRUE)
|
||||
user.visible_message(span_notice("[user] lights up the [src]."))
|
||||
/obj/item/burner/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!lit)
|
||||
return NONE
|
||||
|
||||
return .
|
||||
if(is_reagent_container(interacting_with))
|
||||
var/obj/item/reagent_containers/container = interacting_with
|
||||
container.reagents.expose_temperature(get_temperature())
|
||||
user.visible_message(span_notice("[user] heats up [src]."), span_notice("You heat up [src]."))
|
||||
playsound(user, 'sound/chemistry/heatdam.ogg', 50, TRUE)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
else if(isitem(interacting_with))
|
||||
var/obj/item/item = interacting_with
|
||||
if(item.get_temperature() > 1000)
|
||||
set_lit(TRUE)
|
||||
user.visible_message(span_notice("[user] lights up [src]."), span_notice("You light up [src]."))
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
/obj/item/burner/update_icon_state()
|
||||
. = ..()
|
||||
@@ -281,7 +281,7 @@
|
||||
|
||||
/obj/item/thermometer
|
||||
name = "thermometer"
|
||||
desc = "A thermometer for checking a beaker's temperature"
|
||||
desc = "A thermometer for checking a something's temperature."
|
||||
icon_state = "thermometer"
|
||||
icon = 'icons/obj/medical/chemical.dmi'
|
||||
item_flags = NOBLUDGEON
|
||||
@@ -291,19 +291,18 @@
|
||||
var/datum/reagents/attached_to_reagents
|
||||
|
||||
/obj/item/thermometer/Destroy()
|
||||
QDEL_NULL(attached_to_reagents) //I have no idea how you can destroy this, but not the beaker, but here we go
|
||||
attached_to_reagents = null
|
||||
return ..()
|
||||
|
||||
/obj/item/thermometer/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
if(target.reagents)
|
||||
if(!user.transferItemToLoc(src, target))
|
||||
return .
|
||||
attached_to_reagents = target.reagents
|
||||
to_chat(user, span_notice("You add the [src] to the [target]."))
|
||||
ui_interact(usr, null)
|
||||
return .
|
||||
/obj/item/thermometer/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(isnull(interacting_with.reagents))
|
||||
return NONE
|
||||
if(!user.transferItemToLoc(src, interacting_with))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
attached_to_reagents = interacting_with.reagents
|
||||
to_chat(user, span_notice("You add the [src] to [interacting_with]."))
|
||||
ui_interact(user)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/thermometer/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
@@ -316,7 +315,7 @@
|
||||
INVOKE_ASYNC(src, PROC_REF(remove_thermometer), user)
|
||||
|
||||
/obj/item/thermometer/ui_status(mob/user, datum/ui_state/state)
|
||||
if(!(in_range(src, user)))
|
||||
if(!in_range(src, user))
|
||||
return UI_CLOSE
|
||||
return UI_INTERACTIVE
|
||||
|
||||
@@ -326,7 +325,9 @@
|
||||
/obj/item/thermometer/ui_data(mob/user)
|
||||
if(!attached_to_reagents)
|
||||
ui_close(user)
|
||||
var/data = list()
|
||||
return
|
||||
|
||||
var/list/data = list()
|
||||
data["Temperature"] = round(attached_to_reagents.chem_temp)
|
||||
return data
|
||||
|
||||
@@ -335,8 +336,8 @@
|
||||
attached_to_reagents = null
|
||||
|
||||
/obj/item/thermometer/proc/try_put_in_hand(obj/object, mob/living/user)
|
||||
to_chat(user, span_notice("You remove the [src] from the [attached_to_reagents.my_atom]."))
|
||||
if(!issilicon(user) && in_range(src.loc, user))
|
||||
to_chat(user, span_notice("You remove the [src] from [attached_to_reagents.my_atom]."))
|
||||
if(!issilicon(user) && in_range(loc, user))
|
||||
user.put_in_hands(object)
|
||||
else
|
||||
object.forceMove(drop_location())
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
if(!QDELETED(beaker))
|
||||
if(istype(held_item, /obj/item/reagent_containers/dropper) || istype(held_item, /obj/item/reagent_containers/syringe))
|
||||
var/obj/item/reagent_containers/injector = held_item
|
||||
injector.afterattack(beaker, user, proximity_flag = TRUE)
|
||||
injector.interact_with_atom(beaker, user, modifiers)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
if(is_reagent_container(held_item) && held_item.is_open_container())
|
||||
|
||||
@@ -87,9 +87,9 @@
|
||||
return ..()
|
||||
var/list/modifiers = params2list(params)
|
||||
if(istype(held_item, /obj/item/reagent_containers/syringe) && LAZYACCESS(modifiers, RIGHT_CLICK))
|
||||
held_item.afterattack_secondary(beaker, user, Adjacent(user), params)
|
||||
held_item.interact_with_atom_secondary(beaker, user)
|
||||
else
|
||||
held_item.afterattack(beaker, user, Adjacent(user), params)
|
||||
held_item.interact_with_atom(beaker, user)
|
||||
SStgui.update_uis(src)
|
||||
return TRUE
|
||||
|
||||
|
||||
@@ -66,34 +66,33 @@
|
||||
playsound(M.loc,'sound/items/drink.ogg', rand(10,50), TRUE)
|
||||
return TRUE
|
||||
|
||||
/obj/item/reagent_containers/condiment/afterattack(obj/target, mob/user , proximity)
|
||||
. = ..()
|
||||
if(!proximity)
|
||||
return
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
/obj/item/reagent_containers/condiment/interact_with_atom(atom/target, mob/living/user, list/modifiers)
|
||||
if(istype(target, /obj/structure/reagent_dispensers)) //A dispenser. Transfer FROM it TO us.
|
||||
|
||||
if(!target.reagents.total_volume)
|
||||
to_chat(user, span_warning("[target] is empty!"))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
if(reagents.total_volume >= reagents.maximum_volume)
|
||||
to_chat(user, span_warning("[src] is full!"))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this, transferred_by = user)
|
||||
to_chat(user, span_notice("You fill [src] with [trans] units of the contents of [target]."))
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
//Something like a glass or a food item. Player probably wants to transfer TO it.
|
||||
else if(target.is_drainable() || IS_EDIBLE(target))
|
||||
if(!reagents.total_volume)
|
||||
to_chat(user, span_warning("[src] is empty!"))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(target.reagents.total_volume >= target.reagents.maximum_volume)
|
||||
to_chat(user, span_warning("you can't add anymore to [target]!"))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
var/trans = src.reagents.trans_to(target, amount_per_transfer_from_this, transferred_by = user)
|
||||
to_chat(user, span_notice("You transfer [trans] units of the condiment to [target]."))
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
return NONE
|
||||
|
||||
/obj/item/reagent_containers/condiment/enzyme
|
||||
name = "universal enzyme"
|
||||
@@ -149,11 +148,10 @@
|
||||
desc = "Salt. From dead crew, presumably."
|
||||
return TOXLOSS
|
||||
|
||||
/obj/item/reagent_containers/condiment/saltshaker/afterattack(obj/target, mob/living/user, proximity)
|
||||
/obj/item/reagent_containers/condiment/saltshaker/interact_with_atom(atom/target, mob/living/user, list/modifiers)
|
||||
. = ..()
|
||||
if(!proximity)
|
||||
return
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
if(. & ITEM_INTERACT_ANY_BLOCKER)
|
||||
return .
|
||||
if(isturf(target))
|
||||
if(!reagents.has_reagent(/datum/reagent/consumable/salt, 2))
|
||||
to_chat(user, span_warning("You don't have enough salt to make a pile!"))
|
||||
@@ -161,7 +159,8 @@
|
||||
user.visible_message(span_notice("[user] shakes some salt onto [target]."), span_notice("You shake some salt onto [target]."))
|
||||
reagents.remove_reagent(/datum/reagent/consumable/salt, 2)
|
||||
new/obj/effect/decal/cleanable/food/salt(target)
|
||||
return
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
return .
|
||||
|
||||
/obj/item/reagent_containers/condiment/peppermill
|
||||
name = "pepper mill"
|
||||
@@ -441,26 +440,22 @@
|
||||
/obj/item/reagent_containers/condiment/pack/attack(mob/M, mob/user, def_zone) //Can't feed these to people directly.
|
||||
return
|
||||
|
||||
/obj/item/reagent_containers/condiment/pack/afterattack(obj/target, mob/user , proximity)
|
||||
if(!proximity)
|
||||
return
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
/obj/item/reagent_containers/condiment/pack/interact_with_atom(atom/target, mob/living/user, list/modifiers)
|
||||
//You can tear the bag open above food to put the condiments on it, obviously.
|
||||
if(IS_EDIBLE(target))
|
||||
if(!reagents.total_volume)
|
||||
to_chat(user, span_warning("You tear open [src], but there's nothing in it."))
|
||||
qdel(src)
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(target.reagents.total_volume >= target.reagents.maximum_volume)
|
||||
to_chat(user, span_warning("You tear open [src], but [target] is stacked so high that it just drips off!") )
|
||||
qdel(src)
|
||||
return
|
||||
else
|
||||
to_chat(user, span_notice("You tear open [src] above [target] and the condiments drip onto it."))
|
||||
src.reagents.trans_to(target, amount_per_transfer_from_this, transferred_by = user)
|
||||
qdel(src)
|
||||
return
|
||||
return . | ..()
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
to_chat(user, span_notice("You tear open [src] above [target] and the condiments drip onto it."))
|
||||
src.reagents.trans_to(target, amount_per_transfer_from_this, transferred_by = user)
|
||||
qdel(src)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
return ..()
|
||||
|
||||
/// Handles reagents getting added to the condiment pack.
|
||||
/obj/item/reagent_containers/condiment/pack/proc/on_reagent_add(datum/reagents/reagents)
|
||||
|
||||
@@ -101,68 +101,66 @@
|
||||
if(LAZYLEN(diseases_to_add))
|
||||
AddComponent(/datum/component/infective, diseases_to_add)
|
||||
|
||||
/obj/item/reagent_containers/cup/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(!proximity_flag)
|
||||
return
|
||||
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
|
||||
/obj/item/reagent_containers/cup/interact_with_atom(atom/target, mob/living/user, list/modifiers)
|
||||
if(!check_allowed_items(target, target_self = TRUE))
|
||||
return
|
||||
|
||||
return NONE
|
||||
if(!spillable)
|
||||
return
|
||||
return NONE
|
||||
|
||||
if(target.is_refillable()) //Something like a glass. Player probably wants to transfer TO it.
|
||||
if(!reagents.total_volume)
|
||||
to_chat(user, span_warning("[src] is empty!"))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
if(target.reagents.holder_full())
|
||||
to_chat(user, span_warning("[target] is full."))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
var/trans = reagents.trans_to(target, amount_per_transfer_from_this, transferred_by = user)
|
||||
to_chat(user, span_notice("You transfer [trans] unit\s of the solution to [target]."))
|
||||
SEND_SIGNAL(src, COMSIG_REAGENTS_CUP_TRANSFER_TO, target)
|
||||
target.update_appearance()
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
else if(target.is_drainable()) //A dispenser. Transfer FROM it TO us.
|
||||
if(target.is_drainable()) //A dispenser. Transfer FROM it TO us.
|
||||
if(!target.reagents.total_volume)
|
||||
to_chat(user, span_warning("[target] is empty and can't be refilled!"))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
if(reagents.holder_full())
|
||||
to_chat(user, span_warning("[src] is full."))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this, transferred_by = user)
|
||||
to_chat(user, span_notice("You fill [src] with [trans] unit\s of the contents of [target]."))
|
||||
SEND_SIGNAL(src, COMSIG_REAGENTS_CUP_TRANSFER_FROM, target)
|
||||
target.update_appearance()
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/reagent_containers/cup/afterattack_secondary(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
if((!proximity_flag) || !check_allowed_items(target, target_self = TRUE))
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
return NONE
|
||||
|
||||
/obj/item/reagent_containers/cup/interact_with_atom_secondary(atom/target, mob/living/user, list/modifiers)
|
||||
if(user.combat_mode)
|
||||
return ITEM_INTERACT_SKIP_TO_ATTACK
|
||||
if(!check_allowed_items(target, target_self = TRUE))
|
||||
return NONE
|
||||
if(!spillable)
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
if(target.is_drainable()) //A dispenser. Transfer FROM it TO us.
|
||||
if(!target.reagents.total_volume)
|
||||
to_chat(user, span_warning("[target] is empty!"))
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
if(reagents.holder_full())
|
||||
to_chat(user, span_warning("[src] is full."))
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this, transferred_by = user)
|
||||
to_chat(user, span_notice("You fill [src] with [trans] unit\s of the contents of [target]."))
|
||||
|
||||
target.update_appearance()
|
||||
return SECONDARY_ATTACK_CONTINUE_CHAIN
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/reagent_containers/cup/attackby(obj/item/attacking_item, mob/user, params)
|
||||
var/hotness = attacking_item.get_temperature()
|
||||
|
||||
@@ -291,20 +291,18 @@
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/reagent_containers/cup/glass/waterbottle/afterattack(obj/target, mob/living/user, proximity)
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
|
||||
/obj/item/reagent_containers/cup/glass/waterbottle/interact_with_atom(atom/target, mob/living/user, list/modifiers)
|
||||
if(cap_on && (target.is_refillable() || target.is_drainable() || (reagents.total_volume && !user.combat_mode)))
|
||||
to_chat(user, span_warning("You must remove the cap before you can do that!"))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
else if(istype(target, /obj/item/reagent_containers/cup/glass/waterbottle))
|
||||
if(istype(target, /obj/item/reagent_containers/cup/glass/waterbottle))
|
||||
var/obj/item/reagent_containers/cup/glass/waterbottle/other_bottle = target
|
||||
if(other_bottle.cap_on)
|
||||
to_chat(user, span_warning("[other_bottle] has a cap firmly twisted on!"))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
return . | ..()
|
||||
return ..()
|
||||
|
||||
// heehoo bottle flipping
|
||||
/obj/item/reagent_containers/cup/glass/waterbottle/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
|
||||
|
||||
@@ -11,22 +11,18 @@
|
||||
reagent_flags = TRANSPARENT
|
||||
custom_price = PAYCHECK_CREW
|
||||
|
||||
/obj/item/reagent_containers/dropper/afterattack(obj/target, mob/user , proximity)
|
||||
. = ..()
|
||||
if(!proximity)
|
||||
return
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
/obj/item/reagent_containers/dropper/interact_with_atom(atom/target, mob/living/user, list/modifiers)
|
||||
if(!target.reagents)
|
||||
return
|
||||
return NONE
|
||||
|
||||
if(reagents.total_volume > 0)
|
||||
if(target.reagents.holder_full())
|
||||
to_chat(user, span_notice("[target] is full."))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
if(!target.is_injectable(user))
|
||||
to_chat(user, span_warning("You cannot transfer reagents to [target]!"))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
var/trans = 0
|
||||
var/fraction = min(amount_per_transfer_from_this / reagents.total_volume, 1)
|
||||
@@ -48,10 +44,10 @@
|
||||
|
||||
to_chat(user, span_notice("You transfer [trans] unit\s of the solution."))
|
||||
update_appearance()
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
else if(isalien(target)) //hiss-hiss has no eyes!
|
||||
to_chat(target, span_danger("[target] does not seem to have any eyes!"))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
target.visible_message(span_danger("[user] squirts something into [target]'s eyes!"), \
|
||||
span_userdanger("[user] squirts something into your eyes!"))
|
||||
@@ -69,23 +65,23 @@
|
||||
to_chat(user, span_notice("You transfer [trans] unit\s of the solution."))
|
||||
update_appearance()
|
||||
target.update_appearance()
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
else
|
||||
if(!target.is_drawable(user, FALSE)) //No drawing from mobs here
|
||||
to_chat(user, span_warning("You cannot directly remove reagents from [target]!"))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
if(!target.is_drawable(user, FALSE)) //No drawing from mobs here
|
||||
to_chat(user, span_warning("You cannot directly remove reagents from [target]!"))
|
||||
return
|
||||
if(!target.reagents.total_volume)
|
||||
to_chat(user, span_warning("[target] is empty!"))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
if(!target.reagents.total_volume)
|
||||
to_chat(user, span_warning("[target] is empty!"))
|
||||
return
|
||||
var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this, transferred_by = user)
|
||||
|
||||
var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this, transferred_by = user)
|
||||
to_chat(user, span_notice("You fill [src] with [trans] unit\s of the solution."))
|
||||
|
||||
to_chat(user, span_notice("You fill [src] with [trans] unit\s of the solution."))
|
||||
|
||||
update_appearance()
|
||||
target.update_appearance()
|
||||
update_appearance()
|
||||
target.update_appearance()
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/reagent_containers/dropper/update_overlays()
|
||||
. = ..()
|
||||
|
||||
@@ -137,15 +137,13 @@
|
||||
user.visible_message(span_suicide("[user] is smothering [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit suicide!"))
|
||||
return OXYLOSS
|
||||
|
||||
/obj/item/reagent_containers/cup/rag/afterattack(atom/target, mob/living/user, proximity_flag, click_parameters)
|
||||
if(!proximity_flag)
|
||||
return
|
||||
if(!iscarbon(target) || !reagents?.total_volume)
|
||||
/obj/item/reagent_containers/cup/rag/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!iscarbon(interacting_with) || !reagents?.total_volume)
|
||||
return ..()
|
||||
var/mob/living/carbon/carbon_target = target
|
||||
var/mob/living/carbon/carbon_target = interacting_with
|
||||
var/reagentlist = pretty_string_from_reagent_list(reagents.reagent_list)
|
||||
var/log_object = "containing [reagentlist]"
|
||||
if(user.combat_mode && !carbon_target.is_mouth_covered())
|
||||
if(!carbon_target.is_mouth_covered())
|
||||
reagents.trans_to(carbon_target, reagents.total_volume, transferred_by = user, methods = INGEST)
|
||||
carbon_target.visible_message(span_danger("[user] smothers \the [carbon_target] with \the [src]!"), span_userdanger("[user] smothers you with \the [src]!"), span_hear("You hear some struggling and muffled cries of surprise."))
|
||||
log_combat(user, carbon_target, "smothered", src, log_object)
|
||||
@@ -154,7 +152,12 @@
|
||||
reagents.clear_reagents()
|
||||
carbon_target.visible_message(span_notice("[user] touches \the [carbon_target] with \the [src]."))
|
||||
log_combat(user, carbon_target, "touched", src, log_object)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
///Checks whether or not we should clean.
|
||||
/obj/item/reagent_containers/cup/rag/proc/should_clean(datum/cleaning_source, atom/atom_to_clean, mob/living/cleaner)
|
||||
return (src in cleaner)
|
||||
if(cleaner.combat_mode && ismob(atom_to_clean))
|
||||
return CLEAN_BLOCKED|CLEAN_DONT_BLOCK_INTERACTION
|
||||
if(loc == cleaner)
|
||||
return CLEAN_ALLOWED
|
||||
return CLEAN_ALLOWED|CLEAN_NO_XP
|
||||
|
||||
@@ -59,24 +59,20 @@
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/item/reagent_containers/pill/afterattack(obj/target, mob/user , proximity)
|
||||
. = ..()
|
||||
if(!proximity)
|
||||
return
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
/obj/item/reagent_containers/pill/interact_with_atom(atom/target, mob/living/user, list/modifiers)
|
||||
if(!dissolvable || !target.is_refillable())
|
||||
return
|
||||
return NONE
|
||||
if(target.is_drainable() && !target.reagents.total_volume)
|
||||
to_chat(user, span_warning("[target] is empty! There's nothing to dissolve [src] in."))
|
||||
return
|
||||
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(target.reagents.holder_full())
|
||||
to_chat(user, span_warning("[target] is full."))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
user.visible_message(span_warning("[user] slips something into [target]!"), span_notice("You dissolve [src] in [target]."), null, 2)
|
||||
reagents.trans_to(target, reagents.total_volume, transferred_by = user)
|
||||
qdel(src)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/*
|
||||
* On accidental consumption, consume the pill
|
||||
|
||||
@@ -26,31 +26,38 @@
|
||||
possible_transfer_amounts = list(5,10)
|
||||
var/spray_sound = 'sound/effects/spray2.ogg'
|
||||
|
||||
/obj/item/reagent_containers/spray/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(istype(target, /obj/structure/sink) || istype(target, /obj/structure/mop_bucket/janitorialcart) || istype(target, /obj/machinery/hydroponics))
|
||||
return
|
||||
/obj/item/reagent_containers/spray/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
return try_spray(interacting_with, user) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_BLOCKING
|
||||
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
/obj/item/reagent_containers/spray/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
// This is a hack to make spray bottles fillable from / transferable to these sources
|
||||
// However it can be completely removed when these objects are updated to use the new interaction system
|
||||
// (because the desired effect will just work out of the box)
|
||||
if(istype(interacting_with, /obj/structure/sink) || istype(interacting_with, /obj/structure/mop_bucket/janitorialcart) || istype(interacting_with, /obj/machinery/hydroponics))
|
||||
return NONE
|
||||
|
||||
if((target.is_drainable() && !target.is_refillable()) && (get_dist(src, target) <= 1) && can_fill_from_container)
|
||||
return try_spray(interacting_with, user) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_BLOCKING
|
||||
|
||||
/obj/item/reagent_containers/spray/proc/try_spray(atom/target, mob/user)
|
||||
var/adjacent = user.Adjacent(target)
|
||||
if((target.is_drainable() && !target.is_refillable()) && adjacent && can_fill_from_container)
|
||||
if(!target.reagents.total_volume)
|
||||
to_chat(user, span_warning("[target] is empty."))
|
||||
return
|
||||
return FALSE
|
||||
|
||||
if(reagents.holder_full())
|
||||
to_chat(user, span_warning("[src] is full."))
|
||||
return
|
||||
return FALSE
|
||||
|
||||
var/trans = target.reagents.trans_to(src, 50, transferred_by = user) //transfer 50u , using the spray's transfer amount would take too long to refill
|
||||
to_chat(user, span_notice("You fill \the [src] with [trans] units of the contents of \the [target]."))
|
||||
return
|
||||
return FALSE
|
||||
|
||||
if(reagents.total_volume < amount_per_transfer_from_this)
|
||||
to_chat(user, span_warning("Not enough left!"))
|
||||
return
|
||||
return FALSE
|
||||
|
||||
if(proximity_flag && (target.density || ismob(target)))
|
||||
if(adjacent && (target.density || ismob(target)))
|
||||
// If we're spraying an adjacent mob or a dense object, we start the spray on ITS tile rather than OURs
|
||||
// This is so we can use a spray bottle to clean stuff like windows without getting blocked by passflags
|
||||
spray(target, user, get_turf(target))
|
||||
@@ -58,9 +65,9 @@
|
||||
spray(target, user)
|
||||
|
||||
playsound(src, spray_sound, 50, TRUE, -6)
|
||||
user.changeNext_move(CLICK_CD_RANGE*2)
|
||||
user.changeNext_move(CLICK_CD_RANGE * 2)
|
||||
user.newtonian_move(get_dir(target, user))
|
||||
return
|
||||
return TRUE
|
||||
|
||||
/// Handles creating a chem puff that travels towards the target atom, exposing reagents to everything it hits on the way.
|
||||
/obj/item/reagent_containers/spray/proc/spray(atom/target, mob/user, turf/start_turf = get_turf(src))
|
||||
@@ -232,10 +239,10 @@
|
||||
return OXYLOSS
|
||||
|
||||
// Fix pepperspraying yourself
|
||||
/obj/item/reagent_containers/spray/pepper/afterattack(atom/A as mob|obj, mob/user)
|
||||
if (A.loc == user)
|
||||
return
|
||||
return ..() | AFTERATTACK_PROCESSED_ITEM
|
||||
/obj/item/reagent_containers/spray/pepper/try_spray(atom/target, mob/user)
|
||||
if (target.loc == user)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
//water flower
|
||||
/obj/item/reagent_containers/spray/waterflower
|
||||
@@ -320,11 +327,10 @@
|
||||
amount_per_transfer_from_this = 10
|
||||
volume = 600
|
||||
|
||||
/obj/item/reagent_containers/spray/chemsprayer/afterattack(atom/A as mob|obj, mob/user)
|
||||
// Make it so the bioterror spray doesn't spray yourself when you click your inventory items
|
||||
if (A.loc == user)
|
||||
return
|
||||
return ..() | AFTERATTACK_PROCESSED_ITEM
|
||||
/obj/item/reagent_containers/spray/chemsprayer/try_spray(atom/target, mob/user)
|
||||
if (target.loc == user)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/item/reagent_containers/spray/chemsprayer/spray(atom/A, mob/user)
|
||||
var/direction = get_dir(src, A)
|
||||
|
||||
@@ -25,9 +25,7 @@
|
||||
/obj/item/reagent_containers/syringe/attackby(obj/item/I, mob/user, params)
|
||||
return
|
||||
|
||||
/obj/item/reagent_containers/syringe/proc/try_syringe(atom/target, mob/user, proximity)
|
||||
if(!proximity)
|
||||
return FALSE
|
||||
/obj/item/reagent_containers/syringe/proc/try_syringe(atom/target, mob/user)
|
||||
if(!target.reagents)
|
||||
return FALSE
|
||||
|
||||
@@ -36,49 +34,50 @@
|
||||
if(!living_target.try_inject(user, injection_flags = INJECT_TRY_SHOW_ERROR_MESSAGE|inject_flags))
|
||||
return FALSE
|
||||
|
||||
// chance of monkey retaliation
|
||||
SEND_SIGNAL(target, COMSIG_LIVING_TRY_SYRINGE, user)
|
||||
return TRUE
|
||||
|
||||
/obj/item/reagent_containers/syringe/afterattack(atom/target, mob/user, proximity)
|
||||
. = ..()
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
/obj/item/reagent_containers/syringe/interact_with_atom(atom/target, mob/living/user, list/modifiers)
|
||||
if(!target.reagents)
|
||||
return NONE
|
||||
if(!try_syringe(target, user))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
if (!try_syringe(target, user, proximity))
|
||||
return
|
||||
SEND_SIGNAL(target, COMSIG_LIVING_TRY_SYRINGE_INJECT, user)
|
||||
|
||||
var/contained = reagents.get_reagent_log_string()
|
||||
log_combat(user, target, "attempted to inject", src, addition="which had [contained]")
|
||||
|
||||
if(!reagents.total_volume)
|
||||
to_chat(user, span_warning("[src] is empty! Right-click to draw."))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
if(!isliving(target) && !target.is_injectable(user))
|
||||
to_chat(user, span_warning("You cannot directly fill [target]!"))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
if(target.reagents.total_volume >= target.reagents.maximum_volume)
|
||||
to_chat(user, span_notice("[target] is full."))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
if(isliving(target))
|
||||
var/mob/living/living_target = target
|
||||
if(!living_target.try_inject(user, injection_flags = INJECT_TRY_SHOW_ERROR_MESSAGE|inject_flags))
|
||||
return
|
||||
if(living_target != user)
|
||||
living_target.visible_message(span_danger("[user] is trying to inject [living_target]!"), \
|
||||
span_userdanger("[user] is trying to inject you!"))
|
||||
if(!do_after(user, CHEM_INTERACT_DELAY(3 SECONDS, user), living_target, extra_checks = CALLBACK(living_target, TYPE_PROC_REF(/mob/living, try_inject), user, null, INJECT_TRY_SHOW_ERROR_MESSAGE|inject_flags)))
|
||||
return
|
||||
living_target.visible_message(
|
||||
span_danger("[user] is trying to inject [living_target]!"),
|
||||
span_userdanger("[user] is trying to inject you!"),
|
||||
)
|
||||
if(!do_after(user, CHEM_INTERACT_DELAY(3 SECONDS, user), living_target, extra_checks = CALLBACK(src, PROC_REF(try_syringe), living_target, user)))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(!reagents.total_volume)
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(living_target.reagents.total_volume >= living_target.reagents.maximum_volume)
|
||||
return
|
||||
living_target.visible_message(span_danger("[user] injects [living_target] with the syringe!"), \
|
||||
span_userdanger("[user] injects you with the syringe!"))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
living_target.visible_message(
|
||||
span_danger("[user] injects [living_target] with the syringe!"),
|
||||
span_userdanger("[user] injects you with the syringe!"),
|
||||
)
|
||||
|
||||
if (living_target == user)
|
||||
if(living_target == user)
|
||||
living_target.log_message("injected themselves ([contained]) with [name]", LOG_ATTACK, color="orange")
|
||||
else
|
||||
log_combat(user, living_target, "injected", src, addition="which had [contained]")
|
||||
@@ -86,44 +85,53 @@
|
||||
if(reagents.trans_to(target, amount_per_transfer_from_this, transferred_by = user, methods = INJECT))
|
||||
to_chat(user, span_notice("You inject [amount_per_transfer_from_this] units of the solution. The syringe now contains [reagents.total_volume] units."))
|
||||
target.update_appearance()
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/reagent_containers/syringe/afterattack_secondary(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
if (!try_syringe(target, user, proximity_flag))
|
||||
return SECONDARY_ATTACK_CONTINUE_CHAIN
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
/obj/item/reagent_containers/syringe/interact_with_atom_secondary(atom/target, mob/living/user, list/modifiers)
|
||||
if (!target.reagents)
|
||||
return NONE
|
||||
if (!try_syringe(target, user))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
SEND_SIGNAL(target, COMSIG_LIVING_TRY_SYRINGE_WITHDRAW, user)
|
||||
|
||||
if(reagents.total_volume >= reagents.maximum_volume)
|
||||
to_chat(user, span_notice("[src] is full."))
|
||||
return SECONDARY_ATTACK_CONTINUE_CHAIN
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
if(isliving(target))
|
||||
var/mob/living/living_target = target
|
||||
var/drawn_amount = reagents.maximum_volume - reagents.total_volume
|
||||
if(target != user)
|
||||
target.visible_message(span_danger("[user] is trying to take a blood sample from [target]!"), \
|
||||
span_userdanger("[user] is trying to take a blood sample from you!"))
|
||||
if(!do_after(user, CHEM_INTERACT_DELAY(3 SECONDS, user), target, extra_checks = CALLBACK(living_target, TYPE_PROC_REF(/mob/living, try_inject), user, null, INJECT_TRY_SHOW_ERROR_MESSAGE|inject_flags)))
|
||||
return SECONDARY_ATTACK_CONTINUE_CHAIN
|
||||
target.visible_message(
|
||||
span_danger("[user] is trying to take a blood sample from [target]!"),
|
||||
span_userdanger("[user] is trying to take a blood sample from you!"),
|
||||
)
|
||||
if(!do_after(user, CHEM_INTERACT_DELAY(3 SECONDS, user), target, extra_checks = CALLBACK(src, PROC_REF(try_syringe), living_target, user)))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(reagents.total_volume >= reagents.maximum_volume)
|
||||
return SECONDARY_ATTACK_CONTINUE_CHAIN
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(living_target.transfer_blood_to(src, drawn_amount))
|
||||
user.visible_message(span_notice("[user] takes a blood sample from [living_target]."))
|
||||
else
|
||||
to_chat(user, span_warning("You are unable to draw any blood from [living_target]!"))
|
||||
else
|
||||
if(!target.reagents.total_volume)
|
||||
to_chat(user, span_warning("[target] is empty!"))
|
||||
return SECONDARY_ATTACK_CONTINUE_CHAIN
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
if(!target.is_drawable(user))
|
||||
to_chat(user, span_warning("You cannot directly remove reagents from [target]!"))
|
||||
return SECONDARY_ATTACK_CONTINUE_CHAIN
|
||||
if(!target.reagents.total_volume)
|
||||
to_chat(user, span_warning("[target] is empty!"))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this, transferred_by = user) // transfer from, transfer to - who cares?
|
||||
if(!target.is_drawable(user))
|
||||
to_chat(user, span_warning("You cannot directly remove reagents from [target]!"))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
to_chat(user, span_notice("You fill [src] with [trans] units of the solution. It now contains [reagents.total_volume] units."))
|
||||
target.update_appearance()
|
||||
var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this, transferred_by = user) // transfer from, transfer to - who cares?
|
||||
|
||||
return SECONDARY_ATTACK_CONTINUE_CHAIN
|
||||
to_chat(user, span_notice("You fill [src] with [trans] units of the solution. It now contains [reagents.total_volume] units."))
|
||||
target.update_appearance()
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/*
|
||||
* On accidental consumption, inject the eater with 2/3rd of the syringe and reveal it
|
||||
|
||||
@@ -543,10 +543,9 @@ GLOBAL_LIST_EMPTY(conveyors_by_id)
|
||||
belt.id = id
|
||||
to_chat(user, span_notice("You have linked all nearby conveyor belt assemblies to this switch."))
|
||||
|
||||
/obj/item/conveyor_switch_construct/afterattack(atom/target, mob/user, proximity)
|
||||
. = ..()
|
||||
if(!proximity || user.stat || !isfloorturf(target) || istype(target, /area/shuttle))
|
||||
return
|
||||
/obj/item/conveyor_switch_construct/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!isfloorturf(interacting_with))
|
||||
return NONE
|
||||
|
||||
var/found = FALSE
|
||||
for(var/obj/machinery/conveyor/belt in view())
|
||||
@@ -555,10 +554,11 @@ GLOBAL_LIST_EMPTY(conveyors_by_id)
|
||||
break
|
||||
if(!found)
|
||||
to_chat(user, "[icon2html(src, user)]" + span_notice("The conveyor switch did not detect any linked conveyor belts in range."))
|
||||
return
|
||||
var/obj/machinery/conveyor_switch/built_switch = new/obj/machinery/conveyor_switch(target, id)
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
var/obj/machinery/conveyor_switch/built_switch = new/obj/machinery/conveyor_switch(interacting_with, id)
|
||||
transfer_fingerprints_to(built_switch)
|
||||
qdel(src)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/stack/conveyor
|
||||
name = "conveyor belt assembly"
|
||||
@@ -576,17 +576,17 @@ GLOBAL_LIST_EMPTY(conveyors_by_id)
|
||||
. = ..()
|
||||
id = _id
|
||||
|
||||
/obj/item/stack/conveyor/afterattack(atom/target, mob/user, proximity)
|
||||
. = ..()
|
||||
if(!proximity || user.stat || !isfloorturf(target) || istype(target, /area/shuttle))
|
||||
return
|
||||
var/belt_dir = get_dir(target, user)
|
||||
if(target == user.loc)
|
||||
/obj/item/stack/conveyor/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!isfloorturf(interacting_with))
|
||||
return NONE
|
||||
var/belt_dir = get_dir(interacting_with, user)
|
||||
if(interacting_with == user.loc)
|
||||
to_chat(user, span_warning("You cannot place a conveyor belt under yourself!"))
|
||||
return
|
||||
var/obj/machinery/conveyor/belt = new/obj/machinery/conveyor(target, belt_dir, id)
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
var/obj/machinery/conveyor/belt = new/obj/machinery/conveyor(interacting_with, belt_dir, id)
|
||||
transfer_fingerprints_to(belt)
|
||||
use(1)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/stack/conveyor/attackby(obj/item/item_used, mob/user, params)
|
||||
..()
|
||||
|
||||
@@ -252,7 +252,7 @@
|
||||
|
||||
unwrap_contents()
|
||||
post_unwrap_contents(user)
|
||||
return COMPONENT_CANCEL_ATTACK_CHAIN
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
/obj/item/dest_tagger
|
||||
name = "destination tagger"
|
||||
|
||||
@@ -37,19 +37,24 @@ If you create T5+ please take a pass at mech_fabricator.dm. The parts being good
|
||||
user.Beam(attacked_machinery, icon_state = "rped_upgrade", time = 0.5 SECONDS)
|
||||
return TRUE
|
||||
|
||||
/obj/item/storage/part_replacer/afterattack(obj/attacked_object, mob/living/user, adjacent, params)
|
||||
. = ..()
|
||||
if(!works_from_distance || adjacent) // Adjacent things = already handled by pre-attack
|
||||
return .
|
||||
/obj/item/storage/part_replacer/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(part_replace_action(interacting_with, user))
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
return NONE
|
||||
|
||||
if(part_replace_action(attacked_object, user))
|
||||
user.Beam(attacked_object, icon_state = "rped_upgrade", time = 0.5 SECONDS)
|
||||
return . | AFTERATTACK_PROCESSED_ITEM
|
||||
|
||||
if(istype(attacked_object, /obj/structure/frame))
|
||||
attacked_object.item_interaction(user, src) // Cursed snowflake but we need to handle frame ranged interaction here
|
||||
user.Beam(attacked_object, icon_state = "rped_upgrade", time = 0.5 SECONDS)
|
||||
return . | AFTERATTACK_PROCESSED_ITEM
|
||||
/obj/item/storage/part_replacer/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!works_from_distance)
|
||||
return NONE
|
||||
if(part_replace_action(interacting_with, user))
|
||||
user.Beam(interacting_with, icon_state = "rped_upgrade", time = 0.5 SECONDS)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
if(istype(interacting_with, /obj/structure/frame))
|
||||
// Cursed snowflake but we need to handle frame ranged interaction here
|
||||
// Likely no longer necessary with the new framework, revisit later
|
||||
interacting_with.item_interaction(user, src)
|
||||
user.Beam(interacting_with, icon_state = "rped_upgrade", time = 0.5 SECONDS)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
return NONE
|
||||
|
||||
/obj/item/storage/part_replacer/proc/play_rped_sound()
|
||||
//Plays the sound for RPED exhanging or installing parts.
|
||||
|
||||
@@ -52,11 +52,10 @@ Slimecrossing Items
|
||||
ret[part.body_zone] = saved_part
|
||||
return ret
|
||||
|
||||
/obj/item/camera/rewind/afterattack(atom/target, mob/user, flag)
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
|
||||
if(!on || !pictures_left || !isturf(target.loc))
|
||||
return .
|
||||
/obj/item/camera/rewind/photo_taken(atom/target, mob/user)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
|
||||
if(user == target)
|
||||
to_chat(user, span_notice("You take a selfie!"))
|
||||
@@ -66,9 +65,6 @@ Slimecrossing Items
|
||||
to_chat(target, span_boldnotice("You'll remember this moment forever!"))
|
||||
|
||||
target.AddComponent(/datum/component/dejavu, 2)
|
||||
return . | ..()
|
||||
|
||||
|
||||
|
||||
//Timefreeze camera - Old Burning Sepia result. Kept in case admins want to spawn it
|
||||
/obj/item/camera/timefreeze
|
||||
@@ -77,13 +73,11 @@ Slimecrossing Items
|
||||
pictures_left = 1
|
||||
pictures_max = 1
|
||||
|
||||
/obj/item/camera/timefreeze/afterattack(atom/target, mob/user, flag)
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
|
||||
if(!on || !pictures_left || !isturf(target.loc))
|
||||
return .
|
||||
/obj/item/camera/timefreeze/photo_taken(atom/target, mob/user)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
new /obj/effect/timestop(get_turf(target), 2, 50, list(user))
|
||||
return . | ..()
|
||||
|
||||
//Hypercharged slime cell - Charged Yellow
|
||||
/obj/item/stock_parts/cell/high/slime_hypercharged
|
||||
|
||||
@@ -11,27 +11,25 @@ Slimecrossing Potions
|
||||
icon = 'icons/obj/medical/chemical.dmi'
|
||||
icon_state = "potpurple"
|
||||
|
||||
/obj/item/slimepotion/extract_cloner/afterattack(obj/item/target, mob/user , proximity)
|
||||
if(!proximity)
|
||||
return
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
if(is_reagent_container(target))
|
||||
return ..(target, user, proximity)
|
||||
if(istype(target, /obj/item/slimecross))
|
||||
to_chat(user, span_warning("[target] is too complex for the potion to clone!"))
|
||||
return
|
||||
if(!istype(target, /obj/item/slime_extract))
|
||||
return
|
||||
var/obj/item/slime_extract/S = target
|
||||
/obj/item/slimepotion/extract_cloner/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
. = ..()
|
||||
if(. & ITEM_INTERACT_ANY_BLOCKER)
|
||||
return .
|
||||
if(istype(interacting_with, /obj/item/slimecross))
|
||||
to_chat(user, span_warning("[interacting_with] is too complex for the potion to clone!"))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(!istype(interacting_with, /obj/item/slime_extract))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
var/obj/item/slime_extract/S = interacting_with
|
||||
if(S.recurring)
|
||||
to_chat(user, span_warning("[target] is too complex for the potion to clone!"))
|
||||
return
|
||||
to_chat(user, span_warning("[interacting_with] is too complex for the potion to clone!"))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
var/path = S.type
|
||||
var/obj/item/slime_extract/C = new path(get_turf(target))
|
||||
var/obj/item/slime_extract/C = new path(get_turf(interacting_with))
|
||||
C.extract_uses = S.extract_uses
|
||||
to_chat(user, span_notice("You pour the potion onto [target], and the fluid solidifies into a copy of it!"))
|
||||
to_chat(user, span_notice("You pour the potion onto [interacting_with], and the fluid solidifies into a copy of it!"))
|
||||
qdel(src)
|
||||
return
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
//Peace potion - Charged Light Pink
|
||||
/obj/item/slimepotion/peacepotion
|
||||
@@ -107,34 +105,34 @@ Slimecrossing Potions
|
||||
icon_state = "potblue"
|
||||
var/uses = 2
|
||||
|
||||
/obj/item/slimepotion/spaceproof/afterattack(obj/item/clothing/C, mob/user, proximity)
|
||||
/obj/item/slimepotion/spaceproof/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
. = ..()
|
||||
if(!uses)
|
||||
if(. & ITEM_INTERACT_ANY_BLOCKER)
|
||||
return .
|
||||
if(uses <= 0)
|
||||
qdel(src)
|
||||
return
|
||||
if(!proximity)
|
||||
return
|
||||
if(!istype(C))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
var/obj/item/clothing/clothing = interacting_with
|
||||
if(!istype(clothing))
|
||||
to_chat(user, span_warning("The potion can only be used on clothing!"))
|
||||
return
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
if(istype(C, /obj/item/clothing/suit/space))
|
||||
to_chat(user, span_warning("The [C] is already pressure-resistant!"))
|
||||
return . | ..()
|
||||
if(C.min_cold_protection_temperature == SPACE_SUIT_MIN_TEMP_PROTECT && C.clothing_flags & STOPSPRESSUREDAMAGE)
|
||||
to_chat(user, span_warning("The [C] is already pressure-resistant!"))
|
||||
return . | ..()
|
||||
to_chat(user, span_notice("You slather the blue gunk over the [C], making it airtight."))
|
||||
C.name = "pressure-resistant [C.name]"
|
||||
C.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
|
||||
C.add_atom_colour(COLOR_NAVY, FIXED_COLOUR_PRIORITY)
|
||||
C.min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT
|
||||
C.cold_protection = C.body_parts_covered
|
||||
C.clothing_flags |= STOPSPRESSUREDAMAGE
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(istype(clothing, /obj/item/clothing/suit/space))
|
||||
to_chat(user, span_warning("The [interacting_with] is already pressure-resistant!"))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(clothing.min_cold_protection_temperature == SPACE_SUIT_MIN_TEMP_PROTECT && (clothing.clothing_flags & STOPSPRESSUREDAMAGE))
|
||||
to_chat(user, span_warning("The [interacting_with] is already pressure-resistant!"))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
to_chat(user, span_notice("You slather the blue gunk over the [clothing], making it airtight."))
|
||||
clothing.name = "pressure-resistant [clothing.name]"
|
||||
clothing.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
|
||||
clothing.add_atom_colour(COLOR_NAVY, FIXED_COLOUR_PRIORITY)
|
||||
clothing.min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT
|
||||
clothing.cold_protection = clothing.body_parts_covered
|
||||
clothing.clothing_flags |= STOPSPRESSUREDAMAGE
|
||||
uses--
|
||||
if(!uses)
|
||||
if(uses <= 0)
|
||||
qdel(src)
|
||||
return .
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
//Enhancer potion - Charged Cerulean
|
||||
/obj/item/slimepotion/enhancer/max
|
||||
@@ -152,29 +150,30 @@ Slimecrossing Potions
|
||||
resistance_flags = LAVA_PROOF | FIRE_PROOF
|
||||
var/uses = 2
|
||||
|
||||
/obj/item/slimepotion/lavaproof/afterattack(obj/item/C, mob/user, proximity)
|
||||
/obj/item/slimepotion/lavaproof/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
. = ..()
|
||||
if(!uses)
|
||||
if(. & ITEM_INTERACT_ANY_BLOCKER)
|
||||
return .
|
||||
if(uses <= 0)
|
||||
qdel(src)
|
||||
return ..()
|
||||
if(!proximity)
|
||||
return ..()
|
||||
if(!istype(C))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(!isitem(interacting_with))
|
||||
to_chat(user, span_warning("You can't coat this with lavaproofing fluid!"))
|
||||
return ..()
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
to_chat(user, span_notice("You slather the red gunk over the [C], making it lavaproof."))
|
||||
C.name = "lavaproof [C.name]"
|
||||
C.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
|
||||
C.add_atom_colour(COLOR_MAROON, FIXED_COLOUR_PRIORITY)
|
||||
C.resistance_flags |= LAVA_PROOF
|
||||
if (isclothing(C))
|
||||
var/obj/item/clothing/CL = C
|
||||
CL.clothing_flags |= LAVAPROTECT
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
var/obj/item/clothing = interacting_with
|
||||
to_chat(user, span_notice("You slather the red gunk over the [clothing], making it lavaproof."))
|
||||
clothing.name = "lavaproof [clothing.name]"
|
||||
clothing.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
|
||||
clothing.add_atom_colour(COLOR_MAROON, FIXED_COLOUR_PRIORITY)
|
||||
clothing.resistance_flags |= LAVA_PROOF
|
||||
if (isclothing(clothing))
|
||||
var/obj/item/clothing/clothing_real = clothing
|
||||
clothing_real.clothing_flags |= LAVAPROTECT
|
||||
uses--
|
||||
if(!uses)
|
||||
if(uses <= 0)
|
||||
qdel(src)
|
||||
return .
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
//Revival potion - Charged Grey
|
||||
/obj/item/slimepotion/slime_reviver
|
||||
@@ -183,15 +182,21 @@ Slimecrossing Potions
|
||||
icon = 'icons/obj/medical/chemical.dmi'
|
||||
icon_state = "potsilver"
|
||||
|
||||
/obj/item/slimepotion/slime_reviver/attack(mob/living/basic/slime/revive_target, mob/user)
|
||||
/obj/item/slimepotion/slime_reviver/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
. = ..()
|
||||
if(. & ITEM_INTERACT_ANY_BLOCKER)
|
||||
return .
|
||||
var/mob/living/basic/slime/revive_target = interacting_with
|
||||
if(!isslime(revive_target))
|
||||
to_chat(user, span_warning("The potion only works on slimes!"))
|
||||
return ..()
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(revive_target.stat != DEAD)
|
||||
to_chat(user, span_warning("The slime is still alive!"))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(revive_target.maxHealth <= 0)
|
||||
to_chat(user, span_warning("The slime is too unstable to return!"))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
user.do_attack_animation(interacting_with)
|
||||
revive_target.revive(HEAL_ALL)
|
||||
revive_target.set_stat(CONSCIOUS)
|
||||
revive_target.visible_message(span_notice("[revive_target] is filled with renewed vigor and blinks awake!"))
|
||||
@@ -199,6 +204,7 @@ Slimecrossing Potions
|
||||
revive_target.health -= 10
|
||||
revive_target.regenerate_icons()
|
||||
qdel(src)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
//Stabilizer potion - Charged Blue
|
||||
/obj/item/slimepotion/slime/chargedstabilizer
|
||||
|
||||
@@ -1079,7 +1079,7 @@
|
||||
var/obj/item/slimecross/stabilized/rainbow/X = linked_extract
|
||||
if(istype(X))
|
||||
if(X.regencore)
|
||||
X.regencore.afterattack(owner,owner,TRUE)
|
||||
X.regencore.interact_with_atom(owner, owner)
|
||||
X.regencore = null
|
||||
owner.visible_message(span_warning("[owner] flashes a rainbow of colors, and [owner.p_their()] skin is coated in a milky regenerative goo!"))
|
||||
qdel(src)
|
||||
|
||||
@@ -27,8 +27,8 @@ Slimecrossing Weapons
|
||||
throwforce = 15
|
||||
damtype = BRUTE
|
||||
|
||||
/obj/item/knife/rainbowknife/afterattack(atom/O, mob/user, proximity)
|
||||
if(proximity && isliving(O))
|
||||
/obj/item/knife/rainbowknife/afterattack(atom/target, mob/user, params)
|
||||
if(isliving(target))
|
||||
damtype = pick(BRUTE, BURN, TOX, OXY)
|
||||
switch(damtype)
|
||||
if(BRUTE)
|
||||
@@ -47,7 +47,6 @@ Slimecrossing Weapons
|
||||
hitsound = 'sound/effects/space_wind.ogg'
|
||||
attack_verb_continuous = string_list(list("suffocates", "winds", "vacuums"))
|
||||
attack_verb_simple = string_list(list("suffocate", "wind", "vacuum"))
|
||||
return ..()
|
||||
|
||||
//Adamantine shield - Chilling Adamantine
|
||||
/obj/item/shield/adamantineshield
|
||||
|
||||
@@ -151,19 +151,20 @@ Chilling extracts:
|
||||
var/list/allies = list()
|
||||
var/active = FALSE
|
||||
|
||||
/obj/item/slimecross/chilling/bluespace/afterattack(atom/target, mob/user, proximity)
|
||||
if(!proximity || !isliving(target) || active)
|
||||
return
|
||||
if(HAS_TRAIT(target, TRAIT_NO_TELEPORT))
|
||||
to_chat(user, span_warning("[target] resists being linked with [src]!"))
|
||||
return
|
||||
if(target in allies)
|
||||
allies -= target
|
||||
to_chat(user, span_notice("You unlink [src] with [target]."))
|
||||
/obj/item/slimecross/chilling/bluespace/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!isliving(interacting_with) || active)
|
||||
return NONE
|
||||
user.do_attack_animation(interacting_with)
|
||||
if(HAS_TRAIT(interacting_with, TRAIT_NO_TELEPORT))
|
||||
to_chat(user, span_warning("[interacting_with] resists being linked with [src]!"))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(interacting_with in allies)
|
||||
allies -= interacting_with
|
||||
to_chat(user, span_notice("You unlink [src] with [interacting_with]."))
|
||||
else
|
||||
allies |= target
|
||||
to_chat(user, span_notice("You link [src] with [target]."))
|
||||
return
|
||||
allies += interacting_with
|
||||
to_chat(user, span_notice("You link [src] with [interacting_with]."))
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/slimecross/chilling/bluespace/do_effect(mob/user)
|
||||
if(allies.len <= 0)
|
||||
@@ -193,16 +194,17 @@ Chilling extracts:
|
||||
effect_desc = "Touching someone with it adds/removes them from a list. Activating the extract stops time for 30 seconds, and everyone on the list is immune, except the user."
|
||||
var/list/allies = list()
|
||||
|
||||
/obj/item/slimecross/chilling/sepia/afterattack(atom/target, mob/user, proximity)
|
||||
if(!proximity || !isliving(target))
|
||||
return
|
||||
if(target in allies)
|
||||
allies -= target
|
||||
to_chat(user, span_notice("You unlink [src] with [target]."))
|
||||
/obj/item/slimecross/chilling/sepia/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!isliving(interacting_with))
|
||||
return NONE
|
||||
user.do_attack_animation(interacting_with)
|
||||
if(interacting_with in allies)
|
||||
allies -= interacting_with
|
||||
to_chat(user, span_notice("You unlink [src] with [interacting_with]."))
|
||||
else
|
||||
allies |= target
|
||||
to_chat(user, span_notice("You link [src] with [target]."))
|
||||
return
|
||||
allies += interacting_with
|
||||
to_chat(user, span_notice("You link [src] with [interacting_with]."))
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/slimecross/chilling/sepia/do_effect(mob/user)
|
||||
user.visible_message(span_warning("[src] shatters, freezing time itself!"))
|
||||
|
||||
@@ -10,25 +10,25 @@ Prismatic extracts:
|
||||
icon_state = "prismatic"
|
||||
var/paintcolor = COLOR_WHITE
|
||||
|
||||
/obj/item/slimecross/prismatic/afterattack(turf/target, mob/user, proximity)
|
||||
if(!proximity)
|
||||
return
|
||||
if(!istype(target) || isspaceturf(target))
|
||||
return
|
||||
target.add_atom_colour(paintcolor, WASHABLE_COLOUR_PRIORITY)
|
||||
playsound(target, 'sound/effects/slosh.ogg', 20, TRUE)
|
||||
/obj/item/slimecross/prismatic/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!isturf(interacting_with) || isspaceturf(interacting_with))
|
||||
return NONE
|
||||
user.do_attack_animation(interacting_with)
|
||||
interacting_with.add_atom_colour(paintcolor, WASHABLE_COLOUR_PRIORITY)
|
||||
playsound(interacting_with, 'sound/effects/slosh.ogg', 20, TRUE)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/slimecross/prismatic/grey/
|
||||
/obj/item/slimecross/prismatic/grey
|
||||
colour = SLIME_TYPE_GREY
|
||||
desc = "It's constantly wet with a pungent-smelling, clear chemical."
|
||||
|
||||
/obj/item/slimecross/prismatic/grey/afterattack(turf/target, mob/user, proximity)
|
||||
. = ..()
|
||||
if(!proximity)
|
||||
return
|
||||
if(istype(target) && target.color != initial(target.color))
|
||||
target.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
|
||||
playsound(target, 'sound/effects/slosh.ogg', 20, TRUE)
|
||||
/obj/item/slimecross/prismatic/grey/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(isturf(interacting_with) && interacting_with.color != initial(interacting_with.color))
|
||||
user.do_attack_animation(interacting_with)
|
||||
interacting_with.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
|
||||
playsound(interacting_with, 'sound/effects/slosh.ogg', 20, TRUE)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
return ..()
|
||||
|
||||
/obj/item/slimecross/prismatic/orange
|
||||
paintcolor = "#FFA500"
|
||||
|
||||
@@ -14,14 +14,13 @@ Regenerative extracts:
|
||||
/obj/item/slimecross/regenerative/proc/core_effect_before(mob/living/carbon/human/target, mob/user)
|
||||
return
|
||||
|
||||
/obj/item/slimecross/regenerative/afterattack(atom/target,mob/user,prox)
|
||||
. = ..()
|
||||
if(!prox || !isliving(target))
|
||||
/obj/item/slimecross/regenerative/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(!isliving(interacting_with))
|
||||
return
|
||||
var/mob/living/H = target
|
||||
var/mob/living/H = interacting_with
|
||||
if(H.stat == DEAD)
|
||||
to_chat(user, span_warning("[src] will not work on the dead!"))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(H != user)
|
||||
user.visible_message(span_notice("[user] crushes [src] over [H], the milky goo quickly regenerating all of [H.p_their()] injuries!"),
|
||||
span_notice("You squeeze [src], and it bursts over [H], the milky goo regenerating [H.p_their()] injuries."))
|
||||
@@ -29,10 +28,12 @@ Regenerative extracts:
|
||||
user.visible_message(span_notice("[user] crushes [src] over [user.p_them()]self, the milky goo quickly regenerating all of [user.p_their()] injuries!"),
|
||||
span_notice("You squeeze [src], and it bursts in your hand, splashing you with milky goo which quickly regenerates your injuries!"))
|
||||
core_effect_before(H, user)
|
||||
user.do_attack_animation(interacting_with)
|
||||
H.revive(HEAL_ALL)
|
||||
core_effect(H, user)
|
||||
playsound(target, 'sound/effects/splat.ogg', 40, TRUE)
|
||||
playsound(H, 'sound/effects/splat.ogg', 40, TRUE)
|
||||
qdel(src)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/slimecross/regenerative/grey
|
||||
colour = SLIME_TYPE_GREY //Has no bonus effect.
|
||||
|
||||
@@ -644,13 +644,12 @@
|
||||
desc = "A hard yet gelatinous capsule excreted by a slime, containing mysterious substances."
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
|
||||
/obj/item/slimepotion/afterattack(obj/item/reagent_containers/target, mob/user , proximity)
|
||||
. = ..()
|
||||
if(!proximity)
|
||||
return
|
||||
if (istype(target))
|
||||
to_chat(user, span_warning("You cannot transfer [src] to [target]! It appears the potion must be given directly to a slime to absorb.") )
|
||||
return
|
||||
/obj/item/slimepotion/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
if(is_reagent_container(interacting_with))
|
||||
to_chat(user, span_warning("You cannot transfer [src] to [interacting_with]! \
|
||||
It appears the potion must be given directly to a slime to absorb.") )
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
return NONE
|
||||
|
||||
/obj/item/slimepotion/slime/docility
|
||||
name = "docility potion"
|
||||
@@ -778,33 +777,36 @@
|
||||
var/prompted = 0
|
||||
var/animal_type = SENTIENCE_ORGANIC
|
||||
|
||||
/obj/item/slimepotion/transference/afterattack(mob/living/switchy_mob, mob/living/user, proximity)
|
||||
if(!proximity)
|
||||
return
|
||||
/obj/item/slimepotion/transference/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
. = ..()
|
||||
if(. & ITEM_INTERACT_ANY_BLOCKER)
|
||||
return .
|
||||
var/mob/living/switchy_mob = interacting_with
|
||||
if(prompted || !isliving(switchy_mob))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(switchy_mob.ckey) //much like sentience, these will not work on something that is already player controlled
|
||||
balloon_alert(user, "already sentient!")
|
||||
return ..()
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(switchy_mob.stat)
|
||||
balloon_alert(user, "it's dead!")
|
||||
return ..()
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(!switchy_mob.compare_sentience_type(animal_type))
|
||||
balloon_alert(user, "invalid creature!")
|
||||
return ..()
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
var/job_banned = is_banned_from(user.ckey, ROLE_MIND_TRANSFER)
|
||||
if(QDELETED(src) || QDELETED(switchy_mob) || QDELETED(user))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
if(job_banned)
|
||||
balloon_alert(user, "you're banned!")
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
user.do_attack_animation(interacting_with)
|
||||
prompted = 1
|
||||
if(tgui_alert(usr,"This will permanently transfer your consciousness to [switchy_mob]. Are you sure you want to do this?",,list("Yes","No")) == "No")
|
||||
prompted = 0
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
to_chat(user, span_notice("You drink the potion then place your hands on [switchy_mob]..."))
|
||||
|
||||
@@ -820,6 +822,7 @@
|
||||
if(isanimal(switchy_mob))
|
||||
var/mob/living/simple_animal/switchy_animal= switchy_mob
|
||||
switchy_animal.sentience_act()
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/slimepotion/slime/steroid
|
||||
name = "slime steroid"
|
||||
@@ -903,29 +906,29 @@
|
||||
icon = 'icons/obj/medical/chemical.dmi'
|
||||
icon_state = "potyellow"
|
||||
|
||||
/obj/item/slimepotion/speed/afterattack(obj/C, mob/user, proximity)
|
||||
/obj/item/slimepotion/speed/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
. = ..()
|
||||
if(!proximity)
|
||||
return
|
||||
if(!istype(C))
|
||||
if(. & ITEM_INTERACT_ANY_BLOCKER)
|
||||
return .
|
||||
if(!isobj(interacting_with))
|
||||
to_chat(user, span_warning("The potion can only be used on objects!"))
|
||||
return
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
if(SEND_SIGNAL(C, COMSIG_SPEED_POTION_APPLIED, src, user) & SPEED_POTION_STOP)
|
||||
return
|
||||
if(isitem(C))
|
||||
var/obj/item/I = C
|
||||
if(I.slowdown <= 0 || (I.item_flags & IMMUTABLE_SLOW))
|
||||
to_chat(user, span_warning("The [C] can't be made any faster!"))
|
||||
return ..()
|
||||
I.slowdown = 0
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(SEND_SIGNAL(interacting_with, COMSIG_SPEED_POTION_APPLIED, src, user) & SPEED_POTION_STOP)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
if(isitem(interacting_with))
|
||||
var/obj/item/apply_to = interacting_with
|
||||
if(apply_to.slowdown <= 0 || (apply_to.item_flags & IMMUTABLE_SLOW))
|
||||
to_chat(user, span_warning("The [apply_to] can't be made any faster!"))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
apply_to.slowdown = 0
|
||||
|
||||
to_chat(user, span_notice("You slather the red gunk over the [C], making it faster."))
|
||||
C.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
|
||||
C.add_atom_colour(COLOR_RED, FIXED_COLOUR_PRIORITY)
|
||||
to_chat(user, span_notice("You slather the red gunk over the [interacting_with], making it faster."))
|
||||
interacting_with.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
|
||||
interacting_with.add_atom_colour(COLOR_RED, FIXED_COLOUR_PRIORITY)
|
||||
qdel(src)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/slimepotion/speed/attackby_storage_insert(datum/storage, atom/storage_holder, mob/user)
|
||||
/obj/item/slimepotion/speed/storage_insert_on_interaction(datum/storage, atom/storage_holder, mob/user)
|
||||
if(!isitem(storage_holder))
|
||||
return TRUE
|
||||
if(istype(storage_holder, /obj/item/mod/control))
|
||||
@@ -942,20 +945,20 @@
|
||||
resistance_flags = FIRE_PROOF
|
||||
var/uses = 3
|
||||
|
||||
/obj/item/slimepotion/fireproof/afterattack(obj/item/clothing/clothing, mob/user, proximity)
|
||||
/obj/item/slimepotion/fireproof/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
||||
. = ..()
|
||||
if(!proximity)
|
||||
return
|
||||
if(!uses)
|
||||
if(. & ITEM_INTERACT_ANY_BLOCKER)
|
||||
return .
|
||||
if(uses <= 0)
|
||||
qdel(src)
|
||||
return
|
||||
. |= AFTERATTACK_PROCESSED_ITEM
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
var/obj/item/clothing/clothing = interacting_with
|
||||
if(!istype(clothing))
|
||||
to_chat(user, span_warning("The potion can only be used on clothing!"))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(clothing.max_heat_protection_temperature >= FIRE_IMMUNITY_MAX_TEMP_PROTECT)
|
||||
to_chat(user, span_warning("The [clothing] is already fireproof!"))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
to_chat(user, span_notice("You slather the blue gunk over the [clothing], fireproofing it."))
|
||||
clothing.name = "fireproofed [clothing.name]"
|
||||
clothing.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
|
||||
@@ -964,8 +967,9 @@
|
||||
clothing.heat_protection = clothing.body_parts_covered
|
||||
clothing.resistance_flags |= FIRE_PROOF
|
||||
uses --
|
||||
if(!uses)
|
||||
if(uses <= 0)
|
||||
qdel(src)
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
/obj/item/slimepotion/genderchange
|
||||
name = "gender change potion"
|
||||
@@ -1080,4 +1084,3 @@
|
||||
max_amount = 60
|
||||
turf_type = /turf/open/floor/sepia
|
||||
merge_type = /obj/item/stack/tile/sepia
|
||||
|
||||
|
||||
@@ -797,14 +797,8 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/item/storage/pod, 32)
|
||||
new /obj/item/bodybag/environmental(src)
|
||||
new /obj/item/bodybag/environmental(src)
|
||||
|
||||
/obj/item/storage/pod/attackby(obj/item/W, mob/user, params)
|
||||
if (can_interact(user))
|
||||
return ..()
|
||||
|
||||
/obj/item/storage/pod/attackby_secondary(obj/item/weapon, mob/user, params)
|
||||
if (!can_interact(user))
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
return ..()
|
||||
/obj/item/storage/pod/storage_insert_on_interacted_with(datum/storage, obj/item/inserted, mob/living/user)
|
||||
return can_interact(user)
|
||||
|
||||
/obj/item/storage/pod/attack_hand(mob/user, list/modifiers)
|
||||
if (can_interact(user))
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
RegisterSignal(enchanted, COMSIG_ITEM_DROPPED, PROC_REF(on_dropped))
|
||||
|
||||
/// signal called from attacking with the enchanted item
|
||||
/datum/action/cooldown/spell/sanguine_strike/proc/on_enchanted_afterattack(obj/item/enchanted, atom/target, mob/user, proximity_flag, click_parameters)
|
||||
/datum/action/cooldown/spell/sanguine_strike/proc/on_enchanted_afterattack(obj/item/enchanted, atom/target, mob/user, click_parameters)
|
||||
SIGNAL_HANDLER
|
||||
end_enchantment(enchanted)
|
||||
if(!isliving(target))
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user