diff --git a/_maps/RandomRuins/SpaceRuins/forgottenship.dmm b/_maps/RandomRuins/SpaceRuins/forgottenship.dmm index 09658a8b869..ad75f7c046f 100644 --- a/_maps/RandomRuins/SpaceRuins/forgottenship.dmm +++ b/_maps/RandomRuins/SpaceRuins/forgottenship.dmm @@ -514,7 +514,7 @@ /obj/structure/closet/crate/secure/gear{ req_one_access_txt = "150" }, -/obj/item/melee/transforming/energy/sword/saber/red, +/obj/item/melee/energy/sword/saber/red, /obj/machinery/light/directional/north, /turf/open/floor/pod/dark, /area/ruin/space/has_grav/powered/syndicate_forgotten_vault) diff --git a/_maps/RandomZLevels/spacebattle.dmm b/_maps/RandomZLevels/spacebattle.dmm index f5a5cb88306..8fb1d3dc2ca 100644 --- a/_maps/RandomZLevels/spacebattle.dmm +++ b/_maps/RandomZLevels/spacebattle.dmm @@ -291,7 +291,7 @@ /area/awaymission/spacebattle/syndicate3) "bt" = ( /obj/structure/table/reinforced, -/obj/item/melee/transforming/energy/sword/saber/red, +/obj/item/melee/energy/sword/saber/red, /turf/open/floor/mineral/plastitanium/red, /area/awaymission/spacebattle/syndicate1) "bu" = ( @@ -1152,7 +1152,7 @@ /area/awaymission/spacebattle/cruiser) "eW" = ( /obj/effect/mob_spawn/human/syndicatesoldier, -/obj/item/melee/transforming/energy/sword/saber/red, +/obj/item/melee/energy/sword/saber/red, /obj/effect/decal/cleanable/blood, /turf/open/floor/iron, /area/awaymission/spacebattle/cruiser) diff --git a/_maps/map_files/debug/runtimestation.dmm b/_maps/map_files/debug/runtimestation.dmm index adaecc5ce3e..402da938ea9 100644 --- a/_maps/map_files/debug/runtimestation.dmm +++ b/_maps/map_files/debug/runtimestation.dmm @@ -2036,7 +2036,7 @@ /area/engineering/atmos) "jU" = ( /obj/structure/table, -/obj/item/melee/transforming/energy/axe, +/obj/item/melee/energy/axe, /turf/open/floor/iron, /area/commons/storage/primary) "kj" = ( diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm index a5b6b21a4cc..987d85b3a18 100644 --- a/_maps/map_files/generic/CentCom.dmm +++ b/_maps/map_files/generic/CentCom.dmm @@ -112,7 +112,7 @@ /obj/item/clothing/suit/armor/tdome/red, /obj/item/clothing/head/helmet/thunderdome, /obj/item/melee/baton/loaded, -/obj/item/melee/transforming/energy/sword/saber/red, +/obj/item/melee/energy/sword/saber/red, /obj/effect/turf_decal/stripes/line{ dir = 4 }, @@ -183,7 +183,7 @@ /obj/item/clothing/suit/armor/tdome/green, /obj/item/clothing/head/helmet/thunderdome, /obj/item/melee/baton/loaded, -/obj/item/melee/transforming/energy/sword/saber/green, +/obj/item/melee/energy/sword/saber/green, /obj/effect/turf_decal/stripes/line{ dir = 8 }, @@ -12152,7 +12152,7 @@ /obj/item/clothing/suit/armor/tdome/red, /obj/item/clothing/head/helmet/thunderdome, /obj/item/melee/baton/loaded, -/obj/item/melee/transforming/energy/sword/saber/red, +/obj/item/melee/energy/sword/saber/red, /obj/effect/turf_decal/stripes/line{ dir = 4 }, @@ -12276,7 +12276,7 @@ /obj/item/clothing/suit/armor/tdome/green, /obj/item/clothing/head/helmet/thunderdome, /obj/item/melee/baton/loaded, -/obj/item/melee/transforming/energy/sword/saber/green, +/obj/item/melee/energy/sword/saber/green, /obj/effect/turf_decal/stripes/line{ dir = 8 }, diff --git a/_maps/shuttles/pirate_default.dmm b/_maps/shuttles/pirate_default.dmm index 3a9695a20d6..7b0728ecbb3 100644 --- a/_maps/shuttles/pirate_default.dmm +++ b/_maps/shuttles/pirate_default.dmm @@ -597,15 +597,15 @@ /obj/machinery/firealarm/directional/north, /obj/effect/decal/cleanable/dirt, /obj/structure/table, -/obj/item/melee/transforming/energy/sword/pirate{ +/obj/item/melee/energy/sword/pirate{ pixel_x = -1; pixel_y = 6 }, -/obj/item/melee/transforming/energy/sword/pirate{ +/obj/item/melee/energy/sword/pirate{ pixel_x = 6; pixel_y = 6 }, -/obj/item/melee/transforming/energy/sword/pirate{ +/obj/item/melee/energy/sword/pirate{ pixel_x = 13; pixel_y = 6 }, diff --git a/_maps/shuttles/pirate_silverscale.dmm b/_maps/shuttles/pirate_silverscale.dmm index dc387cfcab6..009219c409e 100644 --- a/_maps/shuttles/pirate_silverscale.dmm +++ b/_maps/shuttles/pirate_silverscale.dmm @@ -358,14 +358,14 @@ dir = 8; layer = 2.9 }, -/obj/item/melee/transforming/energy/sword/saber/purple{ +/obj/item/melee/energy/sword/saber/purple{ pixel_y = 12 }, -/obj/item/melee/transforming/energy/sword/saber/purple{ +/obj/item/melee/energy/sword/saber/purple{ pixel_x = 8; pixel_y = 7 }, -/obj/item/melee/transforming/energy/sword/saber/purple{ +/obj/item/melee/energy/sword/saber/purple{ pixel_x = 17 }, /turf/open/floor/pod/dark, diff --git a/_maps/templates/holodeck_thunderdome.dmm b/_maps/templates/holodeck_thunderdome.dmm index e9b1eb5167a..a1ff05d6203 100644 --- a/_maps/templates/holodeck_thunderdome.dmm +++ b/_maps/templates/holodeck_thunderdome.dmm @@ -14,7 +14,7 @@ /obj/item/clothing/head/helmet/thunderdome/holosuit, /obj/item/clothing/suit/armor/tdome/holosuit/green, /obj/item/clothing/under/color/green, -/obj/item/holo/esword/green, +/obj/item/melee/energy/sword/holographic/green, /turf/open/floor/holofloor/basalt, /area/template_noop) "q" = ( @@ -22,7 +22,7 @@ /obj/item/clothing/head/helmet/thunderdome/holosuit, /obj/item/clothing/suit/armor/tdome/holosuit/red, /obj/item/clothing/under/color/red, -/obj/item/holo/esword/red, +/obj/item/melee/energy/sword/holographic/red, /turf/open/floor/holofloor/basalt, /area/template_noop) "x" = ( diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index 542f7272ec1..2b420439649 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -1177,6 +1177,17 @@ #define COMSIG_SWAB_FOR_SAMPLES "swab_for_samples" ///Called when you try to swab something using the swabable component, includes a mutable list of what has been swabbed so far so it can be modified. #define COMPONENT_SWAB_FOUND (1<<0) +// /datum/component/transforming signals + +/// From /datum/component/transforming/proc/on_attack_self(obj/item/source, mob/user): (obj/item/source, mob/user, active) +#define COMSIG_TRANSFORMING_PRE_TRANSFORM "transforming_pre_transform" + /// Return COMPONENT_BLOCK_TRANSFORM to prevent the item from transforming. + #define COMPONENT_BLOCK_TRANSFORM (1<<0) +/// From /datum/component/transforming/proc/do_transform(obj/item/source, mob/user): (obj/item/source, mob/user, active) +#define COMSIG_TRANSFORMING_ON_TRANSFORM "transforming_on_transform" + /// Return COMPONENT_NO_DEFAULT_MESSAGE to prevent the transforming component from displaying the default transform message / sound. + #define COMPONENT_NO_DEFAULT_MESSAGE (1<<0) + // /datum/component/two_handed signals ///from base of datum/component/two_handed/proc/wield(mob/living/carbon/user): (/mob/user) diff --git a/code/datums/components/transforming.dm b/code/datums/components/transforming.dm new file mode 100644 index 00000000000..60adbd56b3b --- /dev/null +++ b/code/datums/components/transforming.dm @@ -0,0 +1,253 @@ +/* + * Transforming weapon component. For weapons that swap between states. + * For example: Energy swords, cleaving saws, switch blades. + * + * Used to easily make an item that can be attack_self'd to gain force or change mode. + * + * Only values passed on initialize will update when the item is activated (except the icon_state). + * The icon_state of the item will swap between "[icon_state]" and "[icon_state]_on". + */ +/datum/component/transforming + /// Whether the weapon is transformed + var/active = FALSE + /// Cooldown on transforming this item back and forth + var/transform_cooldown_time + /// Force of the weapon when active + var/force_on + /// Throwforce of the weapon when active + var/throwforce_on + /// Throw speed of the weapon when active + var/throw_speed_on + /// Weight class of the weapon when active + var/w_class_on + /// The sharpness of the weapon when active + var/sharpness_on + /// Hitsound played when active + var/hitsound_on + /// List of the original continuous attack verbs the item has. + var/list/attack_verb_continuous_off + /// List of the original simple attack verbs the item has. + var/list/attack_verb_simple_off + /// List of continuous attack verbs used when the weapon is enabled + var/list/attack_verb_continuous_on + /// List of simple attack verbs used when the weapon is enabled + var/list/attack_verb_simple_on + /// Whether clumsy people need to succeed an RNG check to turn it on without hurting themselves + var/clumsy_check + /// If we get sharpened with a whetstone, save the bonus here for later use if we un/redeploy + var/sharpened_bonus = 0 + /// Cooldown in between transforms + COOLDOWN_DECLARE(transform_cooldown) + +/datum/component/transforming/Initialize( + start_transformed = FALSE, + transform_cooldown_time = 0 SECONDS, + force_on = 0, + throwforce_on = 0, + throw_speed_on = 2, + sharpness_on = NONE, + hitsound_on = 'sound/weapons/blade1.ogg', + w_class_on = WEIGHT_CLASS_BULKY, + clumsy_check = TRUE, + list/attack_verb_continuous_on, + list/attack_verb_simple_on, + ) + + if(!isitem(parent)) + return COMPONENT_INCOMPATIBLE + + var/obj/item/item_parent = parent + + src.transform_cooldown_time = transform_cooldown_time + src.force_on = force_on + src.throwforce_on = throwforce_on + src.throw_speed_on = throw_speed_on + src.sharpness_on = sharpness_on + src.hitsound_on = hitsound_on + src.w_class_on = w_class_on + src.clumsy_check = clumsy_check + + if(attack_verb_continuous_on) + src.attack_verb_continuous_on = attack_verb_continuous_on + attack_verb_continuous_off = item_parent.attack_verb_continuous + if(attack_verb_simple_on) + src.attack_verb_simple_on = attack_verb_simple_on + attack_verb_simple_off = item_parent.attack_verb_simple + + if(start_transformed) + toggle_active(parent) + +/datum/component/transforming/RegisterWithParent() + var/obj/item/item_parent = parent + + RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, .proc/on_attack_self) + if(item_parent.sharpness || sharpness_on) + RegisterSignal(parent, COMSIG_ITEM_SHARPEN_ACT, .proc/on_sharpen) + +/datum/component/transforming/UnregisterFromParent() + UnregisterSignal(parent, list(COMSIG_ITEM_ATTACK_SELF, COMSIG_ITEM_SHARPEN_ACT)) + +/* + * Called on [COMSIG_ITEM_ATTACK_SELF]. + * + * Check if we can transform our weapon, and if so, call [do_transform]. + * Sends signal [COMSIG_TRANSFORMING_PRE_TRANSFORM], and stops the transform action if it returns [COMPONENT_BLOCK_TRANSFORM]. + * And, if [do_transform] was successful, do a clumsy effect from [clumsy_transform_effect]. + * + * source - source of the signal, the item being transformed / parent + * user - the mob transforming the weapon + */ +/datum/component/transforming/proc/on_attack_self(obj/item/source, mob/user) + SIGNAL_HANDLER + + if(!COOLDOWN_FINISHED(src, transform_cooldown)) + to_chat(user, span_warning("Wait a bit before trying to use [source] again!")) + return + + if(SEND_SIGNAL(source, COMSIG_TRANSFORMING_PRE_TRANSFORM, user, active) & COMPONENT_BLOCK_TRANSFORM) + return + + if(do_transform(source, user)) + clumsy_transform_effect(user) + . = COMPONENT_CANCEL_ATTACK_CHAIN + +/* + * Transform the weapon into its alternate form, calling [toggle_active]. + * + * Sends signal [COMSIG_TRANSFORMING_ON_TRANSFORM], and calls [default_transform_message] if it does not return [COMPONENT_NO_DEFAULT_MESSAGE]. + * Also starts the [transform_cooldown] if we have a set [transform_cooldown_time]. + * + * source - the item being transformed / parent + * user - the mob transforming the item + * + * returns TRUE. + */ +/datum/component/transforming/proc/do_transform(obj/item/source, mob/user) + toggle_active(source) + if(!(SEND_SIGNAL(source, COMSIG_TRANSFORMING_ON_TRANSFORM, user, active) & COMPONENT_NO_DEFAULT_MESSAGE)) + default_transform_message(source, user) + + if(isnum(transform_cooldown_time)) + COOLDOWN_START(src, transform_cooldown, transform_cooldown_time) + if(user) + source.add_fingerprint(user) + return TRUE + +/* + * The default feedback message and sound effect for an item transforming. + * + * source - the item being transformed / parent + * user - the mob transforming the item + */ +/datum/component/transforming/proc/default_transform_message(obj/item/source, mob/user) + source.balloon_alert(user, "[active ? "enabled" : "disabled"] [source]") + playsound(user ? user : source.loc, 'sound/weapons/batonextend.ogg', 50, TRUE) + +/* + * Toggle active between true and false, and call + * either set_active or set_inactive depending on whichever state is toggled. + * + * source - the item being transformed / parent + */ +/datum/component/transforming/proc/toggle_active(obj/item/source) + active = !active + if(active) + set_active(source) + else + set_inactive(source) + +/* + * Set our transformed item into its active state. + * Updates all the values that were passed from init and the icon_state. + * + * source - the item being transformed / parent + */ +/datum/component/transforming/proc/set_active(obj/item/source) + if(sharpness_on) + source.sharpness = sharpness_on + if(force_on) + source.force = force_on + (source.sharpness ? sharpened_bonus : 0) + if(throwforce_on) + source.throwforce = throwforce_on + (source.sharpness ? sharpened_bonus : 0) + if(throw_speed_on) + source.throw_speed = throw_speed_on + + if(LAZYLEN(attack_verb_continuous_on)) + source.attack_verb_continuous = attack_verb_continuous_on + if(LAZYLEN(attack_verb_simple_on)) + source.attack_verb_simple = attack_verb_simple_on + + source.hitsound = hitsound_on + source.w_class = w_class_on + source.icon_state = "[source.icon_state]_on" + +/* + * Set our transformed item into its inactive state. + * Updates all the values back to the item's initial values. + * + * source - the item being un-transformed / parent + */ +/datum/component/transforming/proc/set_inactive(obj/item/source) + if(sharpness_on) + source.sharpness = initial(source.sharpness) + if(force_on) + source.force = initial(source.force) + (source.sharpness ? sharpened_bonus : 0) + if(throwforce_on) + source.throwforce = initial(source.throwforce) + (source.sharpness ? sharpened_bonus : 0) + if(throw_speed_on) + source.throw_speed = initial(source.throw_speed) + + if(LAZYLEN(attack_verb_continuous_on)) + source.attack_verb_continuous = attack_verb_continuous_off + if(LAZYLEN(attack_verb_simple_off)) + source.attack_verb_simple = attack_verb_simple_off + + source.hitsound = initial(source.hitsound) + source.w_class = initial(source.w_class) + source.icon_state = initial(source.icon_state) + +/* + * If [clumsy_check] is set to TRUE, attempt to cause a side effect for clumsy people activating this item. + * Called after the transform is done, meaning [active] var has already updated. + * + * user - the clumsy mob, transforming our item (parent) + * + * Returns TRUE if side effects happened, FALSE otherwise + */ +/datum/component/transforming/proc/clumsy_transform_effect(mob/living/user) + if(!clumsy_check) + return FALSE + + if(!HAS_TRAIT(user, TRAIT_CLUMSY)) + return FALSE + + if(active && prob(50)) + var/hurt_self_verb_simple = LAZYLEN(attack_verb_simple_on) ? pick(attack_verb_simple_on) : "hit" + var/hurt_self_verb_continuous = LAZYLEN(attack_verb_continuous_on) ? pick(attack_verb_continuous_on) : "hits" + user.visible_message( + span_warning("[user] triggers [parent] while holding it backwards and [hurt_self_verb_continuous] themself, like a doofus!"), + span_warning("You trigger [parent] while holding it backwards and [hurt_self_verb_simple] yourself, like a doofus!") + ) + user.take_bodypart_damage(10) + return TRUE + return FALSE + +/* + * Called on [COMSIG_ITEM_SHARPEN_ACT]. + * We need to track our sharpened bonus here, so we correctly apply and unapply it + * if our item's sharpness state changes from transforming. + * + * source - the item being sharpened / parent + * increment - the amount of force added + * max - the maximum force that the item can be adjusted to. + * + * Does not return naturally [COMPONENT_BLOCK_SHARPEN_APPLIED] as this is only to track our sharpened bonus between transformation. + */ +/datum/component/transforming/proc/on_sharpen(obj/item/source, increment, max) + SIGNAL_HANDLER + + if(sharpened_bonus) + return COMPONENT_BLOCK_SHARPEN_ALREADY + if(force_on + increment > max) + return COMPONENT_BLOCK_SHARPEN_MAXED + sharpened_bonus = increment diff --git a/code/game/objects/items/dualsaber.dm b/code/game/objects/items/dualsaber.dm index 3177df30987..19f71773335 100644 --- a/code/game/objects/items/dualsaber.dm +++ b/code/game/objects/items/dualsaber.dm @@ -160,7 +160,7 @@ return 1 /obj/item/dualsaber/ignition_effect(atom/A, mob/user) - // same as /obj/item/melee/transforming/energy, mostly + // same as /obj/item/melee/energy, mostly if(!wielded) return "" var/in_mouth = "" diff --git a/code/game/objects/items/melee/energy.dm b/code/game/objects/items/melee/energy.dm index 81ca7b24873..bce11c884a1 100644 --- a/code/game/objects/items/melee/energy.dm +++ b/code/game/objects/items/melee/energy.dm @@ -1,57 +1,74 @@ -/obj/item/melee/transforming/energy +/obj/item/melee/energy icon = 'icons/obj/transforming_energy.dmi' - hitsound_on = 'sound/weapons/blade1.ogg' - heat = 3500 max_integrity = 200 armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 100, ACID = 30) + attack_verb_continuous = list("hits", "taps", "pokes") + attack_verb_simple = list("hit", "tap", "poke") resistance_flags = FIRE_PROOF light_system = MOVABLE_LIGHT light_range = 3 light_power = 1 light_on = FALSE - var/sword_color + bare_wound_bonus = 20 + stealthy_audio = TRUE + w_class = WEIGHT_CLASS_SMALL -/obj/item/melee/transforming/energy/Initialize() + /// The color of this energy based sword, for use in editing the icon_state. + var/sword_color_icon + /// Whether our blade is active or not. + var/blade_active = FALSE + /// Force while active. + var/active_force = 30 + /// Throwforce while active. + var/active_throwforce = 20 + /// Sharpness while active. + var/active_sharpness = SHARP_EDGED + /// Hitsound played attacking while active. + var/active_hitsound = 'sound/weapons/blade1.ogg' + /// Weight class while active. + var/active_w_class = WEIGHT_CLASS_BULKY + /// The heat given off when active. + var/active_heat = 3500 + +/obj/item/melee/energy/Initialize() . = ..() - if(active) - START_PROCESSING(SSobj, src) + make_transformable() + AddComponent(/datum/component/butchering, _speed = 5 SECONDS, _butcher_sound = active_hitsound) -/obj/item/melee/transforming/energy/Destroy() +/obj/item/melee/energy/Destroy() STOP_PROCESSING(SSobj, src) return ..() -/obj/item/melee/transforming/energy/suicide_act(mob/user) - if(!active) - transform_weapon(user, TRUE) +/* + * Gives our item the transforming component, passing in our various vars. + */ +/obj/item/melee/energy/proc/make_transformable() + AddComponent(/datum/component/transforming, \ + force_on = active_force, \ + throwforce_on = active_throwforce, \ + throw_speed_on = 4, \ + sharpness_on = active_sharpness, \ + hitsound_on = active_hitsound, \ + w_class_on = active_w_class, \ + attack_verb_continuous_on = list("attacks", "slashes", "stabs", "slices", "tears", "lacerates", "rips", "dices", "cuts"), \ + attack_verb_simple_on = list("attack", "slash", "stab", "slice", "tear", "lacerate", "rip", "dice", "cut")) + RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform) + +/obj/item/melee/energy/suicide_act(mob/user) + if(!blade_active) + attack_self(user) user.visible_message(span_suicide("[user] is [pick("slitting [user.p_their()] stomach open with", "falling on")] [src]! It looks like [user.p_theyre()] trying to commit seppuku!")) return (BRUTELOSS|FIRELOSS) -/obj/item/melee/transforming/energy/add_blood_DNA(list/blood_dna) +/obj/item/melee/energy/add_blood_DNA(list/blood_dna) return FALSE -/obj/item/melee/transforming/energy/get_sharpness() - return active * sharpness +/obj/item/melee/energy/process(delta_time) + if(heat) + open_flame() -/obj/item/melee/transforming/energy/process() - open_flame() - -/obj/item/melee/transforming/energy/transform_weapon(mob/living/user, supress_message_text) - . = ..() - if(.) - if(active) - if(sword_color) - icon_state = "sword[sword_color]" - START_PROCESSING(SSobj, src) - else - STOP_PROCESSING(SSobj, src) - set_light_on(active) - - -/obj/item/melee/transforming/energy/get_temperature() - return active * heat - -/obj/item/melee/transforming/energy/ignition_effect(atom/A, mob/user) - if(!active) +/obj/item/melee/energy/ignition_effect(atom/A, mob/user) + if(!heat && !blade_active) return "" var/in_mouth = "" @@ -63,180 +80,234 @@ playsound(loc, hitsound, get_clamped_volume(), TRUE, -1) add_fingerprint(user) -/obj/item/melee/transforming/energy/axe +/* + * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM]. + * + * Updates our icon to have the correct color, + * updates the amount of heat our item gives out, + * enables / disables embedding, and + * starts / stops processing. + * + * Also gives feedback to the user and activates or deactives the glow. + */ +/obj/item/melee/energy/proc/on_transform(obj/item/source, mob/user, active) + SIGNAL_HANDLER + + blade_active = active + if(active) + if(sword_color_icon) + icon_state = "[icon_state]_[sword_color_icon]" + if(embedding) + updateEmbedding() + heat = active_heat + START_PROCESSING(SSobj, src) + else + if(embedding) + disableEmbedding() + heat = initial(heat) + STOP_PROCESSING(SSobj, src) + + balloon_alert(user, "[name] [active ? "enabled":"disabled"]") + playsound(user ? user : src, active ? 'sound/weapons/saberon.ogg' : 'sound/weapons/saberoff.ogg', 35, TRUE) + set_light_on(active) + return COMPONENT_NO_DEFAULT_MESSAGE + +/// Energy axe - extremely strong. +/obj/item/melee/energy/axe name = "energy axe" desc = "An energized battle axe." - icon_state = "axe0" + icon_state = "axe" lefthand_file = 'icons/mob/inhands/weapons/axes_lefthand.dmi' righthand_file = 'icons/mob/inhands/weapons/axes_righthand.dmi' - force = 40 - force_on = 150 - throwforce = 25 - throwforce_on = 30 hitsound = 'sound/weapons/bladeslice.ogg' + attack_verb_continuous = list("attacks", "chops", "cleaves", "tears", "lacerates", "cuts") + attack_verb_simple = list("attack", "chop", "cleave", "tear", "lacerate", "cut") + force = 40 + throwforce = 25 throw_speed = 3 throw_range = 5 - w_class = WEIGHT_CLASS_NORMAL - w_class_on = WEIGHT_CLASS_HUGE - flags_1 = CONDUCT_1 armour_penetration = 100 - attack_verb_off = list("attacks", "chops", "cleaves", "tears", "lacerates", "cuts") - attack_verb_on = list() + sharpness = SHARP_EDGED + w_class = WEIGHT_CLASS_NORMAL + flags_1 = CONDUCT_1 light_color = LIGHT_COLOR_LIGHT_CYAN -/obj/item/melee/transforming/energy/axe/suicide_act(mob/user) + active_force = 150 + active_throwforce = 30 + active_w_class = WEIGHT_CLASS_HUGE + +/obj/item/melee/energy/axe/make_transformable() + AddComponent(/datum/component/transforming, \ + force_on = active_force, \ + throwforce_on = active_throwforce, \ + throw_speed_on = throw_speed, \ + sharpness_on = sharpness, \ + w_class_on = active_w_class) + RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform) + +/obj/item/melee/energy/axe/suicide_act(mob/user) user.visible_message(span_suicide("[user] swings [src] towards [user.p_their()] head! It looks like [user.p_theyre()] trying to commit suicide!")) return (BRUTELOSS|FIRELOSS) -/obj/item/melee/transforming/energy/sword +/// Energy swords. +/obj/item/melee/energy/sword name = "energy sword" desc = "May the force be within you." - icon_state = "sword0" + icon_state = "e_sword" lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' + hitsound = "swing_hit" force = 3 throwforce = 5 - hitsound = "swing_hit" //it starts deactivated - attack_verb_off = list("taps", "pokes") throw_speed = 3 throw_range = 5 - sharpness = SHARP_EDGED - embedding = list("embed_chance" = 75, "impact_pain_mult" = 10) armour_penetration = 35 block_chance = 50 + embedding = list("embed_chance" = 75, "impact_pain_mult" = 10) -/obj/item/melee/transforming/energy/sword/transform_weapon(mob/living/user, supress_message_text) - . = ..() - if(. && active && sword_color) - icon_state = "sword[sword_color]" - -/obj/item/melee/transforming/energy/sword/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - if(active) +/obj/item/melee/energy/sword/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) + if(blade_active) return ..() - return 0 + return FALSE -/obj/item/melee/transforming/energy/sword/cyborg - sword_color = "red" +/obj/item/melee/energy/sword/cyborg + name = "cyborg energy sword" + sword_color_icon = "red" + /// The cell cost of hitting something. var/hitcost = 50 -/obj/item/melee/transforming/energy/sword/cyborg/attack(mob/M, mob/living/silicon/robot/R) - if(R.cell) - var/obj/item/stock_parts/cell/C = R.cell - if(active && !(C.use(hitcost))) - attack_self(R) - to_chat(R, span_notice("It's out of charge!")) - return - return ..() +/obj/item/melee/energy/sword/cyborg/attack(mob/target, mob/living/silicon/robot/user) + if(!user.cell) + return -/obj/item/melee/transforming/energy/sword/cyborg/saw //Used by medical Syndicate cyborgs + var/obj/item/stock_parts/cell/our_cell = user.cell + if(blade_active && !(our_cell.use(hitcost))) + attack_self(user) + to_chat(user, span_notice("It's out of charge!")) + return + return ..() + +/obj/item/melee/energy/sword/cyborg/cyborg_unequip(mob/user) + if(!blade_active) + return + attack_self(user) + +/obj/item/melee/energy/sword/cyborg/saw //Used by medical Syndicate cyborgs name = "energy saw" desc = "For heavy duty cutting. It has a carbon-fiber blade in addition to a toggleable hard-light edge to dramatically increase sharpness." - force_on = 30 - force = 18 //About as much as a spear - hitsound = 'sound/weapons/circsawhit.ogg' icon = 'icons/obj/surgery.dmi' - icon_state = "esaw_0" - icon_state_on = "esaw_1" - sword_color = null //stops icon from breaking when turned on. - hitcost = 75 //Costs more than a standard cyborg esword + icon_state = "esaw" + hitsound = 'sound/weapons/circsawhit.ogg' + force = 18 + hitcost = 75 // Costs more than a standard cyborg esword. w_class = WEIGHT_CLASS_NORMAL sharpness = SHARP_EDGED light_color = LIGHT_COLOR_LIGHT_CYAN tool_behaviour = TOOL_SAW - toolspeed = 0.7 //faster as a saw + toolspeed = 0.7 // Faster than a normal saw. -/obj/item/melee/transforming/energy/sword/cyborg/saw/cyborg_unequip(mob/user) - if(!active) - return - transform_weapon(user, TRUE) + active_force = 30 + sword_color_icon = null // Stops icon from breaking when turned on. -/obj/item/melee/transforming/energy/sword/cyborg/saw/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - return 0 +/obj/item/melee/energy/sword/cyborg/saw/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) + return FALSE -/obj/item/melee/transforming/energy/sword/saber - var/list/possible_colors = list("red" = COLOR_SOFT_RED, "blue" = LIGHT_COLOR_LIGHT_CYAN, "green" = LIGHT_COLOR_GREEN, "purple" = LIGHT_COLOR_LAVENDER) +// The colored energy swords we all know and love. +/obj/item/melee/energy/sword/saber + /// Assoc list of all possible saber colors to color define. + var/list/possible_colors = list( + "red" = COLOR_SOFT_RED, + "blue" = LIGHT_COLOR_LIGHT_CYAN, + "green" = LIGHT_COLOR_GREEN, + "purple" = LIGHT_COLOR_LAVENDER, + ) + /// Whether this saber has beel multitooled. var/hacked = FALSE -/obj/item/melee/transforming/energy/sword/saber/Initialize(mapload) +/obj/item/melee/energy/sword/saber/Initialize(mapload) . = ..() - if(LAZYLEN(possible_colors)) - var/set_color = pick(possible_colors) - sword_color = set_color - set_light_color(possible_colors[set_color]) + if(!sword_color_icon && LAZYLEN(possible_colors)) + sword_color_icon = pick(possible_colors) -/obj/item/melee/transforming/energy/sword/saber/process() + if(sword_color_icon) + set_light_color(possible_colors[sword_color_icon]) + +/obj/item/melee/energy/sword/saber/process() . = ..() if(hacked) - var/set_color = pick(possible_colors) - set_light_color(possible_colors[set_color]) + set_light_color(possible_colors[pick(possible_colors)]) -/obj/item/melee/transforming/energy/sword/saber/red - possible_colors = list("red" = COLOR_SOFT_RED) +/obj/item/melee/energy/sword/saber/red + sword_color_icon = "red" -/obj/item/melee/transforming/energy/sword/saber/blue - possible_colors = list("blue" = LIGHT_COLOR_LIGHT_CYAN) +/obj/item/melee/energy/sword/saber/blue + sword_color_icon = "blue" -/obj/item/melee/transforming/energy/sword/saber/green - possible_colors = list("green" = LIGHT_COLOR_GREEN) +/obj/item/melee/energy/sword/saber/green + sword_color_icon = "green" -/obj/item/melee/transforming/energy/sword/saber/purple - possible_colors = list("purple" = LIGHT_COLOR_LAVENDER) +/obj/item/melee/energy/sword/saber/purple + sword_color_icon = "purple" -/obj/item/melee/transforming/energy/sword/saber/attackby(obj/item/W, mob/living/user, params) - if(W.tool_behaviour == TOOL_MULTITOOL) - if(!hacked) - hacked = TRUE - sword_color = "rainbow" - to_chat(user, span_warning("RNBW_ENGAGE")) - - if(active) - icon_state = "swordrainbow" - user.update_inv_hands() - else +/obj/item/melee/energy/sword/saber/attackby(obj/item/weapon, mob/living/user, params) + if(weapon.tool_behaviour == TOOL_MULTITOOL) + if(hacked) to_chat(user, span_warning("It's already fabulous!")) + else + hacked = TRUE + sword_color_icon = "rainbow" + to_chat(user, span_warning("RNBW_ENGAGE")) + if(force >= active_force) + icon_state = "[initial(icon_state)]_on_rainbow" + user.update_inv_hands() else return ..() -/obj/item/melee/transforming/energy/sword/pirate +/obj/item/melee/energy/sword/pirate name = "energy cutlass" desc = "Arrrr matey." - icon_state = "cutlass0" + icon_state = "e_cutlass" lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' - icon_state_on = "cutlass1" light_color = COLOR_RED -/obj/item/melee/transforming/energy/blade +/// Energy blades, which are effectively perma-extended energy swords +/obj/item/melee/energy/blade name = "energy blade" desc = "A concentrated beam of energy in the shape of a blade. Very stylish... and lethal." icon_state = "blade" lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' - force = 30 //Normal attacks deal esword damage hitsound = 'sound/weapons/blade1.ogg' - active = 1 - throwforce = 1 //Throwing or dropping the item deletes it. + attack_verb_continuous = list("attacks", "slashes", "stabs", "slices", "tears", "lacerates", "rips", "dices", "cuts") + attack_verb_simple = list("attack", "slash", "stab", "slice", "tear", "lacerate", "rip", "dice", "cut") + force = 30 + throwforce = 1 // Throwing or dropping the item deletes it. throw_speed = 3 throw_range = 1 - w_class = WEIGHT_CLASS_BULKY//So you can't hide it in your pocket or some such. - var/datum/effect_system/spark_spread/spark_system sharpness = SHARP_EDGED + heat = 3500 + w_class = WEIGHT_CLASS_BULKY + blade_active = TRUE + /// Our linked spark system that emits from our sword. + var/datum/effect_system/spark_spread/spark_system //Most of the other special functions are handled in their own files. aka special snowflake code so kewl -/obj/item/melee/transforming/energy/blade/Initialize() +/obj/item/melee/energy/blade/Initialize() . = ..() spark_system = new /datum/effect_system/spark_spread() spark_system.set_up(5, 0, src) spark_system.attach(src) + START_PROCESSING(SSobj, src) -/obj/item/melee/transforming/energy/blade/Destroy() +/obj/item/melee/energy/blade/Destroy() QDEL_NULL(spark_system) return ..() -/obj/item/melee/transforming/energy/blade/transform_weapon(mob/living/user, supress_message_text) - return +/obj/item/melee/energy/blade/make_transformable() + return FALSE -/obj/item/melee/transforming/energy/blade/hardlight +/obj/item/melee/energy/blade/hardlight name = "hardlight blade" desc = "An extremely sharp blade made out of hard light. Packs quite a punch." icon_state = "lightblade" diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm index 6e1a9ba965a..162c888fd79 100644 --- a/code/game/objects/items/melee/misc.dm +++ b/code/game/objects/items/melee/misc.dm @@ -183,9 +183,12 @@ slot_flags = ITEM_SLOT_BELT force = 12 //9 hit crit w_class = WEIGHT_CLASS_NORMAL + wound_bonus = 15 - var/cooldown_check = 0 // Used interally, you don't want to modify - + /// Whether this baton is active or not + var/extended = TRUE + /// Used interally, you don't want to modify + var/cooldown_check = 0 /// Default wait time until can stun again. var/cooldown = (4 SECONDS) /// The length of the knockdown applied to a struck living, non-cyborg mob. @@ -196,23 +199,11 @@ var/stamina_damage = 55 /// Can we stun cyborgs? var/affect_cyborg = FALSE - /// "On" sound, played when switching between able to stun or not. - var/on_sound /// The path of the default sound to play when we stun something. var/on_stun_sound = 'sound/effects/woodhit.ogg' /// Do we animate the "hit" when stunning something? var/stun_animation = TRUE - /// Are we on or off? - var/on = TRUE - var/on_icon_state // What is our sprite when turned on - var/off_icon_state // What is our sprite when turned off - var/on_inhand_icon_state // What is our in-hand sprite when turned on - var/force_on // Damage when on - not stunning - var/force_off // Damage when off - not stunning - var/weight_class_on // What is the new size class when turned on - - wound_bonus = 15 /obj/item/melee/classic_baton/Initialize() . = ..() @@ -224,15 +215,6 @@ /obj/item/melee/classic_baton/proc/get_wait_description() return -/// Description for when turning the baton "on". -/obj/item/melee/classic_baton/proc/get_on_description() - . = list() - - .["local_on"] = "You extend the baton." - .["local_off"] = "You collapse the baton." - - return . - /// Default message for stunning a living, non-cyborg mob. /obj/item/melee/classic_baton/proc/get_stun_description(mob/living/target, mob/living/user) . = list() @@ -269,7 +251,7 @@ return /obj/item/melee/classic_baton/attack(mob/living/target, mob/living/user, params) - if(!on) + if(!extended) return ..() add_fingerprint(user) @@ -361,94 +343,91 @@ name = "telescopic baton" desc = "A compact yet robust personal defense weapon. Can be concealed when folded." icon = 'icons/obj/items_and_weapons.dmi' - icon_state = "telebaton_0" + icon_state = "telebaton" lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' inhand_icon_state = null + attack_verb_continuous = list("hits", "pokes") + attack_verb_simple = list("hit", "poke") worn_icon_state = "tele_baton" slot_flags = ITEM_SLOT_BELT w_class = WEIGHT_CLASS_SMALL item_flags = NONE force = 0 - on = FALSE - on_sound = 'sound/weapons/batonextend.ogg' - - on_icon_state = "telebaton_1" - off_icon_state = "telebaton_0" - on_inhand_icon_state = "nullrod" - force_on = 10 - force_off = 0 - weight_class_on = WEIGHT_CLASS_BULKY bare_wound_bonus = 5 + extended = FALSE + + /// The sound effecte played when our baton is extended. + var/on_sound = 'sound/weapons/batonextend.ogg' + /// The inhand iconstate used when our baton is extended. + var/on_inhand_icon_state = "nullrod" + /// The force on extension. + var/active_force = 10 + +/obj/item/melee/classic_baton/telescopic/Initialize() + . = ..() + AddComponent(/datum/component/transforming, \ + force_on = active_force, \ + hitsound_on = hitsound, \ + w_class_on = WEIGHT_CLASS_NORMAL, \ + clumsy_check = FALSE, \ + attack_verb_continuous_on = list("smacks", "strikes", "cracks", "beats"), \ + attack_verb_simple_on = list("smack", "strike", "crack", "beat")) + RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform) /obj/item/melee/classic_baton/telescopic/suicide_act(mob/user) - var/mob/living/carbon/human/H = user - var/obj/item/organ/brain/B = H.getorgan(/obj/item/organ/brain) + var/mob/living/carbon/human/human_user = user + var/obj/item/organ/brain/our_brain = human_user.getorgan(/obj/item/organ/brain) user.visible_message(span_suicide("[user] stuffs [src] up [user.p_their()] nose and presses the 'extend' button! It looks like [user.p_theyre()] trying to clear [user.p_their()] mind.")) - if(!on) - src.attack_self(user) - else + if(extended) playsound(src, on_sound, 50, TRUE) add_fingerprint(user) + else + attack_self(user) + sleep(3) - if (!QDELETED(H)) - if(!QDELETED(B)) - H.internal_organs -= B - qdel(B) - new /obj/effect/gibspawner/generic(H.drop_location(), H) + if (!QDELETED(human_user)) + if(!QDELETED(our_brain)) + human_user.internal_organs -= our_brain + qdel(our_brain) + new /obj/effect/gibspawner/generic(human_user.drop_location(), human_user) return (BRUTELOSS) -/obj/item/melee/classic_baton/telescopic/attack_self(mob/user) - on = !on - var/list/desc = get_on_description() +/* + * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM]. + * + * Gives feedback to the user and makes it show up inhand. + */ +/obj/item/melee/classic_baton/telescopic/proc/on_transform(obj/item/source, mob/user, active) + SIGNAL_HANDLER - if(on) - to_chat(user, desc["local_on"]) - icon_state = on_icon_state - inhand_icon_state = on_inhand_icon_state - w_class = weight_class_on - force = force_on - attack_verb_continuous = list("smacks", "strikes", "cracks", "beats") - attack_verb_simple = list("smack", "strike", "crack", "beat") - else - to_chat(user, desc["local_off"]) - icon_state = off_icon_state - inhand_icon_state = null //no sprite for concealment even when in hand - slot_flags = ITEM_SLOT_BELT - w_class = WEIGHT_CLASS_SMALL - force = force_off - attack_verb_continuous = list("hits", "pokes") - attack_verb_simple = list("hit", "poke") - - playsound(src.loc, on_sound, 50, TRUE) - add_fingerprint(user) + extended = active + inhand_icon_state = active ? on_inhand_icon_state : null // When inactive, there is no inhand icon_state. + balloon_alert(user, "[active ? "extended" : "collapsed"] [src]") + playsound(user ? user : src, on_sound, 50, TRUE) + return COMPONENT_NO_DEFAULT_MESSAGE /obj/item/melee/classic_baton/telescopic/contractor_baton name = "contractor baton" desc = "A compact, specialised baton assigned to Syndicate contractors. Applies light electrical shocks to targets." icon = 'icons/obj/items_and_weapons.dmi' - icon_state = "contractor_baton_0" + icon_state = "contractor_baton" + worn_icon_state = "contractor_baton" lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' - inhand_icon_state = null slot_flags = ITEM_SLOT_BELT w_class = WEIGHT_CLASS_SMALL item_flags = NONE force = 5 - cooldown = 25 stamina_damage = 85 affect_cyborg = TRUE - on_sound = 'sound/weapons/contractorbatonextend.ogg' on_stun_sound = 'sound/effects/contractorbatonhit.ogg' - on_icon_state = "contractor_baton_1" - off_icon_state = "contractor_baton_0" - on_inhand_icon_state = "contractor_baton" - force_on = 16 - force_off = 5 - weight_class_on = WEIGHT_CLASS_NORMAL + on_inhand_icon_state = "contractor_baton_on" + on_sound = 'sound/weapons/contractorbatonextend.ogg' + active_force = 16 /obj/item/melee/classic_baton/telescopic/contractor_baton/get_wait_description() return span_danger("The baton is still charging!") @@ -582,8 +561,8 @@ /obj/item/melee/roastingstick name = "advanced roasting stick" desc = "A telescopic roasting stick with a miniature shield generator designed to ensure entry into various high-tech shielded cooking ovens and firepits." - icon_state = "roastingstick_0" - inhand_icon_state = "null" + icon_state = "roastingstick" + inhand_icon_state = null worn_icon_state = "tele_baton" slot_flags = ITEM_SLOT_BELT w_class = WEIGHT_CLASS_SMALL @@ -591,33 +570,55 @@ force = 0 attack_verb_continuous = list("hits", "pokes") attack_verb_simple = list("hit", "poke") + /// The sausage attatched to our stick. var/obj/item/food/sausage/held_sausage + /// Static list of things our roasting stick can interact with. var/static/list/ovens - var/on = FALSE + /// The beam that links to the oven we use var/datum/beam/beam + /// Whether or stick is extended and can recieve sausage + var/extended = FALSE /obj/item/melee/roastingstick/Initialize() . = ..() if (!ovens) ovens = typecacheof(list(/obj/singularity, /obj/energy_ball, /obj/machinery/power/supermatter_crystal, /obj/structure/bonfire)) + AddComponent(/datum/component/transforming, \ + hitsound_on = hitsound, \ + clumsy_check = FALSE) + RegisterSignal(src, COMSIG_TRANSFORMING_PRE_TRANSFORM, .proc/attempt_transform) + RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform) -/obj/item/melee/roastingstick/attack_self(mob/user) - on = !on - if(on) - extend(user) - else - if (held_sausage) - to_chat(user, span_warning("You can't retract [src] while [held_sausage] is attached!")) - return - retract(user) +/* + * Signal proc for [COMSIG_TRANSFORMING_PRE_TRANSFORM]. + * + * If there is a sausage attached, returns COMPONENT_BLOCK_TRANSFORM. + */ +/obj/item/melee/roastingstick/proc/attempt_transform(obj/item/source, mob/user, active) + SIGNAL_HANDLER - playsound(src.loc, 'sound/weapons/batonextend.ogg', 50, TRUE) - add_fingerprint(user) + if(held_sausage) + to_chat(user, span_warning("You can't retract [src] while [held_sausage] is attached!")) + return COMPONENT_BLOCK_TRANSFORM + +/* + * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM]. + * + * Gives feedback on stick extension. + */ +/obj/item/melee/roastingstick/proc/on_transform(obj/item/source, mob/user, active) + SIGNAL_HANDLER + + extended = active + inhand_icon_state = active ? "nullrod" : null + balloon_alert(user, "[active ? "extended" : "collapsed"] [src]") + playsound(user ? user : src, 'sound/weapons/batonextend.ogg', 50, TRUE) + return COMPONENT_NO_DEFAULT_MESSAGE /obj/item/melee/roastingstick/attackby(atom/target, mob/user) ..() if (istype(target, /obj/item/food/sausage)) - if (!on) + if (!extended) to_chat(user, span_warning("You must extend [src] to attach anything to it!")) return if (held_sausage) @@ -641,18 +642,6 @@ if(held_sausage) . += mutable_appearance(icon, "roastingstick_sausage") -/obj/item/melee/roastingstick/proc/extend(user) - to_chat(user, span_warning("You extend [src].")) - icon_state = "roastingstick_1" - inhand_icon_state = "nullrod" - w_class = WEIGHT_CLASS_BULKY - -/obj/item/melee/roastingstick/proc/retract(user) - to_chat(user, span_notice("You collapse [src].")) - icon_state = "roastingstick_0" - inhand_icon_state = null - w_class = WEIGHT_CLASS_SMALL - /obj/item/melee/roastingstick/handle_atom_del(atom/target) if (target == held_sausage) held_sausage = null @@ -660,7 +649,7 @@ /obj/item/melee/roastingstick/afterattack(atom/target, mob/user, proximity) . = ..() - if (!on) + if (!extended) return if (is_type_in_typecache(target, ovens)) if (held_sausage?.roasted) diff --git a/code/game/objects/items/melee/transforming.dm b/code/game/objects/items/melee/transforming.dm deleted file mode 100644 index 6e8bf4fda43..00000000000 --- a/code/game/objects/items/melee/transforming.dm +++ /dev/null @@ -1,101 +0,0 @@ -/obj/item/melee/transforming - sharpness = SHARP_EDGED - bare_wound_bonus = 20 - stealthy_audio = TRUE //Most of these are antag weps so we dont want them to be /too/ overt. - var/active = FALSE - var/force_on = 30 //force when active - var/faction_bonus_force = 0 //Bonus force dealt against certain factions - var/throwforce_on = 20 - var/icon_state_on = "axe1" - var/hitsound_on = 'sound/weapons/blade1.ogg' - var/list/attack_verb_on = list("attacks", "slashes", "stabs", "slices", "tears", "lacerates", "rips", "dices", "cuts") - var/list/attack_verb_off = list("attacks", "slashes", "stabs", "slices", "tears", "lacerates", "rips", "dices", "cuts") - w_class = WEIGHT_CLASS_SMALL - var/bonus_active = FALSE //If the faction damage bonus is active - var/list/nemesis_factions //Any mob with a faction that exists in this list will take bonus damage/effects - var/w_class_on = WEIGHT_CLASS_BULKY - var/clumsy_check = TRUE - /// If we get sharpened with a whetstone, save the bonus here for later use if we un/redeploy - var/sharpened_bonus - -/obj/item/melee/transforming/Initialize() - . = ..() - if(active) - if(attack_verb_on.len) - attack_verb_continuous = attack_verb_on - else - if(attack_verb_off.len) - attack_verb_continuous = attack_verb_off - if(embedding) - updateEmbedding() - if(sharpness) - AddComponent(/datum/component/butchering, 50, 100, 0, hitsound) - RegisterSignal(src, COMSIG_ITEM_SHARPEN_ACT, .proc/on_sharpen) - -/obj/item/melee/transforming/attack_self(mob/living/carbon/user) - if(transform_weapon(user)) - clumsy_transform_effect(user) - -/obj/item/melee/transforming/attack(mob/living/target, mob/living/carbon/human/user) - var/nemesis_faction = FALSE - if(LAZYLEN(nemesis_factions)) - for(var/F in target.faction) - if(F in nemesis_factions) - nemesis_faction = TRUE - force += faction_bonus_force - nemesis_effects(user, target) - break - . = ..() - if(nemesis_faction) - force -= faction_bonus_force - -/obj/item/melee/transforming/proc/transform_weapon(mob/living/user, supress_message_text) - active = !active - if(active) - force = force_on + sharpened_bonus - throwforce = throwforce_on + sharpened_bonus - hitsound = hitsound_on - throw_speed = 4 - if(attack_verb_on.len) - attack_verb_continuous = attack_verb_on - icon_state = icon_state_on - w_class = w_class_on - if(embedding) - updateEmbedding() - else - force = initial(force) + (get_sharpness() ? sharpened_bonus : 0) - throwforce = initial(throwforce) + (get_sharpness() ? sharpened_bonus : 0) - hitsound = initial(hitsound) - throw_speed = initial(throw_speed) - if(attack_verb_off.len) - attack_verb_continuous = attack_verb_off - icon_state = initial(icon_state) - w_class = initial(w_class) - if(embedding) - disableEmbedding() - - transform_messages(user, supress_message_text) - add_fingerprint(user) - return TRUE - -/obj/item/melee/transforming/proc/nemesis_effects(mob/living/user, mob/living/target) - return - -/obj/item/melee/transforming/proc/transform_messages(mob/living/user, supress_message_text) - playsound(user, active ? 'sound/weapons/saberon.ogg' : 'sound/weapons/saberoff.ogg', 35, TRUE) //changed it from 50% volume to 35% because deafness - if(!supress_message_text) - to_chat(user, span_notice("[src] [active ? "is now active":"can now be concealed"].")) - -/obj/item/melee/transforming/proc/clumsy_transform_effect(mob/living/user) - if(clumsy_check && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50)) - to_chat(user, span_warning("You accidentally cut yourself with [src], like a doofus!")) - user.take_bodypart_damage(5,5) - -/obj/item/melee/transforming/proc/on_sharpen(datum/source, increment, max) - SIGNAL_HANDLER - - if(sharpened_bonus) - return COMPONENT_BLOCK_SHARPEN_ALREADY - if(force_on + increment > max) - return COMPONENT_BLOCK_SHARPEN_MAXED - sharpened_bonus = increment diff --git a/code/game/objects/items/sharpener.dm b/code/game/objects/items/sharpener.dm index acccb4eca20..7bf30c780a0 100644 --- a/code/game/objects/items/sharpener.dm +++ b/code/game/objects/items/sharpener.dm @@ -33,7 +33,7 @@ if(requires_sharpness && !I.get_sharpness()) to_chat(user, span_warning("You can only sharpen items that are already sharp, such as knives!")) return - if(is_type_in_list(I, list(/obj/item/melee/transforming/energy, /obj/item/dualsaber))) //You can't sharpen the photons in energy meelee weapons + if(is_type_in_list(I, list(/obj/item/melee/energy, /obj/item/dualsaber))) //You can't sharpen the photons in energy meelee weapons to_chat(user, span_warning("You don't think \the [I] will be the thing getting modified if you use it on \the [src]!")) return diff --git a/code/game/objects/items/shields.dm b/code/game/objects/items/shields.dm index ef38ecba4ef..cde1b0ac4a7 100644 --- a/code/game/objects/items/shields.dm +++ b/code/game/objects/items/shields.dm @@ -191,6 +191,7 @@ /obj/item/shield/energy name = "energy combat shield" desc = "A shield that reflects almost all energy projectiles, but is useless against physical attacks. It can be retracted, expanded, and stored anywhere." + icon_state = "eshield" lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi' w_class = WEIGHT_CLASS_TINY @@ -200,50 +201,51 @@ force = 3 throwforce = 3 throw_speed = 3 - base_icon_state = "eshield" // [base_icon_state]1 for expanded, [base_icon_state]0 for contracted - var/on_force = 10 - var/on_throwforce = 8 - var/on_throw_speed = 2 - var/active = 0 - var/clumsy_check = TRUE + + /// Whether the shield is currently extended and protecting the user. + var/enabled = FALSE + /// Force of the shield when active. + var/active_force = 10 + /// Throwforce of the shield when active. + var/active_throwforce = 8 + /// Throwspeed of ethe shield when active. + var/active_throw_speed = 2 + /// Whether clumsy people can transform this without side effects. + var/can_clumsy_use = FALSE /obj/item/shield/energy/Initialize() . = ..() - icon_state = "[base_icon_state]0" + AddComponent(/datum/component/transforming, \ + force_on = active_force, \ + throwforce_on = active_throwforce, \ + throw_speed_on = active_throw_speed, \ + hitsound_on = hitsound, \ + clumsy_check = !can_clumsy_use) + RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform) /obj/item/shield/energy/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - return 0 + return FALSE /obj/item/shield/energy/IsReflect() - return (active) + return enabled -/obj/item/shield/energy/attack_self(mob/living/carbon/human/user) - if(clumsy_check && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50)) - to_chat(user, span_userdanger("You beat yourself in the head with [src]!")) - user.take_bodypart_damage(5) - active = !active - icon_state = "[base_icon_state][active]" +/* + * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM]. + */ +/obj/item/shield/energy/proc/on_transform(obj/item/source, mob/user, active) + SIGNAL_HANDLER - if(active) - force = on_force - throwforce = on_throwforce - throw_speed = on_throw_speed - w_class = WEIGHT_CLASS_BULKY - playsound(user, 'sound/weapons/saberon.ogg', 35, TRUE) - to_chat(user, span_notice("[src] is now active.")) - else - force = initial(force) - throwforce = initial(throwforce) - throw_speed = initial(throw_speed) - w_class = WEIGHT_CLASS_TINY - playsound(user, 'sound/weapons/saberoff.ogg', 35, TRUE) - to_chat(user, span_notice("[src] can now be concealed.")) - add_fingerprint(user) + enabled = active + + balloon_alert(user, "[name] [active ? "activated":"deactivated"]") + playsound(user ? user : src, active ? 'sound/weapons/saberon.ogg' : 'sound/weapons/saberoff.ogg', 35, TRUE) + return COMPONENT_NO_DEFAULT_MESSAGE /obj/item/shield/riot/tele name = "telescopic shield" desc = "An advanced riot shield made of lightweight materials that collapses for easy storage." - icon_state = "teleriot0" + icon_state = "teleriot" + worn_icon_state = "teleriot" lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi' custom_materials = list(/datum/material/iron = 3600, /datum/material/glass = 3600, /datum/material/silver = 270, /datum/material/titanium = 180) @@ -253,30 +255,36 @@ throw_speed = 3 throw_range = 4 w_class = WEIGHT_CLASS_NORMAL - var/active = 0 + /// Whether the shield is extended and protecting the user.. + var/extended = FALSE + +/obj/item/shield/riot/tele/Initialize() + . = ..() + AddComponent(/datum/component/transforming, \ + force_on = 8, \ + throwforce_on = 5, \ + throw_speed_on = 2, \ + hitsound_on = hitsound, \ + w_class_on = WEIGHT_CLASS_NORMAL, \ + attack_verb_continuous_on = list("smacks", "strikes", "cracks", "beats"), \ + attack_verb_simple_on = list("smack", "strike", "crack", "beat")) + RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform) /obj/item/shield/riot/tele/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - if(active) + if(extended) return ..() - return 0 + return FALSE -/obj/item/shield/riot/tele/attack_self(mob/living/user) - active = !active - icon_state = "teleriot[active]" - playsound(src.loc, 'sound/weapons/batonextend.ogg', 50, TRUE) +/* + * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM]. + * + * Allows it to be placed on back slot when active. + */ +/obj/item/shield/riot/tele/proc/on_transform(obj/item/source, mob/user, active) + SIGNAL_HANDLER - if(active) - force = 8 - throwforce = 5 - throw_speed = 2 - w_class = WEIGHT_CLASS_BULKY - slot_flags = ITEM_SLOT_BACK - to_chat(user, span_notice("You extend \the [src].")) - else - force = 3 - throwforce = 3 - throw_speed = 3 - w_class = WEIGHT_CLASS_NORMAL - slot_flags = null - to_chat(user, span_notice("[src] can now be concealed.")) - add_fingerprint(user) + extended = active + slot_flags = active ? ITEM_SLOT_BACK : null + playsound(user ? user : src, 'sound/weapons/batonextend.ogg', 50, TRUE) + balloon_alert(user, "[active ? "extended" : "collapsed"] [src]") + return COMPONENT_NO_DEFAULT_MESSAGE diff --git a/code/game/objects/items/storage/uplink_kits.dm b/code/game/objects/items/storage/uplink_kits.dm index 3452362f26b..57d4994ef48 100644 --- a/code/game/objects/items/storage/uplink_kits.dm +++ b/code/game/objects/items/storage/uplink_kits.dm @@ -89,7 +89,7 @@ new /obj/item/encryptionkey/syndicate(src) if(KIT_MURDER) - new /obj/item/melee/transforming/energy/sword/saber(src) + new /obj/item/melee/energy/sword/saber(src) new /obj/item/clothing/glasses/thermal/syndi(src) new /obj/item/card/emag(src) new /obj/item/clothing/shoes/chameleon/noslip(src) @@ -236,7 +236,7 @@ new /obj/item/dnainjector/geladikinesis(src) new /obj/item/dnainjector/cryokinesis(src) new /obj/item/gun/energy/temperature/security(src) - new /obj/item/melee/transforming/energy/sword/saber/blue(src) //see see it fits the theme bc its blue and ice is blue + new /obj/item/melee/energy/sword/saber/blue(src) //see see it fits the theme bc its blue and ice is blue if(KIT_TRAITOR_2006) //A kit so old, it's probably older than you. //This bundle is filled with the entire unlink contents traitors had access to in 2006, from OpenSS13. Notably the esword was not a choice but existed in code. new /obj/item/storage/toolbox/emergency/old/ancientbundle(src) //Items fit neatly into a classic toolbox just to remind you what the theme is. diff --git a/code/game/objects/items/tools/crowbar.dm b/code/game/objects/items/tools/crowbar.dm index 6a10293c92d..4ac024e5eb7 100644 --- a/code/game/objects/items/tools/crowbar.dm +++ b/code/game/objects/items/tools/crowbar.dm @@ -62,7 +62,7 @@ /obj/item/crowbar/power name = "jaws of life" desc = "A set of jaws of life, compressed through the magic of science." - icon_state = "jaws_pry" + icon_state = "jaws" inhand_icon_state = "jawsoflife" worn_icon_state = "jawsoflife" lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' @@ -73,10 +73,33 @@ toolspeed = 0.7 force_opens = TRUE +/obj/item/crowbar/power/Initialize() + . = ..() + AddComponent(/datum/component/transforming, \ + force_on = force, \ + throwforce_on = throwforce, \ + hitsound_on = hitsound, \ + w_class_on = w_class, \ + clumsy_check = FALSE) + RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform) + +/* + * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM]. + * + * Toggles between crowbar and wirecutters and gives feedback to the user. + */ +/obj/item/crowbar/power/proc/on_transform(obj/item/source, mob/user, active) + SIGNAL_HANDLER + + tool_behaviour = (active ? TOOL_WIRECUTTER : TOOL_CROWBAR) + balloon_alert(user, "attached [active ? "cutting" : "prying"]") + playsound(user ? user : src, 'sound/items/change_jaws.ogg', 50, TRUE) + return COMPONENT_NO_DEFAULT_MESSAGE + /obj/item/crowbar/power/syndicate name = "Syndicate jaws of life" desc = "A re-engineered copy of Nanotrasen's standard jaws of life. Can be used to force open airlocks in its crowbar configuration." - icon_state = "jaws_pry_syndie" + icon_state = "jaws_syndie" toolspeed = 0.5 force_opens = TRUE @@ -99,34 +122,6 @@ playsound(loc, "desecration", 50, TRUE, -1) return (BRUTELOSS) -/obj/item/crowbar/power/attack_self(mob/user) - playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, TRUE) - if(tool_behaviour == TOOL_CROWBAR) - tool_behaviour = TOOL_WIRECUTTER - balloon_alert(user, "attached cutting jaws") - usesound = 'sound/items/jaws_cut.ogg' - update_appearance() - - else - tool_behaviour = TOOL_CROWBAR - balloon_alert(user, "attached prying jaws") - usesound = 'sound/items/jaws_pry.ogg' - update_appearance() - -/obj/item/crowbar/power/update_icon_state() - if(tool_behaviour == TOOL_WIRECUTTER) - icon_state = "jaws_cutter" - else - icon_state = "jaws_pry" - return ..() - -/obj/item/crowbar/power/syndicate/update_icon_state() - if(tool_behaviour == TOOL_WIRECUTTER) - icon_state = "jaws_cutter_syndie" - else - icon_state = "jaws_pry_syndie" - return ..() - /obj/item/crowbar/power/attack(mob/living/carbon/C, mob/user) if(istype(C) && C.handcuffed && tool_behaviour == TOOL_WIRECUTTER) user.visible_message(span_notice("[user] cuts [C]'s restraints with [src]!")) diff --git a/code/game/objects/items/tools/screwdriver.dm b/code/game/objects/items/tools/screwdriver.dm index 19a47c47f85..b4e9030010f 100644 --- a/code/game/objects/items/tools/screwdriver.dm +++ b/code/game/objects/items/tools/screwdriver.dm @@ -72,7 +72,8 @@ /obj/item/screwdriver/power name = "hand drill" desc = "A simple powered hand drill." - icon_state = "drill_screw" + icon_state = "drill" + belt_icon_state = null inhand_icon_state = "drill" worn_icon_state = "drill" lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' @@ -89,9 +90,34 @@ usesound = 'sound/items/drill_use.ogg' toolspeed = 0.7 random_color = FALSE + greyscale_config = null + greyscale_config_belt = null greyscale_config_inhand_left = null greyscale_config_inhand_right = null +/obj/item/screwdriver/power/Initialize() + . = ..() + AddComponent(/datum/component/transforming, \ + force_on = force, \ + throwforce_on = throwforce, \ + hitsound_on = hitsound, \ + w_class_on = w_class, \ + clumsy_check = FALSE) + RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform) + +/* + * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM]. + * + * Toggles between crowbar and wirecutters and gives feedback to the user. + */ +/obj/item/screwdriver/power/proc/on_transform(obj/item/source, mob/user, active) + SIGNAL_HANDLER + + tool_behaviour = (active ? TOOL_WRENCH : TOOL_SCREWDRIVER) + balloon_alert(user, "attached [active ? "bolt bit" : "screw bit"]") + playsound(user ? user : src, 'sound/items/change_drill.ogg', 50, TRUE) + return COMPONENT_NO_DEFAULT_MESSAGE + /obj/item/screwdriver/power/examine() . = ..() . += " It's fitted with a [tool_behaviour == TOOL_SCREWDRIVER ? "screw" : "bolt"] bit." @@ -104,17 +130,6 @@ playsound(loc, 'sound/items/drill_use.ogg', 50, TRUE, -1) return(BRUTELOSS) -/obj/item/screwdriver/power/attack_self(mob/user) - playsound(get_turf(user), 'sound/items/change_drill.ogg', 50, TRUE) - if(tool_behaviour == TOOL_SCREWDRIVER) - tool_behaviour = TOOL_WRENCH - balloon_alert(user, "attached bolt bit") - icon_state = "drill_bolt" - else - tool_behaviour = TOOL_SCREWDRIVER - balloon_alert(user, "attached screw bit") - icon_state = "drill_screw" - /obj/item/screwdriver/cyborg name = "automated screwdriver" desc = "A powerful automated screwdriver, designed to be both precise and quick." diff --git a/code/game/objects/items/tools/wrench.dm b/code/game/objects/items/tools/wrench.dm index 259f261dc45..5582d3d41ec 100644 --- a/code/game/objects/items/tools/wrench.dm +++ b/code/game/objects/items/tools/wrench.dm @@ -82,43 +82,37 @@ name = "combat wrench" desc = "It's like a normal wrench but edgier. Can be found on the battlefield." icon_state = "wrench_combat" - inhand_icon_state = "wrench_combat" + belt_icon_state = "wrench_combat" attack_verb_continuous = list("devastates", "brutalizes", "commits a war crime against", "obliterates", "humiliates") attack_verb_simple = list("devastate", "brutalize", "commit a war crime against", "obliterate", "humiliate") tool_behaviour = null toolspeed = null - var/on = FALSE -/obj/item/wrench/combat/ComponentInitialize() +/obj/item/wrench/combat/Initialize() . = ..() - AddElement(/datum/element/update_icon_updates_onmob) + AddComponent(/datum/component/transforming, \ + force_on = 6, \ + throwforce_on = 8, \ + hitsound_on = hitsound, \ + w_class_on = WEIGHT_CLASS_NORMAL, \ + clumsy_check = FALSE) + RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform) -/obj/item/wrench/combat/attack_self(mob/living/user) - if(on) - on = FALSE - force = initial(force) - w_class = initial(w_class) - throwforce = initial(throwforce) - tool_behaviour = initial(tool_behaviour) - toolspeed = initial(toolspeed) - playsound(user, 'sound/weapons/saberoff.ogg', 5, TRUE) - to_chat(user, span_warning("[src] can now be kept at bay.")) - else - on = TRUE - force = 6 - w_class = WEIGHT_CLASS_NORMAL - throwforce = 8 +/* + * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM]. + * + * Gives it wrench behaviors when active. + */ +/obj/item/wrench/combat/proc/on_transform(obj/item/source, mob/user, active) + SIGNAL_HANDLER + + if(active) tool_behaviour = TOOL_WRENCH toolspeed = 1 - playsound(user, 'sound/weapons/saberon.ogg', 5, TRUE) - to_chat(user, span_warning("[src] is now active. Woe onto your enemies!")) - update_appearance() - -/obj/item/wrench/combat/update_icon_state() - if(on) - icon_state = "[initial(icon_state)]_on" - inhand_icon_state = "[initial(inhand_icon_state)]1" else - icon_state = "[initial(icon_state)]" - inhand_icon_state = "[initial(inhand_icon_state)]" - return ..() + tool_behaviour = initial(tool_behaviour) + toolspeed = initial(toolspeed) + + balloon_alert(user, "[name] [active ? "active, woe!":"restrained"]") + playsound(user ? user : src, active ? 'sound/weapons/saberon.ogg' : 'sound/weapons/saberoff.ogg', 5, TRUE) + return COMPONENT_NO_DEFAULT_MESSAGE diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index cb1bb7b00f0..3f156b1e074 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -325,63 +325,68 @@ /obj/item/toy/sword name = "toy sword" desc = "A cheap, plastic replica of an energy sword. Realistic sounds! Ages 8 and up." + icon_state = "e_sword" icon = 'icons/obj/transforming_energy.dmi' - icon_state = "sword0" - inhand_icon_state = "sword0" lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' - var/active = 0 w_class = WEIGHT_CLASS_SMALL attack_verb_continuous = list("attacks", "strikes", "hits") attack_verb_simple = list("attack", "strike", "hit") + /// Whether our sword has been multitooled to rainbow var/hacked = FALSE - var/saber_color + /// The color of our fake energy sword + var/saber_color = "blue" -/obj/item/toy/sword/attack_self(mob/user) - active = !( active ) - if (active) - to_chat(user, span_notice("You extend the plastic blade with a quick flick of your wrist.")) - playsound(user, 'sound/weapons/saberon.ogg', 20, TRUE) - if(hacked) - icon_state = "swordrainbow" - inhand_icon_state = "swordrainbow" - else - icon_state = "swordblue" - inhand_icon_state = "swordblue" - w_class = WEIGHT_CLASS_BULKY - else - to_chat(user, span_notice("You push the plastic blade back down into the handle.")) - playsound(user, 'sound/weapons/saberoff.ogg', 20, TRUE) - icon_state = "sword0" - inhand_icon_state = "sword0" - w_class = WEIGHT_CLASS_SMALL - add_fingerprint(user) +/obj/item/toy/sword/Initialize() + . = ..() + AddComponent(/datum/component/transforming, \ + throw_speed_on = throw_speed, \ + hitsound_on = hitsound, \ + clumsy_check = FALSE) + RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform) -// Copied from /obj/item/melee/transforming/energy/sword/attackby -/obj/item/toy/sword/attackby(obj/item/W, mob/living/user, params) - if(istype(W, /obj/item/toy/sword)) - if(HAS_TRAIT(W, TRAIT_NODROP) || HAS_TRAIT(src, TRAIT_NODROP)) - to_chat(user, span_warning("\the [HAS_TRAIT(src, TRAIT_NODROP) ? src : W] is stuck to your hand, you can't attach it to \the [HAS_TRAIT(src, TRAIT_NODROP) ? W : src]!")) + +/* + * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM]. + * + * Updates our icon to have the correct color, and give some feedback. + */ +/obj/item/toy/sword/proc/on_transform(obj/item/source, mob/user, active) + SIGNAL_HANDLER + + if(active) + icon_state = "[icon_state]_[saber_color]" + + balloon_alert(user, "[active ? "flicked out":"pushed in"] [src]") + playsound(user ? user : src, active ? 'sound/weapons/saberon.ogg' : 'sound/weapons/saberoff.ogg', 20, TRUE) + return COMPONENT_NO_DEFAULT_MESSAGE + +// Copied from /obj/item/melee/energy/sword/attackby +/obj/item/toy/sword/attackby(obj/item/weapon, mob/living/user, params) + if(istype(weapon, /obj/item/toy/sword)) + var/obj/item/toy/sword/attatched_sword = weapon + if(HAS_TRAIT(weapon, TRAIT_NODROP)) + to_chat(user, span_warning("[weapon] is stuck to your hand, you can't attach it to [src]!")) + return + else if(HAS_TRAIT(src, TRAIT_NODROP)) + to_chat(user, span_warning("[src] is stuck to your hand, you can't attach it to [weapon]!")) return else to_chat(user, span_notice("You attach the ends of the two plastic swords, making a single double-bladed toy! You're fake-cool.")) - var/obj/item/dualsaber/toy/newSaber = new /obj/item/dualsaber/toy(user.loc) - if(hacked) // That's right, we'll only check the "original" "sword". - newSaber.hacked = TRUE - newSaber.saber_color = "rainbow" - qdel(W) + var/obj/item/dualsaber/toy/new_saber = new /obj/item/dualsaber/toy(user.loc) + if(attatched_sword.hacked || hacked) + new_saber.hacked = TRUE + new_saber.saber_color = "rainbow" + qdel(weapon) qdel(src) - else if(W.tool_behaviour == TOOL_MULTITOOL) - if(!hacked) + user.put_in_hands(new_saber) + else if(weapon.tool_behaviour == TOOL_MULTITOOL) + if(hacked) + to_chat(user, span_warning("It's already fabulous!")) + else hacked = TRUE saber_color = "rainbow" to_chat(user, span_warning("RNBW_ENGAGE")) - - if(active) - icon_state = "swordrainbow" - user.update_inv_hands() - else - to_chat(user, span_warning("It's already fabulous!")) else return ..() diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index 41acb9be44a..c58ccbdb710 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -364,48 +364,30 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 attack_verb_continuous = list("stubs", "pokes") attack_verb_simple = list("stub", "poke") resistance_flags = FIRE_PROOF - var/extended = FALSE + /// Whether the switchblade starts extended or not. + var/start_extended = FALSE /obj/item/switchblade/Initialize() . = ..() AddElement(/datum/element/update_icon_updates_onmob) AddComponent(/datum/component/butchering, 7 SECONDS, 100) - set_extended(extended) - -/obj/item/switchblade/attack_self(mob/user) - playsound(src.loc, 'sound/weapons/batonextend.ogg', 50, TRUE) - set_extended(!extended) - -/obj/item/switchblade/update_icon_state() - icon_state = "[base_icon_state][extended ? "_ext" : ""]" - return ..() - -/obj/item/switchblade/proc/set_extended(new_extended) - extended = new_extended - update_icon_state() - if(extended) - force = 20 - w_class = WEIGHT_CLASS_NORMAL - throwforce = 23 - attack_verb_continuous = list("slashes", "stabs", "slices", "tears", "lacerates", "rips", "dices", "cuts") - attack_verb_simple = list("slash", "stab", "slice", "tear", "lacerate", "rip", "dice", "cut") - hitsound = 'sound/weapons/bladeslice.ogg' - sharpness = SHARP_EDGED - else - force = 3 - w_class = WEIGHT_CLASS_SMALL - throwforce = 5 - attack_verb_continuous = list("stubs", "pokes") - attack_verb_simple = list("stub", "poke") - hitsound = 'sound/weapons/genhit.ogg' - sharpness = NONE + AddComponent(/datum/component/transforming, \ + start_transformed = start_extended, \ + force_on = 20, \ + throwforce_on = 23, \ + throw_speed_on = throw_speed, \ + sharpness_on = SHARP_EDGED, \ + hitsound_on = 'sound/weapons/bladeslice.ogg', \ + w_class_on = WEIGHT_CLASS_NORMAL, \ + attack_verb_continuous_on = list("slashes", "stabs", "slices", "tears", "lacerates", "rips", "dices", "cuts"), \ + attack_verb_simple_on = list("slash", "stab", "slice", "tear", "lacerate", "rip", "dice", "cut")) /obj/item/switchblade/suicide_act(mob/user) user.visible_message(span_suicide("[user] is slitting [user.p_their()] own throat with [src]! It looks like [user.p_theyre()] trying to commit suicide!")) return (BRUTELOSS) /obj/item/switchblade/extended - extended = TRUE + start_extended = TRUE /obj/item/phone name = "red phone" diff --git a/code/game/objects/structures/crates_lockers/closets/gimmick.dm b/code/game/objects/structures/crates_lockers/closets/gimmick.dm index 80c6f12fee6..c61e340e45a 100644 --- a/code/game/objects/structures/crates_lockers/closets/gimmick.dm +++ b/code/game/objects/structures/crates_lockers/closets/gimmick.dm @@ -67,7 +67,7 @@ for(var/i in 1 to 3) new /obj/item/clothing/suit/armor/tdome/red(src) for(var/i in 1 to 3) - new /obj/item/melee/transforming/energy/sword/saber(src) + new /obj/item/melee/energy/sword/saber(src) for(var/i in 1 to 3) new /obj/item/gun/energy/laser(src) for(var/i in 1 to 3) @@ -86,7 +86,7 @@ for(var/i in 1 to 3) new /obj/item/clothing/suit/armor/tdome/green(src) for(var/i in 1 to 3) - new /obj/item/melee/transforming/energy/sword/saber(src) + new /obj/item/melee/energy/sword/saber(src) for(var/i in 1 to 3) new /obj/item/gun/energy/laser(src) for(var/i in 1 to 3) diff --git a/code/game/objects/structures/ghost_role_spawners.dm b/code/game/objects/structures/ghost_role_spawners.dm index d8f9f3fae07..a4ea6ed2597 100644 --- a/code/game/objects/structures/ghost_role_spawners.dm +++ b/code/game/objects/structures/ghost_role_spawners.dm @@ -187,7 +187,7 @@ var/can_transfer = TRUE //if golems can switch bodies to this new shell var/mob/living/owner = null //golem's owner if it has one short_desc = "You are a Free Golem. Your family worships The Liberator." - flavour_text = "In his infinite and divine wisdom, he set your clan free to travel the stars with a single declaration: \"Yeah go do whatever.\"" + flavour_text = "In his infinite and divine wisdom, he set your clan free to travel the stars with a single declaration: \"Yeah go do whatever.\"" /obj/effect/mob_spawn/human/golem/Initialize(mapload, datum/species/golem/species = null, mob/creator = null) if(species) //spawners list uses object name to register so this goes before ..() @@ -488,7 +488,7 @@ /datum/outfit/syndicate_empty/battlecruiser/assault/captain name = "Syndicate Battlecruiser Captain" - l_pocket = /obj/item/melee/transforming/energy/sword/saber/red + l_pocket = /obj/item/melee/energy/sword/saber/red r_pocket = /obj/item/melee/classic_baton/telescopic suit = /obj/item/clothing/suit/armor/vest/capcarapace/syndicate suit_store = /obj/item/gun/ballistic/revolver/mateba diff --git a/code/modules/antagonists/clown_ops/clown_weapons.dm b/code/modules/antagonists/clown_ops/clown_weapons.dm index d6c69905ff2..7d97c568b09 100644 --- a/code/modules/antagonists/clown_ops/clown_weapons.dm +++ b/code/modules/antagonists/clown_ops/clown_weapons.dm @@ -59,65 +59,65 @@ //BANANIUM SWORD -/obj/item/melee/transforming/energy/sword/bananium +/obj/item/melee/energy/sword/bananium name = "bananium sword" - desc = "An elegant weapon, for a more civilized age." + icon_state = "e_sword" + attack_verb_continuous = list("hits", "taps", "pokes") + attack_verb_simple = list("hit", "tap", "poke") force = 0 throwforce = 0 - force_on = 0 - throwforce_on = 0 hitsound = null - attack_verb_on = list("slips") - clumsy_check = FALSE - sharpness = NONE - sword_color = "yellow" - heat = 0 + embedding = null light_color = COLOR_YELLOW - var/next_trombone_allowed = 0 + sword_color_icon = "bananium" + active_heat = 0 + /// Cooldown for making a trombone noise for failing to make a bananium desword + COOLDOWN_DECLARE(next_trombone_allowed) -/obj/item/melee/transforming/energy/sword/bananium/Initialize() +/obj/item/melee/energy/sword/bananium/make_transformable() + AddComponent(/datum/component/transforming, \ + throw_speed_on = 4, \ + attack_verb_continuous_on = list("slips"), \ + attack_verb_simple_on = list("slip"), \ + clumsy_check = FALSE) + RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform) + +/obj/item/melee/energy/sword/bananium/on_transform(obj/item/source, mob/user, active) . = ..() adjust_slipperiness() -/* Adds or removes a slippery component, depending on whether the sword - * is active or not. +/* + * Adds or removes a slippery component, depending on whether the sword is active or not. */ -/obj/item/melee/transforming/energy/sword/proc/adjust_slipperiness() - if(active) +/obj/item/melee/energy/sword/bananium/proc/adjust_slipperiness() + if(blade_active) AddComponent(/datum/component/slippery, 60, GALOSHES_DONT_HELP) else qdel(GetComponent(/datum/component/slippery)) -/obj/item/melee/transforming/energy/sword/bananium/attack(mob/living/M, mob/living/user) - ..() - if(active) +/obj/item/melee/energy/sword/bananium/attack(mob/living/M, mob/living/user) + . = ..() + if(blade_active) var/datum/component/slippery/slipper = GetComponent(/datum/component/slippery) slipper.Slip(src, M) -/obj/item/melee/transforming/energy/sword/bananium/throw_impact(atom/hit_atom, throwingdatum) +/obj/item/melee/energy/sword/bananium/throw_impact(atom/hit_atom, throwingdatum) . = ..() - if(active) + if(blade_active) var/datum/component/slippery/slipper = GetComponent(/datum/component/slippery) slipper.Slip(src, hit_atom) -/obj/item/melee/transforming/energy/sword/bananium/attackby(obj/item/I, mob/living/user, params) - if((world.time > next_trombone_allowed) && istype(I, /obj/item/melee/transforming/energy/sword/bananium)) - next_trombone_allowed = world.time + 50 +/obj/item/melee/energy/sword/bananium/attackby(obj/item/weapon, mob/living/user, params) + if(COOLDOWN_FINISHED(src, next_trombone_allowed) && istype(weapon, /obj/item/melee/energy/sword/bananium)) + COOLDOWN_START(src, next_trombone_allowed, 5 SECONDS) to_chat(user, span_warning("You slap the two swords together. Sadly, they do not seem to fit!")) playsound(src, 'sound/misc/sadtrombone.ogg', 50) return TRUE return ..() -/obj/item/melee/transforming/energy/sword/bananium/transform_weapon(mob/living/user, supress_message_text) - . = ..() - adjust_slipperiness() - -/obj/item/melee/transforming/energy/sword/bananium/ignition_effect(atom/A, mob/user) - return "" - -/obj/item/melee/transforming/energy/sword/bananium/suicide_act(mob/user) - if(!active) - transform_weapon(user, TRUE) +/obj/item/melee/energy/sword/bananium/suicide_act(mob/user) + if(!blade_active) + attack_self(user) user.visible_message(span_suicide("[user] is [pick("slitting [user.p_their()] stomach open with", "falling on")] [src]! It looks like [user.p_theyre()] trying to commit seppuku, but the blade slips off of [user.p_them()] harmlessly!")) var/datum/component/slippery/slipper = GetComponent(/datum/component/slippery) slipper.Slip(src, user) @@ -128,42 +128,39 @@ /obj/item/shield/energy/bananium name = "bananium energy shield" desc = "A shield that stops most melee attacks, protects user from almost all energy projectiles, and can be thrown to slip opponents." + icon_state = "bananaeshield" throw_speed = 1 - clumsy_check = 0 - base_icon_state = "bananaeshield" force = 0 throwforce = 0 throw_range = 5 - on_force = 0 - on_throwforce = 0 - on_throw_speed = 1 -/obj/item/shield/energy/bananium/Initialize() + active_force = 0 + active_throwforce = 0 + active_throw_speed = 1 + can_clumsy_use = TRUE + +/obj/item/shield/energy/bananium/on_transform(obj/item/source, mob/user, active) . = ..() adjust_slipperiness() -/* Adds or removes a slippery component, depending on whether the shield - * is active or not. +/* + * Adds or removes a slippery component, depending on whether the shield is active or not. */ /obj/item/shield/energy/bananium/proc/adjust_slipperiness() - if(active) + if(enabled) AddComponent(/datum/component/slippery, 60, GALOSHES_DONT_HELP) else qdel(GetComponent(/datum/component/slippery)) -/obj/item/shield/energy/bananium/attack_self(mob/living/carbon/human/user) - . = ..() - adjust_slipperiness() - /obj/item/shield/energy/bananium/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force, gentle = FALSE, quickstart = TRUE) - if(active) + if(enabled) if(iscarbon(thrower)) var/mob/living/carbon/C = thrower C.throw_mode_on(THROW_MODE_TOGGLE) //so they can catch it on the return. return ..() /obj/item/shield/energy/bananium/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) - if(active) + if(enabled) var/caught = hit_atom.hitby(src, FALSE, FALSE, throwingdatum=throwingdatum) if(iscarbon(hit_atom) && !caught)//if they are a carbon and they didn't catch it var/datum/component/slippery/slipper = GetComponent(/datum/component/slippery) diff --git a/code/modules/awaymissions/mission_code/snowdin.dm b/code/modules/awaymissions/mission_code/snowdin.dm index f9aa22f913e..b66a2c96351 100644 --- a/code/modules/awaymissions/mission_code/snowdin.dm +++ b/code/modules/awaymissions/mission_code/snowdin.dm @@ -491,7 +491,7 @@ /obj/item/dnainjector/lasereyesmut = 7, /obj/item/gun/magic/wand/fireball/inert = 3, /obj/item/pneumatic_cannon = 15, - /obj/item/melee/transforming/energy/sword = 7, + /obj/item/melee/energy/sword = 7, /obj/item/book/granter/spell/knock = 15, /obj/item/book/granter/spell/summonitem = 20, /obj/item/book/granter/spell/forcewall = 17, diff --git a/code/modules/cargo/exports/lavaland.dm b/code/modules/cargo/exports/lavaland.dm index 83b1b73d82e..86539a59b2c 100644 --- a/code/modules/cargo/exports/lavaland.dm +++ b/code/modules/cargo/exports/lavaland.dm @@ -42,7 +42,7 @@ cost = CARGO_CRATE_VALUE * 80 unit_name = "major lava planet artifact" export_types = list(/obj/item/hierophant_club, - /obj/item/melee/transforming/cleaving_saw, + /obj/item/melee/cleaving_saw, /obj/item/organ/vocal_cords/colossus, /obj/machinery/anomalous_crystal, /obj/item/mayhem, diff --git a/code/modules/clothing/outfits/ert.dm b/code/modules/clothing/outfits/ert.dm index 16118b9ed6a..0be53013ce5 100644 --- a/code/modules/clothing/outfits/ert.dm +++ b/code/modules/clothing/outfits/ert.dm @@ -63,7 +63,7 @@ /obj/item/storage/box/survival/engineer = 1, ) glasses = /obj/item/clothing/glasses/thermal/eyepatch - l_pocket = /obj/item/melee/transforming/energy/sword/saber + l_pocket = /obj/item/melee/energy/sword/saber /datum/outfit/centcom/ert/security name = "ERT Security" @@ -330,7 +330,7 @@ back = /obj/item/storage/backpack/ert/clown backpack_contents = list( /obj/item/gun/ballistic/revolver/reverse = 1, - /obj/item/melee/transforming/energy/sword/bananium = 1, + /obj/item/melee/energy/sword/bananium = 1, /obj/item/shield/energy/bananium = 1, /obj/item/storage/box/survival/engineer = 1, ) @@ -512,7 +512,7 @@ gloves = /obj/item/clothing/gloves/tackler/combat/insulated mask = /obj/item/clothing/mask/gas/sechailer/swat shoes = /obj/item/clothing/shoes/combat/swat - l_pocket = /obj/item/melee/transforming/energy/sword/saber + l_pocket = /obj/item/melee/energy/sword/saber r_pocket = /obj/item/shield/energy l_hand = /obj/item/gun/energy/pulse/loyalpin diff --git a/code/modules/clothing/outfits/standard.dm b/code/modules/clothing/outfits/standard.dm index 06f3a31c87e..4ab0bc13d8a 100644 --- a/code/modules/clothing/outfits/standard.dm +++ b/code/modules/clothing/outfits/standard.dm @@ -236,7 +236,7 @@ gloves = /obj/item/clothing/gloves/color/black glasses = /obj/item/clothing/glasses/sunglasses shoes = /obj/item/clothing/shoes/sneakers/black - l_pocket = /obj/item/melee/transforming/energy/sword/saber + l_pocket = /obj/item/melee/energy/sword/saber l_hand = /obj/item/storage/secure/briefcase /datum/outfit/assassin/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) @@ -414,7 +414,7 @@ suit_store = /obj/item/tank/internals/oxygen back = /obj/item/storage/backpack/holding backpack_contents = list( - /obj/item/melee/transforming/energy/axe = 1, + /obj/item/melee/energy/axe = 1, /obj/item/storage/part_replacer/bluespace/tier4 = 1, /obj/item/gun/magic/wand/resurrection/debug = 1, /obj/item/gun/magic/wand/death/debug = 1, @@ -446,7 +446,7 @@ suit_store = /obj/item/tank/internals/oxygen back = /obj/item/storage/backpack/holding backpack_contents = list( - /obj/item/melee/transforming/energy/axe = 1, + /obj/item/melee/energy/axe = 1, /obj/item/storage/part_replacer/bluespace/tier4 = 1, /obj/item/gun/magic/wand/resurrection/debug = 1, /obj/item/gun/magic/wand/death/debug = 1, diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm index 34564f13e16..9839ee46a27 100644 --- a/code/modules/clothing/spacesuits/hardsuit.dm +++ b/code/modules/clothing/spacesuits/hardsuit.dm @@ -417,7 +417,7 @@ hardsuit_type = "syndi" w_class = WEIGHT_CLASS_NORMAL armor = list(MELEE = 40, BULLET = 50, LASER = 30, ENERGY = 40, BOMB = 35, BIO = 100, RAD = 50, FIRE = 50, ACID = 90, WOUND = 25) - allowed = list(/obj/item/gun, /obj/item/ammo_box,/obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/transforming/energy/sword/saber, /obj/item/restraints/handcuffs, /obj/item/tank/internals) + allowed = list(/obj/item/gun, /obj/item/ammo_box,/obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/energy/sword/saber, /obj/item/restraints/handcuffs, /obj/item/tank/internals) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/syndi jetpack = /obj/item/tank/jetpack/suit cell = /obj/item/stock_parts/cell/hyper @@ -1043,7 +1043,7 @@ inhand_icon_state = "syndie_hardsuit" hardsuit_type = "syndi" armor = list(MELEE = 40, BULLET = 50, LASER = 30, ENERGY = 40, BOMB = 35, BIO = 100, RAD = 50, FIRE = 100, ACID = 100, WOUND = 30) - allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/transforming/energy/sword/saber, /obj/item/restraints/handcuffs, /obj/item/tank/internals) + allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/energy/sword/saber, /obj/item/restraints/handcuffs, /obj/item/tank/internals) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/syndi slowdown = 0 shield_icon = "shield-red" diff --git a/code/modules/clothing/spacesuits/pirate.dm b/code/modules/clothing/spacesuits/pirate.dm index 03a1b257b6c..ba44254d11a 100644 --- a/code/modules/clothing/spacesuits/pirate.dm +++ b/code/modules/clothing/spacesuits/pirate.dm @@ -16,7 +16,7 @@ desc = "A modified suit to allow space pirates to board shuttles and stations while avoiding the maw of the void. Comes with additional protection, and is lighter to move in." icon_state = "spacepirate" w_class = WEIGHT_CLASS_NORMAL - allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals, /obj/item/melee/transforming/energy/sword/pirate, /obj/item/clothing/glasses/eyepatch, /obj/item/reagent_containers/food/drinks/bottle/rum) + allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals, /obj/item/melee/energy/sword/pirate, /obj/item/clothing/glasses/eyepatch, /obj/item/reagent_containers/food/drinks/bottle/rum) slowdown = 0 armor = list(MELEE = 30, BULLET = 50, LASER = 30,ENERGY = 40, BOMB = 30, BIO = 30, RAD = 30, FIRE = 60, ACID = 75) strip_delay = 40 diff --git a/code/modules/clothing/spacesuits/plasmamen.dm b/code/modules/clothing/spacesuits/plasmamen.dm index 8f00a602f97..97b3212b3b6 100644 --- a/code/modules/clothing/spacesuits/plasmamen.dm +++ b/code/modules/clothing/spacesuits/plasmamen.dm @@ -4,7 +4,7 @@ /obj/item/clothing/suit/space/eva/plasmaman name = "EVA plasma envirosuit" desc = "A special plasma containment suit designed to be space-worthy, as well as worn over other clothing. Like its smaller counterpart, it can automatically extinguish the wearer in a crisis, and holds twice as many charges." - allowed = list(/obj/item/gun, /obj/item/ammo_casing, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/transforming/energy/sword, /obj/item/restraints/handcuffs, /obj/item/tank) + allowed = list(/obj/item/gun, /obj/item/ammo_casing, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/energy/sword, /obj/item/restraints/handcuffs, /obj/item/tank) armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 100, RAD = 0, FIRE = 100, ACID = 75) resistance_flags = FIRE_PROOF icon_state = "plasmaman_suit" diff --git a/code/modules/clothing/spacesuits/syndi.dm b/code/modules/clothing/spacesuits/syndi.dm index bf907fbbbc8..da5ff41829d 100644 --- a/code/modules/clothing/spacesuits/syndi.dm +++ b/code/modules/clothing/spacesuits/syndi.dm @@ -12,7 +12,7 @@ inhand_icon_state = "space_suit_syndicate" desc = "Has a tag on it: Totally not property of an enemy corporation, honest!" w_class = WEIGHT_CLASS_NORMAL - allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/transforming/energy/sword/saber, /obj/item/restraints/handcuffs, /obj/item/tank/internals) + allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/energy/sword/saber, /obj/item/restraints/handcuffs, /obj/item/tank/internals) armor = list(MELEE = 40, BULLET = 50, LASER = 30,ENERGY = 40, BOMB = 30, BIO = 30, RAD = 30, FIRE = 80, ACID = 85) cell = /obj/item/stock_parts/cell/hyper diff --git a/code/modules/clothing/suits/costume.dm b/code/modules/clothing/suits/costume.dm index b819f322fbe..b6198419e23 100644 --- a/code/modules/clothing/suits/costume.dm +++ b/code/modules/clothing/suits/costume.dm @@ -18,7 +18,7 @@ desc = "Yarr." icon_state = "pirate" inhand_icon_state = "pirate" - allowed = list(/obj/item/melee/transforming/energy/sword/pirate, /obj/item/clothing/glasses/eyepatch, /obj/item/reagent_containers/food/drinks/bottle/rum) + allowed = list(/obj/item/melee/energy/sword/pirate, /obj/item/clothing/glasses/eyepatch, /obj/item/reagent_containers/food/drinks/bottle/rum) species_exception = list(/datum/species/golem) /obj/item/clothing/suit/pirate/armored diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_cake.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_cake.dm index 23600acdda4..ae032445399 100644 --- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_cake.dm +++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_cake.dm @@ -81,7 +81,7 @@ name = "Energy cake" reqs = list( /obj/item/food/cake/birthday = 1, - /obj/item/melee/transforming/energy/sword = 1, + /obj/item/melee/energy/sword = 1, ) blacklist = list(/obj/item/food/cake/birthday/energy) result = /obj/item/food/cake/birthday/energy diff --git a/code/modules/holodeck/items.dm b/code/modules/holodeck/items.dm index 2a8189eb084..54caffca6cb 100644 --- a/code/modules/holodeck/items.dm +++ b/code/modules/holodeck/items.dm @@ -7,63 +7,29 @@ // Items // -/obj/item/holo - damtype = STAMINA - -/obj/item/holo/esword +/obj/item/melee/energy/sword/holographic name = "holographic energy sword" desc = "May the force be with you. Sorta." - icon = 'icons/obj/transforming_energy.dmi' - icon_state = "sword0" - lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' - force = 3.0 + damtype = STAMINA throw_speed = 2 - throw_range = 5 throwforce = 0 - w_class = WEIGHT_CLASS_SMALL - hitsound = "swing_hit" - armour_penetration = 50 - var/active = 0 - var/saber_color + embedding = null + sword_color_icon = null -/obj/item/holo/esword/green/Initialize() + active_throwforce = 0 + active_sharpness = NONE + active_heat = 0 + +/obj/item/melee/energy/sword/holographic/Initialize() . = ..() - saber_color = "green" + if(!sword_color_icon) + sword_color_icon = pick("red", "blue", "green", "purple") -/obj/item/holo/esword/red/Initialize() - . = ..() - saber_color = "red" +/obj/item/melee/energy/sword/holographic/green + sword_color_icon = "green" -/obj/item/holo/esword/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - if(active) - return ..() - return 0 - -/obj/item/holo/esword/attack(target, mob/user) - ..() - -/obj/item/holo/esword/Initialize() - . = ..() - saber_color = pick("red","blue","green","purple") - -/obj/item/holo/esword/attack_self(mob/living/user) - active = !active - if (active) - force = 30 - icon_state = "sword[saber_color]" - w_class = WEIGHT_CLASS_BULKY - hitsound = 'sound/weapons/blade1.ogg' - playsound(user, 'sound/weapons/saberon.ogg', 20, TRUE) - to_chat(user, span_notice("[src] is now active.")) - else - force = 3 - icon_state = "sword0" - w_class = WEIGHT_CLASS_SMALL - hitsound = "swing_hit" - playsound(user, 'sound/weapons/saberoff.ogg', 20, TRUE) - to_chat(user, span_notice("[src] can now be concealed.")) - return +/obj/item/melee/energy/sword/holographic/red + sword_color_icon = "red" //BASKETBALL OBJECTS diff --git a/code/modules/mining/abandoned_crates.dm b/code/modules/mining/abandoned_crates.dm index 6966b41d5d5..e21110678a6 100644 --- a/code/modules/mining/abandoned_crates.dm +++ b/code/modules/mining/abandoned_crates.dm @@ -196,7 +196,7 @@ if(88) new /obj/item/reagent_containers/food/drinks/bottle/lizardwine(src) if(89) - new /obj/item/melee/transforming/energy/sword/bananium(src) + new /obj/item/melee/energy/sword/bananium(src) if(90) new /obj/item/dnainjector/wackymut(src) if(91) diff --git a/code/modules/mining/lavaland/megafauna_loot.dm b/code/modules/mining/lavaland/megafauna_loot.dm index 07062ac6cb8..3706bea017b 100644 --- a/code/modules/mining/lavaland/megafauna_loot.dm +++ b/code/modules/mining/lavaland/megafauna_loot.dm @@ -795,88 +795,84 @@ //Blood-Drunk Miner: Cleaving Saw -/obj/item/melee/transforming/cleaving_saw + +/obj/item/melee/cleaving_saw name = "cleaving saw" desc = "This saw, effective at drawing the blood of beasts, transforms into a long cleaver that makes use of centrifugal force." - force = 12 - force_on = 20 //force when active - throwforce = 20 - throwforce_on = 20 icon = 'icons/obj/lavaland/artefacts.dmi' lefthand_file = 'icons/mob/inhands/64x64_lefthand.dmi' righthand_file = 'icons/mob/inhands/64x64_righthand.dmi' + icon_state = "cleaving_saw" + worn_icon_state = "cleaving_saw" + attack_verb_continuous = list("attacks", "saws", "slices", "tears", "lacerates", "rips", "dices", "cuts") + attack_verb_simple = list("attack", "saw", "slice", "tear", "lacerate", "rip", "dice", "cut") + force = 12 + throwforce = 20 inhand_x_dimension = 64 inhand_y_dimension = 64 - icon_state = "cleaving_saw" - icon_state_on = "cleaving_saw_open" - worn_icon_state = "cleaving_saw" slot_flags = ITEM_SLOT_BELT - attack_verb_off = list("attacks", "saws", "slices", "tears", "lacerates", "rips", "dices", "cuts") - attack_verb_on = list("cleaves", "swipes", "slashes", "chops") hitsound = 'sound/weapons/bladeslice.ogg' - hitsound_on = 'sound/weapons/bladeslice.ogg' w_class = WEIGHT_CLASS_BULKY sharpness = SHARP_EDGED - faction_bonus_force = 30 - nemesis_factions = list("mining", "boss") - resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF - var/transform_cooldown + /// Whether the saw is open or not + var/is_open = FALSE + /// List of factions we deal bonus damage to + var/list/nemesis_factions = list("mining", "boss") + /// Amount of damage we deal to the above factions + var/faction_bonus_force = 30 + /// Whether the cleaver is actively AoE swiping something. var/swiping = FALSE + /// Amount of bleed stacks gained per hit var/bleed_stacks_per_hit = 3 + /// Force when the saw is opened. + var/open_force = 20 + /// Throwforce when the saw is opened. + var/open_throwforce = 20 -/obj/item/melee/transforming/cleaving_saw/examine(mob/user) +/obj/item/melee/cleaving_saw/Initialize() . = ..() - . += "It is [active ? "open, will cleave enemies in a wide arc and deal additional damage to fauna":"closed, and can be used for rapid consecutive attacks that cause fauna to bleed"].\n"+\ - "Both modes will build up existing bleed effects, doing a burst of high damage if the bleed is built up high enough.\n"+\ - "Transforming it immediately after an attack causes the next attack to come out faster." + AddComponent(/datum/component/transforming, \ + transform_cooldown_time = (CLICK_CD_MELEE * 0.25), \ + force_on = open_force, \ + throwforce_on = open_throwforce, \ + sharpness_on = sharpness, \ + hitsound_on = hitsound, \ + w_class_on = w_class, \ + attack_verb_continuous_on = list("cleaves", "swipes", "slashes", "chops"), \ + attack_verb_simple_on = list("cleave", "swipe", "slash", "chop")) + RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform) -/obj/item/melee/transforming/cleaving_saw/suicide_act(mob/user) - user.visible_message(span_suicide("[user] is [active ? "closing [src] on [user.p_their()] neck" : "opening [src] into [user.p_their()] chest"]! It looks like [user.p_theyre()] trying to commit suicide!")) - transform_cooldown = 0 - transform_weapon(user, TRUE) +/obj/item/melee/cleaving_saw/examine(mob/user) + . = ..() + . += span_notice("It is [is_open ? "open, will cleave enemies in a wide arc and deal additional damage to fauna":"closed, and can be used for rapid consecutive attacks that cause fauna to bleed"].") + . += span_notice("Both modes will build up existing bleed effects, doing a burst of high damage if the bleed is built up high enough.") + . += span_notice("Transforming it immediately after an attack causes the next attack to come out faster.") + +/obj/item/melee/cleaving_saw/suicide_act(mob/user) + user.visible_message(span_suicide("[user] is [is_open ? "closing [src] on [user.p_their()] neck" : "opening [src] into [user.p_their()] chest"]! It looks like [user.p_theyre()] trying to commit suicide!")) + attack_self(user) return BRUTELOSS -/obj/item/melee/transforming/cleaving_saw/transform_weapon(mob/living/user, supress_message_text) - if(transform_cooldown > world.time) - return FALSE +/obj/item/melee/cleaving_saw/melee_attack_chain(mob/user, atom/target, params) . = ..() - if(.) - transform_cooldown = world.time + (CLICK_CD_MELEE * 0.5) - user.changeNext_move(CLICK_CD_MELEE * 0.25) - -/obj/item/melee/transforming/cleaving_saw/transform_messages(mob/living/user, supress_message_text) - if(!supress_message_text) - if(active) - to_chat(user, span_notice("You open [src]. It will now cleave enemies in a wide arc and deal additional damage to fauna.")) - else - to_chat(user, span_notice("You close [src]. It will now attack rapidly and cause fauna to bleed.")) - playsound(user, 'sound/magic/clockwork/fellowship_armory.ogg', 35, TRUE, frequency = 90000 - (active * 30000)) - -/obj/item/melee/transforming/cleaving_saw/clumsy_transform_effect(mob/living/user) - if(HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50)) - to_chat(user, span_warning("You accidentally cut yourself with [src], like a doofus!")) - user.take_bodypart_damage(10) - -/obj/item/melee/transforming/cleaving_saw/melee_attack_chain(mob/user, atom/target, params) - ..() - if(!active) + if(!is_open) user.changeNext_move(CLICK_CD_MELEE * 0.5) //when closed, it attacks very rapidly -/obj/item/melee/transforming/cleaving_saw/nemesis_effects(mob/living/user, mob/living/target) - if(istype(target, /mob/living/simple_animal/hostile/asteroid/elite)) - return - var/datum/status_effect/stacking/saw_bleed/B = target.has_status_effect(STATUS_EFFECT_SAWBLEED) - if(!B) - target.apply_status_effect(STATUS_EFFECT_SAWBLEED,bleed_stacks_per_hit) - else - B.add_stacks(bleed_stacks_per_hit) - -/obj/item/melee/transforming/cleaving_saw/attack(mob/living/target, mob/living/carbon/human/user) - if(!active || swiping || !target.density || get_turf(target) == get_turf(user)) - if(!active) +/obj/item/melee/cleaving_saw/attack(mob/living/target, mob/living/carbon/human/user) + if(!is_open || swiping || !target.density || get_turf(target) == get_turf(user)) + if(!is_open) faction_bonus_force = 0 - ..() - if(!active) + var/is_nemesis_faction = FALSE + for(var/found_faction in target.faction) + if(found_faction in nemesis_factions) + is_nemesis_faction = TRUE + force += faction_bonus_force + nemesis_effects(user, target) + break + . = ..() + if(is_nemesis_faction) + force -= faction_bonus_force + if(!is_open) faction_bonus_force = initial(faction_bonus_force) else var/turf/user_turf = get_turf(user) @@ -890,6 +886,36 @@ melee_attack_chain(user, living_target) swiping = FALSE +/* + * If we're attacking [target]s in our nemesis list, apply unique effects. + * + * user - the mob attacking with the saw + * target - the mob being attacked + */ +/obj/item/melee/cleaving_saw/proc/nemesis_effects(mob/living/user, mob/living/target) + if(istype(target, /mob/living/simple_animal/hostile/asteroid/elite)) + return + var/datum/status_effect/stacking/saw_bleed/existing_bleed = target.has_status_effect(STATUS_EFFECT_SAWBLEED) + if(existing_bleed) + existing_bleed.add_stacks(bleed_stacks_per_hit) + else + target.apply_status_effect(STATUS_EFFECT_SAWBLEED, bleed_stacks_per_hit) + +/* + * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM]. + * + * Gives feedback and makes the nextmove after transforming much quicker. + */ +/obj/item/melee/cleaving_saw/proc/on_transform(obj/item/source, mob/user, active) + SIGNAL_HANDLER + + is_open = active + user.changeNext_move(CLICK_CD_MELEE * 0.25) + + balloon_alert(user, "[active ? "opened":"closed"] [src]") + playsound(user ? user : src, 'sound/magic/clockwork/fellowship_armory.ogg', 35, TRUE, frequency = 90000 - (is_open * 30000)) + return COMPONENT_NO_DEFAULT_MESSAGE + //Legion: Staff of Storms /obj/item/storm_staff diff --git a/code/modules/mining/lavaland/tendril_loot.dm b/code/modules/mining/lavaland/tendril_loot.dm index cdcca6004aa..826acb13433 100644 --- a/code/modules/mining/lavaland/tendril_loot.dm +++ b/code/modules/mining/lavaland/tendril_loot.dm @@ -591,7 +591,7 @@ armor = list(MELEE = 30, BULLET = 30, LASER = 10, ENERGY = 20, BOMB = 50, BIO = 100, RAD = 10, FIRE = 100, ACID = 100) max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF - allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/pickaxe, /obj/item/spear, /obj/item/organ/regenerative_core/legion, /obj/item/kitchen/knife, /obj/item/kinetic_crusher, /obj/item/resonator, /obj/item/melee/transforming/cleaving_saw) + allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/pickaxe, /obj/item/spear, /obj/item/organ/regenerative_core/legion, /obj/item/kitchen/knife, /obj/item/kinetic_crusher, /obj/item/resonator, /obj/item/melee/cleaving_saw) /obj/item/clothing/suit/space/hardsuit/berserker/Initialize() diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index 98f76e062e5..51ce2ba4e46 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -519,7 +519,7 @@ name = "Syndicate Assault" basic_modules = list( /obj/item/assembly/flash/cyborg, - /obj/item/melee/transforming/energy/sword/cyborg, + /obj/item/melee/energy/sword/cyborg, /obj/item/gun/energy/printer, /obj/item/gun/ballistic/revolver/grenadelauncher/cyborg, /obj/item/card/emag, @@ -556,7 +556,7 @@ /obj/item/cautery, /obj/item/surgicaldrill, /obj/item/scalpel, - /obj/item/melee/transforming/energy/sword/cyborg/saw, + /obj/item/melee/energy/sword/cyborg/saw, /obj/item/roller/robo, /obj/item/crowbar/cyborg, /obj/item/extinguisher/mini, diff --git a/code/modules/mob/living/simple_animal/bot/SuperBeepsky.dm b/code/modules/mob/living/simple_animal/bot/SuperBeepsky.dm index 2b3a37ef215..8948109f61f 100644 --- a/code/modules/mob/living/simple_animal/bot/SuperBeepsky.dm +++ b/code/modules/mob/living/simple_animal/bot/SuperBeepsky.dm @@ -5,7 +5,7 @@ icon_state = "grievous" health = 150 maxHealth = 150 - baton_type = /obj/item/melee/transforming/energy/sword/saber + baton_type = /obj/item/melee/energy/sword/saber base_speed = 4 //he's a fast fucker var/block_chance = 50 weapon_force = 30 diff --git a/code/modules/mob/living/simple_animal/bot/construction.dm b/code/modules/mob/living/simple_animal/bot/construction.dm index 5d31eded154..0613b78b417 100644 --- a/code/modules/mob/living/simple_animal/bot/construction.dm +++ b/code/modules/mob/living/simple_animal/bot/construction.dm @@ -414,7 +414,7 @@ new /obj/item/toy/sword(Tsec) if(ASSEMBLY_FIFTH_STEP) - if(istype(I, /obj/item/melee/transforming/energy/sword/saber)) + if(istype(I, /obj/item/melee/energy/sword/saber)) if(swordamt < 3) if(!user.temporarilyRemoveItemFromInventory(I)) return @@ -439,7 +439,7 @@ icon_state = initial(icon_state) to_chat(user, span_notice("You unbolt [src]'s energy swords.")) for(var/IS in 1 to swordamt) - new /obj/item/melee/transforming/energy/sword/saber(Tsec) + new /obj/item/melee/energy/sword/saber(Tsec) //Firebot Assembly diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm index ed3fb305d15..c09d24b4bcd 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm @@ -41,8 +41,8 @@ Difficulty: Medium ranged_cooldown_time = 1.6 SECONDS pixel_x = -16 base_pixel_x = -16 - crusher_loot = list(/obj/item/melee/transforming/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator, /obj/item/crusher_trophy/miner_eye) - loot = list(/obj/item/melee/transforming/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator) + crusher_loot = list(/obj/item/melee/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator, /obj/item/crusher_trophy/miner_eye) + loot = list(/obj/item/melee/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator) wander = FALSE del_on_death = TRUE blood_volume = BLOOD_VOLUME_NORMAL @@ -50,7 +50,7 @@ Difficulty: Medium achievement_type = /datum/award/achievement/boss/blood_miner_kill crusher_achievement_type = /datum/award/achievement/boss/blood_miner_crusher score_achievement_type = /datum/award/score/blood_miner_score - var/obj/item/melee/transforming/cleaving_saw/miner/miner_saw + var/obj/item/melee/cleaving_saw/miner/miner_saw var/time_until_next_transform = 0 var/dashing = FALSE var/dash_cooldown = 0 @@ -119,13 +119,13 @@ Difficulty: Medium shoot_ka() transform_weapon() -/obj/item/melee/transforming/cleaving_saw/miner //nerfed saw because it is very murdery +/obj/item/melee/cleaving_saw/miner //nerfed saw because it is very murdery force = 6 - force_on = 10 + open_force = 10 -/obj/item/melee/transforming/cleaving_saw/miner/attack(mob/living/target, mob/living/carbon/human/user) +/obj/item/melee/cleaving_saw/miner/attack(mob/living/target, mob/living/carbon/human/user) target.add_stun_absorption("miner", 10, INFINITY) - ..() + . = ..() target.stun_absorption -= "miner" /obj/projectile/kinetic/miner @@ -260,15 +260,14 @@ Difficulty: Medium /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/proc/transform_weapon() if(time_until_next_transform <= world.time) - miner_saw.transform_cooldown = 0 - miner_saw.transform_weapon(src, TRUE) - if(!miner_saw.active) + miner_saw.attack_self(src) + if(!miner_saw.is_open) rapid_melee = 5 // 4 deci cooldown before changes, npcpool subsystem wait is 20, 20/4 = 5 else rapid_melee = 3 // same thing but halved (slightly rounded up) transform_stop_attack = TRUE - icon_state = "miner[miner_saw.active ? "_transformed":""]" - icon_living = "miner[miner_saw.active ? "_transformed":""]" + icon_state = "miner[miner_saw.is_open ? "_transformed":""]" + icon_living = "miner[miner_saw.is_open ? "_transformed":""]" update_cooldowns(list(COOLDOWN_UPDATE_SET_TRANSFORM = rand(5 SECONDS, 10 SECONDS))) /obj/effect/temp_visual/dir_setting/miner_death diff --git a/code/modules/mob/living/simple_animal/hostile/pirate.dm b/code/modules/mob/living/simple_animal/hostile/pirate.dm index 9414eba70f3..750cf4dfab5 100644 --- a/code/modules/mob/living/simple_animal/hostile/pirate.dm +++ b/code/modules/mob/living/simple_animal/hostile/pirate.dm @@ -25,7 +25,7 @@ unsuitable_atmos_damage = 7.5 speak_emote = list("yarrs") loot = list(/obj/effect/mob_spawn/human/corpse/pirate, - /obj/item/melee/transforming/energy/sword/pirate) + /obj/item/melee/energy/sword/pirate) del_on_death = 1 faction = list("pirate") diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm index 9ff2a05464a..deee8229680 100644 --- a/code/modules/paperwork/pen.dm +++ b/code/modules/paperwork/pen.dm @@ -122,6 +122,10 @@ desc = "It's an expensive [current_skin] fountain pen. The nib is quite sharp." /obj/item/pen/attack_self(mob/living/carbon/user) + . = ..() + if(.) + return + var/deg = input(user, "What angle would you like to rotate the pen head to? (1-360)", "Rotate Pen Head") as null|num if(deg && (deg > 0 && deg <= 360)) degrees = deg @@ -216,62 +220,60 @@ /obj/item/pen/edagger attack_verb_continuous = list("slashes", "stabs", "slices", "tears", "lacerates", "rips", "dices", "cuts") //these won't show up if the pen is off attack_verb_simple = list("slash", "stab", "slice", "tear", "lacerate", "rip", "dice", "cut") - sharpness = SHARP_EDGED - var/on = FALSE + sharpness = SHARP_POINTY + /// The real name of our item when extended. + var/hidden_name = "energy dagger" + /// Whether or pen is extended + var/extended = FALSE -/obj/item/pen/edagger/ComponentInitialize() +/obj/item/pen/edagger/Initialize() . = ..() - AddComponent(/datum/component/butchering, 60, 100, 0, 'sound/weapons/blade1.ogg') - AddElement(/datum/element/update_icon_updates_onmob) - -/obj/item/pen/edagger/get_sharpness() - return on * sharpness + AddComponent(/datum/component/butchering, _speed = 6 SECONDS, _butcher_sound = 'sound/weapons/blade1.ogg') + AddComponent(/datum/component/transforming, \ + force_on = 18, \ + throwforce_on = 35, \ + throw_speed_on = 4, \ + sharpness_on = SHARP_EDGED, \ + w_class_on = WEIGHT_CLASS_NORMAL) + RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform) /obj/item/pen/edagger/suicide_act(mob/user) . = BRUTELOSS - if(on) + if(extended) user.visible_message(span_suicide("[user] forcefully rams the pen into their mouth!")) else user.visible_message(span_suicide("[user] is holding a pen up to their mouth! It looks like [user.p_theyre()] trying to commit suicide!")) attack_self(user) -/obj/item/pen/edagger/attack_self(mob/living/user) - if(on) - on = FALSE - force = initial(force) - throw_speed = initial(throw_speed) - w_class = initial(w_class) - name = initial(name) - hitsound = initial(hitsound) - embedding = list(embed_chance = EMBED_CHANCE) - throwforce = initial(throwforce) - playsound(user, 'sound/weapons/saberoff.ogg', 5, TRUE) - to_chat(user, span_warning("[src] can now be concealed.")) - else - on = TRUE - force = 18 - throw_speed = 4 - w_class = WEIGHT_CLASS_NORMAL - name = "energy dagger" - hitsound = 'sound/weapons/blade1.ogg' - embedding = list(embed_chance = 100) //rule of cool - throwforce = 35 - playsound(user, 'sound/weapons/saberon.ogg', 5, TRUE) - to_chat(user, span_warning("[src] is now active.")) - updateEmbedding() - update_appearance() +/* + * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM]. + * + * Handles swapping their icon files to edagger related icon files - + * as they're supposed to look like a normal pen. + */ +/obj/item/pen/edagger/proc/on_transform(obj/item/source, mob/user, active) + SIGNAL_HANDLER -/obj/item/pen/edagger/update_icon_state() - if(on) - icon_state = inhand_icon_state = "edagger" + extended = active + if(active) + name = hidden_name + icon_state = "edagger" + inhand_icon_state = "edagger" lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' + embedding = list(embed_chance = 100) // Rule of cool else - icon_state = initial(icon_state) //looks like a normal pen when off. + name = initial(name) + icon_state = initial(icon_state) inhand_icon_state = initial(inhand_icon_state) lefthand_file = initial(lefthand_file) righthand_file = initial(righthand_file) - return ..() + embedding = list(embed_chance = EMBED_CHANCE) + + updateEmbedding() + balloon_alert(user, "[hidden_name] [active ? "active":"concealed"]") + playsound(user ? user : src, active ? 'sound/weapons/saberon.ogg' : 'sound/weapons/saberoff.ogg', 5, TRUE) + return COMPONENT_NO_DEFAULT_MESSAGE /obj/item/pen/survival name = "survival pen" diff --git a/code/modules/projectiles/guns/ballistic.dm b/code/modules/projectiles/guns/ballistic.dm index cbc9842ed8a..aad506791e1 100644 --- a/code/modules/projectiles/guns/ballistic.dm +++ b/code/modules/projectiles/guns/ballistic.dm @@ -548,7 +548,7 @@ GLOBAL_LIST_INIT(gun_saw_types, typecacheof(list( /obj/item/gun/energy/plasmacutter, - /obj/item/melee/transforming/energy, + /obj/item/melee/energy, /obj/item/dualsaber ))) diff --git a/code/modules/ruins/lavaland_ruin_code.dm b/code/modules/ruins/lavaland_ruin_code.dm index 67a7261c104..a451fed469c 100644 --- a/code/modules/ruins/lavaland_ruin_code.dm +++ b/code/modules/ruins/lavaland_ruin_code.dm @@ -162,7 +162,7 @@ /datum/outfit/lavaland_syndicate/comms name = "Lavaland Syndicate Comms Agent" - r_hand = /obj/item/melee/transforming/energy/sword/saber + r_hand = /obj/item/melee/energy/sword/saber mask = /obj/item/clothing/mask/chameleon/gps suit = /obj/item/clothing/suit/armor/vest diff --git a/code/modules/surgery/advanced/lobotomy.dm b/code/modules/surgery/advanced/lobotomy.dm index 0c0046dfe5d..710fcfcbe77 100644 --- a/code/modules/surgery/advanced/lobotomy.dm +++ b/code/modules/surgery/advanced/lobotomy.dm @@ -25,7 +25,7 @@ name = "perform lobotomy" implements = list( TOOL_SCALPEL = 85, - /obj/item/melee/transforming/energy/sword = 55, + /obj/item/melee/energy/sword = 55, /obj/item/kitchen/knife = 35, /obj/item/shard = 25, /obj/item = 20) diff --git a/code/modules/surgery/coronary_bypass.dm b/code/modules/surgery/coronary_bypass.dm index a6630578d3b..1a4887b3830 100644 --- a/code/modules/surgery/coronary_bypass.dm +++ b/code/modules/surgery/coronary_bypass.dm @@ -23,7 +23,7 @@ name = "incise heart" implements = list( TOOL_SCALPEL = 90, - /obj/item/melee/transforming/energy/sword = 45, + /obj/item/melee/energy/sword = 45, /obj/item/kitchen/knife = 45, /obj/item/shard = 25) time = 16 diff --git a/code/modules/surgery/gastrectomy.dm b/code/modules/surgery/gastrectomy.dm index a7b4af48f6c..5698aa85f5f 100644 --- a/code/modules/surgery/gastrectomy.dm +++ b/code/modules/surgery/gastrectomy.dm @@ -24,7 +24,7 @@ name = "remove lower duodenum" implements = list( TOOL_SCALPEL = 95, - /obj/item/melee/transforming/energy/sword = 65, + /obj/item/melee/energy/sword = 65, /obj/item/kitchen/knife = 45, /obj/item/shard = 35) time = 52 diff --git a/code/modules/surgery/hepatectomy.dm b/code/modules/surgery/hepatectomy.dm index 1899f0deaf1..2d2de0dd1cf 100644 --- a/code/modules/surgery/hepatectomy.dm +++ b/code/modules/surgery/hepatectomy.dm @@ -23,7 +23,7 @@ name = "remove damaged liver section" implements = list( TOOL_SCALPEL = 95, - /obj/item/melee/transforming/energy/sword = 65, + /obj/item/melee/energy/sword = 65, /obj/item/kitchen/knife = 45, /obj/item/shard = 35) time = 52 diff --git a/code/modules/surgery/lobectomy.dm b/code/modules/surgery/lobectomy.dm index 730741c3eef..d122cce3546 100644 --- a/code/modules/surgery/lobectomy.dm +++ b/code/modules/surgery/lobectomy.dm @@ -22,7 +22,7 @@ name = "excise damaged lung node" implements = list( TOOL_SCALPEL = 95, - /obj/item/melee/transforming/energy/sword = 65, + /obj/item/melee/energy/sword = 65, /obj/item/kitchen/knife = 45, /obj/item/shard = 35) time = 42 diff --git a/code/modules/surgery/organic_steps.dm b/code/modules/surgery/organic_steps.dm index 7c455a1e942..466e6f55695 100644 --- a/code/modules/surgery/organic_steps.dm +++ b/code/modules/surgery/organic_steps.dm @@ -4,7 +4,7 @@ name = "make incision" implements = list( TOOL_SCALPEL = 100, - /obj/item/melee/transforming/energy/sword = 75, + /obj/item/melee/energy/sword = 75, /obj/item/kitchen/knife = 65, /obj/item/shard = 45, /obj/item = 30) // 30% success with any sharp item. diff --git a/code/modules/surgery/organs/augments_arms.dm b/code/modules/surgery/organs/augments_arms.dm index acd69fc0086..f9c0fbd35a7 100644 --- a/code/modules/surgery/organs/augments_arms.dm +++ b/code/modules/surgery/organs/augments_arms.dm @@ -244,7 +244,7 @@ /obj/item/organ/cyberimp/arm/esword name = "arm-mounted energy blade" desc = "An illegal and highly dangerous cybernetic implant that can project a deadly blade of concentrated energy." - items_to_create = list(/obj/item/melee/transforming/energy/blade/hardlight) + items_to_create = list(/obj/item/melee/energy/blade/hardlight) /obj/item/organ/cyberimp/arm/medibeam name = "integrated medical beamgun" @@ -283,7 +283,7 @@ /obj/item/organ/cyberimp/arm/combat name = "combat cybernetics implant" desc = "A powerful cybernetic implant that contains combat modules built into the user's arm." - items_to_create = list(/obj/item/melee/transforming/energy/blade/hardlight, /obj/item/gun/medbeam, /obj/item/borg/stun, /obj/item/assembly/flash/armimplant) + items_to_create = list(/obj/item/melee/energy/blade/hardlight, /obj/item/gun/medbeam, /obj/item/borg/stun, /obj/item/assembly/flash/armimplant) /obj/item/organ/cyberimp/arm/combat/Initialize() . = ..() diff --git a/code/modules/surgery/tools.dm b/code/modules/surgery/tools.dm index 192a8100c2b..f455824d35a 100644 --- a/code/modules/surgery/tools.dm +++ b/code/modules/surgery/tools.dm @@ -68,28 +68,39 @@ name = "searing tool" desc = "It projects a high power laser used for medical applications." icon = 'icons/obj/surgery.dmi' - icon_state = "cautery_a" + icon_state = "e_cautery" hitsound = 'sound/items/welder.ogg' toolspeed = 0.7 light_system = MOVABLE_LIGHT light_range = 1 light_color = COLOR_SOFT_RED +/obj/item/cautery/advanced/Initialize() + . = ..() + AddComponent(/datum/component/transforming, \ + force_on = force, \ + throwforce_on = throwforce, \ + hitsound_on = hitsound, \ + w_class_on = w_class, \ + clumsy_check = FALSE) + RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform) -/obj/item/cautery/advanced/attack_self(mob/user) - playsound(get_turf(user), 'sound/weapons/tap.ogg', 50, TRUE) - if(tool_behaviour == TOOL_CAUTERY) - tool_behaviour = TOOL_DRILL - balloon_alert(user, "lenses set to drill") - icon_state = "surgicaldrill_a" - else - tool_behaviour = TOOL_CAUTERY - balloon_alert(user, "lenses set to mend") - icon_state = "cautery_a" +/* + * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM]. + * + * Toggles between drill and cautery and gives feedback to the user. + */ +/obj/item/cautery/advanced/proc/on_transform(obj/item/source, mob/user, active) + SIGNAL_HANDLER + + tool_behaviour = (active ? TOOL_DRILL : TOOL_CAUTERY) + balloon_alert(user, "lenses set to [active ? "drill" : "mend"]") + playsound(user ? user : src, 'sound/weapons/tap.ogg', 50, TRUE) + return COMPONENT_NO_DEFAULT_MESSAGE /obj/item/cautery/advanced/examine() . = ..() - . += " It's set to [tool_behaviour == TOOL_CAUTERY ? "mending" : "drilling"] mode." + . += span_notice("It's set to [tool_behaviour == TOOL_CAUTERY ? "mending" : "drilling"] mode.") /obj/item/surgicaldrill name = "surgical drill" @@ -251,7 +262,7 @@ name = "laser scalpel" desc = "An advanced scalpel which uses laser technology to cut." icon = 'icons/obj/surgery.dmi' - icon_state = "scalpel_a" + icon_state = "e_scalpel" hitsound = 'sound/weapons/blade1.ogg' force = 16 toolspeed = 0.7 @@ -260,47 +271,74 @@ light_color = LIGHT_COLOR_GREEN sharpness = SHARP_EDGED +/obj/item/scalpel/advanced/Initialize() + . = ..() + AddComponent(/datum/component/transforming, \ + force_on = force + 1, \ + throwforce_on = throwforce, \ + throw_speed_on = throw_speed, \ + sharpness_on = sharpness, \ + hitsound_on = hitsound, \ + w_class_on = w_class, \ + clumsy_check = FALSE) + RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform) -/obj/item/scalpel/advanced/attack_self(mob/user) - playsound(get_turf(user), 'sound/machines/click.ogg', 50, TRUE) - if(tool_behaviour == TOOL_SCALPEL) +/* + * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM]. + * + * Toggles between saw and scalpel and updates the light / gives feedback to the user. + */ +/obj/item/scalpel/advanced/proc/on_transform(obj/item/source, mob/user, active) + SIGNAL_HANDLER + + if(active) tool_behaviour = TOOL_SAW - balloon_alert(user, "enabled bone-cutting mode") set_light_range(2) - force += 1 //we don't want to ruin sharpened stuff - icon_state = "saw_a" else tool_behaviour = TOOL_SCALPEL - balloon_alert(user, "disabled bone-cutting mode") set_light_range(1) - force -= 1 - icon_state = "scalpel_a" + + balloon_alert(user, "[active ? "enabled" : "disabled"] bone-cutting mode") + playsound(user ? user : src, 'sound/machines/click.ogg', 50, TRUE) + return COMPONENT_NO_DEFAULT_MESSAGE /obj/item/scalpel/advanced/examine() . = ..() - . += " It's set to [tool_behaviour == TOOL_SCALPEL ? "scalpel" : "saw"] mode." + . += span_notice("It's set to [tool_behaviour == TOOL_SCALPEL ? "scalpel" : "saw"] mode.") /obj/item/retractor/advanced name = "mechanical pinches" desc = "An agglomerate of rods and gears." icon = 'icons/obj/surgery.dmi' - icon_state = "retractor_a" + icon_state = "adv_retractor" toolspeed = 0.7 -/obj/item/retractor/advanced/attack_self(mob/user) - playsound(get_turf(user), 'sound/items/change_drill.ogg', 50, TRUE) - if(tool_behaviour == TOOL_RETRACTOR) - tool_behaviour = TOOL_HEMOSTAT - balloon_alert(user, "gears set to clamp") - icon_state = "hemostat_a" - else - tool_behaviour = TOOL_RETRACTOR - balloon_alert(user, "gears set to retract") - icon_state = "retractor_a" +/obj/item/retractor/advanced/Initialize() + . = ..() + AddComponent(/datum/component/transforming, \ + force_on = force, \ + throwforce_on = throwforce, \ + hitsound_on = hitsound, \ + w_class_on = w_class, \ + clumsy_check = FALSE) + RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform) + +/* + * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM]. + * + * Toggles between retractor and hemostat and gives feedback to the user. + */ +/obj/item/retractor/advanced/proc/on_transform(obj/item/source, mob/user, active) + SIGNAL_HANDLER + + tool_behaviour = (active ? TOOL_HEMOSTAT : TOOL_RETRACTOR) + balloon_alert(user, "gears set to [active ? "clamp" : "retract"]") + playsound(user ? user : src, 'sound/items/change_drill.ogg', 50, TRUE) + return COMPONENT_NO_DEFAULT_MESSAGE /obj/item/retractor/advanced/examine() . = ..() - . += " It resembles a [tool_behaviour == TOOL_RETRACTOR ? "retractor" : "hemostat"]." + . += span_notice("It resembles a [tool_behaviour == TOOL_RETRACTOR ? "retractor" : "hemostat"].") /obj/item/shears name = "amputation shears" diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm index baa84431bd6..1baddb9f4b2 100644 --- a/code/modules/uplink/uplink_items.dm +++ b/code/modules/uplink/uplink_items.dm @@ -342,7 +342,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) name = "Bananium Energy Sword" desc = "An energy sword that deals no damage, but will slip anyone it contacts, be it by melee attack, thrown \ impact, or just stepping on it. Beware friendly fire, as even anti-slip shoes will not protect against it." - item = /obj/item/melee/transforming/energy/sword/bananium + item = /obj/item/melee/energy/sword/bananium cost = 3 surplus = 0 purchasable_from = UPLINK_CLOWN_OPS @@ -415,7 +415,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) name = "Energy Sword" desc = "The energy sword is an edged weapon with a blade of pure energy. The sword is small enough to be \ pocketed when inactive. Activating it produces a loud, distinctive noise." - item = /obj/item/melee/transforming/energy/sword/saber + item = /obj/item/melee/energy/sword/saber cost = 8 purchasable_from = ~UPLINK_CLOWN_OPS @@ -2035,4 +2035,3 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) cost = 1 purchasable_from = UPLINK_CLOWN_OPS illegal_tech = FALSE - diff --git a/icons/mob/clothing/back.dmi b/icons/mob/clothing/back.dmi index 97110a4c1b0..848aeb13fd6 100644 Binary files a/icons/mob/clothing/back.dmi and b/icons/mob/clothing/back.dmi differ diff --git a/icons/mob/inhands/64x64_lefthand.dmi b/icons/mob/inhands/64x64_lefthand.dmi index f5024467798..5aa54e694c7 100644 Binary files a/icons/mob/inhands/64x64_lefthand.dmi and b/icons/mob/inhands/64x64_lefthand.dmi differ diff --git a/icons/mob/inhands/64x64_righthand.dmi b/icons/mob/inhands/64x64_righthand.dmi index 9061d87a3e4..be49e1eb0eb 100644 Binary files a/icons/mob/inhands/64x64_righthand.dmi and b/icons/mob/inhands/64x64_righthand.dmi differ diff --git a/icons/mob/inhands/equipment/shields_lefthand.dmi b/icons/mob/inhands/equipment/shields_lefthand.dmi index f3eccfa321b..5edcaef0261 100644 Binary files a/icons/mob/inhands/equipment/shields_lefthand.dmi and b/icons/mob/inhands/equipment/shields_lefthand.dmi differ diff --git a/icons/mob/inhands/equipment/shields_righthand.dmi b/icons/mob/inhands/equipment/shields_righthand.dmi index 92ad9ed3ff4..af80dfeccc3 100644 Binary files a/icons/mob/inhands/equipment/shields_righthand.dmi and b/icons/mob/inhands/equipment/shields_righthand.dmi differ diff --git a/icons/mob/inhands/equipment/tools_lefthand.dmi b/icons/mob/inhands/equipment/tools_lefthand.dmi index 7d6bd6fa3b7..aa47817fc26 100644 Binary files a/icons/mob/inhands/equipment/tools_lefthand.dmi and b/icons/mob/inhands/equipment/tools_lefthand.dmi differ diff --git a/icons/mob/inhands/equipment/tools_righthand.dmi b/icons/mob/inhands/equipment/tools_righthand.dmi index 3af63b59e6e..41b6b151a7f 100644 Binary files a/icons/mob/inhands/equipment/tools_righthand.dmi and b/icons/mob/inhands/equipment/tools_righthand.dmi differ diff --git a/icons/mob/inhands/weapons/axes_lefthand.dmi b/icons/mob/inhands/weapons/axes_lefthand.dmi index 447f6116576..566180fe5ff 100644 Binary files a/icons/mob/inhands/weapons/axes_lefthand.dmi and b/icons/mob/inhands/weapons/axes_lefthand.dmi differ diff --git a/icons/mob/inhands/weapons/axes_righthand.dmi b/icons/mob/inhands/weapons/axes_righthand.dmi index d8801bf75bd..94008a727a0 100644 Binary files a/icons/mob/inhands/weapons/axes_righthand.dmi and b/icons/mob/inhands/weapons/axes_righthand.dmi differ diff --git a/icons/mob/inhands/weapons/melee_lefthand.dmi b/icons/mob/inhands/weapons/melee_lefthand.dmi index 36b3abfeddc..d255bf1e854 100644 Binary files a/icons/mob/inhands/weapons/melee_lefthand.dmi and b/icons/mob/inhands/weapons/melee_lefthand.dmi differ diff --git a/icons/mob/inhands/weapons/melee_righthand.dmi b/icons/mob/inhands/weapons/melee_righthand.dmi index be564b93f9e..4ca3e77b672 100644 Binary files a/icons/mob/inhands/weapons/melee_righthand.dmi and b/icons/mob/inhands/weapons/melee_righthand.dmi differ diff --git a/icons/mob/inhands/weapons/swords_lefthand.dmi b/icons/mob/inhands/weapons/swords_lefthand.dmi index 293976209ea..2d3bf918871 100644 Binary files a/icons/mob/inhands/weapons/swords_lefthand.dmi and b/icons/mob/inhands/weapons/swords_lefthand.dmi differ diff --git a/icons/mob/inhands/weapons/swords_righthand.dmi b/icons/mob/inhands/weapons/swords_righthand.dmi index a7bd228ad0d..12e85cfe08d 100644 Binary files a/icons/mob/inhands/weapons/swords_righthand.dmi and b/icons/mob/inhands/weapons/swords_righthand.dmi differ diff --git a/icons/obj/clothing/belt_overlays.dmi b/icons/obj/clothing/belt_overlays.dmi index 19e2e2c7a24..57befb675a1 100644 Binary files a/icons/obj/clothing/belt_overlays.dmi and b/icons/obj/clothing/belt_overlays.dmi differ diff --git a/icons/obj/items_and_weapons.dmi b/icons/obj/items_and_weapons.dmi index 7a81325d0b8..a19e15b20df 100644 Binary files a/icons/obj/items_and_weapons.dmi and b/icons/obj/items_and_weapons.dmi differ diff --git a/icons/obj/lavaland/artefacts.dmi b/icons/obj/lavaland/artefacts.dmi index 589c5ee0a27..dd65e49104f 100644 Binary files a/icons/obj/lavaland/artefacts.dmi and b/icons/obj/lavaland/artefacts.dmi differ diff --git a/icons/obj/shields.dmi b/icons/obj/shields.dmi index 47bdc940d28..c0a2d6a2993 100644 Binary files a/icons/obj/shields.dmi and b/icons/obj/shields.dmi differ diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi index 9d62d4cc580..e1a163b930c 100755 Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ diff --git a/icons/obj/tools.dmi b/icons/obj/tools.dmi index ebc2ec637a5..8bfdd660691 100644 Binary files a/icons/obj/tools.dmi and b/icons/obj/tools.dmi differ diff --git a/icons/obj/transforming_energy.dmi b/icons/obj/transforming_energy.dmi index 2fd2b7ec401..04e9b3e168a 100644 Binary files a/icons/obj/transforming_energy.dmi and b/icons/obj/transforming_energy.dmi differ diff --git a/tgstation.dme b/tgstation.dme index c86eb7b825e..a175b92d5a6 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -598,6 +598,7 @@ #include "code\datums\components\tether.dm" #include "code\datums\components\thermite.dm" #include "code\datums\components\tippable.dm" +#include "code\datums\components\transforming.dm" #include "code\datums\components\trapdoor.dm" #include "code\datums\components\twohanded.dm" #include "code\datums\components\udder.dm" @@ -1347,7 +1348,6 @@ #include "code\game\objects\items\implants\implantuplink.dm" #include "code\game\objects\items\melee\energy.dm" #include "code\game\objects\items\melee\misc.dm" -#include "code\game\objects\items\melee\transforming.dm" #include "code\game\objects\items\robot\ai_upgrades.dm" #include "code\game\objects\items\robot\robot_items.dm" #include "code\game\objects\items\robot\robot_parts.dm"