Merge branch 'master' into spooder

This commit is contained in:
Tupinambis
2020-10-11 14:31:23 -05:00
committed by GitHub
475 changed files with 12056 additions and 5121 deletions
+67 -22
View File
@@ -9,12 +9,19 @@
icon = 'icons/obj/lighting.dmi'
icon_state = "glowshroom" //replaced in New
layer = ABOVE_NORMAL_TURF_LAYER
max_integrity = 5
var/delay = 1200
/// Time interval between glowshroom "spreads"
var/delay_spread = 2 MINUTES
/// Time interval between glowshroom decay checks
var/delay_decay = 30 SECONDS
/// Boolean to indicate if the shroom is on the floor/wall
var/floor = 0
/// Mushroom generation number
var/generation = 1
var/spreadIntoAdjacentChance = 60
/// Chance to spread into adjacent tiles (0-100)
var/spreadIntoAdjacentChance = 75
/// Internal seed of the glowshroom, stats are stored here
var/obj/item/seeds/myseed = /obj/item/seeds/glowshroom
/// Turfs where the glowshroom cannot spread to
var/static/list/blacklisted_glowshroom_turfs = typecacheof(list(
/turf/open/lava,
/turf/open/floor/plating/beach/water))
@@ -43,21 +50,30 @@
QDEL_NULL(myseed)
return ..()
/obj/structure/glowshroom/New(loc, obj/item/seeds/newseed, mutate_stats)
..()
/**
* Creates a new glowshroom structure.
*
* Arguments:
* * newseed - Seed of the shroom
* * mutate_stats - If the plant needs to mutate their stats
* * spread - If the plant is a result of spreading, reduce its stats
*/
/obj/structure/glowshroom/Initialize(mapload, obj/item/seeds/newseed, mutate_stats, spread)
. = ..()
if(newseed)
myseed = newseed.Copy()
myseed.forceMove(src)
else
myseed = new myseed(src)
if(spread)
myseed.potency -= round(myseed.potency * 0.25) // Reduce potency of the little mushie if it's spreading
if(mutate_stats) //baby mushrooms have different stats :3
myseed.adjust_potency(rand(-3,6))
myseed.adjust_yield(rand(-1,2))
myseed.adjust_production(rand(-3,6))
myseed.adjust_endurance(rand(-3,6))
delay = delay - myseed.production * 100 //So the delay goes DOWN with better stats instead of up. :I
obj_integrity = myseed.endurance / 7
max_integrity = myseed.endurance / 7
myseed.adjust_potency(rand(-4,3))
myseed.adjust_yield(rand(-3,2))
myseed.adjust_production(rand(-3,3))
myseed.endurance = clamp(myseed.endurance + rand(-3,2), 0, 100) // adjust_endurance has a min value of 10, need to edit directly
delay_spread = delay_spread - myseed.production * 100 //So the delay goes DOWN with better stats instead of up. :I
var/datum/plant_gene/trait/glow/G = myseed.get_gene(/datum/plant_gene/trait/glow)
if(ispath(G)) // Seeds were ported to initialize so their genes are still typepaths here, luckily their initializer is smart enough to handle us doing this
myseed.genes -= G
@@ -80,13 +96,20 @@
else //if on the floor, glowshroom on-floor sprite
icon_state = base_icon_state
addtimer(CALLBACK(src, .proc/Spread), delay)
addtimer(CALLBACK(src, .proc/Spread), delay_spread)
addtimer(CALLBACK(src, .proc/Decay), delay_decay, FALSE) // Start decaying the plant
/**
* Causes glowshroom spreading across the floor/walls.
*/
/obj/structure/glowshroom/proc/Spread()
var/turf/ownturf = get_turf(src)
var/shrooms_planted = 0
for(var/i in 1 to myseed.yield)
if(prob(1/(generation * generation) * 100))//This formula gives you diminishing returns based on generation. 100% with 1st gen, decreasing to 25%, 11%, 6, 4, 2...
var/chance_stats = ((myseed.potency + myseed.endurance * 2) * 0.2) // Chance of generating a new mushroom based on stats
var/chance_generation = (100 / (generation * generation)) // This formula gives you diminishing returns based on generation. 100% with 1st gen, decreasing to 25%, 11%, 6, 4, 2...
if(prob(max(chance_stats, chance_generation))) // Whatever is the higher chance we use it
var/list/possibleLocs = list()
var/spreadsIntoAdjacent = FALSE
@@ -96,7 +119,7 @@
for(var/turf/open/floor/earth in view(3,src))
if(is_type_in_typecache(earth, blacklisted_glowshroom_turfs))
continue
if(!disease_air_spread_walk(ownturf, earth))
if(!ownturf.CanAtmosPass(earth))
continue
if(spreadsIntoAdjacent || !locate(/obj/structure/glowshroom) in view(1,earth))
possibleLocs += earth
@@ -118,16 +141,15 @@
if(shroomCount >= placeCount)
continue
var/obj/structure/glowshroom/child = new type(newLoc, myseed, TRUE)
Decay(TRUE, 2) // Decay before spawning new mushrooms to reduce their endurance
var/obj/structure/glowshroom/child = new type(newLoc, myseed, TRUE, TRUE)
child.generation = generation + 1
shrooms_planted++
CHECK_TICK
else
shrooms_planted++ //if we failed due to generation, don't try to plant one later
if(shrooms_planted < myseed.yield) //if we didn't get all possible shrooms planted, try again later
myseed.yield -= shrooms_planted
addtimer(CALLBACK(src, .proc/Spread), delay)
if(shrooms_planted <= myseed.yield) //if we didn't get all possible shrooms planted, try again later
myseed.adjust_yield(-shrooms_planted)
addtimer(CALLBACK(src, .proc/Spread), delay_spread)
/obj/structure/glowshroom/proc/CalcDir(turf/location = loc)
var/direction = 16
@@ -161,9 +183,27 @@
floor = 1
return 1
/**
* Causes the glowshroom to decay by decreasing its endurance.
*
* Arguments:
* * spread - Boolean to indicate if the decay is due to spreading or natural decay.
* * amount - Amount of endurance to be reduced due to spread decay.
*/
/obj/structure/glowshroom/proc/Decay(spread, amount)
if (spread) // Decay due to spread
myseed.endurance -= amount
else // Timed decay
myseed.endurance -= 1
if (myseed.endurance > 0)
addtimer(CALLBACK(src, .proc/Decay), delay_decay, FALSE) // Recall decay timer
return
if (myseed.endurance < 1) // Plant is gone
qdel(src)
/obj/structure/glowshroom/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
if(damage_type == BURN && damage_amount)
playsound(src.loc, 'sound/items/welder.ogg', 100, 1)
playsound(src.loc, 'sound/items/welder.ogg', 100, TRUE)
/obj/structure/glowshroom/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
if(exposed_temperature > 300)
@@ -175,3 +215,8 @@
var/obj/effect/decal/cleanable/molten_object/I = new (get_turf(src))
I.desc = "Looks like this was \an [src] some time ago."
qdel(src)
/obj/structure/glowshroom/attackby(obj/item/I, mob/living/user, params)
if (istype(I, /obj/item/plant_analyzer))
return myseed.attackby(I, user, params) // Hacky I guess
return ..() // Attack normally
+1 -5
View File
@@ -40,10 +40,6 @@
density = TRUE
layer = FLY_LAYER
/obj/effect/supplypod_selector
icon_state = "supplypod_selector"
layer = FLY_LAYER
//Makes a tile fully lit no matter what
/obj/effect/fullbright
icon = 'icons/effects/alphacolors.dmi'
@@ -91,4 +87,4 @@
/obj/effect/dummy/lighting_obj/moblight/Initialize(mapload, _color, _range, _power, _duration)
. = ..()
if(!ismob(loc))
return INITIALIZE_HINT_QDEL
return INITIALIZE_HINT_QDEL
@@ -515,3 +515,12 @@
/obj/effect/temp_visual/dir_setting/space_wind/Initialize(mapload, set_dir, set_alpha = 255)
. = ..()
alpha = set_alpha
/obj/effect/temp_visual/slime_puddle
icon = 'icons/mob/mob.dmi'
duration = 12
icon_state = "to_puddle"
/obj/effect/temp_visual/slime_puddle/reverse
icon_state = "from_puddle"
duration = 7
+1
View File
@@ -10,6 +10,7 @@
if(log)
message_admins("EMP with power [power], max distance [max_distance] in area [epicenter.loc.name] ")
log_game("EMP with power [power], max distance [max_distance] in area [epicenter.loc.name] ")
deadchat_broadcast("<span class='deadsay bold'>EMP with power ([power]), max distance ([max_distance]) in [epicenter.loc.name]</span>", turf_target = epicenter)
if(power > 100)
new /obj/effect/temp_visual/emp/pulse(epicenter)
+3 -5
View File
@@ -315,7 +315,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
return
if(loc == user && current_equipped_slot && current_equipped_slot != SLOT_HANDS)
if(current_equipped_slot in user.check_obscured_slots())
to_chat(src, "<span class='warning'>You are unable to unequip that while wearing other garments over it!</span>")
to_chat(user, "<span class='warning'>You are unable to unequip that while wearing other garments over it!</span>")
return FALSE
if(resistance_flags & ON_FIRE)
@@ -383,7 +383,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
return
if(loc == user && current_equipped_slot && current_equipped_slot != SLOT_HANDS)
if(current_equipped_slot in user.check_obscured_slots())
to_chat(src, "<span class='warning'>You are unable to unequip that while wearing other garments over it!</span>")
to_chat(user, "<span class='warning'>You are unable to unequip that while wearing other garments over it!</span>")
return FALSE
@@ -565,7 +565,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
to_chat(user, "<span class='danger'>You cannot locate any organic eyes on this brain!</span>")
return
if(IS_STAMCRIT(user))//CIT CHANGE - makes eyestabbing impossible if you're in stamina softcrit
if(IS_STAMCRIT(user) || !user.UseStaminaBuffer(STAMINA_COST_ITEM_EYESTAB, warn = TRUE))//CIT CHANGE - makes eyestabbing impossible if you're in stamina softcrit
to_chat(user, "<span class='danger'>You're too exhausted for that.</span>")//CIT CHANGE - ditto
return //CIT CHANGE - ditto
@@ -575,8 +575,6 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
user.do_attack_animation(M)
user.adjustStaminaLossBuffered(10)//CIT CHANGE - makes eyestabbing cost stamina
if(M != user)
M.visible_message("<span class='danger'>[user] has stabbed [M] in the eye with [src]!</span>", \
"<span class='userdanger'>[user] stabs you in the eye with [src]!</span>")
+16 -25
View File
@@ -25,41 +25,32 @@
return ..()
/obj/item/binoculars/proc/on_wield(obj/item/source, mob/user)
RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/unwield)
RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/on_walk)
RegisterSignal(user, COMSIG_ATOM_DIR_CHANGE, .proc/rotate)
listeningTo = user
user.visible_message("<span class='notice'>[user] holds [src] up to [user.p_their()] eyes.</span>", "<span class='notice'>You hold [src] up to your eyes.</span>")
item_state = "binoculars_wielded"
user.regenerate_icons()
if(!user?.client)
return
var/client/C = user.client
var/_x = 0
var/_y = 0
switch(user.dir)
if(NORTH)
_y = zoom_amt
if(EAST)
_x = zoom_amt
if(SOUTH)
_y = -zoom_amt
if(WEST)
_x = -zoom_amt
C.change_view(world.view + zoom_out_amt)
C.pixel_x = world.icon_size*_x
C.pixel_y = world.icon_size*_y
user.client.view_size.zoomOut(zoom_out_amt, zoom_amt, user.dir)
/obj/item/binoculars/proc/rotate(atom/thing, old_dir, new_dir)
if(ismob(thing))
var/mob/lad = thing
lad.regenerate_icons()
lad.client.view_size.zoomOut(zoom_out_amt, zoom_amt, new_dir)
/obj/item/binoculars/proc/on_walk()
attack_self(listeningTo) //Yes I have sinned, why do you ask?
/obj/item/binoculars/proc/on_unwield(obj/item/source, mob/user)
unwield(user)
/obj/item/binoculars/proc/unwield(mob/user)
if(listeningTo)
UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
UnregisterSignal(user, COMSIG_MOVABLE_MOVED)
UnregisterSignal(user, COMSIG_ATOM_DIR_CHANGE)
listeningTo = null
user.visible_message("<span class='notice'>[user] lowers [src].</span>", "<span class='notice'>You lower [src].</span>")
item_state = "binoculars"
user.regenerate_icons()
if(user && user.client)
user.regenerate_icons()
var/client/C = user.client
C.change_view(CONFIG_GET(string/default_view))
user.client.pixel_x = 0
user.client.pixel_y = 0
user.client.view_size.zoomIn()
+6 -6
View File
@@ -4,7 +4,7 @@
/obj/item/defibrillator
name = "defibrillator"
desc = "A device that delivers powerful shocks to detachable paddles that resuscitate incapacitated patients."
icon = 'icons/obj/items_and_weapons.dmi'
icon = 'icons/obj/defibrillators.dmi'
icon_state = "defibunit"
item_state = "defibunit"
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
@@ -23,8 +23,8 @@
var/obj/item/stock_parts/cell/cell
var/combat = FALSE //can we revive through space suits?
var/grab_ghost = FALSE // Do we pull the ghost back into their body?
var/healdisk = FALSE // Will we shock people dragging the body?
var/pullshocksafely = FALSE //Dose the unit have the healdisk upgrade?
var/healdisk = FALSE // Does the unit have the healdisk upgrade?
var/pullshocksafely = FALSE // Will we shock people dragging the body?
var/primetime = 0 // is the defib faster
var/timedeath = 10
var/disarm_shock_time = 10
@@ -261,7 +261,7 @@
/obj/item/shockpaddles
name = "defibrillator paddles"
desc = "A pair of plastic-gripped paddles with flat metal surfaces that are used to deliver powerful electric shocks."
icon = 'icons/obj/items_and_weapons.dmi'
icon = 'icons/obj/defibrillators.dmi'
icon_state = "defibpaddles0"
item_state = "defibpaddles0"
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
@@ -682,7 +682,7 @@
/obj/item/shockpaddles/cyborg
name = "cyborg defibrillator paddles"
icon = 'icons/obj/items_and_weapons.dmi'
icon = 'icons/obj/defibrillators.dmi'
icon_state = "defibpaddles0"
item_state = "defibpaddles0"
req_defib = FALSE
@@ -703,7 +703,7 @@
name = "syndicate defibrillator paddles"
desc = "A pair of paddles used to revive deceased operatives. It possesses both the ability to penetrate armor and to deliver powerful shocks offensively."
combat = TRUE
icon = 'icons/obj/items_and_weapons.dmi'
icon = 'icons/obj/defibrillators.dmi'
icon_state = "defibpaddles0"
item_state = "defibpaddles0"
req_defib = FALSE
@@ -366,6 +366,11 @@
flashlight_power = 0.8
custom_price = PRICE_CHEAP
/obj/item/flashlight/lantern/heirloom_moth
name = "old lantern"
desc = "An old lantern that has seen plenty of use."
light_range = 4
/obj/item/flashlight/lantern/jade
name = "jade lantern"
desc = "An ornate, green lantern."
@@ -19,7 +19,8 @@
var/starting_tape_type = /obj/item/tape/random
var/open_panel = 0
var/canprint = 1
var/list/icons_available = list()
var/icon_directory = 'icons/radials/taperecorder.dmi'
/obj/item/taperecorder/Initialize(mapload)
. = ..()
@@ -32,6 +33,29 @@
. = ..()
. += "The wire panel is [open_panel ? "opened" : "closed"]."
/obj/item/taperecorder/AltClick(mob/user)
. = ..()
play()
/obj/item/taperecorder/proc/update_available_icons()
icons_available = list()
if(recording)
icons_available += list("Stop Recording" = image(icon = icon_directory, icon_state = "record_stop"))
else
if(!playing)
icons_available += list("Record" = image(icon = icon_directory, icon_state = "record"))
if(playing)
icons_available += list("Pause" = image(icon = icon_directory, icon_state = "pause"))
else
if(!recording)
icons_available += list("Play" = image(icon = icon_directory, icon_state = "play"))
if(canprint && !recording && !playing)
icons_available += list("Print Transcript" = image(icon = icon_directory, icon_state = "print"))
if(mytape)
icons_available += list("Eject" = image(icon = icon_directory, icon_state = "eject"))
/obj/item/taperecorder/attackby(obj/item/I, mob/user, params)
if(!mytape && istype(I, /obj/item/tape))
@@ -69,7 +93,6 @@
return TRUE
return FALSE
/obj/item/taperecorder/verb/ejectverb()
set name = "Eject Tape"
set category = "Object"
@@ -81,7 +104,6 @@
eject(usr)
/obj/item/taperecorder/update_icon_state()
if(!mytape)
icon_state = "taperecorder_empty"
@@ -92,7 +114,6 @@
else
icon_state = "taperecorder_idle"
/obj/item/taperecorder/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans, message_mode, atom/movable/source)
. = ..()
if(mytape && recording)
@@ -193,13 +214,31 @@
/obj/item/taperecorder/attack_self(mob/user)
if(!mytape || mytape.ruined)
if(!mytape)
to_chat(user, "<span class='notice'>The [src] does not have a tape inside.</span>")
return
if(mytape.ruined)
to_chat(user, "<span class='notice'>The tape inside the [src] appears to be broken.</span>")
return
if(recording)
stop()
else
record()
update_available_icons()
if(icons_available)
var/selection = show_radial_menu(user, src, icons_available, radius = 38, require_near = TRUE, tooltips = TRUE)
if(!selection)
return
switch(selection)
if("Pause")
stop()
if("Stop Recording") // yes we actually need 2 seperate stops for the same proc- Hopek
stop()
if("Record")
record()
if("Play")
play()
if("Print Transcript")
print_transcript()
if("Eject")
eject(user)
/obj/item/taperecorder/verb/print_transcript()
set name = "Print Transcript"
+2 -5
View File
@@ -21,12 +21,11 @@
var/can_block_projectiles = FALSE //can't block guns
var/lethal_cost = 400 //10000/400*20 = 500. decent enough?
var/lethal_damage = 20
var/lethal_stam_cost = 4
var/stun_cost = 333 //10000/333*25 = 750. stunbatons are at time of writing 10000/1000*49 = 490.
var/stun_status_effect = STATUS_EFFECT_ELECTROSTAFF //a small slowdown effect
var/stun_stamdmg = 40
var/stun_status_duration = 25
var/stun_stam_cost = 3.5
var/stam_cost = 3.5
var/wielded = FALSE // track wielded status on item
// haha security desword time /s
@@ -171,7 +170,7 @@
turn_off()
/obj/item/electrostaff/attack(mob/living/target, mob/living/user)
if(IS_STAMCRIT(user))//CIT CHANGE - makes it impossible to baton in stamina softcrit
if(IS_STAMCRIT(user) || !user.UseStaminaBuffer(stam_cost))//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>")//CIT CHANGE - ditto
return //CIT CHANGE - ditto
if(on && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
@@ -186,13 +185,11 @@
if(user.a_intent != INTENT_HARM)
if(stun_act(target, user, null, return_list))
user.do_attack_animation(target)
user.adjustStaminaLossBuffered(stun_stam_cost)
return
else if(!harm_act(target, user, null, return_list))
return ..() //if you can't fry them just beat them with it
else //we did harm act them
user.do_attack_animation(target)
user.adjustStaminaLossBuffered(lethal_stam_cost)
/obj/item/electrostaff/proc/stun_act(mob/living/target, mob/living/user, no_charge_and_force = FALSE, list/block_return = list())
var/stunforce = block_calculate_resultant_damage(stun_stamdmg, block_return)
+2 -2
View File
@@ -40,11 +40,11 @@
//What does the implant do upon injection?
//return 1 if the implant injects
//return 0 if there is no room for implant / it fails
/obj/item/implant/proc/implant(mob/living/target, mob/user, silent = FALSE)
/obj/item/implant/proc/implant(mob/living/target, mob/user, silent = FALSE, force = FALSE)
if(SEND_SIGNAL(src, COMSIG_IMPLANT_IMPLANTING, args) & COMPONENT_STOP_IMPLANTING)
return
LAZYINITLIST(target.implants)
if(!target.can_be_implanted() || !can_be_implanted_in(target))
if(!force && (!target.can_be_implanted() || !can_be_implanted_in(target)))
return FALSE
for(var/X in target.implants)
var/obj/item/implant/imp_e = X
@@ -40,17 +40,80 @@
/obj/item/implant/warp
name = "warp implant"
desc = "Saves your position somewhere, and then warps you back to it after five seconds."
desc = "Warps you to where you were 10 seconds before when activated."
icon_state = "warp"
uses = 15
uses = -1
var/total_delay = 10 SECONDS
var/cooldown = 10 SECONDS
var/last_use = 0
var/list/positions = list()
var/next_prune = 0
/obj/item/implant/warp/Destroy()
positions = null
return ..()
/obj/item/implant/warp/implant(mob/living/target, mob/user, silent, force)
. = ..()
if(.)
update_position()
RegisterSignal(imp_in, COMSIG_MOVABLE_MOVED, .proc/update_position)
/obj/item/implant/warp/removed(mob/living/source, silent, special)
. = ..()
clear_positions()
/obj/item/implant/warp/proc/update_position(datum/source)
if(!isatom(imp_in.loc))
return
positions[num2text(world.time)] = imp_in.loc
if(!((++next_prune) % 10))
prune()
/obj/item/implant/warp/proc/clear_positions()
positions = list()
/obj/item/implant/warp/proc/get_tele_position()
prune()
return positions[positions[1]]
/obj/item/implant/warp/proc/do_teleport_effects()
var/safety = 100
var/list/done = list()
var/time
var/turf/target
for(var/i in 1 to positions.len)
if(!--safety)
break
time = positions[i]
target = positions[time]
if(done[target])
continue
done[target] = TRUE
if(!istype(target))
continue
new /obj/effect/temp_visual/dir_setting/ninja(target)
/obj/item/implant/warp/activate()
. = ..()
uses--
imp_in.do_adrenaline(20, 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)
if(last_use + cooldown > world.time)
to_chat(imp_in, "<span class=warning'>[src] is still recharging!</span>")
return
last_use = world.time
prune()
do_teleport_effects() //first.
do_teleport(imp_in, get_tele_position(), 0, TRUE, null, null, null, null, null, TELEPORT_CHANNEL_QUANTUM, TRUE)
/obj/item/implant/warp/proc/prune()
var/minimum_time = world.time - total_delay
var/remove = 0
for(var/i in 1 to length(positions))
if(text2num(positions[i]) < minimum_time)
remove++
else
break
if(remove)
positions.Cut(1, remove + 1)
/obj/item/implanter/warp
name = "implanter (warp)"
+26 -2
View File
@@ -165,6 +165,30 @@
throwforce = 15
bayonet = TRUE
/obj/item/kitchen/knife/combat/survival/knuckledagger
name = "survival dagger"
icon_state = "glaive-dagger"
desc = "An enhanced hunting grade survival dagger, with a bright light and a handguard that makes it better for efficient butchery."
actions_types = list(/datum/action/item_action/toggle_light)
var/light_on = FALSE
var/brightness_on = 7
/obj/item/kitchen/knife/combat/survival/knuckledagger/Initialize()
. = ..()
AddComponent(/datum/component/butchering, 50, 120, 5) // it's good for butchering stuff
/obj/item/kitchen/knife/combat/survival/knuckledagger/ui_action_click(mob/user, actiontype)
light_on = !light_on
playsound(user, 'sound/weapons/empty.ogg', 100, TRUE)
update_brightness(user)
update_icon()
/obj/item/kitchen/knife/combat/survival/knuckledagger/proc/update_brightness(mob/user = null)
if(light_on)
set_light(brightness_on)
else
set_light(0)
/obj/item/kitchen/knife/combat/bone
name = "bone dagger"
item_state = "bone_dagger"
@@ -222,10 +246,10 @@
/* Trays moved to /obj/item/storage/bag */
/obj/item/kitchen/knife/scimitar
name = "Scimitar knife"
name = "scimitar knife"
desc = "A knife used to cleanly butcher. Its razor-sharp edge has been honed for butchering, but has been poorly maintained over the years."
attack_verb = list("cleaved", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
/obj/item/kitchen/knife/scimiar/Initialize()
/obj/item/kitchen/knife/scimitar/Initialize()
. = ..()
AddComponent(/datum/component/butchering, 90 - force, 100, force - 60) //bonus chance increases depending on force
+82 -12
View File
@@ -190,12 +190,53 @@
/obj/item/melee/transforming/energy/sword/saber
possible_colors = list("red" = LIGHT_COLOR_RED, "blue" = LIGHT_COLOR_LIGHT_CYAN, "green" = LIGHT_COLOR_GREEN, "purple" = LIGHT_COLOR_LAVENDER)
unique_reskin = list("Sword" = "sword0", "saber" = "esaber0")
var/hacked = FALSE
var/saber = FALSE
/obj/item/melee/transforming/energy/sword/saber/set_sword_color()
if(LAZYLEN(possible_colors))
/obj/item/melee/transforming/energy/sword/saber/transform_weapon(mob/living/user, supress_message_text)
. = ..()
if(.)
if(active)
if(sword_color)
if(saber)
icon_state = "esaber[sword_color]"
else
icon_state = "sword[sword_color]"
else
if(saber)
icon_state = "esaber0"
else
icon_state = "sword0"
/obj/item/melee/transforming/energy/sword/saber/reskin_obj(mob/M)
. = ..()
if(icon_state == "esaber0")
saber = TRUE
if(active)
if(saber)
icon_state = "esaber[sword_color]"
else
icon_state = "sword[sword_color]"
/obj/item/melee/transforming/energy/sword/saber/set_sword_color(var/color_forced)
if(color_forced) // wow i really do not like this at fucking all holy SHIT
if(color_forced == "red")
sword_color = "red"
light_color = LIGHT_COLOR_RED
else if(color_forced == "blue")
sword_color = "blue"
light_color = LIGHT_COLOR_LIGHT_CYAN
else if(color_forced == "green")
sword_color = "green"
light_color = LIGHT_COLOR_GREEN
else if(color_forced == "purple")
sword_color = "purple"
light_color = LIGHT_COLOR_LAVENDER
else if(LAZYLEN(possible_colors))
sword_color = pick(possible_colors)
light_color = possible_colors[sword_color]
return
/obj/item/melee/transforming/energy/sword/saber/process()
. = ..()
@@ -204,30 +245,59 @@
light_color = possible_colors[set_color]
update_light()
/obj/item/melee/transforming/energy/sword/saber/red
possible_colors = list("red" = LIGHT_COLOR_RED)
/obj/item/melee/transforming/energy/sword/saber/red/Initialize(mapload)
. = ..()
set_sword_color("red")
/obj/item/melee/transforming/energy/sword/saber/blue
possible_colors = list("blue" = LIGHT_COLOR_LIGHT_CYAN)
/obj/item/melee/transforming/energy/sword/saber/blue/Initialize(mapload)
. = ..()
set_sword_color("blue")
/obj/item/melee/transforming/energy/sword/saber/green
possible_colors = list("green" = LIGHT_COLOR_GREEN)
/obj/item/melee/transforming/energy/sword/saber/green/Initialize(mapload)
. = ..()
set_sword_color("green")
/obj/item/melee/transforming/energy/sword/saber/purple
possible_colors = list("purple" = LIGHT_COLOR_LAVENDER)
/obj/item/melee/transforming/energy/sword/saber/purple/Initialize(mapload)
. = ..()
set_sword_color("purple")
/obj/item/melee/transforming/energy/sword/saber/proc/select_sword_color(mob/user) /// this is for the radial
if(!istype(user) || user.incapacitated())
return
var/static/list/options = list(
"red" = image(icon = 'icons/obj/items_and_weapons.dmi', icon_state = "swordred-blade"),
"blue" = image(icon = 'icons/obj/items_and_weapons.dmi', icon_state = "swordblue-blade"),
"green" = image(icon = 'icons/obj/items_and_weapons.dmi', icon_state = "swordgreen-blade"),
"purple" = image(icon = 'icons/obj/items_and_weapons.dmi', icon_state = "swordpurple-blade")
)
var/choice = show_radial_menu(user, src, options, custom_check = FALSE, radius = 36, require_near = TRUE)
if(src && choice && !user.incapacitated() && in_range(user,src))
set_sword_color(choice)
to_chat(user, "<span class='notice'>[src] is now [choice].</span>")
/obj/item/melee/transforming/energy/sword/saber/attackby(obj/item/W, mob/living/user, params)
if(istype(W, /obj/item/multitool))
if(user.a_intent == INTENT_DISARM)
if(!active)
to_chat(user, "<span class='warning'>COLOR_SET</span>")
hacked = FALSE
select_sword_color(user)
return
else
to_chat(user, "<span class='notice'>Turn it off first - getting that close to an active sword is not a great idea.</span>")
return
if(!hacked)
hacked = TRUE
sword_color = "rainbow"
to_chat(user, "<span class='warning'>RNBW_ENGAGE</span>")
if(active)
icon_state = "swordrainbow"
user.update_inv_hands()
else
to_chat(user, "<span class='warning'>It's already fabulous!</span>")
to_chat(user, "<span class='warning'>It's already fabulous!</span> <span class='notice'>If you wanted to reset the color, though, try a disarming intent while it's off.</span>")
else
return ..()
+2 -1
View File
@@ -352,6 +352,8 @@
return
else
if(cooldown_check < world.time)
if(!UseStaminaBufferStandard(user, STAM_COST_BATON_MOB_MULT, warn = TRUE))
return DISCARD_LAST_ACTION
if(target.mob_run_block(src, 0, "[user]'s [name]", ATTACK_TYPE_MELEE, 0, user, null, null) & BLOCK_SUCCESS)
playsound(target, 'sound/weapons/genhit.ogg', 50, 1)
return
@@ -373,7 +375,6 @@
else
target.LAssailant = WEAKREF(user)
cooldown_check = world.time + cooldown
user.adjustStaminaLossBuffered(getweight(user, STAM_COST_BATON_MOB_MULT))
else
var/wait_desc = get_wait_description()
if(wait_desc)
+1 -1
View File
@@ -62,7 +62,7 @@
msg = "You hear something crackle in your ears for a moment before a voice speaks. \"Please stand by for a message from Central Command. Message as follows: <span class='bold'>Item request received. Your package is inbound, please stand back from the landing site.</span> Message ends.\""
to_chat(M, msg)
new /obj/effect/abstract/DPtarget(get_turf(src), pod)
new /obj/effect/pod_landingzone(get_turf(src), pod)
/obj/item/choice_beacon/ingredients
name = "ingredient box delivery beacon"
+2 -4
View File
@@ -56,22 +56,20 @@
return
if(T)
if(!L.UseStaminaBuffer(stamusage, warn = TRUE))
return
user.visible_message("[user] cleans \the [T] with [src].", "<span class='notice'>You clean \the [T] with [src].</span>")
clean(T)
user.DelayNextAction(CLICK_CD_MELEE)
user.do_attack_animation(T, used_item = src)
if(istype(L))
L.adjustStaminaLossBuffered(stamusage)
playsound(T, "slosh", 50, 1)
/obj/effect/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/mop) || istype(I, /obj/item/soap))
return
else
return ..()
/obj/item/mop/proc/janicart_insert(mob/user, obj/structure/janitorialcart/J)
if(insertable)
J.put_in_cart(src, user)
+9 -1
View File
@@ -199,4 +199,12 @@
/obj/item/pinpointer/shuttle/Destroy()
shuttleport = null
. = ..()
. = ..()
/obj/item/pinpointer/ian
name = "ian pinpointer"
desc = "A handheld tracking device that locates Ian. Made with real corgis!"
icon_state = "pinpointer_ian"
/obj/item/pinpointer/ian/scan_for_target()
target = locate(/mob/living/simple_animal/pet/dog/corgi/Ian) in GLOB.mob_living_list
+11 -6
View File
@@ -150,6 +150,7 @@
if(squeak_override)
var/datum/component/squeak/S = GetComponent(/datum/component/squeak)
S?.override_squeak_sounds = squeak_override
snowflake_id = id
/obj/item/toy/plush/handle_atom_del(atom/A)
if(A == grenade)
@@ -827,12 +828,16 @@ GLOBAL_LIST_INIT(valid_plushie_paths, valid_plushie_paths())
if(!victim)
return
visible_message("<span class='warning'>[src] gruesomely mutilliates [victim], leaving nothing more than dust!</span>")
name = victim.name
desc = victim.desc + " Wait, did it just move..?"
icon_state = victim.icon_state
item_state = victim.item_state
squeak_override = victim.squeak_override
attack_verb = victim.attack_verb
if(victim.snowflake_id) //Snowflake code for snowflake plushies.
set_snowflake_from_config(victim.snowflake_id)
desc += " Wait, did it just move..?"
else
name = victim.name
desc = victim.desc + " Wait, did it just move..?"
icon_state = victim.icon_state
item_state = victim.item_state
squeak_override = victim.squeak_override
attack_verb = victim.attack_verb
new /obj/effect/decal/cleanable/ash(get_turf(victim))
qdel(victim)
+4 -5
View File
@@ -6,7 +6,7 @@
lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
flags_1 = CONDUCT_1
item_flags = NEEDS_PERMIT | NO_COMBAT_MODE_FORCE_MODIFIER //To avoid ambushing and oneshotting healthy crewmembers on force setting 3.
item_flags = NEEDS_PERMIT
attack_verb = list("whacked", "fisted", "power-punched")
force = 20
throwforce = 10
@@ -76,6 +76,9 @@
if(!tank)
to_chat(user, "<span class='warning'>\The [src] can't operate without a source of gas!</span>")
return FALSE
var/weight = getweight(user, STAM_COST_ATTACK_MOB_MULT)
if(!user.UseStaminaBuffer(weight, warn = TRUE))
return FALSE
var/datum/gas_mixture/gasused = tank.air_contents.remove(gasperfist * fisto_setting)
var/turf/T = get_turf(src)
if(!T)
@@ -108,8 +111,4 @@
target.throw_at(throw_target, 5 * fisto_setting, 0.5 + (fisto_setting / 2))
log_combat(user, target, "power fisted", src)
var/weight = getweight(user, STAM_COST_ATTACK_MOB_MULT)
if(weight)
user.adjustStaminaLossBuffered(weight)
return TRUE
@@ -27,6 +27,13 @@
return FALSE
return TRUE
/*
This proc gets called by upgrades after installing them. Use this for things that for example need to be moved into a specific borg item,
as performing this in action() will cause the upgrade to end up in the borg instead of its intended location due to forceMove() being called afterwards..
*/
/obj/item/borg/upgrade/proc/afterInstall(mob/living/silicon/robot/R, user = usr)
return
/obj/item/borg/upgrade/proc/deactivate(mob/living/silicon/robot/R, user = usr)
if (!(src in R.upgrades))
return FALSE
+4 -2
View File
@@ -136,15 +136,17 @@
if(!(shield_flags & SHIELD_BASH_GROUND_SLAM))
to_chat(user, "<span class='warning'>You can't ground slam with [src]!</span>")
return FALSE
if(!user.UseStaminaBuffer(shieldbash_stamcost, warn = TRUE))
return FALSE
bash_target(user, target, NONE, harmful)
user.do_attack_animation(target, used_item = src)
playsound(src, harmful? "swing_hit" : 'sound/weapons/thudswoosh.ogg', 75, 1)
last_shieldbash = world.time
user.adjustStaminaLossBuffered(shieldbash_stamcost)
return TRUE
// Directional sweep!
last_shieldbash = world.time
user.adjustStaminaLossBuffered(shieldbash_stamcost)
if(!user.UseStaminaBuffer(shieldbash_stamcost, warn = TRUE))
return FALSE
// Since we are in combat mode, we can probably safely use the user's dir instead of getting their mouse pointing cardinal dir.
var/bashdir = user.dir
do_shieldbash_effect(user, bashdir, harmful)
@@ -211,6 +211,12 @@
turf_type = /turf/open/floor/carpet/black
tableVariant = /obj/structure/table/wood/fancy/black
/obj/item/stack/tile/carpet/arcade
name = "arcade carpet"
icon_state = "tile-carpet-arcade"
turf_type = /turf/open/floor/carpet/arcade
tableVariant = null
/obj/item/stack/tile/carpet/blackred
name = "red carpet"
icon_state = "tile-carpet-blackred"
@@ -297,6 +303,15 @@
/obj/item/stack/tile/carpet/black/fifty
amount = 50
/obj/item/stack/tile/carpet/arcade/ten
amount = 10
/obj/item/stack/tile/carpet/arcade/twenty
amount = 20
/obj/item/stack/tile/carpet/arcade/fifty
amount = 50
/obj/item/stack/tile/carpet/blackred/ten
amount = 10
+1 -1
View File
@@ -234,7 +234,7 @@
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.max_combined_w_class = 100
STR.max_items = 100
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food/snacks/grown, /obj/item/seeds, /obj/item/grown, /obj/item/reagent_containers/honeycomb))
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food/snacks/grown, /obj/item/seeds, /obj/item/grown, /obj/item/reagent_containers/honeycomb, /obj/item/disk/plantgene))
////////
+25
View File
@@ -830,3 +830,28 @@
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 2
STR.max_w_class = WEIGHT_CLASS_BULKY + WEIGHT_CLASS_NORMAL //katana and waki.
/obj/item/storage/belt/plant
name = "botanical belt"
desc = "A belt used to hold most hydroponics supplies. Suprisingly, not green."
icon_state = "plantbelt"
item_state = "plantbelt"
content_overlays = TRUE
/obj/item/storage/belt/plant/ComponentInitialize()
. = ..()
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 6
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.can_hold = typecacheof(list(
/obj/item/reagent_containers/spray/plantbgone,
/obj/item/plant_analyzer,
/obj/item/seeds,
/obj/item/reagent_containers/glass/bottle,
/obj/item/reagent_containers/glass/beaker,
/obj/item/cultivator,
/obj/item/reagent_containers/spray/pestspray,
/obj/item/hatchet,
/obj/item/shovel/spade,
/obj/item/gun/energy/floragun
))
+4 -2
View File
@@ -166,13 +166,12 @@
if(turned_on)
if(baton_stun(M, user, disarming))
user.do_attack_animation(M)
user.adjustStaminaLossBuffered(getweight(user, STAM_COST_BATON_MOB_MULT))
else if(user.a_intent != INTENT_HARM) //they'll try to bash in the last proc.
M.visible_message("<span class='warning'>[user] has prodded [M] with [src]. Luckily it was off.</span>", \
"<span class='warning'>[user] has prodded you with [src]. Luckily it was off</span>")
return disarming || (user.a_intent != INTENT_HARM)
/obj/item/melee/baton/proc/baton_stun(mob/living/L, mob/user, disarming = FALSE)
/obj/item/melee/baton/proc/baton_stun(mob/living/L, mob/living/user, disarming = FALSE)
var/list/return_list = list()
if(L.mob_run_block(src, 0, "[user]'s [name]", ATTACK_TYPE_MELEE, 0, user, null, return_list) & BLOCK_SUCCESS) //No message; check_shields() handles that
playsound(L, 'sound/weapons/genhit.ogg', 50, 1)
@@ -194,6 +193,9 @@
return FALSE
stunpwr *= round(stuncharge/hitcost, 0.1)
if(!user.UseStaminaBuffer(getweight(user, STAM_COST_BATON_MOB_MULT), warn = TRUE))
return FALSE
if(!disarming)
if(knockdown)
L.DefaultCombatKnockdown(50, override_stamdmg = 0) //knockdown
+3
View File
@@ -55,6 +55,8 @@
RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/move_react)
if(full_speed)
user.add_movespeed_modifier(/datum/movespeed_modifier/jetpack/fullspeed)
else
user.add_movespeed_modifier(/datum/movespeed_modifier/jetpack)
/obj/item/tank/jetpack/proc/turn_off(mob/user)
on = FALSE
@@ -63,6 +65,7 @@
ion_trail.stop()
UnregisterSignal(user, COMSIG_MOVABLE_MOVED)
user.remove_movespeed_modifier(/datum/movespeed_modifier/jetpack/fullspeed)
user.remove_movespeed_modifier(/datum/movespeed_modifier/jetpack)
/obj/item/tank/jetpack/proc/move_react(mob/user)
allow_thrust(0.01, user)
+3
View File
@@ -37,6 +37,9 @@
icon_state = "crowbar_clock"
toolspeed = 0.5
/obj/item/crowbar/brass/family
toolspeed = 1
/obj/item/crowbar/bronze
name = "bronze plated crowbar"
desc = "A bronze plated crowbar."
+4 -1
View File
@@ -89,6 +89,9 @@
toolspeed = 0.5
random_color = FALSE
/obj/item/screwdriver/brass/family
toolspeed = 1
/obj/item/screwdriver/bronze
name = "bronze screwdriver"
desc = "A screwdriver plated with bronze."
@@ -158,4 +161,4 @@
item_state = "screwdriver_nuke"
usesound = 'sound/items/pshoom.ogg'
toolspeed = 0.2
random_color = FALSE
random_color = FALSE
@@ -69,6 +69,9 @@
random_color = FALSE
toolspeed = 0.5
/obj/item/wirecutters/brass/family
toolspeed = 1
/obj/item/wirecutters/bronze
name = "bronze plated wirecutters"
desc = "A pair of wirecutters plated with bronze."
+3
View File
@@ -40,6 +40,9 @@
icon_state = "wrench_clock"
toolspeed = 0.5
/obj/item/wrench/brass/family
toolspeed = 1
/obj/item/wrench/bronze
name = "bronze plated wrench"
desc = "A bronze plated wrench."
+29 -11
View File
@@ -304,18 +304,36 @@
/obj/proc/reskin_obj(mob/M)
if(!LAZYLEN(unique_reskin))
return
var/list/skins = list()
for(var/S in unique_reskin)
skins[S] = image(icon = icon, icon_state = unique_reskin[S])
var/choice = show_radial_menu(M, src, skins, custom_check = CALLBACK(src, .proc/check_skinnable, M), radius = 40, require_near = TRUE)
if(!choice)
return FALSE
icon_state = unique_reskin[choice]
current_skin = choice
return
/obj/proc/check_skinnable(/mob/M)
if(current_skin || !always_reskinnable)
var/list/items = list()
for(var/reskin_option in unique_reskin)
var/image/item_image = image(icon = src.icon, icon_state = unique_reskin[reskin_option])
items += list("[reskin_option]" = item_image)
sortList(items)
var/pick = show_radial_menu(M, src, items, custom_check = CALLBACK(src, .proc/check_reskin_menu, M), radius = 38, require_near = TRUE)
if(!pick)
return
if(!unique_reskin[pick])
return
current_skin = pick
icon_state = unique_reskin[pick]
to_chat(M, "[src] is now skinned as '[pick].'")
/**
* Checks if we are allowed to interact with a radial menu for reskins
*
* Arguments:
* * user The mob interacting with the menu
*/
/obj/proc/check_reskin_menu(mob/user)
if(QDELETED(src))
return FALSE
if(current_skin)
return FALSE
if(!istype(user))
return FALSE
if(user.incapacitated())
return FALSE
return TRUE
+4
View File
@@ -98,6 +98,10 @@
/obj/structure/holosign/barrier/firelock/BlockSuperconductivity()
return TRUE
/obj/structure/holosign/barrier/firelock/Initialize()
. = ..()
air_update_turf(TRUE)
/obj/structure/holosign/barrier/combifan
name = "holo combifan"
desc = "A holographic barrier resembling a blue-accented tiny fan. Though it does not prevent solid objects from passing through, gas and temperature changes are kept out."
+2 -2
View File
@@ -100,7 +100,7 @@
number_of_rods = 2
smooth = SMOOTH_TRUE
canSmoothWith = null
obj_flags = CAN_BE_HIT | BLOCK_Z_FALL
obj_flags = CAN_BE_HIT | BLOCK_Z_OUT_DOWN | BLOCK_Z_IN_UP
/obj/structure/lattice/catwalk/deconstruction_hints(mob/user)
to_chat(user, "<span class='notice'>The supporting rods look like they could be <b>cut</b>.</span>")
@@ -159,7 +159,7 @@
color = "#5286b9ff"
smooth = SMOOTH_TRUE
canSmoothWith = null
obj_flags = CAN_BE_HIT | BLOCK_Z_FALL
obj_flags = CAN_BE_HIT | BLOCK_Z_OUT_DOWN | BLOCK_Z_IN_UP
resistance_flags = FIRE_PROOF | LAVA_PROOF
/obj/structure/lattice/lava/deconstruction_hints(mob/user)
@@ -11,7 +11,7 @@
max_integrity = 100
buckle_lying = FALSE
layer = ABOVE_MOB_LAYER
var/view_range = 10
var/view_range = 3
var/cooldown = 0
var/projectile_type = /obj/item/projectile/bullet/manned_turret
var/rate_of_fire = 1
@@ -38,7 +38,7 @@
buckled_mob.pixel_x = 0
buckled_mob.pixel_y = 0
if(buckled_mob.client)
buckled_mob.client.change_view(CONFIG_GET(string/default_view))
buckled_mob.client.view_size.resetToDefault()
anchored = FALSE
. = ..()
STOP_PROCESSING(SSfastprocess, src)
@@ -65,7 +65,7 @@
playsound(src,'sound/mecha/mechmove01.ogg', 50, 1)
anchored = TRUE
if(M.client)
M.client.change_view(view_range)
M.client.view_size.setTo(view_range)
START_PROCESSING(SSfastprocess, src)
/obj/machinery/manned_turret/process()
+2 -2
View File
@@ -163,7 +163,7 @@
var/custom_tone = input(user, "Choose your custom skin tone:", "Race change", default) as color|null
if(custom_tone)
var/temp_hsv = RGBtoHSV(new_s_tone)
if(ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3])
if(ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3])
to_chat(H,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
else
H.skin_tone = custom_tone
@@ -177,7 +177,7 @@
if(new_mutantcolor)
var/temp_hsv = RGBtoHSV(new_mutantcolor)
if(ReadHSV(temp_hsv)[3] >= ReadHSV("#7F7F7F")[3]) // mutantcolors must be bright
if(ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3]) // mutantcolors must be bright
H.dna.features["mcolor"] = sanitize_hexcolor(new_mutantcolor)
else
+2 -2
View File
@@ -73,7 +73,7 @@
if(user.grab_state < GRAB_AGGRESSIVE)
to_chat(user, "<span class='warning'>You need a better grip to do that!</span>")
return
if(user.grab_state >= GRAB_NECK)
if(user.grab_state >= GRAB_NECK || HAS_TRAIT(user, TRAIT_MAULER))
tablelimbsmash(user, pushed_mob)
else
tablepush(user, pushed_mob)
@@ -147,7 +147,7 @@
pushed_mob.Knockdown(30)
var/obj/item/bodypart/banged_limb = pushed_mob.get_bodypart(user.zone_selected) || pushed_mob.get_bodypart(BODY_ZONE_HEAD)
var/extra_wound = 0
if(HAS_TRAIT(user, TRAIT_HULK))
if(HAS_TRAIT(user, TRAIT_HULK) || HAS_TRAIT(user, TRAIT_MAULER))
extra_wound = 20
banged_limb.receive_damage(30, wound_bonus = extra_wound)
pushed_mob.apply_damage(60, STAMINA)
+2 -5
View File
@@ -131,15 +131,12 @@
return ..()
/obj/structure/toilet/secret
var/obj/item/secret
var/secret_type = null
/obj/structure/toilet/secret/Initialize(mapload)
/obj/structure/toilet/secret/Initialize()
. = ..()
if (secret_type)
secret = new secret_type(src)
secret.desc += "" //In case you want to add something to the item that spawns
contents += secret
new secret_type(src)
/obj/structure/toilet/secret/LateInitialize()
. = ..()