diff --git a/code/datums/status_effects/debuffs/debuffs.dm b/code/datums/status_effects/debuffs/debuffs.dm index 34eae9515ff..006a2a527df 100644 --- a/code/datums/status_effects/debuffs/debuffs.dm +++ b/code/datums/status_effects/debuffs/debuffs.dm @@ -347,19 +347,33 @@ duration = 300 //if you leave for 30 seconds you lose the mark, deal with it status_type = STATUS_EFFECT_REFRESH alert_type = null - var/mutable_appearance/marked_underlay + /// The bubble that is added to the mob as a visual + var/obj/effect/abstract/crusher_mark/marked_underlay + /// If the projectile that applies this was boosted, the mark will also be boosted var/boosted = FALSE + /// How long before the mark is ready to be detonated. Used for both the visual overlay and to determine when it's ready + var/ready_delay = 0.8 SECONDS + /// Tracks world.time when the mark was applied + var/mark_applied /datum/status_effect/crusher_mark/on_creation(mob/living/new_owner, was_boosted) . = ..() boosted = was_boosted + mark_applied = world.time /datum/status_effect/crusher_mark/on_apply() if(owner.mob_size >= MOB_SIZE_LARGE) - marked_underlay = mutable_appearance('icons/effects/effects.dmi', boosted ? "shield" : "shield2") + marked_underlay = new() marked_underlay.pixel_x = -owner.pixel_x marked_underlay.pixel_y = -owner.pixel_y - owner.underlays += marked_underlay + + var/list/new_color = list( + 0, 1, 0, + 0, 1, 0, + 0, 1, 0 + ) + owner.vis_contents += marked_underlay + animate(marked_underlay, color = new_color, time = ready_delay, loop = 1) return TRUE return FALSE @@ -369,6 +383,20 @@ QDEL_NULL(marked_underlay) return ..() +// Object used to apply a underlay to the mob that gets this status applied +/obj/effect/abstract/crusher_mark + name = "Crusher mark underlay" + icon = 'icons/effects/effects.dmi' + icon_state = "shield" + appearance_flags = TILE_BOUND|LONG_GLIDE|RESET_COLOR + vis_flags = VIS_UNDERLAY + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + color = list( + 1, 0, 0, + 1, 0, 0, + 1, 0, 0 + ) + /datum/status_effect/stacking/saw_bleed id = "saw_bleed" tick_interval = 0.6 SECONDS diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm deleted file mode 100644 index 09982715f23..00000000000 --- a/code/modules/mining/equipment/kinetic_crusher.dm +++ /dev/null @@ -1,631 +0,0 @@ -/** - * Kinetic Crusher - * - * Lavaland's "Hard Mode" option for players, requiring melee attacks (backstabs even better), - * but allowing you to upgrade it with trophies gained from fighting lavaland monsters, making it - * a good tradeoff and a decent playstyle. - */ -/obj/item/kinetic_crusher - name = "proto-kinetic crusher" - desc = "An early design of the proto-kinetic accelerator, it is little more than a combination of various mining tools cobbled together, \ - forming a high-tech club. While it is an effective mining tool, it did little to aid any but the most skilled and/or \ - suicidal miners against local fauna." - icon = 'icons/obj/mining.dmi' - icon_state = "crusher" - inhand_icon_state = "crusher0" - icon_angle = -45 - lefthand_file = 'icons/mob/inhands/weapons/hammers_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/hammers_righthand.dmi' - resistance_flags = FIRE_PROOF - force = 0 //You can't hit stuff unless wielded - w_class = WEIGHT_CLASS_BULKY - slot_flags = ITEM_SLOT_BACK - throwforce = 5 - throw_speed = 4 - armour_penetration = 10 - custom_materials = list(/datum/material/iron=HALF_SHEET_MATERIAL_AMOUNT*1.15, /datum/material/glass=HALF_SHEET_MATERIAL_AMOUNT*2.075) - hitsound = 'sound/items/weapons/bladeslice.ogg' - attack_verb_continuous = list("smashes", "crushes", "cleaves", "chops", "pulps") - attack_verb_simple = list("smash", "crush", "cleave", "chop", "pulp") - sharpness = SHARP_EDGED - actions_types = list(/datum/action/item_action/toggle_light) - obj_flags = UNIQUE_RENAME - light_system = OVERLAY_LIGHT - light_range = 5 - light_power = 1.2 - light_color = "#ffff66" - light_on = FALSE - ///List of all crusher trophies attached to this. - var/list/obj/item/crusher_trophy/trophies = list() - var/charged = TRUE - var/charge_time = 1.5 SECONDS - var/detonation_damage = 50 - var/backstab_bonus = 30 - var/current_inhand_icon_state = "crusher" //variable used by retool kits when changing the crusher's appearance - var/projectile_icon = "pulse1" //variable used by retool kits when changing the crusher's projectile sprite - -/obj/item/kinetic_crusher/Initialize(mapload) - . = ..() - AddComponent(/datum/component/butchering, \ - speed = 6 SECONDS, \ - effectiveness = 110, \ - ) - //technically it's huge and bulky, but this provides an incentive to use it - AddComponent(/datum/component/two_handed, force_unwielded=0, force_wielded=20) - register_context() - -/obj/item/kinetic_crusher/add_context(atom/source, list/context, obj/item/held_item, mob/user) - . = ..() - if(!held_item) - context[SCREENTIP_CONTEXT_RMB] = "Detach trophy" - return CONTEXTUAL_SCREENTIP_SET - - if(istype(held_item) && held_item.tool_behaviour == TOOL_CROWBAR) - context[SCREENTIP_CONTEXT_LMB] = "Detach all trophies" - return CONTEXTUAL_SCREENTIP_SET - -/obj/item/kinetic_crusher/Destroy() - QDEL_LIST(trophies) - return ..() - -/obj/item/kinetic_crusher/Exited(atom/movable/gone, direction) - . = ..() - trophies -= gone - -/obj/item/kinetic_crusher/examine(mob/living/user) - . = ..() - . += span_notice("Mark a large creature with a destabilizing force with right-click, then hit them in melee to do [force + detonation_damage] damage.") - . += span_notice("Does [force + detonation_damage + backstab_bonus] damage if the target is backstabbed, instead of [force + detonation_damage].") - for(var/obj/item/crusher_trophy/crusher_trophy as anything in trophies) - . += span_notice("It has \a [crusher_trophy] attached, which causes [crusher_trophy.effect_desc()].") - -/obj/item/kinetic_crusher/attackby(obj/item/attacking_item, mob/user, params) - if(istype(attacking_item, /obj/item/crusher_trophy)) - var/obj/item/crusher_trophy/crusher_trophy = attacking_item - crusher_trophy.add_to(src, user) - return - return ..() - -/obj/item/kinetic_crusher/crowbar_act(mob/living/user, obj/item/tool) - . = ..() - if(!LAZYLEN(trophies)) - user.balloon_alert(user, "no trophies!") - return ITEM_INTERACT_BLOCKING - user.balloon_alert(user, "trophies removed") - tool.play_tool_sound(src) - for(var/obj/item/crusher_trophy/crusher_trophy as anything in trophies) - crusher_trophy.remove_from(src, user) - return ITEM_INTERACT_SUCCESS - -// adapted from kinetic accelerator attack_hand_secodary -/obj/item/kinetic_crusher/attack_hand_secondary(mob/user, list/modifiers) - . = ..() - if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - - if(!LAZYLEN(trophies)) - return SECONDARY_ATTACK_CONTINUE_CHAIN - - var/list/display_names = list() - var/list/items = list() - for(var/trophies_length in 1 to length(trophies)) - var/obj/item/crusher_trophy/trophy = trophies[trophies_length] - display_names[trophy.name] = REF(trophy) - var/image/item_image = image(icon = trophy.icon, icon_state = trophy.icon_state) - if(length(trophy.overlays)) - item_image.copy_overlays(trophy) - items["[trophy.name]"] = item_image - - var/pick = show_radial_menu(user, src, items, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE, tooltips = TRUE) - if(!pick) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - - var/trophy_reference = display_names[pick] - var/obj/item/crusher_trophy/trophy_to_remove = locate(trophy_reference) in trophies - if(!istype(trophy_to_remove)) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - trophy_to_remove.remove_from(src, user) - if(!user.put_in_hands(trophy_to_remove)) - trophy_to_remove.forceMove(drop_location()) - - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - -/obj/item/kinetic_crusher/proc/check_menu(mob/living/carbon/human/user) - if(!istype(user)) - return FALSE - if(user.incapacitated) - return FALSE - return TRUE - -/obj/item/kinetic_crusher/pre_attack(atom/A, mob/living/user, params) - . = ..() - if(.) - return TRUE - if(!HAS_TRAIT(src, TRAIT_WIELDED)) - user.balloon_alert(user, "must be wielded!") - return TRUE - return . - -/obj/item/kinetic_crusher/attack(mob/living/target, mob/living/carbon/user) - target.apply_status_effect(/datum/status_effect/crusher_damage) - return ..() - -/obj/item/kinetic_crusher/afterattack(mob/living/target, mob/living/user, clickparams) - if(!isliving(target)) - return - // Melee effect - for(var/obj/item/crusher_trophy/crusher_trophy as anything in trophies) - crusher_trophy.on_melee_hit(target, user) - if(QDELETED(target)) - return - var/datum/status_effect/crusher_mark/mark = target.has_status_effect(/datum/status_effect/crusher_mark) - var/boosted_mark = mark?.boosted - if(!target.remove_status_effect(mark)) - return - // Detonation effect - var/datum/status_effect/crusher_damage/crusher_damage_effect = target.has_status_effect(/datum/status_effect/crusher_damage) || target.apply_status_effect(/datum/status_effect/crusher_damage) - var/target_health = target.health - for(var/obj/item/crusher_trophy/crusher_trophy as anything in trophies) - crusher_trophy.on_mark_detonation(target, user) - if(QDELETED(target)) - return - if(!QDELETED(crusher_damage_effect)) - crusher_damage_effect.total_damage += target_health - target.health //we did some damage, but let's not assume how much we did - new /obj/effect/temp_visual/kinetic_blast(get_turf(target)) - var/backstabbed = FALSE - var/combined_damage = detonation_damage - var/def_check = target.getarmor(type = BOMB) - // Backstab bonus - if(check_behind(user, target) || boosted_mark) - backstabbed = TRUE - combined_damage += backstab_bonus - playsound(user, 'sound/items/weapons/kinetic_accel.ogg', 100, TRUE) //Seriously who spelled it wrong - if(!QDELETED(crusher_damage_effect)) - crusher_damage_effect.total_damage += combined_damage - SEND_SIGNAL(user, COMSIG_LIVING_CRUSHER_DETONATE, target, src, backstabbed) - target.apply_damage(combined_damage, BRUTE, blocked = def_check) - -/obj/item/kinetic_crusher/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) - if(!HAS_TRAIT(src, TRAIT_WIELDED)) - balloon_alert(user, "wield it first!") - return ITEM_INTERACT_BLOCKING - if(interacting_with == user) - balloon_alert(user, "can't aim at yourself!") - return ITEM_INTERACT_BLOCKING - fire_kinetic_blast(interacting_with, user, modifiers) - user.changeNext_move(CLICK_CD_MELEE) - return ITEM_INTERACT_SUCCESS - -/obj/item/kinetic_crusher/ranged_interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) - return interact_with_atom_secondary(interacting_with, user, modifiers) - -/obj/item/kinetic_crusher/proc/fire_kinetic_blast(atom/target, mob/living/user, list/modifiers) - if(!charged) - return - var/turf/proj_turf = user.loc - if(!isturf(proj_turf)) - return - var/obj/projectile/destabilizer/destabilizer = new(proj_turf) - destabilizer.icon_state = "[projectile_icon]" - for(var/obj/item/crusher_trophy/attached_trophy as anything in trophies) - attached_trophy.on_projectile_fire(destabilizer, user) - destabilizer.aim_projectile(target, user, modifiers) - destabilizer.firer = user - playsound(user, 'sound/items/weapons/plasma_cutter.ogg', 100, TRUE) - destabilizer.fire() - charged = FALSE - update_appearance() - addtimer(CALLBACK(src, PROC_REF(recharge_projectile)), charge_time) - -/obj/item/kinetic_crusher/proc/recharge_projectile() - if(!charged) - charged = TRUE - update_appearance() - playsound(src.loc, 'sound/items/weapons/kinetic_reload.ogg', 60, TRUE) - -/obj/item/kinetic_crusher/ui_action_click(mob/user, actiontype) - set_light_on(!light_on) - playsound(user, 'sound/items/weapons/empty.ogg', 100, TRUE) - update_appearance() - -/obj/item/kinetic_crusher/on_saboteur(datum/source, disrupt_duration) - . = ..() - set_light_on(FALSE) - playsound(src, 'sound/items/weapons/empty.ogg', 100, TRUE) - return TRUE - -/obj/item/kinetic_crusher/update_icon_state() - inhand_icon_state = "[current_inhand_icon_state][HAS_TRAIT(src, TRAIT_WIELDED)]" // this is not icon_state and not supported by 2hcomponent - return ..() - -/obj/item/kinetic_crusher/update_overlays() - . = ..() - if(!charged) - . += "[icon_state]_uncharged" - if(light_on) - . += "[icon_state]_lit" - -/obj/item/kinetic_crusher/compact //for admins - name = "compact kinetic crusher" - w_class = WEIGHT_CLASS_NORMAL - -//destablizing force -/obj/projectile/destabilizer - name = "destabilizing force" - damage = 0 //We're just here to mark people. This is still a melee weapon. - damage_type = BRUTE - armor_flag = BOMB - range = 6 - log_override = TRUE - /// Has this projectile been boosted - var/boosted = FALSE - -/obj/projectile/destabilizer/Initialize(mapload) - . = ..() - AddComponent(/datum/component/parriable_projectile, parry_callback = CALLBACK(src, PROC_REF(on_parry))) - -/obj/projectile/destabilizer/proc/on_parry(mob/user) - SIGNAL_HANDLER - boosted = TRUE - // Get a bit of a damage/range boost after being parried - damage = 10 - range = 9 - -/obj/projectile/destabilizer/on_hit(atom/target, blocked = 0, pierce_hit) - if(isliving(target)) - var/mob/living/living_target = target - living_target.apply_status_effect(/datum/status_effect/crusher_mark, boosted) - var/target_turf = get_turf(target) - if(ismineralturf(target_turf)) - var/turf/closed/mineral/hit_mineral = target_turf - new /obj/effect/temp_visual/kinetic_blast(hit_mineral) - hit_mineral.gets_drilled(firer) - return ..() - -//trophies -/obj/item/crusher_trophy - name = "tail spike" - desc = "A strange spike with no usage." - icon = 'icons/obj/mining_zones/artefacts.dmi' - icon_state = "tail_spike" - var/bonus_value = 10 //if it has a bonus effect, this is how much that effect is - var/denied_type = /obj/item/crusher_trophy - -/obj/item/crusher_trophy/examine(mob/living/user) - . = ..() - . += span_notice("Causes [effect_desc()] when attached to a kinetic crusher.") - -/obj/item/crusher_trophy/proc/effect_desc() - return "errors" - -/obj/item/crusher_trophy/attackby(obj/item/A, mob/living/user) - if(istype(A, /obj/item/kinetic_crusher)) - add_to(A, user) - else - ..() - -/obj/item/crusher_trophy/proc/add_to(obj/item/kinetic_crusher/crusher, mob/living/user) - for(var/obj/item/crusher_trophy/trophy as anything in crusher.trophies) - if(istype(trophy, denied_type) || istype(src, trophy.denied_type)) - to_chat(user, span_warning("You can't seem to attach [src] to [crusher]. Maybe remove a few trophies?")) - return FALSE - if(!user.transferItemToLoc(src, crusher)) - return - crusher.trophies += src - to_chat(user, span_notice("You attach [src] to [crusher].")) - return TRUE - -/obj/item/crusher_trophy/proc/remove_from(obj/item/kinetic_crusher/crusher, mob/living/user) - forceMove(get_turf(crusher)) - return TRUE - -/obj/item/crusher_trophy/proc/on_melee_hit(mob/living/target, mob/living/user) //the target and the user -/obj/item/crusher_trophy/proc/on_projectile_fire(obj/projectile/destabilizer/marker, mob/living/user) //the projectile fired and the user -/obj/item/crusher_trophy/proc/on_mark_detonation(mob/living/target, mob/living/user) //the target and the user - -//watcher -/obj/item/crusher_trophy/watcher_wing - name = "watcher wing" - desc = "A wing ripped from a watcher. Suitable as a trophy for a kinetic crusher." - icon_state = "watcher_wing" - denied_type = /obj/item/crusher_trophy/watcher_wing - bonus_value = 5 - -/obj/item/crusher_trophy/watcher_wing/effect_desc() - return "mark detonation to prevent certain creatures from using certain attacks for [bonus_value*0.1] second\s" - -/obj/item/crusher_trophy/watcher_wing/on_mark_detonation(mob/living/target, mob/living/user) - if(ishostile(target)) - var/mob/living/simple_animal/hostile/H = target - if(H.ranged) //briefly delay ranged attacks - if(H.ranged_cooldown >= world.time) - H.ranged_cooldown += bonus_value - else - H.ranged_cooldown = bonus_value + world.time - -//magmawing watcher -/obj/item/crusher_trophy/blaster_tubes/magma_wing - name = "magmawing watcher wing" - desc = "A still-searing wing from a magmawing watcher. Suitable as a trophy for a kinetic crusher." - icon_state = "magma_wing" - gender = NEUTER - bonus_value = 5 - -/obj/item/crusher_trophy/blaster_tubes/magma_wing/effect_desc() - return "mark detonation to make the next destabilizer shot deal [bonus_value] damage" - -/obj/item/crusher_trophy/blaster_tubes/magma_wing/on_projectile_fire(obj/projectile/destabilizer/marker, mob/living/user) - if(deadly_shot) - marker.name = "heated [marker.name]" - marker.icon_state = "lava" - marker.damage = bonus_value - deadly_shot = FALSE - -//icewing watcher -/obj/item/crusher_trophy/watcher_wing/ice_wing - name = "icewing watcher wing" - desc = "A carefully preserved frozen wing from an icewing watcher. Suitable as a trophy for a kinetic crusher." - icon_state = "ice_wing" - bonus_value = 8 - -//legion -/obj/item/crusher_trophy/legion_skull - name = "legion skull" - desc = "A dead and lifeless legion skull. Suitable as a trophy for a kinetic crusher." - icon_state = "legion_skull" - denied_type = /obj/item/crusher_trophy/legion_skull - bonus_value = 3 - -/obj/item/crusher_trophy/legion_skull/effect_desc() - return "a kinetic crusher to recharge [bonus_value*0.1] second\s faster" - -/obj/item/crusher_trophy/legion_skull/add_to(obj/item/kinetic_crusher/pkc, mob/living/user) - . = ..() - if(.) - pkc.charge_time -= bonus_value - -/obj/item/crusher_trophy/legion_skull/remove_from(obj/item/kinetic_crusher/pkc, mob/living/user) - . = ..() - if(.) - pkc.charge_time += bonus_value - -//blood-drunk hunter -/obj/item/crusher_trophy/miner_eye - name = "eye of a blood-drunk hunter" - desc = "Its pupil is collapsed and turned to mush. Suitable as a trophy for a kinetic crusher." - icon_state = "hunter_eye" - denied_type = /obj/item/crusher_trophy/miner_eye - -/obj/item/crusher_trophy/miner_eye/effect_desc() - return "mark detonation to grant stun immunity and 90% damage reduction for 1 second" - -/obj/item/crusher_trophy/miner_eye/on_mark_detonation(mob/living/target, mob/living/user) - user.apply_status_effect(/datum/status_effect/blooddrunk) - -//ash drake -/obj/item/crusher_trophy/tail_spike - desc = "A spike taken from an ash drake's tail. Suitable as a trophy for a kinetic crusher." - denied_type = /obj/item/crusher_trophy/tail_spike - bonus_value = 5 - -/obj/item/crusher_trophy/tail_spike/effect_desc() - return "mark detonation to do [bonus_value] damage to nearby creatures and push them back" - -/obj/item/crusher_trophy/tail_spike/on_mark_detonation(mob/living/target, mob/living/user) - for(var/mob/living/living_target in oview(2, user)) - if(user.faction_check_atom(living_target) || living_target.stat == DEAD) - continue - playsound(living_target, 'sound/effects/magic/fireball.ogg', 20, TRUE) - new /obj/effect/temp_visual/fire(living_target.loc) - addtimer(CALLBACK(src, PROC_REF(pushback), living_target, user), 1) //no free backstabs, we push AFTER module stuff is done - living_target.adjustFireLoss(bonus_value, forced = TRUE) - -/obj/item/crusher_trophy/tail_spike/proc/pushback(mob/living/target, mob/living/user) - if(!QDELETED(target) && !QDELETED(user) && (!target.anchored || ismegafauna(target))) //megafauna will always be pushed - step(target, get_dir(user, target)) - -//bubblegum -/obj/item/crusher_trophy/demon_claws - name = "demon claws" - desc = "A set of blood-drenched claws from a massive demon's hand. Suitable as a trophy for a kinetic crusher." - icon_state = "demon_claws" - gender = PLURAL - denied_type = /obj/item/crusher_trophy/demon_claws - bonus_value = 10 - var/static/list/damage_heal_order = list(BRUTE, BURN, OXY) - -/obj/item/crusher_trophy/demon_claws/effect_desc() - return "melee hits to do [bonus_value * 0.2] more damage and heal you for [bonus_value * 0.1], with 5X effect on mark detonation" - -/obj/item/crusher_trophy/demon_claws/add_to(obj/item/kinetic_crusher/pkc, mob/living/user) - . = ..() - if(.) - pkc.force += bonus_value * 0.2 - pkc.detonation_damage += bonus_value * 0.8 - AddComponent(/datum/component/two_handed, force_wielded=(20 + bonus_value * 0.2)) - -/obj/item/crusher_trophy/demon_claws/remove_from(obj/item/kinetic_crusher/pkc, mob/living/user) - . = ..() - if(.) - pkc.force -= bonus_value * 0.2 - pkc.detonation_damage -= bonus_value * 0.8 - AddComponent(/datum/component/two_handed, force_wielded=20) - -/obj/item/crusher_trophy/demon_claws/on_melee_hit(mob/living/target, mob/living/user) - user.heal_ordered_damage(bonus_value * 0.1, damage_heal_order) - -/obj/item/crusher_trophy/demon_claws/on_mark_detonation(mob/living/target, mob/living/user) - user.heal_ordered_damage(bonus_value * 0.4, damage_heal_order) - -//colossus -/obj/item/crusher_trophy/blaster_tubes - name = "blaster tubes" - desc = "The blaster tubes from a colossus's arm. Suitable as a trophy for a kinetic crusher." - icon_state = "blaster_tubes" - gender = PLURAL - denied_type = /obj/item/crusher_trophy/blaster_tubes - bonus_value = 15 - var/deadly_shot = FALSE - -/obj/item/crusher_trophy/blaster_tubes/effect_desc() - return "mark detonation to make the next destabilizer shot deal [bonus_value] damage but move slower" - -/obj/item/crusher_trophy/blaster_tubes/on_projectile_fire(obj/projectile/destabilizer/marker, mob/living/user) - if(deadly_shot) - marker.name = "deadly [marker.name]" - marker.icon_state = "chronobolt" - marker.damage = bonus_value - marker.speed = 0.5 - deadly_shot = FALSE - -/obj/item/crusher_trophy/blaster_tubes/on_mark_detonation(mob/living/target, mob/living/user) - deadly_shot = TRUE - addtimer(CALLBACK(src, PROC_REF(reset_deadly_shot)), 300, TIMER_UNIQUE|TIMER_OVERRIDE) - -/obj/item/crusher_trophy/blaster_tubes/proc/reset_deadly_shot() - deadly_shot = FALSE - -//hierophant -/obj/item/crusher_trophy/vortex_talisman - name = "vortex talisman" - desc = "A glowing trinket that was originally the Hierophant's beacon. Suitable as a trophy for a kinetic crusher." - icon_state = "vortex_talisman" - denied_type = /obj/item/crusher_trophy/vortex_talisman - -/obj/item/crusher_trophy/vortex_talisman/effect_desc() - return "mark detonation to create a homing hierophant chaser" - -/obj/item/crusher_trophy/vortex_talisman/on_mark_detonation(mob/living/target, mob/living/user) - if(isliving(target)) - var/obj/effect/temp_visual/hierophant/chaser/chaser = new(get_turf(user), user, target, 3, TRUE) - chaser.monster_damage_boost = FALSE // Weaker cuz no cooldown - chaser.damage = 20 - log_combat(user, target, "fired a chaser at", src) - -/obj/item/crusher_trophy/ice_demon_cube - name = "demonic cube" - desc = "A stone cold cube dropped from an ice demon." - icon_state = "ice_demon_cube" - denied_type = /obj/item/crusher_trophy/ice_demon_cube - ///how many will we summon? - var/summon_amount = 2 - ///cooldown to summon demons upon the target - COOLDOWN_DECLARE(summon_cooldown) - -/obj/item/crusher_trophy/ice_demon_cube/effect_desc() - return "mark detonation to unleash demonic ice clones upon the target" - -/obj/item/crusher_trophy/ice_demon_cube/on_mark_detonation(mob/living/target, mob/living/user) - if(isnull(target) || !COOLDOWN_FINISHED(src, summon_cooldown)) - return - for(var/i in 1 to summon_amount) - var/turf/drop_off = find_dropoff_turf(target, user) - var/mob/living/basic/mining/demon_afterimage/crusher/friend = new(drop_off) - friend.faction = list(FACTION_NEUTRAL) - friend.befriend(user) - friend.ai_controller?.set_blackboard_key(BB_BASIC_MOB_CURRENT_TARGET, target) - COOLDOWN_START(src, summon_cooldown, 30 SECONDS) - -///try to make them spawn all around the target to surround him -/obj/item/crusher_trophy/ice_demon_cube/proc/find_dropoff_turf(mob/living/target, mob/living/user) - var/list/turfs_list = get_adjacent_open_turfs(target) - for(var/turf/possible_turf in turfs_list) - if(possible_turf.is_blocked_turf()) - continue - return possible_turf - return get_turf(user) - -//wolf trophy - -/obj/item/crusher_trophy/wolf_ear - name = "wolf ear" - desc = "It's a wolf ear." - icon_state = "wolf_ear" - denied_type = /obj/item/crusher_trophy/wolf_ear - -/obj/item/crusher_trophy/wolf_ear/effect_desc() - return "mark detonation to gain a slight speed boost temporarily" - -/obj/item/crusher_trophy/wolf_ear/on_mark_detonation(mob/living/target, mob/living/user) - user.apply_status_effect(/datum/status_effect/speed_boost, 1 SECONDS) - -//cosmetic items for changing the crusher's look - -/obj/item/crusher_trophy/retool_kit - name = "crusher sword retool kit" - desc = "A toolkit for changing the crusher's appearance without affecting the device's function. This one will make it look like a sword." - icon = 'icons/obj/mining.dmi' - icon_state = "retool_kit" - denied_type = /obj/item/crusher_trophy/retool_kit - ///Specifies the sprite/icon state which the crusher is changed to as an item. Should appear in the icons/obj/mining.dmi file with accompanying "lit" and "recharging" sprites - var/retool_icon = "crusher_sword" - ///Specifies the icon state for the crusher's appearance in hand. Should appear in both icons/mob/inhands/weapons/hammers_lefthand.dmi and icons/mob/inhands/weapons/hammers_righthand.dmi - var/retool_inhand_icon = "crusher_sword" - ///For if the retool kit changes the projectile's appearance. The sprite should be in icons/obj/weapons/guns/projectiles.dmi - var/retool_projectile_icon = "pulse1" - -/obj/item/crusher_trophy/retool_kit/effect_desc() - return "the crusher to have the appearance of a sword" - -/obj/item/crusher_trophy/retool_kit/add_to(obj/item/kinetic_crusher/pkc, mob/user) - . = ..() - if(.) - pkc.icon_state = retool_icon - pkc.current_inhand_icon_state = retool_inhand_icon - pkc.projectile_icon = retool_projectile_icon - if(iscarbon(pkc.loc)) - var/mob/living/carbon/holder = pkc.loc - holder.update_worn_back() - holder.update_suit_storage() - holder.update_held_items() - pkc.update_appearance() - -/obj/item/crusher_trophy/retool_kit/remove_from(obj/item/kinetic_crusher/pkc) - pkc.icon_state = initial(pkc.icon_state) - pkc.current_inhand_icon_state = initial(pkc.current_inhand_icon_state) - pkc.projectile_icon = initial(pkc.projectile_icon) - if(iscarbon(pkc.loc)) - var/mob/living/carbon/holder = pkc.loc - holder.update_worn_back() - holder.update_suit_storage() - holder.update_held_items() - pkc.update_appearance() - ..() - -/obj/item/crusher_trophy/retool_kit/harpoon - name = "crusher harpoon retool kit" - desc = "A toolkit for changing the crusher's appearance without affecting the device's function. This one will make it look like a harpoon." - icon = 'icons/obj/mining.dmi' - icon_state = "retool_kit" - denied_type = /obj/item/crusher_trophy/retool_kit - retool_icon = "crusher_harpoon" - retool_inhand_icon = "crusher_harpoon" - retool_projectile_icon = "pulse_harpoon" - -/obj/item/crusher_trophy/retool_kit/harpoon/effect_desc() - return "the crusher to have the appearance of a harpoon" - -/obj/item/crusher_trophy/retool_kit/dagger - name = "crusher dagger retool kit" - desc = "A toolkit for changing the crusher's appearance without affecting the device's function. This one will make it look like a dual dagger and mini-blaster on a chain." - icon = 'icons/obj/mining.dmi' - icon_state = "retool_kit" - denied_type = /obj/item/crusher_trophy/retool_kit - retool_icon = "crusher_dagger" - retool_inhand_icon = "crusher_dagger" - -/obj/item/crusher_trophy/retool_kit/dagger/effect_desc() - return "the crusher to have the appearance of a dual dagger and blaster" - -/obj/item/crusher_trophy/retool_kit/ashenskull - name = "ashen skull" - desc = "It burns with the flame of the necropolis, whispering in your ear. It demands to be bound to a suitable weapon." - icon = 'icons/obj/mining.dmi' - icon_state = "retool_kit_skull" - denied_type = /obj/item/crusher_trophy/retool_kit - retool_icon = "crusher_skull" - retool_inhand_icon = "crusher_skull" - retool_projectile_icon = "pulse_skull" - -/obj/item/crusher_trophy/retool_kit/ashenskull/effect_desc() - return "the crusher to appear corrupted by infernal powers" diff --git a/code/modules/mining/equipment/kinetic_crusher/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher/kinetic_crusher.dm new file mode 100644 index 00000000000..871dbc6ecca --- /dev/null +++ b/code/modules/mining/equipment/kinetic_crusher/kinetic_crusher.dm @@ -0,0 +1,329 @@ +/** + * Kinetic Crusher + * + * Lavaland's "Hard Mode" option for players, requiring melee attacks (backstabs even better), + * but allowing you to upgrade it with trophies gained from fighting lavaland monsters, making it + * a good tradeoff and a decent playstyle. + */ +/obj/item/kinetic_crusher + name = "proto-kinetic crusher" + desc = "An early design of the proto-kinetic accelerator, it is little more than a combination of various mining tools cobbled together, \ + forming a high-tech club. While it is an effective mining tool, it did little to aid any but the most skilled and/or \ + suicidal miners against local fauna." + icon = 'icons/obj/mining.dmi' + icon_state = "crusher" + inhand_icon_state = "crusher0" + icon_angle = -45 + lefthand_file = 'icons/mob/inhands/weapons/hammers_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/hammers_righthand.dmi' + resistance_flags = FIRE_PROOF + force = 0 //You can't hit stuff unless wielded + w_class = WEIGHT_CLASS_BULKY + slot_flags = ITEM_SLOT_BACK + throwforce = 5 + throw_speed = 4 + armour_penetration = 10 + custom_materials = list(/datum/material/iron=HALF_SHEET_MATERIAL_AMOUNT*1.15, /datum/material/glass=HALF_SHEET_MATERIAL_AMOUNT*2.075) + hitsound = 'sound/items/weapons/bladeslice.ogg' + attack_verb_continuous = list("smashes", "crushes", "cleaves", "chops", "pulps") + attack_verb_simple = list("smash", "crush", "cleave", "chop", "pulp") + sharpness = SHARP_EDGED + actions_types = list(/datum/action/item_action/toggle_light) + obj_flags = UNIQUE_RENAME + light_system = OVERLAY_LIGHT + light_range = 5 + light_power = 1.2 + light_color = "#ffff66" + light_on = FALSE + /// List of all crusher trophies attached to this. + var/list/obj/item/crusher_trophy/trophies = list() + /// If our crusher is ready to fire a projectile (FALSE means it's on cooldown) + var/charged = TRUE + /// How long before our crusher will recharge by default + var/charge_time = 1.5 SECONDS + /// Timer before our crusher recharges + var/charge_timer + /// Damage that the mark does when hit by the crusher + var/detonation_damage = 50 + /// Damage that the mark additionally does when hit by the crusher via backstab + var/backstab_bonus = 30 + /// Used by retool kits when changing the crusher's appearance + var/current_inhand_icon_state = "crusher" + /// Used by retool kits when changing the crusher's projectile sprite + var/projectile_icon = "pulse1" + +/obj/item/kinetic_crusher/Initialize(mapload) + . = ..() + AddComponent(/datum/component/butchering, \ + speed = 6 SECONDS, \ + effectiveness = 110, \ + ) + //technically it's huge and bulky, but this provides an incentive to use it + AddComponent(/datum/component/two_handed, force_unwielded=0, force_wielded=20) + register_context() + +/obj/item/kinetic_crusher/add_context(atom/source, list/context, obj/item/held_item, mob/user) + . = ..() + if(!held_item) + context[SCREENTIP_CONTEXT_RMB] = "Detach trophy" + return CONTEXTUAL_SCREENTIP_SET + + if(istype(held_item) && held_item.tool_behaviour == TOOL_CROWBAR) + context[SCREENTIP_CONTEXT_LMB] = "Detach all trophies" + return CONTEXTUAL_SCREENTIP_SET + +/obj/item/kinetic_crusher/Destroy() + QDEL_LIST(trophies) + return ..() + +/obj/item/kinetic_crusher/Exited(atom/movable/gone, direction) + . = ..() + trophies -= gone + +/obj/item/kinetic_crusher/examine(mob/living/user) + . = ..() + . += span_notice("Mark a large creature with a destabilizing force with right-click, then hit them in melee to do [force + detonation_damage] damage.") + . += span_notice("Does [force + detonation_damage + backstab_bonus] damage if the target is backstabbed, instead of [force + detonation_damage].") + for(var/obj/item/crusher_trophy/crusher_trophy as anything in trophies) + . += span_notice("It has \a [crusher_trophy] attached, which causes [crusher_trophy.effect_desc()].") + +/obj/item/kinetic_crusher/attackby(obj/item/attacking_item, mob/user, params) + if(istype(attacking_item, /obj/item/crusher_trophy)) + var/obj/item/crusher_trophy/crusher_trophy = attacking_item + crusher_trophy.add_to(src, user) + return + return ..() + +/obj/item/kinetic_crusher/crowbar_act(mob/living/user, obj/item/tool) + . = ..() + if(!LAZYLEN(trophies)) + user.balloon_alert(user, "no trophies!") + return ITEM_INTERACT_BLOCKING + user.balloon_alert(user, "trophies removed") + tool.play_tool_sound(src) + for(var/obj/item/crusher_trophy/crusher_trophy as anything in trophies) + crusher_trophy.remove_from(src, user) + return ITEM_INTERACT_SUCCESS + +// adapted from kinetic accelerator attack_hand_secodary +/obj/item/kinetic_crusher/attack_hand_secondary(mob/user, list/modifiers) + . = ..() + if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + + if(!LAZYLEN(trophies)) + return SECONDARY_ATTACK_CONTINUE_CHAIN + + var/list/display_names = list() + var/list/items = list() + for(var/trophies_length in 1 to length(trophies)) + var/obj/item/crusher_trophy/trophy = trophies[trophies_length] + display_names[trophy.name] = REF(trophy) + var/image/item_image = image(icon = trophy.icon, icon_state = trophy.icon_state) + if(length(trophy.overlays)) + item_image.copy_overlays(trophy) + items["[trophy.name]"] = item_image + + var/pick = show_radial_menu(user, src, items, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE, tooltips = TRUE) + if(!pick) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + + var/trophy_reference = display_names[pick] + var/obj/item/crusher_trophy/trophy_to_remove = locate(trophy_reference) in trophies + if(!istype(trophy_to_remove)) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + trophy_to_remove.remove_from(src, user) + if(!user.put_in_hands(trophy_to_remove)) + trophy_to_remove.forceMove(drop_location()) + + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + +/obj/item/kinetic_crusher/proc/check_menu(mob/living/carbon/human/user) + if(!istype(user)) + return FALSE + if(user.incapacitated) + return FALSE + return TRUE + +/obj/item/kinetic_crusher/pre_attack(atom/A, mob/living/user, params) + . = ..() + if(.) + return TRUE + if(!HAS_TRAIT(src, TRAIT_WIELDED)) + user.balloon_alert(user, "must be wielded!") + return TRUE + return . + +/obj/item/kinetic_crusher/attack(mob/living/target, mob/living/carbon/user) + target.apply_status_effect(/datum/status_effect/crusher_damage) + return ..() + +/obj/item/kinetic_crusher/afterattack(mob/living/target, mob/living/user, clickparams) + if(!isliving(target)) + return + // Melee effect + for(var/obj/item/crusher_trophy/crusher_trophy as anything in trophies) + crusher_trophy.on_melee_hit(target, user) + if(QDELETED(target)) + return + var/datum/status_effect/crusher_mark/mark = target.has_status_effect(/datum/status_effect/crusher_mark) + var/boosted_mark = mark?.boosted + if(world.time < mark.mark_applied + mark.ready_delay) // Simple way to prevent right+left click at the same time to detonate the mark for free + return + if(!target.remove_status_effect(mark)) + return + // Detonation effect + var/datum/status_effect/crusher_damage/crusher_damage_effect = target.has_status_effect(/datum/status_effect/crusher_damage) || target.apply_status_effect(/datum/status_effect/crusher_damage) + var/target_health = target.health + for(var/obj/item/crusher_trophy/crusher_trophy as anything in trophies) + crusher_trophy.on_mark_detonation(target, user) + if(QDELETED(target)) + return + if(!QDELETED(crusher_damage_effect)) + crusher_damage_effect.total_damage += target_health - target.health //we did some damage, but let's not assume how much we did + new /obj/effect/temp_visual/kinetic_blast(get_turf(target)) + var/backstabbed = FALSE + var/combined_damage = detonation_damage + var/def_check = target.getarmor(type = BOMB) + // Backstab bonus + if(check_behind(user, target) || boosted_mark) + backstabbed = TRUE + combined_damage += backstab_bonus + playsound(user, 'sound/items/weapons/kinetic_accel.ogg', 100, TRUE) //Seriously who spelled it wrong + if(!QDELETED(crusher_damage_effect)) + crusher_damage_effect.total_damage += combined_damage + SEND_SIGNAL(user, COMSIG_LIVING_CRUSHER_DETONATE, target, src, backstabbed) + target.apply_damage(combined_damage, BRUTE, blocked = def_check) + +/obj/item/kinetic_crusher/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) + if(!HAS_TRAIT(src, TRAIT_WIELDED)) + balloon_alert(user, "wield it first!") + return ITEM_INTERACT_BLOCKING + if(interacting_with == user) + balloon_alert(user, "can't aim at yourself!") + return ITEM_INTERACT_BLOCKING + fire_kinetic_blast(interacting_with, user, modifiers) + return ITEM_INTERACT_SUCCESS + +/obj/item/kinetic_crusher/ranged_interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) + return interact_with_atom_secondary(interacting_with, user, modifiers) + +/obj/item/kinetic_crusher/proc/fire_kinetic_blast(atom/target, mob/living/user, list/modifiers) + if(!charged) + return + var/turf/proj_turf = user.loc + if(!isturf(proj_turf)) + return + var/obj/projectile/destabilizer/destabilizer = new(proj_turf) + destabilizer.icon_state = "[projectile_icon]" + for(var/obj/item/crusher_trophy/attached_trophy as anything in trophies) + attached_trophy.on_projectile_fire(destabilizer, user) + destabilizer.aim_projectile(target, user, modifiers) + destabilizer.firer = user + destabilizer.fired_from = src + playsound(user, 'sound/items/weapons/plasma_cutter.ogg', 100, TRUE) + destabilizer.fire() + charged = FALSE + update_appearance() + attempt_recharge_projectile() + +/// Handles the timer for reloading the projectile +/obj/item/kinetic_crusher/proc/attempt_recharge_projectile(set_recharge_time) + if(!set_recharge_time) + set_recharge_time = charge_time + deltimer(charge_timer) + charge_timer = addtimer(CALLBACK(src, PROC_REF(recharge_projectile)), set_recharge_time, TIMER_STOPPABLE) + +/// Recharges the projectile +/obj/item/kinetic_crusher/proc/recharge_projectile() + if(!charged) + charged = TRUE + update_appearance() + playsound(src.loc, 'sound/items/weapons/kinetic_reload.ogg', 60, TRUE) + +/obj/item/kinetic_crusher/ui_action_click(mob/user, actiontype) + set_light_on(!light_on) + playsound(user, 'sound/items/weapons/empty.ogg', 100, TRUE) + update_appearance() + +/obj/item/kinetic_crusher/on_saboteur(datum/source, disrupt_duration) + . = ..() + set_light_on(FALSE) + playsound(src, 'sound/items/weapons/empty.ogg', 100, TRUE) + return TRUE + +/obj/item/kinetic_crusher/update_icon_state() + inhand_icon_state = "[current_inhand_icon_state][HAS_TRAIT(src, TRAIT_WIELDED)]" // this is not icon_state and not supported by 2hcomponent + return ..() + +/obj/item/kinetic_crusher/update_overlays() + . = ..() + if(!charged) + . += "[icon_state]_uncharged" + if(light_on) + . += "[icon_state]_lit" + +/obj/item/kinetic_crusher/compact //for admins + name = "compact kinetic crusher" + w_class = WEIGHT_CLASS_NORMAL + +//destablizing force +/obj/projectile/destabilizer + name = "destabilizing force" + damage = 0 //We're just here to mark people. This is still a melee weapon. + damage_type = BRUTE + armor_flag = BOMB + range = 6 + log_override = TRUE + /// Has this projectile been boosted + var/boosted = FALSE + +/obj/projectile/destabilizer/Initialize(mapload) + . = ..() + AddComponent(/datum/component/parriable_projectile, parry_callback = CALLBACK(src, PROC_REF(on_parry))) + +/obj/projectile/destabilizer/Destroy() + fired_from = null + return ..() + +/obj/projectile/destabilizer/proc/on_parry(mob/user) + SIGNAL_HANDLER + boosted = TRUE + // Get a bit of a damage/range boost after being parried + damage = 10 + range = 9 + +/obj/projectile/destabilizer/on_hit(atom/target, blocked = 0, pierce_hit) + var/obj/item/kinetic_crusher/used_crusher + if(istype(fired_from, /obj/item/kinetic_crusher)) + used_crusher = fired_from + + if(isliving(target)) + for(var/obj/item/crusher_trophy/crusher_trophy as anything in used_crusher?.trophies) + crusher_trophy.on_projectile_hit_mob(target, firer) + if(QDELETED(target)) + return ..() + var/mob/living/living_target = target + living_target.apply_status_effect(/datum/status_effect/crusher_mark, boosted) + return ..() + + var/target_turf = get_turf(target) + if(ismineralturf(target_turf)) + var/turf/closed/mineral/hit_mineral = target_turf + for(var/obj/item/crusher_trophy/crusher_trophy as anything in used_crusher?.trophies) + crusher_trophy.on_projectile_hit_mineral(hit_mineral, firer) + if(QDELETED(hit_mineral)) + return ..() + new /obj/effect/temp_visual/kinetic_blast(hit_mineral) + hit_mineral.gets_drilled(firer, TRUE) + if(!iscarbon(firer)) + return ..() + var/mob/living/carbon/carbon_firer = firer + var/skill_modifier = 1 + // If there is a mind, check for skill modifier to allow them to reload faster. + if(carbon_firer.mind && used_crusher) + skill_modifier = carbon_firer.mind.get_skill_modifier(/datum/skill/mining, SKILL_SPEED_MODIFIER) + used_crusher.attempt_recharge_projectile(used_crusher.charge_time * skill_modifier) //If you hit a mineral, you might get a quicker reload. epic gamer style. + + return ..() + diff --git a/code/modules/mining/equipment/kinetic_crusher/kinetic_crusher_trophies.dm b/code/modules/mining/equipment/kinetic_crusher/kinetic_crusher_trophies.dm new file mode 100644 index 00000000000..6a00423206e --- /dev/null +++ b/code/modules/mining/equipment/kinetic_crusher/kinetic_crusher_trophies.dm @@ -0,0 +1,63 @@ +/*! + * Contains the baseline of kinetic crusher trophies. + */ + +/obj/item/crusher_trophy + name = "tail spike" + desc = "A strange spike with no usage." + icon = 'icons/obj/mining_zones/artefacts.dmi' + icon_state = "tail_spike" + /// if it has a bonus effect, this is how much that effect is + var/bonus_value = 10 + /// what type of trophies will block this trophy from being added, must be overriden + var/denied_type = /obj/item/crusher_trophy + +/obj/item/crusher_trophy/examine(mob/living/user) + . = ..() + . += span_notice("Causes [effect_desc()] when attached to a kinetic crusher.") + +/// Returns a string to get added to the examine +/obj/item/crusher_trophy/proc/effect_desc() + SHOULD_CALL_PARENT(FALSE) + return "errors" + +/obj/item/crusher_trophy/attackby(obj/item/attacking_item, mob/living/user) + if(!istype(attacking_item, /obj/item/kinetic_crusher)) + return ..() + add_to(attacking_item, user) + +/// Tries to add the trophy to our crusher +/obj/item/crusher_trophy/proc/add_to(obj/item/kinetic_crusher/crusher, mob/living/user) + for(var/obj/item/crusher_trophy/trophy as anything in crusher.trophies) + if(istype(trophy, denied_type) || istype(src, trophy.denied_type)) + to_chat(user, span_warning("You can't seem to attach [src] to [crusher]. Maybe remove a few trophies?")) + return FALSE + if(!user.transferItemToLoc(src, crusher)) + return + crusher.trophies += src + to_chat(user, span_notice("You attach [src] to [crusher].")) + return TRUE + +/// Removes the trophy from our crusher +/obj/item/crusher_trophy/proc/remove_from(obj/item/kinetic_crusher/crusher, mob/living/user) + forceMove(get_turf(crusher)) + return TRUE + +/// Does an effect when you hit a mob with a crusher +/obj/item/crusher_trophy/proc/on_melee_hit(mob/living/target, mob/living/user) //the target and the user + return + +/obj/item/crusher_trophy/proc/on_projectile_fire(obj/projectile/destabilizer/marker, mob/living/user) //the projectile fired and the user + return + +/// Does an effect when you hit a mob with the projectile +/obj/item/crusher_trophy/proc/on_projectile_hit_mob(mob/living/target, mob/living/user) //the target and the user + return + +/// Does an effect when you hit a mineral turf with the projectile +/obj/item/crusher_trophy/proc/on_projectile_hit_mineral(turf/closed/mineral, mob/living/user) //the target and the user + return + +/// Does an effect when you hit a mob that is marked via the projectile +/obj/item/crusher_trophy/proc/on_mark_detonation(mob/living/target, mob/living/user) //the target and the user + return diff --git a/code/modules/mining/equipment/kinetic_crusher/trophies_fauna.dm b/code/modules/mining/equipment/kinetic_crusher/trophies_fauna.dm new file mode 100644 index 00000000000..2327980a983 --- /dev/null +++ b/code/modules/mining/equipment/kinetic_crusher/trophies_fauna.dm @@ -0,0 +1,241 @@ +/*! + * Contains crusher trophies you can obtain from regular fauna + */ + +//watcher +/obj/item/crusher_trophy/watcher_wing + name = "watcher wing" + desc = "A wing ripped from a watcher. Suitable as a trophy for a kinetic crusher." + icon_state = "watcher_wing" + denied_type = /obj/item/crusher_trophy/watcher_wing + bonus_value = 5 + +/obj/item/crusher_trophy/watcher_wing/effect_desc() + return "mark detonation to prevent certain creatures from using certain attacks for [bonus_value*0.1] second\s" + +/obj/item/crusher_trophy/watcher_wing/on_mark_detonation(mob/living/target, mob/living/user) + if(ishostile(target)) + var/mob/living/simple_animal/hostile/H = target + if(H.ranged) //briefly delay ranged attacks + if(H.ranged_cooldown >= world.time) + H.ranged_cooldown += bonus_value + else + H.ranged_cooldown = bonus_value + world.time + +//magmawing watcher +/obj/item/crusher_trophy/blaster_tubes/magma_wing + name = "magmawing watcher wing" + desc = "A still-searing wing from a magmawing watcher. Suitable as a trophy for a kinetic crusher." + icon_state = "magma_wing" + gender = NEUTER + bonus_value = 5 + +/obj/item/crusher_trophy/blaster_tubes/magma_wing/effect_desc() + return "mark detonation to make the next destabilizer shot deal [bonus_value] damage" + +/obj/item/crusher_trophy/blaster_tubes/magma_wing/on_projectile_fire(obj/projectile/destabilizer/marker, mob/living/user) + if(deadly_shot) + marker.name = "heated [marker.name]" + marker.icon_state = "lava" + marker.damage = bonus_value + deadly_shot = FALSE + +//icewing watcher +/obj/item/crusher_trophy/watcher_wing/ice_wing + name = "icewing watcher wing" + desc = "A carefully preserved frozen wing from an icewing watcher. Suitable as a trophy for a kinetic crusher." + icon_state = "ice_wing" + bonus_value = 8 + +//legion +/obj/item/crusher_trophy/legion_skull + name = "legion skull" + desc = "A dead and lifeless legion skull. Suitable as a trophy for a kinetic crusher." + icon_state = "legion_skull" + denied_type = /obj/item/crusher_trophy/legion_skull + bonus_value = 3 + +/obj/item/crusher_trophy/legion_skull/effect_desc() + return "a kinetic crusher to recharge [bonus_value*0.1] second\s faster" + +/obj/item/crusher_trophy/legion_skull/add_to(obj/item/kinetic_crusher/pkc, mob/living/user) + . = ..() + if(.) + pkc.charge_time -= bonus_value + +/obj/item/crusher_trophy/legion_skull/remove_from(obj/item/kinetic_crusher/pkc, mob/living/user) + . = ..() + if(.) + pkc.charge_time += bonus_value + +// Goliath - Increases damage as your health decreases. +/obj/item/crusher_trophy/goliath_tentacle + name = "goliath tentacle" + desc = "A sliced-off goliath tentacle. Suitable as a trophy for a kinetic crusher." + icon_state = "goliath_tentacle" + denied_type = /obj/item/crusher_trophy/goliath_tentacle + bonus_value = 2 + /// Your missing health is multiplied by this value to find the bonus damage + var/missing_health_ratio = 0.1 + /// Amount of health you must lose to gain damage, according to the examine text. Cached so we don't recalculate it every examine. + var/missing_health_desc + +/obj/item/crusher_trophy/goliath_tentacle/Initialize(mapload) + . = ..() + missing_health_desc = 1 / missing_health_ratio / bonus_value + +/obj/item/crusher_trophy/goliath_tentacle/effect_desc() + return "mark detonation to do [bonus_value] more damage for every [missing_health_desc] health you are missing" + +/obj/item/crusher_trophy/goliath_tentacle/on_mark_detonation(mob/living/target, mob/living/user) + var/missing_health = user.maxHealth - user.health + missing_health *= missing_health_ratio //bonus is active at all times, even if you're above 90 health + missing_health *= bonus_value //multiply the remaining amount by bonus_value + if(missing_health > 0) + target.adjustBruteLoss(missing_health) //and do that much damage + +// Lobstrosity - Rebukes targets, increasing their click cooldown. +/obj/item/crusher_trophy/lobster_claw + name = "lobster claw" + icon_state = "lobster_claw" + desc = "A lobster claw." + denied_type = /obj/item/crusher_trophy/lobster_claw + bonus_value = 1 + +/obj/item/crusher_trophy/lobster_claw/effect_desc() + return "mark detonation to briefly rebuke the target for [bonus_value] seconds" + +/obj/item/crusher_trophy/lobster_claw/on_mark_detonation(mob/living/target, mob/living/user) + target.apply_status_effect(/datum/status_effect/rebuked, bonus_value SECONDS) + +// Brimdemon - makes a funny sound, the most essential trophy out of all +/obj/item/crusher_trophy/brimdemon_fang + name = "brimdemon's fang" + icon_state = "brimdemon_fang" + desc = "A fang from a brimdemon's corpse." + denied_type = /obj/item/crusher_trophy/brimdemon_fang + /// Cartoon punching vfx + var/static/list/comic_phrases = list("BOOM", "BANG", "KABLOW", "KAPOW", "OUCH", "BAM", "KAPOW", "WHAM", "POW", "KABOOM") + +/obj/item/crusher_trophy/brimdemon_fang/effect_desc() + return "mark detonation to create visual and audiosensory effects at the target" + +/obj/item/crusher_trophy/brimdemon_fang/on_mark_detonation(mob/living/target, mob/living/user) + target.balloon_alert_to_viewers("[pick(comic_phrases)]!") + playsound(target, 'sound/mobs/non-humanoids/brimdemon/brimdemon_crush.ogg', 100) + +// Bileworm +/obj/item/crusher_trophy/bileworm_spewlet + name = "bileworm spewlet" + icon = 'icons/mob/simple/lavaland/bileworm.dmi' + icon_state = "bileworm_spewlet" + desc = "A baby bileworm. Suitable as a trophy for a kinetic crusher." + denied_type = /obj/item/crusher_trophy/bileworm_spewlet + ///item ability that handles the effect + var/datum/action/cooldown/mob_cooldown/projectile_attack/dir_shots/spewlet/ability + +/obj/item/crusher_trophy/bileworm_spewlet/Initialize(mapload) + . = ..() + ability = new() + +/obj/item/crusher_trophy/bileworm_spewlet/Destroy(force) + . = ..() + QDEL_NULL(ability) + +/obj/item/crusher_trophy/bileworm_spewlet/add_to(obj/item/kinetic_crusher/crusher, mob/living/user) + . = ..() + if(.) + crusher.add_item_action(ability) + +/obj/item/crusher_trophy/bileworm_spewlet/remove_from(obj/item/kinetic_crusher/crusher, mob/living/user) + . = ..() + crusher.remove_item_action(ability) + +/obj/item/crusher_trophy/bileworm_spewlet/effect_desc() + return "mark detonation launches projectiles in cardinal directions on a 10 second cooldown. Also gives you an AOE when mining minerals" + +/obj/item/crusher_trophy/bileworm_spewlet/on_mark_detonation(mob/living/target, mob/living/user) + //ability itself handles cooldowns. + ability.InterceptClickOn(user, null, target) + +/obj/item/crusher_trophy/bileworm_spewlet/on_projectile_hit_mineral(turf/closed/mineral, mob/living/user) + for(var/turf/closed/mineral/mineral_turf in RANGE_TURFS(1, mineral) - mineral) + mineral_turf.gets_drilled(user, TRUE) + +//yes this is a /mob_cooldown subtype being added to an item. I can't recommend you do what I'm doing +/datum/action/cooldown/mob_cooldown/projectile_attack/dir_shots/spewlet + check_flags = NONE + owner_has_control = FALSE + cooldown_time = 10 SECONDS + projectile_type = /obj/projectile/bileworm_acid + projectile_sound = 'sound/mobs/non-humanoids/bileworm/bileworm_spit.ogg' + +/datum/action/cooldown/mob_cooldown/projectile_attack/dir_shots/spewlet/New(Target) + firing_directions = GLOB.cardinals.Copy() + return ..() + +// demonic watcher +/obj/item/crusher_trophy/ice_demon_cube + name = "demonic cube" + desc = "A stone cold cube dropped from an ice demon." + icon_state = "ice_demon_cube" + denied_type = /obj/item/crusher_trophy/ice_demon_cube + ///how many will we summon? + var/summon_amount = 2 + ///cooldown to summon demons upon the target + COOLDOWN_DECLARE(summon_cooldown) + +/obj/item/crusher_trophy/ice_demon_cube/effect_desc() + return "mark detonation to unleash demonic ice clones upon the target" + +/obj/item/crusher_trophy/ice_demon_cube/on_mark_detonation(mob/living/target, mob/living/user) + if(isnull(target) || !COOLDOWN_FINISHED(src, summon_cooldown)) + return + for(var/i in 1 to summon_amount) + var/turf/drop_off = find_dropoff_turf(target, user) + var/mob/living/basic/mining/demon_afterimage/crusher/friend = new(drop_off) + friend.faction = list(FACTION_NEUTRAL) + friend.befriend(user) + friend.ai_controller?.set_blackboard_key(BB_BASIC_MOB_CURRENT_TARGET, target) + COOLDOWN_START(src, summon_cooldown, 30 SECONDS) + +///try to make them spawn all around the target to surround him +/obj/item/crusher_trophy/ice_demon_cube/proc/find_dropoff_turf(mob/living/target, mob/living/user) + var/list/turfs_list = get_adjacent_open_turfs(target) + for(var/turf/possible_turf in turfs_list) + if(possible_turf.is_blocked_turf()) + continue + return possible_turf + return get_turf(user) + +// Wolf + +/obj/item/crusher_trophy/wolf_ear + name = "wolf ear" + desc = "It's a wolf ear." + icon_state = "wolf_ear" + denied_type = /obj/item/crusher_trophy/wolf_ear + +/obj/item/crusher_trophy/wolf_ear/effect_desc() + return "mark detonation to gain a slight speed boost temporarily" + +/obj/item/crusher_trophy/wolf_ear/on_mark_detonation(mob/living/target, mob/living/user) + user.apply_status_effect(/datum/status_effect/speed_boost, 1 SECONDS) + +// Polar bear +/obj/item/crusher_trophy/bear_paw + name = "polar bear paw" + desc = "It's a polar bear paw." + icon_state = "bear_paw" + denied_type = /obj/item/crusher_trophy/bear_paw + +/obj/item/crusher_trophy/bear_paw/effect_desc() + return "mark detonation to attack twice if you are below half your life" + +/obj/item/crusher_trophy/bear_paw/on_mark_detonation(mob/living/target, mob/living/user) + if(user.health / user.maxHealth > 0.5) + return + var/obj/item/I = user.get_active_held_item() + if(!I) + return + I.melee_attack_chain(user, target, null) diff --git a/code/modules/mining/equipment/kinetic_crusher/trophies_megafauna.dm b/code/modules/mining/equipment/kinetic_crusher/trophies_megafauna.dm new file mode 100644 index 00000000000..ba302999010 --- /dev/null +++ b/code/modules/mining/equipment/kinetic_crusher/trophies_megafauna.dm @@ -0,0 +1,217 @@ +/*! + * Contains crusher trophies you can obtain from megafauna + */ + +//blood-drunk hunter +/obj/item/crusher_trophy/miner_eye + name = "eye of a blood-drunk hunter" + desc = "Its pupil is collapsed and turned to mush. Suitable as a trophy for a kinetic crusher." + icon_state = "hunter_eye" + denied_type = /obj/item/crusher_trophy/miner_eye + +/obj/item/crusher_trophy/miner_eye/effect_desc() + return "mark detonation to grant stun immunity and 90% damage reduction for 1 second" + +/obj/item/crusher_trophy/miner_eye/on_mark_detonation(mob/living/target, mob/living/user) + user.apply_status_effect(/datum/status_effect/blooddrunk) + +//ash drake +/obj/item/crusher_trophy/tail_spike + desc = "A spike taken from an ash drake's tail. Suitable as a trophy for a kinetic crusher." + denied_type = /obj/item/crusher_trophy/tail_spike + bonus_value = 5 + +/obj/item/crusher_trophy/tail_spike/effect_desc() + return "mark detonation to do [bonus_value] damage to nearby creatures and push them back" + +/obj/item/crusher_trophy/tail_spike/on_mark_detonation(mob/living/target, mob/living/user) + for(var/mob/living/living_target in oview(2, user)) + if(user.faction_check_atom(living_target) || living_target.stat == DEAD) + continue + playsound(living_target, 'sound/effects/magic/fireball.ogg', 20, TRUE) + new /obj/effect/temp_visual/fire(living_target.loc) + addtimer(CALLBACK(src, PROC_REF(pushback), living_target, user), 1) //no free backstabs, we push AFTER module stuff is done + living_target.adjustFireLoss(bonus_value, forced = TRUE) + +/obj/item/crusher_trophy/tail_spike/proc/pushback(mob/living/target, mob/living/user) + if(!QDELETED(target) && !QDELETED(user) && (!target.anchored || ismegafauna(target))) //megafauna will always be pushed + step(target, get_dir(user, target)) + +//bubblegum +/obj/item/crusher_trophy/demon_claws + name = "demon claws" + desc = "A set of blood-drenched claws from a massive demon's hand. Suitable as a trophy for a kinetic crusher." + icon_state = "demon_claws" + gender = PLURAL + denied_type = /obj/item/crusher_trophy/demon_claws + bonus_value = 10 + var/static/list/damage_heal_order = list(BRUTE, BURN, OXY) + +/obj/item/crusher_trophy/demon_claws/effect_desc() + return "melee hits to do [bonus_value * 0.2] more damage and heal you for [bonus_value * 0.1], with 5X effect on mark detonation" + +/obj/item/crusher_trophy/demon_claws/add_to(obj/item/kinetic_crusher/pkc, mob/living/user) + . = ..() + if(.) + pkc.force += bonus_value * 0.2 + pkc.detonation_damage += bonus_value * 0.8 + AddComponent(/datum/component/two_handed, force_wielded=(20 + bonus_value * 0.2)) + +/obj/item/crusher_trophy/demon_claws/remove_from(obj/item/kinetic_crusher/pkc, mob/living/user) + . = ..() + if(.) + pkc.force -= bonus_value * 0.2 + pkc.detonation_damage -= bonus_value * 0.8 + AddComponent(/datum/component/two_handed, force_wielded=20) + +/obj/item/crusher_trophy/demon_claws/on_melee_hit(mob/living/target, mob/living/user) + user.heal_ordered_damage(bonus_value * 0.1, damage_heal_order) + +/obj/item/crusher_trophy/demon_claws/on_mark_detonation(mob/living/target, mob/living/user) + user.heal_ordered_damage(bonus_value * 0.4, damage_heal_order) + +//colossus +/obj/item/crusher_trophy/blaster_tubes + name = "blaster tubes" + desc = "The blaster tubes from a colossus's arm. Suitable as a trophy for a kinetic crusher." + icon_state = "blaster_tubes" + gender = PLURAL + denied_type = /obj/item/crusher_trophy/blaster_tubes + bonus_value = 15 + var/deadly_shot = FALSE + +/obj/item/crusher_trophy/blaster_tubes/effect_desc() + return "mark detonation to make the next destabilizer shot deal [bonus_value] damage but move slower" + +/obj/item/crusher_trophy/blaster_tubes/on_projectile_fire(obj/projectile/destabilizer/marker, mob/living/user) + if(deadly_shot) + marker.name = "deadly [marker.name]" + marker.icon_state = "chronobolt" + marker.damage = bonus_value + marker.speed = 2 + deadly_shot = FALSE + +/obj/item/crusher_trophy/blaster_tubes/on_mark_detonation(mob/living/target, mob/living/user) + deadly_shot = TRUE + addtimer(CALLBACK(src, PROC_REF(reset_deadly_shot)), 300, TIMER_UNIQUE|TIMER_OVERRIDE) + +/obj/item/crusher_trophy/blaster_tubes/proc/reset_deadly_shot() + deadly_shot = FALSE + +//hierophant +/obj/item/crusher_trophy/vortex_talisman + name = "vortex talisman" + desc = "A glowing trinket that was originally the Hierophant's beacon. Suitable as a trophy for a kinetic crusher." + icon_state = "vortex_talisman" + denied_type = /obj/item/crusher_trophy/vortex_talisman + +/obj/item/crusher_trophy/vortex_talisman/effect_desc() + return "mark detonation to create a homing hierophant chaser" + +/obj/item/crusher_trophy/vortex_talisman/on_mark_detonation(mob/living/target, mob/living/user) + if(isliving(target)) + var/obj/effect/temp_visual/hierophant/chaser/chaser = new(get_turf(user), user, target, 3, TRUE) + chaser.monster_damage_boost = FALSE // Weaker cuz no cooldown + chaser.damage = 20 + log_combat(user, target, "fired a chaser at", src) + +// Demonic frost miner +/obj/item/crusher_trophy/ice_block_talisman + name = "ice block talisman" + desc = "A glowing trinket that a demonic miner had on him, it seems he couldn't utilize it for whatever reason." + icon_state = "ice_trap_talisman" + denied_type = /obj/item/crusher_trophy/ice_block_talisman + +/obj/item/crusher_trophy/ice_block_talisman/effect_desc() + return "mark detonation to freeze a creature in a block of ice for a period, preventing them from moving" + +/obj/item/crusher_trophy/ice_block_talisman/on_mark_detonation(mob/living/target, mob/living/user) + target.apply_status_effect(/datum/status_effect/ice_block_talisman) + +// Wendigo +/obj/item/crusher_trophy/wendigo_horn + name = "wendigo horn" + desc = "A gnarled horn ripped from the skull of a wendigo. Suitable as a trophy for a kinetic crusher." + icon_state = "wendigo_horn" + denied_type = /obj/item/crusher_trophy/wendigo_horn + +/obj/item/crusher_trophy/wendigo_horn/effect_desc() + return "melee hits inflict twice as much damage" + +/obj/item/crusher_trophy/wendigo_horn/add_to(obj/item/kinetic_crusher/crusher, mob/living/user) + . = ..() + if(.) + crusher.AddComponent(/datum/component/two_handed, force_wielded=40) + +/obj/item/crusher_trophy/wendigo_horn/remove_from(obj/item/kinetic_crusher/crusher, mob/living/user) + . = ..() + if(.) + crusher.AddComponent(/datum/component/two_handed, force_wielded=20) + +// Goliath Broodmother +/obj/item/crusher_trophy/broodmother_tongue + name = "broodmother tongue" + desc = "The tongue of a broodmother. If attached a certain way, makes for a suitable crusher trophy. It also feels very spongey, I wonder what would happen if you squeezed it?..." + icon = 'icons/obj/mining_zones/elite_trophies.dmi' + icon_state = "broodmother_tongue" + denied_type = /obj/item/crusher_trophy/broodmother_tongue + bonus_value = 10 + /// Time at which the item becomes usable again + var/use_time + +/obj/item/crusher_trophy/broodmother_tongue/effect_desc() + return "mark detonation to have a [bonus_value]% chance to summon a patch of goliath tentacles at the target's location" + +/obj/item/crusher_trophy/broodmother_tongue/on_mark_detonation(mob/living/target, mob/living/user) + if(prob(bonus_value) && target.stat != DEAD) + new /obj/effect/goliath_tentacle/broodmother/patch(get_turf(target), user) + +/obj/item/crusher_trophy/broodmother_tongue/attack_self(mob/user) + if(!isliving(user)) + return + var/mob/living/living_user = user + if(use_time > world.time) + to_chat(living_user, "The tongue looks dried out. You'll need to wait longer to use it again.") + return + else if(HAS_TRAIT(living_user, TRAIT_LAVA_IMMUNE)) + to_chat(living_user, "You stare at the tongue. You don't think this is any use to you.") + return + ADD_TRAIT(living_user, TRAIT_LAVA_IMMUNE, type) + to_chat(living_user, "You squeeze the tongue, and some transluscent liquid shoots out all over you.") + addtimer(TRAIT_CALLBACK_REMOVE(user, TRAIT_LAVA_IMMUNE, type), 10 SECONDS) + use_time = world.time + 60 SECONDS + +// Legionnaire +/obj/item/crusher_trophy/legionnaire_spine + name = "legionnaire spine" + desc = "The spine of a legionnaire. With some creativity, you could use it as a crusher trophy. Alternatively, shaking it might do something as well." + icon = 'icons/obj/mining_zones/elite_trophies.dmi' + icon_state = "legionnaire_spine" + denied_type = /obj/item/crusher_trophy/legionnaire_spine + bonus_value = 20 + /// Time at which the item becomes usable again + var/next_use_time + +/obj/item/crusher_trophy/legionnaire_spine/effect_desc() + return "mark detonation to have a [bonus_value]% chance to summon a loyal legion skull" + +/obj/item/crusher_trophy/legionnaire_spine/on_mark_detonation(mob/living/target, mob/living/user) + if(!prob(bonus_value) || target.stat == DEAD) + return + var/mob/living/basic/legion_brood/minion = new (user.loc) + minion.assign_creator(user) + minion.ai_controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] = target + +/obj/item/crusher_trophy/legionnaire_spine/attack_self(mob/user) + if(!isliving(user)) + return + var/mob/living/LivingUser = user + if(next_use_time > world.time) + LivingUser.visible_message(span_warning("[LivingUser] shakes the [src], but nothing happens...")) + to_chat(LivingUser, "You need to wait longer to use this again.") + return + LivingUser.visible_message(span_boldwarning("[LivingUser] shakes the [src] and summons a legion skull!")) + + var/mob/living/basic/legion_brood/minion = new (LivingUser.loc) + minion.assign_creator(LivingUser) + next_use_time = world.time + 4 SECONDS diff --git a/code/modules/mining/equipment/kinetic_crusher/trophies_misc.dm b/code/modules/mining/equipment/kinetic_crusher/trophies_misc.dm new file mode 100644 index 00000000000..4d50d0aa3f7 --- /dev/null +++ b/code/modules/mining/equipment/kinetic_crusher/trophies_misc.dm @@ -0,0 +1,84 @@ +/*! + * Contains crusher trophies that are not obtained from fauna + */ + +//cosmetic items for changing the crusher's look + +/obj/item/crusher_trophy/retool_kit + name = "crusher sword retool kit" + desc = "A toolkit for changing the crusher's appearance without affecting the device's function. This one will make it look like a sword." + icon = 'icons/obj/mining.dmi' + icon_state = "retool_kit" + denied_type = /obj/item/crusher_trophy/retool_kit + ///Specifies the sprite/icon state which the crusher is changed to as an item. Should appear in the icons/obj/mining.dmi file with accompanying "lit" and "recharging" sprites + var/retool_icon = "crusher_sword" + ///Specifies the icon state for the crusher's appearance in hand. Should appear in both icons/mob/inhands/weapons/hammers_lefthand.dmi and icons/mob/inhands/weapons/hammers_righthand.dmi + var/retool_inhand_icon = "crusher_sword" + ///For if the retool kit changes the projectile's appearance. The sprite should be in icons/obj/weapons/guns/projectiles.dmi + var/retool_projectile_icon = "pulse1" + +/obj/item/crusher_trophy/retool_kit/effect_desc() + return "the crusher to have the appearance of a sword" + +/obj/item/crusher_trophy/retool_kit/add_to(obj/item/kinetic_crusher/pkc, mob/user) + . = ..() + if(.) + pkc.icon_state = retool_icon + pkc.current_inhand_icon_state = retool_inhand_icon + pkc.projectile_icon = retool_projectile_icon + if(iscarbon(pkc.loc)) + var/mob/living/carbon/holder = pkc.loc + holder.update_worn_back() + holder.update_suit_storage() + holder.update_held_items() + pkc.update_appearance() + +/obj/item/crusher_trophy/retool_kit/remove_from(obj/item/kinetic_crusher/pkc) + pkc.icon_state = initial(pkc.icon_state) + pkc.current_inhand_icon_state = initial(pkc.current_inhand_icon_state) + pkc.projectile_icon = initial(pkc.projectile_icon) + if(iscarbon(pkc.loc)) + var/mob/living/carbon/holder = pkc.loc + holder.update_worn_back() + holder.update_suit_storage() + holder.update_held_items() + pkc.update_appearance() + ..() + +/obj/item/crusher_trophy/retool_kit/harpoon + name = "crusher harpoon retool kit" + desc = "A toolkit for changing the crusher's appearance without affecting the device's function. This one will make it look like a harpoon." + icon = 'icons/obj/mining.dmi' + icon_state = "retool_kit" + denied_type = /obj/item/crusher_trophy/retool_kit + retool_icon = "crusher_harpoon" + retool_inhand_icon = "crusher_harpoon" + retool_projectile_icon = "pulse_harpoon" + +/obj/item/crusher_trophy/retool_kit/harpoon/effect_desc() + return "the crusher to have the appearance of a harpoon" + +/obj/item/crusher_trophy/retool_kit/dagger + name = "crusher dagger retool kit" + desc = "A toolkit for changing the crusher's appearance without affecting the device's function. This one will make it look like a dual dagger and mini-blaster on a chain." + icon = 'icons/obj/mining.dmi' + icon_state = "retool_kit" + denied_type = /obj/item/crusher_trophy/retool_kit + retool_icon = "crusher_dagger" + retool_inhand_icon = "crusher_dagger" + +/obj/item/crusher_trophy/retool_kit/dagger/effect_desc() + return "the crusher to have the appearance of a dual dagger and blaster" + +/obj/item/crusher_trophy/retool_kit/ashenskull + name = "ashen skull" + desc = "It burns with the flame of the necropolis, whispering in your ear. It demands to be bound to a suitable weapon." + icon = 'icons/obj/mining.dmi' + icon_state = "retool_kit_skull" + denied_type = /obj/item/crusher_trophy/retool_kit + retool_icon = "crusher_skull" + retool_inhand_icon = "crusher_skull" + retool_projectile_icon = "pulse_skull" + +/obj/item/crusher_trophy/retool_kit/ashenskull/effect_desc() + return "the crusher to appear corrupted by infernal powers" diff --git a/code/modules/mob/living/basic/lavaland/bileworm/bileworm_loot.dm b/code/modules/mob/living/basic/lavaland/bileworm/bileworm_loot.dm index a5740a51ebd..55f960e736a 100644 --- a/code/modules/mob/living/basic/lavaland/bileworm/bileworm_loot.dm +++ b/code/modules/mob/living/basic/lavaland/bileworm/bileworm_loot.dm @@ -9,50 +9,3 @@ icon_state = "sheet-bileworm" inhand_icon_state = null merge_type = /obj/item/stack/sheet/animalhide/bileworm - -//trophy - -/obj/item/crusher_trophy/bileworm_spewlet - name = "bileworm spewlet" - icon = 'icons/mob/simple/lavaland/bileworm.dmi' - icon_state = "bileworm_spewlet" - desc = "A baby bileworm. Suitable as a trophy for a kinetic crusher." - denied_type = /obj/item/crusher_trophy/bileworm_spewlet - ///item ability that handles the effect - var/datum/action/cooldown/mob_cooldown/projectile_attack/dir_shots/spewlet/ability - -/obj/item/crusher_trophy/bileworm_spewlet/Initialize(mapload) - . = ..() - ability = new() - -/obj/item/crusher_trophy/bileworm_spewlet/Destroy(force) - . = ..() - QDEL_NULL(ability) - -/obj/item/crusher_trophy/bileworm_spewlet/add_to(obj/item/kinetic_crusher/crusher, mob/living/user) - . = ..() - if(.) - crusher.add_item_action(ability) - -/obj/item/crusher_trophy/bileworm_spewlet/remove_from(obj/item/kinetic_crusher/crusher, mob/living/user) - . = ..() - crusher.remove_item_action(ability) - -/obj/item/crusher_trophy/bileworm_spewlet/effect_desc() - return "mark detonation launches projectiles in cardinal directions on a 10 second cooldown" - -/obj/item/crusher_trophy/bileworm_spewlet/on_mark_detonation(mob/living/target, mob/living/user) - //ability itself handles cooldowns. - ability.InterceptClickOn(user, null, target) - -//yes this is a /mob_cooldown subtype being added to an item. I can't recommend you do what I'm doing -/datum/action/cooldown/mob_cooldown/projectile_attack/dir_shots/spewlet - check_flags = NONE - owner_has_control = FALSE - cooldown_time = 10 SECONDS - projectile_type = /obj/projectile/bileworm_acid - projectile_sound = 'sound/mobs/non-humanoids/bileworm/bileworm_spit.ogg' - -/datum/action/cooldown/mob_cooldown/projectile_attack/dir_shots/spewlet/New(Target) - firing_directions = GLOB.cardinals.Copy() - return ..() diff --git a/code/modules/mob/living/basic/lavaland/brimdemon/brimdemon_loot.dm b/code/modules/mob/living/basic/lavaland/brimdemon/brimdemon_loot.dm index 9b1916c9ac0..fcc03c95318 100644 --- a/code/modules/mob/living/basic/lavaland/brimdemon/brimdemon_loot.dm +++ b/code/modules/mob/living/basic/lavaland/brimdemon/brimdemon_loot.dm @@ -1,19 +1,3 @@ -/// Brimdemon crusher trophy, it... makes a funny sound? -/obj/item/crusher_trophy/brimdemon_fang - name = "brimdemon's fang" - icon_state = "brimdemon_fang" - desc = "A fang from a brimdemon's corpse." - denied_type = /obj/item/crusher_trophy/brimdemon_fang - /// Cartoon punching vfx - var/static/list/comic_phrases = list("BOOM", "BANG", "KABLOW", "KAPOW", "OUCH", "BAM", "KAPOW", "WHAM", "POW", "KABOOM") - -/obj/item/crusher_trophy/brimdemon_fang/effect_desc() - return "mark detonation to create visual and audiosensory effects at the target" - -/obj/item/crusher_trophy/brimdemon_fang/on_mark_detonation(mob/living/target, mob/living/user) - target.balloon_alert_to_viewers("[pick(comic_phrases)]!") - playsound(target, 'sound/mobs/non-humanoids/brimdemon/brimdemon_crush.ogg', 100) - /// Reagent pool left by dying brimdemon /obj/effect/decal/cleanable/brimdust name = "brimdust" diff --git a/code/modules/mob/living/basic/lavaland/goliath/goliath_trophy.dm b/code/modules/mob/living/basic/lavaland/goliath/goliath_trophy.dm deleted file mode 100644 index a4801569cea..00000000000 --- a/code/modules/mob/living/basic/lavaland/goliath/goliath_trophy.dm +++ /dev/null @@ -1,25 +0,0 @@ -/// Mining crusher trophy from a goliath. Increases damage as your health decreases. -/obj/item/crusher_trophy/goliath_tentacle - name = "goliath tentacle" - desc = "A sliced-off goliath tentacle. Suitable as a trophy for a kinetic crusher." - icon_state = "goliath_tentacle" - denied_type = /obj/item/crusher_trophy/goliath_tentacle - bonus_value = 2 - /// Your missing health is multiplied by this value to find the bonus damage - var/missing_health_ratio = 0.1 - /// Amount of health you must lose to gain damage, according to the examine text. Cached so we don't recalculate it every examine. - var/missing_health_desc - -/obj/item/crusher_trophy/goliath_tentacle/Initialize(mapload) - . = ..() - missing_health_desc = 1 / missing_health_ratio / bonus_value - -/obj/item/crusher_trophy/goliath_tentacle/effect_desc() - return "mark detonation to do [bonus_value] more damage for every [missing_health_desc] health you are missing" - -/obj/item/crusher_trophy/goliath_tentacle/on_mark_detonation(mob/living/target, mob/living/user) - var/missing_health = user.maxHealth - user.health - missing_health *= missing_health_ratio //bonus is active at all times, even if you're above 90 health - missing_health *= bonus_value //multiply the remaining amount by bonus_value - if(missing_health > 0) - target.adjustBruteLoss(missing_health) //and do that much damage diff --git a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_trophy.dm b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_trophy.dm deleted file mode 100644 index 4647aab260a..00000000000 --- a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_trophy.dm +++ /dev/null @@ -1,13 +0,0 @@ -/// Lobstrosity crusher trophy. Rebukes targets, increasing their click cooldown. -/obj/item/crusher_trophy/lobster_claw - name = "lobster claw" - icon_state = "lobster_claw" - desc = "A lobster claw." - denied_type = /obj/item/crusher_trophy/lobster_claw - bonus_value = 1 - -/obj/item/crusher_trophy/lobster_claw/effect_desc() - return "mark detonation to briefly rebuke the target for [bonus_value] seconds" - -/obj/item/crusher_trophy/lobster_claw/on_mark_detonation(mob/living/target, mob/living/user) - target.apply_status_effect(/datum/status_effect/rebuked, bonus_value SECONDS) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner.dm index 8cdf9141ab8..a5897c01695 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner.dm @@ -321,18 +321,6 @@ Difficulty: Extremely Hard mineral_scan_pulse(T, world.view + 1, src) . = ..() -/obj/item/crusher_trophy/ice_block_talisman - name = "ice block talisman" - desc = "A glowing trinket that a demonic miner had on him, it seems he couldn't utilize it for whatever reason." - icon_state = "ice_trap_talisman" - denied_type = /obj/item/crusher_trophy/ice_block_talisman - -/obj/item/crusher_trophy/ice_block_talisman/effect_desc() - return "mark detonation to freeze a creature in a block of ice for a period, preventing them from moving" - -/obj/item/crusher_trophy/ice_block_talisman/on_mark_detonation(mob/living/target, mob/living/user) - target.apply_status_effect(/datum/status_effect/ice_block_talisman) - /datum/status_effect/ice_block_talisman id = "ice_block_talisman" duration = 4 SECONDS diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/wendigo.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/wendigo.dm index 4643d529d49..b6ba30f523f 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/wendigo.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/wendigo.dm @@ -240,25 +240,6 @@ Difficulty: Hard playsound(human_user.loc, 'sound/items/drink.ogg', rand(10,50), TRUE) qdel(src) -/obj/item/crusher_trophy/wendigo_horn - name = "wendigo horn" - desc = "A gnarled horn ripped from the skull of a wendigo. Suitable as a trophy for a kinetic crusher." - icon_state = "wendigo_horn" - denied_type = /obj/item/crusher_trophy/wendigo_horn - -/obj/item/crusher_trophy/wendigo_horn/effect_desc() - return "melee hits inflict twice as much damage" - -/obj/item/crusher_trophy/wendigo_horn/add_to(obj/item/kinetic_crusher/crusher, mob/living/user) - . = ..() - if(.) - crusher.AddComponent(/datum/component/two_handed, force_wielded=40) - -/obj/item/crusher_trophy/wendigo_horn/remove_from(obj/item/kinetic_crusher/crusher, mob/living/user) - . = ..() - if(.) - crusher.AddComponent(/datum/component/two_handed, force_wielded=20) - /obj/item/wendigo_skull name = "wendigo skull" desc = "A bloody skull torn from a murderous beast, the soulless eye sockets seem to constantly track your movement." diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm index 6e673aa9be5..55d7a1d5c3d 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm @@ -244,39 +244,6 @@ T = get_step(T, i) new /obj/effect/goliath_tentacle/broodmother(T) -// Broodmother's loot: Broodmother Tongue -/obj/item/crusher_trophy/broodmother_tongue - name = "broodmother tongue" - desc = "The tongue of a broodmother. If attached a certain way, makes for a suitable crusher trophy. It also feels very spongey, I wonder what would happen if you squeezed it?..." - icon = 'icons/obj/mining_zones/elite_trophies.dmi' - icon_state = "broodmother_tongue" - denied_type = /obj/item/crusher_trophy/broodmother_tongue - bonus_value = 10 - /// Time at which the item becomes usable again - var/use_time - -/obj/item/crusher_trophy/broodmother_tongue/effect_desc() - return "mark detonation to have a [bonus_value]% chance to summon a patch of goliath tentacles at the target's location" - -/obj/item/crusher_trophy/broodmother_tongue/on_mark_detonation(mob/living/target, mob/living/user) - if(prob(bonus_value) && target.stat != DEAD) - new /obj/effect/goliath_tentacle/broodmother/patch(get_turf(target), user) - -/obj/item/crusher_trophy/broodmother_tongue/attack_self(mob/user) - if(!isliving(user)) - return - var/mob/living/living_user = user - if(use_time > world.time) - to_chat(living_user, "The tongue looks dried out. You'll need to wait longer to use it again.") - return - else if(HAS_TRAIT(living_user, TRAIT_LAVA_IMMUNE)) - to_chat(living_user, "You stare at the tongue. You don't think this is any use to you.") - return - ADD_TRAIT(living_user, TRAIT_LAVA_IMMUNE, type) - to_chat(living_user, "You squeeze the tongue, and some transluscent liquid shoots out all over you.") - addtimer(TRAIT_CALLBACK_REMOVE(user, TRAIT_LAVA_IMMUNE, type), 10 SECONDS) - use_time = world.time + 60 SECONDS - #undef CALL_CHILDREN #undef RAGE #undef SPAWN_CHILDREN diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm index 051733211ed..1c729df07d3 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm @@ -310,42 +310,6 @@ . = ..() transform *= 0.33 -// Legionnaire's loot: Legionnaire Spine - -/obj/item/crusher_trophy/legionnaire_spine - name = "legionnaire spine" - desc = "The spine of a legionnaire. With some creativity, you could use it as a crusher trophy. Alternatively, shaking it might do something as well." - icon = 'icons/obj/mining_zones/elite_trophies.dmi' - icon_state = "legionnaire_spine" - denied_type = /obj/item/crusher_trophy/legionnaire_spine - bonus_value = 20 - /// Time at which the item becomes usable again - var/next_use_time - -/obj/item/crusher_trophy/legionnaire_spine/effect_desc() - return "mark detonation to have a [bonus_value]% chance to summon a loyal legion skull" - -/obj/item/crusher_trophy/legionnaire_spine/on_mark_detonation(mob/living/target, mob/living/user) - if(!prob(bonus_value) || target.stat == DEAD) - return - var/mob/living/basic/legion_brood/minion = new (user.loc) - minion.assign_creator(user) - minion.ai_controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] = target - -/obj/item/crusher_trophy/legionnaire_spine/attack_self(mob/user) - if(!isliving(user)) - return - var/mob/living/LivingUser = user - if(next_use_time > world.time) - LivingUser.visible_message(span_warning("[LivingUser] shakes the [src], but nothing happens...")) - to_chat(LivingUser, "You need to wait longer to use this again.") - return - LivingUser.visible_message(span_boldwarning("[LivingUser] shakes the [src] and summons a legion skull!")) - - var/mob/living/basic/legion_brood/minion = new (LivingUser.loc) - minion.assign_creator(LivingUser) - next_use_time = world.time + 4 SECONDS - #undef LEGIONNAIRE_CHARGE #undef HEAD_DETACH #undef BONFIRE_TELEPORT diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/polarbear.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/polarbear.dm index 5dba83e2532..ef8e596ac2c 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/polarbear.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/polarbear.dm @@ -65,20 +65,3 @@ name = "magic polar bear" desc = "It seems sentient somehow." faction = list(FACTION_NEUTRAL) - -/obj/item/crusher_trophy/bear_paw - name = "polar bear paw" - desc = "It's a polar bear paw." - icon_state = "bear_paw" - denied_type = /obj/item/crusher_trophy/bear_paw - -/obj/item/crusher_trophy/bear_paw/effect_desc() - return "mark detonation to attack twice if you are below half your life" - -/obj/item/crusher_trophy/bear_paw/on_mark_detonation(mob/living/target, mob/living/user) - if(user.health / user.maxHealth > 0.5) - return - var/obj/item/I = user.get_active_held_item() - if(!I) - return - I.melee_attack_chain(user, target, null) diff --git a/tgstation.dme b/tgstation.dme index 0080adde356..da97fec2249 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -4759,7 +4759,6 @@ #include "code\modules\mining\equipment\explorer_gear.dm" #include "code\modules\mining\equipment\grapple_gun.dm" #include "code\modules\mining\equipment\kheiral_cuffs.dm" -#include "code\modules\mining\equipment\kinetic_crusher.dm" #include "code\modules\mining\equipment\lazarus_injector.dm" #include "code\modules\mining\equipment\marker_beacons.dm" #include "code\modules\mining\equipment\mineral_scanner.dm" @@ -4769,6 +4768,11 @@ #include "code\modules\mining\equipment\survival_pod.dm" #include "code\modules\mining\equipment\vent_pointer.dm" #include "code\modules\mining\equipment\wormhole_jaunter.dm" +#include "code\modules\mining\equipment\kinetic_crusher\kinetic_crusher.dm" +#include "code\modules\mining\equipment\kinetic_crusher\kinetic_crusher_trophies.dm" +#include "code\modules\mining\equipment\kinetic_crusher\trophies_fauna.dm" +#include "code\modules\mining\equipment\kinetic_crusher\trophies_megafauna.dm" +#include "code\modules\mining\equipment\kinetic_crusher\trophies_misc.dm" #include "code\modules\mining\equipment\monster_organs\brimdust_sac.dm" #include "code\modules\mining\equipment\monster_organs\monster_organ.dm" #include "code\modules\mining\equipment\monster_organs\regenerative_core.dm" @@ -4975,7 +4979,6 @@ #include "code\modules\mob\living\basic\lavaland\goliath\goliath.dm" #include "code\modules\mob\living\basic\lavaland\goliath\goliath_actions.dm" #include "code\modules\mob\living\basic\lavaland\goliath\goliath_ai.dm" -#include "code\modules\mob\living\basic\lavaland\goliath\goliath_trophy.dm" #include "code\modules\mob\living\basic\lavaland\goliath\tentacle.dm" #include "code\modules\mob\living\basic\lavaland\gutlunchers\gutluncher_foodtrough.dm" #include "code\modules\mob\living\basic\lavaland\gutlunchers\gutlunchers.dm" @@ -4992,7 +4995,6 @@ #include "code\modules\mob\living\basic\lavaland\legion\spawn_legions.dm" #include "code\modules\mob\living\basic\lavaland\lobstrosity\lobstrosity.dm" #include "code\modules\mob\living\basic\lavaland\lobstrosity\lobstrosity_ai.dm" -#include "code\modules\mob\living\basic\lavaland\lobstrosity\lobstrosity_trophy.dm" #include "code\modules\mob\living\basic\lavaland\mook\mook.dm" #include "code\modules\mob\living\basic\lavaland\mook\mook_abilities.dm" #include "code\modules\mob\living\basic\lavaland\mook\mook_ai.dm"