Merge branch 'master' into plumb

This commit is contained in:
lolman360
2020-08-09 22:48:18 +10:00
committed by GitHub
1405 changed files with 39348 additions and 21867 deletions
+11 -1
View File
@@ -9,7 +9,7 @@
var/buckle_prevents_pull = FALSE
//Interaction
/atom/movable/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
/atom/movable/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
@@ -145,3 +145,13 @@
var/mob/living/L = M.pulledby
L.set_pull_offsets(M, L.grab_state)
return M
/atom/movable/proc/precise_user_unbuckle_mob(mob/user)
if(!buckled_mobs)
return
else if(length(buckled_mobs) == 1)
return user_unbuckle_mob(buckled_mobs[1], user)
else
var/unbuckled = input(user, "Who do you wish to unbuckle?","Unbuckle Who?") as null|mob in buckled_mobs
return user_unbuckle_mob(unbuckled, user)
+45 -29
View File
@@ -8,7 +8,7 @@
anchored = TRUE
light_range = 3
var/movechance = 70
var/obj/item/assembly/signaler/anomaly/aSignal
var/obj/item/assembly/signaler/anomaly/aSignal = /obj/item/assembly/signaler/anomaly
var/area/impact_area
var/lifespan = 990
@@ -23,8 +23,10 @@
START_PROCESSING(SSobj, src)
impact_area = get_area(src)
aSignal = new(src)
aSignal.name = "[name] core"
if (!impact_area)
return INITIALIZE_HINT_QDEL
aSignal = new aSignal(src)
aSignal.code = rand(1,100)
aSignal.anomaly_type = type
@@ -75,7 +77,7 @@
/obj/effect/anomaly/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/analyzer))
if(I.tool_behaviour == TOOL_ANALYZER) //revert if runtimed
to_chat(user, "<span class='notice'>Analyzing... [src]'s unstable field is fluctuating along frequency [format_frequency(aSignal.frequency)], code [aSignal.code].</span>")
///////////////////////
@@ -85,6 +87,7 @@
icon_state = "shield2"
density = FALSE
var/boing = 0
aSignal = /obj/item/assembly/signaler/anomaly/grav
/obj/effect/anomaly/grav/anomalyEffect()
..()
@@ -95,17 +98,23 @@
for(var/mob/living/M in range(0, src))
gravShock(M)
for(var/mob/living/M in orange(4, src))
step_towards(M,src)
if(!M.mob_negates_gravity()) //delete when runtimed
step_towards(M,src)
for(var/obj/O in range(0,src))
if(!O.anchored)
//if(isturf(O.loc))
// var/turf/T = O.loc
// if(T.intact && HAS_TRAIT(O, TRAIT_T_RAY_VISIBLE))
// continue
var/mob/living/target = locate() in view(4,src)
if(target && !target.stat)
O.throw_at(target, 5, 10)
/obj/effect/anomaly/grav/Crossed(mob/A)
gravShock(A)
/obj/effect/anomaly/grav/Crossed(atom/movable/AM)
. = ..()
gravShock(AM)
/obj/effect/anomaly/grav/Bump(mob/A)
/obj/effect/anomaly/grav/Bump(atom/A)
gravShock(A)
/obj/effect/anomaly/grav/Bumped(atom/movable/AM)
@@ -138,6 +147,7 @@
name = "flux wave anomaly"
icon_state = "electricity2"
density = TRUE
aSignal = /obj/item/assembly/signaler/anomaly/flux
var/canshock = FALSE
var/shockdamage = 20
var/explosive = TRUE
@@ -148,11 +158,12 @@
for(var/mob/living/M in range(0, src))
mobShock(M)
/obj/effect/anomaly/flux/Crossed(mob/living/M)
mobShock(M)
/obj/effect/anomaly/flux/Crossed(atom/movable/AM)
. = ..()
mobShock(AM)
/obj/effect/anomaly/flux/Bump(mob/living/M)
mobShock(M)
/obj/effect/anomaly/flux/Bump(atom/A)
mobShock(A)
/obj/effect/anomaly/flux/Bumped(atom/movable/AM)
mobShock(AM)
@@ -160,7 +171,7 @@
/obj/effect/anomaly/flux/proc/mobShock(mob/living/M)
if(canshock && istype(M))
canshock = FALSE //Just so you don't instakill yourself if you slam into the anomaly five times in a second.
M.electrocute_act(shockdamage, "[name]", flags = SHOCK_NOGLOVES)
M.electrocute_act(shockdamage, name, flags = SHOCK_NOGLOVES)
/obj/effect/anomaly/flux/detonate()
if(explosive)
@@ -176,6 +187,7 @@
icon = 'icons/obj/projectiles.dmi'
icon_state = "bluespace"
density = TRUE
aSignal = /obj/item/assembly/signaler/anomaly/bluespace
/obj/effect/anomaly/bluespace/anomalyEffect()
..()
@@ -187,7 +199,7 @@
do_teleport(AM, locate(AM.x, AM.y, AM.z), 8, channel = TELEPORT_CHANNEL_BLUESPACE)
/obj/effect/anomaly/bluespace/detonate()
var/turf/T = safepick(get_area_turfs(impact_area))
var/turf/T = pick(get_area_turfs(impact_area))
if(T)
// Calculate new position (searches through beacons in world)
var/obj/item/beacon/chosen
@@ -224,21 +236,23 @@
if(!A.Move(newloc) && newloc) // if the atom, for some reason, can't move, FORCE them to move! :) We try Move() first to invoke any movement-related checks the atom needs to perform after moving
A.forceMove(newloc)
spawn()
if(ismob(A) && !(A in flashers)) // don't flash if we're already doing an effect
var/mob/M = A
if(M.client)
var/obj/blueeffect = new /obj(src)
blueeffect.screen_loc = "WEST,SOUTH to EAST,NORTH"
blueeffect.icon = 'icons/effects/effects.dmi'
blueeffect.icon_state = "shieldsparkles"
blueeffect.layer = FLASH_LAYER
blueeffect.plane = FULLSCREEN_PLANE
blueeffect.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
M.client.screen += blueeffect
sleep(20)
M.client.screen -= blueeffect
qdel(blueeffect)
if(ismob(A) && !(A in flashers)) // don't flash if we're already doing an effect
var/mob/M = A
if(M.client)
INVOKE_ASYNC(src, .proc/blue_effect, M)
/obj/effect/anomaly/bluespace/proc/blue_effect(mob/M)
var/obj/blueeffect = new /obj(src)
blueeffect.screen_loc = "WEST,SOUTH to EAST,NORTH"
blueeffect.icon = 'icons/effects/effects.dmi'
blueeffect.icon_state = "shieldsparkles"
blueeffect.layer = FLASH_LAYER
blueeffect.plane = FULLSCREEN_PLANE
blueeffect.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
M.client.screen += blueeffect
sleep(20)
M.client.screen -= blueeffect
qdel(blueeffect)
/////////////////////
@@ -246,6 +260,7 @@
name = "pyroclastic anomaly"
icon_state = "mustard"
var/ticks = 0
aSignal = /obj/item/assembly/signaler/anomaly/pyro
/obj/effect/anomaly/pyro/anomalyEffect()
..()
@@ -278,6 +293,7 @@
name = "vortex anomaly"
icon_state = "bhole3"
desc = "That's a nice station you have there. It'd be a shame if something happened to it."
aSignal = /obj/item/assembly/signaler/anomaly/vortex
/obj/effect/anomaly/bhole/anomalyEffect()
..()
+1 -4
View File
@@ -101,10 +101,7 @@
to_chat(user, "<span class='notice'>You carefully remove the poster from the wall.</span>")
roll_and_drop(user.loc)
/obj/structure/sign/poster/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
/obj/structure/sign/poster/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(ruined)
return
visible_message("[user] rips [src] in a single, decisive motion!" )
@@ -137,10 +137,7 @@
random_icon_states = list("vomit_1", "vomit_2", "vomit_3", "vomit_4")
beauty = -150
/obj/effect/decal/cleanable/vomit/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
/obj/effect/decal/cleanable/vomit/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(ishuman(user))
var/mob/living/carbon/human/H = user
if(isflyperson(H))
@@ -268,6 +268,8 @@
gender = PLURAL
max_integrity = 20
CanAtmosPass = ATMOS_PASS_DENSITY
attack_hand_speed = CLICK_CD_MELEE
attack_hand_is_action = TRUE
/obj/structure/foamedmetal/Initialize()
. = ..()
@@ -284,11 +286,7 @@
/obj/structure/foamedmetal/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
playsound(src.loc, 'sound/weapons/tap.ogg', 100, 1)
/obj/structure/foamedmetal/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
user.changeNext_move(CLICK_CD_MELEE)
/obj/structure/foamedmetal/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
user.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
to_chat(user, "<span class='warning'>You hit [src] but bounce off it!</span>")
playsound(src.loc, 'sound/weapons/tap.ogg', 100, 1)
+10 -17
View File
@@ -1,10 +1,10 @@
/proc/create_portal_pair(turf/source, turf/destination, _creator = null, _lifespan = 300, accuracy = 0, newtype = /obj/effect/portal, atmos_link_override)
/proc/create_portal_pair(turf/source, turf/destination, _lifespan = 300, accuracy = 0, newtype = /obj/effect/portal, atmos_link_override)
if(!istype(source) || !istype(destination))
return
var/turf/actual_destination = get_teleport_turf(destination, accuracy)
var/obj/effect/portal/P1 = new newtype(source, _creator, _lifespan, null, FALSE, null, atmos_link_override)
var/obj/effect/portal/P2 = new newtype(actual_destination, _creator, _lifespan, P1, TRUE, null, atmos_link_override)
var/obj/effect/portal/P1 = new newtype(source, _lifespan, null, FALSE, null, atmos_link_override)
var/obj/effect/portal/P2 = new newtype(actual_destination, _lifespan, P1, TRUE, null, atmos_link_override)
if(!istype(P1)||!istype(P2))
return
P1.link_portal(P2)
@@ -21,7 +21,6 @@
var/obj/effect/portal/linked
var/hardlinked = TRUE //Requires a linked portal at all times. Destroy if there's no linked portal, if there is destroy it when this one is deleted.
var/teleport_channel = TELEPORT_CHANNEL_BLUESPACE
var/creator
var/turf/hard_target //For when a portal needs a hard target and isn't to be linked.
var/atmos_link = FALSE //Link source/destination atmos.
var/turf/open/atmos_source //Atmos link source
@@ -35,6 +34,7 @@
name = "wormhole"
icon = 'icons/obj/objects.dmi'
icon_state = "anom"
layer = RIPPLE_LAYER
mech_sized = TRUE
teleport_channel = TELEPORT_CHANNEL_WORMHOLE
@@ -49,7 +49,9 @@
user.forceMove(get_turf(src))
return TRUE
/obj/effect/portal/Crossed(atom/movable/AM, oldloc)
/obj/effect/portal/Crossed(atom/movable/AM, oldloc, force_stop = 0)
if(force_stop)
return ..()
if(isobserver(AM))
return ..()
if(linked && (get_turf(oldloc) == get_turf(linked)))
@@ -60,16 +62,13 @@
/obj/effect/portal/attack_tk(mob/user)
return
/obj/effect/portal/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
/obj/effect/portal/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(get_turf(user) == get_turf(src))
teleport(user)
if(Adjacent(user))
user.forceMove(get_turf(src))
/obj/effect/portal/Initialize(mapload, _creator, _lifespan = 0, obj/effect/portal/_linked, automatic_link = FALSE, turf/hard_target_override, atmos_link_override)
/obj/effect/portal/Initialize(mapload, _lifespan = 0, obj/effect/portal/_linked, automatic_link = FALSE, turf/hard_target_override, atmos_link_override)
. = ..()
GLOB.portals += src
if(!istype(_linked) && automatic_link)
@@ -81,7 +80,6 @@
atmos_link = atmos_link_override
link_portal(_linked)
hardlinked = automatic_link
creator = _creator
if(isturf(hard_target_override))
hard_target = hard_target_override
@@ -132,10 +130,7 @@
LAZYREMOVE(atmos_destination.atmos_adjacent_turfs, atmos_source)
atmos_destination = null
/obj/effect/portal/Destroy() //Calls on_portal_destroy(destroyed portal, location of destroyed portal) on creator if creator has such call.
if(creator && hascall(creator, "on_portal_destroy"))
call(creator, "on_portal_destroy")(src, src.loc)
creator = null
/obj/effect/portal/Destroy()
GLOB.portals -= src
unlink_atmos()
if(hardlinked && !QDELETED(linked))
@@ -156,8 +151,6 @@
return FALSE
if(!force && (!ismecha(M) && !istype(M, /obj/item/projectile) && M.anchored && !allow_anchored))
return
if(ismegafauna(M))
message_admins("[M] has used a portal at [ADMIN_VERBOSEJMP(src)] made by [usr].")
var/no_effect = FALSE
if(last_effect == world.time)
no_effect = TRUE
@@ -380,8 +380,6 @@
name = "random keg spawner"
lootcount = 1
loot = list(/obj/structure/reagent_dispensers/keg/mead = 5,
/obj/structure/reagent_dispensers/keg/aphro = 2,
/obj/structure/reagent_dispensers/keg/aphro/strong = 2,
/obj/structure/reagent_dispensers/keg/gargle = 1)
/obj/effect/spawner/lootdrop/coin
+3 -6
View File
@@ -120,6 +120,8 @@
var/poison_type = "toxin"
var/poison_per_bite = 5
var/list/faction = list("spiders")
attack_hand_speed = CLICK_CD_MELEE
attack_hand_is_action = TRUE
/obj/structure/spider/spiderling/Destroy()
new/obj/item/reagent_containers/food/snacks/spiderling(get_turf(src))
@@ -153,10 +155,9 @@
else
..()
/obj/structure/spider/spiderling/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/structure/spider/spiderling/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(user.a_intent != INTENT_HELP)
user.changeNext_move(CLICK_CD_MELEE)
user.do_attack_animation(src)
user.visible_message("<span class='warning'>[user] splats [src].</span>", "<span class='warning'>You splat [src].</span>", "<span class='italics'>You hear a splat...</span>")
playsound(loc, 'sound/effects/snap.ogg', 25)
@@ -253,8 +254,6 @@
/obj/structure/spider/cocoon/container_resist(mob/living/user)
var/breakout_time = 600
user.changeNext_move(CLICK_CD_BREAKOUT)
user.last_special = world.time + CLICK_CD_BREAKOUT
to_chat(user, "<span class='notice'>You struggle against the tight bonds... (This will take about [DisplayTimeText(breakout_time)].)</span>")
visible_message("You see something struggling and writhing in \the [src]!")
if(do_after(user,(breakout_time), target = src))
@@ -262,8 +261,6 @@
return
qdel(src)
/obj/structure/spider/cocoon/Destroy()
var/turf/T = get_turf(src)
src.visible_message("<span class='warning'>\The [src] splits open.</span>")
+11 -18
View File
@@ -11,6 +11,10 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
name = "item"
icon = 'icons/obj/items_and_weapons.dmi'
blocks_emissive = EMISSIVE_BLOCK_GENERIC
attack_hand_speed = 0
attack_hand_is_action = FALSE
attack_hand_unwieldlyness = 0
///icon state name for inhand overlays
var/item_state = null
@@ -58,15 +62,6 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
/// How long, in deciseconds, this staggers for, if null it will autocalculate from w_class and force. Unlike total mass this supports 0 and negatives.
var/stagger_force
/**
* Set FALSE and then checked at the end of on mob/living/attackby(), set TRUE on living/pre_attacked_by().
* Should it be FALSE by the end of the item/attack(), that means the item overrode the standard attack behaviour
* and the user still needs the delay applied. We can't be using return values since that'll stop afterattack() from being triggered.
*/
var/attack_delay_done = FALSE
///next_move click/attack delay of this item.
var/click_delay = CLICK_CD_MELEE
var/slot_flags = 0 //This is used to determine on which slots an item can fit.
var/current_equipped_slot
pass_flags = PASSTABLE
@@ -108,12 +103,12 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
mouse_drag_pointer = MOUSE_ACTIVE_POINTER //the icon to indicate this object is being dragged
var/list/embedding = NONE
var/list/embedding
var/flags_cover = 0 //for flags such as GLASSESCOVERSEYES
var/heat = 0
///All items with sharpness of IS_SHARP or higher will automatically get the butchering component.
var/sharpness = IS_BLUNT
///All items with sharpness of SHARP_EDGED or higher will automatically get the butchering component.
var/sharpness = SHARP_NONE
var/tool_behaviour = NONE
var/toolspeed = 1
@@ -211,7 +206,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
if(GLOB.rpg_loot_items)
AddComponent(/datum/component/fantasy)
if(sharpness) //give sharp objects butchering functionality, for consistency
if(sharpness && force > 5) //give sharp objects butchering functionality, for consistency
AddComponent(/datum/component/butchering, 80 * toolspeed)
/obj/item/proc/check_allowed_items(atom/target, not_inside, target_self)
@@ -313,10 +308,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
add_fingerprint(usr)
return ..()
/obj/item/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
/obj/item/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(!user)
return
if(anchored)
@@ -473,6 +465,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
usr.UnarmedAttack(src, TRUE)
if(usr.get_active_held_item() == src)
melee_attack_chain(usr, over)
usr.FlushCurrentAction()
return TRUE //returning TRUE as a "is this overridden?" flag
if(!Adjacent(usr) || !over.Adjacent(usr))
return // should stop you from dragging through windows
@@ -1097,7 +1090,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
/obj/item/proc/updateEmbedding()
if(!islist(embedding) || !LAZYLEN(embedding))
if(!LAZYLEN(embedding))
return
AddElement(/datum/element/embed,\
+15 -15
View File
@@ -259,25 +259,24 @@ GLOBAL_LIST_INIT(fluid_duct_recipes, list(
playsound(get_turf(user), 'sound/items/deconstruct.ogg', 50, 1)
return(BRUTELOSS)
/obj/item/pipe_dispenser/ui_base_html(html)
var/datum/asset/spritesheet/assets = get_asset_datum(/datum/asset/spritesheet/pipes)
. = replacetext(html, "<!--customheadhtml-->", assets.css_tag())
/obj/item/pipe_dispenser/ui_assets(mob/user)
return list(
get_asset_datum(/datum/asset/spritesheet/pipes),
)
/obj/item/pipe_dispenser/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/item/pipe_dispenser/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
var/datum/asset/assets = get_asset_datum(/datum/asset/spritesheet/pipes)
assets.send(user)
ui = new(user, src, ui_key, "RapidPipeDispenser", name, 425, 515, master_ui, state)
ui = new(user, src, "RapidPipeDispenser", name)
ui.open()
/obj/item/pipe_dispenser/ui_data(mob/user)
var/list/data = list(
"category" = category,
"piping_layer" = piping_layer,
"ducting_layer" = ducting_layer,
"preview_rows" = recipe.get_preview(p_dir),
"categories" = list(),
"selected_color" = paint_color,
@@ -309,7 +308,7 @@ GLOBAL_LIST_INIT(fluid_duct_recipes, list(
/obj/item/pipe_dispenser/ui_act(action, params)
if(..())
return
if(!usr.canUseTopic(src))
if(!usr.canUseTopic(src, BE_CLOSE))
return
var/playeffect = TRUE
switch(action)
@@ -331,6 +330,9 @@ GLOBAL_LIST_INIT(fluid_duct_recipes, list(
if("piping_layer")
piping_layer = text2num(params["piping_layer"])
playeffect = FALSE
// if("ducting_layer")
// ducting_layer = text2num(params["ducting_layer"])
// playeffect = FALSE
if("pipe_type")
var/static/list/recipes
if(!recipes)
@@ -347,11 +349,9 @@ GLOBAL_LIST_INIT(fluid_duct_recipes, list(
mode &= ~n
else
mode |= n
if(playeffect && world.time >= effectcooldown)
if(playeffect)
spark_system.start()
effectcooldown = world.time + 100
playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0)
playsound(get_turf(src), 'sound/effects/pop.ogg', 50, FALSE)
return TRUE
/obj/item/pipe_dispenser/pre_attack(atom/A, mob/user)
+3 -3
View File
@@ -180,10 +180,10 @@
stored_decal_total = "[stored_decal][yellow_fix][stored_color]"
return
/obj/item/airlock_painter/decal/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/item/airlock_painter/decal/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "DecalPainter", name, 500, 400, master_ui, state)
ui = new(user, src, "DecalPainter", name)
ui.open()
/obj/item/airlock_painter/decal/ui_data(mob/user)
+44
View File
@@ -0,0 +1,44 @@
// Armor kits! Reinforcing uniforms to maintain fashion and also armor capabilities.
/obj/item/armorkit
name = "durathread armor kit"
desc = "A glorified sewing kit with durathread sheets, thread, and a titanium needle, for reinforcing jumpsuits and uniforms."
icon = 'icons/obj/clothing/reinf_kits.dmi'
w_class = WEIGHT_CLASS_SMALL
icon_state = "durathread_kit" // shoutout to my guy Toriate for being good at sprites tho
/obj/item/armorkit/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
// yeah have fun making subtypes and modifying the afterattack if you want to make variants
// idiot
// - hatter
var/used = FALSE
if(isobj(target) && istype(target, /obj/item/clothing/under))
var/obj/item/clothing/under/C = target
if(C.armor.melee < 10)
C.armor.melee = 10
used = TRUE
if(C.armor.laser < 10)
C.armor.laser = 10
used = TRUE
if(C.armor.fire < 40)
C.armor.fire = 40
used = TRUE
if(C.armor.acid < 10)
C.armor.acid = 10
used = TRUE
if(C.armor.bomb < 5)
C.armor.bomb = 5
used = TRUE
if(used)
user.visible_message("<span class = 'notice'>[user] uses [src] on [C], reinforcing it and tossing the empty case away afterwards.</span>", \
"<span class = 'notice'>You reinforce [C] with [src], making it a little more protective! You toss the empty casing away afterwards.</span>")
C.name = "durathread [C.name]" // this disappears if it gets repaired, which is annoying
qdel(src)
return
else
to_chat(user, "<span class = 'notice'>You stare at [src] and [C], coming to the conclusion that you probably don't need to reinforce it any further.")
return
else
return
-2
View File
@@ -71,8 +71,6 @@
if(user.incapacitated())
to_chat(user, "<span class='warning'>You can't get out while you're restrained like this!</span>")
return
user.changeNext_move(CLICK_CD_BREAKOUT)
user.last_special = world.time + CLICK_CD_BREAKOUT
to_chat(user, "<span class='notice'>You claw at the fabric of [src], trying to tear it open...</span>")
to_chat(loc, "<span class='warning'>Someone starts trying to break free of [src]!</span>")
if(!do_after(user, 200, target = src))
+3 -3
View File
@@ -6,6 +6,8 @@
icon_state = "cutout_basic"
w_class = WEIGHT_CLASS_BULKY
resistance_flags = FLAMMABLE
attack_hand_speed = CLICK_CD_MELEE
attack_hand_is_action = TRUE
/// Possible restyles for the cutout, add an entry in change_appearance() if you add to here
var/static/list/possible_appearances
/// If the cutout is pushed over and has to be righted
@@ -43,8 +45,7 @@
"Monkey" = image(icon = src.icon, icon_state = "cutout_monky"),
))
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/cardboard_cutout/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/cardboard_cutout/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
if(user.a_intent == INTENT_HELP || pushed_over)
return ..()
user.visible_message("<span class='warning'>[user] pushes over [src]!</span>", "<span class='danger'>You push over [src]!</span>")
@@ -81,7 +82,6 @@
else if(I.hitsound)
playsound(loc, I.hitsound, get_clamped_volume(), 1, -1)
user.changeNext_move(CLICK_CD_MELEE)
user.do_attack_animation(src)
if(I.force)
+1 -5
View File
@@ -16,7 +16,7 @@
custom_materials = list(/datum/material/iron=13000)
attack_verb = list("sawed", "torn", "cut", "chopped", "diced")
hitsound = "swing_hit"
sharpness = IS_SHARP
sharpness = SHARP_EDGED
actions_types = list(/datum/action/item_action/startchainsaw)
tool_behaviour = TOOL_SAW
toolspeed = 0.5
@@ -71,10 +71,6 @@
/obj/item/chainsaw/update_icon_state()
icon_state = "chainsaw_[on ? "on" : "off"]"
/obj/item/chainsaw/get_dismemberment_chance()
if(wielded)
. = ..()
/obj/item/chainsaw/doomslayer
name = "THE GREAT COMMUNICATOR"
desc = "<span class='warning'>VRRRRRRR!!!</span>"
+1 -1
View File
@@ -188,4 +188,4 @@
else
..()
else
..()
..()
+2 -2
View File
@@ -32,6 +32,6 @@
if(istype(I, /obj/item/gavelhammer))
playsound(loc, 'sound/items/gavel.ogg', 100, 1)
user.visible_message("<span class='warning'>[user] strikes [src] with [I].</span>")
user.changeNext_move(CLICK_CD_MELEE)
return TRUE
else
return ..()
return ..()
+13 -11
View File
@@ -147,23 +147,23 @@
to_chat(user, "<span class='warning'>There is not enough of [src] left!</span>")
. = TRUE
/obj/item/toy/crayon/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
// tgui is a plague upon this codebase
/obj/item/toy/crayon/ui_state(mob/user)
return GLOB.hands_state
SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/item/toy/crayon/ui_interact(mob/user, datum/tgui/ui)
// tgui is a plague upon this codebase
// no u
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "Crayon", name, 600, 600,
master_ui, state)
ui = new(user, src, "Crayon", name)
ui.open()
/obj/item/toy/crayon/spraycan/AltClick(mob/user)
. = ..()
if(user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
if(has_cap)
is_capped = !is_capped
to_chat(user, "<span class='notice'>The cap on [src] is now [is_capped ? "on" : "off"].</span>")
update_icon()
return TRUE
/obj/item/toy/crayon/CtrlClick(mob/user)
if(can_change_colour && !isturf(loc) && user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
@@ -273,7 +273,9 @@
. = ..()
if(!proximity || !check_allowed_items(target))
return
draw_on(target, user, proximity, params)
/obj/item/toy/crayon/proc/draw_on(atom/target, mob/user, proximity, params)
var/static/list/punctuation = list("!","?",".",",","/","+","-","=","%","#","&")
var/cost = 1
@@ -568,9 +570,9 @@
dye_color = DYE_RAINBOW
charges = -1
/obj/item/toy/crayon/rainbow/afterattack(atom/target, mob/user, proximity, params)
/obj/item/toy/crayon/rainbow/draw_on(atom/target, mob/user, proximity, params)
paint_color = rgb(rand(0,255), rand(0,255), rand(0,255))
. = ..()
return ..()
/*
* Crayon Box
@@ -693,7 +695,7 @@
. += "It is empty."
. += "<span class='notice'>Alt-click [src] to [ is_capped ? "take the cap off" : "put the cap on"].</span>"
/obj/item/toy/crayon/spraycan/afterattack(atom/target, mob/user, proximity, params)
/obj/item/toy/crayon/spraycan/draw_on(atom/target, mob/user, proximity, params)
if(!proximity)
return
@@ -766,7 +768,7 @@
desc = "A metallic container containing shiny synthesised paint."
charges = -1
/obj/item/toy/crayon/spraycan/borg/afterattack(atom/target,mob/user,proximity, params)
/obj/item/toy/crayon/spraycan/borg/draw_on(atom/target,mob/user,proximity, params)
var/diff = ..()
if(!iscyborg(user))
to_chat(user, "<span class='notice'>How did you get this?</span>")
+1 -2
View File
@@ -77,8 +77,7 @@
/obj/item/defibrillator/ui_action_click()
toggle_paddles()
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/defibrillator/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/defibrillator/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(loc == user)
if(slot_flags == ITEM_SLOT_BACK)
if(user.get_item_by_slot(SLOT_BACK) == src)
+11 -9
View File
@@ -54,18 +54,20 @@
name = initial(name)
icon_state = initial(icon_state)
/obj/item/aicard/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/item/aicard/ui_state(mob/user)
return GLOB.hands_state
/obj/item/aicard/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "Intellicard", name, 500, 500, master_ui, state)
ui = new(user, src, "Intellicard", name)
ui.open()
/obj/item/aicard/ui_data()
var/list/data = list()
if(AI)
data["name"] = AI.name
data["laws"] = AI.laws.get_law_list(include_zeroth = 1)
data["laws"] = AI.laws.get_law_list(include_zeroth = TRUE, render_html = FALSE)
data["health"] = (AI.health + 100) / 2
data["wireless"] = !AI.control_disabled //todo disabled->enabled
data["radio"] = AI.radio_enabled
@@ -86,19 +88,19 @@
if(confirm == "Yes" && !..())
flush = TRUE
if(AI && AI.loc == src)
to_chat(AI, "Your core files are being wiped!")
to_chat(AI, "<span class='userdanger'>Your core files are being wiped!</span>")
while(AI.stat != DEAD && flush)
AI.adjustOxyLoss(1)
AI.adjustOxyLoss(5)
AI.updatehealth()
sleep(5)
flush = FALSE
. = TRUE
if("wireless")
AI.control_disabled = !AI.control_disabled
to_chat(AI, "[src]'s wireless port has been [AI.control_disabled ? "disabled" : "enabled"]!")
to_chat(AI, "<span class='warning'>[src]'s wireless port has been [AI.control_disabled ? "disabled" : "enabled"]!</span>")
. = TRUE
if("radio")
AI.radio_enabled = !AI.radio_enabled
to_chat(AI, "Your Subspace Transceiver has been [AI.radio_enabled ? "enabled" : "disabled"]!")
to_chat(AI, "<span class='warning'>Your Subspace Transceiver has been [AI.radio_enabled ? "enabled" : "disabled"]!</span>")
. = TRUE
update_icon()
@@ -132,8 +132,7 @@
/obj/effect/dummy/chameleon/attackby()
master.disrupt()
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/effect/dummy/chameleon/attack_hand()
/obj/effect/dummy/chameleon/on_attack_hand()
master.disrupt()
/obj/effect/dummy/chameleon/attack_animal()
@@ -116,8 +116,6 @@
if(!hound)
go_out(user)
return
user.changeNext_move(CLICK_CD_BREAKOUT)
user.last_special = world.time + CLICK_CD_BREAKOUT
if(user.a_intent == INTENT_HELP)
return
var/voracious = TRUE
@@ -165,12 +163,13 @@
return
ui_interact(user)
/obj/item/dogborg/sleeper/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state)
/obj/item/dogborg/sleeper/ui_state(mob/user)
return GLOB.notcontained_state
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/item/dogborg/sleeper/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "dogborg_sleeper", name, 375, 550, master_ui, state)
ui = new(user, src, "dogborg_sleeper", name, 375, 550) //UI DOES NOT EXIST
ui.open()
/obj/item/dogborg/sleeper/ui_data()
+13 -1
View File
@@ -183,9 +183,21 @@
var/T = get_turf(target)
if(locate(/mob/living) in T)
new /obj/effect/temp_visual/medical_holosign(T,user) //produce a holographic glow
holo_cooldown = world.time + 100
holo_cooldown = world.time + 10 SECONDS
return
// see: [/datum/wound/burn/proc/uv()]
/obj/item/flashlight/pen/paramedic
name = "paramedic penlight"
desc = "A high-powered UV penlight intended to help stave off infection in the field on serious burned patients. Probably really bad to look into."
icon_state = "penlight_surgical"
/// Our current UV cooldown
var/uv_cooldown = 0
/// How long between UV fryings
var/uv_cooldown_length = 1 MINUTES
/// How much sanitization to apply to the burn wound
var/uv_power = 1
/obj/effect/temp_visual/medical_holosign
name = "medical holosign"
desc = "A small holographic glow that indicates a medic is coming to treat a patient."
@@ -43,7 +43,7 @@
user.visible_message("<span class='warning'>[user] projects a forcefield!</span>","<span class='notice'>You project a forcefield.</span>")
var/obj/structure/projected_forcefield/F = new(T, src)
current_fields += F
user.changeNext_move(CLICK_CD_MELEE)
user.DelayNextAction(CLICK_CD_MELEE)
/obj/item/forcefield_projector/attack_self(mob/user)
if(LAZYLEN(current_fields))
+2 -130
View File
@@ -1,4 +1,4 @@
GLOBAL_LIST_EMPTY(GPS_list)
/obj/item/gps
name = "global positioning system"
desc = "Helping lost spacemen find their way through the planets since 2016."
@@ -8,138 +8,10 @@ GLOBAL_LIST_EMPTY(GPS_list)
slot_flags = ITEM_SLOT_BELT
obj_flags = UNIQUE_RENAME
var/gpstag = "COM0"
var/emped = FALSE
var/tracking = TRUE
var/updating = TRUE //Automatic updating of GPS list. Can be set to manual by user.
var/global_mode = TRUE //If disabled, only GPS signals of the same Z level are shown
/obj/item/gps/examine(mob/user)
. = ..()
var/turf/curr = get_turf(src)
. += "The screen says: [get_area_name(curr, TRUE)] ([curr.x], [curr.y], [curr.z])"
. += "<span class='notice'>Alt-click to switch it [tracking ? "off":"on"].</span>"
/obj/item/gps/Initialize()
. = ..()
GLOB.GPS_list += src
name = "global positioning system ([gpstag])"
add_overlay("working")
/obj/item/gps/Destroy()
GLOB.GPS_list -= src
return ..()
/obj/item/gps/emp_act(severity)
. = ..()
if (. & EMP_PROTECT_SELF)
return
emped = TRUE
cut_overlay("working")
add_overlay("emp")
addtimer(CALLBACK(src, .proc/reboot), 300, TIMER_UNIQUE|TIMER_OVERRIDE) //if a new EMP happens, remove the old timer so it doesn't reactivate early
SStgui.close_uis(src) //Close the UI control if it is open.
/obj/item/gps/proc/reboot()
emped = FALSE
cut_overlay("emp")
add_overlay("working")
/obj/item/gps/AltClick(mob/user)
. = ..()
if(!user.canUseTopic(src, BE_CLOSE))
return
toggletracking(user)
return TRUE
/obj/item/gps/proc/toggletracking(mob/user)
if(!user.canUseTopic(src, BE_CLOSE))
return //user not valid to use gps
if(emped)
to_chat(user, "It's busted!")
return
if(tracking)
cut_overlay("working")
to_chat(user, "[src] is no longer tracking, or visible to other GPS devices.")
tracking = FALSE
else
add_overlay("working")
to_chat(user, "[src] is now tracking, and visible to other GPS devices.")
tracking = TRUE
/obj/item/gps/ui_interact(mob/user, ui_key = "gps", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) // Remember to use the appropriate state.
if(emped)
to_chat(user, "[src] fizzles weakly.")
return
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
// Variable window height, depending on how many GPS units there are
// to show, clamped to relatively safe range.
var/gps_window_height = clamp(325 + GLOB.GPS_list.len * 14, 325, 700)
ui = new(user, src, ui_key, "Gps", "Global Positioning System", 470, gps_window_height, master_ui, state) //width, height
ui.open()
ui.set_autoupdate(state = updating)
/obj/item/gps/ui_data(mob/user)
var/list/data = list()
data["power"] = tracking
data["tag"] = gpstag
data["updating"] = updating
data["globalmode"] = global_mode
if(!tracking || emped) //Do not bother scanning if the GPS is off or EMPed
return data
var/turf/curr = get_turf(src)
data["current"] = "[get_area_name(curr, TRUE)] ([curr.x], [curr.y], [curr.z])"
data["currentArea"] = "[get_area_name(curr, TRUE)]"
data["currentCoords"] = "[curr.x], [curr.y], [curr.z]"
var/list/signals = list()
data["signals"] = list()
for(var/gps in GLOB.GPS_list)
var/obj/item/gps/G = gps
if(G.emped || !G.tracking || G == src)
continue
var/turf/pos = get_turf(G)
if(!global_mode && pos.z != curr.z)
continue
var/list/signal = list()
signal["entrytag"] = G.gpstag //Name or 'tag' of the GPS
signal["coords"] = "[pos.x], [pos.y], [pos.z]"
if(pos.z == curr.z) //Distance/Direction calculations for same z-level only
signal["dist"] = max(get_dist(curr, pos), 0) //Distance between the src and remote GPS turfs
signal["degrees"] = round(Get_Angle(curr, pos)) //0-360 degree directional bearing, for more precision.
signals += list(signal) //Add this signal to the list of signals
data["signals"] = signals
return data
/obj/item/gps/ui_act(action, params)
if(..())
return
switch(action)
if("rename")
var/a = input("Please enter desired tag.", name, gpstag) as text
a = copytext(sanitize(a), 1, 20)
gpstag = a
. = TRUE
name = "global positioning system ([gpstag])"
if("power")
toggletracking(usr)
. = TRUE
if("updating")
updating = !updating
. = TRUE
if("globalmode")
global_mode = !global_mode
. = TRUE
AddComponent(/datum/component/gps/item, gpstag)
/obj/item/gps/science
icon_state = "gps-s"
@@ -263,3 +263,11 @@
icon = 'icons/obj/advancedtools.dmi'
icon_state = "multitool"
toolspeed = 0.2
/obj/item/multitool/advanced/brass
name = "clockwork multitool"
desc = "A brass...multitool? With three prongs arcing electricity between them. It vibrates subtly in your hand."
icon = 'icons/obj/tools.dmi'
icon_state = "clockitool"
toolspeed = 0.2
@@ -11,7 +11,7 @@
/obj/item/stack/circuit_stack/attack_self(mob/user)// Prevents the crafting menu, and tells you how to use it.
to_chat(user, "<span class='warning'>You can't use [src] by itself, you'll have to try and remove one of these circuits by hand... carefully.</span>")
/obj/item/stack/circuit_stack/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/stack/circuit_stack/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
var/mob/living/carbon/human/H = user
if(!user.get_inactive_held_item() == src)
return ..()
+1 -4
View File
@@ -97,10 +97,7 @@ GLOBAL_LIST_EMPTY(power_sinks)
/obj/item/powersink/attack_ai()
return
/obj/item/powersink/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
/obj/item/powersink/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
switch(mode)
if(DISCONNECTED)
..()
@@ -29,10 +29,9 @@
/obj/item/electropack/Destroy()
SSradio.remove_object(src, frequency)
. = ..()
return ..()
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/electropack/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/electropack/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(iscarbon(user))
var/mob/living/carbon/C = user
if(src == C.back)
@@ -40,7 +39,7 @@
return
return ..()
/obj/item/electropack/attackby(obj/item/W, mob/living/user, params)
/obj/item/electropack/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/clothing/head/helmet))
var/obj/item/assembly/shock_kit/A = new /obj/item/assembly/shock_kit(user)
A.icon = 'icons/obj/assemblies.dmi'
@@ -60,56 +59,12 @@
else
return ..()
/obj/item/electropack/Topic(href, href_list)
var/mob/living/carbon/C = usr
if(usr.stat || usr.restrained() || C.back == src)
return
if(!usr.canUseTopic(src, BE_CLOSE))
usr << browse(null, "window=radio")
onclose(usr, "radio")
return
if(href_list["set"])
if(href_list["set"] == "freq")
var/new_freq = input(usr, "Input a new receiving frequency", "Electropack Frequency", format_frequency(frequency)) as num|null
if(!usr.canUseTopic(src, BE_CLOSE))
return
new_freq = unformat_frequency(new_freq)
new_freq = sanitize_frequency(new_freq, TRUE)
set_frequency(new_freq)
if(href_list["set"] == "code")
var/new_code = input(usr, "Input a new receiving code", "Electropack Code", code) as num|null
if(!usr.canUseTopic(src, BE_CLOSE))
return
new_code = round(new_code)
new_code = clamp(new_code, 1, 100)
code = new_code
if(href_list["set"] == "power")
if(!usr.canUseTopic(src, BE_CLOSE))
return
on = !(on)
icon_state = "electropack[on]"
if(usr)
attack_self(usr)
return
/obj/item/electropack/proc/set_frequency(new_frequency)
SSradio.remove_object(src, frequency)
frequency = new_frequency
SSradio.add_object(src, frequency, RADIO_SIGNALER)
return
/obj/item/electropack/receive_signal(datum/signal/signal)
if(!signal || signal.data["code"] != code)
return
if(isliving(loc) && on)
if(shock_cooldown == TRUE)
if(shock_cooldown)
return
shock_cooldown = TRUE
addtimer(VARSET_CALLBACK(src, shock_cooldown, FALSE), 100)
@@ -125,18 +80,59 @@
if(master)
master.receive_signal()
return
/obj/item/electropack/ui_interact(mob/user)
if(!ishuman(user))
/obj/item/electropack/proc/set_frequency(new_frequency)
SSradio.remove_object(src, frequency)
frequency = new_frequency
SSradio.add_object(src, frequency, RADIO_SIGNALER)
/obj/item/electropack/ui_state(mob/user)
return GLOB.hands_state
/obj/item/electropack/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Electropack", name)
ui.open()
/obj/item/electropack/ui_data(mob/user)
var/list/data = list()
data["power"] = on
data["frequency"] = frequency
data["code"] = code
data["minFrequency"] = MIN_FREE_FREQ
data["maxFrequency"] = MAX_FREE_FREQ
return data
/obj/item/electropack/ui_act(action, params)
if(..())
return
/obj/item/electropack/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "Electropack", name, ui_x, ui_y, master_ui, state)
ui.open()
switch(action)
if("power")
on = !on
icon_state = "electropack[on]"
. = TRUE
if("freq")
var/value = unformat_frequency(params["freq"])
if(value)
frequency = sanitize_frequency(value, TRUE)
set_frequency(frequency)
. = TRUE
if("code")
var/value = text2num(params["code"])
if(value)
value = round(value)
code = clamp(value, 1, 100)
. = TRUE
if("reset")
if(params["reset"] == "freq")
frequency = initial(frequency)
. = TRUE
else if(params["reset"] == "code")
code = initial(code)
. = TRUE
/obj/item/electropack/shockcollar
name = "shock collar"
@@ -146,7 +142,7 @@
icon_state = "shockcollar"
item_state = "shockcollar"
body_parts_covered = NECK
slot_flags = ITEM_SLOT_NECK | ITEM_SLOT_DENYPOCKET //no more pocket shockers
slot_flags = ITEM_SLOT_NECK //no more pocket shockers. Now done without lazyness
w_class = WEIGHT_CLASS_SMALL
strip_delay = 60
equip_delay_other = 60
@@ -162,22 +158,24 @@
materials = list(/datum/material/iron = 5000, /datum/material/glass =2000)
category = list("hacked", "Misc")
/obj/item/electropack/shockcollar/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/electropack/shockcollar/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(loc == user && user.get_item_by_slot(SLOT_NECK))
to_chat(user, "<span class='warning'>The collar is fastened tight! You'll need help taking this off!</span>")
return
return ..()
/obj/item/electropack/shockcollar/receive_signal(datum/signal/signal)
/obj/item/electropack/shockcollar/receive_signal(datum/signal/signal) //we have to override this because of text
if(!signal || signal.data["code"] != code)
return
if(isliving(loc) && on)
if(isliving(loc) && on) //the "on" arg is currently useless
var/mob/living/L = loc
if(!L.get_item_by_slot(SLOT_NECK)) //**properly** stops pocket shockers
return
if(shock_cooldown == TRUE)
return
shock_cooldown = TRUE
addtimer(VARSET_CALLBACK(src, shock_cooldown, FALSE), 100)
var/mob/living/L = loc
step(L, pick(GLOB.cardinals))
to_chat(L, "<span class='danger'>You feel a sharp shock from the collar!</span>")
@@ -197,10 +195,13 @@
if(t)
tagname = t
name = "[initial(name)] - [t]"
return
if(istype(W, /obj/item/clothing/head/helmet)) //lazy method of denying this
return
else
return ..()
/obj/item/electropack/shockcollar/ui_interact(mob/user) //on_click calls this
/obj/item/electropack/shockcollar/ui_interact(mob/user) //note to src: use tgooey
var/dat = {"
<TT>
<B>Frequency/Code</B> for shock collar:<BR>
@@ -86,10 +86,7 @@
/obj/item/radio/intercom/attack_ai(mob/user)
interact(user)
/obj/item/radio/intercom/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
/obj/item/radio/intercom/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
interact(user)
/obj/item/radio/intercom/interact(mob/user)
+8 -12
View File
@@ -107,19 +107,15 @@
else
..()
/obj/item/radio/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.inventory_state)
. = ..()
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/item/radio/ui_state(mob/user)
return GLOB.inventory_state
/obj/item/radio/ui_interact(mob/user, datum/tgui/ui, datum/ui_state/state)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
var/ui_width = 360
var/ui_height = 106
if(subspace_transmission)
if(channels.len > 0)
ui_height += 6 + channels.len * 21
else
ui_height += 24
ui = new(user, src, ui_key, "Radio", name, ui_width, ui_height, master_ui, state)
ui = new(user, src, "Radio", name)
if(state)
ui.set_state(state)
ui.open()
/obj/item/radio/ui_data(mob/user)
@@ -45,7 +45,7 @@
to_chat(loc, "<span class='userdanger'>*ding*</span>")
addtimer(CALLBACK(src, .proc/snap), 2)
/obj/item/reverse_bear_trap/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/reverse_bear_trap/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(iscarbon(user))
var/mob/living/carbon/C = user
if(C.get_item_by_slot(SLOT_HEAD) == src)
+182 -67
View File
@@ -10,6 +10,14 @@ NANITE SCANNER
GENETICS SCANNER
*/
// Describes the three modes of scanning available for health analyzers
#define SCANMODE_HEALTH 0
#define SCANMODE_CHEMICAL 1
#define SCANMODE_WOUND 2
#define SCANNER_CONDENSED 0
#define SCANNER_VERBOSE 1
/obj/item/t_scanner
name = "\improper T-ray scanner"
desc = "A terahertz-ray emitter and scanner used to detect underfloor objects such as cables and pipes."
@@ -80,7 +88,7 @@ GENETICS SCANNER
throw_range = 7
custom_materials = list(/datum/material/iron=200)
var/mode = 1
var/scanmode = 0
var/scanmode = SCANMODE_HEALTH
var/advanced = FALSE
/obj/item/healthanalyzer/suicide_act(mob/living/carbon/user)
@@ -88,37 +96,40 @@ GENETICS SCANNER
return BRUTELOSS
/obj/item/healthanalyzer/attack_self(mob/user)
if(!scanmode)
to_chat(user, "<span class='notice'>You switch the health analyzer to scan chemical contents.</span>")
scanmode = 1
else
to_chat(user, "<span class='notice'>You switch the health analyzer to check physical health.</span>")
scanmode = 0
scanmode = (scanmode + 1) % 3
switch(scanmode)
if(SCANMODE_HEALTH)
to_chat(user, "<span class='notice'>You switch the health analyzer to check physical health.</span>")
if(SCANMODE_CHEMICAL)
to_chat(user, "<span class='notice'>You switch the health analyzer to scan chemical contents.</span>")
if(SCANMODE_WOUND)
to_chat(user, "<span class='notice'>You switch the health analyzer to report extra info on wounds.</span>")
/obj/item/healthanalyzer/attack(mob/living/M, mob/living/carbon/human/user)
flick("[icon_state]-scan", src) //makes it so that it plays the scan animation upon scanning, including clumsy scanning
// Clumsiness/brain damage check
if ((HAS_TRAIT(user, TRAIT_CLUMSY) || HAS_TRAIT(user, TRAIT_DUMB)) && prob(50))
to_chat(user, "<span class='notice'>You stupidly try to analyze the floor's vitals!</span>")
user.visible_message("<span class='warning'>[user] has analyzed the floor's vitals!</span>")
var/msg = "<span class='info'>*---------*\nAnalyzing results for The floor:\n\tOverall status: <b>Healthy</b>\n"
msg += "Key: <font color='blue'>Suffocation</font>/<font color='green'>Toxin</font>/<font color='#FF8000'>Burn</font>/<font color='red'>Brute</font>\n"
msg += "\tDamage specifics: <font color='blue'>0</font>-<font color='green'>0</font>-<font color='#FF8000'>0</font>-<font color='red'>0</font>\n"
msg += "Body temperature: ???\n"
msg += "*---------*</span>"
to_chat(user, msg)
user.visible_message("<span class='warning'>[user] analyzes the floor's vitals!</span>", \
"<span class='notice'>You stupidly try to analyze the floor's vitals!</span>")
to_chat(user, "<span class='info'>Analyzing results for The floor:\n\tOverall status: <b>Healthy</b></span>\
\n<span class='info'>Key: <font color='blue'>Suffocation</font>/<font color='green'>Toxin</font>/<font color='#FF8000'>Burn</font>/<font color='red'>Brute</font></span>\
\n<span class='info'>\tDamage specifics: <font color='blue'>0</font>-<font color='green'>0</font>-<font color='#FF8000'>0</font>-<font color='red'>0</font></span>\
\n<span class='info'>Body temperature: ???</span>")
return
user.visible_message("<span class='notice'>[user] has analyzed [M]'s vitals.</span>")
user.visible_message("<span class='notice'>[user] analyzes [M]'s vitals.</span>", \
"<span class='notice'>You analyze [M]'s vitals.</span>")
if(scanmode == 0)
if(scanmode == SCANMODE_HEALTH)
healthscan(user, M, mode, advanced)
else if(scanmode == 1)
else if(scanmode == SCANMODE_CHEMICAL)
chemscan(user, M)
else
woundscan(user, M, src)
add_fingerprint(user)
// Used by the PDA medical scanner too
/proc/healthscan(mob/user, mob/living/M, mode = 1, advanced = FALSE)
if(isliving(user) && (user.incapacitated() || user.eye_blind))
@@ -402,6 +413,17 @@ GENETICS SCANNER
msg += "<span class='danger'> Intervention recommended.</span>\n"
else
msg += "\n"
// Wounds
if(iscarbon(M))
var/mob/living/carbon/C = M
var/list/wounded_parts = C.get_wounded_bodyparts()
for(var/i in wounded_parts)
var/obj/item/bodypart/wounded_part = i
msg += "<span class='alert ml-1'><b>Warning: Physical trauma[LAZYLEN(wounded_part.wounds) > 1? "s" : ""] detected in [wounded_part.name]</b>"
for(var/k in wounded_part.wounds)
var/datum/wound/W = k
msg += "<div class='ml-2'>Type: [W.name]\nSeverity: [W.severity_text()]\nRecommended Treatment: [W.treat_text]</div>\n" // less lines than in woundscan() so we don't overload people trying to get basic med info
msg += "</span>\n"
for(var/thing in M.diseases)
var/datum/disease/D = thing
@@ -414,7 +436,7 @@ GENETICS SCANNER
var/blood_typepath = C.get_blood_id()
if(blood_typepath)
if(ishuman(C))
if(H.bleed_rate)
if(H.is_bleeding())
msg += "<span class='danger'>Subject is bleeding!</span>\n"
var/blood_percent = round((C.scan_blood_volume() / (BLOOD_VOLUME_NORMAL * C.blood_ratio))*100)
var/blood_type = C.dna.blood_type
@@ -505,6 +527,67 @@ GENETICS SCANNER
desc = "A hand-held body scanner able to distinguish vital signs of the subject with high accuracy."
advanced = TRUE
/// Displays wounds with extended information on their status vs medscanners
/proc/woundscan(mob/user, mob/living/carbon/patient, obj/item/healthanalyzer/wound/scanner)
if(!istype(patient))
return
var/render_list = ""
for(var/i in patient.get_wounded_bodyparts())
var/obj/item/bodypart/wounded_part = i
render_list += "<span class='alert ml-1'><b>Warning: Physical trauma[LAZYLEN(wounded_part.wounds) > 1? "s" : ""] detected in [wounded_part.name]</b>"
for(var/k in wounded_part.wounds)
var/datum/wound/W = k
render_list += "<div class='ml-2'>[W.get_scanner_description()]</div>\n"
render_list += "</span>"
if(render_list == "")
if(istype(scanner))
// Only emit the cheerful scanner message if this scan came from a scanner
playsound(scanner, 'sound/machines/ping.ogg', 50, FALSE)
to_chat(user, "<span class='notice'>\The [scanner] makes a happy ping and briefly displays a smiley face with several exclamation points! It's really excited to report that [patient] has no wounds!</span>")
else
to_chat(user, "<span class='notice ml-1'>No wounds detected in subject.</span>")
else
to_chat(user, jointext(render_list, ""))
/obj/item/healthanalyzer/wound
name = "first aid analyzer"
icon_state = "adv_spectrometer"
desc = "A prototype MeLo-Tech medical scanner used to diagnose injuries and recommend treatment for serious wounds, but offers no further insight into the patient's health. You hope the final version is less annoying to read!"
var/next_encouragement
var/greedy
/obj/item/healthanalyzer/wound/attack_self(mob/user)
if(next_encouragement < world.time)
playsound(src, 'sound/machines/ping.ogg', 50, FALSE)
var/list/encouragements = list("briefly displays a happy face, gazing emptily at you", "briefly displays a spinning cartoon heart", "displays an encouraging message about eating healthy and exercising", \
"reminds you that everyone is doing their best", "displays a message wishing you well", "displays a sincere thank-you for your interest in first-aid", "formally absolves you of all your sins")
to_chat(user, "<span class='notice'>\The [src] makes a happy ping and [pick(encouragements)]!</span>")
next_encouragement = world.time + 10 SECONDS
greedy = FALSE
else if(!greedy)
to_chat(user, "<span class='warning'>\The [src] displays an eerily high-definition frowny face, chastizing you for asking it for too much encouragement.</span>")
greedy = TRUE
else
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, FALSE)
if(isliving(user))
var/mob/living/L = user
to_chat(L, "<span class='warning'>\The [src] makes a disappointed buzz and pricks your finger for being greedy. Ow!</span>")
L.adjustBruteLoss(4)
L.dropItemToGround(src)
/obj/item/healthanalyzer/wound/attack(mob/living/carbon/patient, mob/living/carbon/human/user)
add_fingerprint(user)
user.visible_message("<span class='notice'>[user] scans [patient] for serious injuries.</span>", "<span class='notice'>You scan [patient] for serious injuries.</span>")
if(!istype(patient))
playsound(src, 'sound/machines/buzz-sigh.ogg', 30, TRUE)
to_chat(user, "<span class='notice'>\The [src] makes a sad buzz and briefly displays a frowny face, indicating it can't scan [patient].</span>")
return
woundscan(user, patient, src)
/obj/item/analyzer
desc = "A hand-held environmental scanner which reports current gas levels. Alt-Click to use the built in barometer function."
name = "analyzer"
@@ -541,54 +624,13 @@ GENETICS SCANNER
if (user.stat || user.eye_blind)
return
var/turf/location = user.loc
//Functionality moved down to proc/scan_turf()
var/turf/location = get_turf(user)
if(!istype(location))
return
var/datum/gas_mixture/environment = location.return_air()
var/pressure = environment.return_pressure()
var/total_moles = environment.total_moles()
to_chat(user, "<span class='info'><B>Results:</B></span>")
if(abs(pressure - ONE_ATMOSPHERE) < 10)
to_chat(user, "<span class='info'>Pressure: [round(pressure, 0.01)] kPa</span>")
else
to_chat(user, "<span class='alert'>Pressure: [round(pressure, 0.01)] kPa</span>")
if(total_moles)
var/o2_concentration = environment.get_moles(/datum/gas/oxygen)/total_moles
var/n2_concentration = environment.get_moles(/datum/gas/nitrogen)/total_moles
var/co2_concentration = environment.get_moles(/datum/gas/carbon_dioxide)/total_moles
var/plasma_concentration = environment.get_moles(/datum/gas/plasma)/total_moles
if(abs(n2_concentration - N2STANDARD) < 20)
to_chat(user, "<span class='info'>Nitrogen: [round(n2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/nitrogen), 0.01)] mol)</span>")
else
to_chat(user, "<span class='alert'>Nitrogen: [round(n2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/nitrogen), 0.01)] mol)</span>")
if(abs(o2_concentration - O2STANDARD) < 2)
to_chat(user, "<span class='info'>Oxygen: [round(o2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/oxygen), 0.01)] mol)</span>")
else
to_chat(user, "<span class='alert'>Oxygen: [round(o2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/oxygen), 0.01)] mol)</span>")
if(co2_concentration > 0.01)
to_chat(user, "<span class='alert'>CO2: [round(co2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/carbon_dioxide), 0.01)] mol)</span>")
else
to_chat(user, "<span class='info'>CO2: [round(co2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/carbon_dioxide), 0.01)] mol)</span>")
if(plasma_concentration > 0.005)
to_chat(user, "<span class='alert'>Plasma: [round(plasma_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/plasma), 0.01)] mol)</span>")
else
to_chat(user, "<span class='info'>Plasma: [round(plasma_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/plasma), 0.01)] mol)</span>")
for(var/id in environment.get_gases())
if(id in GLOB.hardcoded_gases)
continue
var/gas_concentration = environment.get_moles(id)/total_moles
to_chat(user, "<span class='alert'>[GLOB.meta_gas_names[id]]: [round(gas_concentration*100, 0.01)] % ([round(environment.get_moles(id), 0.01)] mol)</span>")
to_chat(user, "<span class='info'>Temperature: [round(environment.return_temperature()-T0C, 0.01)] &deg;C ([round(environment.return_temperature(), 0.01)] K)</span>")
scan_turf(user, location)
/obj/item/analyzer/AltClick(mob/user) //Barometer output for measuring when the next storm happens
. = ..()
@@ -666,7 +708,7 @@ GENETICS SCANNER
var/total_moles = air_contents.total_moles()
var/pressure = air_contents.return_pressure()
var/volume = air_contents.return_volume()
var/volume = air_contents.return_volume() //could just do mixture.volume... but safety, I guess?
var/temperature = air_contents.return_temperature()
var/cached_scan_results = air_contents.analyzer_results
@@ -693,6 +735,73 @@ GENETICS SCANNER
to_chat(user, "<span class='notice'>Power of the last fusion reaction: [fusion_power]\n This power indicates it was a [tier]-tier fusion reaction.</span>")
return
/obj/item/analyzer/proc/scan_turf(mob/user, turf/location)
var/datum/gas_mixture/environment = location.return_air()
var/pressure = environment.return_pressure()
var/total_moles = environment.total_moles()
var/cached_scan_results = environment.analyzer_results
to_chat(user, "<span class='info'><B>Results:</B></span>")
if(abs(pressure - ONE_ATMOSPHERE) < 10)
to_chat(user, "<span class='info'>Pressure: [round(pressure, 0.01)] kPa</span>")
else
to_chat(user, "<span class='alert'>Pressure: [round(pressure, 0.01)] kPa</span>")
if(total_moles)
var/o2_concentration = environment.get_moles(/datum/gas/oxygen)/total_moles
var/n2_concentration = environment.get_moles(/datum/gas/nitrogen)/total_moles
var/co2_concentration = environment.get_moles(/datum/gas/carbon_dioxide)/total_moles
var/plasma_concentration = environment.get_moles(/datum/gas/plasma)/total_moles
if(abs(n2_concentration - N2STANDARD) < 20)
to_chat(user, "<span class='info'>Nitrogen: [round(n2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/nitrogen), 0.01)] mol)</span>")
else
to_chat(user, "<span class='alert'>Nitrogen: [round(n2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/nitrogen), 0.01)] mol)</span>")
if(abs(o2_concentration - O2STANDARD) < 2)
to_chat(user, "<span class='info'>Oxygen: [round(o2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/oxygen), 0.01)] mol)</span>")
else
to_chat(user, "<span class='alert'>Oxygen: [round(o2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/oxygen), 0.01)] mol)</span>")
if(co2_concentration > 0.01)
to_chat(user, "<span class='alert'>CO2: [round(co2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/carbon_dioxide), 0.01)] mol)</span>")
else
to_chat(user, "<span class='info'>CO2: [round(co2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/carbon_dioxide), 0.01)] mol)</span>")
if(plasma_concentration > 0.005)
to_chat(user, "<span class='alert'>Plasma: [round(plasma_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/plasma), 0.01)] mol)</span>")
else
to_chat(user, "<span class='info'>Plasma: [round(plasma_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/plasma), 0.01)] mol)</span>")
for(var/id in environment.get_gases())
if(id in GLOB.hardcoded_gases)
continue
var/gas_concentration = environment.get_moles(id)/total_moles
to_chat(user, "<span class='alert'>[GLOB.meta_gas_names[id]]: [round(gas_concentration*100, 0.01)] % ([round(environment.get_moles(id), 0.01)] mol)</span>")
to_chat(user, "<span class='info'>Temperature: [round(environment.return_temperature()-T0C, 0.01)] &deg;C ([round(environment.return_temperature(), 0.01)] K)</span>")
if(cached_scan_results && cached_scan_results["fusion"]) //notify the user if a fusion reaction was detected
var/fusion_power = round(cached_scan_results["fusion"], 0.01)
var/tier = fusionpower2text(fusion_power)
to_chat(user, "<span class='boldnotice'>Large amounts of free neutrons detected in the air indicate that a fusion reaction took place.</span>")
to_chat(user, "<span class='notice'>Power of the last fusion reaction: [fusion_power]\n This power indicates it was a [tier]-tier fusion reaction.</span>")
/obj/item/analyzer/ranged
desc = "A hand-held scanner which uses advanced spectroscopy and infrared readings to analyze gases as a distance. Alt-Click to use the built in barometer function."
name = "long-range analyzer"
icon = 'icons/obj/device.dmi'
icon_state = "ranged_analyzer"
/obj/item/analyzer/ranged/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
. = ..()
if(target.tool_act(user, src, tool_behaviour))
return
// Tool act didn't scan it, so let's get it's turf.
var/turf/location = get_turf(target)
scan_turf(user, location)
//slime scanner
/obj/item/slime_scanner
@@ -878,3 +987,9 @@ GENETICS SCANNER
return "[HM.name] ([HM.alias])"
else
return HM.alias
#undef SCANMODE_HEALTH
#undef SCANMODE_CHEMICAL
#undef SCANMODE_WOUND
#undef SCANNER_CONDENSED
#undef SCANNER_VERBOSE
@@ -54,8 +54,7 @@
mytape.ruin() //Fires destroy the tape
..()
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/taperecorder/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/taperecorder/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(loc == user)
if(mytape)
if(!user.is_holding(src))
@@ -86,98 +86,102 @@ effective or pretty fucking useless.
return
if(!used)
log_combat(user, M, "irradiated", src)
var/cooldown = GetCooldown()
used = 1
var/cooldown = get_cooldown()
used = TRUE
icon_state = "health1"
handle_cooldown(cooldown) // splits off to handle the cooldown while handling wavelength
addtimer(VARSET_CALLBACK(src, used, FALSE), cooldown)
addtimer(VARSET_CALLBACK(src, icon_state, "health"), cooldown)
to_chat(user, "<span class='warning'>Successfully irradiated [M].</span>")
spawn((wavelength+(intensity*4))*5)
if(M)
if(intensity >= 5)
M.apply_effect(round(intensity/0.075), EFFECT_UNCONSCIOUS)
M.rad_act(intensity*10)
addtimer(CALLBACK(src, .proc/radiation_aftereffect, M), (wavelength+(intensity*4))*5)
else
to_chat(user, "<span class='warning'>The radioactive microlaser is still recharging.</span>")
/obj/item/healthanalyzer/rad_laser/proc/handle_cooldown(cooldown)
spawn(cooldown)
used = 0
icon_state = "health"
/obj/item/healthanalyzer/rad_laser/proc/radiation_aftereffect(mob/living/M)
if(QDELETED(M))
return
if(intensity >= 5)
M.apply_effect(round(intensity/0.075), EFFECT_UNCONSCIOUS)
M.rad_act(intensity*10)
/obj/item/healthanalyzer/rad_laser/proc/get_cooldown()
return round(max(10, (stealth*30 + intensity*5 - wavelength/4)))
/obj/item/healthanalyzer/rad_laser/attack_self(mob/user)
interact(user)
/obj/item/healthanalyzer/rad_laser/proc/GetCooldown()
return round(max(10, (stealth*30 + intensity*5 - wavelength/4)))
/obj/item/healthanalyzer/rad_laser/interact(mob/user)
ui_interact(user)
/obj/item/healthanalyzer/rad_laser/ui_interact(mob/user)
/obj/item/healthanalyzer/rad_laser/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/item/healthanalyzer/rad_laser/ui_state(mob/user)
return GLOB.hands_state
/obj/item/healthanalyzer/rad_laser/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "RadioactiveMicrolaser", "Radioactive Microlaser", ui_x, ui_y, master_ui, state)
ui = new(user, src, "RadioactiveMicrolaser")
ui.open()
var/dat = "Irradiation: <A href='?src=[REF(src)];rad=1'>[irradiate ? "On" : "Off"]</A><br>"
dat += "Stealth Mode (NOTE: Deactivates automatically while Irradiation is off): <A href='?src=[REF(src)];stealthy=[TRUE]'>[stealth ? "On" : "Off"]</A><br>"
dat += "Scan Mode: <a href='?src=[REF(src)];mode=1'>"
if(!scanmode)
dat += "Scan Health"
else if(scanmode == 1)
dat += "Scan Reagents"
else
dat += "Disabled"
dat += "</a><br><br>"
/obj/item/healthanalyzer/rad_laser/ui_data(mob/user)
var/list/data = list()
data["irradiate"] = irradiate
data["stealth"] = stealth
data["scanmode"] = scanmode
data["intensity"] = intensity
data["wavelength"] = wavelength
data["on_cooldown"] = used
data["cooldown"] = DisplayTimeText(get_cooldown())
return data
dat += {"
Radiation Intensity:
<A href='?src=[REF(src)];radint=-5'>-</A><A href='?src=[REF(src)];radint=-1'>-</A>
[intensity]
<A href='?src=[REF(src)];radint=1'>+</A><A href='?src=[REF(src)];radint=5'>+</A><BR>
/obj/item/healthanalyzer/rad_laser/ui_act(action, params)
if(..())
return
Radiation Wavelength:
<A href='?src=[REF(src)];radwav=-5'>-</A><A href='?src=[REF(src)];radwav=-1'>-</A>
[(wavelength+(intensity*4))]
<A href='?src=[REF(src)];radwav=1'>+</A><A href='?src=[REF(src)];radwav=5'>+</A><BR>
Laser Cooldown: [DisplayTimeText(GetCooldown())]<BR>
"}
var/datum/browser/popup = new(user, "radlaser", "Radioactive Microlaser Interface", 400, 240)
popup.set_content(dat)
popup.open()
/obj/item/healthanalyzer/rad_laser/Topic(href, href_list)
if(!usr.canUseTopic(src))
return 1
usr.set_machine(src)
if(href_list["rad"])
irradiate = !irradiate
else if(href_list["stealthy"])
stealth = !stealth
else if(href_list["mode"])
scanmode += 1
if(scanmode > 2)
scanmode = 0
else if(href_list["radint"])
var/amount = text2num(href_list["radint"])
amount += intensity
intensity = max(1,(min(20,amount)))
else if(href_list["radwav"])
var/amount = text2num(href_list["radwav"])
amount += wavelength
wavelength = max(0,(min(120,amount)))
attack_self(usr)
add_fingerprint(usr)
return
switch(action)
if("irradiate")
irradiate = !irradiate
. = TRUE
if("stealth")
stealth = !stealth
. = TRUE
if("scanmode")
scanmode = !scanmode
. = TRUE
if("radintensity")
var/target = params["target"]
var/adjust = text2num(params["adjust"])
if(target == "min")
target = 1
. = TRUE
else if(target == "max")
target = 20
. = TRUE
else if(adjust)
target = intensity + adjust
. = TRUE
else if(text2num(target) != null)
target = text2num(target)
. = TRUE
if(.)
target = round(target)
intensity = clamp(target, 1, 20)
if("radwavelength")
var/target = params["target"]
var/adjust = text2num(params["adjust"])
if(target == "min")
target = 0
. = TRUE
else if(target == "max")
target = 120
. = TRUE
else if(adjust)
target = wavelength + adjust
. = TRUE
else if(text2num(target) != null)
target = text2num(target)
. = TRUE
if(.)
target = round(target)
wavelength = clamp(target, 0, 120)
/obj/item/shadowcloak
name = "cloaker belt"
@@ -79,7 +79,7 @@
if(attached_device)
attached_device.Crossed(AM)
/obj/item/transfer_valve/attack_hand()//Triggers mousetraps
/obj/item/transfer_valve/on_attack_hand()//Triggers mousetraps
. = ..()
if(.)
return
@@ -188,11 +188,10 @@
tank_one.air_contents.merge(temp)
tank_two.air_contents.set_volume(tank_two.air_contents.return_volume() - tank_one.air_contents.return_volume())
/*
/*
Exadv1: I know this isn't how it's going to work, but this was just to check
it explodes properly when it gets a signal (and it does).
*/
*/
/obj/item/transfer_valve/proc/toggle_valve()
if(!valve_open && tank_one && tank_two)
valve_open = TRUE
@@ -233,16 +232,20 @@
valve_open = FALSE
update_icon()
// this doesn't do anything but the timer etc. expects it to be here
// eventually maybe have it update icon to show state (timer, prox etc.) like old bombs
/*
This doesn't do anything but the timer etc. expects it to be here
eventually maybe have it update icon to show state (timer, prox etc.) like old bombs
*/
/obj/item/transfer_valve/proc/c_state()
return
/obj/item/transfer_valve/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/item/transfer_valve/ui_state(mob/user)
return GLOB.hands_state
/obj/item/transfer_valve/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "TransferValve", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, "TransferValve", name)
ui.open()
/obj/item/transfer_valve/ui_data(mob/user)
+3 -1
View File
@@ -23,6 +23,8 @@
max_integrity = 200
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 70)
resistance_flags = FIRE_PROOF
wound_bonus = -110
bare_wound_bonus = 20
block_parry_data = /datum/block_parry_data/dual_esword
var/hacked = FALSE
/// Can this reflect all energy projectiles?
@@ -103,7 +105,7 @@
to_chat(user, "<span class='warning'>You lack the grace to wield this!</span>")
return COMPONENT_TWOHANDED_BLOCK_WIELD
wielded = TRUE
sharpness = IS_SHARP
sharpness = SHARP_EDGED
w_class = w_class_on
total_mass = total_mass_on
hitsound = 'sound/weapons/blade1.ogg'
+6 -4
View File
@@ -192,11 +192,13 @@
return top_vote
/obj/item/toy/eightball/haunted/ui_interact(mob/user, ui_key="main", datum/tgui/ui=null, force_open=0, datum/tgui/master_ui=null, datum/ui_state/state = GLOB.always_state)
/obj/item/toy/eightball/haunted/ui_state(mob/user)
return GLOB.observer_state
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/item/toy/eightball/haunted/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "EightBallVote", name, 400, 600, master_ui, state)
ui = new(user, src, "EightBallVote", name)
ui.open()
/obj/item/toy/eightball/haunted/ui_data(mob/user)
@@ -229,4 +231,4 @@
else
votes[selected_answer] += 1
voted[user.ckey] = selected_answer
. = TRUE
. = TRUE
+1
View File
@@ -15,6 +15,7 @@
attack_verb = list("struck", "beaten", "thwacked", "pulped")
total_mass = 5 //yeah this is a heavy thing, beating people with it while it's off is not going to do you any favors. (to curb stun-kill rampaging without it being on)
block_parry_data = /datum/block_parry_data/electrostaff
attack_speed = CLICK_CD_MELEE
var/obj/item/stock_parts/cell/cell = /obj/item/stock_parts/cell/high
var/on = FALSE
var/can_block_projectiles = FALSE //can't block guns
+3 -3
View File
@@ -110,7 +110,7 @@
. += "The safety is [safety ? "on" : "off"]."
if(reagents.total_volume)
. += "<span class='notice'>You can loose its <b>screws</b> to empty it.</span>"
. += "<span class='notice'>Alt-click to empty it.</span>"
/obj/item/extinguisher/proc/AttemptRefill(atom/target, mob/user)
if(istype(target, tanktype) && target.Adjacent(user))
@@ -230,7 +230,7 @@
repetition++
addtimer(CALLBACK(src, /obj/item/extinguisher/proc/move_chair, B, movementdirection, repetition), timer_seconds)
/obj/item/extinguisher/screwdriver_act(mob/user, obj/item/tool)
/obj/item/extinguisher/AltClick(mob/user)
if(!user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
return
EmptyExtinguisher(user)
@@ -244,7 +244,7 @@
var/turf/open/theturf = T
theturf.MakeSlippery(TURF_WET_WATER, min_wet_time = 10 SECONDS, wet_time_to_add = 5 SECONDS)
user.visible_message("[user] empties out \the [src] onto the floor using the release valve.", "<span class='info'>You quietly empty out \the [src] by loosing the release valve's screws.</span>")
user.visible_message("[user] empties out \the [src] onto the floor using the release valve.", "<span class='info'>You quietly empty out \the [src] by using its release valve.</span>")
//firebot assembly
/obj/item/extinguisher/attackby(obj/O, mob/user, params)
+3 -1
View File
@@ -13,10 +13,12 @@
slot_flags = ITEM_SLOT_BACK
attack_verb = list("attacked", "chopped", "cleaved", "torn", "cut")
hitsound = 'sound/weapons/bladeslice.ogg'
sharpness = IS_SHARP
sharpness = SHARP_EDGED
max_integrity = 200
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 30)
resistance_flags = FIRE_PROOF
wound_bonus = -15
bare_wound_bonus = 20
var/wielded = FALSE // track wielded status on item
/obj/item/fireaxe/Initialize()
+1
View File
@@ -131,6 +131,7 @@
/obj/item/flamethrower/analyzer_act(mob/living/user, obj/item/I)
if(ptank)
ptank.analyzer_act(user, I)
return TRUE
/obj/item/flamethrower/attack_self(mob/user)
+18 -1
View File
@@ -79,7 +79,7 @@
ADD_TRAIT(user, granted_trait, BOOK_TRAIT)
/obj/item/book/granter/trait/rifleman
name = "\proper the Neo-Russian Rifleman\'s Primer"
name = "The Neo-Russian Rifleman\'s Primer"
desc = "A book with stains of vodka and...blood? The back is hard to read, but says something about bolt-actions. Or pump-actions. Both, maybe."
oneuse = FALSE
granted_trait = TRAIT_FAST_PUMP
@@ -477,6 +477,23 @@
name = "empty scroll"
icon_state = "blankscroll"
/obj/item/book/granter/martial/krav_maga
martial = /datum/martial_art/krav_maga
name = "parchment scroll"
martialname = "krav maga"
desc = "A worn parchment scrap written in an ancient language. Somehow you can still understand the lessons!"
greet = "<span class='sciradio'>You have learned the ancient martial art of Krav Maga. You have special attacks with which to take down your foes.</span>"
icon = 'icons/obj/wizard.dmi'
icon_state ="scroll2"
remarks = list("Sweep the legs...", "Chop the throat...", "Punch the lungs...", "Get the gold...", "Where are my sick gloves..?")
/obj/item/book/granter/martial/krav_maga/onlearned(mob/living/carbon/user)
. = ..()
if(oneuse == TRUE)
desc = "It's completely blank."
name = "empty scroll"
icon_state = "blankscroll"
// I did not include mushpunch's grant, it is not a book and the item does it just fine.
+11 -1
View File
@@ -60,6 +60,14 @@
shrapnel_type = /obj/item/projectile/bullet/pellet/stingball/mega
shrapnel_radius = 12
/obj/item/grenade/stingbang/breaker
name = "breakbang"
shrapnel_type = /obj/item/projectile/bullet/pellet/stingball/breaker
/obj/item/grenade/stingbang/shred
name = "shredbang"
shrapnel_type = /obj/item/projectile/bullet/pellet/stingball/shred
/obj/item/grenade/stingbang/prime(mob/living/lanced_by)
if(iscarbon(loc))
var/mob/living/carbon/C = loc
@@ -116,9 +124,11 @@
/obj/item/grenade/primer/attack_self(mob/user)
. = ..()
if(active)
if(!user.CheckActionCooldown())
return
user.playsound_local(user, 'sound/misc/box_deploy.ogg', 50, TRUE)
rots++
user.changeNext_move(CLICK_CD_RAPID)
user.DelayNextAction(CLICK_CD_RAPID)
/obj/item/grenade/primer/prime(mob/living/lanced_by)
shrapnel_radius = round(rots / rots_per_mag)
+1 -1
View File
@@ -320,7 +320,7 @@
do_sparks(1, TRUE, src)
qdel(src)
/obj/item/restraints/legcuffs/beartrap/energy/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/restraints/legcuffs/beartrap/energy/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
Crossed(user) //honk
. = ..()
+12 -9
View File
@@ -225,6 +225,7 @@
throwforce = 10
w_class = WEIGHT_CLASS_TINY
obj_flags = UNIQUE_RENAME
wound_bonus = -10
var/chaplain_spawnable = TRUE
total_mass = TOTAL_MASS_MEDIEVAL_WEAPON
@@ -351,7 +352,7 @@
w_class = WEIGHT_CLASS_HUGE
slot_flags = ITEM_SLOT_BACK|ITEM_SLOT_BELT
block_chance = 30
sharpness = IS_SHARP
sharpness = SHARP_EDGED
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
@@ -451,7 +452,7 @@
w_class = WEIGHT_CLASS_BULKY
armour_penetration = 35
slot_flags = ITEM_SLOT_BACK
sharpness = IS_SHARP
sharpness = SHARP_EDGED
attack_verb = list("chopped", "sliced", "cut", "reaped")
/obj/item/nullrod/scythe/Initialize()
@@ -574,7 +575,7 @@
righthand_file = 'icons/mob/inhands/weapons/chainsaw_righthand.dmi'
w_class = WEIGHT_CLASS_HUGE
item_flags = ABSTRACT
sharpness = IS_SHARP
sharpness = SHARP_EDGED
attack_verb = list("sawed", "torn", "cut", "chopped", "diced")
hitsound = 'sound/weapons/chainsawhit.ogg'
total_mass = TOTAL_MASS_HAND_REPLACEMENT
@@ -593,7 +594,7 @@
name = "clown dagger"
desc = "Used for absolutely hilarious sacrifices."
hitsound = 'sound/items/bikehorn.ogg'
sharpness = IS_SHARP
sharpness = SHARP_EDGED
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
/obj/item/nullrod/pride_hammer
@@ -644,7 +645,7 @@
throw_speed = 4
throw_range = 7
throwforce = 30
sharpness = IS_SHARP
sharpness = SHARP_EDGED
attack_verb = list("enlightened", "redpilled")
/obj/item/nullrod/armblade
@@ -656,7 +657,9 @@
righthand_file = 'icons/mob/inhands/antag/changeling_righthand.dmi'
item_flags = ABSTRACT
w_class = WEIGHT_CLASS_HUGE
sharpness = IS_SHARP
sharpness = SHARP_EDGED
wound_bonus = -20
bare_wound_bonus = 25
total_mass = TOTAL_MASS_HAND_REPLACEMENT
/obj/item/nullrod/armblade/Initialize()
@@ -696,7 +699,7 @@
force = 15
block_chance = 40
slot_flags = ITEM_SLOT_BACK
sharpness = IS_BLUNT
sharpness = SHARP_NONE
hitsound = "swing_hit"
attack_verb = list("smashed", "slammed", "whacked", "thwacked")
icon = 'icons/obj/items_and_weapons.dmi'
@@ -751,7 +754,7 @@
name = "arrhythmic knife"
w_class = WEIGHT_CLASS_HUGE
desc = "They say fear is the true mind killer, but stabbing them in the head works too. Honour compels you to not sheathe it once drawn."
sharpness = IS_SHARP
sharpness = SHARP_EDGED
slot_flags = null
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
@@ -779,7 +782,7 @@
desc = "Holding this makes you look absolutely devilish."
attack_verb = list("poked", "impaled", "pierced", "jabbed")
hitsound = 'sound/weapons/bladeslice.ogg'
sharpness = IS_SHARP
sharpness = SHARP_EDGED
/obj/item/nullrod/egyptian
name = "egyptian staff"
@@ -38,6 +38,23 @@
if(!uses)
qdel(src)
/obj/item/implant/warp
name = "warp implant"
desc = "Saves your position somewhere, and then warps you back to it after five seconds."
icon_state = "warp"
uses = 15
/obj/item/implant/warp/activate()
. = ..()
uses--
imp_in.do_adrenaline(150, TRUE, 0, 0, TRUE, list(/datum/reagent/fermi/eigenstate = 1.2), "<span class='boldnotice'>You feel an internal prick as as the bluespace starts ramping up!</span>")
to_chat(imp_in, "<span class='notice'>You feel an internal prick as as the bluespace starts ramping up!</span>")
if(!uses)
qdel(src)
/obj/item/implanter/warp
name = "implanter (warp)"
imp_type = /obj/item/implant/warp
/obj/item/implant/emp
name = "emp implant"
@@ -10,7 +10,7 @@
/obj/item/implant/radio/activate()
. = ..()
// needs to be GLOB.deep_inventory_state otherwise it won't open
radio.ui_interact(usr, "main", null, FALSE, null, GLOB.deep_inventory_state)
radio.ui_interact(usr, state = GLOB.deep_inventory_state)
/obj/item/implant/radio/implant(mob/living/target, mob/user, silent = FALSE)
. = ..()
@@ -26,14 +26,15 @@
open_machine()
update_icon()
/obj/machinery/implantchair/ui_state(mob/user)
return GLOB.notcontained_state
/obj/machinery/implantchair/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/implantchair/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "implantchair", name, 375, 280, master_ui, state)
ui = new(user, src, "ImplantChair", name)
ui.open()
/obj/machinery/implantchair/ui_data()
var/list/data = list()
data["occupied"] = occupant ? 1 : 0
@@ -121,8 +122,6 @@
update_icon()
/obj/machinery/implantchair/container_resist(mob/living/user)
user.changeNext_move(CLICK_CD_BREAKOUT)
user.last_special = world.time + CLICK_CD_BREAKOUT
user.visible_message("<span class='notice'>You see [user] kicking against the door of [src]!</span>", \
"<span class='notice'>You lean on the back of [src] and start pushing the door open... (this will take about [DisplayTimeText(breakout_time)].)</span>", \
"<span class='italics'>You hear a metallic creaking from [src].</span>")
@@ -191,4 +190,4 @@
brainwash(C, objective)
message_admins("[ADMIN_LOOKUPFLW(user)] brainwashed [key_name_admin(C)] with objective '[objective]'.")
log_game("[key_name(user)] brainwashed [key_name(C)] with objective '[objective]'.")
return TRUE
return TRUE
+6 -3
View File
@@ -18,7 +18,7 @@
name = "fork"
desc = "Pointy."
icon_state = "fork"
force = 5
force = 4
w_class = WEIGHT_CLASS_TINY
throwforce = 0
throw_speed = 3
@@ -28,6 +28,7 @@
attack_verb = list("attacked", "stabbed", "poked")
hitsound = 'sound/weapons/bladeslice.ogg'
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30)
sharpness = SHARP_POINTY
var/datum/reagent/forkload //used to eat omelette
/obj/item/kitchen/fork/suicide_act(mob/living/carbon/user)
@@ -61,7 +62,7 @@
throw_speed = 4
throw_range = 6
embedding = list("pain_mult" = 2, "embed_chance" = 100, "fall_chance" = 0, "embed_chance_turf_mod" = 15)
sharpness = IS_SHARP
sharpness = SHARP_EDGED
/obj/item/kitchen/knife
name = "kitchen knife"
@@ -76,9 +77,11 @@
throw_range = 6
custom_materials = list(/datum/material/iron=12000)
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
sharpness = IS_SHARP_ACCURATE
sharpness = SHARP_POINTY
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
var/bayonet = FALSE //Can this be attached to a gun?
wound_bonus = -5
bare_wound_bonus = 10
custom_price = PRICE_NORMAL
/obj/item/kitchen/knife/Initialize()
+1 -1
View File
@@ -54,5 +54,5 @@
var/obj/item/tank/T = W
blow(T, user)
return
if (W.get_sharpness() || W.get_temperature() || is_pointed(W))
if (W.get_sharpness() || W.get_temperature())
burst()
+3 -1
View File
@@ -506,7 +506,9 @@
if(prob(50))
step(W, pick(GLOB.alldirs))
ADD_TRAIT(H, TRAIT_DISFIGURED, TRAIT_GENERIC)
H.bleed_rate = 5
for(var/i in H.bodyparts)
var/obj/item/bodypart/BP = i
BP.generic_bleedstacks += 5
H.gib_animation()
sleep(3)
H.adjustBruteLoss(1000) //to make the body super-bloody
+10 -4
View File
@@ -102,7 +102,7 @@
attack_verb_off = list("tapped", "poked")
throw_speed = 3
throw_range = 5
sharpness = IS_SHARP
sharpness = SHARP_EDGED
embedding = list("embed_chance" = 75, "impact_pain_mult" = 10)
armour_penetration = 35
item_flags = NEEDS_PERMIT | ITEM_CAN_PARRY
@@ -147,6 +147,12 @@
return NONE
return ..()
/obj/item/melee/transforming/energy/sword/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time)
. = ..()
if(parry_efficiency >= 80) // perfect parry
block_return[BLOCK_RETURN_REDIRECT_METHOD] = REDIRECT_METHOD_RETURN_TO_SENDER
. |= BLOCK_SHOULD_REDIRECT
/obj/item/melee/transforming/energy/sword/cyborg
sword_color = "red"
light_color = "#ff0000"
@@ -174,7 +180,7 @@
sword_color = null //stops icon from breaking when turned on.
hitcost = 75 //Costs more than a standard cyborg esword
w_class = WEIGHT_CLASS_NORMAL
sharpness = IS_SHARP
sharpness = SHARP_EDGED
light_color = "#40ceff"
tool_behaviour = TOOL_SAW
toolspeed = 0.7
@@ -249,7 +255,7 @@
throw_range = 1
w_class = WEIGHT_CLASS_BULKY//So you can't hide it in your pocket or some such.
var/datum/effect_system/spark_spread/spark_system
sharpness = IS_SHARP
sharpness = SHARP_EDGED
//Most of the other special functions are handled in their own files. aka special snowflake code so kewl
/obj/item/melee/transforming/energy/blade/Initialize()
@@ -285,7 +291,7 @@
attack_verb_off = list("tapped", "poked")
throw_speed = 3
throw_range = 5
sharpness = IS_SHARP
sharpness = SHARP_EDGED
embedding = list("embedded_pain_multiplier" = 6, "embed_chance" = 20, "embedded_fall_chance" = 60)
armour_penetration = 10
block_chance = 35
+10 -4
View File
@@ -19,6 +19,8 @@
slot_flags = ITEM_SLOT_BELT
force = 14
throwforce = 10
wound_bonus = 15
bare_wound_bonus = 10
reach = 2
w_class = WEIGHT_CLASS_NORMAL
attack_verb = list("flogged", "whipped", "lashed", "disciplined")
@@ -42,7 +44,7 @@
throwforce = 10
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("attacked", "impaled", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
sharpness = IS_SHARP
sharpness = SHARP_EDGED
total_mass = TOTAL_MASS_HAND_REPLACEMENT
/obj/item/melee/synthetic_arm_blade/Initialize()
@@ -62,7 +64,7 @@
throwforce = 15
w_class = WEIGHT_CLASS_BULKY
armour_penetration = 75
sharpness = IS_SHARP
sharpness = SHARP_EDGED
attack_verb = list("slashed", "cut")
hitsound = 'sound/weapons/rapierhit.ogg'
custom_materials = list(/datum/material/iron = 1000)
@@ -166,7 +168,7 @@
flags_1 = CONDUCT_1
obj_flags = UNIQUE_RENAME
w_class = WEIGHT_CLASS_BULKY
sharpness = IS_SHARP_ACCURATE //It cant be sharpend cook -_-
sharpness = SHARP_POINTY //It cant be sharpend cook -_-
attack_verb = list("stabs", "punctures", "pierces", "pokes")
hitsound = 'sound/weapons/rapierhit.ogg'
total_mass = 0.4
@@ -268,6 +270,8 @@
var/force_off // Damage when off - not stunning
var/weight_class_on // What is the new size class when turned on
wound_bonus = 15
/obj/item/melee/classic_baton/Initialize()
. = ..()
@@ -371,6 +375,7 @@
var/wait_desc = get_wait_description()
if(wait_desc)
to_chat(user, wait_desc)
return DISCARD_LAST_ACTION
/obj/item/melee/classic_baton/telescopic
name = "telescopic baton"
@@ -393,6 +398,7 @@
force_off = 0
weight_class_on = WEIGHT_CLASS_BULKY
total_mass = TOTAL_MASS_NORMAL_ITEM
bare_wound_bonus = 5
/obj/item/melee/classic_baton/telescopic/suicide_act(mob/user)
var/mob/living/carbon/human/H = user
@@ -621,7 +627,7 @@
to_chat(user, "<span class='warning'>[target] doesn't seem to want to get on [src]!</span>")
update_icon()
/obj/item/melee/roastingstick/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/melee/roastingstick/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
..()
if (held_sausage)
user.put_in_hands(held_sausage)
@@ -1,5 +1,5 @@
/obj/item/melee/transforming
sharpness = IS_SHARP
sharpness = SHARP_EDGED
var/active = FALSE
var/force_on = 30 //force when active
var/faction_bonus_force = 0 //Bonus force dealt against certain factions
@@ -84,4 +84,4 @@
/obj/item/melee/transforming/proc/clumsy_transform_effect(mob/living/user)
if(clumsy_check && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
to_chat(user, "<span class='warning'>You accidentally cut yourself with [src], like a doofus!</span>")
user.take_bodypart_damage(5,5)
user.take_bodypart_damage(5,5)
+2 -2
View File
@@ -58,7 +58,7 @@
if(T)
user.visible_message("[user] cleans \the [T] with [src].", "<span class='notice'>You clean \the [T] with [src].</span>")
clean(T)
user.changeNext_move(CLICK_CD_MELEE)
user.DelayNextAction(CLICK_CD_MELEE)
user.do_attack_animation(T, used_item = src)
if(istype(L))
L.adjustStaminaLossBuffered(stamusage)
@@ -128,4 +128,4 @@
return ..()
/obj/item/mop/advanced/cyborg
insertable = FALSE
insertable = FALSE
+27 -13
View File
@@ -24,6 +24,7 @@
var/max_occupant_weight = MOB_SIZE_SMALL //This is calculated from the mob sizes of occupants
var/entrance_name = "door" //name of the entrance to the item
var/escape_time = 200 //how long it takes for mobs above small sizes to escape (for small sizes, its randomly 1.5 to 2x this)
var/alternate_escape_time = 0 //how long it takes for mobs to escape when the entrance is open
var/load_time = 30 //how long it takes for mobs to be loaded into the pet carrier
var/has_lock_sprites = TRUE //whether to load the lock overlays or not
var/allows_hostiles = FALSE //does the pet carrier allow hostile entities to be held within it?
@@ -106,8 +107,9 @@
if(user == target)
to_chat(user, "<span class='warning'>Why would you ever do that?</span>")
return
if(ishostile(target) && (!allows_hostiles || istype(target, /mob/living/simple_animal/hostile/carp/cayenne)) || target.move_resist < MOVE_FORCE_VERY_STRONG) //don't allow goliaths into pet carriers, but let cayenne in!
if((ishostile(target) && (!allows_hostiles || !istype(target, /mob/living/simple_animal/hostile/carp/cayenne))) || target.move_resist >= MOVE_FORCE_VERY_STRONG) //don't allow goliaths into pet carriers, but let cayenne in!
to_chat(user, "<span class='warning'>You have a feeling you shouldn't keep this as a pet.</span>")
return
load_occupant(user, target)
/obj/item/pet_carrier/relaymove(mob/living/user, direction)
@@ -128,13 +130,18 @@
/obj/item/pet_carrier/container_resist(mob/living/user)
//don't do the whole resist timer thing if it's open!
if(open)
loc.visible_message("<span class='notice'>[user] climbs out of [src]!</span>", \
"<span class='warning'>[user] jumps out of [src]!</span>")
remove_occupant(user)
return
if(alternate_escape_time > 0)
loc.visible_message("<span class='notice'>The [src] begins to shake!</span>")
if(do_after(user, alternate_escape_time, target = user))
loc.visible_message("<span class='notice'>[user] jumps out of [src]</span>")
remove_occupant(user)
return
else //instant escape, different message
loc.visible_message("<span class='notice'>[user] climbs out of [src]!</span>", \
"<span class='warning'>[user] jumps out of [src]!</span>")
remove_occupant(user)
return
user.changeNext_move(CLICK_CD_BREAKOUT)
user.last_special = world.time + CLICK_CD_BREAKOUT
if(user.mob_size <= MOB_SIZE_SMALL)
to_chat(user, "<span class='notice'>You begin to try escaping the [src] and start fumbling for the lock switch... (This will take some time.)</span>")
to_chat(loc, "<span class='warning'>You see [user] attempting to unlock the [src]!</span>")
@@ -147,7 +154,7 @@
update_icon()
else
loc.visible_message("<span class='warning'>[src] starts rattling as something pushes against the [entrance_name]!</span>", null, null, null, user)
to_chat(user, "<span class='notice'>You start pushing out of [src]... (This will take about 20 seconds.)</span>")
to_chat(user, "<span class='notice'>You start pushing out of [src]... (This will take about [escape_time/10] seconds.)</span>")
if(!do_after(user, escape_time, target = user) || open || !locked || !(user in occupants))
return
loc.visible_message("<span class='warning'>[user] shoves out of [src]!</span>", null, null, null, user)
@@ -180,21 +187,22 @@
/obj/item/pet_carrier/proc/load_occupant(mob/living/user, mob/living/target)
if(pet_carrier_full(src))
to_chat(user, "<span class='warning'>[src] is already carrying too much!</span>")
return
return FALSE
user.visible_message("<span class='notice'>[user] starts loading [target] into [src].</span>", \
"<span class='notice'>You start loading [target] into [src]...</span>", null, null, target)
to_chat(target, "<span class='userdanger'>[user] starts loading you into [user.p_their()] [name]!</span>")
if(!do_mob(user, target, load_time))
return
return FALSE
if(target in occupants)
return
return FALSE
if(pet_carrier_full(src)) //Run the checks again, just in case
to_chat(user, "<span class='warning'>[src] is already carrying too much!</span>")
return
return FALSE
user.visible_message("<span class='notice'>[user] loads [target] into [src]!</span>", \
"<span class='notice'>You load [target] into [src].</span>", null, null, target)
to_chat(target, "<span class='userdanger'>[user] loads you into [user.p_their()] [name]!</span>")
add_occupant(target)
return TRUE
/obj/item/pet_carrier/proc/add_occupant(mob/living/occupant)
if(occupant in occupants || !istype(occupant))
@@ -230,7 +238,8 @@
allows_hostiles = TRUE //can fit hostile creatures, with the move resist restrictions in place, this means they still cannot take things like legions/goliaths/etc regardless
has_lock_sprites = FALSE //jar doesn't show the regular lock overlay
custom_materials = list(/datum/material/glass = 1000, /datum/material/bluespace = 600)
escape_time = 10 //half the time of a bluespace bodybag
escape_time = 200 //equal to the time of a bluespace bodybag
alternate_escape_time = 100
var/datum/gas_mixture/occupant_gas_supply
/obj/item/pet_carrier/bluespace/update_icon_state()
@@ -271,10 +280,15 @@
REMOVE_TRAIT(occupant, TRAIT_NOBREATH, "bluespace_container_no_breath")
REMOVE_TRAIT(occupant, TRAIT_RESISTHIGHPRESSURE, "bluespace_container_resist_high_pressure")
REMOVE_TRAIT(occupant, TRAIT_RESISTLOWPRESSURE, "bluespace_container_resist_low_pressure")
name = initial(name)
/obj/item/pet_carrier/bluespace/return_air()
if(!occupant_gas_supply)
occupant_gas_supply = new
return occupant_gas_supply
/obj/item/pet_carrier/bluespace/load_occupant(mob/living/user, mob/living/target)
if(..())
name = "[initial(name)] ([target])"
#undef pet_carrier_full
+1 -1
View File
@@ -9,7 +9,7 @@
w_class = WEIGHT_CLASS_BULKY
attack_verb = list("attacked", "impaled", "pierced")
hitsound = 'sound/weapons/bladeslice.ogg'
sharpness = IS_SHARP
sharpness = SHARP_EDGED
max_integrity = 200
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 30)
resistance_flags = FIRE_PROOF
+22
View File
@@ -8,6 +8,7 @@
resistance_flags = FLAMMABLE
var/list/squeak_override //Weighted list; If you want your plush to have different squeak sounds use this
var/stuffed = TRUE //If the plushie has stuffing in it
var/unstuffable = FALSE //for plushies that can't be stuffed
var/obj/item/grenade/grenade //You can remove the stuffing from a plushie and add a grenade to it for *nefarious uses*
//--love ~<3--
gender = NEUTER
@@ -174,6 +175,9 @@
/obj/item/toy/plush/attackby(obj/item/I, mob/living/user, params)
if(I.get_sharpness())
if(!grenade)
if(unstuffable)
to_chat(user, "<span class='notice'>Nothing to do here.</span>")
return
if(!stuffed)
to_chat(user, "<span class='warning'>You already murdered it!</span>")
return
@@ -187,6 +191,13 @@
grenade = null
return
if(istype(I, /obj/item/grenade))
if(unstuffable)
to_chat(user, "<span class='warning'>No... you should destroy it now!</span>")
sleep(10)
if(QDELETED(user) || QDELETED(src))
return
SEND_SOUND(user, 'sound/weapons/armbomb.ogg')
return
if(stuffed)
to_chat(user, "<span class='warning'>You need to remove some stuffing first!</span>")
return
@@ -743,3 +754,14 @@ GLOBAL_LIST_INIT(valid_plushie_paths, valid_plushie_paths())
attack_verb = list("headbutt", "scritched", "bit")
squeak_override = list('modular_citadel/sound/voice/nya.ogg' = 1)
can_random_spawn = FALSE
/obj/item/toy/plush/hairball
name = "Hairball"
desc = "A bundle of undigested fibers and scales. Yuck."
icon_state = "Hairball"
unstuffable = TRUE
young = TRUE // Your own mouth-baby.
squeak_override = list('sound/misc/splort.ogg'=1)
attack_verb = list("sploshed", "splorted", "slushed")
can_random_spawn = FALSE
+2 -3
View File
@@ -14,12 +14,11 @@
w_class = WEIGHT_CLASS_NORMAL
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 40)
resistance_flags = FIRE_PROOF
click_delay = CLICK_CD_MELEE * 1.5
attack_speed = CLICK_CD_MELEE * 1.5
var/fisto_setting = 1
var/gasperfist = 3
var/obj/item/tank/internals/tank = null //Tank used for the gauntlet's piston-ram.
/obj/item/melee/powerfist/examine(mob/user)
. = ..()
if(!in_range(user, src))
@@ -98,7 +97,7 @@
target.visible_message("<span class='danger'>[user]'s powerfist lets out a weak hiss as [user.p_they()] punch[user.p_es()] [target.name]!</span>", \
"<span class='userdanger'>[user]'s punch strikes with force!</span>")
return
target.apply_damage(totalitemdamage * fisto_setting, BRUTE)
target.apply_damage(totalitemdamage * fisto_setting, BRUTE, wound_bonus = -25*fisto_setting**2)
target.visible_message("<span class='danger'>[user]'s powerfist lets out a loud hiss as [user.p_they()] punch[user.p_es()] [target.name]!</span>", \
"<span class='userdanger'>You cry out in pain as [user]'s punch flings you backwards!</span>")
new /obj/effect/temp_visual/kinetic_blast(target.loc)
+18 -2
View File
@@ -747,7 +747,7 @@
/obj/item/weapon/gripper
name = "engineering gripper"
desc = "A simple grasping tool for interacting with various engineering related items, such as circuits, gas tanks and conveyer belts. Alt click to drop instead of use."
desc = "A simple grasping tool for interacting with various engineering related items, such as circuits, gas tanks, conveyer belts and more. Alt click to drop instead of use."
icon = 'icons/obj/device.dmi'
icon_state = "gripper"
@@ -784,7 +784,7 @@
wrapped = null
return ..()
/obj/item/weapon/gripper/afterattack(var/atom/target, var/mob/living/silicon/robot/user, proximity, params)
/obj/item/weapon/gripper/pre_attack(var/atom/target, var/mob/living/silicon/robot/user, proximity, params)
if(!proximity)
return
@@ -839,6 +839,19 @@
/obj/item/survivalcapsule
)
/obj/item/weapon/gripper/medical
name = "medical gripper"
desc = "A simple grasping tool for interacting with medical equipment, such as beakers, blood bags, chem bags and more. Alt click to drop instead of use."
icon_state = "gripper_medical"
can_hold = list(
/obj/item/storage/bag/bio,
/obj/item/storage/bag/chemistry,
/obj/item/storage/pill_bottle,
/obj/item/reagent_containers/glass,
/obj/item/reagent_containers/pill,
/obj/item/reagent_containers/blood
)
/obj/item/gun/energy/plasmacutter/cyborg
name = "cyborg plasma cutter"
desc = "A basic variation of the plasma cutter, compressed into a cyborg chassis. Less effective than normal plasma cutters."
@@ -921,6 +934,9 @@
icon_state = "data_1"
/**********************************************************************
Dogborg stuff
***********************************************************************/
///Mere cosmetic dogborg items, remnants of what were once the most annoying cyborg modules.
/obj/item/dogborg_tongue
name = "synthetic tongue"
@@ -6,21 +6,24 @@
desc = "Protected by FRM."
icon = 'icons/obj/module.dmi'
icon_state = "cyborg_upgrade"
w_class = WEIGHT_CLASS_SMALL
var/locked = FALSE
var/installed = 0
var/require_module = 0
var/list/module_type
/// Bitflags listing module compatibility. Used in the exosuit fabricator for creating sub-categories.
var/module_flags = NONE
// if true, is not stored in the robot to be ejected
// if module is reset
var/one_use = FALSE
/obj/item/borg/upgrade/proc/action(mob/living/silicon/robot/R, user = usr)
if(R.stat == DEAD)
to_chat(user, "<span class='notice'>[src] will not function on a deceased cyborg.</span>")
to_chat(user, "<span class='warning'>[src] will not function on a deceased cyborg.</span>")
return FALSE
if(module_type && !is_type_in_list(R.module, module_type))
to_chat(R, "Upgrade mounting error! No suitable hardpoint detected!")
to_chat(user, "There's no mounting point for the module!")
to_chat(R, "<span class='alert'>Upgrade mounting error! No suitable hardpoint detected.</span>")
to_chat(user, "<span class='warning'>There's no mounting point for the module!</span>")
return FALSE
return TRUE
@@ -37,7 +40,7 @@
one_use = TRUE
/obj/item/borg/upgrade/rename/attack_self(mob/user)
heldname = stripped_input(user, "Enter new robot name", "Cyborg Reclassification", heldname, MAX_NAME_LEN)
heldname = sanitize_name(stripped_input(user, "Enter new robot name", "Cyborg Reclassification", heldname, MAX_NAME_LEN))
/obj/item/borg/upgrade/rename/action(mob/living/silicon/robot/R)
. = ..()
@@ -95,6 +98,7 @@
desc = "Used to cool a mounted energy-based firearm, increasing the potential current in it and thus its recharge rate."
icon_state = "cyborg_upgrade3"
require_module = 1
module_flags = BORG_MODULE_SECURITY
/obj/item/borg/upgrade/disablercooler/action(mob/living/silicon/robot/R, user = usr)
. = ..()
@@ -147,6 +151,7 @@
icon_state = "cyborg_upgrade3"
require_module = 1
module_type = list(/obj/item/robot_module/miner)
module_flags = BORG_MODULE_MINER
/obj/item/borg/upgrade/ddrill/action(mob/living/silicon/robot/R, user = usr)
. = ..()
@@ -207,6 +212,7 @@
icon_state = "cyborg_upgrade3"
require_module = 1
module_type = list(/obj/item/robot_module/butler)
module_flags = BORG_MODULE_JANITOR
/obj/item/borg/upgrade/tboh/action(mob/living/silicon/robot/R)
. = ..()
@@ -234,6 +240,7 @@
icon_state = "cyborg_upgrade3"
require_module = 1
module_type = list(/obj/item/robot_module/butler)
module_flags = BORG_MODULE_JANITOR
/obj/item/borg/upgrade/amop/action(mob/living/silicon/robot/R)
. = ..()
@@ -241,9 +248,9 @@
for(var/obj/item/mop/cyborg/M in R.module.modules)
R.module.remove_module(M, TRUE)
var/obj/item/mop/advanced/cyborg/A = new /obj/item/mop/advanced/cyborg(R.module)
R.module.basic_modules += A
R.module.add_module(A, FALSE, TRUE)
var/obj/item/mop/advanced/cyborg/A = new /obj/item/mop/advanced/cyborg(R.module)
R.module.basic_modules += A
R.module.add_module(A, FALSE, TRUE)
/obj/item/borg/upgrade/amop/deactivate(mob/living/silicon/robot/R, user = usr)
. = ..()
@@ -283,6 +290,7 @@
resistance_flags = LAVA_PROOF | FIRE_PROOF
require_module = 1
module_type = list(/obj/item/robot_module/miner)
module_flags = BORG_MODULE_MINER
/obj/item/borg/upgrade/lavaproof/action(mob/living/silicon/robot/R, user = usr)
. = ..()
@@ -402,6 +410,7 @@
module_type = list(/obj/item/robot_module/medical,
/obj/item/robot_module/syndicate_medical)
var/list/additional_reagents = list()
module_flags = BORG_MODULE_MEDICAL
/obj/item/borg/upgrade/hypospray/action(mob/living/silicon/robot/R, user = usr)
. = ..()
@@ -471,6 +480,7 @@
require_module = 1
module_type = list(/obj/item/robot_module/medical,
/obj/item/robot_module/syndicate_medical)
module_flags = BORG_MODULE_MEDICAL
/obj/item/borg/upgrade/processor/action(mob/living/silicon/robot/R, user = usr)
. = ..()
@@ -578,6 +588,7 @@
icon_state = "borg_BS_RPED"
require_module = TRUE
module_type = list(/obj/item/robot_module/engineering, /obj/item/robot_module/saboteur)
module_flags = BORG_MODULE_ENGINEERING
/obj/item/borg/upgrade/rped/action(mob/living/silicon/robot/R, user = usr)
. = ..()
@@ -612,8 +623,8 @@
icon = 'icons/obj/device.dmi'
icon_state = "pinpointer_crew"
require_module = TRUE
module_type = list(/obj/item/robot_module/medical,
/obj/item/robot_module/syndicate_medical)
module_type = list(/obj/item/robot_module/medical, /obj/item/robot_module/syndicate_medical)
module_flags = BORG_MODULE_MEDICAL
/obj/item/borg/upgrade/pinpointer/action(mob/living/silicon/robot/R, user = usr)
. = ..()
+1 -1
View File
@@ -39,7 +39,7 @@
I.force = clamp(I.force + increment, 0, max)
user.visible_message("<span class='notice'>[user] sharpens [I] with [src]!</span>", "<span class='notice'>You sharpen [I], making it much more deadly than before.</span>")
I.sharpness = IS_SHARP_ACCURATE
I.sharpness = SHARP_POINTY
I.throwforce = clamp(I.throwforce + increment, 0, max)
I.name = "[prefix] [I.name]"
name = "worn out [name]"
+2 -2
View File
@@ -106,8 +106,8 @@
var/disarming = (target_downed && (shield_flags & SHIELD_BASH_GROUND_SLAM_DISARM)) || (shield_flags & SHIELD_BASH_ALWAYS_DISARM) || (wallhit && (shield_flags & SHIELD_BASH_WALL_DISARM))
var/knockdown = !target_downed && ((shield_flags & SHIELD_BASH_ALWAYS_KNOCKDOWN) || (wallhit && (shield_flags & SHIELD_BASH_WALL_KNOCKDOWN)))
if(shieldbash_stagger_duration || knockdown)
target.visible_message("<span class='warning'>[target] is knocked [knockdown? "to the floor" : "off balanace"]!</span>",
"<span class='userdanger'>You are knocked [knockdown? "to the floor" : "off balanace"]!</span>")
target.visible_message("<span class='warning'>[target] is knocked [knockdown? "to the floor" : "off balance"]!</span>",
"<span class='userdanger'>You are knocked [knockdown? "to the floor" : "off balance"]!</span>")
if(knockdown)
target.KnockToFloor(disarming)
else if(disarming)
+1 -4
View File
@@ -31,10 +31,7 @@
to_chat(user, "<span class='notice'>You slice off [src]'s uneven chunks of aluminium and scorch marks.</span>")
return TRUE
/obj/item/target/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
/obj/item/target/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(pinnedLoc)
pinnedLoc.removeTarget(user)
+24 -7
View File
@@ -7,11 +7,13 @@
icon_state = "large"
w_class = WEIGHT_CLASS_TINY
item_flags = DROPDEL
sharpness = SHARP_EDGED
/obj/item/shrapnel/stingball // stingbang grenades
name = "stingball"
embedding = list(embed_chance=90, fall_chance=3, jostle_chance=7, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.7, pain_mult=5, jostle_pain_mult=6, rip_time=15, embed_chance_turf_mod=-100)
icon_state = "tiny"
sharpness = SHARP_NONE
/obj/item/shrapnel/bullet // bullets
name = "bullet"
@@ -28,21 +30,24 @@
/obj/item/projectile/bullet/shrapnel
name = "flying shrapnel shard"
damage = 9
range = 10
damage = 14
range = 20
armour_penetration = -30
dismemberment = 5
ricochets_max = 2
ricochet_chance = 40
ricochet_chance = 70
shrapnel_type = /obj/item/shrapnel
ricochet_incidence_leeway = 60
sharpness = SHARP_EDGED
wound_bonus = 40
/obj/item/projectile/bullet/shrapnel/mega
name = "flying shrapnel hunk"
range = 25
dismemberment = 10
ricochets_max = 4
ricochet_chance = 90
range = 45
dismemberment = 15
ricochets_max = 6
ricochet_chance = 130
ricochet_incidence_leeway = 0
ricochet_decay_chance = 0.9
/obj/item/projectile/bullet/pellet/stingball
@@ -62,3 +67,15 @@
name = "megastingball pellet"
ricochets_max = 6
ricochet_chance = 110
/obj/item/projectile/bullet/pellet/stingball/breaker
name = "breakbang pellet"
damage = 10
wound_bonus = 40
sharpness = SHARP_NONE
/obj/item/projectile/bullet/pellet/stingball/shred
name = "shredbang pellet"
damage = 10
wound_bonus = 30
sharpness = SHARP_EDGED
-1
View File
@@ -40,4 +40,3 @@
user.visible_message("<span class='warning'>[user] waves around \the \"[label]\" sign.</span>")
else
user.visible_message("<span class='warning'>[user] waves around blank sign.</span>")
user.changeNext_move(CLICK_CD_MELEE)
+4 -2
View File
@@ -15,13 +15,15 @@
custom_materials = list(/datum/material/iron=1150, /datum/material/glass=2075)
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("attacked", "poked", "jabbed", "torn", "gored")
sharpness = IS_SHARP
sharpness = SHARP_EDGED
max_integrity = 200
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30)
var/obj/item/grenade/explosive = null
var/war_cry = "AAAAARGH!!!"
var/icon_prefix = "spearglass"
var/wielded = FALSE // track wielded status on item
wound_bonus = -15
bare_wound_bonus = 15
/obj/item/spear/Initialize()
. = ..()
@@ -177,7 +179,7 @@
custom_materials = null
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("attacked", "poked", "jabbed", "torn", "gored")
sharpness = IS_SHARP
sharpness = SHARP_EDGED
icon_prefix = "bone_spear"
/obj/item/spear/bonespear/ComponentInitialize()
+1 -2
View File
@@ -74,8 +74,7 @@
/obj/item/stack/sheet/bluespace_crystal/attack_self(mob/user)// to prevent the construction menu from ever happening
to_chat(user, "<span class='warning'>You cannot crush the polycrystal in-hand, try breaking one off.</span>")
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/stack/sheet/bluespace_crystal/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/stack/sheet/bluespace_crystal/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(user.get_inactive_held_item() == src)
if(zero_amount())
return
+170 -61
View File
@@ -15,11 +15,20 @@
var/self_delay = 50
var/other_delay = 0
var/repeating = FALSE
/// How much brute we heal per application
var/heal_brute
/// How much burn we heal per application
var/heal_burn
/// How much we reduce bleeding per application on cut wounds
var/stop_bleeding
/// How much sanitization to apply to burns on application
var/sanitization
/// How much we add to flesh_healing for burn wounds on application
var/flesh_regeneration
/obj/item/stack/medical/attack(mob/living/M, mob/user)
. = ..()
try_heal(M, user)
INVOKE_ASYNC(src, .proc/try_heal, M, user)
/obj/item/stack/medical/proc/try_heal(mob/living/M, mob/user, silent = FALSE)
if(!M.can_inject(user, TRUE))
@@ -70,8 +79,9 @@
icon_state = "brutepack"
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
var/heal_brute = 20
self_delay = 20
heal_brute = 40
self_delay = 40
other_delay = 20
grind_results = list(/datum/reagent/medicine/styptic_powder = 10)
/obj/item/stack/medical/bruise_pack/one
@@ -95,7 +105,8 @@
M.heal_bodypart_damage((heal_brute/2))
return TRUE
if(iscarbon(M))
return heal_carbon(M, user, heal_brute, 0)
return heal_carbon(M, user, heal_brute, heal_burn)
to_chat(user, "<span class='warning'>You can't heal [M] with \the [src]!</span>")
to_chat(user, "<span class='notice'>You can't heal [M] with the \the [src]!</span>")
/obj/item/stack/medical/bruise_pack/suicide_act(mob/user)
@@ -104,24 +115,51 @@
/obj/item/stack/medical/gauze
name = "medical gauze"
desc = "A roll of elastic cloth that is extremely effective at stopping bleeding, heals minor wounds."
desc = "A roll of elastic cloth, perfect for stabilizing all kinds of wounds, from cuts and burns to broken bones."
gender = PLURAL
singular_name = "medical gauze"
icon_state = "gauze"
var/stop_bleeding = 1800
var/heal_brute = 5
self_delay = 10
heal_brute = 5
self_delay = 50
other_delay = 20
amount = 10
max_amount = 10
absorption_rate = 0.25
absorption_capacity = 5
splint_factor = 0.35
custom_price = PRICE_REALLY_CHEAP
/obj/item/stack/medical/gauze/heal(mob/living/M, mob/user)
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(!H.bleedsuppress && H.bleed_rate) //so you can't stack bleed suppression
H.suppress_bloodloss(stop_bleeding)
to_chat(user, "<span class='notice'>You stop the bleeding of [M]!</span>")
H.adjustBruteLoss(-(heal_brute))
return TRUE
to_chat(user, "<span class='notice'>You can not use \the [src] on [M]!</span>")
// gauze is only relevant for wounds, which are handled in the wounds themselves
/obj/item/stack/medical/gauze/try_heal(mob/living/M, mob/user, silent)
var/obj/item/bodypart/limb = M.get_bodypart(check_zone(user.zone_selected))
if(!limb)
to_chat(user, "<span class='notice'>There's nothing there to bandage!</span>")
return
if(!LAZYLEN(limb.wounds))
to_chat(user, "<span class='notice'>There's no wounds that require bandaging on [user==M ? "your" : "[M]'s"] [limb.name]!</span>") // good problem to have imo
return
var/gauzeable_wound = FALSE
for(var/i in limb.wounds)
var/datum/wound/woundies = i
if(woundies.wound_flags & ACCEPTS_GAUZE)
gauzeable_wound = TRUE
break
if(!gauzeable_wound)
to_chat(user, "<span class='notice'>There's no wounds that require bandaging on [user==M ? "your" : "[M]'s"] [limb.name]!</span>") // good problem to have imo
return
if(limb.current_gauze && (limb.current_gauze.absorption_capacity * 0.8 > absorption_capacity)) // ignore if our new wrap is < 20% better than the current one, so someone doesn't bandage it 5 times in a row
to_chat(user, "<span class='warning'>The bandage currently on [user==M ? "your" : "[M]'s"] [limb.name] is still in good condition!</span>")
return
user.visible_message("<span class='warning'>[user] begins wrapping the wounds on [M]'s [limb.name] with [src]...</span>", "<span class='warning'>You begin wrapping the wounds on [user == M ? "your" : "[M]'s"] [limb.name] with [src]...</span>")
if(!do_after(user, (user == M ? self_delay : other_delay), target=M))
return
user.visible_message("<span class='green'>[user] applies [src] to [M]'s [limb.name].</span>", "<span class='green'>You bandage the wounds on [user == M ? "yourself" : "[M]'s"] [limb.name].</span>")
limb.apply_gauze(src)
/obj/item/stack/medical/gauze/attackby(obj/item/I, mob/user, params)
if(I.tool_behaviour == TOOL_WIRECUTTER || I.get_sharpness())
@@ -133,6 +171,14 @@
"<span class='notice'>You cut [src] into pieces of cloth with [I].</span>", \
"<span class='italics'>You hear cutting.</span>")
use(2)
else if(I.is_drainable() && I.reagents.has_reagent(/datum/reagent/space_cleaner/sterilizine))
if(!I.reagents.has_reagent(/datum/reagent/space_cleaner/sterilizine, 10))
to_chat(user, "<span class='warning'>There's not enough sterilizine in [I] to sterilize [src]!</span>")
return
user.visible_message("<span class='notice'>[user] pours the contents of [I] onto [src], sterilizing it.</span>", "<span class='notice'>You pour the contents of [I] onto [src], sterilizing it.</span>")
I.reagents.remove_reagent(/datum/reagent/space_cleaner/sterilizine, 10)
new /obj/item/stack/medical/gauze/adv/one(user.drop_location())
use(1)
else
return ..()
@@ -143,15 +189,22 @@
/obj/item/stack/medical/gauze/improvised
name = "improvised gauze"
singular_name = "improvised gauze"
desc = "A roll of cloth roughly cut from something that can stop bleeding, but does not heal wounds."
stop_bleeding = 900
heal_brute = 0
desc = "A roll of cloth roughly cut from something that does a decent job of stabilizing wounds, but less efficiently than real medical gauze."
self_delay = 60
other_delay = 30
absorption_rate = 0.15
absorption_capacity = 4
/obj/item/stack/medical/gauze/adv
name = "sterilized medical gauze"
desc = "A roll of elastic sterilized cloth that is extremely effective at stopping bleeding, heals minor wounds and cleans them."
singular_name = "sterilized medical gauze"
self_delay = 5
desc = "A roll of elastic sterilized cloth that is extremely effective at stopping bleeding and covering burns."
heal_brute = 6
self_delay = 45
other_delay = 15
absorption_rate = 0.4
absorption_capacity = 6
/obj/item/stack/medical/gauze/adv/one
amount = 1
@@ -161,38 +214,9 @@
is_cyborg = 1
cost = 250
/obj/item/stack/medical/ointment
name = "ointment"
desc = "Used to treat those nasty burn wounds."
gender = PLURAL
singular_name = "ointment"
icon_state = "ointment"
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
var/heal_burn = 20
self_delay = 20
grind_results = list(/datum/reagent/medicine/silver_sulfadiazine = 10)
/obj/item/stack/medical/ointment/one
amount = 1
/obj/item/stack/medical/ointment/heal(mob/living/M, mob/user)
if(M.stat == DEAD)
to_chat(user, "<span class='notice'> [M] is dead. You can not help [M.p_them()]!</span>")
return
if(iscarbon(M))
return heal_carbon(M, user, 0, heal_burn)
if(AmBloodsucker(M))
return
to_chat(user, "<span class='notice'>You can't heal [M] with the \the [src]!</span>")
/obj/item/stack/medical/ointment/suicide_act(mob/living/user)
user.visible_message("<span class='suicide'>[user] is squeezing \the [src] into [user.p_their()] mouth! [user.p_do(TRUE)]n't [user.p_they()] know that stuff is toxic?</span>")
return TOXLOSS
/obj/item/stack/medical/suture
name = "suture"
desc = "Sterile sutures used to seal up cuts and lacerations."
desc = "Basic sterile sutures used to seal up cuts and lacerations and stop bleeding."
gender = PLURAL
singular_name = "suture"
icon_state = "suture"
@@ -201,9 +225,17 @@
amount = 15
max_amount = 15
repeating = TRUE
var/heal_brute = 10
heal_brute = 10
stop_bleeding = 0.6
grind_results = list(/datum/reagent/medicine/spaceacillin = 2)
/obj/item/stack/medical/suture/emergency
name = "emergency suture"
desc = "A value pack of cheap sutures, not very good at repairing damage, but still decent at stopping bleeding."
heal_brute = 5
amount = 5
max_amount = 5
/obj/item/stack/medical/suture/one
amount = 1
@@ -233,10 +265,39 @@
to_chat(user, "<span class='notice'>[M] is at full health.</span>")
return FALSE
user.visible_message("<span class='green'>[user] applies \the [src] on [M].</span>", "<span class='green'>You apply \the [src] on [M].</span>")
M.heal_bodypart_damage(heal_brute)
return TRUE
return heal_carbon(M, user, heal_brute, heal_burn)
to_chat(user, "<span class='warning'>You can't heal [M] with the \the [src]!</span>")
to_chat(user, "<span class='warning'>You can't heal [M] with \the [src]!</span>")
/obj/item/stack/medical/ointment
name = "ointment"
desc = "Basic burn ointment, rated effective for second degree burns with proper bandaging, though it's still an effective stabilizer for worse burns. Not terribly good at outright healing burns though."
gender = PLURAL
singular_name = "ointment"
icon_state = "ointment"
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
amount = 12
max_amount = 12
self_delay = 40
other_delay = 20
heal_burn = 5
flesh_regeneration = 2.5
sanitization = 0.3
grind_results = list(/datum/reagent/medicine/kelotane = 10)
/obj/item/stack/medical/ointment/heal(mob/living/M, mob/user)
if(M.stat == DEAD)
to_chat(user, "<span class='warning'>[M] is dead! You can not help [M.p_them()].</span>")
return
if(iscarbon(M))
return heal_carbon(M, user, heal_brute, heal_burn)
to_chat(user, "<span class='warning'>You can't heal [M] with \the [src]!</span>")
/obj/item/stack/medical/ointment/suicide_act(mob/living/user)
user.visible_message("<span class='suicide'>[user] is squeezing \the [src] into [user.p_their()] mouth! [user.p_do(TRUE)]n't [user.p_they()] know that stuff is toxic?</span>")
return TOXLOSS
/obj/item/stack/medical/mesh
name = "regenerative mesh"
@@ -248,8 +309,10 @@
other_delay = 10
amount = 15
max_amount = 15
heal_burn = 10
repeating = TRUE
var/heal_burn = 10
sanitization = 0.75
flesh_regeneration = 3
var/is_open = TRUE ///This var determines if the sterile packaging of the mesh has been opened.
grind_results = list(/datum/reagent/medicine/spaceacillin = 2)
@@ -292,8 +355,8 @@
to_chat(user, "<span class='warning'>[M] is dead! You can not help [M.p_them()].</span>")
return
if(iscarbon(M))
return heal_carbon(M, user, 0, heal_burn)
to_chat(user, "<span class='warning'>You can't heal [M] with the \the [src]!</span>")
return heal_carbon(M, user, heal_brute, heal_burn)
to_chat(user, "<span class='warning'>You can't heal [M] with \the [src]!</span>")
/obj/item/stack/medical/mesh/try_heal(mob/living/M, mob/user, silent = FALSE)
@@ -308,7 +371,7 @@
return
. = ..()
/obj/item/stack/medical/mesh/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/stack/medical/mesh/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(!is_open & user.get_inactive_held_item() == src)
to_chat(user, "<span class='warning'>You need to open [src] first.</span>")
return
@@ -323,6 +386,52 @@
return
. = ..()
/obj/item/stack/medical/bone_gel
name = "bone gel"
singular_name = "bone gel"
desc = "A potent medical gel that, when applied to a damaged bone in a proper surgical setting, triggers an intense melding reaction to repair the wound. Can be directly applied alongside surgical sticky tape to a broken bone in dire circumstances, though this is very harmful to the patient and not recommended."
icon = 'icons/obj/surgery.dmi'
icon_state = "bone-gel"
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
amount = 4
self_delay = 20
grind_results = list(/datum/reagent/medicine/bicaridine = 10)
novariants = TRUE
/obj/item/stack/medical/bone_gel/attack(mob/living/M, mob/user)
to_chat(user, "<span class='warning'>Bone gel can only be used on fractured limbs while aggressively holding someone!</span>")
return
/obj/item/stack/medical/bone_gel/suicide_act(mob/user)
if(iscarbon(user))
var/mob/living/carbon/C = user
C.visible_message("<span class='suicide'>[C] is squirting all of \the [src] into [C.p_their()] mouth! That's not proper procedure! It looks like [C.p_theyre()] trying to commit suicide!</span>")
if(do_after(C, 2 SECONDS))
C.emote("scream")
for(var/i in C.bodyparts)
var/obj/item/bodypart/bone = i
var/datum/wound/blunt/severe/oof_ouch = new
oof_ouch.apply_wound(bone)
var/datum/wound/blunt/critical/oof_OUCH = new
oof_OUCH.apply_wound(bone)
for(var/i in C.bodyparts)
var/obj/item/bodypart/bone = i
bone.receive_damage(brute=60)
use(1)
return (BRUTELOSS)
else
C.visible_message("<span class='suicide'>[C] screws up like an idiot and still dies anyway!</span>")
return (BRUTELOSS)
/obj/item/stack/medical/bone_gel/cyborg
custom_materials = null
is_cyborg = 1
cost = 250
/obj/item/stack/medical/aloe
name = "aloe cream"
desc = "A healing paste you can apply on wounds."
@@ -355,4 +464,4 @@
M.heal_bodypart_damage(heal, heal)
return TRUE
to_chat(user, "<span class='warning'>You can't heal [M] with the \the [src]!</span>")
to_chat(user, "<span class='warning'>You can't heal [M] with the \the [src]!</span>")
@@ -289,7 +289,7 @@ GLOBAL_LIST_INIT(plastitaniumglass_recipes, list(
resistance_flags = ACID_PROOF
armor = list("melee" = 100, "bullet" = 0, "laser" = 0, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 100)
max_integrity = 40
sharpness = IS_SHARP
sharpness = SHARP_EDGED
var/icon_prefix
embedding = list("embed_chance" = 65)
@@ -184,13 +184,13 @@ GLOBAL_LIST_INIT(plasteel_recipes, list ( \
new /datum/stack_recipe("trash cart", /obj/structure/closet/crate/trashcart, 5, time = 50, one_per_turf = 1, on_floor = 1), \
new /datum/stack_recipe("medical crate", /obj/structure/closet/crate/medical, 5, time = 50, one_per_turf = 1, on_floor = 1), \
new /datum/stack_recipe("freezer crate", /obj/structure/closet/crate/freezer, 8, time = 50, one_per_turf = 1, on_floor = 1), \
new /datum/stack_recipe("blood bag crate", /obj/structure/closet/crate/freezer/blood, 8, time = 50, one_per_turf = 1, on_floor = 1), \
new /datum/stack_recipe("surplus limbs crate", /obj/structure/closet/crate/freezer/surplus_limbs, 8, time = 50, one_per_turf = 1, on_floor = 1), \
new /datum/stack_recipe("blood bag crate", /obj/structure/closet/crate/freezer/blood/fake, 8, time = 50, one_per_turf = 1, on_floor = 1), \
new /datum/stack_recipe("surplus limbs crate", /obj/structure/closet/crate/freezer/surplus_limbs/fake, 8, time = 50, one_per_turf = 1, on_floor = 1), \
new /datum/stack_recipe("radiation containment crate", /obj/structure/closet/crate/radiation, 8, time = 50, one_per_turf = 1, on_floor = 1), \
new /datum/stack_recipe("hydroponics crate", /obj/structure/closet/crate/hydroponics, 5, time = 50, one_per_turf = 1, on_floor = 1), \
new /datum/stack_recipe("engineering crate", /obj/structure/closet/crate/engineering, 5, time = 50, one_per_turf = 1, on_floor = 1), \
new /datum/stack_recipe("eletrical crate", /obj/structure/closet/crate/engineering/electrical, 5, time = 50, one_per_turf = 1, on_floor = 1), \
new /datum/stack_recipe("RCD storage crate", /obj/structure/closet/crate/rcd, 5, time = 50, one_per_turf = 1, on_floor = 1), \
new /datum/stack_recipe("RCD storage crate", /obj/structure/closet/crate/rcd/fake, 5, time = 50, one_per_turf = 1, on_floor = 1), \
new /datum/stack_recipe("science crate", /obj/structure/closet/crate/science, 5, time = 50, one_per_turf = 1, on_floor = 1), \
)), \
new /datum/stack_recipe_list("airlock assemblies", list( \
@@ -247,6 +247,7 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \
new/datum/stack_recipe("painting frame", /obj/item/wallframe/painting, 1, time = 10),\
new/datum/stack_recipe("wooden buckler", /obj/item/shield/riot/buckler, 20, time = 40), \
new/datum/stack_recipe("baseball bat", /obj/item/melee/baseball_bat, 5, time = 15),\
new/datum/stack_recipe("training bokken", /obj/item/melee/bokken, 10, time = 15),\
null, \
new/datum/stack_recipe("wooden chair", /obj/structure/chair/wood/, 3, time = 10, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("winged wooden chair", /obj/structure/chair/wood/wings, 3, time = 10, one_per_turf = TRUE, on_floor = TRUE), \
+11 -3
View File
@@ -25,9 +25,18 @@
var/list/mats_per_unit //list that tells you how much is in a single unit.
///Datum material type that this stack is made of
var/material_type
max_integrity = 100
//NOTE: When adding grind_results, the amounts should be for an INDIVIDUAL ITEM - these amounts will be multiplied by the stack size in on_grind()
var/obj/structure/table/tableVariant // we tables now (stores table variant to be built from this stack)
// The following are all for medical treatment, they're here instead of /stack/medical because sticky tape can be used as a makeshift bandage or splint
/// If set and this used as a splint for a broken bone wound, this is used as a multiplier for applicable slowdowns (lower = better) (also for speeding up burn recoveries)
var/splint_factor
/// How much blood flow this stack can absorb if used as a bandage on a cut wound, note that absorption is how much we lower the flow rate, not the raw amount of blood we suck up
var/absorption_capacity
/// How quickly we lower the blood flow on a cut wound we're bandaging. Expected lifetime of this bandage in ticks is thus absorption_capacity/absorption_rate, or until the cut heals, whichever comes first
var/absorption_rate
/obj/item/stack/on_grind()
for(var/i in 1 to grind_results.len) //This should only call if it's ground, so no need to check if grind_results exists
grind_results[grind_results[i]] *= get_amount() //Gets the key at position i, then the reagent amount of that key, then multiplies it by stack size
@@ -224,7 +233,7 @@
return
T.PlaceOnTop(R.result_type, flags = CHANGETURF_INHERIT_AIR)
else
O = new R.result_type(usr.drop_location())
O = new R.result_type(get_turf(usr))
if(O)
O.setDir(usr.dir)
log_craft("[O] crafted by [usr] at [loc_name(O.loc)]")
@@ -389,8 +398,7 @@
merge(AM)
. = ..()
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/stack/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/stack/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(user.get_inactive_held_item() == src)
if(zero_amount())
return
+15 -1
View File
@@ -7,10 +7,13 @@
icon = 'icons/obj/tapes.dmi'
icon_state = "tape_w"
var/prefix = "sticky"
w_class = WEIGHT_CLASS_TINY
full_w_class = WEIGHT_CLASS_TINY
item_flags = NOBLUDGEON
amount = 5
max_amount = 5
resistance_flags = FLAMMABLE
splint_factor = 0.8
grind_results = list(/datum/reagent/cellulose = 5)
var/list/conferred_embed = EMBED_HARMLESS
@@ -54,6 +57,7 @@
icon_state = "tape_y"
prefix = "super sticky"
conferred_embed = EMBED_HARMLESS_SUPERIOR
splint_factor = 0.6
/obj/item/stack/sticky_tape/pointy
name = "pointy tape"
@@ -69,4 +73,14 @@
desc = "You didn't know tape could look so sinister. Welcome to Space Station 13."
icon_state = "tape_spikes"
prefix = "super pointy"
conferred_embed = EMBED_POINTY_SUPERIOR
conferred_embed = EMBED_POINTY_SUPERIOR
/obj/item/stack/sticky_tape/surgical
name = "surgical tape"
singular_name = "surgical tape"
desc = "Made for patching broken bones back together alongside bone gel, not for playing pranks."
//icon_state = "tape_spikes"
prefix = "surgical"
conferred_embed = list("embed_chance" = 30, "pain_mult" = 0, "jostle_pain_mult" = 0, "ignore_throwspeed_threshold" = TRUE)
splint_factor = 0.4
custom_price = 500
+2 -1
View File
@@ -19,8 +19,9 @@
return TRUE
/obj/item/storage/contents_explosion(severity, target)
var/in_storage = istype(loc, /obj/item/storage)? (max(0, severity - 1)) : (severity)
for(var/atom/A in contents)
A.ex_act(severity, target)
A.ex_act(in_storage, target)
CHECK_TICK
//Cyberboss says: "USE THIS TO FILL IT, NOT INITIALIZE OR NEW"
@@ -369,6 +369,7 @@
new /obj/item/circular_saw(src)
new /obj/item/surgicaldrill(src)
new /obj/item/cautery(src)
new /obj/item/bonesetter(src)
new /obj/item/surgical_drapes(src)
new /obj/item/clothing/mask/surgical(src)
new /obj/item/reagent_containers/medspray/sterilizine(src)
@@ -391,6 +392,7 @@
new /obj/item/circular_saw(src)
new /obj/item/surgicaldrill(src)
new /obj/item/cautery(src)
new /obj/item/bonesetter(src)
new /obj/item/surgical_drapes(src)
new /obj/item/clothing/mask/surgical(src)
new /obj/item/reagent_containers/medspray/sterilizine(src)
@@ -485,6 +487,7 @@
new /obj/item/circular_saw(src)
new /obj/item/surgicaldrill(src)
new /obj/item/cautery(src)
new /obj/item/bonesetter(src)
new /obj/item/surgical_drapes(src)
new /obj/item/clothing/suit/straight_jacket(src)
new /obj/item/clothing/mask/muzzle(src)
@@ -501,6 +504,7 @@
new /obj/item/scalpel/advanced(src)
new /obj/item/retractor/advanced(src)
new /obj/item/surgicaldrill/advanced(src)
new /obj/item/bonesetter(src)
new /obj/item/surgical_drapes(src)
new /obj/item/clothing/suit/straight_jacket(src)
new /obj/item/clothing/mask/muzzle(src)
+10 -7
View File
@@ -83,7 +83,7 @@
new /obj/item/multitool(src)
new /obj/item/stack/cable_coil(src,30,pick("red","yellow","orange"))
new /obj/item/extinguisher/mini(src)
new /obj/item/analyzer(src)
new /obj/item/analyzer/ranged(src)
//much roomier now that we've managed to remove two tools
/obj/item/storage/belt/utility/full/PopulateContents()
@@ -120,7 +120,7 @@
new /obj/item/wrench/brass(src)
new /obj/item/crowbar/brass(src)
new /obj/item/weldingtool/experimental/brass(src)
new /obj/item/multitool(src)
new /obj/item/multitool/advanced/brass(src)
new /obj/item/stack/cable_coil(src, 30, "yellow")
/obj/item/storage/belt/medical
@@ -162,6 +162,7 @@
/obj/item/surgical_drapes, //for true paramedics
/obj/item/scalpel,
/obj/item/circular_saw,
/obj/item/bonesetter,
/obj/item/surgicaldrill,
/obj/item/retractor,
/obj/item/cautery,
@@ -181,7 +182,8 @@
/obj/item/implant,
/obj/item/implanter,
/obj/item/pinpointer/crew,
/obj/item/reagent_containers/chem_pack
/obj/item/reagent_containers/chem_pack,
/obj/item/stack/sticky_tape //surgical tape
))
/obj/item/storage/belt/medical/surgery_belt_adv
@@ -444,10 +446,11 @@
/obj/item/storage/belt/durathread
name = "durathread toolbelt"
desc = "A toolbelt made out of durathread, it seems resistant enough to hold even big tools like an RCD, it also has higher capacity."
desc = "A toolbelt made out of durathread, it seems robust enough to hold bigger tools like RCDs or RPDs, with enough pouches to hold more gear than a normal belt."
icon_state = "webbing-durathread"
item_state = "webbing-durathread"
resistance_flags = FIRE_PROOF
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE //If normal belts get this, the upgraded version should too
/obj/item/storage/belt/durathread/ComponentInitialize()
. = ..()
@@ -467,7 +470,7 @@
/obj/item/t_scanner,
/obj/item/analyzer,
/obj/item/geiger_counter,
/obj/item/extinguisher/mini,
/obj/item/extinguisher,
/obj/item/radio,
/obj/item/clothing/gloves,
/obj/item/holosign_creator,
@@ -488,7 +491,8 @@
desc = "A belt for holding grenades."
icon_state = "grenadebeltnew"
item_state = "security"
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
/obj/item/storage/belt/grenade/ComponentInitialize()
. = ..()
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
@@ -811,4 +815,3 @@
attack_verb = list("bashed", "slashes", "prods", "pokes")
fitting_swords = list(/obj/item/melee/rapier)
starting_sword = /obj/item/melee/rapier
+5 -6
View File
@@ -104,7 +104,7 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible",
SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "blessing", /datum/mood_event/blessing)
return 1
/obj/item/storage/book/bible/attack(mob/living/M, mob/living/carbon/human/user, heal_mode = TRUE)
/obj/item/storage/book/bible/attack(mob/living/M, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1, heal_mode = TRUE)
if (!user.IsAdvancedToolUser())
to_chat(user, "<span class='warning'>You don't have the dexterity to do this!</span>")
@@ -238,11 +238,10 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible",
var/ownername = H.real_name
desc += "<span class='warning'>The name [ownername] is written in blood inside the cover.</span>"
/obj/item/storage/book/bible/syndicate/attack(mob/living/M, mob/living/carbon/human/user, heal_mode = TRUE)
if (user.a_intent == INTENT_HELP)
return ..()
else
return ..(M,user,heal_mode = FALSE)
/obj/item/storage/book/bible/syndicate/attack(mob/living/M, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1, heal_mode = TRUE)
if(user.a_intent != INTENT_HELP)
heal_mode = FALSE //args pass over
return ..() // to ..()
/obj/item/storage/book/bible/syndicate/add_blood_DNA(list/blood_dna)
return FALSE
+4 -4
View File
@@ -726,9 +726,9 @@ obj/item/storage/box/stingbangs
return (BRUTELOSS)
/obj/item/storage/box/hug/attack_self(mob/user)
..()
user.changeNext_move(CLICK_CD_MELEE)
playsound(loc, "rustle", 50, 1, -5)
. = ..()
user.DelayNextAction(CLICK_CD_MELEE)
playsound(src, "rustle", 50, 1, -5)
user.visible_message("<span class='notice'>[user] hugs \the [src].</span>","<span class='notice'>You hug \the [src].</span>")
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT,"hugbox", /datum/mood_event/hugbox)
@@ -1423,4 +1423,4 @@ obj/item/storage/box/stingbangs
/obj/item/storage/box/strange_seeds_5pack/PopulateContents()
for(var/i in 1 to 5)
new /obj/item/seeds/random(src)
new /obj/item/seeds/random(src)
+1 -1
View File
@@ -47,6 +47,6 @@
if(INTENT_HARM)
user.visible_message("<span class='danger'>[user] punches the [name]!</span>")
playsound(src, 'sound/effects/shieldbash.ogg', 50, 1)
user.changeNext_move(CLICK_CD_MELEE)
user.DelayNextAction(CLICK_CD_MELEE)
////////////////////////////
+22 -2
View File
@@ -168,13 +168,19 @@
. += "<span class='notice'>There's a coupon on the back of the pack! You can tear it off once it's empty.</span>"
/obj/item/storage/fancy/cigarettes/AltClick(mob/living/carbon/user)
. = ..()
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
return
var/obj/item/clothing/mask/cigarette/W = locate(/obj/item/clothing/mask/cigarette) in contents
var/obj/item/lighter/L = locate() in contents
if(L)
SEND_SIGNAL(src, COMSIG_TRY_STORAGE_TAKE, L, user)
user.put_in_hands(L)
to_chat(user, "<span class='notice'>You take \a [L] out of the pack.</span>")
return TRUE
var/obj/item/clothing/mask/cigarette/W = locate() in contents
if(W && contents.len > 0)
SEND_SIGNAL(src, COMSIG_TRY_STORAGE_TAKE, W, user)
user.put_in_hands(W)
contents -= W
to_chat(user, "<span class='notice'>You take \a [W] out of the pack.</span>")
else
to_chat(user, "<span class='notice'>There are no [icon_type]s left in the pack.</span>")
@@ -398,6 +404,20 @@
STR.max_items = 6
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food/snacks/nugget))
/obj/item/storage/fancy/cracker_pack
name = "cracker pack"
desc = "A pack of delicious crackers. Keep away from parrots!"
icon = 'icons/obj/food/containers.dmi'
icon_state = "crackerbox"
icon_type = "cracker"
spawn_type = /obj/item/reagent_containers/food/snacks/cracker
/obj/item/storage/fancy/cracker_pack/ComponentInitialize()
. = ..()
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 6
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food/snacks/cracker))
/*
* Ring Box
*/
+18 -1
View File
@@ -41,9 +41,25 @@
new /obj/item/stack/medical/suture(src)
new /obj/item/stack/medical/mesh(src)
new /obj/item/stack/medical/mesh(src)
new /obj/item/reagent_containers/hypospray/medipen(src)
new /obj/item/reagent_containers/hypospray/medipen/ekit(src)
new /obj/item/healthanalyzer(src)
/obj/item/storage/firstaid/emergency
icon_state = "medbriefcase"
name = "emergency first-aid kit"
desc = "A very simple first aid kit meant to secure and stabilize serious wounds for later treatment."
/obj/item/storage/firstaid/emergency/PopulateContents()
if(empty)
return
var/static/items_inside = list(
/obj/item/healthanalyzer/wound = 1,
/obj/item/stack/medical/gauze = 1,
/obj/item/stack/medical/suture/emergency = 1,
/obj/item/stack/medical/ointment = 1,
/obj/item/reagent_containers/hypospray/medipen/ekit = 2)
generate_items_inside(items_inside,src)
/obj/item/storage/firstaid/ancient
icon_state = "firstaid"
desc = "A first aid kit with the ability to heal common types of injuries."
@@ -435,6 +451,7 @@
/obj/item/retractor,
/obj/item/cautery,
/obj/item/surgical_drapes,
/obj/item/bonesetter,
/obj/item/autosurgeon,
/obj/item/organ,
/obj/item/implant,
+1 -4
View File
@@ -205,10 +205,7 @@
new /obj/item/paper(src)
new /obj/item/pen(src)
/obj/item/storage/secure/safe/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
/obj/item/storage/secure/safe/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
return attack_self(user)
/obj/item/storage/secure/safe/HoS
@@ -20,6 +20,8 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons)
var/has_latches = TRUE
var/can_rubberify = TRUE
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE //very protecc too
wound_bonus = -10
bare_wound_bonus = 5
/obj/item/storage/toolbox/greyscale
icon_state = "toolbox_default"
+10 -1
View File
@@ -169,6 +169,14 @@
O.imp = new /obj/item/implant/freedom(O)
O.update_icon()
/obj/item/storage/box/syndie_kit/imp_warp
name = "boxed warp implant (with injector)"
/obj/item/storage/box/syndie_kit/imp_warp/PopulateContents()
var/obj/item/implanter/O = new(src)
O.imp = new /obj/item/implant/warp(O)
O.update_icon()
/obj/item/storage/box/syndie_kit/imp_microbomb
name = "Microbomb Implant (with injector)"
@@ -327,6 +335,7 @@
new /obj/item/reagent_containers/glass/bottle/romerol(src)
new /obj/item/reagent_containers/syringe(src)
new /obj/item/reagent_containers/dropper(src)
new /obj/item/paper/guides/antag/romerol_instructions(src)
/obj/item/storage/box/syndie_kit/ez_clean/PopulateContents()
for(var/i in 1 to 3)
@@ -401,7 +410,7 @@
/obj/item/storage/box/syndie_kit/revolver
/obj/item/storage/box/syndie_kit/revolver/PopulateContents()
new /obj/item/gun/ballistic/revolver(src)
new /obj/item/gun/ballistic/revolver/syndicate(src)
new /obj/item/ammo_box/a357(src)
/obj/item/storage/box/syndie_kit/pistol
+4 -1
View File
@@ -14,6 +14,7 @@
w_class = WEIGHT_CLASS_NORMAL
attack_verb = list("beaten")
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 50, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80)
attack_speed = CLICK_CD_MELEE
var/stamforce = 35
var/turned_on = FALSE
@@ -144,8 +145,9 @@
return ..()
/obj/item/melee/baton/alt_pre_attack(atom/A, mob/living/user, params)
if(!user.CheckActionCooldown(CLICK_CD_MELEE))
return
. = common_baton_melee(A, user, TRUE) //return true (attackchain interrupt) if this also returns true. no harm-disarming.
user.changeNext_move(CLICK_CD_MELEE)
//return TRUE to interrupt attack chain.
/obj/item/melee/baton/proc/common_baton_melee(mob/M, mob/living/user, disarming = FALSE)
@@ -156,6 +158,7 @@
if(IS_STAMCRIT(user)) //CIT CHANGE - makes it impossible to baton in stamina softcrit
to_chat(user, "<span class='danger'>You're too exhausted to use [src] properly.</span>")
return TRUE
user.DelayNextAction()
if(ishuman(M))
var/mob/living/carbon/human/L = M
if(check_martial_counter(L, user))
+7 -9
View File
@@ -123,6 +123,7 @@
/obj/item/tank/analyzer_act(mob/living/user, obj/item/I)
atmosanalyzer_scan(air_contents, user, src)
return TRUE
/obj/item/tank/deconstruct(disassembled = TRUE)
if(!disassembled)
@@ -143,7 +144,6 @@
if(prob(50))
step(W, pick(GLOB.alldirs))
ADD_TRAIT(H, TRAIT_DISFIGURED, TRAIT_GENERIC)
H.bleed_rate = 5
H.gib_animation()
sleep(3)
H.adjustBruteLoss(1000) //to make the body super-bloody
@@ -164,11 +164,13 @@
else
. = ..()
/obj/item/tank/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/item/tank/ui_state(mob/user)
return GLOB.hands_state
/obj/item/tank/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "Tank", name, 400, 120, master_ui, state)
ui = new(user, src, "Tank", name)
ui.open()
/obj/item/tank/ui_data(mob/user)
@@ -205,10 +207,6 @@
else if(pressure == "max")
pressure = TANK_MAX_RELEASE_PRESSURE
. = TRUE
else if(pressure == "input")
pressure = input("New release pressure ([TANK_MIN_RELEASE_PRESSURE]-[TANK_MAX_RELEASE_PRESSURE] kPa):", name, distribute_pressure) as num|null
if(!isnull(pressure) && !..())
. = TRUE
else if(text2num(pressure) != null)
pressure = text2num(pressure)
. = TRUE
+1 -1
View File
@@ -72,7 +72,7 @@
QDEL_NULL(noz)
return ..()
/obj/item/watertank/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/watertank/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if (user.get_item_by_slot(user.getBackSlot()) == src)
toggle_mister(user)
else
+65 -90
View File
@@ -1,4 +1,3 @@
#define SOURCE_PORTAL 1
#define DESTINATION_PORTAL 2
@@ -25,90 +24,72 @@
throw_speed = 3
throw_range = 7
custom_materials = list(/datum/material/iron=400)
var/tracking_range = 20
/obj/item/locator/attack_self(mob/user)
user.set_machine(src)
var/dat
if (temp)
dat = "[temp]<BR><BR><A href='byond://?src=[REF(src)];temp=1'>Clear</A>"
else
dat = {"
<B>Persistent Signal Locator</B><HR>
<A href='?src=[REF(src)];refresh=1'>Refresh</A>"}
user << browse(dat, "window=radio")
onclose(user, "radio")
return
/obj/item/locator/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "BluespaceLocator", name)
ui.open()
/obj/item/locator/Topic(href, href_list)
..()
if (usr.stat || usr.restrained())
return
var/turf/current_location = get_turf(usr)//What turf is the user on?
if(!current_location || is_centcom_level(current_location.z))//If turf was not found or they're on CentCom
to_chat(usr, "[src] is malfunctioning.")
return
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)))
usr.set_machine(src)
if (href_list["refresh"])
temp = "<B>Persistent Signal Locator</B><HR>"
var/turf/sr = get_turf(src)
/obj/item/locator/ui_data(mob/user)
var/list/data = list()
if (sr)
temp += "<B>Beacon Signals:</B><BR>"
for(var/obj/item/beacon/W in GLOB.teleportbeacons)
if (!W.renamed)
continue
var/turf/tr = get_turf(W)
if (tr.z == sr.z && tr)
var/direct = max(abs(tr.x - sr.x), abs(tr.y - sr.y))
if (direct < 5)
direct = "very strong"
else
if (direct < 10)
direct = "strong"
else
if (direct < 20)
direct = "weak"
else
direct = "very weak"
temp += "[W.name]-[dir2text(get_dir(sr, tr))]-[direct]<BR>"
data["trackingrange"] = tracking_range
temp += "<B>Implant Signals:</B><BR>"
for (var/obj/item/implant/tracking/W in GLOB.tracked_implants)
if (!isliving(W.imp_in))
continue
var/mob/living/M = W.imp_in
if (M.stat == DEAD)
if (M.timeofdeath + W.lifespan_postmortem < world.time)
continue
// Get our current turf location.
var/turf/sr = get_turf(src)
var/turf/tr = get_turf(M)
if (tr.z == sr.z && tr)
var/direct = max(abs(tr.x - sr.x), abs(tr.y - sr.y))
if (direct < 20)
if (direct < 5)
direct = "very strong"
else
if (direct < 10)
direct = "strong"
else
direct = "weak"
temp += "[W.imp_in.name]-[dir2text(get_dir(sr, tr))]-[direct]<BR>"
if (sr)
// Check every teleport beacon.
var/list/tele_beacons = list()
for(var/obj/item/beacon/W in GLOB.teleportbeacons)
temp += "<B>You are at \[[sr.x],[sr.y],[sr.z]\]</B> in orbital coordinates.<BR><BR><A href='byond://?src=[REF(src)];refresh=1'>Refresh</A><BR>"
// Get the tracking beacon's turf location.
var/turf/tr = get_turf(W)
// Make sure it's on a turf and that its Z-level matches the tracker's Z-level
if (tr && tr.z == sr.z)
// Get the distance between the beacon's turf and our turf
var/distance = max(abs(tr.x - sr.x), abs(tr.y - sr.y))
// If the target is too far away, skip over this beacon.
if(distance > tracking_range)
continue
var/beacon_name
if(W.renamed)
beacon_name = W.name
else
var/area/A = get_area(W)
beacon_name = A.name
var/D = dir2text(get_dir(sr, tr))
tele_beacons += list(list(name = beacon_name, direction = D, distance = distance))
data["telebeacons"] = tele_beacons
var/list/track_implants = list()
for (var/obj/item/implant/tracking/W in GLOB.tracked_implants)
if (!W.imp_in || !isliving(W.loc))
continue
else
temp += "<B><FONT color='red'>Processing Error:</FONT></B> Unable to locate orbital position.<BR>"
else
if (href_list["temp"])
temp = null
if (ismob(src.loc))
attack_self(src.loc)
else
for(var/mob/M in fov_viewers(1, src))
if (M.client)
src.attack_self(M)
return
var/mob/living/M = W.loc
if (M.stat == DEAD)
if (M.timeofdeath + W.lifespan_postmortem < world.time)
continue
var/turf/tr = get_turf(W)
var/distance = max(abs(tr.x - sr.x), abs(tr.y - sr.y))
if(distance > tracking_range)
continue
var/D = dir2text(get_dir(sr, tr))
track_implants += list(list(name = W.imp_in.name, direction = D, distance = distance))
data["trackimplants"] = track_implants
return data
/*
* Hand-tele
@@ -141,14 +122,11 @@
return TRUE
return ..()
/obj/item/hand_tele/proc/try_dispel_portal(atom/target, mob/user, delay = 30)
var/datum/beam/B = user.Beam(target, icon_state = "rped_upgrade", maxdistance = 50)
if(is_parent_of_portal(target) && (!delay || do_after(user, delay, target = target)))
/obj/item/hand_tele/proc/try_dispel_portal(atom/target, mob/user)
if(is_parent_of_portal(target))
qdel(target)
to_chat(user, "<span class='notice'>You dispel [target] with \the [src]!</span>")
qdel(B)
return TRUE
qdel(B)
return FALSE
/obj/item/hand_tele/afterattack(atom/target, mob/user)
@@ -190,13 +168,8 @@
user.show_message("<span class='notice'>\The [src] is recharging!</span>")
return
var/atom/T = L[t1]
var/implantcheckmate = FALSE
if(isliving(T))
var/mob/living/M = T
if(!locate(/obj/item/implant/tracking) in M.implants) //The user was too slow and let the target mob's tracking implant expire or get removed.
implantcheckmate = TRUE
var/area/A = get_area(T)
if(A.noteleport || implantcheckmate)
if(A.noteleport)
to_chat(user, "<span class='notice'>\The [src] is malfunctioning.</span>")
return
current_location = get_turf(user) //Recheck.
@@ -205,10 +178,12 @@
to_chat(user, "<span class='notice'>\The [src] is malfunctioning.</span>")
return
user.show_message("<span class='notice'>Locked In.</span>", MSG_AUDIBLE)
var/list/obj/effect/portal/created = create_portal_pair(current_location, get_teleport_turf(get_turf(T)), src, 300, 1, null, atmos_link_override)
var/list/obj/effect/portal/created = create_portal_pair(current_location, get_teleport_turf(get_turf(T)), 300, 1, null, atmos_link_override)
if(!(LAZYLEN(created) == 2))
return
try_move_adjacent(created[1])
RegisterSignal(created[1], COMSIG_PARENT_QDELETING, .proc/on_portal_destroy) //Gosh darn it kevinz.
RegisterSignal(created[2], COMSIG_PARENT_QDELETING, .proc/on_portal_destroy)
try_move_adjacent(created[1], user.dir)
active_portal_pairs[created[1]] = created[2]
var/obj/effect/portal/c1 = created[1]
var/obj/effect/portal/c2 = created[2]
+4
View File
@@ -18,6 +18,9 @@
toolspeed = 1
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30)
wound_bonus = -10
bare_wound_bonus = 5
/obj/item/crowbar/suicide_act(mob/user)
user.visible_message("<span class='suicide'>[user] is beating [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1)
@@ -90,6 +93,7 @@
/obj/item/crowbar/power/attack_self(mob/user)
playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, 1)
var/obj/item/wirecutters/power/cutjaws = new /obj/item/wirecutters/power(drop_location())
cutjaws.name = name
to_chat(user, "<span class='notice'>You attach the cutting jaws to [src].</span>")
qdel(src)
user.put_in_active_hand(cutjaws)
@@ -31,6 +31,9 @@
"yellow" = rgb(255, 165, 0)
)
wound_bonus = -10
bare_wound_bonus = 5
/obj/item/screwdriver/suicide_act(mob/user)
user.visible_message("<span class='suicide'>[user] is stabbing [src] into [user.p_their()] [pick("temple", "heart")]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
return(BRUTELOSS)
@@ -33,6 +33,8 @@
heat = 3800
tool_behaviour = TOOL_WELDER
toolspeed = 1
wound_bonus = 0
bare_wound_bonus = 5
/obj/item/weldingtool/Initialize()
. = ..()
@@ -117,6 +117,7 @@
/obj/item/wirecutters/power/attack_self(mob/user)
playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, 1)
var/obj/item/crowbar/power/pryjaws = new /obj/item/crowbar/power(drop_location())
pryjaws.name = name
to_chat(user, "<span class='notice'>You attach the pry jaws to [src].</span>")
qdel(src)
user.put_in_active_hand(pryjaws)
+3
View File
@@ -18,6 +18,9 @@
toolspeed = 1
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30)
wound_bonus = -10
bare_wound_bonus = 5
/obj/item/wrench/suicide_act(mob/user)
user.visible_message("<span class='suicide'>[user] is beating [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1)
+5 -9
View File
@@ -447,7 +447,7 @@
block_parry_data = null
attack_verb = list("attacked", "struck", "hit")
total_mass_on = TOTAL_MASS_TOY_SWORD
sharpness = IS_BLUNT
sharpness = SHARP_NONE
/obj/item/dualsaber/toy/ComponentInitialize()
AddComponent(/datum/component/two_handed, force_unwielded=0, force_wielded=0, wieldsound='sound/weapons/saberon.ogg', unwieldsound='sound/weapons/saberoff.ogg')
@@ -466,7 +466,7 @@
attack_verb = list("attacked", "struck", "hit")
total_mass_on = TOTAL_MASS_TOY_SWORD
slowdown_wielded = 0
sharpness = IS_BLUNT
sharpness = SHARP_NONE
/obj/item/dualsaber/hypereutactic/toy/ComponentInitialize()
AddComponent(/datum/component/two_handed, force_unwielded=0, force_wielded=0, wieldsound='sound/weapons/saberon.ogg', unwieldsound='sound/weapons/saberoff.ogg')
@@ -574,10 +574,7 @@
else
. = ..()
/obj/item/toy/prize/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
/obj/item/toy/prize/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(loc == user)
attack_self(user)
@@ -811,9 +808,8 @@
cards += "Ace of Clubs"
cards += "Ace of Diamonds"
//ATTACK HAND IGNORING PARENT RETURN VALUE
//ATTACK HAND NOT CALLING PARENT
/obj/item/toy/cards/deck/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/toy/cards/deck/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
draw_card(user)
/obj/item/toy/cards/deck/proc/draw_card(mob/user)
@@ -1234,7 +1230,7 @@
name = "steampunk watch"
desc = "A stylish steampunk watch made out of thousands of tiny cogwheels."
icon = 'icons/obj/clockwork_objects.dmi'
icon_state = "dread_ipad"
icon_state = "clockwork_slab"
slot_flags = ITEM_SLOT_BELT
w_class = WEIGHT_CLASS_SMALL
var/cooldown = 0
+4
View File
@@ -35,6 +35,10 @@
name = "syndi-cakes"
icon_state = "syndi_cakes"
/obj/item/trash/energybar
name = "energybar wrapper"
icon_state = "energybar"
/obj/item/trash/waffles
name = "waffles tray"
icon_state = "waffles"
+180 -10
View File
@@ -65,7 +65,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
w_class = WEIGHT_CLASS_NORMAL
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
block_chance = 50
sharpness = IS_SHARP
sharpness = SHARP_EDGED
max_integrity = 200
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50)
resistance_flags = FIRE_PROOF
@@ -231,7 +231,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
block_chance = 50
sharpness = IS_SHARP
sharpness = SHARP_EDGED
max_integrity = 200
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50)
resistance_flags = FIRE_PROOF
@@ -249,6 +249,172 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
playsound(src, 'sound/weapons/bladeslice.ogg', 50, 1)
return(BRUTELOSS)
/obj/item/katana/timestop
name = "temporal katana"
desc = "Delicately balanced, this finely-crafted blade hums with barely-restrained potential."
item_flags = ITEM_CAN_PARRY
block_parry_data = /datum/block_parry_data/bokken/quick_parry/proj
/obj/item/katana/timestop/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time)
if(ishuman(owner))
var/mob/living/carbon/human/flynn = owner
flynn.emote("smirk")
new /obj/effect/timestop(get_turf(owner), 2, 50, list(owner))
/obj/item/melee/bokken // parrying stick
name = "bokken"
desc = "A space-Japanese training sword made of wood and shaped like a katana."
icon_state = "bokken"
item_state = "bokken"
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_BACK
w_class = WEIGHT_CLASS_BULKY
force = 9
throwforce = 10
damtype = STAMINA
attack_verb = list("whacked", "smacked", "struck")
total_mass = TOTAL_MASS_MEDIEVAL_WEAPON
hitsound = 'sound/weapons/grenadelaunch.ogg' // no good wood thunk sounds
var/harm = FALSE // TRUE = brute, FALSE = stam
var/reinforced = FALSE
var/burnt = FALSE
var/burned_in // text you burned in (with a welder)
var/quick_parry = FALSE // false = default parry, true = really small parry window
item_flags = ITEM_CAN_PARRY
block_parry_data = /datum/block_parry_data/bokken
bare_wound_bonus = 0
wound_bonus = 0
/datum/block_parry_data/bokken // fucked up parry data, emphasizing quicker, shorter parries
parry_stamina_cost = 8 // be wise about when you parry, though, else you won't be able to fight enough to make it count
parry_time_windup = 0
parry_time_active = 10 // small parry window
parry_time_spindown = 0
// parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK // bokken users can no longer strike while parrying
parry_time_perfect = 1.5
parry_time_perfect_leeway = 1
parry_imperfect_falloff_percent = 7.5
parry_efficiency_to_counterattack = 100
parry_efficiency_considered_successful = 65 // VERY generous
parry_efficiency_perfect = 120
parry_efficiency_perfect_override = list(
TEXT_ATTACK_TYPE_PROJECTILE = 30,
)
parry_failed_stagger_duration = 3 SECONDS
parry_data = list(
PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN = 2.5, // 7*2.5 = 17.5, 8*2.5 = 20, 9*2.5 = 22.5, 10*2.5 = 25
)
/datum/block_parry_data/bokken/quick_parry // emphasizing REALLY SHORT PARRIES
parry_stamina_cost = 6 // still more costly than most parries, but less than a full bokken parry
parry_time_active = 5 // REALLY small parry window
parry_time_perfect = 2.5 // however...
parry_time_perfect_leeway = 2.5 // the entire time, the parry is perfect
parry_failed_stagger_duration = 1 SECONDS
parry_failed_clickcd_duration = 1 SECONDS // more forgiving punishments for missed parries
// still, don't fucking miss your parries or you're down stamina and staggered to shit
/datum/block_parry_data/bokken/quick_parry/proj
parry_efficiency_perfect_override = list()
/obj/item/melee/bokken/Initialize()
. = ..()
AddElement(/datum/element/sword_point)
/obj/item/melee/bokken/attack_self(mob/user)
harm = !harm
if(harm)
force -= 2
damtype = BRUTE
attack_verb = list("bashed", "smashed", "attacked")
bare_wound_bonus = 15 // having your leg smacked by a wooden stick is probably not great for it if it's naked
wound_bonus = 0
else
force += 2
damtype = STAMINA
attack_verb = list("whacked", "smacked", "struck")
bare_wound_bonus = 0
wound_bonus = 0
to_chat(user, "<span class='notice'>[src] is now [harm ? "harmful" : "not quite as harmful"].</span>")
/obj/item/melee/bokken/AltClick(mob/user)
. = ..()
quick_parry = !quick_parry
if(quick_parry)
block_parry_data = /datum/block_parry_data/bokken/quick_parry
else
block_parry_data = /datum/block_parry_data/bokken
to_chat(user, "<span class='notice'>[src] is now [quick_parry ? "emphasizing shorter parries, forcing you to riposte or be staggered" : "emphasizing longer parries, with a shorter window to riposte but more forgiving parries"].</span>")
/obj/item/melee/bokken/attackby(obj/item/I, mob/living/user, params)
if(istype(I, /obj/item/pen))
var/new_name = stripped_input(user, "What do you wish to name [src]?", "New Name", "bokken", 30)
if(new_name)
name = new_name
if(I.tool_behaviour == TOOL_WELDER)
var/new_burn = stripped_input(user, "What do you wish to burn into [src]?", "Burnt Inscription","", 140)
if(new_burn)
burned_in = new_burn
if(!burnt)
icon_state += "_burnt"
item_state += "_burnt"
burnt = TRUE
update_icon()
update_icon_state()
if(istype(I, /obj/item/stack/rods))
var/obj/item/stack/rods/R = I
if(!reinforced)
if(R.use(1))
force++
reinforced = TRUE
to_chat(user, "<span class='notice'>You slide a metal rod into [src]\'s hilt. It feels a little heftier in your hands.")
else
to_chat(user, "<span class='notice'>[src] already has a weight slid into the hilt.")
/obj/item/melee/bokken/examine(mob/user)
. = ..()
if(quick_parry)
. += " [src] is gripped in a way to emphasize quicker parries."
if(reinforced)
. += " There's a metal rod shoved into the base."
if(burnt)
. += " Burned into the \"blade\" is [burned_in]."
/obj/item/melee/bokken/debug
name = "funny debug parrying stick"
desc = "if you see this you've fucked up somewhere my good man"
block_parry_data = /datum/block_parry_data/bokken/debug
/obj/item/melee/bokken/debug/AltClick(mob/user)
quick_parry = !quick_parry
if(quick_parry)
block_parry_data = /datum/block_parry_data/bokken/quick_parry/debug
else
block_parry_data = /datum/block_parry_data/bokken/debug
to_chat(user, "<span class='notice'>[src] is now [quick_parry ? "emphasizing shorter parries, forcing you to riposte or be staggered" : "emphasizing longer parries, with a shorter window to riposte but more forgiving parries"].</span>")
/datum/block_parry_data/bokken/debug
parry_efficiency_perfect_override = list()
parry_data = list(
PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN = 2.5, // 7*2.5 = 17.5, 8*2.5 = 20, 9*2.5 = 22.5, 10*2.5 = 25
PARRY_DISARM_ATTACKER = TRUE,
PARRY_KNOCKDOWN_ATTACKER = 10,
PARRY_STAGGER_ATTACKER = 10,
PARRY_DAZE_ATTACKER = 10,
)
/datum/block_parry_data/bokken/quick_parry/debug
parry_efficiency_perfect_override = list()
parry_data = list(
PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN = 2.5, // 7*2.5 = 17.5, 8*2.5 = 20, 9*2.5 = 22.5, 10*2.5 = 25
PARRY_DISARM_ATTACKER = TRUE,
PARRY_KNOCKDOWN_ATTACKER = 10,
PARRY_STAGGER_ATTACKER = 10,
PARRY_DAZE_ATTACKER = 10,
)
/obj/item/wirerod
name = "wired rod"
desc = "A rod with some wire wrapped around the top. It'd be easy to attach something to the top bit."
@@ -260,6 +426,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
w_class = WEIGHT_CLASS_NORMAL
custom_materials = list(/datum/material/iron=1150, /datum/material/glass=75)
attack_verb = list("hit", "bludgeoned", "whacked", "bonked")
wound_bonus = -10
/obj/item/wirerod/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/shard))
@@ -297,13 +464,13 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi'
force = 2
throwforce = 20 //This is never used on mobs since this has a 100% embed chance.
throwforce = 10 //This is never used on mobs since this has a 100% embed chance.
throw_speed = 4
embedding = list("pain_mult" = 4, "embed_chance" = 100, "fall_chance" = 0, "embed_chance_turf_mod" = 15)
armour_penetration = 40
w_class = WEIGHT_CLASS_SMALL
sharpness = IS_SHARP
sharpness = SHARP_EDGED
custom_materials = list(/datum/material/iron=500, /datum/material/glass=500)
resistance_flags = FIRE_PROOF
@@ -316,7 +483,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
/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 = IS_BLUNT
sharpness = SHARP_NONE
force = 0
throwforce = 0
embedding = list("pain_mult" = 0, "jostle_pain_mult" = 0, "embed_chance" = 100, "fall_chance" = 0)
@@ -353,7 +520,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
icon_state = extended_icon_state
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
hitsound = 'sound/weapons/bladeslice.ogg'
sharpness = IS_SHARP
sharpness = SHARP_EDGED
else
force = initial(force)
w_class = WEIGHT_CLASS_SMALL
@@ -361,7 +528,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
icon_state = retracted_icon_state
attack_verb = list("stubbed", "poked")
hitsound = 'sound/weapons/genhit.ogg'
sharpness = IS_BLUNT
sharpness = SHARP_NONE
/obj/item/switchblade/suicide_act(mob/user)
user.visible_message("<span class='suicide'>[user] is slitting [user.p_their()] own throat with [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
@@ -462,7 +629,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
throwforce = 0
throw_range = 0
throw_speed = 0
sharpness = IS_SHARP
sharpness = SHARP_EDGED
attack_verb = list("sawed", "torn", "cut", "chopped", "diced")
hitsound = 'sound/weapons/chainsawhit.ogg'
total_mass = TOTAL_MASS_HAND_REPLACEMENT
@@ -574,6 +741,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
force = 10
wound_bonus = -10
throwforce = 12
attack_verb = list("beat", "smacked")
custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 3.5)
@@ -590,6 +758,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
obj_flags = UNIQUE_RENAME
var/chaplain_spawnable = TRUE
total_mass = TOTAL_MASS_MEDIEVAL_WEAPON
wound_bonus = -5
/obj/item/melee/baseball_bat/chaplain/Initialize()
. = ..()
@@ -626,7 +795,8 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
homerun_ready = 0
return
else if(!target.anchored)
target.throw_at(throw_target, rand(1,2), 7, user)
var/whack_speed = (prob(60) ? 1 : 4)
target.throw_at(throw_target, rand(1, 2), whack_speed, user) // sorry friends, 7 speed batting caused wounds to absolutely delete whoever you knocked your target into (and said target)
/obj/item/melee/baseball_bat/ablative
name = "metal baseball bat"
@@ -858,7 +1028,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
block_chance = 40
throwforce = 20
throw_speed = 4
sharpness = IS_SHARP
sharpness = SHARP_EDGED
attack_verb = list("cut", "sliced", "diced")
w_class = WEIGHT_CLASS_BULKY
slot_flags = ITEM_SLOT_BACK
+6 -2
View File
@@ -105,15 +105,19 @@
/obj/proc/attack_generic(mob/user, damage_amount = 0, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, armor_penetration = 0) //used by attack_alien, attack_animal, and attack_slime
if(SEND_SIGNAL(src, COMSIG_OBJ_ATTACK_GENERIC, user, damage_amount, damage_type, damage_flag, sound_effect, armor_penetration) & COMPONENT_STOP_GENERIC_ATTACK)
return FALSE
if(!user.CheckActionCooldown(CLICK_CD_MELEE))
return
user.do_attack_animation(src)
user.changeNext_move(CLICK_CD_MELEE)
return take_damage(damage_amount, damage_type, damage_flag, sound_effect, get_dir(src, user), armor_penetration)
. = take_damage(damage_amount, damage_type, damage_flag, sound_effect, get_dir(src, user), armor_penetration)
user.DelayNextAction()
/obj/attack_alien(mob/living/carbon/alien/humanoid/user)
if(attack_generic(user, 60, BRUTE, "melee", 0))
playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1)
/obj/attack_animal(mob/living/simple_animal/M)
if(!M.CheckActionCooldown(CLICK_CD_MELEE))
return
if(!M.melee_damage_upper && !M.obj_damage)
M.emote("custom", message = "[M.friendly_verb_continuous] [src].")
return 0
+5
View File
@@ -10,6 +10,11 @@
var/damtype = BRUTE
var/force = 0
/// How good a given object is at causing wounds on carbons. Higher values equal better shots at creating serious wounds.
var/wound_bonus = 0
/// If this attacks a human with no wound armor on the affected body part, add this to the wound mod. Some attacks may be significantly worse at wounding if there's even a slight layer of armor to absorb some of it vs bare flesh
var/bare_wound_bonus = 0
var/datum/armor/armor
var/obj_integrity //defaults to max_integrity
var/max_integrity = 500
+2 -4
View File
@@ -28,12 +28,10 @@
queue_smooth_neighbors(src)
return ..()
/obj/structure/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/structure/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
if(structureclimber && structureclimber != user)
user.changeNext_move(CLICK_CD_MELEE)
user.DelayNextAction(CLICK_CD_MELEE)
user.do_attack_animation(src)
structureclimber.DefaultCombatKnockdown(40)
structureclimber.visible_message("<span class='warning'>[structureclimber] has been knocked off [src].", "You're knocked off [src]!", "You see [structureclimber] get knocked off [src].</span>")

Some files were not shown because too many files have changed in this diff Show More