Merge remote-tracking branch 'refs/remotes/Citadel-Station-13/master' into syntheticbloods

This commit is contained in:
Poojawa
2019-10-01 00:05:44 -05:00
61 changed files with 846 additions and 415 deletions
+3
View File
@@ -266,3 +266,6 @@
#define BODYPART_LIFE_UPDATE_HEALTH (1<<0)
#define HUMAN_FIRE_STACK_ICON_NUM 3
#define PULL_PRONE_SLOWDOWN 0.6
#define HUMAN_CARRY_SLOWDOWN 0
+3
View File
@@ -31,3 +31,6 @@
#define MOVESPEED_ID_PAI_SPACEWALK_SPEEDMOD "PAI_SPACEWALK_MODIFIER"
#define MOVESPEED_ID_SANITY "MOOD_SANITY"
#define MOVESPEED_ID_PRONE_DRAGGING "PRONE_DRAG"
#define MOVESPEED_ID_HUMAN_CARRYING "HUMAN_CARRY"
+3
View File
@@ -791,3 +791,6 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
rearranged += cword
message = "[prefix][jointext(rearranged," ")]"
. = message
#define is_alpha(X) ((text2ascii(X) <= 122) && (text2ascii(X) >= 97))
#define is_digit(X) ((length(X) == 1) && (length(text2num(X)) == 1))
+107 -107
View File
@@ -1,108 +1,108 @@
/datum/component/footstep
var/steps = 0
var/volume
var/e_range
/datum/component/footstep/Initialize(volume_ = 0.5, e_range_ = -1)
if(!isliving(parent))
return COMPONENT_INCOMPATIBLE
volume = volume_
e_range = e_range_
RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED), .proc/play_footstep)
/datum/component/footstep/proc/play_footstep()
var/turf/open/T = get_turf(parent)
if(!istype(T))
return
var/mob/living/LM = parent
var/v = volume
var/e = e_range
if(!T.footstep || LM.buckled || LM.lying || !LM.canmove || LM.resting || LM.buckled || LM.throwing || LM.movement_type & (VENTCRAWLING | FLYING))
if (LM.lying && !LM.buckled && !(!T.footstep || LM.movement_type & (VENTCRAWLING | FLYING))) //play crawling sound if we're lying
playsound(T, 'sound/effects/footstep/crawl1.ogg', 15 * v)
return
if(HAS_TRAIT(LM, TRAIT_SILENT_STEP))
return
if(iscarbon(LM))
var/mob/living/carbon/C = LM
if(!C.get_bodypart(BODY_ZONE_L_LEG) && !C.get_bodypart(BODY_ZONE_R_LEG))
return
if(ishuman(C) && C.m_intent == MOVE_INTENT_WALK)
v /= 2
e -= 5
steps++
if(steps >= 3)
steps = 0
else
return
if(prob(80) && !LM.has_gravity(T)) // don't need to step as often when you hop around
return
//begin playsound shenanigans//
//for barefooted non-clawed mobs like monkeys
if(isbarefoot(LM))
playsound(T, pick(GLOB.barefootstep[T.barefootstep][1]),
GLOB.barefootstep[T.barefootstep][2] * v,
TRUE,
GLOB.barefootstep[T.barefootstep][3] + e)
return
//for xenomorphs, dogs, and other clawed mobs
if(isclawfoot(LM))
if(isalienadult(LM)) //xenos are stealthy and get quieter footsteps
v /= 3
e -= 5
playsound(T, pick(GLOB.clawfootstep[T.clawfootstep][1]),
GLOB.clawfootstep[T.clawfootstep][2] * v,
TRUE,
GLOB.clawfootstep[T.clawfootstep][3] + e)
return
//for megafauna and other large and imtimidating mobs such as the bloodminer
if(isheavyfoot(LM))
playsound(T, pick(GLOB.heavyfootstep[T.heavyfootstep][1]),
GLOB.heavyfootstep[T.heavyfootstep][2] * v,
TRUE,
GLOB.heavyfootstep[T.heavyfootstep][3] + e)
return
//for slimes
if(isslime(LM))
playsound(T, 'sound/effects/footstep/slime1.ogg', 15 * v)
return
//for (simple) humanoid mobs (clowns, russians, pirates, etc.)
if(isshoefoot(LM))
if(!ishuman(LM))
playsound(T, pick(GLOB.footstep[T.footstep][1]),
GLOB.footstep[T.footstep][2] * v,
TRUE,
GLOB.footstep[T.footstep][3] + e)
return
if(ishuman(LM)) //for proper humans, they're special
var/mob/living/carbon/human/H = LM
var/feetCover = (H.wear_suit && (H.wear_suit.body_parts_covered & FEET)) || (H.w_uniform && (H.w_uniform.body_parts_covered & FEET))
if (H.dna.features["taur"] == "Naga" || H.dna.features["taur"] == "Tentacle") //are we a naga or tentacle taur creature
playsound(T, 'sound/effects/footstep/crawl1.ogg', 15 * v)
return
if(H.shoes || feetCover) //are we wearing shoes
playsound(T, pick(GLOB.footstep[T.footstep][1]),
GLOB.footstep[T.footstep][2] * v,
TRUE,
GLOB.footstep[T.footstep][3] + e)
if((!H.shoes && !feetCover)) //are we NOT wearing shoes
playsound(T, pick(GLOB.barefootstep[T.barefootstep][1]),
GLOB.barefootstep[T.barefootstep][2] * v,
TRUE,
/datum/component/footstep
var/steps = 0
var/volume
var/e_range
/datum/component/footstep/Initialize(volume_ = 0.5, e_range_ = -1)
if(!isliving(parent))
return COMPONENT_INCOMPATIBLE
volume = volume_
e_range = e_range_
RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED), .proc/play_footstep)
/datum/component/footstep/proc/play_footstep()
var/turf/open/T = get_turf(parent)
if(!istype(T))
return
var/mob/living/LM = parent
var/v = volume
var/e = e_range
if(!T.footstep || LM.buckled || LM.lying || !LM.canmove || LM.resting || LM.buckled || LM.throwing || LM.movement_type & (VENTCRAWLING | FLYING))
if (LM.lying && !LM.buckled && !(!T.footstep || LM.movement_type & (VENTCRAWLING | FLYING))) //play crawling sound if we're lying
playsound(T, 'sound/effects/footstep/crawl1.ogg', 15 * v)
return
if(HAS_TRAIT(LM, TRAIT_SILENT_STEP))
return
if(iscarbon(LM))
var/mob/living/carbon/C = LM
if(!C.get_bodypart(BODY_ZONE_L_LEG) && !C.get_bodypart(BODY_ZONE_R_LEG))
return
if(ishuman(C) && C.m_intent == MOVE_INTENT_WALK)
v /= 2
e -= 5
steps++
if(steps >= 3)
steps = 0
else
return
if(prob(80) && !LM.has_gravity(T)) // don't need to step as often when you hop around
return
//begin playsound shenanigans//
//for barefooted non-clawed mobs like monkeys
if(isbarefoot(LM))
playsound(T, pick(GLOB.barefootstep[T.barefootstep][1]),
GLOB.barefootstep[T.barefootstep][2] * v,
TRUE,
GLOB.barefootstep[T.barefootstep][3] + e)
return
//for xenomorphs, dogs, and other clawed mobs
if(isclawfoot(LM))
if(isalienadult(LM)) //xenos are stealthy and get quieter footsteps
v /= 3
e -= 5
playsound(T, pick(GLOB.clawfootstep[T.clawfootstep][1]),
GLOB.clawfootstep[T.clawfootstep][2] * v,
TRUE,
GLOB.clawfootstep[T.clawfootstep][3] + e)
return
//for megafauna and other large and imtimidating mobs such as the bloodminer
if(isheavyfoot(LM))
playsound(T, pick(GLOB.heavyfootstep[T.heavyfootstep][1]),
GLOB.heavyfootstep[T.heavyfootstep][2] * v,
TRUE,
GLOB.heavyfootstep[T.heavyfootstep][3] + e)
return
//for slimes
if(isslime(LM))
playsound(T, 'sound/effects/footstep/slime1.ogg', 15 * v)
return
//for (simple) humanoid mobs (clowns, russians, pirates, etc.)
if(isshoefoot(LM))
if(!ishuman(LM))
playsound(T, pick(GLOB.footstep[T.footstep][1]),
GLOB.footstep[T.footstep][2] * v,
TRUE,
GLOB.footstep[T.footstep][3] + e)
return
if(ishuman(LM)) //for proper humans, they're special
var/mob/living/carbon/human/H = LM
var/feetCover = (H.wear_suit && (H.wear_suit.body_parts_covered & FEET)) || (H.w_uniform && (H.w_uniform.body_parts_covered & FEET))
if (H.dna.features["taur"] == "Naga" || H.dna.features["taur"] == "Tentacle") //are we a naga or tentacle taur creature
playsound(T, 'sound/effects/footstep/crawl1.ogg', 15 * v)
return
if(H.shoes || feetCover) //are we wearing shoes
playsound(T, pick(GLOB.footstep[T.footstep][1]),
GLOB.footstep[T.footstep][2] * v,
TRUE,
GLOB.footstep[T.footstep][3] + e)
if((!H.shoes && !feetCover)) //are we NOT wearing shoes
playsound(T, pick(GLOB.barefootstep[T.barefootstep][1]),
GLOB.barefootstep[T.barefootstep][2] * v,
TRUE,
GLOB.barefootstep[T.barefootstep][3] + e)
+37 -8
View File
@@ -195,21 +195,47 @@
. = ..()
RegisterSignal(parent, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, .proc/on_host_unarmed_melee)
/datum/component/riding/human/vehicle_mob_unbuckle(datum/source, mob/living/M, force = FALSE)
var/mob/living/carbon/human/H = parent
H.remove_movespeed_modifier(MOVESPEED_ID_HUMAN_CARRYING)
. = ..()
/datum/component/riding/human/vehicle_mob_buckle(datum/source, mob/living/M, force = FALSE)
. = ..()
var/mob/living/carbon/human/H = parent
H.add_movespeed_modifier(MOVESPEED_ID_HUMAN_CARRYING, multiplicative_slowdown = HUMAN_CARRY_SLOWDOWN)
/datum/component/riding/human/proc/on_host_unarmed_melee(atom/target)
var/mob/living/carbon/human/AM = parent
if(AM.a_intent == INTENT_DISARM && (target in AM.buckled_mobs))
var/mob/living/carbon/human/H = parent
if(H.a_intent == INTENT_DISARM && (target in H.buckled_mobs))
force_dismount(target)
/datum/component/riding/human/handle_vehicle_layer()
var/atom/movable/AM = parent
if(AM.buckled_mobs && AM.buckled_mobs.len)
if(AM.dir == SOUTH)
AM.layer = ABOVE_MOB_LAYER
for(var/mob/M in AM.buckled_mobs) //ensure proper layering of piggyback and carry, sometimes weird offsets get applied
M.layer = MOB_LAYER
if(!AM.buckle_lying)
if(AM.dir == SOUTH)
AM.layer = ABOVE_MOB_LAYER
else
AM.layer = OBJ_LAYER
else
AM.layer = OBJ_LAYER
if(AM.dir == NORTH)
AM.layer = OBJ_LAYER
else
AM.layer = ABOVE_MOB_LAYER
else
AM.layer = MOB_LAYER
/datum/component/riding/human/get_offsets(pass_index)
var/mob/living/carbon/human/H = parent
if(H.buckle_lying)
return list(TEXT_NORTH = list(0, 6), TEXT_SOUTH = list(0, 6), TEXT_EAST = list(0, 6), TEXT_WEST = list(0, 6))
else
return list(TEXT_NORTH = list(0, 6), TEXT_SOUTH = list(0, 6), TEXT_EAST = list(-6, 4), TEXT_WEST = list( 6, 4))
/datum/component/riding/human/force_dismount(mob/living/user)
var/atom/movable/AM = parent
AM.unbuckle_mob(user)
@@ -273,12 +299,15 @@
M.throw_at(target, 14, 5, AM)
M.Knockdown(60)
/datum/component/riding/proc/equip_buckle_inhands(mob/living/carbon/human/user, amount_required = 1)
/datum/component/riding/proc/equip_buckle_inhands(mob/living/carbon/human/user, amount_required = 1, riding_target_override = null)
var/atom/movable/AM = parent
var/amount_equipped = 0
for(var/amount_needed = amount_required, amount_needed > 0, amount_needed--)
var/obj/item/riding_offhand/inhand = new /obj/item/riding_offhand(user)
inhand.rider = user
if(!riding_target_override)
inhand.rider = user
else
inhand.rider = riding_target_override
inhand.parent = AM
if(user.put_in_hands(inhand, TRUE))
amount_equipped++
@@ -318,7 +347,7 @@
. = ..()
/obj/item/riding_offhand/equipped()
if(loc != rider)
if(loc != rider && loc != parent)
selfdeleting = TRUE
qdel(src)
. = ..()
+1 -1
View File
@@ -182,7 +182,7 @@ RSF
to_chat(user, "Fabricating Cookie..")
var/obj/item/reagent_containers/food/snacks/cookie/S = new /obj/item/reagent_containers/food/snacks/cookie(T)
if(toxin)
S.reagents.add_reagent("chloralhydratedelayed", 10)
S.reagents.add_reagent("chloralhydrate", 10)
if (iscyborg(user))
var/mob/living/silicon/robot/R = user
R.cell.charge -= 100
+96 -66
View File
@@ -1,6 +1,9 @@
#define RANDOM_GRAFFITI "Random Graffiti"
#define RANDOM_LETTER "Random Letter"
#define RANDOM_PUNCTUATION "Random Punctuation"
#define RANDOM_NUMBER "Random Number"
#define RANDOM_SYMBOL "Random Symbol"
#define RANDOM_DRAWING "Random Drawing"
#define RANDOM_ORIENTED "Random Oriented"
#define RANDOM_RUNE "Random Rune"
#define RANDOM_ANY "Random Anything"
@@ -32,16 +35,16 @@
var/drawtype
var/text_buffer = ""
var/list/graffiti = list("amyjon","face","matt","revolution","engie","guy","end","dwarf","uboa","body","cyka","arrow","star","poseur tag","prolizard","antilizard", "tile") //cit edit
var/list/letters = list("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z")
var/list/numerals = list("0","1","2","3","4","5","6","7","8","9")
var/list/oriented = list("arrow","body") // These turn to face the same way as the drawer
var/list/runes = list("rune1","rune2","rune3","rune4","rune5","rune6")
var/list/randoms = list(RANDOM_ANY, RANDOM_RUNE, RANDOM_ORIENTED,
RANDOM_NUMBER, RANDOM_GRAFFITI, RANDOM_LETTER)
var/list/graffiti_large_h = list("yiffhell", "secborg", "paint")
var/static/list/graffiti = list("amyjon","face","matt","revolution","engie","guy","end","dwarf","uboa","body","cyka","star","poseur tag","prolizard","antilizard", "tile")
var/static/list/symbols = list("danger","firedanger","electricdanger","biohazard","radiation","safe","evac","space","med","trade","shop","food","peace","like","skull","nay","heart","credit")
var/static/list/drawings = list("smallbrush","brush","largebrush","splatter","snake","stickman","carp","ghost","clown","taser","disk","fireaxe","toolbox","corgi","cat","toilet","blueprint","beepsky","scroll","bottle","shotgun")
var/static/list/oriented = list("arrow","line","thinline","shortline","body","chevron","footprint","clawprint","pawprint") // These turn to face the same way as the drawer
var/static/list/runes = list("rune1","rune2","rune3","rune4","rune5","rune6")
var/static/list/randoms = list(RANDOM_ANY, RANDOM_RUNE, RANDOM_ORIENTED,
RANDOM_NUMBER, RANDOM_GRAFFITI, RANDOM_LETTER, RANDOM_SYMBOL, RANDOM_PUNCTUATION, RANDOM_DRAWING)
var/static/list/graffiti_large_h = list("yiffhell", "secborg", "paint")
var/list/all_drawables
var/static/list/all_drawables = graffiti + symbols + drawings + oriented + runes + graffiti_large_h
var/paint_mode = PAINT_NORMAL
@@ -54,8 +57,6 @@
var/instant = FALSE
var/self_contained = TRUE // If it deletes itself when it is empty
var/list/validSurfaces = list(/turf/open/floor)
var/edible = TRUE // That doesn't mean eating it is a good idea
var/list/reagent_contents = list("nutriment" = 1)
@@ -71,6 +72,9 @@
var/datum/team/gang/gang //For marking territory.
var/gang_tag_delay = 30 //this is the delay for gang mode tag applications on anything that gang = true on.
/obj/item/toy/crayon/proc/isValidSurface(surface)
return istype(surface, /turf/open/floor)
/obj/item/toy/crayon/suicide_act(mob/user)
user.visible_message("<span class='suicide'>[user] is jamming [src] up [user.p_their()] nose and into [user.p_their()] brain. It looks like [user.p_theyre()] trying to commit suicide!</span>")
return (BRUTELOSS|OXYLOSS)
@@ -81,7 +85,6 @@
if(name == "crayon")
name = "[item_color] crayon"
all_drawables = graffiti + letters + numerals + oriented + runes + graffiti_large_h
drawtype = pick(all_drawables)
refill()
@@ -153,55 +156,62 @@
to_chat(user, "<span class='notice'>The cap on [src] is now [is_capped ? "on" : "off"].</span>")
update_icon()
/obj/item/toy/crayon/ui_data()
var/list/data = list()
data["drawables"] = list()
var/list/D = data["drawables"]
/obj/item/toy/crayon/proc/staticDrawables()
. = list()
var/list/g_items = list()
D += list(list("name" = "Graffiti", "items" = g_items))
. += list(list("name" = "Graffiti", "items" = g_items))
for(var/g in graffiti)
g_items += list(list("item" = g))
var/list/glh_items = list()
D += list(list("name" = "Graffiti Large Horizontal", "items" = glh_items))
. += list(list("name" = "Graffiti Large Horizontal", "items" = glh_items))
for(var/glh in graffiti_large_h)
glh_items += list(list("item" = glh))
var/list/L_items = list()
D += list(list("name" = "Letters", "items" = L_items))
for(var/L in letters)
L_items += list(list("item" = L))
var/list/S_items = list()
. += list(list("name" = "Symbols", "items" = S_items))
for(var/S in symbols)
S_items += list(list("item" = S))
var/list/N_items = list()
D += list(list(name = "Numerals", "items" = N_items))
for(var/N in numerals)
N_items += list(list("item" = N))
var/list/D_items = list()
. += list(list("name" = "Drawings", "items" = D_items))
for(var/D in drawings)
D_items += list(list("item" = D))
var/list/O_items = list()
D += list(list(name = "Oriented", "items" = O_items))
. += list(list(name = "Oriented", "items" = O_items))
for(var/O in oriented)
O_items += list(list("item" = O))
var/list/R_items = list()
D += list(list(name = "Runes", "items" = R_items))
. += list(list(name = "Runes", "items" = R_items))
for(var/R in runes)
R_items += list(list("item" = R))
var/list/rand_items = list()
D += list(list(name = "Random", "items" = rand_items))
. += list(list(name = "Random", "items" = rand_items))
for(var/i in randoms)
rand_items += list(list("item" = i))
data["selected_stencil"] = drawtype
data["text_buffer"] = text_buffer
data["has_cap"] = has_cap
data["is_capped"] = is_capped
data["can_change_colour"] = can_change_colour
data["current_colour"] = paint_color
/obj/item/toy/crayon/ui_data()
return data
var/static/list/crayon_drawables
if (!crayon_drawables)
crayon_drawables = staticDrawables()
. = list()
.["drawables"] = crayon_drawables
.["selected_stencil"] = drawtype
.["text_buffer"] = text_buffer
.["has_cap"] = has_cap
.["is_capped"] = is_capped
.["can_change_colour"] = can_change_colour
.["current_colour"] = paint_color
/obj/item/toy/crayon/ui_act(action, list/params)
if(..())
@@ -216,6 +226,7 @@
if(stencil in all_drawables + randoms)
drawtype = stencil
. = TRUE
text_buffer = ""
if(stencil in graffiti_large_h)
paint_mode = PAINT_LARGE_HORIZONTAL
text_buffer = ""
@@ -235,18 +246,16 @@
update_icon()
/obj/item/toy/crayon/proc/crayon_text_strip(text)
var/list/base = string2charlist(lowertext(text))
var/list/out = list()
for(var/a in base)
if(a in (letters|numerals))
out += a
return jointext(out,"")
var/static/regex/crayon_r = new /regex(@"[^\w!?,.=%#&+\/\-]")
return replacetext(lowertext(text), crayon_r, "")
/obj/item/toy/crayon/afterattack(atom/target, mob/user, proximity, params)
. = ..()
if(!proximity || !check_allowed_items(target))
return
var/static/list/punctuation = list("!","?",".",",","/","+","-","=","%","#","&")
var/cost = 1
if(paint_mode == PAINT_LARGE_HORIZONTAL)
cost = 5
@@ -264,13 +273,19 @@
if(istype(target, /obj/effect/decal/cleanable))
target = target.loc
if(!is_type_in_list(target,validSurfaces))
if(!isValidSurface(target))
return
var/drawing = drawtype
switch(drawtype)
if(RANDOM_LETTER)
drawing = pick(letters)
drawing = ascii2text(rand(97, 122)) // a-z
if(RANDOM_PUNCTUATION)
drawing = pick(punctuation)
if(RANDOM_SYMBOL)
drawing = pick(symbols)
if(RANDOM_DRAWING)
drawing = pick(drawings)
if(RANDOM_GRAFFITI)
drawing = pick(graffiti)
if(RANDOM_RUNE)
@@ -278,17 +293,23 @@
if(RANDOM_ORIENTED)
drawing = pick(oriented)
if(RANDOM_NUMBER)
drawing = pick(numerals)
drawing = ascii2text(rand(48, 57)) // 0-9
if(RANDOM_ANY)
drawing = pick(all_drawables)
var/temp = "rune"
if(drawing in letters)
if(is_alpha(drawing))
temp = "letter"
else if(drawing in graffiti)
temp = "graffiti"
else if(drawing in numerals)
else if(is_digit(drawing))
temp = "number"
else if(drawing in punctuation)
temp = "punctuation mark"
else if(drawing in symbols)
temp = "symbol"
else if(drawing in drawings)
temp = "drawing"
else if(drawing in graffiti|oriented)
temp = "graffiti"
// If a gang member is using a gang spraycan, it'll behave differently
var/gang_mode = FALSE
@@ -338,7 +359,7 @@
return
if(length(text_buffer))
drawing = copytext(text_buffer,1,2)
drawing = text_buffer[1]
var/list/turf/affected_turfs = list()
@@ -362,7 +383,7 @@
if(PAINT_LARGE_HORIZONTAL)
var/turf/left = locate(target.x-1,target.y,target.z)
var/turf/right = locate(target.x+1,target.y,target.z)
if(is_type_in_list(left, validSurfaces) && is_type_in_list(right, validSurfaces))
if(isValidSurface(left) && isValidSurface(right))
var/obj/effect/decal/cleanable/crayon/C = new(left, paint_color, drawing, temp, graf_rot, PAINT_LARGE_HORIZONTAL_ICON)
C.add_hiddenprint(user)
affected_turfs += left
@@ -377,8 +398,9 @@
else
to_chat(user, "<span class='notice'>You spray a [temp] on \the [target.name]</span>")
if(length(text_buffer))
if(length(text_buffer) > 1)
text_buffer = copytext(text_buffer,2)
SStgui.update_uis(src)
if(post_noise)
audible_message("<span class='notice'>You hear spraying.</span>")
@@ -516,7 +538,7 @@
charges = -1
/obj/item/toy/crayon/rainbow/afterattack(atom/target, mob/user, proximity)
/obj/item/toy/crayon/rainbow/afterattack(atom/target, mob/user, proximity, params)
paint_color = rgb(rand(0,255), rand(0,255), rand(0,255))
. = ..()
@@ -591,12 +613,14 @@
can_change_colour = TRUE
gang = TRUE //Gang check is true for all things upon the honored hierarchy of spraycans, except those that are FALSE.
validSurfaces = list(/turf/open/floor, /turf/closed/wall)
reagent_contents = list("welding_fuel" = 1, "ethanol" = 1)
pre_noise = TRUE
post_noise = FALSE
/obj/item/toy/crayon/spraycan/isValidSurface(surface)
return (istype(surface, /turf/open/floor) || istype(surface, /turf/closed/wall))
/obj/item/toy/crayon/spraycan/suicide_act(mob/user)
var/mob/living/carbon/human/H = user
if(is_capped || !actually_paints)
@@ -622,8 +646,8 @@
return (OXYLOSS)
/obj/item/toy/crayon/spraycan/New()
..()
/obj/item/toy/crayon/spraycan/Initialize()
. = ..()
// If default crayon red colour, pick a more fun spraycan colour
if(!paint_color)
paint_color = pick("#DA0000","#FF9300","#FFF200","#A8E61D","#00B7EF",
@@ -640,7 +664,7 @@
to_chat(user, "It is empty.")
to_chat(user, "<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)
/obj/item/toy/crayon/spraycan/afterattack(atom/target, mob/user, proximity, params)
if(!proximity)
return
@@ -656,8 +680,7 @@
playsound(user.loc, 'sound/effects/spray.ogg', 25, 1, 5)
var/mob/living/carbon/C = target
user.visible_message("<span class='danger'>[user] sprays [src] into the face of [target]!</span>")
to_chat(target, "<span class='userdanger'>[user] sprays [src] into your face!</span>")
C.visible_message("<span class='danger'>[user] sprays [src] into the face of [C]!</span>", "<span class='userdanger'>[user] sprays [src] into your face!</span>")
if(C.client)
C.blur_eyes(3)
@@ -678,13 +701,14 @@
return
if(istype(target, /obj/structure/window))
if(isobj(target))
if(actually_paints)
target.add_atom_colour(paint_color, WASHABLE_COLOUR_PRIORITY)
if(color_hex2num(paint_color) < 255)
target.set_opacity(255)
else
target.set_opacity(initial(target.opacity))
if(istype(target, /obj/structure/window))
if(color_hex2num(paint_color) < 255)
target.set_opacity(255)
else
target.set_opacity(initial(target.opacity))
. = use_charges(user, 2)
var/fraction = min(1, . / reagents.maximum_volume)
reagents.reaction(target, TOUCH, fraction * volume_multiplier)
@@ -692,6 +716,7 @@
if(pre_noise || post_noise)
playsound(user.loc, 'sound/effects/spray.ogg', 5, 1, 5)
user.visible_message("[user] coats [target] with spray paint!", "<span class='notice'>You coat [target] with spray paint.</span>")
return
. = ..()
@@ -709,7 +734,7 @@
desc = "A metallic container containing shiny synthesised paint."
charges = -1
/obj/item/toy/crayon/spraycan/borg/afterattack(atom/target,mob/user,proximity)
/obj/item/toy/crayon/spraycan/borg/afterattack(atom/target,mob/user,proximity, params)
var/diff = ..()
if(!iscyborg(user))
to_chat(user, "<span class='notice'>How did you get this?</span>")
@@ -754,7 +779,9 @@
reagent_contents = list("lube" = 1, "banana" = 1)
volume_multiplier = 5
validSurfaces = list(/turf/open/floor)
/obj/item/toy/crayon/spraycan/lubecan/isValidSurface(surface)
return istype(surface, /turf/open/floor)
/obj/item/toy/crayon/spraycan/mimecan
name = "silent spraycan"
@@ -794,6 +821,9 @@
#undef RANDOM_GRAFFITI
#undef RANDOM_LETTER
#undef RANDOM_PUNCTUATION
#undef RANDOM_SYMBOL
#undef RANDOM_DRAWING
#undef RANDOM_NUMBER
#undef RANDOM_ORIENTED
#undef RANDOM_RUNE
+2
View File
@@ -1,5 +1,6 @@
/obj/item/restraints
breakouttime = 600
var/demoralize_criminals = TRUE // checked on carbon/carbon.dm to decide wheter to apply the handcuffed negative moodlet or not.
/obj/item/restraints/suicide_act(mob/living/carbon/user)
user.visible_message("<span class='suicide'>[user] is strangling [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
@@ -220,6 +221,7 @@
name = "fake handcuffs"
desc = "Fake handcuffs meant for gag purposes."
breakouttime = 10 //Deciseconds = 1s
demoralize_criminals = FALSE
/obj/item/restraints/handcuffs/fake/kinky
name = "kinky handcuffs"
+7 -5
View File
@@ -90,14 +90,14 @@
add_fingerprint(user)
/obj/item/paint/afterattack(turf/target, mob/user, proximity)
/obj/item/paint/afterattack(atom/target, mob/user, proximity)
. = ..()
if(!proximity)
return
if(paintleft <= 0)
icon_state = "paint_empty"
return
if(!istype(target) || isspaceturf(target))
if(!isturf(target) || isspaceturf(target))
return
var/newcolor = "#" + item_color
target.add_atom_colour(newcolor, WASHABLE_COLOUR_PRIORITY)
@@ -105,12 +105,14 @@
/obj/item/paint/paint_remover
gender = PLURAL
name = "paint remover"
desc = "Used to remove color from floors and walls."
desc = "Used to remove color from anything."
icon_state = "paint_neutral"
/obj/item/paint/paint_remover/afterattack(turf/target, mob/user, proximity)
/obj/item/paint/paint_remover/afterattack(atom/target, mob/user, proximity)
. = ..()
if(!proximity)
return
if(istype(target) && target.color != initial(target.color))
if(!isturf(target) || !isobj(target))
return
if(target.color != initial(target.color))
target.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
+51 -14
View File
@@ -9,7 +9,7 @@
var/locked = FALSE
var/installed = 0
var/require_module = 0
var/module_type = null
var/list/module_type
// if true, is not stored in the robot to be ejected
// if module is reset
var/one_use = FALSE
@@ -18,7 +18,7 @@
if(R.stat == DEAD)
to_chat(user, "<span class='notice'>[src] will not function on a deceased cyborg.</span>")
return FALSE
if(module_type && !istype(R.module, module_type))
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!")
return FALSE
@@ -93,7 +93,6 @@
desc = "Used to cool a mounted disabler, increasing the potential current in it and thus its recharge rate."
icon_state = "cyborg_upgrade3"
require_module = 1
//module_type = /obj/item/robot_module/security
/obj/item/borg/upgrade/disablercooler/action(mob/living/silicon/robot/R, user = usr)
. = ..()
@@ -141,7 +140,7 @@
desc = "A diamond drill replacement for the mining module's standard drill."
icon_state = "cyborg_upgrade3"
require_module = 1
module_type = /obj/item/robot_module/miner
module_type = list(/obj/item/robot_module/miner)
/obj/item/borg/upgrade/ddrill/action(mob/living/silicon/robot/R, user = usr)
. = ..()
@@ -173,7 +172,7 @@
desc = "A satchel of holding replacement for mining cyborg's ore satchel module."
icon_state = "cyborg_upgrade3"
require_module = 1
module_type = /obj/item/robot_module/miner
module_type = list(/obj/item/robot_module/miner)
/obj/item/borg/upgrade/soh/action(mob/living/silicon/robot/R)
. = ..()
@@ -200,7 +199,7 @@
desc = "A trash bag of holding replacement for the janiborg's standard trash bag."
icon_state = "cyborg_upgrade3"
require_module = 1
module_type = /obj/item/robot_module/janitor
module_type = list(/obj/item/robot_module/janitor, /obj/item/robot_module/scrubpup)
/obj/item/borg/upgrade/tboh/action(mob/living/silicon/robot/R)
. = ..()
@@ -227,7 +226,7 @@
desc = "An advanced mop replacement for the janiborg's standard mop."
icon_state = "cyborg_upgrade3"
require_module = 1
module_type = /obj/item/robot_module/janitor
module_type = list(/obj/item/robot_module/janitor, /obj/item/robot_module/scrubpup)
/obj/item/borg/upgrade/amop/action(mob/living/silicon/robot/R)
. = ..()
@@ -276,7 +275,7 @@
icon_state = "ash_plating"
resistance_flags = LAVA_PROOF | FIRE_PROOF
require_module = 1
module_type = /obj/item/robot_module/miner
module_type = list(/obj/item/robot_module/miner)
/obj/item/borg/upgrade/lavaproof/action(mob/living/silicon/robot/R, user = usr)
. = ..()
@@ -405,7 +404,9 @@
to produce more advanced and complex medical reagents."
icon_state = "cyborg_upgrade3"
require_module = 1
module_type = /obj/item/robot_module/medical
module_type = list(/obj/item/robot_module/medical,
/obj/item/robot_module/syndicate_medical,
/obj/item/robot_module/medihound)
var/list/additional_reagents = list()
/obj/item/borg/upgrade/hypospray/action(mob/living/silicon/robot/R, user = usr)
@@ -467,7 +468,9 @@
defibrillator, for on the scene revival."
icon_state = "cyborg_upgrade3"
require_module = 1
module_type = /obj/item/robot_module/medical
module_type = list(/obj/item/robot_module/medical,
/obj/item/robot_module/syndicate_medical,
/obj/item/robot_module/medihound)
/obj/item/borg/upgrade/defib/action(mob/living/silicon/robot/R, user = usr)
. = ..()
@@ -489,7 +492,9 @@
out procedures"
icon_state = "cyborg_upgrade3"
require_module = 1
module_type = /obj/item/robot_module/medical
module_type = list(/obj/item/robot_module/medical,
/obj/item/robot_module/syndicate_medical,
/obj/item/robot_module/medihound)
/obj/item/borg/upgrade/processor/action(mob/living/silicon/robot/R, user = usr)
. = ..()
@@ -514,7 +519,7 @@
/obj/item/robot_module/medical,
/obj/item/robot_module/syndicate_medical,
/obj/item/robot_module/medihound,
/obj/item/robot_module/borgi)
/obj/item/robot_module/borgi)
/obj/item/borg/upgrade/advhealth/action(mob/living/silicon/robot/R, user = usr)
. = ..()
@@ -598,7 +603,7 @@
icon = 'icons/obj/storage.dmi'
icon_state = "borgrped"
require_module = TRUE
module_type = /obj/item/robot_module/engineering
module_type = list(/obj/item/robot_module/engineering)
/obj/item/borg/upgrade/rped/action(mob/living/silicon/robot/R, user = usr)
. = ..()
@@ -626,7 +631,9 @@
icon = 'icons/obj/device.dmi'
icon_state = "pinpointer_crew"
require_module = TRUE
module_type = /obj/item/robot_module/medical
module_type = list(/obj/item/robot_module/medical,
/obj/item/robot_module/syndicate_medical,
/obj/item/robot_module/medihound)
/obj/item/borg/upgrade/pinpointer/action(mob/living/silicon/robot/R, user = usr)
. = ..()
@@ -664,3 +671,33 @@
desc = "Allows you to to turn a cyborg into a clown, honk."
icon_state = "cyborg_upgrade3"
new_module = /obj/item/robot_module/clown
// Citadel's Vtech Controller
/obj/effect/proc_holder/silicon/cyborg/vtecControl
name = "vTec Control"
desc = "Allows finer-grained control of the vTec speed boost."
action_icon = 'icons/mob/actions.dmi'
action_icon_state = "Chevron_State_0"
var/currentState = 0
var/maxReduction = 2
/obj/effect/proc_holder/silicon/cyborg/vtecControl/Click(mob/living/silicon/robot/user)
var/mob/living/silicon/robot/self = usr
currentState = (currentState + 1) % 3
if(usr)
switch(currentState)
if (0)
self.speed = maxReduction
if (1)
self.speed -= maxReduction*0.5
if (2)
self.speed -= maxReduction*1.25
action.button_icon_state = "Chevron_State_[currentState]"
action.UpdateButtonIcon()
return
+6 -3
View File
@@ -115,6 +115,9 @@
log_combat(user, pushed_mob, "placed")
/obj/structure/table/proc/tablepush(mob/living/user, mob/living/pushed_mob)
if(HAS_TRAIT(user, TRAIT_PACIFISM))
to_chat(user, "<span class='danger'>Throwing [pushed_mob] onto the table might hurt them!</span>")
return
var/added_passtable = FALSE
if(!pushed_mob.pass_flags & PASSTABLE)
added_passtable = TRUE
@@ -125,9 +128,9 @@
if(pushed_mob.loc != loc) //Something prevented the tabling
return
pushed_mob.Knockdown(40)
pushed_mob.visible_message("<span class='danger'>[user] pushes [pushed_mob] onto [src].</span>", \
"<span class='userdanger'>[user] pushes [pushed_mob] onto [src].</span>")
log_combat(user, pushed_mob, "pushed")
pushed_mob.visible_message("<span class='danger'>[user] slams [pushed_mob] onto [src]!</span>", \
"<span class='userdanger'>[user] slams you onto [src]!</span>")
log_combat(user, pushed_mob, "tabled", null, "onto [src]")
if(!ishuman(pushed_mob))
return
var/mob/living/carbon/human/H = pushed_mob
+10 -5
View File
@@ -648,6 +648,11 @@
desc = "A spell that will absorb blood from anything you touch.<br>Touching cultists and constructs can heal them.<br><b>Clicking the hand will potentially let you focus the spell into something stronger.</b>"
color = "#7D1717"
/obj/item/melee/blood_magic/manipulator/examine(mob/user)
. = ..()
if(iscultist(user))
to_chat(user, "<span class='cultitalic'>The [name] currently has <b>[uses]</b> blood charges left.</span>")
/obj/item/melee/blood_magic/manipulator/afterattack(atom/target, mob/living/carbon/human/user, proximity)
if(proximity)
if(ishuman(target))
@@ -682,9 +687,9 @@
if(ratio>1)
ratio = 1
uses -= round(overall_damage)
H.visible_message("<span class='warning'>[H] is fully healed by [H==user ? "[H.p_their()]":"[H]'s"]'s blood magic!</span>")
H.visible_message("<span class='warning'>[H] is fully healed by [H==user ? "[H.p_their()]":"[user]'s"] blood magic!</span>")
else
H.visible_message("<span class='warning'>[H] is partially healed by [H==user ? "[H.p_their()]":"[H]'s"] blood magic.</span>")
H.visible_message("<span class='warning'>[H] is partially healed by [H==user ? "[H.p_their()]":"[user]'s"] blood magic.</span>")
uses = 0
ratio *= -1
H.adjustOxyLoss((overall_damage*ratio) * (H.getOxyLoss() / overall_damage), 0)
@@ -766,7 +771,7 @@
switch(choice)
if("Blood Spear (150)")
if(uses < 150)
to_chat(user, "<span class='cultitalic'>You need 200 charges to perform this rite.</span>")
to_chat(user, "<span class='cultitalic'>You need 150 charges to perform this rite.</span>")
else
uses -= 150
var/turf/T = get_turf(user)
@@ -782,7 +787,7 @@
"<span class='cultitalic'>A [rite.name] materializes at your feet.</span>")
if("Blood Bolt Barrage (300)")
if(uses < 300)
to_chat(user, "<span class='cultitalic'>You need 400 charges to perform this rite.</span>")
to_chat(user, "<span class='cultitalic'>You need 300 charges to perform this rite.</span>")
else
var/obj/rite = new /obj/item/gun/ballistic/shotgun/boltaction/enchanted/arcane_barrage/blood()
uses -= 300
@@ -794,7 +799,7 @@
qdel(rite)
if("Blood Beam (500)")
if(uses < 500)
to_chat(user, "<span class='cultitalic'>You need 600 charges to perform this rite.</span>")
to_chat(user, "<span class='cultitalic'>You need 500 charges to perform this rite.</span>")
else
var/obj/rite = new /obj/item/blood_beam()
uses -= 500
@@ -666,6 +666,7 @@
righthand_file = 'icons/mob/inhands/weapons/polearms_righthand.dmi'
slot_flags = 0
force = 17
force_unwielded = 17
force_wielded = 24
throwforce = 40
throw_speed = 2
+7 -42
View File
@@ -185,9 +185,6 @@ structure_check() searches for nearby cultist structures required for the invoca
color = RUNE_COLOR_OFFER
req_cultists = 1
rune_in_use = FALSE
var/mob/living/currentconversionman
var/conversiontimeout
var/conversionresult
/obj/effect/rune/convert/do_invoke_glow()
return
@@ -233,37 +230,18 @@ structure_check() searches for nearby cultist structures required for the invoca
addtimer(CALLBACK(src, /atom/proc/update_atom_colour), 5)
Cult_team.check_size() // Triggers the eye glow or aura effects if the cult has grown large enough relative to the crew
rune_in_use = FALSE
/obj/effect/rune/convert/proc/do_convert(mob/living/convertee, list/invokers)
if(invokers.len < 2)
for(var/M in invokers)
to_chat(M, "<span class='danger'>You need at least two invokers to convert [convertee]!</span>")
to_chat(M, "<span class='warning'>You need at least two invokers to convert [convertee]!</span>")
log_game("Offer rune failed - tried conversion with one invoker")
return 0
if(convertee.anti_magic_check(TRUE, TRUE))
if(convertee.anti_magic_check(TRUE, TRUE, FALSE, 0)) //Not chargecost because it can be spammed
for(var/M in invokers)
to_chat(M, "<span class='warning'>Something is shielding [convertee]'s mind!</span>")
log_game("Offer rune failed - convertee had anti-magic")
return 0
to_chat(convertee, "<span class='cult italic'><b>The world goes red. All at once you are aware of an evil, eldritch truth taking roots into your mind.\n\
<a href='?src=\ref[src];signmeup=1'>Click here to become a follower of Nar'sie</a></b>, or suffer a fate worse than death.</span>")
INVOKE_ASYNC(src, .proc/optinalert, convertee)
currentconversionman = convertee
conversiontimeout = world.time + (14 SECONDS)
convertee.Stun(140)
ADD_TRAIT(convertee, TRAIT_MUTE, "conversionrune")
flash_color(convertee, list("#960000", "#960000", "#960000", rgb(0,0,0)), 50)
conversionresult = FALSE
while(world.time < conversiontimeout && convertee && !conversionresult)
stoplag(1)
currentconversionman = null
if(!convertee)
return FALSE
REMOVE_TRAIT(convertee, TRAIT_MUTE, "conversionrune")
if(get_turf(convertee) != get_turf(src))
return FALSE
if(!conversionresult)
do_sacrifice(convertee, invokers, TRUE)
return FALSE
var/brutedamage = convertee.getBruteLoss()
var/burndamage = convertee.getFireLoss()
if(brutedamage || burndamage)
@@ -275,6 +253,8 @@ structure_check() searches for nearby cultist structures required for the invoca
SSticker.mode.add_cultist(convertee.mind, 1)
new /obj/item/melee/cultblade/dagger(get_turf(src))
convertee.mind.special_role = ROLE_CULTIST
to_chat(convertee, "<span class='cult italic'><b>Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible, truth. The veil of reality has been ripped away \
and something evil takes root.</b></span>")
to_chat(convertee, "<span class='cult italic'><b>Assist your new compatriots in their dark dealings. Your goal is theirs, and theirs is yours. You serve the Geometer above all else. Bring it back.\
</b></span>")
if(ishuman(convertee))
@@ -284,18 +264,7 @@ structure_check() searches for nearby cultist structures required for the invoca
H.cultslurring = 0
return 1
/obj/effect/rune/convert/proc/optinalert(mob/living/convertee)
var/alert = alert(convertee, "Will you embrace the Geometer of Blood or perish in futile resistance?", "Choose your own fate", "Join the Blood Cult", "Suffer a horrible demise")
if(src && alert == "Join the Blood Cult")
signmeup(convertee)
/obj/effect/rune/convert/proc/signmeup(mob/living/convertee)
if(currentconversionman == convertee)
conversionresult = TRUE
else
to_chat(convertee, "<span class='cult italic'>Your fate has already been set in stone.</span>")
/obj/effect/rune/convert/proc/do_sacrifice(mob/living/sacrificial, list/invokers, force_a_sac)
/obj/effect/rune/convert/proc/do_sacrifice(mob/living/sacrificial, list/invokers)
var/mob/living/first_invoker = invokers[1]
if(!first_invoker)
return FALSE
@@ -305,7 +274,7 @@ structure_check() searches for nearby cultist structures required for the invoca
var/big_sac = FALSE
if(!force_a_sac && (((ishuman(sacrificial) || iscyborg(sacrificial)) && sacrificial.stat != DEAD) || C.cult_team.is_sacrifice_target(sacrificial.mind)) && invokers.len < 3)
if((((ishuman(sacrificial) || iscyborg(sacrificial)) && sacrificial.stat != DEAD) || C.cult_team.is_sacrifice_target(sacrificial.mind)) && invokers.len < 3)
for(var/M in invokers)
to_chat(M, "<span class='cult italic'>[sacrificial] is too greatly linked to the world! You need three acolytes!</span>")
log_game("Offer rune failed - not enough acolytes and target is living or sac target")
@@ -345,10 +314,6 @@ structure_check() searches for nearby cultist structures required for the invoca
sacrificial.gib()
return TRUE
/obj/effect/rune/convert/Topic(href, href_list)
if(href_list["signmeup"])
signmeup(usr)
/obj/effect/rune/empower
cultist_name = "Empower"
cultist_desc = "allows cultists to prepare greater amounts of blood magic at far less of a cost."
+12
View File
@@ -133,6 +133,18 @@
category = CAT_WEAPONRY
subcategory = CAT_WEAPON
/datum/crafting_recipe/minigun
name = "Laser Minigun"
result = /obj/item/minigunpack2
reqs = list(/obj/item/gun/energy/laser/carbine = 3,
/obj/item/stack/sheet/plasteel = 5,
/obj/item/stack/cable_coil = 30,
/obj/item/stock_parts/cell/bluespace = 2)
tools = list(TOOL_WIRECUTTER, TOOL_SCREWDRIVER, TOOL_WELDER)
time = 150
category = CAT_WEAPONRY
subcategory = CAT_WEAPON
/datum/crafting_recipe/ed209
name = "ED209"
result = /mob/living/simple_animal/bot/ed209
+9
View File
@@ -169,6 +169,7 @@
locked = FALSE
cut_overlays()
add_overlay("securecrateg")
tamperproof = 0 // set explosion chance to zero, so we dont accidently hit it with a multitool and instantly die
else if (input == null || sanitycheck == null || length(input) != codelen)
to_chat(user, "<span class='notice'>You leave the crate alone.</span>")
else
@@ -213,6 +214,12 @@
return
return ..()
/obj/structure/closet/secure/loot/dive_into(mob/living/user)
if(!locked)
return ..()
to_chat(user, "<span class='notice'>That seems like a stupid idea.</span>")
return FALSE
/obj/structure/closet/crate/secure/loot/emag_act(mob/user)
. = SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT)
if(!locked)
@@ -227,4 +234,6 @@
..()
/obj/structure/closet/crate/secure/loot/deconstruct(disassembled = TRUE)
if(!locked && disassembled)
return ..()
boom()
+8 -3
View File
@@ -271,9 +271,13 @@
if(restrained())
changeNext_move(CLICK_CD_BREAKOUT)
last_special = world.time + CLICK_CD_BREAKOUT
var/buckle_cd = 600
if(handcuffed)
var/obj/item/restraints/O = src.get_item_by_slot(SLOT_HANDCUFFED)
buckle_cd = O.breakouttime
visible_message("<span class='warning'>[src] attempts to unbuckle [p_them()]self!</span>", \
"<span class='notice'>You attempt to unbuckle yourself... (This will take around one minute and you need to stay still.)</span>")
if(do_after(src, 600, 0, target = src))
"<span class='notice'>You attempt to unbuckle yourself... (This will take around [round(buckle_cd/600,1)] minute\s, and you need to stay still.)</span>")
if(do_after(src, buckle_cd, 0, target = src))
if(!buckled)
return
buckled.user_unbuckle_mob(src,src)
@@ -801,7 +805,8 @@
drop_all_held_items()
stop_pulling()
throw_alert("handcuffed", /obj/screen/alert/restrained/handcuffed, new_master = src.handcuffed)
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "handcuffed", /datum/mood_event/handcuffed)
if(handcuffed.demoralize_criminals)
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "handcuffed", /datum/mood_event/handcuffed)
else
clear_alert("handcuffed")
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "handcuffed")
+69 -37
View File
@@ -860,52 +860,84 @@
.["Copy outfit"] = "?_src_=vars;[HrefToken()];copyoutfit=[REF(src)]"
/mob/living/carbon/human/MouseDrop_T(mob/living/target, mob/living/user)
//If they dragged themselves and we're currently aggressively grabbing them try to piggyback
if(user == target && can_piggyback(target) && pulling == target && (HAS_TRAIT(src, TRAIT_PACIFISM) || grab_state >= GRAB_AGGRESSIVE) && stat == CONSCIOUS)
buckle_mob(target,TRUE,TRUE)
if(pulling == target && grab_state >= GRAB_AGGRESSIVE && stat == CONSCIOUS)
//If they dragged themselves and we're currently aggressively grabbing them try to piggyback
if(user == target && can_piggyback(target))
piggyback(target)
return
//If you dragged them to you and you're aggressively grabbing try to fireman carry them
else if(user != target && can_be_firemanned(target))
fireman_carry(target)
return
. = ..()
/mob/living/carbon/human/proc/piggyback_instant(mob/living/M)
return buckle_mob(M, TRUE, TRUE, FALSE, TRUE)
//src is the user that will be carrying, target is the mob to be carried
/mob/living/carbon/human/proc/can_piggyback(mob/living/carbon/target)
return (istype(target) && target.stat == CONSCIOUS)
//Can C try to piggyback at all.
/mob/living/carbon/human/proc/can_piggyback(mob/living/carbon/C)
if(istype(C) && C.stat == CONSCIOUS)
return TRUE
return FALSE
/mob/living/carbon/human/proc/can_be_firemanned(mob/living/carbon/target)
return (ishuman(target) && target.lying)
/mob/living/carbon/human/buckle_mob(mob/living/M, force = FALSE, check_loc = TRUE, bypass_piggybacking = FALSE, no_delay = FALSE)
/mob/living/carbon/human/proc/fireman_carry(mob/living/carbon/target)
if(can_be_firemanned(target))
visible_message("<span class='notice'>[src] starts lifting [target] onto their back...</span>",
"<span class='notice'>You start lifting [target] onto your back...</span>")
if(do_after(src, 30, TRUE, target))
//Second check to make sure they're still valid to be carried
if(can_be_firemanned(target) && !incapacitated(FALSE, TRUE))
target.resting = FALSE
buckle_mob(target, TRUE, TRUE, 90, 1, 0)
return
visible_message("<span class='warning'>[src] fails to fireman carry [target]!")
else
to_chat(src, "<span class='notice'>You can't fireman carry [target] while they're standing!</span>")
/mob/living/carbon/human/proc/piggyback(mob/living/carbon/target)
if(can_piggyback(target))
visible_message("<span class='notice'>[target] starts to climb onto [src]...</span>")
if(do_after(target, 15, target = src))
if(can_piggyback(target))
if(target.incapacitated(FALSE, TRUE) || incapacitated(FALSE, TRUE))
target.visible_message("<span class='warning'>[target] can't hang onto [src]!</span>")
return
buckle_mob(target, TRUE, TRUE, FALSE, 0, 2)
else
visible_message("<span class='warning'>[target] fails to climb onto [src]!</span>")
else
to_chat(target, "<span class='warning'>You can't piggyback ride [src] right now!</span>")
/mob/living/carbon/human/buckle_mob(mob/living/target, force = FALSE, check_loc = TRUE, lying_buckle = FALSE, hands_needed = 0, target_hands_needed = 0)
if(!force)//humans are only meant to be ridden through piggybacking and special cases
return
if(bypass_piggybacking)
return ..()
if(!is_type_in_typecache(M, can_ride_typecache))
M.visible_message("<span class='warning'>[M] really can't seem to mount [src]...</span>")
if(!is_type_in_typecache(target, can_ride_typecache))
target.visible_message("<span class='warning'>[target] really can't seem to mount [src]...</span>")
return
buckle_lying = lying_buckle
var/datum/component/riding/human/riding_datum = LoadComponent(/datum/component/riding/human)
riding_datum.ride_check_rider_incapacitated = TRUE
riding_datum.ride_check_rider_restrained = TRUE
riding_datum.set_riding_offsets(RIDING_OFFSET_ALL, list(TEXT_NORTH = list(0, 6), TEXT_SOUTH = list(0, 6), TEXT_EAST = list(-6, 4), TEXT_WEST = list( 6, 4)))
if(buckled_mobs && ((M in buckled_mobs) || (buckled_mobs.len >= max_buckled_mobs)) || buckled || (M.stat != CONSCIOUS))
if(target_hands_needed)
riding_datum.ride_check_rider_restrained = TRUE
if(buckled_mobs && ((target in buckled_mobs) || (buckled_mobs.len >= max_buckled_mobs)) || buckled)
return
if(can_piggyback(M))
riding_datum.ride_check_ridden_incapacitated = TRUE
visible_message("<span class='notice'>[M] starts to climb onto [src]...</span>")
if(no_delay || do_after(M, 15, target = src))
if(can_piggyback(M))
if(M.incapacitated(FALSE, TRUE) || incapacitated(FALSE, TRUE))
M.visible_message("<span class='warning'>[M] can't hang onto [src]!</span>")
return
if(!riding_datum.equip_buckle_inhands(M, 2)) //MAKE SURE THIS IS LAST!!
M.visible_message("<span class='warning'>[M] can't climb onto [src]!</span>")
return
. = ..(M, force, check_loc)
stop_pulling()
else
visible_message("<span class='warning'>[M] fails to climb onto [src]!</span>")
else
. = ..(M,force,check_loc)
stop_pulling()
var/equipped_hands_self
var/equipped_hands_target
if(hands_needed)
equipped_hands_self = riding_datum.equip_buckle_inhands(src, hands_needed, target)
if(target_hands_needed)
equipped_hands_target = riding_datum.equip_buckle_inhands(target, target_hands_needed)
if(hands_needed || target_hands_needed)
if(hands_needed && !equipped_hands_self)
src.visible_message("<span class='warning'>[src] can't get a grip on [target] because their hands are full!</span>",
"<span class='warning'>You can't get a grip on [target] because your hands are full!</span>")
return
else if(target_hands_needed && !equipped_hands_target)
target.visible_message("<span class='warning'>[target] can't get a grip on [src] because their hands are full!</span>",
"<span class='warning'>You can't get a grip on [src] because your hands are full!</span>")
return
stop_pulling()
riding_datum.handle_vehicle_layer()
. = ..(target, force, check_loc)
/mob/living/carbon/human/proc/is_shove_knockdown_blocked() //If you want to add more things that block shove knockdown, extend this
for(var/obj/item/clothing/C in get_equipped_items()) //doesn't include pockets
+10
View File
@@ -287,6 +287,8 @@
if(HAS_TRAIT(src, TRAIT_STRONG_GRABBER))
C.grippedby(src)
update_pull_movespeed()
//mob verbs are a lot faster than object verbs
//for more info on why this is not atom/pull, see examinate() in mob.dm
/mob/living/verb/pulled(atom/movable/AM as mob|obj in oview(1))
@@ -300,6 +302,7 @@
/mob/living/stop_pulling()
..()
update_pull_movespeed()
update_pull_hud_icon()
/mob/living/verb/stop_pulling1()
@@ -520,6 +523,10 @@
var/old_direction = dir
var/turf/T = loc
if(pulling)
update_pull_movespeed()
. = ..()
if(pulledby && moving_diagonally != FIRST_DIAG_STEP && get_dist(src, pulledby) > 1)//separated from our puller and not in the middle of a diagonal move.
@@ -1023,6 +1030,9 @@
stop_pulling() //CIT CHANGE - Ditto...
else if(has_legs || ignore_legs)
lying = 0
if (pulledby)
var/mob/living/L = pulledby
L.update_pull_movespeed()
if(buckled)
lying = 90*buckle_lying
else if(!lying)
+11 -5
View File
@@ -153,7 +153,7 @@
to_chat(user, "<span class='warning'>[src] can't be grabbed more aggressively!</span>")
return FALSE
if(HAS_TRAIT(user, TRAIT_PACIFISM))
if(user.grab_state >= GRAB_AGGRESSIVE && HAS_TRAIT(user, TRAIT_PACIFISM))
to_chat(user, "<span class='notice'>You don't want to risk hurting [src]!</span>")
return FALSE
@@ -184,11 +184,17 @@
user.grab_state++
switch(user.grab_state)
if(GRAB_AGGRESSIVE)
log_combat(user, src, "grabbed", addition="aggressive grab")
visible_message("<span class='danger'>[user] has grabbed [src] aggressively!</span>", \
"<span class='userdanger'>[user] has grabbed [src] aggressively!</span>")
drop_all_held_items()
var/add_log = ""
if(HAS_TRAIT(user, TRAIT_PACIFISM))
visible_message("<span class='danger'>[user] has firmly gripped [src]!</span>",
"<span class='danger'>[user] has firmly gripped you!</span>")
add_log = " (pacifist)"
else
visible_message("<span class='danger'>[user] has grabbed [src] aggressively!</span>", \
"<span class='userdanger'>[user] has grabbed you aggressively!</span>")
drop_all_held_items()
stop_pulling()
log_combat(user, src, "grabbed", addition="aggressive grab[add_log]")
if(GRAB_NECK)
log_combat(user, src, "grabbed", addition="neck grab")
visible_message("<span class='danger'>[user] has grabbed [src] by the neck!</span>",\
@@ -110,3 +110,5 @@
//List of active diseases
var/list/diseases = list() // list of all diseases in a mob
var/list/disease_resistances = list()
var/drag_slowdown = TRUE //Whether the mob is slowed down when dragging another prone mob
@@ -25,3 +25,11 @@
add_movespeed_modifier(MOVESPEED_ID_LIVING_TURF_SPEEDMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = T.slowdown)
else
remove_movespeed_modifier(MOVESPEED_ID_LIVING_TURF_SPEEDMOD)
/mob/living/proc/update_pull_movespeed()
if(pulling && isliving(pulling))
var/mob/living/L = pulling
if(drag_slowdown && L.lying && !L.buckled && grab_state < GRAB_AGGRESSIVE)
add_movespeed_modifier(MOVESPEED_ID_PRONE_DRAGGING, multiplicative_slowdown = PULL_PRONE_SLOWDOWN)
return
remove_movespeed_modifier(MOVESPEED_ID_PRONE_DRAGGING)
@@ -1216,14 +1216,15 @@
return
if(incapacitated())
return
if(M.incapacitated())
return
if(module)
if(!module.allow_riding)
M.visible_message("<span class='boldwarning'>Unfortunately, [M] just can't seem to hold onto [src]!</span>")
return
if(iscarbon(M) && (!riding_datum.equip_buckle_inhands(M, 1)))
M.visible_message("<span class='boldwarning'>[M] can't climb onto [src] because [M.p_their()] hands are full!</span>")
if(iscarbon(M) && !M.incapacitated() && !riding_datum.equip_buckle_inhands(M, 1))
if(M.get_num_arms() <= 0)
M.visible_message("<span class='boldwarning'>[M] can't climb onto [src] because [M.p_they()] don't have any usable arms!</span>")
else
M.visible_message("<span class='boldwarning'>[M] can't climb onto [src] because [M.p_their()] hands are full!</span>")
return
. = ..(M, force, check_loc)
+6 -1
View File
@@ -534,7 +534,12 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
return
if(isAI(M))
return
show_inv(usr)
/mob/MouseDrop_T(atom/dropping, atom/user)
. = ..()
if(ismob(dropping) && dropping != user)
var/mob/M = dropping
M.show_inv(user)
/mob/proc/is_muzzled()
return 0
+1 -1
View File
@@ -164,7 +164,7 @@
/obj/item/pen/sleepy/Initialize()
. = ..()
create_reagents(45, OPENCONTAINER)
reagents.add_reagent("chloralhydratedelayed", 20)
reagents.add_reagent("chloralhydrate", 20)
reagents.add_reagent("mutetoxin", 15)
reagents.add_reagent("tirizene", 10)
+5
View File
@@ -323,6 +323,8 @@
var/BR = brightness
var/PO = bulb_power
var/CO = bulb_colour
if(color)
CO = color
var/area/A = get_area(src)
if (A && A.fire)
CO = bulb_emergency_colour
@@ -360,6 +362,9 @@
else
removeStaticPower(static_power_used, STATIC_LIGHT)
/obj/machinery/light/update_atom_colour()
. = ..()
update()
/obj/machinery/light/process()
if (!cell)
+6 -5
View File
@@ -19,6 +19,7 @@
circuit = /obj/item/circuitboard/machine/rad_collector
var/obj/item/tank/internals/plasma/loaded_tank = null
var/stored_power = 0
var/last_push
var/active = 0
var/locked = FALSE
var/drainratio = 1
@@ -61,9 +62,9 @@
loaded_tank.air_contents.gases[/datum/gas/oxygen] -= gasdrained
loaded_tank.air_contents.gases[/datum/gas/carbon_dioxide] += gasdrained*2
GAS_GARBAGE_COLLECT(loaded_tank.air_contents.gases)
var/bitcoins_mined = RAD_COLLECTOR_OUTPUT
SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, bitcoins_mined*RAD_COLLECTOR_MINING_CONVERSION_RATE)
stored_power-=bitcoins_mined
SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, stored_power*RAD_COLLECTOR_MINING_CONVERSION_RATE)
last_push = stored_power
stored_power = 0
/obj/machinery/power/rad_collector/interact(mob/user)
if(anchored)
@@ -170,9 +171,9 @@
. = ..()
if(active)
if(!bitcoinmining)
to_chat(user, "<span class='notice'>[src]'s display states that it has stored <b>[DisplayPower(stored_power)]</b>, and processing <b>[DisplayPower(RAD_COLLECTOR_OUTPUT)]</b>.</span>")
to_chat(user, "<span class='notice'>[src]'s display states that it has stored <b>[DisplayPower(stored_power)]</b>, and is processing <b>[DisplayPower((RAD_COLLECTOR_OUTPUT)*((60 SECONDS)/SSmachines.wait))]</b> per minute. <br>The <b>plasma</b> within it's tank is being irradiated into <b>tritium</b>.</span>")
else
to_chat(user, "<span class='notice'>[src]'s display states that it has stored a total of <b>[stored_power*RAD_COLLECTOR_MINING_CONVERSION_RATE]</b>, and producing [RAD_COLLECTOR_OUTPUT*RAD_COLLECTOR_MINING_CONVERSION_RATE] research points per minute.</span>")
to_chat(user, "<span class='notice'>[src]'s display states that it's producing a total of <b>[(last_push*RAD_COLLECTOR_MINING_CONVERSION_RATE)*((60 SECONDS)/SSmachines.wait)]</b> research points per minute. <br>The <b>tritium</b> and <b>oxygen</b> within it's tank is being combusted into <b>carbon dioxide</b>.</span>")
else
if(!bitcoinmining)
to_chat(user,"<span class='notice'><b>[src]'s display displays the words:</b> \"Power production mode. Please insert <b>Plasma</b>. Use a multitool to change production modes.\"</span>")
@@ -71,3 +71,9 @@
projectile_type = /obj/item/projectile/beam/mindflayer
select_name = "MINDFUCK"
fire_sound = 'sound/weapons/laser.ogg'
/obj/item/ammo_casing/energy/laser/weak
projectile_type = /obj/item/projectile/beam/weak/minigun
e_cost = 10
fire_sound = 'sound/weapons/gatling.ogg'
click_cooldown_override = 1
@@ -118,11 +118,11 @@
switch(fail_tick)
if(0 to 200)
fail_tick += (2*(fail_chance))
M.rad_act(40)
M.rad_act(400)
to_chat(M, "<span class='userdanger'>Your [name] feels warmer.</span>")
if(201 to INFINITY)
SSobj.processing.Remove(src)
M.rad_act(80)
M.rad_act(800)
crit_fail = 1
to_chat(M, "<span class='userdanger'>Your [name]'s reactor overloads!</span>")
@@ -0,0 +1,149 @@
//The ammo/gun is stored in a back slot item
/obj/item/minigunpack2
name = " Laser Gatling Pack"
desc = "A massive battery pack with an attached laser gatling gun!"
icon = 'icons/obj/guns/minigun.dmi'
icon_state = "holstered"
item_state = "backpack"
lefthand_file = 'icons/mob/inhands/equipment/backpack_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/backpack_righthand.dmi'
slot_flags = ITEM_SLOT_BACK
w_class = WEIGHT_CLASS_HUGE
var/obj/item/gun/energy/minigun/gun
var/armed = 0 //whether the gun is attached, 0 is attached, 1 is the gun is wielded.
var/overheat = 0
var/overheat_max = 60
var/heat_diffusion = 5
/obj/item/minigunpack2/Initialize()
. = ..()
gun = new(src)
START_PROCESSING(SSobj, src)
/obj/item/minigunpack2/Destroy()
STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/minigunpack2/process()
overheat = max(0, overheat - heat_diffusion)
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/minigunpack2/attack_hand(var/mob/living/carbon/user)
if(src.loc == user)
if(!armed)
if(user.get_item_by_slot(SLOT_BACK) == src)
armed = 1
if(!user.put_in_hands(gun))
armed = 0
to_chat(user, "<span class='warning'>You need a free hand to hold the gun!</span>")
return
update_icon()
user.update_inv_back()
else
to_chat(user, "<span class='warning'>You are already holding the gun!</span>")
else
..()
/obj/item/minigunpack2/attackby(obj/item/W, mob/user, params)
if(W == gun) //Don't need armed check, because if you have the gun assume its armed.
user.dropItemToGround(gun, TRUE)
else
..()
/obj/item/minigunpack2/dropped(mob/user)
if(armed)
user.dropItemToGround(gun, TRUE)
/obj/item/minigunpack2/MouseDrop(atom/over_object)
. = ..()
if(armed)
return
if(iscarbon(usr))
var/mob/M = usr
if(!over_object)
return
if(!M.incapacitated())
if(istype(over_object, /obj/screen/inventory/hand))
var/obj/screen/inventory/hand/H = over_object
M.putItemFromInventoryInHandIfPossible(src, H.held_index)
/obj/item/minigunpack2/update_icon()
if(armed)
icon_state = "notholstered"
else
icon_state = "holstered"
/obj/item/minigunpack2/proc/attach_gun(var/mob/user)
if(!gun)
gun = new(src)
gun.forceMove(src)
armed = 0
if(user)
to_chat(user, "<span class='notice'>You attach the [gun.name] to the [name].</span>")
else
src.visible_message("<span class='warning'>The [gun.name] snaps back onto the [name]!</span>")
update_icon()
user.update_inv_back()
/obj/item/gun/energy/minigun
name = "laser gatling gun"
desc = "An advanced laser cannon with an incredible rate of fire. Requires a bulky backpack power source to use."
icon = 'icons/obj/guns/minigun.dmi'
icon_state = "minigun_spin"
item_state = "minigun"
flags_1 = CONDUCT_1
force = 15
recoil = 2
slowdown = 1
slot_flags = null
w_class = WEIGHT_CLASS_HUGE
materials = list()
ammo_type = list(/obj/item/ammo_casing/energy/laser/weak)
burst_size = 2
automatic = 1
can_charge = 0
selfcharge = EGUN_SELFCHARGE
charge_tick = 2
charge_delay = 5
weapon_weight = WEAPON_HEAVY
item_flags = NEEDS_PERMIT | SLOWS_WHILE_IN_HAND
var/obj/item/minigunpack2/ammo_pack
/obj/item/gun/energy/minigun/Initialize()
if(istype(loc, /obj/item/minigunpack2)) //We should spawn inside an ammo pack so let's use that one.
ammo_pack = loc
else
return INITIALIZE_HINT_QDEL //No pack, no gun
return ..()
/obj/item/gun/energy/minigun/attack_self(mob/living/user)
return
/obj/item/gun/energy/minigun/dropped(mob/user)
if(ammo_pack)
ammo_pack.attach_gun(user)
else
qdel(src)
/obj/item/gun/energy/minigun/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0)
if(ammo_pack)
if(ammo_pack.overheat < ammo_pack.overheat_max)
ammo_pack.overheat += burst_size
..()
else
to_chat(user, "The gun's heat sensor locked the trigger to prevent lens damage.")
/obj/item/gun/energy/minigun/afterattack(atom/target, mob/living/user, flag, params)
if(!ammo_pack || ammo_pack.loc != user)
to_chat(user, "You need the backpack power source to fire the gun!")
. = ..()
/obj/item/gun/energy/minigun/dropped(mob/living/user)
ammo_pack.attach_gun(user)
@@ -39,6 +39,14 @@
/obj/item/projectile/beam/weak
damage = 15
/obj/item/projectile/beam/weak/minigun
damage = 12.5
armour_penetration = 40
/obj/item/projectile/beam/weak/minigun/Initialize()
.=..()
speed = pick(0.7,0.75,0.8,0.85,0.9,0.95,1,1.05,1.1,1.15)
/obj/item/projectile/beam/weak/penetrator
armour_penetration = 50
@@ -77,6 +77,16 @@
updateUsrDialog()
update_icon()
return
if(beaker)
if(istype(I, /obj/item/reagent_containers/dropper))
var/obj/item/reagent_containers/dropper/D = I
D.afterattack(beaker, user, 1)
if(istype(I, /obj/item/reagent_containers/syringe))
var/obj/item/reagent_containers/syringe/S = I
S.afterattack(beaker, user, 1)
return ..()
/obj/machinery/chem_heater/on_deconstruction()
@@ -313,25 +313,6 @@
. = 1
..()
/datum/reagent/toxin/chloralhydratedelayed //sedates half as quickly and does not cause toxloss. same name/desc so it doesn't give away sleepypens
name = "Chloral Hydrate"
id = "chloralhydratedelayed"
description = "A powerful sedative that induces confusion and drowsiness before putting its target to sleep."
reagent_state = SOLID
color = "#000067" // rgb: 0, 0, 103
toxpwr = 0
metabolization_rate = 1 * REAGENTS_METABOLISM
/datum/reagent/toxin/chloralhydratedelayed/on_mob_life(mob/living/carbon/M)
switch(current_cycle)
if(10 to 20)
M.confused += 1
M.drowsyness += 1
M.adjustStaminaLoss(7.5)
if(20 to INFINITY)
M.Sleeping(40, 0)
..()
/datum/reagent/toxin/fakebeer //disguised as normal beer for use by emagged brobots
name = "Beer"
id = "fakebeer"
@@ -389,12 +370,12 @@
id = "tirizene"
description = "A nonlethal poison that causes extreme fatigue and weakness in its victim."
color = "#6E2828"
data = 13
data = 15
toxpwr = 0
/datum/reagent/toxin/staminatoxin/on_mob_life(mob/living/carbon/M)
M.adjustStaminaLoss(REM * data, 0)
data = max(data - 1, 3)
data = max(data - 1, 5)
..()
. = 1
+64 -22
View File
@@ -17,6 +17,7 @@
var/spillable = FALSE
var/beaker_weakness_bitflag = NONE//Bitflag!
var/container_HP = 2
var/cached_icon
/obj/item/reagent_containers/Initialize(mapload, vol)
. = ..()
@@ -148,30 +149,71 @@
/obj/item/reagent_containers/proc/temp_check()
if(beaker_weakness_bitflag & TEMP_WEAK)
if(reagents.chem_temp >= 444)//assuming polypropylene
var/list/seen = viewers(5, get_turf(src))
var/iconhtml = icon2html(src, seen)
for(var/mob/M in seen)
to_chat(M, "<span class='notice'>[iconhtml] \The [src]'s melts from the temperature!</span>")
playsound(get_turf(src), 'sound/FermiChem/heatmelt.ogg', 80, 1)
to_chat(M, "<span class='warning'><i>[iconhtml] Have you tried using glass or meta beakers for high temperature reactions? These are immune to temperature effects.</i></span>")
SSblackbox.record_feedback("tally", "fermi_chem", 1, "Times beakers have melted from temperature")
qdel(src)
START_PROCESSING(SSobj, src)
//melts glass beakers
/obj/item/reagent_containers/proc/pH_check()
if(beaker_weakness_bitflag & PH_WEAK)
if((reagents.pH < 0.5) || (reagents.pH > 13.5))
var/list/seen = viewers(5, get_turf(src))
var/iconhtml = icon2html(src, seen)
container_HP--
if(container_HP <= 0)
for(var/mob/M in seen)
to_chat(M, "<span class='notice'>[iconhtml] \The [src]'s melts from the extreme pH!</span>")
playsound(get_turf(src), 'sound/FermiChem/acidmelt.ogg', 80, 1)
SSblackbox.record_feedback("tally", "fermi_chem", 1, "Times beakers have melted from pH")
qdel(src)
if((reagents.pH < 1.5) || (reagents.pH > 12.5))
START_PROCESSING(SSobj, src)
/obj/item/reagent_containers/process()
if(!cached_icon)
cached_icon = icon_state
var/damage
var/cause
if(beaker_weakness_bitflag & PH_WEAK)
if(reagents.pH < 2)
damage = (2 - reagents.pH)/20
cause = "from the extreme pH"
playsound(get_turf(src), 'sound/FermiChem/bufferadd.ogg', 50, 1)
if(reagents.pH > 12)
damage = (reagents.pH - 12)/20
cause = "from the extreme pH"
playsound(get_turf(src), 'sound/FermiChem/bufferadd.ogg', 50, 1)
if(beaker_weakness_bitflag & TEMP_WEAK)
if(reagents.chem_temp >= 444)
if(damage)
damage += (reagents.chem_temp/444)/5
else
for(var/mob/M in seen)
to_chat(M, "<span class='notice'>[iconhtml] \The [src]'s is damaged by the extreme pH and begins to deform!</span>")
playsound(get_turf(src), 'sound/FermiChem/bufferadd.ogg', 50, 1)
to_chat(M, "<span class='warning'><i>[iconhtml] Have you tried using plastic beakers (XL) or metabeakers for high pH reactions? These beakers are immune to pH effects.</i></span>")
damage = (reagents.chem_temp/444)/5
if(cause)
cause += " and "
cause += "from the high temperature"
playsound(get_turf(src), 'sound/FermiChem/heatdam.ogg', 50, 1)
if(!damage || damage <= 0)
STOP_PROCESSING(SSobj, src)
container_HP -= damage
var/list/seen = viewers(5, get_turf(src))
var/iconhtml = icon2html(src, seen)
var/damage_percent = ((container_HP / initial(container_HP)*100))
switch(damage_percent)
if(-INFINITY to 0)
for(var/mob/M in seen)
to_chat(M, "<span class='notice'>[iconhtml] \The [src]'s melts [cause]!</span>")
playsound(get_turf(src), 'sound/FermiChem/acidmelt.ogg', 80, 1)
SSblackbox.record_feedback("tally", "fermi_chem", 1, "Times beakers have melted")
STOP_PROCESSING(SSobj, src)
qdel(src)
return
if(0 to 35)
icon_state = "[cached_icon]_m3"
desc = "[initial(desc)] It is severely deformed."
if(35 to 70)
icon_state = "[cached_icon]_m2"
desc = "[initial(desc)] It is deformed."
if(70 to 85)
desc = "[initial(desc)] It is mildly deformed."
icon_state = "[cached_icon]_m1"
update_icon()
if(prob(25))
for(var/mob/M in seen)
to_chat(M, "<span class='notice'>[iconhtml] \The [src]'s is damaged by [cause] and begins to deform!</span>")
@@ -6,7 +6,7 @@
reagent_flags = OPENCONTAINER
spillable = TRUE
resistance_flags = ACID_PROOF
container_HP = 3
container_HP = 2
/obj/item/reagent_containers/glass/attack(mob/M, mob/user, obj/target)
@@ -115,7 +115,6 @@
item_state = "beaker"
materials = list(MAT_GLASS=500)
beaker_weakness_bitflag = PH_WEAK
container_HP = 5
/obj/item/reagent_containers/glass/beaker/Initialize()
. = ..()
@@ -128,27 +127,29 @@
update_icon()
/obj/item/reagent_containers/glass/beaker/update_icon()
if(!cached_icon)
cached_icon = icon_state
cut_overlays()
if(reagents.total_volume)
var/mutable_appearance/filling = mutable_appearance('icons/obj/reagentfillings.dmi', "[icon_state]10")
var/mutable_appearance/filling = mutable_appearance('icons/obj/reagentfillings.dmi', "[cached_icon]10")
var/percent = round((reagents.total_volume / volume) * 100)
switch(percent)
if(0 to 9)
filling.icon_state = "[icon_state]-10"
filling.icon_state = "[cached_icon]-10"
if(10 to 24)
filling.icon_state = "[icon_state]10"
filling.icon_state = "[cached_icon]10"
if(25 to 49)
filling.icon_state = "[icon_state]25"
filling.icon_state = "[cached_icon]25"
if(50 to 74)
filling.icon_state = "[icon_state]50"
filling.icon_state = "[cached_icon]50"
if(75 to 79)
filling.icon_state = "[icon_state]75"
filling.icon_state = "[cached_icon]75"
if(80 to 90)
filling.icon_state = "[icon_state]80"
filling.icon_state = "[cached_icon]80"
if(91 to INFINITY)
filling.icon_state = "[icon_state]100"
filling.icon_state = "[cached_icon]100"
filling.color = mix_color_from_reagents(reagents.reagent_list)
add_overlay(filling)
@@ -167,7 +168,7 @@
volume = 100
amount_per_transfer_from_this = 10
possible_transfer_amounts = list(5,10,15,20,25,30,50,100)
container_HP = 6
container_HP = 3
/obj/item/reagent_containers/glass/beaker/plastic
name = "x-large beaker"
@@ -227,7 +228,7 @@
volume = 300
amount_per_transfer_from_this = 10
possible_transfer_amounts = list(5,10,15,20,25,30,50,100,300)
container_HP = 8
container_HP = 4
/obj/item/reagent_containers/glass/beaker/cryoxadone
list_reagents = list("cryoxadone" = 30)
@@ -284,7 +285,7 @@
SLOT_L_STORE, SLOT_R_STORE,\
SLOT_GENERC_DEXTROUS_STORAGE
)
container_HP = 2
container_HP = 1
/obj/item/reagent_containers/glass/bucket/Initialize()
beaker_weakness_bitflag |= TEMP_WEAK
@@ -338,7 +339,7 @@
materials = list(MAT_GLASS=0)
volume = 50
amount_per_transfer_from_this = 10
container_HP = 2
container_HP = 1
/obj/item/reagent_containers/glass/beaker/waterbottle/Initialize()
beaker_weakness_bitflag |= TEMP_WEAK
@@ -354,7 +355,7 @@
list_reagents = list("water" = 100)
volume = 100
amount_per_transfer_from_this = 20
container_HP = 2
container_HP = 1
/obj/item/reagent_containers/glass/beaker/waterbottle/large/empty
list_reagents = list()
+3 -3
View File
@@ -7,12 +7,12 @@
products = list(/obj/item/clothing/glasses/meson/engine = 5,
/obj/item/clothing/glasses/welding = 5,
/obj/item/multitool = 5,
/obj/item/construction/rcd/loaded = 3,
/obj/item/construction/rcd/loaded/upgraded = 3,
/obj/item/grenade/chem_grenade/smart_metal_foam = 10,
/obj/item/geiger_counter = 6,
/obj/item/stock_parts/cell/high = 10,
/obj/item/electronics/airlock = 10,
/obj/item/electronics/apc = 10,
/obj/item/electronics/airlock = 10,
/obj/item/electronics/apc = 10,
/obj/item/electronics/airalarm = 10,
/obj/item/electronics/firealarm = 10,
/obj/item/electronics/firelock = 10,
+13
View File
@@ -0,0 +1,13 @@
author: "Ghommie (original PRs by Mickyan, Anturk, ShizCalev, nemvar and Naksu)"
delete-after: True
changes:
- rscadd: "After rigorous mandatory art training for the crew, many new graffiti styles are now available"
- bugfix: "Cleaned up some crayon and spraycan code for futureproofing."
- bugfix: "Spraypainting blast doors no longer makes them see-through."
- balance: "Paint remover now works on blast doors and the like."
- rscadd: "Most objects can now be colored using a spray can."
- spellcheck: "Added visible message to spraying objects and windows."
- rscadd: "Colored lights now shine in different colours."
- rscdel: "Removed individual buttons text in crayon/spraycan UI, speeding it up."
- bugfix: "Text mode buffer is actually visible in the UI."
- tweak: "Last letter of a text mode buffer no longer rotates out to be replaced with \"a\", allowing the text mode to be used for individual symbols."
@@ -0,0 +1,5 @@
author: "Sishen1542"
delete-after: True
changes:
- rscadd: "made laser minigun not shitcode and also craftable"
- soundadd: "added new fire sounds for the laser minigun"
@@ -0,0 +1,6 @@
author: "Linzolle"
delete-after: True
changes:
- rscadd: "can now carry people on your back by aggressive grabbing them while they are laying down and then dragging their sprite onto yours."
- tweak: "dragging people who are prone is now much slower, and carrying them will allow you to move faster at the cost of taking 5 seconds to lift them up onto your back."
- tweak: "pacifists can now aggressive grab (cannot table slam people though)"
@@ -0,0 +1,4 @@
author: "Tupinambis"
delete-after: True
changes:
- balance: "Engivend RCDs now vend upgraded RCDs"
@@ -0,0 +1,7 @@
author: "Ghommie (original PR by CrazyClown12)"
delete-after: True
changes:
- tweak: "The chloral hydrate inside of the sleepy pen is no longer slower acting than chloral hydrate made in chemistry."
- tweak: "The chloral hydrate inside of cookies synthesised by emagged borgs is no longer slower acting than chloral hydrate made in chemistry."
- balance: "Slight tirizene buff."
- rscdel: "Delayed chloral hydrate"
@@ -0,0 +1,5 @@
author: "Ghommie (original PR by harmonyn)"
delete-after: True
changes:
- balance: "Resisting out of bucklecuffs takes more/less time depending on the handcuffs you used, i.e., fake handcuffs will not bucklecuff someone for ages."
- tweak: "fake handcuffs shouldn't no longer demoralize restrained criminals scums."
@@ -0,0 +1,6 @@
author: "Linzolle"
delete-after: True
changes:
- bugfix: "blood halberd not going back to 17 force after unwielding"
- spellcheck: "unnecessary 's at the end of blood rites healing"
- rscadd: "QoL to blood rites, examine the ritual aura to view how many blood charges are left"
@@ -0,0 +1,4 @@
author: "Sishen1542"
delete-after: True
changes:
- bugfix: "narsie no longer asks for consent"
@@ -0,0 +1,4 @@
author: "YakumoChen"
delete-after: True
changes:
- tweak: "AEGs brought more in line with current radiation system. Try not to get EMP'd."
@@ -0,0 +1,8 @@
author: "Fermis"
delete-after: True
changes:
- tweak: "tweaked beaker health and allows use of syringes/droppers on chem_heaters"
- soundadd: "added a sound for when beakers take temperature damage."
- imageadd: "added some icons for melting beakers"
- refactor: "refactored how beakers take damage"
- bugfix: "fixes how beakers would only take one instance of damage on pH damage"
@@ -0,0 +1,6 @@
author: "Ghommie (original PRs by Time-Green and Qustinnus)"
delete-after: True
changes:
- tweak: "loot crates can't explode after unlocking anymore"
- bugfix: "jumping into loot crates no longers causes them to go boom"
- bugfix: "You can now deconstruct abandoned crates with a welder without making them go boom. After unlocking them, of course."
@@ -0,0 +1,5 @@
author: "Ghommie"
delete-after: True
changes:
- bugfix: "Fixed advanced medical scanners borg upgrades."
- bugfix: "Fixes certain borg upgrades being unapplicable on dogborg counterparts of the target cyborg type."
@@ -0,0 +1,6 @@
author: "Bhijn"
delete-after: True
changes:
- balance: "The point production mode of radiation collectors has been reverted to the original behavior of using all of the stored power every process cycle instead of just 4% of it"
- tweak: "Radiation collectors now display the amount of power/research points they're producing per minute rather than per process cycle, which should hopefully clear up a lot of confusion."
- tweak: "Radiation collectors also display what's happening to the gas within them, which should make it a lot more obvious as to how you get tritium."
Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 25 KiB

@@ -1,29 +0,0 @@
// Citadel's Vtech Controller
/obj/effect/proc_holder/silicon/cyborg/vtecControl
name = "vTec Control"
desc = "Allows finer-grained control of the vTec speed boost."
action_icon = 'icons/mob/actions.dmi'
action_icon_state = "Chevron_State_0"
var/currentState = 0
var/maxReduction = 2
/obj/effect/proc_holder/silicon/cyborg/vtecControl/Click(mob/living/silicon/robot/user)
var/mob/living/silicon/robot/self = usr
currentState = (currentState + 1) % 3
if(usr)
switch(currentState)
if (0)
self.speed = maxReduction
if (1)
self.speed -= maxReduction*0.5
if (2)
self.speed -= maxReduction*1.25
action.button_icon_state = "Chevron_State_[currentState]"
action.UpdateButtonIcon()
return
@@ -16,7 +16,7 @@
//When merging two fermichems, see above
/datum/reagent/fermi/on_merge(data, amount, mob/living/carbon/M, purity)//basically on_mob_add but for merging
. = ..()
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -331,6 +331,8 @@
//Consumes self on addition and shifts pH
/datum/reagent/fermi/acidic_buffer/on_new(datapH)
if(holder.has_reagent("stabilizing_agent"))
return ..()
data = datapH
if(LAZYLEN(holder.reagent_list) == 1)
return
@@ -351,6 +353,8 @@
can_synth = TRUE
/datum/reagent/fermi/basic_buffer/on_new(datapH)
if(holder.has_reagent("stabilizing_agent"))
return ..()
data = datapH
if(LAZYLEN(holder.reagent_list) == 1)
return
+1
View File
@@ -6,5 +6,6 @@ heatacid.ogg - from https://freesound.org/people/klankbeeld/sounds/233697/
from bubbles2.ogg
from fuse.ogg
bufferadd.ogg- https://freesound.org/people/toiletrolltube/sounds/181483/
heatdamn.ogg - from https://freesound.org/people/klankbeeld/sounds/233697/
Work is licensed under the Creative Commons and Attribution License.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -2458,6 +2458,7 @@
#include "code\modules\projectiles\guns\energy\kinetic_accelerator.dm"
#include "code\modules\projectiles\guns\energy\laser.dm"
#include "code\modules\projectiles\guns\energy\megabuster.dm"
#include "code\modules\projectiles\guns\energy\minigun.dm"
#include "code\modules\projectiles\guns\energy\mounted.dm"
#include "code\modules\projectiles\guns\energy\plasma_cit.dm"
#include "code\modules\projectiles\guns\energy\pulse.dm"
@@ -2951,7 +2952,6 @@
#include "modular_citadel\code\game\objects\items\devices\radio\headset.dm"
#include "modular_citadel\code\game\objects\items\devices\radio\shockcollar.dm"
#include "modular_citadel\code\game\objects\items\melee\eutactic_blades.dm"
#include "modular_citadel\code\game\objects\items\robot\robot_upgrades.dm"
#include "modular_citadel\code\game\objects\items\storage\firstaid.dm"
#include "modular_citadel\code\game\objects\structures\tables_racks.dm"
#include "modular_citadel\code\game\objects\structures\beds_chairs\chair.dm"
+13 -13
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -29,7 +29,7 @@
{{/each}}
</ui-display>
<ui-display title="Text Mode">
<ui-section label='Current Buffer'>{{text_buffer}}
<ui-section label='Current Buffer'>{{data.text_buffer}}
</ui-section>
<ui-section><ui-button action='enter_text'>New Text</ui-button></ui-section>
</ui-display>