mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-30 02:52:30 +00:00
## About The Pull Request FOV as it is currently implemented is incompatible* with wallening. I'm doin wallening, so we gotta redo things here. The issue is the masking of mobs. Wallening relies on sidemap (layering based off physical position), which only works on things on the same plane (because planes are basically sheets we render down onto) So rather then masking mobs, let's reuse the masking idea from old fov, and use it to cut out a bit of the game render plane, and blur/over-saturate the bit that's masked out. My hope is this makes things visible in light, but not as much in darkness, alongside making more vivid shit more easily seen (just like real life) Here's some videos, what follows after is the commits I care about (since I had to rip a bunch of planes to nothing, so the files changed tab might be a bit of a mess) Oh also I had to remove the darkness pref since the darkness is doing a lot of the heavy lifting now. I'm sorry. Edit: NEW FOV SPRITES! Thanks dongle your aviator glasses will guide us to a better future. https://github.com/tgstation/tgstation/assets/58055496/afa9eeb8-8b7b-4364-b0c0-7ac8070b5609 https://github.com/tgstation/tgstation/assets/58055496/0eff040c-8bf1-47e4-a4f3-dac56fb2ccc8 ## Commits I Care About [Implements something like fov, but without the planes as layers hell](a604c7b1c8) Rather then masking out mobs standing behind us, we use a combo color matrix and blur filter to make the stuff covered by fov harder to see. We achive this by splitting the game plane into two, masking both by fov (one normally and one inversely), and then applying effects to one of the two. I want to make the fov fullscreens more gradient, but as an effect this is a good start [Removes WALL_PLANE_UPPER by adding a WALL_PLANE overlay to material walls (init cost comes here)](2548933739) @Mothblocks see this. comment in commit explains further but uh, we need to draw material walls to the light mask plane so things actually can be seen on them, but we can't do that and also have them be big, so they get an overlay. Sorry, slight init time bump, about 0.5 seconds. I can kill it with wallening. [Moves SEETHROUGH_PLANE above ABOVE_GAME_PLANE](beec4c00e0) I don't think it actually wants to draw here @Time-Green I think this was you so pinging for opinion [Resprites FOV masks to be clean (and more consistent)](f02ad13696) [f02ad13](f02ad13696) This is 100% donglesplonge's work, he's spent a week or so going back and forth with me sharpening these to a mirror shine, real chill ## Why It's Good For The Game Walls are closing in ## Changelog 🆑 LemonInTheDark, Donglesplonge image: Redoes fov "mask" sprites. They're clean, have a very pleasant dithering effect, and look real fuckin good! del: Changed FOV, it no longer hides mobs, instead it blurs the hidden area, and makes it a bit darker/oversaturated /🆑 ###### * It's technically possible if we start using render targets to create 2 sets of sources but that's insane and we aren't doing it
1169 lines
47 KiB
Plaintext
1169 lines
47 KiB
Plaintext
/obj/item/banhammer
|
|
desc = "A banhammer."
|
|
name = "banhammer"
|
|
icon = 'icons/obj/weapons/hammer.dmi'
|
|
icon_state = "toyhammer"
|
|
slot_flags = ITEM_SLOT_BELT
|
|
throwforce = 0
|
|
force = 1
|
|
w_class = WEIGHT_CLASS_TINY
|
|
throw_speed = 3
|
|
throw_range = 7
|
|
attack_verb_continuous = list("bans")
|
|
attack_verb_simple = list("ban")
|
|
max_integrity = 200
|
|
armor_type = /datum/armor/item_banhammer
|
|
resistance_flags = FIRE_PROOF
|
|
|
|
/datum/armor/item_banhammer
|
|
fire = 100
|
|
acid = 70
|
|
|
|
/obj/item/banhammer/Initialize(mapload)
|
|
. = ..()
|
|
AddElement(/datum/element/kneejerk)
|
|
|
|
/obj/item/banhammer/suicide_act(mob/living/user)
|
|
user.visible_message(span_suicide("[user] is hitting [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to ban [user.p_them()]self from life."))
|
|
return (BRUTELOSS|FIRELOSS|TOXLOSS|OXYLOSS)
|
|
/*
|
|
oranges says: This is a meme relating to the english translation of the ss13 russian wiki page on lurkmore.
|
|
mrdoombringer sez: and remember kids, if you try and PR a fix for this item's grammar, you are admitting that you are, indeed, a newfriend.
|
|
for further reading, please see: https://github.com/tgstation/tgstation/pull/30173 and https://translate.google.com/translate?sl=auto&tl=en&js=y&prev=_t&hl=en&ie=UTF-8&u=%2F%2Flurkmore.to%2FSS13&edit-text=&act=url
|
|
*/
|
|
/obj/item/banhammer/attack(mob/M, mob/living/user)
|
|
if(user.zone_selected == BODY_ZONE_HEAD)
|
|
M.visible_message(span_danger("[user] are stroking the head of [M] with a bangammer."), span_userdanger("[user] are stroking your head with a bangammer."), span_hear("You hear a bangammer stroking a head.")) // see above comment
|
|
else
|
|
M.visible_message(span_danger("[M] has been banned FOR NO REISIN by [user]!"), span_userdanger("You have been banned FOR NO REISIN by [user]!"), span_hear("You hear a banhammer banning someone."))
|
|
playsound(loc, 'sound/effects/adminhelp.ogg', 15) //keep it at 15% volume so people don't jump out of their skin too much
|
|
if(user.combat_mode)
|
|
return ..(M, user)
|
|
|
|
/obj/item/sord
|
|
name = "\improper SORD"
|
|
desc = "This thing is so unspeakably shitty you are having a hard time even holding it."
|
|
icon = 'icons/obj/weapons/sword.dmi'
|
|
icon_state = "sord"
|
|
inhand_icon_state = "sord"
|
|
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
|
|
slot_flags = ITEM_SLOT_BELT
|
|
force = 2
|
|
throwforce = 1
|
|
w_class = WEIGHT_CLASS_NORMAL
|
|
hitsound = 'sound/weapons/bladeslice.ogg'
|
|
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")
|
|
|
|
/obj/item/sord/suicide_act(mob/living/user)
|
|
user.visible_message(span_suicide("[user] is trying to impale [user.p_them()]self with [src]! It might be a suicide attempt if it weren't so shitty."), \
|
|
span_suicide("You try to impale yourself with [src], but it's USELESS..."))
|
|
return SHAME
|
|
|
|
/obj/item/claymore
|
|
name = "claymore"
|
|
desc = "What are you standing around staring at this for? Get to killing!"
|
|
icon = 'icons/obj/weapons/sword.dmi'
|
|
icon_state = "claymore"
|
|
inhand_icon_state = "claymore"
|
|
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
|
|
hitsound = 'sound/weapons/bladeslice.ogg'
|
|
obj_flags = CONDUCTS_ELECTRICITY
|
|
slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_BACK
|
|
force = 40
|
|
throwforce = 10
|
|
w_class = WEIGHT_CLASS_NORMAL
|
|
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")
|
|
block_chance = 50
|
|
block_sound = 'sound/weapons/parry.ogg'
|
|
sharpness = SHARP_EDGED
|
|
max_integrity = 200
|
|
armor_type = /datum/armor/item_claymore
|
|
resistance_flags = FIRE_PROOF
|
|
|
|
/datum/armor/item_claymore
|
|
fire = 100
|
|
acid = 50
|
|
|
|
/obj/item/claymore/Initialize(mapload)
|
|
. = ..()
|
|
AddComponent(/datum/component/butchering, \
|
|
speed = 4 SECONDS, \
|
|
effectiveness = 105, \
|
|
)
|
|
|
|
/obj/item/claymore/suicide_act(mob/living/user)
|
|
user.visible_message(span_suicide("[user] is falling on [src]! It looks like [user.p_theyre()] trying to commit suicide!"))
|
|
return BRUTELOSS
|
|
|
|
/obj/item/claymore/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE)
|
|
if(attack_type == PROJECTILE_ATTACK || attack_type == LEAP_ATTACK)
|
|
final_block_chance = 0 //Don't bring a sword to a gunfight, and also you aren't going to really block someone full body tackling you with a sword
|
|
return ..()
|
|
|
|
//statistically similar to e-cutlasses
|
|
/obj/item/claymore/cutlass
|
|
name = "cutlass"
|
|
desc = "A piratey sword used by buckaneers to \"negotiate\" the transfer of treasure."
|
|
icon_state = "cutlass"
|
|
inhand_icon_state = "cutlass"
|
|
worn_icon_state = "cutlass"
|
|
slot_flags = ITEM_SLOT_BACK
|
|
force = 30
|
|
throwforce = 20
|
|
throw_speed = 3
|
|
throw_range = 5
|
|
armour_penetration = 35
|
|
|
|
/obj/item/claymore/carrot
|
|
name = "carrot sword"
|
|
desc = "A full-sized carrot sword. Definitely \not\ good for the eyes, not anymore."
|
|
icon_state = "carrot_sword"
|
|
inhand_icon_state = "carrot_sword"
|
|
worn_icon_state = "carrot_sword"
|
|
flags_1 = NONE
|
|
force = 19
|
|
throwforce = 7
|
|
throw_speed = 3
|
|
throw_range = 7
|
|
armour_penetration = 5
|
|
block_chance = 10
|
|
resistance_flags = NONE
|
|
|
|
/obj/item/claymore/highlander //ALL COMMENTS MADE REGARDING THIS SWORD MUST BE MADE IN ALL CAPS
|
|
desc = "<b><i>THERE CAN BE ONLY ONE, AND IT WILL BE YOU!!!</i></b>\nActivate it in your hand to point to the nearest victim."
|
|
obj_flags = CONDUCTS_ELECTRICITY
|
|
item_flags = DROPDEL //WOW BRO YOU LOST AN ARM, GUESS WHAT YOU DONT GET YOUR SWORD ANYMORE //I CANT BELIEVE SPOOKYDONUT WOULD BREAK THE REQUIREMENTS
|
|
slot_flags = null
|
|
block_chance = 0 //RNG WON'T HELP YOU NOW, PANSY
|
|
light_range = 3
|
|
attack_verb_continuous = list("brutalizes", "eviscerates", "disembowels", "hacks", "carves", "cleaves") //ONLY THE MOST VISCERAL ATTACK VERBS
|
|
attack_verb_simple = list("brutalize", "eviscerate", "disembowel", "hack", "carve", "cleave")
|
|
var/notches = 0 //HOW MANY PEOPLE HAVE BEEN SLAIN WITH THIS BLADE
|
|
var/obj/item/disk/nuclear/nuke_disk //OUR STORED NUKE DISK
|
|
|
|
/obj/item/claymore/highlander/Initialize(mapload)
|
|
. = ..()
|
|
ADD_TRAIT(src, TRAIT_NODROP, HIGHLANDER_TRAIT)
|
|
START_PROCESSING(SSobj, src)
|
|
|
|
/obj/item/claymore/highlander/Destroy()
|
|
if(nuke_disk)
|
|
nuke_disk.forceMove(get_turf(src))
|
|
nuke_disk.visible_message(span_warning("The nuke disk is vulnerable!"))
|
|
nuke_disk = null
|
|
STOP_PROCESSING(SSobj, src)
|
|
return ..()
|
|
|
|
/obj/item/claymore/highlander/process()
|
|
if(ishuman(loc))
|
|
var/mob/living/carbon/human/holder = loc
|
|
layer = ABOVE_ALL_MOB_LAYER //NO HIDING BEHIND PLANTS FOR YOU, DICKWEED (HA GET IT, BECAUSE WEEDS ARE PLANTS)
|
|
ADD_TRAIT(holder, TRAIT_NOBLOOD, HIGHLANDER_TRAIT) //AND WE WON'T BLEED OUT LIKE COWARDS
|
|
else
|
|
if(!(flags_1 & ADMIN_SPAWNED_1))
|
|
qdel(src)
|
|
|
|
|
|
/obj/item/claymore/highlander/pickup(mob/living/user)
|
|
. = ..()
|
|
to_chat(user, span_notice("The power of Scotland protects you! You are shielded from all stuns and knockdowns."))
|
|
user.ignore_slowdown(HIGHLANDER_TRAIT)
|
|
user.add_stun_absorption(
|
|
source = HIGHLANDER_TRAIT,
|
|
message = span_warning("%EFFECT_OWNER is protected by the power of Scotland!"),
|
|
self_message = span_boldwarning("The power of Scotland absorbs the stun!"),
|
|
examine_message = span_warning("%EFFECT_OWNER_THEYRE protected by the power of Scotland!"),
|
|
)
|
|
|
|
/obj/item/claymore/highlander/dropped(mob/living/user)
|
|
. = ..()
|
|
user.unignore_slowdown(HIGHLANDER_TRAIT)
|
|
user.remove_stun_absorption(HIGHLANDER_TRAIT)
|
|
|
|
/obj/item/claymore/highlander/examine(mob/user)
|
|
. = ..()
|
|
. += "It has [!notches ? "nothing" : "[notches] notches"] scratched into the blade."
|
|
if(nuke_disk)
|
|
. += span_boldwarning("It's holding the nuke disk!")
|
|
|
|
/obj/item/claymore/highlander/attack(mob/living/target, mob/living/user)
|
|
. = ..()
|
|
if(!QDELETED(target) && target.stat == DEAD && target.mind?.has_antag_datum(/datum/antagonist/highlander))
|
|
user.fully_heal() //STEAL THE LIFE OF OUR FALLEN FOES
|
|
add_notch(user)
|
|
target.visible_message(span_warning("[target] crumbles to dust beneath [user]'s blows!"), span_userdanger("As you fall, your body crumbles to dust!"))
|
|
target.investigate_log("has been dusted by a highlander claymore.", INVESTIGATE_DEATHS)
|
|
target.dust()
|
|
|
|
/obj/item/claymore/highlander/attack_self(mob/living/user)
|
|
var/closest_victim
|
|
var/closest_distance = 255
|
|
for(var/mob/living/carbon/human/scot in GLOB.player_list - user)
|
|
if(scot.mind?.has_antag_datum(/datum/antagonist/highlander) && (!closest_victim || get_dist(user, closest_victim) < closest_distance))
|
|
closest_victim = scot
|
|
for(var/mob/living/silicon/robot/siliscot in GLOB.player_list - user)
|
|
if(siliscot.mind?.has_antag_datum(/datum/antagonist/highlander) && (!closest_victim || get_dist(user, closest_victim) < closest_distance))
|
|
closest_victim = siliscot
|
|
|
|
if(!closest_victim)
|
|
to_chat(user, span_warning("[src] thrums for a moment and falls dark. Perhaps there's nobody nearby."))
|
|
return
|
|
to_chat(user, span_danger("[src] thrums and points to the [dir2text(get_dir(user, closest_victim))]."))
|
|
|
|
/obj/item/claymore/highlander/IsReflect()
|
|
return 1 //YOU THINK YOUR PUNY LASERS CAN STOP ME?
|
|
|
|
/obj/item/claymore/highlander/proc/add_notch(mob/living/user) //DYNAMIC CLAYMORE PROGRESSION SYSTEM - THIS IS THE FUTURE
|
|
notches++
|
|
force++
|
|
var/new_name = name
|
|
switch(notches)
|
|
if(1)
|
|
to_chat(user, span_notice("Your first kill - hopefully one of many. You scratch a notch into [src]'s blade."))
|
|
to_chat(user, span_warning("You feel your fallen foe's soul entering your blade, restoring your wounds!"))
|
|
new_name = "notched claymore"
|
|
if(2)
|
|
to_chat(user, span_notice("Another falls before you. Another soul fuses with your own. Another notch in the blade."))
|
|
new_name = "double-notched claymore"
|
|
add_atom_colour(rgb(255, 235, 235), ADMIN_COLOUR_PRIORITY)
|
|
if(3)
|
|
to_chat(user, span_notice("You're beginning to</span> <span class='danger'><b>relish</b> the <b>thrill</b> of <b>battle.</b>"))
|
|
new_name = "triple-notched claymore"
|
|
add_atom_colour(rgb(255, 215, 215), ADMIN_COLOUR_PRIORITY)
|
|
if(4)
|
|
to_chat(user, span_notice("You've lost count of</span> <span class='boldannounce'>how many you've killed."))
|
|
new_name = "many-notched claymore"
|
|
add_atom_colour(rgb(255, 195, 195), ADMIN_COLOUR_PRIORITY)
|
|
if(5)
|
|
to_chat(user, span_boldannounce("Five voices now echo in your mind, cheering the slaughter."))
|
|
new_name = "battle-tested claymore"
|
|
add_atom_colour(rgb(255, 175, 175), ADMIN_COLOUR_PRIORITY)
|
|
if(6)
|
|
to_chat(user, span_boldannounce("Is this what the vikings felt like? Visions of glory fill your head as you slay your sixth foe."))
|
|
new_name = "battle-scarred claymore"
|
|
add_atom_colour(rgb(255, 155, 155), ADMIN_COLOUR_PRIORITY)
|
|
if(7)
|
|
to_chat(user, span_boldannounce("Kill. Butcher. <i>Conquer.</i>"))
|
|
new_name = "vicious claymore"
|
|
add_atom_colour(rgb(255, 135, 135), ADMIN_COLOUR_PRIORITY)
|
|
if(8)
|
|
to_chat(user, span_userdanger("IT NEVER GETS OLD. THE <i>SCREAMING</i>. THE <i>BLOOD</i> AS IT <i>SPRAYS</i> ACROSS YOUR <i>FACE.</i>"))
|
|
new_name = "bloodthirsty claymore"
|
|
add_atom_colour(rgb(255, 115, 115), ADMIN_COLOUR_PRIORITY)
|
|
if(9)
|
|
to_chat(user, span_userdanger("ANOTHER ONE FALLS TO YOUR BLOWS. ANOTHER WEAKLING UNFIT TO LIVE."))
|
|
new_name = "gore-stained claymore"
|
|
add_atom_colour(rgb(255, 95, 95), ADMIN_COLOUR_PRIORITY)
|
|
if(10)
|
|
user.visible_message(span_warning("[user]'s eyes light up with a vengeful fire!"), \
|
|
span_userdanger("YOU FEEL THE POWER OF VALHALLA FLOWING THROUGH YOU! <i>THERE CAN BE ONLY ONE!!!</i>"))
|
|
new_name = "GORE-DRENCHED CLAYMORE OF [pick("THE WHIMSICAL SLAUGHTER", "A THOUSAND SLAUGHTERED CATTLE", "GLORY AND VALHALLA", "ANNIHILATION", "OBLITERATION")]"
|
|
icon_state = "claymore_gold"
|
|
inhand_icon_state = "cultblade"
|
|
lefthand_file = 'icons/mob/inhands/64x64_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/64x64_righthand.dmi'
|
|
remove_atom_colour(ADMIN_COLOUR_PRIORITY)
|
|
user.update_held_items()
|
|
|
|
name = new_name
|
|
playsound(user, 'sound/items/screwdriver2.ogg', 50, TRUE)
|
|
|
|
/obj/item/claymore/highlander/robot //BLOODTHIRSTY BORGS NOW COME IN PLAID
|
|
icon = 'icons/obj/items_cyborg.dmi'
|
|
icon_state = "claymore_cyborg"
|
|
var/mob/living/silicon/robot/robot
|
|
|
|
/obj/item/claymore/highlander/robot/Initialize(mapload)
|
|
var/obj/item/robot_model/kiltkit = loc
|
|
robot = kiltkit.loc
|
|
. = ..()
|
|
if(!istype(robot))
|
|
return INITIALIZE_HINT_QDEL
|
|
|
|
/obj/item/claymore/highlander/robot/process()
|
|
layer = ABOVE_ALL_MOB_LAYER
|
|
|
|
/obj/item/katana
|
|
name = "katana"
|
|
desc = "Woefully underpowered in D20."
|
|
icon = 'icons/obj/weapons/sword.dmi'
|
|
icon_state = "katana"
|
|
inhand_icon_state = "katana"
|
|
worn_icon_state = "katana"
|
|
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
|
|
obj_flags = CONDUCTS_ELECTRICITY
|
|
slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_BACK
|
|
force = 40
|
|
throwforce = 10
|
|
w_class = WEIGHT_CLASS_HUGE
|
|
hitsound = 'sound/weapons/bladeslice.ogg'
|
|
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")
|
|
block_chance = 50
|
|
block_sound = 'sound/weapons/parry.ogg'
|
|
sharpness = SHARP_EDGED
|
|
max_integrity = 200
|
|
armor_type = /datum/armor/item_katana
|
|
resistance_flags = FIRE_PROOF
|
|
|
|
/datum/armor/item_katana
|
|
fire = 100
|
|
acid = 50
|
|
|
|
/obj/item/katana/suicide_act(mob/living/user)
|
|
user.visible_message(span_suicide("[user] is slitting [user.p_their()] stomach open with [src]! It looks like [user.p_theyre()] trying to commit seppuku!"))
|
|
return BRUTELOSS
|
|
|
|
/obj/item/katana/cursed //used by wizard events, see the tendril_loot.dm file for the miner one
|
|
slot_flags = null
|
|
|
|
/obj/item/throwing_star
|
|
name = "throwing star"
|
|
desc = "An ancient weapon still used to this day, due to its ease of lodging itself into its victim's body parts."
|
|
icon = 'icons/obj/weapons/thrown.dmi'
|
|
icon_state = "throwingstar"
|
|
inhand_icon_state = "eshield"
|
|
lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi'
|
|
force = 2
|
|
throwforce = 10 //10 + 2 (WEIGHT_CLASS_SMALL) * 4 (EMBEDDED_IMPACT_PAIN_MULTIPLIER) = 18 damage on hit due to guaranteed embedding
|
|
throw_speed = 4
|
|
embedding = list("pain_mult" = 4, "embed_chance" = 100, "fall_chance" = 0)
|
|
armour_penetration = 40
|
|
|
|
w_class = WEIGHT_CLASS_SMALL
|
|
sharpness = SHARP_POINTY
|
|
custom_materials = list(/datum/material/iron= SMALL_MATERIAL_AMOUNT * 5, /datum/material/glass= SMALL_MATERIAL_AMOUNT * 5)
|
|
resistance_flags = FIRE_PROOF
|
|
|
|
/obj/item/throwing_star/stamina
|
|
name = "shock throwing star"
|
|
desc = "An aerodynamic disc designed to cause excruciating pain when stuck inside fleeing targets, hopefully without causing fatal harm."
|
|
throwforce = 5
|
|
embedding = list("pain_chance" = 5, "embed_chance" = 100, "fall_chance" = 0, "jostle_chance" = 10, "pain_stam_pct" = 0.8, "jostle_pain_mult" = 3)
|
|
|
|
/obj/item/throwing_star/toy
|
|
name = "toy throwing star"
|
|
desc = "An aerodynamic disc strapped with adhesive for sticking to people, good for playing pranks and getting yourself killed by security."
|
|
sharpness = NONE
|
|
force = 0
|
|
throwforce = 0
|
|
embedding = list("pain_mult" = 0, "jostle_pain_mult" = 0, "embed_chance" = 100, "fall_chance" = 0)
|
|
|
|
/obj/item/switchblade
|
|
name = "switchblade"
|
|
icon = 'icons/obj/weapons/sword.dmi'
|
|
icon_state = "switchblade"
|
|
base_icon_state = "switchblade"
|
|
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
|
|
desc = "A sharp, concealable, spring-loaded knife."
|
|
obj_flags = CONDUCTS_ELECTRICITY
|
|
force = 3
|
|
w_class = WEIGHT_CLASS_SMALL
|
|
throwforce = 5
|
|
throw_speed = 3
|
|
throw_range = 6
|
|
custom_materials = list(/datum/material/iron= SHEET_MATERIAL_AMOUNT * 6)
|
|
hitsound = 'sound/weapons/genhit.ogg'
|
|
attack_verb_continuous = list("stubs", "pokes")
|
|
attack_verb_simple = list("stub", "poke")
|
|
resistance_flags = FIRE_PROOF
|
|
/// Whether the switchblade starts extended or not.
|
|
var/start_extended = FALSE
|
|
|
|
/obj/item/switchblade/get_all_tool_behaviours()
|
|
return list(TOOL_KNIFE)
|
|
|
|
/obj/item/switchblade/Initialize(mapload)
|
|
. = ..()
|
|
AddElement(/datum/element/update_icon_updates_onmob)
|
|
AddComponent(/datum/component/butchering, \
|
|
speed = 7 SECONDS, \
|
|
effectiveness = 100, \
|
|
)
|
|
|
|
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"), \
|
|
)
|
|
|
|
RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, PROC_REF(on_transform))
|
|
|
|
/obj/item/switchblade/proc/on_transform(obj/item/source, mob/user, active)
|
|
SIGNAL_HANDLER
|
|
|
|
tool_behaviour = (active ? TOOL_KNIFE : NONE)
|
|
|
|
/obj/item/switchblade/suicide_act(mob/living/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
|
|
start_extended = TRUE
|
|
|
|
/obj/item/phone
|
|
name = "red phone"
|
|
desc = "Should anything ever go wrong..."
|
|
icon = 'icons/obj/devices/voice.dmi'
|
|
icon_state = "red_phone"
|
|
force = 3
|
|
throwforce = 2
|
|
throw_speed = 3
|
|
throw_range = 4
|
|
w_class = WEIGHT_CLASS_SMALL
|
|
attack_verb_continuous = list("calls", "rings")
|
|
attack_verb_simple = list("call", "ring")
|
|
hitsound = 'sound/weapons/ring.ogg'
|
|
|
|
/obj/item/phone/suicide_act(mob/living/user)
|
|
if(locate(/obj/structure/chair/stool) in user.loc)
|
|
user.visible_message(span_suicide("[user] begins to tie a noose with [src]'s cord! It looks like [user.p_theyre()] trying to commit suicide!"))
|
|
else
|
|
user.visible_message(span_suicide("[user] is strangling [user.p_them()]self with [src]'s cord! It looks like [user.p_theyre()] trying to commit suicide!"))
|
|
return OXYLOSS
|
|
|
|
/obj/item/cane
|
|
name = "cane"
|
|
desc = "A cane used by a true gentleman. Or a clown."
|
|
icon = 'icons/obj/weapons/staff.dmi'
|
|
icon_state = "cane"
|
|
inhand_icon_state = "stick"
|
|
lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
|
|
force = 5
|
|
throwforce = 5
|
|
w_class = WEIGHT_CLASS_SMALL
|
|
custom_materials = list(/datum/material/iron= SMALL_MATERIAL_AMOUNT * 0.5)
|
|
attack_verb_continuous = list("bludgeons", "whacks", "disciplines", "thrashes")
|
|
attack_verb_simple = list("bludgeon", "whack", "discipline", "thrash")
|
|
|
|
/obj/item/cane/white
|
|
name = "white cane"
|
|
desc = "A cane traditionally used by the blind to help them see. Folds down to be easier to transport."
|
|
icon_state = "cane_white"
|
|
inhand_icon_state = "cane_white"
|
|
lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
|
|
force = 1
|
|
w_class = WEIGHT_CLASS_SMALL
|
|
custom_materials = list(/datum/material/iron = SMALL_MATERIAL_AMOUNT * 6)
|
|
|
|
/obj/item/cane/white/Initialize(mapload)
|
|
. = ..()
|
|
AddComponent( \
|
|
/datum/component/transforming, \
|
|
force_on = 7, \
|
|
hitsound_on = hitsound, \
|
|
w_class_on = WEIGHT_CLASS_BULKY, \
|
|
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_REF(on_transform))
|
|
ADD_TRAIT(src, TRAIT_BLIND_TOOL, INNATE_TRAIT)
|
|
|
|
/*
|
|
* Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM].
|
|
*
|
|
* Gives feedback to the user and makes it show up inhand.
|
|
*/
|
|
/obj/item/cane/white/proc/on_transform(obj/item/source, mob/user, active)
|
|
SIGNAL_HANDLER
|
|
|
|
if(user)
|
|
balloon_alert(user, active ? "extended" : "collapsed")
|
|
playsound(src, 'sound/weapons/batonextend.ogg', 50, TRUE)
|
|
return COMPONENT_NO_DEFAULT_MESSAGE
|
|
|
|
/obj/item/staff
|
|
name = "wizard staff"
|
|
desc = "Apparently a staff used by the wizard."
|
|
icon = 'icons/obj/weapons/guns/magic.dmi'
|
|
icon_state = "staff"
|
|
inhand_icon_state = "staff"
|
|
lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi'
|
|
force = 3
|
|
throwforce = 5
|
|
throw_speed = 2
|
|
throw_range = 5
|
|
w_class = WEIGHT_CLASS_SMALL
|
|
armour_penetration = 100
|
|
attack_verb_continuous = list("bludgeons", "whacks", "disciplines")
|
|
attack_verb_simple = list("bludgeon", "whack", "discipline")
|
|
resistance_flags = FLAMMABLE
|
|
|
|
/obj/item/staff/broom
|
|
name = "broom"
|
|
desc = "Used for sweeping, and flying into the night while cackling. Black cat not included."
|
|
icon_state = "broom"
|
|
inhand_icon_state = "broom"
|
|
resistance_flags = FLAMMABLE
|
|
|
|
/obj/item/staff/tape
|
|
name = "tape staff"
|
|
desc = "A roll of tape snugly attached to a stick."
|
|
icon_state = "tapestaff"
|
|
inhand_icon_state = "tapestaff"
|
|
resistance_flags = FLAMMABLE
|
|
|
|
/obj/item/staff/stick
|
|
name = "stick"
|
|
desc = "A great tool to drag someone else's drinks across the bar."
|
|
icon = 'icons/obj/weapons/staff.dmi'
|
|
icon_state = "cane"
|
|
inhand_icon_state = "stick"
|
|
lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
|
|
force = 3
|
|
throwforce = 5
|
|
throw_speed = 2
|
|
throw_range = 5
|
|
w_class = WEIGHT_CLASS_SMALL
|
|
|
|
/obj/item/ectoplasm
|
|
name = "ectoplasm"
|
|
desc = "Spooky."
|
|
gender = PLURAL
|
|
icon = 'icons/effects/magic.dmi'
|
|
icon_state = "ectoplasm"
|
|
grind_results = list(/datum/reagent/hauntium = 25) //can be ground into hauntium
|
|
|
|
/obj/item/ectoplasm/suicide_act(mob/living/user)
|
|
user.visible_message(span_suicide("[user] is inhaling [src]! It looks like [user.p_theyre()] trying to visit the astral plane!"))
|
|
return OXYLOSS
|
|
|
|
/obj/item/ectoplasm/angelic
|
|
icon = 'icons/effects/magic.dmi'
|
|
icon_state = "angelplasm"
|
|
|
|
/obj/item/ectoplasm/mystic
|
|
icon_state = "mysticplasm"
|
|
|
|
/obj/item/statuebust
|
|
name = "bust"
|
|
desc = "A priceless ancient marble bust, the kind that belongs in a museum." //or you can hit people with it
|
|
icon = 'icons/obj/art/statue.dmi'
|
|
icon_state = "bust"
|
|
force = 15
|
|
throwforce = 10
|
|
throw_speed = 5
|
|
throw_range = 2
|
|
attack_verb_continuous = list("busts")
|
|
attack_verb_simple = list("bust")
|
|
var/impressiveness = 45
|
|
|
|
/obj/item/statuebust/Initialize(mapload)
|
|
. = ..()
|
|
AddElement(/datum/element/art, impressiveness)
|
|
AddElement(/datum/element/beauty, 1000)
|
|
|
|
/obj/item/statuebust/hippocratic
|
|
name = "hippocrates bust"
|
|
desc = "A bust of the famous Greek physician Hippocrates of Kos, often referred to as the father of western medicine."
|
|
icon_state = "hippocratic"
|
|
impressiveness = 50
|
|
// If it hits the prob(reference_chance) chance, this is set to TRUE. Adds medical HUD when wielded, but has a 10% slower attack speed and is too bloody to make an oath with.
|
|
var/reference = FALSE
|
|
// Chance for above.
|
|
var/reference_chance = 1
|
|
// Minimum time inbetween oaths.
|
|
COOLDOWN_DECLARE(oath_cd)
|
|
|
|
/obj/item/statuebust/hippocratic/evil
|
|
reference_chance = 100
|
|
|
|
/obj/item/statuebust/hippocratic/Initialize(mapload)
|
|
. = ..()
|
|
if(prob(reference_chance))
|
|
name = "Solemn Vow"
|
|
desc = "Art lovers will cherish the bust of Hippocrates, commemorating a time when medics still thought doing no harm was a good idea."
|
|
attack_speed = CLICK_CD_SLOW
|
|
reference = TRUE
|
|
|
|
/obj/item/statuebust/hippocratic/examine(mob/user)
|
|
. = ..()
|
|
if(reference)
|
|
. += span_notice("You could activate the bust in-hand to swear or forswear a Hippocratic Oath... but it seems like somebody decided it was more of a Hippocratic Suggestion. This thing is caked with bits of blood and gore.")
|
|
return
|
|
. += span_notice("You can activate the bust in-hand to swear or forswear a Hippocratic Oath! This has no effects except pacifism or bragging rights. Does not remove other sources of pacifism. Do not eat.")
|
|
|
|
/obj/item/statuebust/hippocratic/equipped(mob/living/carbon/human/user, slot)
|
|
..()
|
|
if(!(slot & ITEM_SLOT_HANDS))
|
|
return
|
|
var/datum/atom_hud/our_hud = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
|
|
our_hud.show_to(user)
|
|
ADD_TRAIT(user, TRAIT_MEDICAL_HUD, type)
|
|
|
|
/obj/item/statuebust/hippocratic/dropped(mob/living/carbon/human/user)
|
|
..()
|
|
if(HAS_TRAIT_NOT_FROM(user, TRAIT_MEDICAL_HUD, type))
|
|
return
|
|
var/datum/atom_hud/our_hud = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
|
|
our_hud.hide_from(user)
|
|
REMOVE_TRAIT(user, TRAIT_MEDICAL_HUD, type)
|
|
|
|
/obj/item/statuebust/hippocratic/attack_self(mob/user)
|
|
if(!iscarbon(user))
|
|
to_chat(user, span_warning("You remember how the Hippocratic Oath specifies 'my fellow human beings' and realize that it's completely meaningless to you."))
|
|
return
|
|
|
|
if(reference)
|
|
to_chat(user, span_warning("As you prepare yourself to swear the Oath, you realize that doing so on a blood-caked bust is probably not a good idea."))
|
|
return
|
|
|
|
if(!COOLDOWN_FINISHED(src, oath_cd))
|
|
to_chat(user, span_warning("You've sworn or forsworn an oath too recently to undo your decisions. The bust looks at you with disgust."))
|
|
return
|
|
|
|
COOLDOWN_START(src, oath_cd, 5 MINUTES)
|
|
|
|
if(HAS_TRAIT_FROM(user, TRAIT_PACIFISM, type))
|
|
to_chat(user, span_warning("You've already sworn a vow. You start preparing to rescind it..."))
|
|
if(do_after(user, 5 SECONDS, target = user))
|
|
user.say("Yeah this Hippopotamus thing isn't working out. I quit!", forced = "hippocratic hippocrisy")
|
|
REMOVE_TRAIT(user, TRAIT_PACIFISM, type)
|
|
|
|
// they can still do it for rp purposes
|
|
if(HAS_TRAIT_NOT_FROM(user, TRAIT_PACIFISM, type))
|
|
to_chat(user, span_warning("You already don't want to harm people, this isn't going to do anything!"))
|
|
|
|
|
|
to_chat(user, span_notice("You remind yourself of the Hippocratic Oath's contents and prepare to swear yourself to it..."))
|
|
if(do_after(user, 4 SECONDS, target = user))
|
|
user.say("I swear to fulfill, to the best of my ability and judgment, this covenant:", forced = "hippocratic oath")
|
|
else
|
|
return fuck_it_up(user)
|
|
if(do_after(user, 2 SECONDS, target = user))
|
|
user.say("I will apply, for the benefit of the sick, all measures that are required, avoiding those twin traps of overtreatment and therapeutic nihilism.", forced = "hippocratic oath")
|
|
else
|
|
return fuck_it_up(user)
|
|
if(do_after(user, 3 SECONDS, target = user))
|
|
user.say("I will remember that I remain a member of society, with special obligations to all my fellow human beings, those sound of mind and body as well as the infirm.", forced = "hippocratic oath")
|
|
else
|
|
|
|
return fuck_it_up(user)
|
|
if(do_after(user, 3 SECONDS, target = user))
|
|
user.say("If I do not violate this oath, may I enjoy life and art, respected while I live and remembered with affection thereafter. May I always act so as to preserve the finest traditions of my calling and may I long experience the joy of healing those who seek my help.", forced = "hippocratic oath")
|
|
else
|
|
return fuck_it_up(user)
|
|
|
|
to_chat(user, span_notice("Contentment, understanding, and purpose washes over you as you finish the oath. You consider for a second the concept of harm and shudder."))
|
|
ADD_TRAIT(user, TRAIT_PACIFISM, type)
|
|
|
|
// Bully the guy for fucking up.
|
|
/obj/item/statuebust/hippocratic/proc/fuck_it_up(mob/living/carbon/user)
|
|
to_chat(user, span_warning("You forget what comes next like a dumbass. The Hippocrates bust looks down on you, disappointed."))
|
|
user.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2)
|
|
COOLDOWN_RESET(src, oath_cd)
|
|
|
|
/obj/item/tailclub
|
|
name = "tail club"
|
|
desc = "For the beating to death of lizards with their own tails."
|
|
icon = 'icons/obj/weapons/club.dmi'
|
|
icon_state = "tailclub"
|
|
force = 14
|
|
throwforce = 1 // why are you throwing a club do you even weapon
|
|
throw_speed = 1
|
|
throw_range = 1
|
|
attack_verb_continuous = list("clubs", "bludgeons")
|
|
attack_verb_simple = list("club", "bludgeon")
|
|
|
|
/obj/item/melee/chainofcommand/tailwhip
|
|
name = "liz o' nine tails"
|
|
desc = "A whip fashioned from the severed tails of lizards."
|
|
icon_state = "tailwhip"
|
|
inhand_icon_state = "tailwhip"
|
|
item_flags = NONE
|
|
|
|
/obj/item/melee/chainofcommand/tailwhip/kitty
|
|
name = "cat o' nine tails"
|
|
desc = "A whip fashioned from the severed tails of cats."
|
|
icon_state = "catwhip"
|
|
inhand_icon_state = "catwhip"
|
|
|
|
/obj/item/melee/skateboard
|
|
name = "skateboard"
|
|
desc = "A skateboard. It can be placed on its wheels and ridden, or used as a radical weapon."
|
|
icon = 'icons/obj/vehicles.dmi'
|
|
icon_state = "skateboard_held"
|
|
inhand_icon_state = "skateboard"
|
|
force = 12
|
|
throwforce = 4
|
|
w_class = WEIGHT_CLASS_NORMAL
|
|
attack_verb_continuous = list("smacks", "whacks", "slams", "smashes")
|
|
attack_verb_simple = list("smack", "whack", "slam", "smash")
|
|
///The vehicle counterpart for the board
|
|
var/board_item_type = /obj/vehicle/ridden/scooter/skateboard
|
|
|
|
/obj/item/melee/skateboard/attack_self(mob/user)
|
|
var/obj/vehicle/ridden/scooter/skateboard/S = new board_item_type(get_turf(user))//this probably has fucky interactions with telekinesis but for the record it wasn't my fault
|
|
S.buckle_mob(user)
|
|
qdel(src)
|
|
|
|
/obj/item/melee/skateboard/improvised
|
|
name = "improvised skateboard"
|
|
desc = "A jury-rigged skateboard. It can be placed on its wheels and ridden, or used as a radical weapon."
|
|
board_item_type = /obj/vehicle/ridden/scooter/skateboard/improvised
|
|
|
|
/obj/item/melee/skateboard/pro
|
|
name = "skateboard"
|
|
desc = "An EightO brand professional skateboard. It looks sturdy and well made."
|
|
icon_state = "skateboard2_held"
|
|
inhand_icon_state = "skateboard2"
|
|
board_item_type = /obj/vehicle/ridden/scooter/skateboard/pro
|
|
custom_premium_price = PAYCHECK_COMMAND * 5
|
|
|
|
/obj/item/melee/skateboard/hoverboard
|
|
name = "hoverboard"
|
|
desc = "A blast from the past, so retro!"
|
|
icon_state = "hoverboard_red_held"
|
|
inhand_icon_state = "hoverboard_red"
|
|
board_item_type = /obj/vehicle/ridden/scooter/skateboard/hoverboard
|
|
custom_premium_price = PAYCHECK_COMMAND * 5.4 //If I can't make it a meme I'll make it RAD
|
|
|
|
/obj/item/melee/skateboard/hoverboard/admin
|
|
name = "Board Of Directors"
|
|
desc = "The engineering complexity of a spaceship concentrated inside of a board. Just as expensive, too."
|
|
icon_state = "hoverboard_nt_held"
|
|
inhand_icon_state = "hoverboard_nt"
|
|
board_item_type = /obj/vehicle/ridden/scooter/skateboard/hoverboard/admin
|
|
|
|
/obj/item/melee/baseball_bat
|
|
name = "baseball bat"
|
|
desc = "There ain't a skull in the league that can withstand a swatter."
|
|
icon = 'icons/obj/weapons/bat.dmi'
|
|
icon_state = "baseball_bat"
|
|
inhand_icon_state = "baseball_bat"
|
|
lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
|
|
force = 12
|
|
wound_bonus = -10
|
|
throwforce = 12
|
|
demolition_mod = 1.25
|
|
attack_verb_continuous = list("beats", "smacks")
|
|
attack_verb_simple = list("beat", "smack")
|
|
custom_materials = list(/datum/material/wood = SHEET_MATERIAL_AMOUNT * 3.5)
|
|
resistance_flags = FLAMMABLE
|
|
w_class = WEIGHT_CLASS_HUGE
|
|
/// Are we able to do a homerun?
|
|
var/homerun_able = FALSE
|
|
/// Are we ready to do a homerun?
|
|
var/homerun_ready = FALSE
|
|
/// Can we launch mobs thrown at us away?
|
|
var/mob_thrower = FALSE
|
|
/// List of all thrown datums we sent.
|
|
var/list/thrown_datums = list()
|
|
|
|
/obj/item/melee/baseball_bat/Initialize(mapload)
|
|
. = ..()
|
|
if(prob(1))
|
|
name = "cricket bat"
|
|
icon_state = "baseball_bat_brit"
|
|
inhand_icon_state = "baseball_bat_brit"
|
|
desc = pick("You've got red on you.", "You gotta know what a crumpet is to understand cricket.")
|
|
|
|
AddElement(/datum/element/kneecapping)
|
|
|
|
/obj/item/melee/baseball_bat/attack_self(mob/user)
|
|
if(!homerun_able)
|
|
return ..()
|
|
if(homerun_ready)
|
|
to_chat(user, span_warning("You're already ready to do a home run!"))
|
|
return ..()
|
|
to_chat(user, span_warning("You begin gathering strength..."))
|
|
playsound(get_turf(src), 'sound/magic/lightning_chargeup.ogg', 65, TRUE)
|
|
if(do_after(user, 9 SECONDS, target = src))
|
|
to_chat(user, span_userdanger("You gather power! Time for a home run!"))
|
|
homerun_ready = TRUE
|
|
return ..()
|
|
|
|
/obj/item/melee/baseball_bat/attack(mob/living/target, mob/living/user)
|
|
// we obtain the relative direction from the bat itself to the target
|
|
var/relative_direction = get_cardinal_dir(src, target)
|
|
var/atom/throw_target = get_edge_target_turf(target, relative_direction)
|
|
. = ..()
|
|
if(HAS_TRAIT(user, TRAIT_PACIFISM))
|
|
return
|
|
if(homerun_ready)
|
|
user.visible_message(span_userdanger("It's a home run!"))
|
|
if(!QDELETED(target))
|
|
target.throw_at(throw_target, rand(8,10), 14, user)
|
|
SSexplosions.medturf += throw_target
|
|
playsound(get_turf(src), 'sound/weapons/homerun.ogg', 100, TRUE)
|
|
homerun_ready = FALSE
|
|
return
|
|
else if(!QDELETED(target) && !target.anchored)
|
|
var/whack_speed = (prob(60) ? 1 : 4)
|
|
target.throw_at(throw_target, rand(1, 2), whack_speed, user, gentle = TRUE) // sorry friends, 7 speed batting caused wounds to absolutely delete whoever you knocked your target into (and said target)
|
|
|
|
/obj/item/melee/baseball_bat/Destroy(force)
|
|
for(var/target in thrown_datums)
|
|
var/datum/thrownthing/throw_datum = thrown_datums[target]
|
|
throw_datum.callback.Invoke()
|
|
thrown_datums.Cut()
|
|
return ..()
|
|
|
|
/obj/item/melee/baseball_bat/pre_attack(atom/movable/target, mob/living/user, params)
|
|
var/turf/target_turf = get_turf(target)
|
|
if(!target_turf)
|
|
return ..()
|
|
for(var/atom/movable/atom as anything in target_turf)
|
|
if(!try_launch(atom, user))
|
|
continue
|
|
return TRUE
|
|
return ..()
|
|
|
|
/obj/item/melee/baseball_bat/proc/try_launch(atom/movable/target, mob/living/user)
|
|
if(!target.throwing || (ismob(target) && !mob_thrower))
|
|
return FALSE
|
|
var/datum/thrownthing/throw_datum = target.throwing
|
|
var/datum_throw_speed = throw_datum.speed
|
|
var/angle = 0
|
|
var/target_to_user = get_dir(target, user)
|
|
if(target.dir & turn(target_to_user, 90))
|
|
angle = 270
|
|
if(target.dir & turn(target_to_user, 270))
|
|
angle = 90
|
|
if(target.dir & REVERSE_DIR(target_to_user))
|
|
angle = 180
|
|
if(target.dir & target_to_user)
|
|
angle = 360
|
|
var/turf/return_to_sender = get_ranged_target_turf_direct(user, throw_datum.starting_turf, round(target.throw_range * 1.5, 1), offset = angle + (rand(-1, 1) * 10))
|
|
throw_datum.finalize(hit = FALSE)
|
|
target.mouse_opacity = MOUSE_OPACITY_TRANSPARENT //dont mess with our ball
|
|
target.color = list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,3) //make them super light
|
|
animate(target, 0.5 SECONDS, color = null, flags = ANIMATION_PARALLEL)
|
|
user.color = list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,3)
|
|
animate(user, 0.5 SECONDS, color = null, flags = ANIMATION_PARALLEL)
|
|
playsound(src, 'sound/items/baseballhit.ogg', 100, TRUE)
|
|
user.do_attack_animation(target, used_item = src)
|
|
ADD_TRAIT(user, TRAIT_IMMOBILIZED, type)
|
|
addtimer(CALLBACK(src, PROC_REF(launch_back), target, user, return_to_sender, datum_throw_speed), 0.5 SECONDS)
|
|
return TRUE
|
|
|
|
/obj/item/melee/baseball_bat/proc/launch_back(atom/movable/target, mob/living/user, turf/target_turf, datum_throw_speed)
|
|
playsound(target, 'sound/magic/tail_swing.ogg', 50, TRUE)
|
|
REMOVE_TRAIT(user, TRAIT_IMMOBILIZED, type)
|
|
target.mouse_opacity = initial(target.mouse_opacity)
|
|
target.add_filter("baseball_launch", 3, motion_blur_filter(1, 3))
|
|
target.throwforce *= 2
|
|
target.throw_at(target_turf, get_dist(target, target_turf), datum_throw_speed + 1, user, callback = CALLBACK(src, PROC_REF(on_hit), target))
|
|
thrown_datums[target] = target.throwing
|
|
|
|
/obj/item/melee/baseball_bat/proc/on_hit(atom/movable/target)
|
|
target.remove_filter("baseball_launch")
|
|
target.throwforce *= 0.5
|
|
thrown_datums -= target
|
|
|
|
/obj/item/melee/baseball_bat/homerun
|
|
name = "home run bat"
|
|
desc = "This thing looks dangerous... Dangerously good at baseball, that is."
|
|
icon_state = "baseball_bat_home"
|
|
inhand_icon_state = "baseball_bat_home"
|
|
homerun_able = TRUE
|
|
mob_thrower = TRUE
|
|
|
|
/obj/item/melee/baseball_bat/ablative
|
|
name = "metal baseball bat"
|
|
desc = "This bat is made of highly reflective, highly armored material."
|
|
icon_state = "baseball_bat_metal"
|
|
inhand_icon_state = "baseball_bat_metal"
|
|
custom_materials = list(/datum/material/titanium = SHEET_MATERIAL_AMOUNT * 3.5)
|
|
resistance_flags = NONE
|
|
force = 20
|
|
throwforce = 20
|
|
mob_thrower = TRUE
|
|
block_sound = 'sound/weapons/effects/batreflect.ogg'
|
|
|
|
/obj/item/melee/baseball_bat/ablative/IsReflect()//some day this will reflect thrown items instead of lasers
|
|
return TRUE
|
|
|
|
/obj/item/melee/flyswatter
|
|
name = "flyswatter"
|
|
desc = "Useful for killing pests of all sizes."
|
|
icon = 'icons/obj/service/hydroponics/equipment.dmi'
|
|
icon_state = "flyswatter"
|
|
inhand_icon_state = "flyswatter"
|
|
lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
|
|
force = 1
|
|
throwforce = 1
|
|
attack_verb_continuous = list("swats", "smacks")
|
|
attack_verb_simple = list("swat", "smack")
|
|
hitsound = 'sound/effects/snap.ogg'
|
|
w_class = WEIGHT_CLASS_SMALL
|
|
/// Things in this list will be instantly splatted. Flyman weakness is handled in the flyman species weakness proc.
|
|
var/list/splattable
|
|
/// Things in this list which take a lot more damage from the fly swatter, but not be necessarily killed by it.
|
|
var/list/strong_against
|
|
/// How much extra damage the fly swatter does against mobs it is strong against
|
|
var/extra_strength_damage = 24
|
|
|
|
/obj/item/melee/flyswatter/Initialize(mapload)
|
|
. = ..()
|
|
splattable = typecacheof(list(
|
|
/mob/living/basic/ant,
|
|
/mob/living/basic/butterfly,
|
|
/mob/living/basic/cockroach,
|
|
/mob/living/basic/spider/growing/spiderling,
|
|
/mob/living/basic/bee,
|
|
/obj/effect/decal/cleanable/ants,
|
|
/obj/item/queen_bee,
|
|
))
|
|
strong_against = typecacheof(list(
|
|
/mob/living/basic/spider/giant,
|
|
))
|
|
|
|
|
|
/obj/item/melee/flyswatter/afterattack(atom/target, mob/user, proximity_flag)
|
|
. = ..()
|
|
if(!proximity_flag || HAS_TRAIT(user, TRAIT_PACIFISM))
|
|
return
|
|
|
|
if(is_type_in_typecache(target, splattable))
|
|
new /obj/effect/decal/cleanable/insectguts(target.drop_location())
|
|
to_chat(user, span_warning("You easily splat [target]."))
|
|
if(isliving(target))
|
|
var/mob/living/bug = target
|
|
bug.investigate_log("has been splatted by a flyswatter.", INVESTIGATE_DEATHS)
|
|
bug.gib(DROP_ALL_REMAINS)
|
|
else
|
|
qdel(target)
|
|
return
|
|
if(is_type_in_typecache(target, strong_against) && isliving(target))
|
|
var/mob/living/living_target = target
|
|
living_target.adjustBruteLoss(extra_strength_damage)
|
|
|
|
/obj/item/proc/can_trigger_gun(mob/living/user, akimbo_usage)
|
|
if(!user.can_use_guns(src))
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/obj/item/extendohand
|
|
name = "extendo-hand"
|
|
desc = "Futuristic tech has allowed these classic spring-boxing toys to essentially act as a fully functional hand-operated hand prosthetic."
|
|
icon = 'icons/obj/toys/toy.dmi'
|
|
icon_state = "extendohand"
|
|
inhand_icon_state = "extendohand"
|
|
lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
|
|
force = 0
|
|
throwforce = 5
|
|
reach = 2
|
|
var/min_reach = 2
|
|
|
|
/obj/item/extendohand/acme
|
|
name = "\improper ACME Extendo-Hand"
|
|
desc = "A novelty extendo-hand produced by the ACME corporation. Originally designed to knock out roadrunners."
|
|
|
|
/obj/item/extendohand/attack(atom/M, mob/living/carbon/human/user, params)
|
|
var/dist = get_dist(M, user)
|
|
if(dist < min_reach)
|
|
to_chat(user, span_warning("[M] is too close to use [src] on."))
|
|
return
|
|
var/list/modifiers = params2list(params)
|
|
M.attack_hand(user, modifiers)
|
|
|
|
/obj/item/gohei
|
|
name = "gohei"
|
|
desc = "A wooden stick with white streamers at the end. Originally used by shrine maidens to purify things. Now used by the station's valued weeaboos."
|
|
resistance_flags = FLAMMABLE
|
|
force = 5
|
|
throwforce = 5
|
|
hitsound = SFX_SWING_HIT
|
|
attack_verb_continuous = list("whacks", "thwacks", "wallops", "socks")
|
|
attack_verb_simple = list("whack", "thwack", "wallop", "sock")
|
|
icon = 'icons/obj/weapons/club.dmi'
|
|
icon_state = "gohei"
|
|
inhand_icon_state = "gohei"
|
|
lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi'
|
|
|
|
/obj/item/melee/moonlight_greatsword
|
|
name = "moonlight greatsword"
|
|
desc = "Don't tell anyone you put any points into dex, though."
|
|
icon = 'icons/obj/weapons/sword.dmi'
|
|
icon_state = "swordon"
|
|
inhand_icon_state = "swordon"
|
|
worn_icon_state = "swordon"
|
|
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
|
|
w_class = WEIGHT_CLASS_BULKY
|
|
slot_flags = ITEM_SLOT_BACK|ITEM_SLOT_BELT
|
|
block_chance = 20
|
|
block_sound = 'sound/weapons/parry.ogg'
|
|
sharpness = SHARP_EDGED
|
|
force = 14
|
|
throwforce = 12
|
|
hitsound = 'sound/weapons/bladeslice.ogg'
|
|
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")
|
|
|
|
//High Frequency Blade
|
|
|
|
/obj/item/highfrequencyblade
|
|
name = "high frequency blade"
|
|
desc = "A sword reinforced by a powerful alternating current and resonating at extremely high vibration frequencies. \
|
|
This oscillation weakens the molecular bonds of anything it cuts, thereby increasing its cutting ability."
|
|
icon = 'icons/obj/weapons/sword.dmi'
|
|
icon_state = "hfrequency0"
|
|
worn_icon_state = "hfrequency0"
|
|
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
|
|
force = 10
|
|
wound_bonus = 25
|
|
bare_wound_bonus = 50
|
|
throwforce = 25
|
|
throw_speed = 4
|
|
attack_speed = CLICK_CD_HYPER_RAPID
|
|
embedding = list("embed_chance" = 100)
|
|
block_chance = 25
|
|
block_sound = 'sound/weapons/parry.ogg'
|
|
sharpness = SHARP_EDGED
|
|
w_class = WEIGHT_CLASS_BULKY
|
|
slot_flags = ITEM_SLOT_BACK
|
|
/// The color of the slash we create
|
|
var/slash_color = COLOR_BLUE
|
|
/// Previous x position of where we clicked on the target's icon
|
|
var/previous_x
|
|
/// Previous y position of where we clicked on the target's icon
|
|
var/previous_y
|
|
/// The previous target we attacked
|
|
var/datum/weakref/previous_target
|
|
|
|
/obj/item/highfrequencyblade/Initialize(mapload)
|
|
. = ..()
|
|
AddComponent(/datum/component/two_handed, \
|
|
wield_callback = CALLBACK(src, PROC_REF(on_wield)), \
|
|
unwield_callback = CALLBACK(src, PROC_REF(on_unwield)), \
|
|
)
|
|
AddElement(/datum/element/update_icon_updates_onmob)
|
|
|
|
/obj/item/highfrequencyblade/update_icon_state()
|
|
icon_state = "hfrequency[HAS_TRAIT(src, TRAIT_WIELDED)]"
|
|
return ..()
|
|
|
|
/obj/item/highfrequencyblade/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE)
|
|
if(attack_type == PROJECTILE_ATTACK)
|
|
if(HAS_TRAIT(src, TRAIT_WIELDED) || prob(final_block_chance))
|
|
owner.visible_message(span_danger("[owner] deflects [attack_text] with [src]!"))
|
|
playsound(src, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 75, TRUE)
|
|
return TRUE
|
|
return FALSE
|
|
if(prob(final_block_chance * (HAS_TRAIT(src, TRAIT_WIELDED) ? 2 : 1)))
|
|
owner.visible_message(span_danger("[owner] parries [attack_text] with [src]!"))
|
|
return TRUE
|
|
|
|
/obj/item/highfrequencyblade/attack(mob/living/target, mob/living/user, params)
|
|
if(!HAS_TRAIT(src, TRAIT_WIELDED) || HAS_TRAIT(src, TRAIT_PACIFISM))
|
|
return ..()
|
|
slash(target, user, params)
|
|
|
|
/obj/item/highfrequencyblade/attack_atom(atom/target, mob/living/user, params)
|
|
if(HAS_TRAIT(src, TRAIT_WIELDED))
|
|
return
|
|
return ..()
|
|
|
|
/obj/item/highfrequencyblade/afterattack(atom/target, mob/user, proximity_flag, params)
|
|
if(!HAS_TRAIT(src, TRAIT_WIELDED))
|
|
return ..()
|
|
if(!proximity_flag || !(isclosedturf(target) || isitem(target) || ismachinery(target) || isstructure(target) || isvehicle(target)))
|
|
return
|
|
slash(target, user, params)
|
|
return AFTERATTACK_PROCESSED_ITEM
|
|
|
|
/// triggered on wield of two handed item
|
|
/obj/item/highfrequencyblade/proc/on_wield(obj/item/source, mob/user)
|
|
update_icon(UPDATE_ICON_STATE)
|
|
|
|
/// triggered on unwield of two handed item
|
|
/obj/item/highfrequencyblade/proc/on_unwield(obj/item/source, mob/user)
|
|
update_icon(UPDATE_ICON_STATE)
|
|
|
|
/obj/item/highfrequencyblade/proc/slash(atom/target, mob/living/user, params)
|
|
user.do_attack_animation(target, "nothing")
|
|
var/list/modifiers = params2list(params)
|
|
var/damage_mod = 1
|
|
var/x_slashed = text2num(modifiers[ICON_X]) || world.icon_size/2 //in case we arent called by a client
|
|
var/y_slashed = text2num(modifiers[ICON_Y]) || world.icon_size/2 //in case we arent called by a client
|
|
new /obj/effect/temp_visual/slash(get_turf(target), target, x_slashed, y_slashed, slash_color)
|
|
if(target == previous_target?.resolve()) //if the same target, we calculate a damage multiplier if you swing your mouse around
|
|
var/x_mod = previous_x - x_slashed
|
|
var/y_mod = previous_y - y_slashed
|
|
damage_mod = max(1, round((sqrt(x_mod ** 2 + y_mod ** 2) / 10), 0.1))
|
|
previous_target = WEAKREF(target)
|
|
previous_x = x_slashed
|
|
previous_y = y_slashed
|
|
playsound(src, 'sound/weapons/bladeslice.ogg', 100, vary = TRUE)
|
|
playsound(src, 'sound/weapons/zapbang.ogg', 50, vary = TRUE)
|
|
if(isliving(target))
|
|
var/mob/living/living_target = target
|
|
living_target.apply_damage(force*damage_mod, BRUTE, sharpness = SHARP_EDGED, wound_bonus = wound_bonus, bare_wound_bonus = bare_wound_bonus, def_zone = user.zone_selected)
|
|
log_combat(user, living_target, "slashed", src)
|
|
if(living_target.stat == DEAD && prob(force*damage_mod*0.5))
|
|
living_target.visible_message(span_danger("[living_target] explodes in a shower of gore!"), blind_message = span_hear("You hear organic matter ripping and tearing!"))
|
|
living_target.investigate_log("has been gibbed by [src].", INVESTIGATE_DEATHS)
|
|
living_target.gib(DROP_ALL_REMAINS)
|
|
log_combat(user, living_target, "gibbed", src)
|
|
else if(target.uses_integrity)
|
|
target.take_damage(force*damage_mod*3, BRUTE, MELEE, FALSE, null, 50)
|
|
else if(iswallturf(target) && prob(force*damage_mod*0.5))
|
|
var/turf/closed/wall/wall_target = target
|
|
wall_target.dismantle_wall()
|
|
else if(ismineralturf(target) && prob(force*damage_mod))
|
|
var/turf/closed/mineral/mineral_target = target
|
|
mineral_target.gets_drilled()
|
|
|
|
/obj/effect/temp_visual/slash
|
|
icon_state = "highfreq_slash"
|
|
alpha = 150
|
|
duration = 0.5 SECONDS
|
|
layer = ABOVE_ALL_MOB_LAYER
|
|
plane = ABOVE_GAME_PLANE
|
|
|
|
/obj/effect/temp_visual/slash/Initialize(mapload, atom/target, x_slashed, y_slashed, slash_color)
|
|
. = ..()
|
|
if(!target)
|
|
return
|
|
var/matrix/new_transform = matrix()
|
|
new_transform.Turn(rand(1, 360)) // Random slash angle
|
|
var/datum/decompose_matrix/decomp = target.transform.decompose()
|
|
new_transform.Translate((x_slashed - world.icon_size/2) * decomp.scale_x, (y_slashed - world.icon_size/2) * decomp.scale_y) // Move to where we clicked
|
|
//Follow target's transform while ignoring scaling
|
|
new_transform.Turn(decomp.rotation)
|
|
new_transform.Translate(decomp.shift_x, decomp.shift_y)
|
|
new_transform.Translate(target.pixel_x, target.pixel_y) // Follow target's pixel offsets
|
|
transform = new_transform
|
|
//Double the scale of the matrix by doubling the 2x2 part without touching the translation part
|
|
var/matrix/scaled_transform = new_transform + matrix(new_transform.a, new_transform.b, 0, new_transform.d, new_transform.e, 0)
|
|
animate(src, duration*0.5, color = slash_color, transform = scaled_transform, alpha = 255)
|
|
|
|
/obj/item/highfrequencyblade/wizard
|
|
desc = "A blade that was mastercrafted by a legendary blacksmith. Its' enchantments let it slash through anything."
|
|
force = 8
|
|
throwforce = 20
|
|
wound_bonus = 20
|
|
bare_wound_bonus = 25
|
|
|
|
/obj/item/highfrequencyblade/wizard/attack_self(mob/user, modifiers)
|
|
if(!HAS_MIND_TRAIT(user, TRAIT_MAGICALLY_GIFTED))
|
|
balloon_alert(user, "you're too weak!")
|
|
return
|
|
return ..()
|