Merge branch 'master' into Unmodular
This commit is contained in:
@@ -29,69 +29,62 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
|
||||
/client/proc/callproc()
|
||||
set category = "Debug"
|
||||
set name = "Advanced ProcCall"
|
||||
set waitfor = 0
|
||||
set waitfor = FALSE
|
||||
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
var/datum/target = null
|
||||
var/targetselected = 0
|
||||
var/targetselected = FALSE
|
||||
var/returnval = null
|
||||
|
||||
switch(alert("Proc owned by something?",,"Yes","No"))
|
||||
if("Yes")
|
||||
targetselected = 1
|
||||
var/list/value = vv_get_value(default_class = VV_ATOM_REFERENCE, classes = list(VV_ATOM_REFERENCE, VV_DATUM_REFERENCE, VV_MOB_REFERENCE, VV_CLIENT))
|
||||
if (!value["class"] || !value["value"])
|
||||
return
|
||||
target = value["value"]
|
||||
if("No")
|
||||
target = null
|
||||
targetselected = 0
|
||||
|
||||
var/procname = input("Proc path, eg: /proc/fake_blood","Path:", null) as text|null
|
||||
if(!procname)
|
||||
return
|
||||
|
||||
//hascall() doesn't support proc paths (eg: /proc/gib(), it only supports "gib")
|
||||
var/testname = procname
|
||||
if(targetselected)
|
||||
//Find one of the 3 possible ways they could have written /proc/PROCNAME
|
||||
if(findtext(procname, "/proc/"))
|
||||
testname = replacetext(procname, "/proc/", "")
|
||||
else if(findtext(procname, "/proc"))
|
||||
testname = replacetext(procname, "/proc", "")
|
||||
else if(findtext(procname, "proc/"))
|
||||
testname = replacetext(procname, "proc/", "")
|
||||
//Clear out any parenthesis if they're a dummy
|
||||
testname = replacetext(testname, "()", "")
|
||||
|
||||
if(targetselected && !hascall(target,testname))
|
||||
to_chat(usr, "<font color='red'>Error: callproc(): type [target.type] has no proc named [procname].</font>")
|
||||
return
|
||||
else
|
||||
var/procpath = text2path(procname)
|
||||
if (!procpath)
|
||||
to_chat(usr, "<font color='red'>Error: callproc(): proc [procname] does not exist. (Did you forget the /proc/ part?)</font>")
|
||||
if(alert("Proc owned by something?",,"Yes","No") == "Yes")
|
||||
targetselected = TRUE
|
||||
var/list/value = vv_get_value(default_class = VV_ATOM_REFERENCE, classes = list(VV_ATOM_REFERENCE, VV_DATUM_REFERENCE, VV_MOB_REFERENCE, VV_CLIENT))
|
||||
if (!value["class"] || !value["value"])
|
||||
return
|
||||
target = value["value"]
|
||||
|
||||
var/procpath = input("Proc path, eg: /proc/fake_blood","Path:", null) as text|null
|
||||
if(!procpath)
|
||||
return
|
||||
|
||||
//strip away everything but the proc name
|
||||
var/list/proclist = splittext(procpath, "/")
|
||||
if (!length(proclist))
|
||||
return
|
||||
|
||||
var/procname = proclist[proclist.len]
|
||||
var/proctype = ("verb" in proclist) ? "verb" :"proc"
|
||||
|
||||
if(targetselected)
|
||||
if(!hascall(target, procname))
|
||||
to_chat(usr, "<span class='warning'>Error: callproc(): type [target.type] has no [proctype] named [procpath].</span>")
|
||||
return
|
||||
else
|
||||
procpath = "/[proctype]/[procname]"
|
||||
if(!text2path(procpath))
|
||||
to_chat(usr, "<span class='warning'>Error: callproc(): [procpath] does not exist.</span>")
|
||||
return
|
||||
|
||||
var/list/lst = get_callproc_args()
|
||||
if(!lst)
|
||||
return
|
||||
|
||||
if(targetselected)
|
||||
if(!target)
|
||||
to_chat(usr, "<font color='red'>Error: callproc(): owner of proc no longer exists.</font>")
|
||||
to_chat(usr, "<span class='warning'>Error: callproc(): owner of proc no longer exists.</span>")
|
||||
return
|
||||
var/msg = "[key_name(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]."
|
||||
var/msg = "[key_name(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no argument"]."
|
||||
log_admin(msg)
|
||||
message_admins(msg)
|
||||
admin_ticket_log(target, msg)
|
||||
returnval = WrapAdminProcCall(target, procname, lst) // Pass the lst as an argument list to the proc
|
||||
returnval = WrapAdminProcCall(target, procname, lst)
|
||||
else
|
||||
//this currently has no hascall protection. wasn't able to get it working.
|
||||
log_admin("[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
|
||||
message_admins("[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
|
||||
returnval = WrapAdminProcCall(GLOBAL_PROC, procname, lst) // Pass the lst as an argument list to the proc
|
||||
var/msg = "[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no argument"]."
|
||||
log_admin(msg)
|
||||
message_admins(msg)
|
||||
returnval = WrapAdminProcCall(GLOBAL_PROC, procpath, lst) //calling globals needs full qualified name (e.g /proc/foo)
|
||||
. = get_callproc_returnval(returnval, procname)
|
||||
if(.)
|
||||
to_chat(usr, .)
|
||||
@@ -111,8 +104,8 @@ GLOBAL_LIST_EMPTY(AdminProcCallSpamPrevention)
|
||||
GLOBAL_PROTECT(AdminProcCallSpamPrevention)
|
||||
|
||||
/proc/WrapAdminProcCall(datum/target, procname, list/arguments)
|
||||
if(target && procname == "Del")
|
||||
to_chat(usr, "Calling Del() is not allowed")
|
||||
if(target != GLOBAL_PROC && procname == "Del")
|
||||
to_chat(usr, "<span class='warning'>Calling Del() is not allowed</span>")
|
||||
return
|
||||
|
||||
if(target != GLOBAL_PROC && !target.CanProcCall(procname))
|
||||
@@ -159,7 +152,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
|
||||
/client/proc/callproc_datum(datum/A as null|area|mob|obj|turf)
|
||||
set category = "Debug"
|
||||
set name = "Atom ProcCall"
|
||||
set waitfor = 0
|
||||
set waitfor = FALSE
|
||||
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
@@ -168,7 +161,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
|
||||
if(!procname)
|
||||
return
|
||||
if(!hascall(A,procname))
|
||||
to_chat(usr, "<font color='red'>Error: callproc_datum(): type [A.type] has no proc named [procname].</font>")
|
||||
to_chat(usr, "<span class='warning'>Error: callproc_datum(): type [A.type] has no proc named [procname].</span>")
|
||||
return
|
||||
var/list/lst = get_callproc_args()
|
||||
if(!lst)
|
||||
@@ -177,8 +170,8 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
|
||||
if(!A || !IsValidSrc(A))
|
||||
to_chat(usr, "<span class='warning'>Error: callproc_datum(): owner of proc no longer exists.</span>")
|
||||
return
|
||||
log_admin("[key_name(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
|
||||
var/msg = "[key_name(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]."
|
||||
log_admin(msg)
|
||||
message_admins(msg)
|
||||
admin_ticket_log(A, msg)
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Atom ProcCall") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
@@ -188,8 +181,6 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
|
||||
if(.)
|
||||
to_chat(usr, .)
|
||||
|
||||
|
||||
|
||||
/client/proc/get_callproc_args()
|
||||
var/argnum = input("Number of arguments","Number:",0) as num|null
|
||||
if(isnull(argnum))
|
||||
@@ -213,7 +204,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
|
||||
. = ""
|
||||
if(islist(returnval))
|
||||
var/list/returnedlist = returnval
|
||||
. = "<font color='blue'>"
|
||||
. = "<span class='notice'>"
|
||||
if(returnedlist.len)
|
||||
var/assoc_check = returnedlist[1]
|
||||
if(istext(assoc_check) && (returnedlist[assoc_check] != null))
|
||||
@@ -227,11 +218,10 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
|
||||
. += "\n[elem]"
|
||||
else
|
||||
. = "[procname] returned an empty list"
|
||||
. += "</font>"
|
||||
. += "</span>"
|
||||
|
||||
else
|
||||
. = "<font color='blue'>[procname] returned: [!isnull(returnval) ? returnval : "null"]</font>"
|
||||
|
||||
. = "<span class='notice'>[procname] returned: [!isnull(returnval) ? returnval : "null"]</span>"
|
||||
|
||||
/client/proc/Cell()
|
||||
set category = "Debug"
|
||||
|
||||
@@ -126,8 +126,20 @@
|
||||
if(vest)
|
||||
vest.flip_mode()
|
||||
|
||||
/obj/machinery/abductor/console/proc/SelectDisguise(remote = 0)
|
||||
var/entry_name = input( "Choose Disguise", "Disguise") as null|anything in disguises
|
||||
/obj/machinery/abductor/console/proc/SelectDisguise(remote = FALSE)
|
||||
var/list/disguises2 = list()
|
||||
for(var/name in disguises)
|
||||
var/datum/icon_snapshot/snap = disguises[name]
|
||||
var/image/dummy = image(snap.icon, src, snap.icon_state)
|
||||
dummy.overlays = snap.overlays
|
||||
disguises2[name] = dummy
|
||||
|
||||
var/entry_name
|
||||
if(remote)
|
||||
entry_name = show_radial_menu(usr, camera.eyeobj, disguises2)
|
||||
else
|
||||
entry_name = show_radial_menu(usr, src, disguises2)
|
||||
|
||||
var/datum/icon_snapshot/chosen = disguises[entry_name]
|
||||
if(chosen && vest && (remote || in_range(usr,src)))
|
||||
vest.SetDisguise(chosen)
|
||||
|
||||
@@ -12,5 +12,5 @@
|
||||
|
||||
//Recover from stuns.
|
||||
/obj/effect/proc_holder/changeling/adrenaline/sting_action(mob/living/user)
|
||||
user.do_adrenaline(100, FALSE, 70, 0, TRUE, list("epinephrine" = 3, "changelingmeth" = 10, "mannitol" = 10, "omnizine" = 10, "changelingadrenaline" = 5), "<span class='notice'>Energy rushes through us.</span>")
|
||||
user.do_adrenaline(0, FALSE, 70, 0, TRUE, list("epinephrine" = 3, "changelingmeth" = 10, "mannitol" = 10, "regen_jelly" = 10, "changelingadrenaline" = 5), "<span class='notice'>Energy rushes through us.</span>", 0, 0.75, 0)
|
||||
return TRUE
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
O.forceMove(get_turf(user))
|
||||
|
||||
user.reagents.add_reagent("mutadone", 10)
|
||||
user.reagents.add_reagent("pen_acid", 20)
|
||||
user.reagents.add_reagent("pen_jelly", 20)
|
||||
user.reagents.add_reagent("antihol", 10)
|
||||
user.reagents.add_reagent("mannitol", 25)
|
||||
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/obj/structure/destructible/clockwork/reflector
|
||||
name = "reflector"
|
||||
desc = "A large lantern-shaped machine made of thin brass. It looks fragile."
|
||||
clockwork_desc = "A lantern-shaped generator that produces power when near starlight."
|
||||
icon_state = "reflector"
|
||||
unanchored_icon = "reflector_unwrenched"
|
||||
max_integrity = 40
|
||||
construction_value = 5
|
||||
layer = WALL_OBJ_LAYER
|
||||
break_message = "<span class='warning'>The reflectors's fragile shield shatters into pieces!</span>"
|
||||
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
|
||||
light_color = "#DAAA18"
|
||||
var/list/allowed_projectile_typecache = list(
|
||||
/obj/item/projectile/beam
|
||||
)
|
||||
|
||||
var/ini_dir = null
|
||||
|
||||
/obj/structure/destructible/clockwork/reflector/Initialize()
|
||||
. = ..()
|
||||
allowed_projectile_typecache = typecacheof(allowed_projectile_typecache)
|
||||
|
||||
/obj/structure/destructible/clockwork/reflector/ComponentInitialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/simple_rotation,ROTATION_ALTCLICK | ROTATION_CLOCKWISE | ROTATION_COUNTERCLOCKWISE | ROTATION_VERBS ,null,CALLBACK(src, .proc/can_be_rotated),CALLBACK(src,.proc/after_rotation))
|
||||
|
||||
/obj/structure/destructible/clockwork/reflector/bullet_act(obj/item/projectile/P)
|
||||
if(!anchored || !allowed_projectile_typecache[P.type] || !(P.dir in GLOB.cardinals))
|
||||
return ..()
|
||||
|
||||
if(auto_reflect(P, P.dir, get_turf(P), P.Angle) != -1)
|
||||
return ..()
|
||||
|
||||
return -1
|
||||
|
||||
/obj/structure/destructible/clockwork/reflector/proc/auto_reflect(obj/item/projectile/P, pdir, turf/ploc, pangle)
|
||||
|
||||
//Yell at me if this exists already.
|
||||
|
||||
var/real_angle = 0
|
||||
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
real_angle = 0
|
||||
if(EAST)
|
||||
real_angle = 90
|
||||
if(SOUTH)
|
||||
real_angle = 180
|
||||
if(WEST)
|
||||
real_angle = 270
|
||||
|
||||
var/incidence = GET_ANGLE_OF_INCIDENCE(real_angle, (P.Angle + 180))
|
||||
if(abs(incidence) > 90 && abs(incidence) < 270)
|
||||
return FALSE
|
||||
var/new_angle = SIMPLIFY_DEGREES(real_angle + incidence)
|
||||
P.setAngle(new_angle)
|
||||
P.ignore_source_check = TRUE
|
||||
P.range = P.decayedRange
|
||||
P.decayedRange = max(P.decayedRange--, 0)
|
||||
return -1
|
||||
|
||||
/obj/structure/destructible/clockwork/reflector/proc/can_be_rotated(mob/user,rotation_type)
|
||||
if(anchored)
|
||||
to_chat(user, "<span class='warning'>[src] cannot be rotated while it is fastened to the floor!</span>")
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/structure/destructible/clockwork/reflector/Move()
|
||||
. = ..()
|
||||
setDir(ini_dir)
|
||||
|
||||
/obj/structure/destructible/clockwork/reflector/proc/after_rotation(mob/user,rotation_type)
|
||||
ini_dir = dir
|
||||
add_fingerprint(user)
|
||||
|
||||
|
||||
/obj/structure/destructible/clockwork/reflector/wrench_act(mob/living/user, obj/item/I)
|
||||
|
||||
if(!is_servant_of_ratvar(user))
|
||||
return ..()
|
||||
|
||||
anchored = !anchored
|
||||
to_chat(user, "<span class='notice'>You [anchored ? "secure" : "unsecure"] \the [src].</span>")
|
||||
I.play_tool_sound(src)
|
||||
return TRUE
|
||||
@@ -361,6 +361,7 @@
|
||||
reshape.Shift(EAST, 1)
|
||||
reshape.Crop(7,4,26,31)
|
||||
reshape.Crop(-5,-3,26,30)
|
||||
return reshape
|
||||
|
||||
/mob/living/carbon/human/get_sac_image()
|
||||
var/datum/job/sacjob = SSjob.GetJob(mind.assigned_role)
|
||||
@@ -370,6 +371,7 @@
|
||||
reshape.Shift(EAST, 1)
|
||||
reshape.Crop(7,4,26,31)
|
||||
reshape.Crop(-5,-3,26,30)
|
||||
return reshape
|
||||
|
||||
/datum/objective/sacrifice
|
||||
var/sacced = FALSE
|
||||
|
||||
@@ -342,10 +342,7 @@
|
||||
if(cooldown>world.time)
|
||||
to_chat(owner, "<span class='cultbold'>You aren't ready to place another blood mark yet!</span>")
|
||||
return
|
||||
if(owner.orbiting && owner.orbiting.orbiting)
|
||||
target = owner.orbiting.orbiting
|
||||
else
|
||||
target = get_turf(owner)
|
||||
target = owner.orbiting?.parent || get_turf(owner)
|
||||
if(!target)
|
||||
return
|
||||
C.cult_team.blood_target = target
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
visible_message("<span class='warning'>[src] easily breaks out of [p_their()] handcuffs!</span>", \
|
||||
"<span class='notice'>With just a thought your handcuffs fall off.</span>")
|
||||
|
||||
/mob/living/carbon/true_devil/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
|
||||
/mob/living/carbon/true_devil/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
|
||||
if(incapacitated())
|
||||
to_chat(src, "<span class='warning'>You can't do that right now!</span>")
|
||||
return FALSE
|
||||
|
||||
@@ -516,14 +516,16 @@
|
||||
|
||||
/datum/supply_pack/security/armory/ballistic
|
||||
name = "Combat Shotguns Crate"
|
||||
desc = "For when the enemy absolutely needs to be replaced with lead. Contains three Aussec-designed Combat Shotguns, and three Shotgun Bandoliers. Requires Armory access to open."
|
||||
desc = "For when the enemy absolutely needs to be replaced with lead. Contains three Aussec-designed Combat Shotguns, with three Shotgun Bandoliers, as well as seven buchshot and 12g shotgun slugs. Requires Armory access to open."
|
||||
cost = 8000
|
||||
contains = list(/obj/item/gun/ballistic/shotgun/automatic/combat,
|
||||
/obj/item/gun/ballistic/shotgun/automatic/combat,
|
||||
/obj/item/gun/ballistic/shotgun/automatic/combat,
|
||||
/obj/item/storage/belt/bandolier,
|
||||
/obj/item/storage/belt/bandolier,
|
||||
/obj/item/storage/belt/bandolier)
|
||||
/obj/item/storage/belt/bandolier,
|
||||
/obj/item/storage/box/lethalshot,
|
||||
/obj/item/storage/box/lethalslugs)
|
||||
crate_name = "combat shotguns crate"
|
||||
|
||||
/datum/supply_pack/security/armory/dragnetgun
|
||||
@@ -567,7 +569,7 @@
|
||||
|
||||
/datum/supply_pack/security/armory/fire
|
||||
name = "Incendiary Weapons Crate"
|
||||
desc = "Burn, baby burn. Contains three incendiary grenades, three plasma canisters, and a flamethrower. Requires Brige access to open."
|
||||
desc = "Burn, baby burn. Contains three incendiary grenades, seven incendiary slugs, three plasma canisters, and a flamethrower. Requires Brige access to open."
|
||||
cost = 1500
|
||||
access = ACCESS_HEADS
|
||||
contains = list(/obj/item/flamethrower/full,
|
||||
@@ -576,7 +578,8 @@
|
||||
/obj/item/tank/internals/plasma,
|
||||
/obj/item/grenade/chem_grenade/incendiary,
|
||||
/obj/item/grenade/chem_grenade/incendiary,
|
||||
/obj/item/grenade/chem_grenade/incendiary)
|
||||
/obj/item/grenade/chem_grenade/incendiary,
|
||||
/obj/item/storage/box/fireshot)
|
||||
crate_name = "incendiary weapons crate"
|
||||
crate_type = /obj/structure/closet/crate/secure/plasma
|
||||
dangerous = TRUE
|
||||
@@ -629,11 +632,13 @@
|
||||
|
||||
/datum/supply_pack/security/armory/riotshotguns
|
||||
name = "Riot Shotgun Crate"
|
||||
desc = "For when the greytide gets really uppity. Contains three riot Shotguns. Requires Armory access to open."
|
||||
desc = "For when the greytide gets really uppity. Contains three riot shotguns, seven rubber shot and beanbag shells. Requires Armory access to open."
|
||||
cost = 6000
|
||||
contains = list(/obj/item/gun/ballistic/shotgun/riot,
|
||||
/obj/item/gun/ballistic/shotgun/riot,
|
||||
/obj/item/gun/ballistic/shotgun/riot)
|
||||
/obj/item/gun/ballistic/shotgun/riot,
|
||||
/obj/item/storage/box/rubbershot,
|
||||
/obj/item/storage/box/beanbag)
|
||||
crate_name = "riot shotgun crate"
|
||||
|
||||
/datum/supply_pack/security/armory/swat
|
||||
@@ -1540,6 +1545,15 @@
|
||||
crate_type = /obj/structure/closet/crate/secure/science
|
||||
dangerous = TRUE
|
||||
|
||||
/datum/supply_pack/science/tech_slugs
|
||||
name = "Tech Slug Ammo Shells"
|
||||
desc = "A new type of shell that is able to be made into a few different dangerous types. Contains two boxes of tech slugs, 14 shells in all."
|
||||
cost = 1000
|
||||
contains = list(/obj/item/storage/box/techsslug,
|
||||
/obj/item/storage/box/techsslug)
|
||||
crate_name = "tech slug crate"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////// Service //////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -2236,8 +2236,11 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
character.hair_style = hair_style
|
||||
character.facial_hair_style = facial_hair_style
|
||||
character.underwear = underwear
|
||||
character.saved_underwear = underwear
|
||||
character.undershirt = undershirt
|
||||
character.saved_undershirt = undershirt
|
||||
character.socks = socks
|
||||
character.saved_socks = socks
|
||||
|
||||
character.backbag = backbag
|
||||
|
||||
|
||||
@@ -216,6 +216,34 @@ BLIND // can't see anything
|
||||
|
||||
..()
|
||||
|
||||
/obj/item/clothing/under/CtrlClick(mob/user)
|
||||
. = ..()
|
||||
|
||||
if (!(item_flags & IN_INVENTORY))
|
||||
return
|
||||
|
||||
if(!isliving(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
|
||||
return
|
||||
|
||||
if(has_sensor == LOCKED_SENSORS)
|
||||
to_chat(user, "The controls are locked.")
|
||||
return
|
||||
if(has_sensor == BROKEN_SENSORS)
|
||||
to_chat(user, "The sensors have shorted out!")
|
||||
return
|
||||
if(has_sensor <= NO_SENSORS)
|
||||
to_chat(user, "This suit does not have any sensors.")
|
||||
return
|
||||
|
||||
sensor_mode = SENSOR_COORDS
|
||||
|
||||
to_chat(user, "<span class='notice'>Your suit will now report your exact vital lifesigns as well as your coordinate position.</span>")
|
||||
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(H.w_uniform == src)
|
||||
H.update_suit_sensors()
|
||||
|
||||
/obj/item/clothing/under/AltClick(mob/user)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
@@ -124,6 +124,9 @@
|
||||
icon_state = "suitjacket_black"
|
||||
item_state = "ro_suit"
|
||||
|
||||
/obj/item/clothing/suit/toggle/lawyer/black/syndie
|
||||
desc = "A snappy dress jacket. Suspiciously has no tags or branding."
|
||||
armor = list("melee" = 10, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 10, "bio" = 10, "rad" = 10, "fire" = 40, "acid" = 40)
|
||||
|
||||
//Mime
|
||||
/obj/item/clothing/suit/suspenders
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,7 +21,7 @@
|
||||
CAT_BURGER,
|
||||
CAT_CAKE,
|
||||
CAT_EGG,
|
||||
CAT_SUSHI, //Called Fish
|
||||
CAT_FISH,
|
||||
CAT_ICE, //Called Frozen
|
||||
CAT_MEAT,
|
||||
CAT_MISCFOOD,
|
||||
|
||||
@@ -371,28 +371,6 @@
|
||||
parts = list(/obj/item/camera = 1)
|
||||
category = CAT_MISC
|
||||
|
||||
/datum/crafting_recipe/lizardhat
|
||||
name = "Lizard Cloche Hat"
|
||||
result = /obj/item/clothing/head/lizard
|
||||
time = 10
|
||||
reqs = list(/obj/item/organ/tail/lizard = 1)
|
||||
category = CAT_MISC
|
||||
|
||||
/datum/crafting_recipe/lizardhat_alternate
|
||||
name = "Lizard Cloche Hat"
|
||||
result = /obj/item/clothing/head/lizard
|
||||
time = 10
|
||||
reqs = list(/obj/item/stack/sheet/animalhide/lizard = 1)
|
||||
category = CAT_MISC
|
||||
|
||||
/datum/crafting_recipe/kittyears
|
||||
name = "Kitty Ears"
|
||||
result = /obj/item/clothing/head/kitty/genuine
|
||||
time = 10
|
||||
reqs = list(/obj/item/organ/tail/cat = 1,
|
||||
/obj/item/organ/ears/cat = 1)
|
||||
category = CAT_MISC
|
||||
|
||||
/datum/crafting_recipe/skateboard
|
||||
name = "Skateboard"
|
||||
result = /obj/vehicle/ridden/scooter/skateboard
|
||||
@@ -653,6 +631,15 @@
|
||||
/obj/item/assembly/igniter = 1)
|
||||
category = CAT_MISC
|
||||
|
||||
|
||||
/datum/crafting_recipe/wheelchair
|
||||
name = "Wheelchair"
|
||||
result = /obj/vehicle/ridden/wheelchair
|
||||
reqs = list(/obj/item/stack/sheet/plasteel = 2,
|
||||
/obj/item/stack/rods = 8)
|
||||
time = 100
|
||||
category = CAT_MISC
|
||||
|
||||
/datum/crafting_recipe/rcl
|
||||
name = "Makeshift Rapid Cable Layer"
|
||||
result = /obj/item/twohanded/rcl/ghetto
|
||||
@@ -684,6 +671,28 @@
|
||||
tools = list(TOOL_SCREWDRIVER, TOOL_WRENCH, TOOL_WELDER)
|
||||
category = CAT_MISC
|
||||
|
||||
/datum/crafting_recipe/lizardhat
|
||||
name = "Lizard Cloche Hat"
|
||||
result = /obj/item/clothing/head/lizard
|
||||
time = 10
|
||||
reqs = list(/obj/item/organ/tail/lizard = 1)
|
||||
category = CAT_CLOTHING
|
||||
|
||||
/datum/crafting_recipe/lizardhat_alternate
|
||||
name = "Lizard Cloche Hat"
|
||||
result = /obj/item/clothing/head/lizard
|
||||
time = 10
|
||||
reqs = list(/obj/item/stack/sheet/animalhide/lizard = 1)
|
||||
category = CAT_CLOTHING
|
||||
|
||||
/datum/crafting_recipe/kittyears
|
||||
name = "Kitty Ears"
|
||||
result = /obj/item/clothing/head/kitty/genuine
|
||||
time = 10
|
||||
reqs = list(/obj/item/organ/tail/cat = 1,
|
||||
/obj/item/organ/ears/cat = 1)
|
||||
category = CAT_CLOTHING
|
||||
|
||||
/datum/crafting_recipe/hudsunsec
|
||||
name = "Security HUDsunglasses"
|
||||
result = /obj/item/clothing/glasses/hud/security/sunglasses
|
||||
@@ -793,3 +802,36 @@
|
||||
/datum/reagent/water = 15)
|
||||
time = 40
|
||||
category = CAT_MISC
|
||||
|
||||
/datum/crafting_recipe/smartdart
|
||||
name = "Medical smartdart"
|
||||
result = /obj/item/reagent_containers/syringe/dart
|
||||
reqs = list(/obj/item/stack/sheet/metal = 1,
|
||||
/obj/item/stack/sheet/glass = 1,
|
||||
/obj/item/stack/sheet/plastic = 1)
|
||||
time = 10
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_AMMO
|
||||
|
||||
/datum/crafting_recipe/medolier
|
||||
name = "Medolier"
|
||||
result = /obj/item/storage/belt/medolier
|
||||
reqs = list(/obj/item/stack/sheet/metal = 2,
|
||||
/obj/item/stack/sheet/cloth = 3,
|
||||
/obj/item/stack/sheet/plastic = 4)
|
||||
time = 30
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_AMMO
|
||||
|
||||
/datum/crafting_recipe/smartdartgun
|
||||
name = "Smart dartgun"
|
||||
result = /obj/item/gun/syringe/dart
|
||||
reqs = list(/obj/item/stack/sheet/metal = 15,
|
||||
/obj/item/stack/sheet/glass = 10,
|
||||
/obj/item/tank/internals = 1,
|
||||
/obj/item/reagent_containers/glass/beaker = 1,
|
||||
/obj/item/stack/sheet/plastic = 10,
|
||||
/obj/item/stack/cable_coil = 2)
|
||||
time = 150 //It's a gun
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
var/max_n_of_items = 1500
|
||||
var/allow_ai_retrieve = FALSE
|
||||
var/list/initial_contents
|
||||
var/visible_contents = TRUE
|
||||
|
||||
/obj/machinery/smartfridge/Initialize()
|
||||
. = ..()
|
||||
@@ -37,11 +38,21 @@
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/smartfridge/update_icon()
|
||||
var/startstate = initial(icon_state)
|
||||
if(!stat)
|
||||
icon_state = startstate
|
||||
if(visible_contents)
|
||||
switch(contents.len)
|
||||
if(0)
|
||||
icon_state = "[initial(icon_state)]"
|
||||
if(1 to 25)
|
||||
icon_state = "[initial(icon_state)]1"
|
||||
if(26 to 75)
|
||||
icon_state = "[initial(icon_state)]2"
|
||||
if(76 to INFINITY)
|
||||
icon_state = "[initial(icon_state)]3"
|
||||
else
|
||||
icon_state = "[initial(icon_state)]"
|
||||
else
|
||||
icon_state = "[startstate]-off"
|
||||
icon_state = "[initial(icon_state)]-off"
|
||||
|
||||
|
||||
|
||||
@@ -50,7 +61,14 @@
|
||||
********************/
|
||||
|
||||
/obj/machinery/smartfridge/attackby(obj/item/O, mob/user, params)
|
||||
if(default_deconstruction_screwdriver(user, "smartfridge_open", "smartfridge", O))
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
return ..()
|
||||
|
||||
if(default_deconstruction_screwdriver(user, icon_state, icon_state, O))
|
||||
cut_overlays()
|
||||
if(panel_open)
|
||||
add_overlay("[initial(icon_state)]-panel")
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
if(default_pry_open(O))
|
||||
@@ -64,49 +82,46 @@
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
if(!stat)
|
||||
|
||||
if(contents.len >= max_n_of_items)
|
||||
to_chat(user, "<span class='warning'>\The [src] is full!</span>")
|
||||
return FALSE
|
||||
|
||||
if(accept_check(O))
|
||||
load(O)
|
||||
user.visible_message("[user] has added \the [O] to \the [src].", "<span class='notice'>You add \the [O] to \the [src].</span>")
|
||||
updateUsrDialog()
|
||||
return TRUE
|
||||
|
||||
if(istype(O, /obj/item/storage/bag))
|
||||
var/obj/item/storage/P = O
|
||||
var/loaded = 0
|
||||
for(var/obj/G in P.contents)
|
||||
if(contents.len >= max_n_of_items)
|
||||
break
|
||||
if(accept_check(G))
|
||||
load(G)
|
||||
loaded++
|
||||
updateUsrDialog()
|
||||
|
||||
if(loaded)
|
||||
if(contents.len >= max_n_of_items)
|
||||
user.visible_message("[user] loads \the [src] with \the [O].", \
|
||||
"<span class='notice'>You fill \the [src] with \the [O].</span>")
|
||||
else
|
||||
user.visible_message("[user] loads \the [src] with \the [O].", \
|
||||
"<span class='notice'>You load \the [src] with \the [O].</span>")
|
||||
if(O.contents.len > 0)
|
||||
to_chat(user, "<span class='warning'>Some items are refused.</span>")
|
||||
return TRUE
|
||||
else
|
||||
to_chat(user, "<span class='warning'>There is nothing in [O] to put in [src]!</span>")
|
||||
return FALSE
|
||||
|
||||
if(user.a_intent != INTENT_HARM)
|
||||
to_chat(user, "<span class='warning'>\The [src] smartly refuses [O].</span>")
|
||||
if(stat)
|
||||
updateUsrDialog()
|
||||
return FALSE
|
||||
else
|
||||
return ..()
|
||||
|
||||
if(contents.len >= max_n_of_items)
|
||||
to_chat(user, "<span class='warning'>\The [src] is full!</span>")
|
||||
return FALSE
|
||||
|
||||
if(accept_check(O))
|
||||
load(O)
|
||||
user.visible_message("[user] has added \the [O] to \the [src].", "<span class='notice'>You add \the [O] to \the [src].</span>")
|
||||
updateUsrDialog()
|
||||
if (visible_contents)
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
if(istype(O, /obj/item/storage/bag))
|
||||
var/obj/item/storage/P = O
|
||||
var/loaded = 0
|
||||
for(var/obj/G in P.contents)
|
||||
if(contents.len >= max_n_of_items)
|
||||
break
|
||||
if(accept_check(G))
|
||||
load(G)
|
||||
loaded++
|
||||
updateUsrDialog()
|
||||
|
||||
if(loaded)
|
||||
user.visible_message("[user] loads \the [src] with \the [O].", \
|
||||
"<span class='notice'>You [contents.len >= max_n_of_items ? "fill" : "load"] \the [src] with \the [O].</span>")
|
||||
if(O.contents.len > 0)
|
||||
to_chat(user, "<span class='warning'>Some items are refused.</span>")
|
||||
return TRUE
|
||||
else
|
||||
to_chat(user, "<span class='warning'>There is nothing in [O] to put in [src]!</span>")
|
||||
return FALSE
|
||||
|
||||
to_chat(user, "<span class='warning'>\The [src] smartly refuses [O].</span>")
|
||||
updateUsrDialog()
|
||||
return FALSE
|
||||
|
||||
|
||||
|
||||
@@ -186,6 +201,8 @@
|
||||
O.forceMove(drop_location())
|
||||
adjust_item_drop_location(O)
|
||||
break
|
||||
if (visible_contents)
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
for(var/obj/item/O in src)
|
||||
@@ -195,6 +212,8 @@
|
||||
O.forceMove(drop_location())
|
||||
adjust_item_drop_location(O)
|
||||
desired--
|
||||
if (visible_contents)
|
||||
update_icon()
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
@@ -210,6 +229,7 @@
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 5
|
||||
active_power_usage = 200
|
||||
visible_contents = FALSE
|
||||
var/drying = FALSE
|
||||
|
||||
/obj/machinery/smartfridge/drying_rack/Initialize()
|
||||
@@ -414,6 +434,7 @@
|
||||
name = "disk compartmentalizer"
|
||||
desc = "A machine capable of storing a variety of disks. Denoted by most as the DSU (disk storage unit)."
|
||||
icon_state = "disktoaster"
|
||||
visible_contents = FALSE
|
||||
pass_flags = PASSTABLE
|
||||
|
||||
/obj/machinery/smartfridge/disks/accept_check(obj/item/O)
|
||||
|
||||
@@ -38,37 +38,6 @@
|
||||
|
||||
// see code/module/crafting/table.dm
|
||||
|
||||
////////////////////////////////////////////////FISH////////////////////////////////////////////////
|
||||
|
||||
/datum/crafting_recipe/food/cubancarp
|
||||
name = "Cuban carp"
|
||||
reqs = list(
|
||||
/datum/reagent/consumable/flour = 5,
|
||||
/obj/item/reagent_containers/food/snacks/grown/chili = 1,
|
||||
/obj/item/reagent_containers/food/snacks/carpmeat = 1
|
||||
)
|
||||
result = /obj/item/reagent_containers/food/snacks/cubancarp
|
||||
subcategory = CAT_MEAT
|
||||
|
||||
/datum/crafting_recipe/food/fishandchips
|
||||
name = "Fish and chips"
|
||||
reqs = list(
|
||||
/obj/item/reagent_containers/food/snacks/fries = 1,
|
||||
/obj/item/reagent_containers/food/snacks/carpmeat = 1
|
||||
)
|
||||
result = /obj/item/reagent_containers/food/snacks/fishandchips
|
||||
subcategory = CAT_MEAT
|
||||
|
||||
/datum/crafting_recipe/food/fishfingers
|
||||
name = "Fish fingers"
|
||||
reqs = list(
|
||||
/datum/reagent/consumable/flour = 5,
|
||||
/obj/item/reagent_containers/food/snacks/bun = 1,
|
||||
/obj/item/reagent_containers/food/snacks/carpmeat = 1
|
||||
)
|
||||
result = /obj/item/reagent_containers/food/snacks/fishfingers
|
||||
subcategory = CAT_MEAT
|
||||
|
||||
////////////////////////////////////////////////MR SPIDER////////////////////////////////////////////////
|
||||
|
||||
/datum/crafting_recipe/food/spidereggsham
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
)
|
||||
result = /obj/item/reagent_containers/food/snacks/donut
|
||||
subcategory = CAT_PASTRY
|
||||
|
||||
|
||||
/datum/crafting_recipe/food/donut
|
||||
time = 15
|
||||
name = "Semen donut"
|
||||
@@ -104,7 +104,7 @@ datum/crafting_recipe/food/donut/meat
|
||||
/datum/crafting_recipe/food/rofflewaffles
|
||||
name = "Roffle waffles"
|
||||
reqs = list(
|
||||
/datum/reagent/mushroomhallucinogen = 5,
|
||||
/datum/reagent/drug/mushroomhallucinogen = 5,
|
||||
/obj/item/reagent_containers/food/snacks/pastrybase = 2
|
||||
)
|
||||
result = /obj/item/reagent_containers/food/snacks/rofflewaffles
|
||||
@@ -205,16 +205,6 @@ datum/crafting_recipe/food/donut/meat
|
||||
|
||||
////////////////////////////////////////////OTHER////////////////////////////////////////////
|
||||
|
||||
/datum/crafting_recipe/food/hotdog
|
||||
name = "Hot dog"
|
||||
reqs = list(
|
||||
/datum/reagent/consumable/ketchup = 5,
|
||||
/obj/item/reagent_containers/food/snacks/bun = 1,
|
||||
/obj/item/reagent_containers/food/snacks/sausage = 1
|
||||
)
|
||||
result = /obj/item/reagent_containers/food/snacks/hotdog
|
||||
subcategory = CAT_PASTRY
|
||||
|
||||
/datum/crafting_recipe/food/meatbun
|
||||
name = "Meat bun"
|
||||
reqs = list(
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
result = /obj/item/reagent_containers/food/snacks/notasandwich
|
||||
subcategory = CAT_SANDWICH
|
||||
|
||||
/datum/crafting_recipe/food/notasandwich
|
||||
/datum/crafting_recipe/food/tunasandwich
|
||||
name = "Tuna sandwich"
|
||||
reqs = list(
|
||||
/obj/item/reagent_containers/food/snacks/breadslice/plain = 2,
|
||||
@@ -62,3 +62,13 @@
|
||||
)
|
||||
result = /obj/item/reagent_containers/food/snacks/tuna_sandwich
|
||||
subcategory = CAT_SANDWICH
|
||||
|
||||
/datum/crafting_recipe/food/hotdog
|
||||
name = "Hot dog"
|
||||
reqs = list(
|
||||
/datum/reagent/consumable/ketchup = 5,
|
||||
/obj/item/reagent_containers/food/snacks/bun = 1,
|
||||
/obj/item/reagent_containers/food/snacks/sausage = 1
|
||||
)
|
||||
result = /obj/item/reagent_containers/food/snacks/hotdog
|
||||
subcategory = CAT_SANDWICH
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
/datum/reagent/consumable/rice = 10
|
||||
)
|
||||
result = /obj/item/reagent_containers/food/snacks/sushi_rice
|
||||
subcategory = CAT_SUSHI
|
||||
subcategory = CAT_FISH
|
||||
|
||||
/datum/crafting_recipe/food/sea_weed
|
||||
name = "Sea Weed Sheet"
|
||||
@@ -17,7 +17,7 @@
|
||||
/obj/item/reagent_containers/food/snacks/grown/kudzupod = 1,
|
||||
)
|
||||
result = /obj/item/reagent_containers/food/snacks/sea_weed
|
||||
subcategory = CAT_SUSHI
|
||||
subcategory = CAT_FISH
|
||||
|
||||
/datum/crafting_recipe/food/tuna_can
|
||||
name = "Can of Tuna"
|
||||
@@ -27,7 +27,7 @@
|
||||
/obj/item/reagent_containers/food/snacks/carpmeat = 1,
|
||||
)
|
||||
result = /obj/item/reagent_containers/food/snacks/tuna
|
||||
subcategory = CAT_SUSHI
|
||||
subcategory = CAT_FISH
|
||||
|
||||
//////////////////////////Sushi/////////////////////////////////
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
/obj/item/reagent_containers/food/snacks/carpmeat = 1
|
||||
)
|
||||
result = /obj/item/reagent_containers/food/snacks/sashimi
|
||||
subcategory = CAT_SUSHI
|
||||
subcategory = CAT_FISH
|
||||
|
||||
/datum/crafting_recipe/food/riceball
|
||||
name = "Onigiri"
|
||||
@@ -49,7 +49,7 @@
|
||||
/obj/item/reagent_containers/food/snacks/sushi_rice = 1
|
||||
)
|
||||
result = /obj/item/reagent_containers/food/snacks/riceball
|
||||
subcategory = CAT_SUSHI
|
||||
subcategory = CAT_FISH
|
||||
|
||||
/datum/crafting_recipe/food/sushie_egg
|
||||
name = "Tobiko"
|
||||
@@ -59,7 +59,7 @@
|
||||
/obj/item/reagent_containers/food/snacks/sea_weed = 2,
|
||||
)
|
||||
result = /obj/item/reagent_containers/food/snacks/tobiko
|
||||
subcategory = CAT_SUSHI
|
||||
subcategory = CAT_FISH
|
||||
|
||||
/datum/crafting_recipe/food/sushie_basic
|
||||
name = "Funa Hosomaki"
|
||||
@@ -70,7 +70,7 @@
|
||||
/obj/item/reagent_containers/food/snacks/sea_weed = 3,
|
||||
)
|
||||
result = /obj/item/reagent_containers/food/snacks/sushie_basic
|
||||
subcategory = CAT_SUSHI
|
||||
subcategory = CAT_FISH
|
||||
|
||||
/datum/crafting_recipe/food/sushie_adv
|
||||
name = "Funa Nigiri"
|
||||
@@ -80,7 +80,7 @@
|
||||
/obj/item/reagent_containers/food/snacks/carpmeat = 1
|
||||
)
|
||||
result = /obj/item/reagent_containers/food/snacks/sushie_adv
|
||||
subcategory = CAT_SUSHI
|
||||
subcategory = CAT_FISH
|
||||
|
||||
/datum/crafting_recipe/food/sushie_pro
|
||||
name = "Well made Funa Nigiri"
|
||||
@@ -91,4 +91,35 @@
|
||||
/obj/item/reagent_containers/food/snacks/sea_weed = 1
|
||||
)
|
||||
result = /obj/item/reagent_containers/food/snacks/sushie_pro
|
||||
subcategory = CAT_SUSHI
|
||||
subcategory = CAT_FISH
|
||||
|
||||
///////////////Gaijin junk/////////////////////////////////////
|
||||
|
||||
/datum/crafting_recipe/food/fishfingers
|
||||
name = "Fish fingers"
|
||||
reqs = list(
|
||||
/datum/reagent/consumable/flour = 5,
|
||||
/obj/item/reagent_containers/food/snacks/bun = 1,
|
||||
/obj/item/reagent_containers/food/snacks/carpmeat = 1
|
||||
)
|
||||
result = /obj/item/reagent_containers/food/snacks/fishfingers
|
||||
subcategory = CAT_FISH
|
||||
|
||||
/datum/crafting_recipe/food/cubancarp
|
||||
name = "Cuban carp"
|
||||
reqs = list(
|
||||
/datum/reagent/consumable/flour = 5,
|
||||
/obj/item/reagent_containers/food/snacks/grown/chili = 1,
|
||||
/obj/item/reagent_containers/food/snacks/carpmeat = 1
|
||||
)
|
||||
result = /obj/item/reagent_containers/food/snacks/cubancarp
|
||||
subcategory = CAT_FISH
|
||||
|
||||
/datum/crafting_recipe/food/fishandchips
|
||||
name = "Fish and chips"
|
||||
reqs = list(
|
||||
/obj/item/reagent_containers/food/snacks/fries = 1,
|
||||
/obj/item/reagent_containers/food/snacks/carpmeat = 1
|
||||
)
|
||||
result = /obj/item/reagent_containers/food/snacks/fishandchips
|
||||
subcategory = CAT_FISH
|
||||
@@ -471,15 +471,6 @@ function ehjaxCallback(data) {
|
||||
handleClientData(data.clientData.ckey, data.clientData.ip, data.clientData.compid);
|
||||
}
|
||||
sendVolumeUpdate();
|
||||
} else if (data.firebug) {
|
||||
if (data.trigger) {
|
||||
internalOutput('<span class="internal boldnshit">Loading firebug console, triggered by '+data.trigger+'...</span>', 'internal');
|
||||
} else {
|
||||
internalOutput('<span class="internal boldnshit">Loading firebug console...</span>', 'internal');
|
||||
}
|
||||
var firebugEl = document.createElement('script');
|
||||
firebugEl.src = 'https://getfirebug.com/firebug-lite-debug.js';
|
||||
document.body.appendChild(firebugEl);
|
||||
} else if (data.adminMusic) {
|
||||
if (typeof data.adminMusic === 'string') {
|
||||
var adminMusic = byondDecode(data.adminMusic);
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
var/list/obj/machinery/atmospherics/atmos_machines = list()
|
||||
var/list/obj/structure/cable/cables = list()
|
||||
var/list/atom/atoms = list()
|
||||
var/list/area/areas = list()
|
||||
|
||||
var/list/turfs = block( locate(bounds[MAP_MINX], bounds[MAP_MINY], bounds[MAP_MINZ]),
|
||||
locate(bounds[MAP_MAXX], bounds[MAP_MAXY], bounds[MAP_MAXZ]))
|
||||
@@ -37,6 +38,7 @@
|
||||
for(var/L in turfs)
|
||||
var/turf/B = L
|
||||
atoms += B
|
||||
areas |= B.loc
|
||||
for(var/A in B)
|
||||
atoms += A
|
||||
if(istype(A, /obj/structure/cable))
|
||||
@@ -48,6 +50,7 @@
|
||||
var/turf/T = L
|
||||
T.air_update_turf(TRUE) //calculate adjacent turfs along the border to prevent runtimes
|
||||
|
||||
SSmapping.reg_in_areas_in_z(areas)
|
||||
SSatoms.InitializeAtoms(atoms)
|
||||
SSmachines.setup_template_powernets(cables)
|
||||
SSair.setup_template_machinery(atmos_machines)
|
||||
|
||||
@@ -273,23 +273,12 @@
|
||||
to_chat(user, "<span class='notice'>You release the wisp. It begins to bob around your head.</span>")
|
||||
icon_state = "lantern"
|
||||
wisp.orbit(user, 20)
|
||||
user.update_sight()
|
||||
SSblackbox.record_feedback("tally", "wisp_lantern", 1, "Freed")
|
||||
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You return the wisp to the lantern.</span>")
|
||||
|
||||
var/mob/target
|
||||
if(wisp.orbiting)
|
||||
target = wisp.orbiting.orbiting
|
||||
wisp.stop_orbit()
|
||||
wisp.forceMove(src)
|
||||
|
||||
if (istype(target))
|
||||
target.update_sight()
|
||||
to_chat(target, "<span class='notice'>Your vision returns to normal.</span>")
|
||||
|
||||
icon_state = "lantern-blue"
|
||||
wisp.forceMove(src)
|
||||
SSblackbox.record_feedback("tally", "wisp_lantern", 1, "Returned")
|
||||
|
||||
/obj/item/wisp_lantern/Initialize()
|
||||
@@ -302,7 +291,7 @@
|
||||
qdel(wisp)
|
||||
else
|
||||
wisp.visible_message("<span class='notice'>[wisp] has a sad feeling for a moment, then it passes.</span>")
|
||||
..()
|
||||
return ..()
|
||||
|
||||
/obj/effect/wisp
|
||||
name = "friendly wisp"
|
||||
@@ -314,6 +303,25 @@
|
||||
var/sight_flags = SEE_MOBS
|
||||
var/lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
|
||||
|
||||
/obj/effect/wisp/orbit(atom/thing, radius, clockwise, rotation_speed, rotation_segments, pre_rotation, lockinorbit)
|
||||
. = ..()
|
||||
if(ismob(thing))
|
||||
RegisterSignal(thing, COMSIG_MOB_UPDATE_SIGHT, .proc/update_user_sight)
|
||||
var/mob/being = thing
|
||||
being.update_sight()
|
||||
to_chat(thing, "<span class='notice'>The wisp enhances your vision.</span>")
|
||||
|
||||
/obj/effect/wisp/stop_orbit(datum/component/orbiter/orbits)
|
||||
. = ..()
|
||||
if(ismob(orbits.parent))
|
||||
UnregisterSignal(orbits.parent, COMSIG_MOB_UPDATE_SIGHT)
|
||||
to_chat(orbits.parent, "<span class='notice'>Your vision returns to normal.</span>")
|
||||
|
||||
/obj/effect/wisp/proc/update_user_sight(mob/user)
|
||||
user.sight |= sight_flags
|
||||
if(!isnull(lighting_alpha))
|
||||
user.lighting_alpha = min(user.lighting_alpha, lighting_alpha)
|
||||
|
||||
//Red/Blue Cubes
|
||||
/obj/item/warp_cube
|
||||
name = "blue cube"
|
||||
@@ -781,19 +789,17 @@
|
||||
var/turf/T = get_turf(src)
|
||||
var/list/contents = T.GetAllContents()
|
||||
var/mob/dead/observer/current_spirits = list()
|
||||
var/list/orbiters = list()
|
||||
for(var/thing in contents)
|
||||
var/atom/A = thing
|
||||
if (A.orbiters)
|
||||
orbiters += A.orbiters
|
||||
A.transfer_observers_to(src)
|
||||
|
||||
for(var/thing in orbiters)
|
||||
var/datum/orbit/O = thing
|
||||
if (isobserver(O.orbiter))
|
||||
var/mob/dead/observer/G = O.orbiter
|
||||
ghost_counter++
|
||||
G.invisibility = 0
|
||||
current_spirits |= G
|
||||
for(var/i in orbiters?.orbiters)
|
||||
if(!isobserver(i))
|
||||
continue
|
||||
var/mob/dead/observer/G = i
|
||||
ghost_counter++
|
||||
G.invisibility = 0
|
||||
current_spirits |= G
|
||||
|
||||
for(var/mob/dead/observer/G in spirits - current_spirits)
|
||||
G.invisibility = GLOB.observer_default_invisibility
|
||||
|
||||
@@ -26,7 +26,9 @@
|
||||
return
|
||||
|
||||
/mob/camera/forceMove(atom/destination)
|
||||
var/oldloc = loc
|
||||
loc = destination
|
||||
Moved(oldloc, NONE, TRUE)
|
||||
|
||||
/mob/camera/emote(act, m_type=1, message = null, intentional = FALSE)
|
||||
return
|
||||
|
||||
@@ -34,7 +34,9 @@ INITIALIZE_IMMEDIATE(/mob/dead)
|
||||
var/turf/new_turf = get_turf(destination)
|
||||
if (old_turf?.z != new_turf?.z)
|
||||
onTransitZ(old_turf?.z, new_turf?.z)
|
||||
var/oldloc = loc
|
||||
loc = destination
|
||||
Moved(oldloc, NONE, TRUE)
|
||||
|
||||
/mob/dead/Stat()
|
||||
..()
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
|
||||
// please make sure they're sorted alphabetically and categorized
|
||||
|
||||
/datum/sprite_accessory/socks/bee_knee
|
||||
name = "Knee-high (Bee)"
|
||||
icon_state = "bee_knee"
|
||||
|
||||
/datum/sprite_accessory/socks/black_knee
|
||||
name = "Knee-high (Black)"
|
||||
icon_state = "black_knee"
|
||||
@@ -63,6 +67,10 @@
|
||||
name = "Short (White)"
|
||||
icon_state = "white_short"
|
||||
|
||||
/datum/sprite_accessory/socks/bee_thigh
|
||||
name = "Thigh-high (Bee)"
|
||||
icon_state = "bee_thigh"
|
||||
|
||||
/datum/sprite_accessory/socks/black_thigh
|
||||
name = "Thigh-high (Black)"
|
||||
icon_state = "black_thigh"
|
||||
@@ -93,4 +101,4 @@
|
||||
|
||||
/datum/sprite_accessory/socks/white_thigh
|
||||
name = "Thigh-high (White)"
|
||||
icon_state = "white_thigh"
|
||||
icon_state = "white_thigh"
|
||||
|
||||
@@ -248,9 +248,13 @@
|
||||
icon_state = "bra_commie"
|
||||
|
||||
/datum/sprite_accessory/undershirt/female_babyblue
|
||||
name = "Bra, Baby Blue"
|
||||
name = "Bra - Baby Blue"
|
||||
icon_state = "bra_babyblue"
|
||||
|
||||
/datum/sprite_accessory/undershirt/female_beekini
|
||||
name = "Bra - Bee-kini"
|
||||
icon_state = "bra_bee-kini"
|
||||
|
||||
/datum/sprite_accessory/undershirt/female_black
|
||||
name = "Bra - Black"
|
||||
icon_state = "bra_black"
|
||||
|
||||
@@ -90,6 +90,9 @@
|
||||
name = "Boxer Briefs - Yellow"
|
||||
icon_state = "boxer_briefs_yellow"
|
||||
|
||||
/datum/sprite_accessory/underwear/female_beekini
|
||||
name = "Panties - Bee-kini"
|
||||
icon_state = "panties_bee-kini"
|
||||
|
||||
/datum/sprite_accessory/underwear/female_black
|
||||
name = "Panties - Black"
|
||||
|
||||
@@ -429,9 +429,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
var/orbitsize = (I.Width()+I.Height())*0.5
|
||||
orbitsize -= (orbitsize/world.icon_size)*(world.icon_size*0.25)
|
||||
|
||||
if(orbiting && orbiting.orbiting != target)
|
||||
to_chat(src, "<span class='notice'>Now orbiting [target].</span>")
|
||||
|
||||
var/rot_seg
|
||||
|
||||
switch(ghost_orbit)
|
||||
@@ -450,10 +447,10 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
|
||||
/mob/dead/observer/orbit()
|
||||
setDir(2)//reset dir so the right directional sprites show up
|
||||
..()
|
||||
return ..()
|
||||
|
||||
/mob/dead/observer/stop_orbit()
|
||||
..()
|
||||
/mob/dead/observer/stop_orbit(datum/component/orbiter/orbits)
|
||||
. = ..()
|
||||
//restart our floating animation after orbit is done.
|
||||
pixel_y = 0
|
||||
animate(src, pixel_y = 2, time = 10, loop = -1)
|
||||
@@ -753,7 +750,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
|
||||
update_icon()
|
||||
|
||||
/mob/dead/observer/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
|
||||
/mob/dead/observer/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
|
||||
return IsAdminGhost(usr)
|
||||
|
||||
/mob/dead/observer/is_literate()
|
||||
|
||||
@@ -895,6 +895,11 @@
|
||||
var/obj/item/organ/I = X
|
||||
I.Insert(src)
|
||||
|
||||
/mob/living/carbon/proc/update_disabled_bodyparts()
|
||||
for(var/B in bodyparts)
|
||||
var/obj/item/bodypart/BP = B
|
||||
BP.update_disabled()
|
||||
|
||||
/mob/living/carbon/vv_get_dropdown()
|
||||
. = ..()
|
||||
. += "---"
|
||||
|
||||
@@ -48,18 +48,27 @@
|
||||
if(affecting && affecting.dismemberable && affecting.get_damage() >= (affecting.max_damage - P.dismemberment))
|
||||
affecting.dismember(P.damtype)
|
||||
|
||||
/mob/living/carbon/proc/can_catch_item(skip_throw_mode_check)
|
||||
. = FALSE
|
||||
if(!skip_throw_mode_check && !in_throw_mode)
|
||||
return
|
||||
if(get_active_held_item())
|
||||
return
|
||||
if(restrained())
|
||||
return
|
||||
return TRUE
|
||||
|
||||
/mob/living/carbon/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked = FALSE)
|
||||
if(!skipcatch) //ugly, but easy
|
||||
if(in_throw_mode && !get_active_held_item()) //empty active hand and we're in throw mode
|
||||
if(canmove && !restrained())
|
||||
if(istype(AM, /obj/item))
|
||||
var/obj/item/I = AM
|
||||
if(isturf(I.loc))
|
||||
I.attack_hand(src)
|
||||
if(get_active_held_item() == I) //if our attack_hand() picks up the item...
|
||||
visible_message("<span class='warning'>[src] catches [I]!</span>") //catch that sucker!
|
||||
throw_mode_off()
|
||||
return 1
|
||||
if(can_catch_item())
|
||||
if(istype(AM, /obj/item))
|
||||
var/obj/item/I = AM
|
||||
if(isturf(I.loc))
|
||||
I.attack_hand(src)
|
||||
if(get_active_held_item() == I) //if our attack_hand() picks up the item...
|
||||
visible_message("<span class='warning'>[src] catches [I]!</span>") //catch that sucker!
|
||||
throw_mode_off()
|
||||
return 1
|
||||
..()
|
||||
|
||||
|
||||
|
||||
@@ -294,7 +294,7 @@
|
||||
if(mood.sanity <= SANITY_DISTURBED)
|
||||
msg += "[t_He] seem[p_s()] distressed.\n"
|
||||
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "empath", /datum/mood_event/sad_empath, src)
|
||||
if(mood.mood >= 5) //So roundstart people aren't all "happy"
|
||||
if(mood.shown_mood >= 6) //So roundstart people aren't all "happy" and that antags don't show their true happiness.
|
||||
msg += "[t_He] seem[p_s()] to have had something nice happen to them recently.\n"
|
||||
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "empathH", /datum/mood_event/happy_empath, src)
|
||||
if (HAS_TRAIT(src, TRAIT_BLIND))
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
/mob/living/carbon/human/Initialize()
|
||||
verbs += /mob/living/proc/mob_sleep
|
||||
verbs += /mob/living/proc/lay_down
|
||||
verbs += /mob/living/carbon/human/proc/underwear_toggle //fwee
|
||||
|
||||
//initialize limbs first
|
||||
create_bodyparts()
|
||||
@@ -724,12 +725,12 @@
|
||||
remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, "#000000")
|
||||
cut_overlay(MA)
|
||||
|
||||
/mob/living/carbon/human/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
|
||||
/mob/living/carbon/human/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
|
||||
if(incapacitated() || lying )
|
||||
to_chat(src, "<span class='warning'>You can't do that right now!</span>")
|
||||
return FALSE
|
||||
if(!Adjacent(M) && (M.loc != src))
|
||||
if((be_close == 0) || (dna.check_mutation(TK) && tkMaxRangeCheck(src, M)))
|
||||
if((be_close == 0) || (!no_tk && (dna.check_mutation(TK) && tkMaxRangeCheck(src, M))))
|
||||
return TRUE
|
||||
to_chat(src, "<span class='warning'>You are too far away!</span>")
|
||||
return FALSE
|
||||
@@ -851,19 +852,24 @@
|
||||
|
||||
/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 && grab_state >= GRAB_AGGRESSIVE && stat == CONSCIOUS)
|
||||
if(user == target && can_piggyback(target) && pulling == target && (HAS_TRAIT(src, TRAIT_PACIFISM) || grab_state >= GRAB_AGGRESSIVE) && stat == CONSCIOUS)
|
||||
buckle_mob(target,TRUE,TRUE)
|
||||
. = ..()
|
||||
|
||||
/mob/living/carbon/human/proc/piggyback_instant(mob/living/M)
|
||||
return buckle_mob(M, TRUE, TRUE, FALSE, TRUE)
|
||||
|
||||
//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/buckle_mob(mob/living/M, force = FALSE, check_loc = TRUE)
|
||||
/mob/living/carbon/human/buckle_mob(mob/living/M, force = FALSE, check_loc = TRUE, bypass_piggybacking = FALSE, no_delay = FALSE)
|
||||
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>")
|
||||
return
|
||||
@@ -876,7 +882,7 @@
|
||||
if(can_piggyback(M))
|
||||
riding_datum.ride_check_ridden_incapacitated = TRUE
|
||||
visible_message("<span class='notice'>[M] starts to climb onto [src]...</span>")
|
||||
if(do_after(M, 15, target = src))
|
||||
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>")
|
||||
|
||||
@@ -490,11 +490,19 @@ GLOBAL_LIST_EMPTY(roundstart_races)
|
||||
//Underwear, Undershirts & Socks
|
||||
if(!(NO_UNDERWEAR in species_traits))
|
||||
if(H.underwear)
|
||||
if(H.hidden_underwear)
|
||||
H.underwear = "Nude"
|
||||
else
|
||||
H.underwear = H.saved_underwear
|
||||
var/datum/sprite_accessory/underwear/underwear = GLOB.underwear_list[H.underwear]
|
||||
if(underwear)
|
||||
standing += mutable_appearance(underwear.icon, underwear.icon_state, -BODY_LAYER)
|
||||
|
||||
if(H.undershirt)
|
||||
if(H.hidden_undershirt)
|
||||
H.undershirt = "Nude"
|
||||
else
|
||||
H.undershirt = H.saved_undershirt
|
||||
var/datum/sprite_accessory/undershirt/undershirt = GLOB.undershirt_list[H.undershirt]
|
||||
if(undershirt)
|
||||
if(H.dna.species.sexes && H.gender == FEMALE)
|
||||
@@ -503,6 +511,10 @@ GLOBAL_LIST_EMPTY(roundstart_races)
|
||||
standing += mutable_appearance(undershirt.icon, undershirt.icon_state, -BODY_LAYER)
|
||||
|
||||
if(H.socks && H.get_num_legs(FALSE) >= 2)
|
||||
if(H.hidden_socks)
|
||||
H.socks = "Nude"
|
||||
else
|
||||
H.socks = H.saved_socks
|
||||
var/datum/sprite_accessory/socks/socks = GLOB.socks_list[H.socks]
|
||||
if(socks)
|
||||
if(DIGITIGRADE in species_traits)
|
||||
@@ -1288,7 +1300,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
|
||||
. += H.physiology.speed_mod
|
||||
|
||||
if (H.m_intent == MOVE_INTENT_WALK && HAS_TRAIT(H, TRAIT_SPEEDY_STEP))
|
||||
. -= 1
|
||||
. -= 1.5
|
||||
|
||||
if(HAS_TRAIT(H, TRAIT_IGNORESLOWDOWN))
|
||||
ignoreslow = 1
|
||||
|
||||
@@ -654,6 +654,7 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
|
||||
L.damage += d
|
||||
|
||||
/mob/living/carbon/proc/liver_failure()
|
||||
reagents.end_metabolization(src, keep_liverless = TRUE) //Stops trait-based effects on reagents, to prevent permanent buffs
|
||||
reagents.metabolize(src, can_overdose=FALSE, liverless = TRUE)
|
||||
if(HAS_TRAIT(src, TRAIT_STABLEHEART))
|
||||
return
|
||||
|
||||
@@ -814,7 +814,7 @@
|
||||
/mob/living/proc/harvest(mob/living/user) //used for extra objects etc. in butchering
|
||||
return
|
||||
|
||||
/mob/living/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
|
||||
/mob/living/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
|
||||
if(incapacitated())
|
||||
to_chat(src, "<span class='warning'>You can't do that right now!</span>")
|
||||
return FALSE
|
||||
@@ -1189,9 +1189,13 @@
|
||||
clamp_unconscious_to = 0,
|
||||
clamp_immobility_to = 0,
|
||||
reset_misc = TRUE,
|
||||
healing_chems = list("inaprovaline" = 3, "synaptizine" = 10, "omnizine" = 10, "stimulants" = 10),
|
||||
message = "<span class='boldnotice'>You feel a surge of energy!</span>"
|
||||
healing_chems = list("inaprovaline" = 3, "synaptizine" = 10, "regen_jelly" = 10, "stimulants" = 10),
|
||||
message = "<span class='boldnotice'>You feel a surge of energy!</span>",
|
||||
stamina_buffer_boost = 0, //restores stamina buffer rather than just health
|
||||
scale_stamina_loss_recovery, //defaults to null. if this is set, restores loss * this stamina. make sure it's a fraction.
|
||||
stamina_loss_recovery_bypass = 0 //amount of stamina loss to ignore during calculation
|
||||
)
|
||||
to_chat(src, message)
|
||||
if(AmountSleeping() > clamp_unconscious_to)
|
||||
SetSleeping(clamp_unconscious_to)
|
||||
if(AmountUnconscious() > clamp_unconscious_to)
|
||||
@@ -1200,7 +1204,10 @@
|
||||
SetStun(clamp_immobility_to)
|
||||
if(AmountKnockdown() > clamp_immobility_to)
|
||||
SetKnockdown(clamp_immobility_to)
|
||||
adjustStaminaLoss(max(0, -stamina_boost))
|
||||
adjustStaminaLoss(min(0, -stamina_boost))
|
||||
adjustStaminaLossBuffered(min(0, -stamina_buffer_boost))
|
||||
if(scale_stamina_loss_recovery)
|
||||
adjustStaminaLoss(min(-((getStaminaLoss() - stamina_loss_recovery_bypass) * scale_stamina_loss_recovery), 0))
|
||||
if(put_on_feet)
|
||||
resting = FALSE
|
||||
lying = FALSE
|
||||
|
||||
@@ -779,7 +779,7 @@
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/ai/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
|
||||
/mob/living/silicon/ai/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
|
||||
if(control_disabled || incapacitated())
|
||||
to_chat(src, "<span class='warning'>You can't do that right now!</span>")
|
||||
return FALSE
|
||||
|
||||
@@ -183,7 +183,7 @@
|
||||
|
||||
// See software.dm for Topic()
|
||||
|
||||
/mob/living/silicon/pai/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
|
||||
/mob/living/silicon/pai/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
|
||||
if(be_close && !in_range(M, src))
|
||||
to_chat(src, "<span class='warning'>You are too far away!</span>")
|
||||
return FALSE
|
||||
|
||||
@@ -910,7 +910,7 @@
|
||||
if(DISCONNECT) //Tampering with the wires
|
||||
to_chat(connected_ai, "<br><br><span class='notice'>NOTICE - Remote telemetry lost with [name].</span><br>")
|
||||
|
||||
/mob/living/silicon/robot/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
|
||||
/mob/living/silicon/robot/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
|
||||
if(stat || lockcharge || low_power_mode)
|
||||
to_chat(src, "<span class='warning'>You can't do that right now!</span>")
|
||||
return FALSE
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/mob/living/simple_animal/pet/redpanda
|
||||
name = "Red panda"
|
||||
desc = "Wah't a dork."
|
||||
icon = 'icons/mob/pets.dmi'
|
||||
icon_state = "red_panda"
|
||||
icon_living = "red_panda"
|
||||
icon_dead = "dead_panda"
|
||||
speak = list("Churip","Chuuriip","Cheep-cheep","Chiteurp","squueeaacipt")
|
||||
speak_emote = list("chirps", "huff-quacks")
|
||||
emote_hear = list("squeak-chrips.", "huff-squacks.")
|
||||
emote_see = list("shakes its head.", "rolls about.")
|
||||
speak_chance = 1
|
||||
turns_per_move = 5
|
||||
see_in_dark = 6
|
||||
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 3)
|
||||
response_help = "pets"
|
||||
response_disarm = "gently pushes aside"
|
||||
response_harm = "kicks"
|
||||
gold_core_spawnable = FRIENDLY_SPAWN
|
||||
do_footstep = TRUE
|
||||
@@ -596,6 +596,9 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
|
||||
/obj/item/guardiancreator/tech/choose/traitor
|
||||
possible_guardians = list("Assassin", "Chaos", "Charger", "Explosive", "Lightning", "Protector", "Ranged", "Standard", "Support")
|
||||
|
||||
/obj/item/guardiancreator/tech/choose/traitor/check_uplink_validity()
|
||||
return !used
|
||||
|
||||
/obj/item/guardiancreator/tech/choose
|
||||
random = FALSE
|
||||
|
||||
|
||||
@@ -392,7 +392,7 @@
|
||||
if(target)
|
||||
return new childspawn(target)
|
||||
|
||||
/mob/living/simple_animal/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
|
||||
/mob/living/simple_animal/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
|
||||
if(incapacitated())
|
||||
to_chat(src, "<span class='warning'>You can't do that right now!</span>")
|
||||
return FALSE
|
||||
|
||||
@@ -784,7 +784,7 @@
|
||||
return 0
|
||||
|
||||
//Can the mob use Topic to interact with machines
|
||||
/mob/proc/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
|
||||
/mob/proc/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
|
||||
return
|
||||
|
||||
/mob/proc/faction_check_mob(mob/target, exact_match)
|
||||
@@ -871,13 +871,7 @@
|
||||
return
|
||||
|
||||
/mob/proc/update_sight()
|
||||
for(var/O in orbiters)
|
||||
var/datum/orbit/orbit = O
|
||||
var/obj/effect/wisp/wisp = orbit.orbiter
|
||||
if (istype(wisp))
|
||||
sight |= wisp.sight_flags
|
||||
if(!isnull(wisp.lighting_alpha))
|
||||
lighting_alpha = min(lighting_alpha, wisp.lighting_alpha)
|
||||
SEND_SIGNAL(src, COMSIG_MOB_UPDATE_SIGHT)
|
||||
|
||||
sync_lighting_plane_alpha()
|
||||
|
||||
|
||||
@@ -148,7 +148,7 @@
|
||||
if(INCORPOREAL_MOVE_BASIC)
|
||||
var/T = get_step(L,direct)
|
||||
if(T)
|
||||
L.loc = T
|
||||
L.forceMove(T)
|
||||
L.setDir(direct)
|
||||
if(INCORPOREAL_MOVE_SHADOW)
|
||||
if(prob(50))
|
||||
@@ -190,7 +190,7 @@
|
||||
new /obj/effect/temp_visual/dir_setting/ninja/shadow(mobloc, L.dir)
|
||||
var/T = get_step(L,direct)
|
||||
if(T)
|
||||
L.loc = T
|
||||
L.forceMove(T)
|
||||
L.setDir(direct)
|
||||
if(INCORPOREAL_MOVE_JAUNT) //Incorporeal move, but blocked by holy-watered tiles and salt piles.
|
||||
var/turf/open/floor/stepTurf = get_step(L, direct)
|
||||
@@ -209,7 +209,7 @@
|
||||
to_chat(L, "<span class='warning'>Holy energies block your path!</span>")
|
||||
return
|
||||
|
||||
L.loc = get_step(L, direct)
|
||||
L.forceMove(stepTurf)
|
||||
L.setDir(direct)
|
||||
return TRUE
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
return machinery_computer.update_icon()
|
||||
|
||||
// This thing is not meant to be used on it's own, get topic data from our machinery owner.
|
||||
//obj/item/modular_computer/processor/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
|
||||
//obj/item/modular_computer/processor/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
|
||||
// if(!machinery_computer)
|
||||
// return 0
|
||||
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
/datum/orbit
|
||||
var/atom/movable/orbiter
|
||||
var/atom/orbiting
|
||||
var/lock = TRUE
|
||||
var/turf/lastloc
|
||||
var/lastprocess
|
||||
|
||||
/datum/orbit/New(_orbiter, _orbiting, _lock)
|
||||
orbiter = _orbiter
|
||||
orbiting = _orbiting
|
||||
SSorbit.processing += src
|
||||
if (!orbiting.orbiters)
|
||||
orbiting.orbiters = list()
|
||||
orbiting.orbiters += src
|
||||
|
||||
if (orbiter.orbiting)
|
||||
orbiter.stop_orbit()
|
||||
orbiter.orbiting = src
|
||||
Check()
|
||||
lock = _lock
|
||||
|
||||
//do not qdel directly, use stop_orbit on the orbiter. (This way the orbiter can bind to the orbit stopping)
|
||||
/datum/orbit/Destroy(force = FALSE)
|
||||
SSorbit.processing -= src
|
||||
if (orbiter)
|
||||
orbiter.orbiting = null
|
||||
orbiter = null
|
||||
if (orbiting)
|
||||
if (orbiting.orbiters)
|
||||
orbiting.orbiters -= src
|
||||
if (!orbiting.orbiters.len)//we are the last orbit, delete the list
|
||||
orbiting.orbiters = null
|
||||
orbiting = null
|
||||
return ..()
|
||||
|
||||
/datum/orbit/proc/Check(turf/targetloc, list/checked_already = list())
|
||||
//Avoid infinite loops for people who end up orbiting themself through another orbiter
|
||||
checked_already[src] = TRUE
|
||||
if (!orbiter)
|
||||
qdel(src)
|
||||
return
|
||||
if (!orbiting)
|
||||
orbiter.stop_orbit()
|
||||
return
|
||||
if (!orbiter.orbiting) //admin wants to stop the orbit.
|
||||
orbiter.orbiting = src //set it back to us first
|
||||
orbiter.stop_orbit()
|
||||
var/atom/movable/AM = orbiting
|
||||
if(istype(AM) && AM.orbiting && AM.orbiting.orbiting == orbiter)
|
||||
orbiter.stop_orbit()
|
||||
return
|
||||
lastprocess = world.time
|
||||
if (!targetloc)
|
||||
targetloc = get_turf(orbiting)
|
||||
if (!targetloc || (!lock && orbiter.loc != lastloc && orbiter.loc != targetloc))
|
||||
orbiter.stop_orbit()
|
||||
return
|
||||
var/turf/old_turf = get_turf(orbiter)
|
||||
var/turf/new_turf = get_turf(targetloc)
|
||||
if (old_turf?.z != new_turf?.z)
|
||||
orbiter.onTransitZ(old_turf?.z, new_turf?.z)
|
||||
// DO NOT PORT TO FORCEMOVE - MEMECODE WILL KILL MC
|
||||
orbiter.loc = targetloc
|
||||
orbiter.update_parallax_contents()
|
||||
orbiter.update_light()
|
||||
lastloc = orbiter.loc
|
||||
for(var/other_orbit in orbiter.orbiters)
|
||||
var/datum/orbit/OO = other_orbit
|
||||
//Skip if checked already
|
||||
if(checked_already[OO])
|
||||
continue
|
||||
OO.Check(targetloc, checked_already)
|
||||
|
||||
/atom/movable/var/datum/orbit/orbiting = null
|
||||
/atom/var/list/orbiters = null
|
||||
|
||||
//A: atom to orbit
|
||||
//radius: range to orbit at, radius of the circle formed by orbiting (in pixels)
|
||||
//clockwise: whether you orbit clockwise or anti clockwise
|
||||
//rotation_speed: how fast to rotate (how many ds should it take for a rotation to complete)
|
||||
//rotation_segments: the resolution of the orbit circle, less = a more block circle, this can be used to produce hexagons (6 segments) triangles (3 segments), and so on, 36 is the best default.
|
||||
//pre_rotation: Chooses to rotate src 90 degress towards the orbit dir (clockwise/anticlockwise), useful for things to go "head first" like ghosts
|
||||
//lockinorbit: Forces src to always be on A's turf, otherwise the orbit cancels when src gets too far away (eg: ghosts)
|
||||
|
||||
/atom/movable/proc/orbit(atom/A, radius = 10, clockwise = FALSE, rotation_speed = 20, rotation_segments = 36, pre_rotation = TRUE, lockinorbit = FALSE)
|
||||
if (!istype(A))
|
||||
return
|
||||
|
||||
new/datum/orbit(src, A, lockinorbit)
|
||||
if (!orbiting) //something failed, and our orbit datum deleted itself
|
||||
return
|
||||
var/matrix/initial_transform = matrix(transform)
|
||||
|
||||
//Head first!
|
||||
if (pre_rotation)
|
||||
var/matrix/M = matrix(transform)
|
||||
var/pre_rot = 90
|
||||
if(!clockwise)
|
||||
pre_rot = -90
|
||||
M.Turn(pre_rot)
|
||||
transform = M
|
||||
|
||||
var/matrix/shift = matrix(transform)
|
||||
shift.Translate(0,radius)
|
||||
transform = shift
|
||||
|
||||
SpinAnimation(rotation_speed, -1, clockwise, rotation_segments)
|
||||
|
||||
//we stack the orbits up client side, so we can assign this back to normal server side without it breaking the orbit
|
||||
transform = initial_transform
|
||||
|
||||
/atom/movable/proc/stop_orbit()
|
||||
SpinAnimation(0,0)
|
||||
qdel(orbiting)
|
||||
|
||||
/atom/Destroy(force = FALSE)
|
||||
. = ..()
|
||||
if (orbiters)
|
||||
for (var/thing in orbiters)
|
||||
var/datum/orbit/O = thing
|
||||
if (O.orbiter)
|
||||
O.orbiter.stop_orbit()
|
||||
|
||||
/atom/movable/Destroy(force = FALSE)
|
||||
. = ..()
|
||||
if (orbiting)
|
||||
stop_orbit()
|
||||
|
||||
/atom/movable/proc/transfer_observers_to(atom/movable/target)
|
||||
if(orbiters)
|
||||
for(var/thing in orbiters)
|
||||
var/datum/orbit/O = thing
|
||||
if(O.orbiter && isobserver(O.orbiter))
|
||||
var/mob/dead/observer/D = O.orbiter
|
||||
D.ManualFollow(target)
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
/obj/item/paperplane
|
||||
name = "paper plane"
|
||||
desc = "Paper, folded in the shape of a plane."
|
||||
@@ -10,8 +11,14 @@
|
||||
resistance_flags = FLAMMABLE
|
||||
max_integrity = 50
|
||||
|
||||
var/hit_probability = 2//%
|
||||
var/obj/item/paper/internalPaper
|
||||
|
||||
/obj/item/paperplane/origami
|
||||
desc = "Paper, masterfully folded in the shape of a plane."
|
||||
throwforce = 20 //same as throwing stars, but no chance of embedding.
|
||||
hit_probability = 100 //guaranteed to cause eye damage when it hits a mob.
|
||||
|
||||
/obj/item/paperplane/Initialize(mapload, obj/item/paper/newPaper)
|
||||
. = ..()
|
||||
pixel_y = rand(-8, 8)
|
||||
@@ -22,13 +29,18 @@
|
||||
color = newPaper.color
|
||||
newPaper.forceMove(src)
|
||||
else
|
||||
internalPaper = new /obj/item/paper(src)
|
||||
internalPaper = new(src)
|
||||
update_icon()
|
||||
|
||||
/obj/item/paperplane/Destroy()
|
||||
if(internalPaper)
|
||||
qdel(internalPaper)
|
||||
/obj/item/paperplane/handle_atom_del(atom/A)
|
||||
if(A == internalPaper)
|
||||
internalPaper = null
|
||||
if(!QDELETED(src))
|
||||
qdel(src)
|
||||
return ..()
|
||||
|
||||
/obj/item/paperplane/Destroy()
|
||||
QDEL_NULL(internalPaper)
|
||||
return ..()
|
||||
|
||||
/obj/item/paperplane/suicide_act(mob/living/user)
|
||||
@@ -48,7 +60,7 @@
|
||||
|
||||
/obj/item/paperplane/attack_self(mob/user)
|
||||
to_chat(user, "<span class='notice'>You unfold [src].</span>")
|
||||
var/atom/movable/internal_paper_tmp = internalPaper
|
||||
var/obj/item/paper/internal_paper_tmp = internalPaper
|
||||
internal_paper_tmp.forceMove(loc)
|
||||
internalPaper = null
|
||||
qdel(src)
|
||||
@@ -86,11 +98,18 @@
|
||||
. = ..(target, range, speed, thrower, FALSE, diagonals_first, callback)
|
||||
|
||||
/obj/item/paperplane/throw_impact(atom/hit_atom)
|
||||
if(iscarbon(hit_atom))
|
||||
var/mob/living/carbon/C = hit_atom
|
||||
if(C.can_catch_item(TRUE))
|
||||
var/datum/action/innate/origami/origami_action = locate() in C.actions
|
||||
if(origami_action?.active) //if they're a master of origami and have the ability turned on, force throwmode on so they'll automatically catch the plane.
|
||||
C.throw_mode_on()
|
||||
|
||||
if(..() || !ishuman(hit_atom))//if the plane is caught or it hits a nonhuman
|
||||
return
|
||||
var/mob/living/carbon/human/H = hit_atom
|
||||
if(prob(2))
|
||||
if((H.head && H.head.flags_cover & HEADCOVERSEYES) || (H.wear_mask && H.wear_mask.flags_cover & MASKCOVERSEYES) || (H.glasses && H.glasses.flags_cover & GLASSESCOVERSEYES))
|
||||
if(prob(hit_probability))
|
||||
if(H.is_eyes_covered())
|
||||
return
|
||||
visible_message("<span class='danger'>\The [src] hits [H] in the eye!</span>")
|
||||
H.adjust_blurriness(6)
|
||||
@@ -107,5 +126,11 @@
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You fold [src] into the shape of a plane!</span>")
|
||||
user.temporarilyRemoveItemFromInventory(src)
|
||||
I = new /obj/item/paperplane(user, src)
|
||||
var/obj/item/paperplane/plane_type = /obj/item/paperplane
|
||||
//Origami Master
|
||||
var/datum/action/innate/origami/origami_action = locate() in user.actions
|
||||
if(origami_action?.active)
|
||||
plane_type = /obj/item/paperplane/origami
|
||||
|
||||
I = new plane_type(user, src)
|
||||
user.put_in_hands(I)
|
||||
|
||||
@@ -33,8 +33,8 @@
|
||||
return
|
||||
|
||||
/obj/singularity/energy_ball/Destroy()
|
||||
if(orbiting && istype(orbiting.orbiting, /obj/singularity/energy_ball))
|
||||
var/obj/singularity/energy_ball/EB = orbiting.orbiting
|
||||
if(orbiting && istype(orbiting.parent, /obj/singularity/energy_ball))
|
||||
var/obj/singularity/energy_ball/EB = orbiting.parent
|
||||
EB.orbiting_balls -= src
|
||||
|
||||
for(var/ball in orbiting_balls)
|
||||
@@ -146,12 +146,12 @@
|
||||
|
||||
. = ..()
|
||||
/obj/singularity/energy_ball/stop_orbit()
|
||||
if (orbiting && istype(orbiting.orbiting, /obj/singularity/energy_ball))
|
||||
var/obj/singularity/energy_ball/orbitingball = orbiting.orbiting
|
||||
if (orbiting && istype(orbiting.parent, /obj/singularity/energy_ball))
|
||||
var/obj/singularity/energy_ball/orbitingball = orbiting.parent
|
||||
orbitingball.orbiting_balls -= src
|
||||
orbitingball.dissipate_strength = orbitingball.orbiting_balls.len
|
||||
..()
|
||||
if (!loc && !QDELETED(src))
|
||||
. = ..()
|
||||
if (!QDELETED(src))
|
||||
qdel(src)
|
||||
|
||||
|
||||
|
||||
@@ -24,4 +24,4 @@
|
||||
e_cost = 40
|
||||
fire_sound = 'sound/weapons/taser2.ogg'
|
||||
harmful = FALSE
|
||||
click_cooldown_override = 3
|
||||
click_cooldown_override = 3.5
|
||||
|
||||
@@ -59,3 +59,20 @@
|
||||
S.forceMove(D)
|
||||
D.injector = S
|
||||
..()
|
||||
|
||||
/obj/item/ammo_casing/syringegun/dart
|
||||
name = "used air canister"
|
||||
desc = "A small canister of compressed gas."
|
||||
projectile_type = /obj/item/projectile/bullet/dart/syringe/dart
|
||||
firing_effect_type = null
|
||||
harmful = FALSE
|
||||
|
||||
/obj/item/ammo_casing/syringegun/dart/ready_proj(atom/target, mob/living/user, quiet, zone_override = "")
|
||||
..()
|
||||
var/obj/item/gun/syringe/SG = loc
|
||||
if(!SG.syringes.len)
|
||||
return
|
||||
var/obj/item/reagent_containers/syringe/dart/S = SG.syringes[1]
|
||||
if(S.emptrig == TRUE)
|
||||
var/obj/item/projectile/bullet/dart/syringe/dart/D = BB
|
||||
D.emptrig = TRUE
|
||||
|
||||
@@ -116,7 +116,7 @@
|
||||
new /obj/effect/temp_visual/heal(get_turf(target), "#80F5FF")
|
||||
target.adjustBruteLoss(-4)
|
||||
target.adjustFireLoss(-4)
|
||||
target.adjustToxLoss(-1)
|
||||
target.adjustToxLoss(-1, forced = TRUE)
|
||||
target.adjustOxyLoss(-1)
|
||||
return
|
||||
|
||||
|
||||
@@ -102,3 +102,23 @@
|
||||
else
|
||||
to_chat(user, "<span class='warning'>[src] cannot hold more syringes!</span>")
|
||||
return FALSE
|
||||
|
||||
/obj/item/gun/syringe/dart
|
||||
name = "dart gun"
|
||||
desc = "A compressed air gun, designed to fit medicinal darts for application of medicine for those patients just out of reach."
|
||||
icon_state = "dartgun"
|
||||
item_state = "dartgun"
|
||||
materials = list(MAT_METAL=2000, MAT_GLASS=500)
|
||||
suppressed = TRUE //Softer fire sound
|
||||
can_unsuppress = FALSE
|
||||
|
||||
/obj/item/gun/syringe/dart/Initialize()
|
||||
..()
|
||||
chambered = new /obj/item/ammo_casing/syringegun/dart(src)
|
||||
|
||||
/obj/item/gun/syringe/dart/attackby(obj/item/A, mob/user, params, show_msg = TRUE)
|
||||
if(istype(A, /obj/item/reagent_containers/syringe/dart))
|
||||
..()
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You can't put the [A] into \the [src]!</span>")
|
||||
return FALSE
|
||||
|
||||
@@ -8,12 +8,14 @@
|
||||
. = ..()
|
||||
create_reagents(50, NO_REACT)
|
||||
|
||||
/obj/item/projectile/bullet/dart/on_hit(atom/target, blocked = FALSE)
|
||||
/obj/item/projectile/bullet/dart/on_hit(atom/target, blocked = FALSE, skip = FALSE)
|
||||
if(iscarbon(target))
|
||||
var/mob/living/carbon/M = target
|
||||
if(blocked != 100) // not completely blocked
|
||||
if(M.can_inject(null, FALSE, def_zone, piercing)) // Pass the hit zone to see if it can inject by whether it hit the head or the body.
|
||||
..()
|
||||
if(skip == TRUE)
|
||||
return
|
||||
reagents.reaction(M, INJECT)
|
||||
reagents.trans_to(M, reagents.total_volume)
|
||||
return TRUE
|
||||
@@ -36,3 +38,44 @@
|
||||
/obj/item/projectile/bullet/dart/syringe
|
||||
name = "syringe"
|
||||
icon_state = "syringeproj"
|
||||
|
||||
//I am in a mess of my own making
|
||||
/obj/item/projectile/bullet/dart/syringe/dart
|
||||
name = "Smartdart"
|
||||
icon_state = "dartproj"
|
||||
damage = 0
|
||||
var/emptrig = FALSE
|
||||
|
||||
/obj/item/projectile/bullet/dart/syringe/dart/on_hit(atom/target, blocked = FALSE)
|
||||
if(iscarbon(target))
|
||||
var/mob/living/carbon/M = target
|
||||
if(blocked != 100)
|
||||
if(M.can_inject(null, FALSE, def_zone, piercing)) // Pass the hit zone to see if it can inject by whether it hit the head or the body.
|
||||
..(target, blocked, TRUE)
|
||||
for(var/datum/reagent/R in reagents.reagent_list) //OD prevention time!
|
||||
if(istype(R, /datum/reagent/medicine)) //Is this a medicine?
|
||||
if(M.reagents.has_reagent(R.id))
|
||||
if(R.overdose_threshold == 0 || emptrig == TRUE) //Is there a possible OD?
|
||||
M.reagents.add_reagent(R.id, R.volume)
|
||||
else
|
||||
var/transVol = CLAMP(R.volume, 0, (R.overdose_threshold - M.reagents.get_reagent_amount(R.id)) -1)
|
||||
M.reagents.add_reagent(R.id, transVol)
|
||||
else
|
||||
if(!R.overdose_threshold == 0)
|
||||
var/transVol = CLAMP(R.volume, 0, R.overdose_threshold-1)
|
||||
M.reagents.add_reagent(R.id, transVol)
|
||||
else
|
||||
M.reagents.add_reagent(R.id, R.volume)
|
||||
|
||||
|
||||
|
||||
target.visible_message("<span class='notice'>\The [src] beeps!</span>")
|
||||
to_chat("<span class='notice'><i>You feel a tiny prick as a smartdart embeds itself in you with a beep.</i></span>")
|
||||
return TRUE
|
||||
else
|
||||
blocked = 100
|
||||
target.visible_message("<span class='danger'>\The [src] was deflected!</span>", \
|
||||
"<span class='userdanger'>You see a [src] bounce off you, booping sadly!</span>")
|
||||
|
||||
target.visible_message("<span class='danger'>\The [src] fails to land on target!</span>")
|
||||
return TRUE
|
||||
|
||||
@@ -21,7 +21,9 @@
|
||||
if(GLOB.chemical_reactions_list)
|
||||
return
|
||||
|
||||
var/paths = subtypesof(/datum/chemical_reaction)
|
||||
|
||||
//Randomized need to go last since they need to check against conflicts with normal recipes
|
||||
var/paths = subtypesof(/datum/chemical_reaction) - typesof(/datum/chemical_reaction/randomized) + subtypesof(/datum/chemical_reaction/randomized)
|
||||
GLOB.chemical_reactions_list = list()
|
||||
|
||||
for(var/path in paths)
|
||||
@@ -29,6 +31,9 @@
|
||||
var/datum/chemical_reaction/D = new path()
|
||||
var/list/reaction_ids = list()
|
||||
|
||||
if(!D.id)
|
||||
continue
|
||||
|
||||
if(D.required_reagents && D.required_reagents.len)
|
||||
for(var/reaction in D.required_reagents)
|
||||
reaction_ids += reaction
|
||||
@@ -267,6 +272,9 @@
|
||||
continue
|
||||
if(!C)
|
||||
C = R.holder.my_atom
|
||||
if(!R.metabolizing)
|
||||
R.metabolizing = TRUE
|
||||
R.on_mob_metabolize(C)
|
||||
if(C && R)
|
||||
if(C.reagent_check(R) != 1)
|
||||
if(can_overdose)
|
||||
@@ -313,6 +321,21 @@
|
||||
C.update_stamina()
|
||||
update_total()
|
||||
|
||||
//Signals that metabolization has stopped, triggering the end of trait-based effects
|
||||
/datum/reagents/proc/end_metabolization(mob/living/carbon/C, keep_liverless = TRUE)
|
||||
var/list/cached_reagents = reagent_list
|
||||
for(var/reagent in cached_reagents)
|
||||
var/datum/reagent/R = reagent
|
||||
if(QDELETED(R.holder))
|
||||
continue
|
||||
if(keep_liverless && R.self_consuming) //Will keep working without a liver
|
||||
continue
|
||||
if(!C)
|
||||
C = R.holder.my_atom
|
||||
if(R.metabolizing)
|
||||
R.metabolizing = FALSE
|
||||
R.on_mob_end_metabolize(C)
|
||||
|
||||
/datum/reagents/proc/conditional_update_move(atom/A, Running = 0)
|
||||
var/list/cached_reagents = reagent_list
|
||||
for(var/reagent in cached_reagents)
|
||||
@@ -466,6 +489,9 @@
|
||||
if(R.id == reagent)
|
||||
if(my_atom && isliving(my_atom))
|
||||
var/mob/living/M = my_atom
|
||||
if(R.metabolizing)
|
||||
R.metabolizing = FALSE
|
||||
R.on_mob_end_metabolize(M)
|
||||
R.on_mob_delete(M)
|
||||
qdel(R)
|
||||
reagent_list -= R
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
interaction_flags_machine = INTERACT_MACHINE_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OFFLINE
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
circuit = /obj/item/circuitboard/machine/chem_dispenser
|
||||
var/cell_type = /obj/item/stock_parts/cell/high
|
||||
var/obj/item/stock_parts/cell/cell
|
||||
var/powerefficiency = 0.1
|
||||
var/amount = 30
|
||||
@@ -79,7 +78,6 @@
|
||||
|
||||
/obj/machinery/chem_dispenser/Initialize()
|
||||
. = ..()
|
||||
cell = new cell_type
|
||||
dispensable_reagents = sortList(dispensable_reagents)
|
||||
update_icon()
|
||||
|
||||
|
||||
@@ -33,6 +33,10 @@
|
||||
var/addiction_stage4_end = 40
|
||||
var/overdosed = 0 // You fucked up and this is now triggering its overdose effects, purge that shit quick.
|
||||
var/self_consuming = FALSE
|
||||
var/metabolizing = FALSE
|
||||
|
||||
|
||||
|
||||
|
||||
/datum/reagent/Destroy() // This should only be called by the holder, so it's already handled clearing its references
|
||||
. = ..()
|
||||
@@ -68,6 +72,14 @@
|
||||
/datum/reagent/proc/on_mob_delete(mob/living/L)
|
||||
return
|
||||
|
||||
// Called when this reagent first starts being metabolized by a liver
|
||||
/datum/reagent/proc/on_mob_metabolize(mob/living/L)
|
||||
return
|
||||
|
||||
// Called when this reagent stops being metabolized by a liver
|
||||
/datum/reagent/proc/on_mob_end_metabolize(mob/living/L)
|
||||
return
|
||||
|
||||
/datum/reagent/proc/on_move(mob/M)
|
||||
return
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
|
||||
M.add_atom_colour(color, TEMPORARY_COLOUR_PRIORITY)
|
||||
return ..()
|
||||
|
||||
/datum/reagent/consumable/ethanol/beer/green/on_mob_delete(mob/living/M)
|
||||
/datum/reagent/consumable/ethanol/beer/green/on_mob_end_metabolize(mob/living/M)
|
||||
M.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, color)
|
||||
|
||||
/datum/reagent/consumable/ethanol/kahlua
|
||||
@@ -569,13 +569,13 @@ All effects don't start immediately, but rather get worse over time; the rate is
|
||||
glass_desc = "Tequila and Coffee liqueur, brought together in a mouthwatering mixture. Drink up."
|
||||
var/tough_text
|
||||
|
||||
/datum/reagent/consumable/ethanol/brave_bull/on_mob_add(mob/living/M)
|
||||
/datum/reagent/consumable/ethanol/brave_bull/on_mob_metabolize(mob/living/M)
|
||||
tough_text = pick("brawny", "tenacious", "tough", "hardy", "sturdy") //Tuff stuff
|
||||
to_chat(M, "<span class='notice'>You feel [tough_text]!</span>")
|
||||
M.maxHealth += 10 //Brave Bull makes you sturdier, and thus capable of withstanding a tiny bit more punishment.
|
||||
M.health += 10
|
||||
|
||||
/datum/reagent/consumable/ethanol/brave_bull/on_mob_delete(mob/living/M)
|
||||
/datum/reagent/consumable/ethanol/brave_bull/on_mob_end_metabolize(mob/living/M)
|
||||
to_chat(M, "<span class='notice'>You no longer feel [tough_text].</span>")
|
||||
M.maxHealth -= 10
|
||||
M.health = min(M.health - 10, M.maxHealth) //This can indeed crit you if you're alive solely based on alchol ingestion
|
||||
@@ -593,7 +593,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
|
||||
glass_desc = "Oh great, now you feel nostalgic about sunrises back on Terra..."
|
||||
var/obj/effect/light_holder
|
||||
|
||||
/datum/reagent/consumable/ethanol/tequila_sunrise/on_mob_add(mob/living/M)
|
||||
/datum/reagent/consumable/ethanol/tequila_sunrise/on_mob_metabolize(mob/living/M)
|
||||
to_chat(M, "<span class='notice'>You feel gentle warmth spread through your body!</span>")
|
||||
light_holder = new(M)
|
||||
light_holder.set_light(3, 0.7, "#FFCC00") //Tequila Sunrise makes you radiate dim light, like a sunrise!
|
||||
@@ -605,7 +605,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
|
||||
light_holder.forceMove(M)
|
||||
return ..()
|
||||
|
||||
/datum/reagent/consumable/ethanol/tequila_sunrise/on_mob_delete(mob/living/M)
|
||||
/datum/reagent/consumable/ethanol/tequila_sunrise/on_mob_end_metabolize(mob/living/M)
|
||||
to_chat(M, "<span class='notice'>The warmth in your body fades.</span>")
|
||||
QDEL_NULL(light_holder)
|
||||
|
||||
@@ -671,7 +671,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
|
||||
glass_desc = "A manly concoction made from Ale and Beer. Intended for true men only."
|
||||
var/dorf_mode
|
||||
|
||||
/datum/reagent/consumable/ethanol/manly_dorf/on_mob_add(mob/living/M)
|
||||
/datum/reagent/consumable/ethanol/manly_dorf/on_mob_metabolize(mob/living/M)
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(H.dna.check_mutation(DWARFISM) || HAS_TRAIT(H, TRAIT_ALCOHOL_TOLERANCE))
|
||||
@@ -722,7 +722,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
|
||||
glass_desc = "Kahlua, Irish Cream, and cognac. You will get bombed."
|
||||
shot_glass_icon_state = "b52glass"
|
||||
|
||||
/datum/reagent/consumable/ethanol/b52/on_mob_add(mob/living/M)
|
||||
/datum/reagent/consumable/ethanol/b52/on_mob_metabolize(mob/living/M)
|
||||
playsound(M, 'sound/effects/explosion_distant.ogg', 100, FALSE)
|
||||
|
||||
/datum/reagent/consumable/ethanol/irishcoffee
|
||||
@@ -1534,7 +1534,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
|
||||
glass_desc = "If you're feeling low, count on the buttery flavor of our own bastion bourbon."
|
||||
shot_glass_icon_state = "shotglassgreen"
|
||||
|
||||
/datum/reagent/consumable/ethanol/bastion_bourbon/on_mob_add(mob/living/L)
|
||||
/datum/reagent/consumable/ethanol/bastion_bourbon/on_mob_metabolize(mob/living/L)
|
||||
var/heal_points = 10
|
||||
if(L.health <= 0)
|
||||
heal_points = 20 //heal more if we're in softcrit
|
||||
@@ -1618,7 +1618,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
|
||||
glass_name = "Crevice Spike"
|
||||
glass_desc = "It'll either knock the drunkenness out of you or knock you out cold. Both, probably."
|
||||
|
||||
/datum/reagent/consumable/ethanol/crevice_spike/on_mob_add(mob/living/L) //damage only applies when drink first enters system and won't again until drink metabolizes out
|
||||
/datum/reagent/consumable/ethanol/crevice_spike/on_mob_metabolize(mob/living/L) //damage only applies when drink first enters system and won't again until drink metabolizes out
|
||||
L.adjustBruteLoss(3 * min(5,volume)) //minimum 3 brute damage on ingestion to limit non-drink means of injury - a full 5 unit gulp of the drink trucks you for the full 15
|
||||
|
||||
/datum/reagent/consumable/ethanol/sake
|
||||
@@ -1661,7 +1661,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
|
||||
glass_desc = "A creamy, indulgent delight that is stronger than it seems."
|
||||
var/obj/item/shield/mighty_shield
|
||||
|
||||
/datum/reagent/consumable/ethanol/alexander/on_mob_add(mob/living/L)
|
||||
/datum/reagent/consumable/ethanol/alexander/on_mob_metabolize(mob/living/L)
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/thehuman = L
|
||||
for(var/obj/item/shield/theshield in thehuman.contents)
|
||||
@@ -1675,7 +1675,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
|
||||
if(mighty_shield && !(mighty_shield in L.contents)) //If you had a shield and lose it, you lose the reagent as well. Otherwise this is just a normal drink.
|
||||
L.reagents.del_reagent("alexander")
|
||||
|
||||
/datum/reagent/consumable/ethanol/alexander/on_mob_delete(mob/living/L)
|
||||
/datum/reagent/consumable/ethanol/alexander/on_mob_end_metabolize(mob/living/L)
|
||||
if(mighty_shield)
|
||||
mighty_shield.block_chance -= 10
|
||||
to_chat(L,"<span class='notice'>You notice [mighty_shield] looks worn again. Weird.</span>")
|
||||
@@ -1796,7 +1796,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
|
||||
M.overeatduration = 0
|
||||
return ..()
|
||||
|
||||
/datum/reagent/consumable/ethanol/fanciulli/on_mob_add(mob/living/M)
|
||||
/datum/reagent/consumable/ethanol/fanciulli/on_mob_metabolize(mob/living/M)
|
||||
if(M.health > 0)
|
||||
M.adjustStaminaLoss(20)
|
||||
. = TRUE
|
||||
@@ -1820,7 +1820,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
|
||||
M.adjust_bodytemperature(-20 * TEMPERATURE_DAMAGE_COEFFICIENT, T0C)
|
||||
return ..()
|
||||
|
||||
/datum/reagent/consumable/ethanol/branca_menta/on_mob_add(mob/living/M)
|
||||
/datum/reagent/consumable/ethanol/branca_menta/on_mob_metabolize(mob/living/M)
|
||||
if(M.health > 0)
|
||||
M.adjustStaminaLoss(35)
|
||||
. = TRUE
|
||||
|
||||
@@ -204,7 +204,7 @@
|
||||
C.hal_screwyhud = SCREWYHUD_HEALTHY //fully healed, honest
|
||||
..()
|
||||
|
||||
/datum/reagent/blob/regenerative_materia/on_mob_delete(mob/living/M)
|
||||
/datum/reagent/blob/regenerative_materia/on_mob_end_metabolize(mob/living/M)
|
||||
if(iscarbon(M))
|
||||
var/mob/living/carbon/N = M
|
||||
N.hal_screwyhud = 0
|
||||
|
||||
@@ -390,11 +390,11 @@
|
||||
glass_name = "glass of Nuka Cola"
|
||||
glass_desc = "Don't cry, Don't raise your eye, It's only nuclear wasteland."
|
||||
|
||||
/datum/reagent/consumable/nuka_cola/on_mob_add(mob/living/L)
|
||||
/datum/reagent/consumable/nuka_cola/on_mob_metabolize(mob/living/L)
|
||||
..()
|
||||
ADD_TRAIT(L, TRAIT_GOTTAGOFAST, id)
|
||||
|
||||
/datum/reagent/consumable/nuka_cola/on_mob_delete(mob/living/L)
|
||||
/datum/reagent/consumable/nuka_cola/on_mob_end_metabolize(mob/living/L)
|
||||
REMOVE_TRAIT(L, TRAIT_GOTTAGOFAST, id)
|
||||
..()
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
taste_description = "bitterness"
|
||||
var/trippy = TRUE //Does this drug make you trip?
|
||||
|
||||
/datum/reagent/drug/on_mob_delete(mob/living/M)
|
||||
/datum/reagent/drug/on_mob_end_metabolize(mob/living/M)
|
||||
if(trippy)
|
||||
SEND_SIGNAL(M, COMSIG_CLEAR_MOOD_EVENT, "[id]_high")
|
||||
|
||||
@@ -168,11 +168,11 @@
|
||||
var/jitter = TRUE
|
||||
var/confusion = TRUE
|
||||
|
||||
/datum/reagent/drug/methamphetamine/on_mob_add(mob/living/L)
|
||||
/datum/reagent/drug/methamphetamine/on_mob_metabolize(mob/living/L)
|
||||
..()
|
||||
L.ignore_slowdown(id)
|
||||
|
||||
/datum/reagent/drug/methamphetamine/on_mob_delete(mob/living/L)
|
||||
/datum/reagent/drug/methamphetamine/on_mob_end_metabolize(mob/living/L)
|
||||
L.unignore_slowdown(id)
|
||||
..()
|
||||
|
||||
@@ -262,7 +262,7 @@
|
||||
taste_description = "salt" // because they're bathsalts?
|
||||
var/datum/brain_trauma/special/psychotic_brawling/bath_salts/rage
|
||||
|
||||
/datum/reagent/drug/bath_salts/on_mob_add(mob/living/L)
|
||||
/datum/reagent/drug/bath_salts/on_mob_metabolize(mob/living/L)
|
||||
..()
|
||||
ADD_TRAIT(L, TRAIT_STUNIMMUNE, id)
|
||||
ADD_TRAIT(L, TRAIT_SLEEPIMMUNE, id)
|
||||
@@ -271,7 +271,7 @@
|
||||
rage = new()
|
||||
C.gain_trauma(rage, TRAUMA_RESILIENCE_ABSOLUTE)
|
||||
|
||||
/datum/reagent/drug/bath_salts/on_mob_delete(mob/living/L)
|
||||
/datum/reagent/drug/bath_salts/on_mob_end_metabolize(mob/living/L)
|
||||
REMOVE_TRAIT(L, TRAIT_STUNIMMUNE, id)
|
||||
REMOVE_TRAIT(L, TRAIT_SLEEPIMMUNE, id)
|
||||
if(rage)
|
||||
@@ -381,7 +381,7 @@
|
||||
addiction_stage3_end = 40
|
||||
addiction_stage4_end = 240
|
||||
|
||||
/datum/reagent/drug/skooma/on_mob_add(mob/living/L)
|
||||
/datum/reagent/drug/skooma/on_mob_metabolize(mob/living/L)
|
||||
. = ..()
|
||||
ADD_TRAIT(L, TRAIT_GOTTAGOFAST, id)
|
||||
L.next_move_modifier *= 2
|
||||
@@ -392,7 +392,7 @@
|
||||
if(H.dna && H.dna.species)
|
||||
H.dna.species.punchdamagehigh *= 5
|
||||
|
||||
/datum/reagent/drug/skooma/on_mob_delete(mob/living/L)
|
||||
/datum/reagent/drug/skooma/on_mob_end_metabolize(mob/living/L)
|
||||
. = ..()
|
||||
REMOVE_TRAIT(L, TRAIT_GOTTAGOFAST, id)
|
||||
L.next_move_modifier *= 0.5
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "quality_drink", /datum/mood_event/quality_verygood)
|
||||
if (DRINK_FANTASTIC)
|
||||
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "quality_drink", /datum/mood_event/quality_fantastic)
|
||||
if (FOOD_AMAZING)
|
||||
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "quality_food", /datum/mood_event/amazingtaste)
|
||||
return ..()
|
||||
|
||||
/datum/reagent/consumable/nutriment
|
||||
@@ -401,7 +403,7 @@
|
||||
metabolization_rate = 0.2 * REAGENTS_METABOLISM
|
||||
taste_description = "mushroom"
|
||||
|
||||
/datum/reagent/mushroomhallucinogen/on_mob_life(mob/living/carbon/M)
|
||||
/datum/reagent/drug/mushroomhallucinogen/on_mob_life(mob/living/carbon/M)
|
||||
M.slurring = max(M.slurring,50)
|
||||
switch(current_cycle)
|
||||
if(1 to 5)
|
||||
@@ -686,7 +688,7 @@
|
||||
/datum/reagent/consumable/tinlux/reaction_mob(mob/living/M)
|
||||
M.set_light(2)
|
||||
|
||||
/datum/reagent/consumable/tinlux/on_mob_delete(mob/living/M)
|
||||
/datum/reagent/consumable/tinlux/on_mob_end_metabolize(mob/living/M)
|
||||
M.set_light(-2)
|
||||
|
||||
/datum/reagent/consumable/vitfro
|
||||
@@ -711,3 +713,14 @@
|
||||
nutriment_factor = 5 * REAGENTS_METABOLISM
|
||||
color = "#eef442" // rgb: 238, 244, 66
|
||||
taste_description = "mournful honking"
|
||||
|
||||
/datum/reagent/consumable/secretsauce
|
||||
name = "secret sauce"
|
||||
id = "secret_sauce"
|
||||
description = "What could it be."
|
||||
nutriment_factor = 2 * REAGENTS_METABOLISM
|
||||
color = "#792300"
|
||||
taste_description = "indescribable"
|
||||
quality = FOOD_AMAZING
|
||||
taste_mult = 100
|
||||
can_synth = FALSE
|
||||
|
||||
@@ -366,7 +366,7 @@
|
||||
to_chat(M, "<span class='danger'>You feel your wounds fade away to nothing!</span>" )
|
||||
..()
|
||||
|
||||
/datum/reagent/medicine/mine_salve/on_mob_delete(mob/living/M)
|
||||
/datum/reagent/medicine/mine_salve/on_mob_end_metabolize(mob/living/M)
|
||||
if(iscarbon(M))
|
||||
var/mob/living/carbon/N = M
|
||||
N.hal_screwyhud = SCREWYHUD_NONE
|
||||
@@ -483,16 +483,24 @@
|
||||
reagent_state = LIQUID
|
||||
color = "#E6FFF0"
|
||||
metabolization_rate = 0.5 * REAGENTS_METABOLISM
|
||||
var/healtoxinlover = FALSE
|
||||
|
||||
/datum/reagent/medicine/pen_acid/on_mob_life(mob/living/carbon/M)
|
||||
M.radiation -= max(M.radiation-RAD_MOB_SAFE, 0)/50
|
||||
M.adjustToxLoss(-2*REM, 0)
|
||||
M.adjustToxLoss(-2*REM, 0, healtoxinlover)
|
||||
for(var/datum/reagent/R in M.reagents.reagent_list)
|
||||
if(R != src)
|
||||
M.reagents.remove_reagent(R.id,2)
|
||||
..()
|
||||
. = 1
|
||||
|
||||
/datum/reagent/medicine/pen_acid/pen_jelly
|
||||
name = "Pentetic Jelly"
|
||||
id = "pen_jelly"
|
||||
description = "Reduces massive amounts of radiation and toxin damage while purging other chemicals from the body. Slimepeople friendly!"
|
||||
color = "#91D865"
|
||||
healtoxinlover = TRUE
|
||||
|
||||
/datum/reagent/medicine/sal_acid
|
||||
name = "Salicyclic Acid"
|
||||
id = "sal_acid"
|
||||
@@ -630,11 +638,11 @@
|
||||
overdose_threshold = 30
|
||||
addiction_threshold = 25
|
||||
|
||||
/datum/reagent/medicine/morphine/on_mob_add(mob/living/L)
|
||||
/datum/reagent/medicine/morphine/on_mob_metabolize(mob/living/L)
|
||||
..()
|
||||
L.ignore_slowdown(id)
|
||||
|
||||
/datum/reagent/medicine/morphine/on_mob_delete(mob/living/L)
|
||||
/datum/reagent/medicine/morphine/on_mob_end_metabolize(mob/living/L)
|
||||
L.unignore_slowdown(id)
|
||||
..()
|
||||
|
||||
@@ -875,11 +883,11 @@
|
||||
metabolization_rate = 0.5 * REAGENTS_METABOLISM
|
||||
overdose_threshold = 60
|
||||
|
||||
/datum/reagent/medicine/stimulants/on_mob_add(mob/living/L)
|
||||
/datum/reagent/medicine/stimulants/on_mob_metabolize(mob/living/L)
|
||||
..()
|
||||
ADD_TRAIT(L, TRAIT_GOTTAGOFAST, id)
|
||||
|
||||
/datum/reagent/medicine/stimulants/on_mob_delete(mob/living/L)
|
||||
/datum/reagent/medicine/stimulants/on_mob_end_metabolize(mob/living/L)
|
||||
REMOVE_TRAIT(L, TRAIT_GOTTAGOFAST, id)
|
||||
..()
|
||||
|
||||
@@ -1102,7 +1110,7 @@
|
||||
M.adjustBruteLoss(-3 * REM, 0)
|
||||
M.adjustFireLoss(-3 * REM, 0)
|
||||
M.adjustOxyLoss(-15 * REM, 0)
|
||||
M.adjustToxLoss(-3 * REM, 0)
|
||||
M.adjustToxLoss(-3 * REM, 0, TRUE) //Heals TOXINLOVERS
|
||||
M.adjustBrainLoss(2 * REM, 150) //This does, after all, come from ambrosia, and the most powerful ambrosia in existence, at that!
|
||||
M.adjustCloneLoss(-1 * REM, 0)
|
||||
M.adjustStaminaLoss(-30 * REM, 0)
|
||||
@@ -1113,7 +1121,7 @@
|
||||
|
||||
/datum/reagent/medicine/earthsblood/overdose_process(mob/living/M)
|
||||
M.hallucination = min(max(0, M.hallucination + 5), 60)
|
||||
M.adjustToxLoss(5 * REM, 0)
|
||||
M.adjustToxLoss(8 * REM, 0, TRUE) //Hurts TOXINLOVERS
|
||||
..()
|
||||
. = 1
|
||||
|
||||
@@ -1188,11 +1196,11 @@
|
||||
color = "#C8A5DC"
|
||||
metabolization_rate = 1
|
||||
|
||||
/datum/reagent/medicine/changelinghaste/on_mob_add(mob/living/L)
|
||||
/datum/reagent/medicine/changelinghaste/on_mob_metabolize(mob/living/L)
|
||||
..()
|
||||
ADD_TRAIT(L, TRAIT_GOTTAGOREALLYFAST, id)
|
||||
|
||||
/datum/reagent/medicine/changelinghaste/on_mob_delete(mob/living/L)
|
||||
/datum/reagent/medicine/changelinghaste/on_mob_end_metabolize(mob/living/L)
|
||||
REMOVE_TRAIT(L, TRAIT_GOTTAGOREALLYFAST, id)
|
||||
..()
|
||||
|
||||
@@ -1210,11 +1218,11 @@
|
||||
color = "#F5F5F5"
|
||||
self_consuming = TRUE
|
||||
|
||||
/datum/reagent/medicine/corazone/on_mob_add(mob/living/M)
|
||||
/datum/reagent/medicine/corazone/on_mob_metabolize(mob/living/M)
|
||||
..()
|
||||
ADD_TRAIT(M, TRAIT_STABLEHEART, id)
|
||||
|
||||
/datum/reagent/medicine/corazone/on_mob_delete(mob/living/M)
|
||||
/datum/reagent/medicine/corazone/on_mob_end_metabolize(mob/living/M)
|
||||
REMOVE_TRAIT(M, TRAIT_STABLEHEART, id)
|
||||
..()
|
||||
|
||||
@@ -1223,11 +1231,11 @@
|
||||
id = "muscle_stimulant"
|
||||
description = "A potent chemical that allows someone under its influence to be at full physical ability even when under massive amounts of pain."
|
||||
|
||||
/datum/reagent/medicine/muscle_stimulant/on_mob_add(mob/living/M)
|
||||
/datum/reagent/medicine/muscle_stimulant/on_mob_metabolize(mob/living/M)
|
||||
. = ..()
|
||||
M.ignore_slowdown(id)
|
||||
|
||||
/datum/reagent/medicine/muscle_stimulant/on_mob_delete(mob/living/M)
|
||||
/datum/reagent/medicine/muscle_stimulant/on_mob_end_metabolize(mob/living/M)
|
||||
. = ..()
|
||||
M.unignore_slowdown(id)
|
||||
|
||||
@@ -1242,11 +1250,11 @@
|
||||
taste_description = "salt" // it actually does taste salty
|
||||
var/overdose_progress = 0 // to track overdose progress
|
||||
|
||||
/datum/reagent/medicine/modafinil/on_mob_add(mob/living/M)
|
||||
/datum/reagent/medicine/modafinil/on_mob_metabolize(mob/living/M)
|
||||
ADD_TRAIT(M, TRAIT_SLEEPIMMUNE, id)
|
||||
..()
|
||||
|
||||
/datum/reagent/medicine/modafinil/on_mob_delete(mob/living/M)
|
||||
/datum/reagent/medicine/modafinil/on_mob_end_metabolize(mob/living/M)
|
||||
REMOVE_TRAIT(M, TRAIT_SLEEPIMMUNE, id)
|
||||
..()
|
||||
|
||||
|
||||
@@ -196,11 +196,11 @@
|
||||
glass_name = "glass of holy water"
|
||||
glass_desc = "A glass of holy water."
|
||||
|
||||
/datum/reagent/water/holywater/on_mob_add(mob/living/L)
|
||||
/datum/reagent/water/holywater/on_mob_metabolize(mob/living/L)
|
||||
..()
|
||||
ADD_TRAIT(L, TRAIT_HOLY, id)
|
||||
|
||||
/datum/reagent/water/holywater/on_mob_delete(mob/living/L)
|
||||
/datum/reagent/water/holywater/on_mob_end_metabolize(mob/living/L)
|
||||
REMOVE_TRAIT(L, TRAIT_HOLY, id)
|
||||
..()
|
||||
|
||||
@@ -1241,12 +1241,12 @@
|
||||
color = "E1A116"
|
||||
taste_description = "sourness"
|
||||
|
||||
/datum/reagent/stimulum/on_mob_add(mob/living/L)
|
||||
/datum/reagent/stimulum/on_mob_metabolize(mob/living/L)
|
||||
..()
|
||||
ADD_TRAIT(L, TRAIT_STUNIMMUNE, id)
|
||||
ADD_TRAIT(L, TRAIT_SLEEPIMMUNE, id)
|
||||
|
||||
/datum/reagent/stimulum/on_mob_delete(mob/living/L)
|
||||
/datum/reagent/stimulum/on_mob_end_metabolize(mob/living/L)
|
||||
REMOVE_TRAIT(L, TRAIT_STUNIMMUNE, id)
|
||||
REMOVE_TRAIT(L, TRAIT_SLEEPIMMUNE, id)
|
||||
..()
|
||||
@@ -1266,11 +1266,11 @@
|
||||
color = "90560B"
|
||||
taste_description = "burning"
|
||||
|
||||
/datum/reagent/nitryl/on_mob_add(mob/living/L)
|
||||
/datum/reagent/nitryl/on_mob_metabolize(mob/living/L)
|
||||
..()
|
||||
ADD_TRAIT(L, TRAIT_GOTTAGOFAST, id)
|
||||
|
||||
/datum/reagent/nitryl/on_mob_delete(mob/living/L)
|
||||
/datum/reagent/nitryl/on_mob_end_metabolize(mob/living/L)
|
||||
REMOVE_TRAIT(L, TRAIT_GOTTAGOFAST, id)
|
||||
..()
|
||||
|
||||
@@ -1723,7 +1723,7 @@
|
||||
H.update_transform()
|
||||
..()
|
||||
|
||||
/datum/reagent/growthserum/on_mob_delete(mob/living/M)
|
||||
/datum/reagent/growthserum/on_mob_end_metabolize(mob/living/M)
|
||||
M.resize = 1/current_size
|
||||
M.update_transform()
|
||||
..()
|
||||
@@ -1777,11 +1777,11 @@
|
||||
taste_description = "water"
|
||||
metabolization_rate = 0.25 * REAGENTS_METABOLISM
|
||||
|
||||
/datum/reagent/pax/on_mob_add(mob/living/L)
|
||||
/datum/reagent/pax/on_mob_metabolize(mob/living/L)
|
||||
..()
|
||||
ADD_TRAIT(L, TRAIT_PACIFISM, id)
|
||||
|
||||
/datum/reagent/pax/on_mob_delete(mob/living/L)
|
||||
/datum/reagent/pax/on_mob_end_metabolize(mob/living/L)
|
||||
REMOVE_TRAIT(L, TRAIT_PACIFISM, id)
|
||||
..()
|
||||
|
||||
@@ -1793,11 +1793,11 @@
|
||||
taste_description = "acrid cinnamon"
|
||||
metabolization_rate = 0.2 * REAGENTS_METABOLISM
|
||||
|
||||
/datum/reagent/bz_metabolites/on_mob_add(mob/living/L)
|
||||
/datum/reagent/bz_metabolites/on_mob_metabolize(mob/living/L)
|
||||
..()
|
||||
ADD_TRAIT(L, CHANGELING_HIVEMIND_MUTE, id)
|
||||
|
||||
/datum/reagent/bz_metabolites/on_mob_delete(mob/living/L)
|
||||
/datum/reagent/bz_metabolites/on_mob_end_metabolize(mob/living/L)
|
||||
..()
|
||||
REMOVE_TRAIT(L, CHANGELING_HIVEMIND_MUTE, id)
|
||||
|
||||
@@ -1814,14 +1814,14 @@
|
||||
description = "A colorless liquid that suppresses violence on the subjects. Cheaper to synthetize, but wears out faster than normal Pax."
|
||||
metabolization_rate = 1.5 * REAGENTS_METABOLISM
|
||||
|
||||
/datum/reagent/peaceborg/confuse
|
||||
/datum/reagent/peaceborg_confuse
|
||||
name = "Dizzying Solution"
|
||||
id = "dizzysolution"
|
||||
description = "Makes the target off balance and dizzy"
|
||||
metabolization_rate = 1.5 * REAGENTS_METABOLISM
|
||||
taste_description = "dizziness"
|
||||
|
||||
/datum/reagent/peaceborg/confuse/on_mob_life(mob/living/carbon/M)
|
||||
/datum/reagent/peaceborg_confuse/on_mob_life(mob/living/carbon/M)
|
||||
if(M.confused < 6)
|
||||
M.confused = CLAMP(M.confused + 3, 0, 5)
|
||||
if(M.dizziness < 6)
|
||||
@@ -1830,14 +1830,14 @@
|
||||
to_chat(M, "You feel confused and disorientated.")
|
||||
..()
|
||||
|
||||
/datum/reagent/peaceborg/tire
|
||||
/datum/reagent/peaceborg_tire
|
||||
name = "Tiring Solution"
|
||||
id = "tiresolution"
|
||||
description = "An extremely weak stamina-toxin that tires out the target. Completely harmless."
|
||||
metabolization_rate = 1.5 * REAGENTS_METABOLISM
|
||||
taste_description = "tiredness"
|
||||
|
||||
/datum/reagent/peaceborg/tire/on_mob_life(mob/living/carbon/M)
|
||||
/datum/reagent/peaceborg_tire/on_mob_life(mob/living/carbon/M)
|
||||
var/healthcomp = (100 - M.health) //DOES NOT ACCOUNT FOR ADMINBUS THINGS THAT MAKE YOU HAVE MORE THAN 200/210 HEALTH, OR SOMETHING OTHER THAN A HUMAN PROCESSING THIS.
|
||||
if(M.getStaminaLoss() < (45 - healthcomp)) //At 50 health you would have 200 - 150 health meaning 50 compensation. 60 - 50 = 10, so would only do 10-19 stamina.)
|
||||
M.adjustStaminaLoss(10)
|
||||
|
||||
@@ -156,11 +156,11 @@
|
||||
toxpwr = 0.5
|
||||
taste_description = "death"
|
||||
|
||||
/datum/reagent/toxin/zombiepowder/on_mob_add(mob/living/L)
|
||||
/datum/reagent/toxin/zombiepowder/on_mob_metabolize(mob/living/L)
|
||||
..()
|
||||
L.fakedeath(id)
|
||||
|
||||
/datum/reagent/toxin/zombiepowder/on_mob_delete(mob/living/L)
|
||||
/datum/reagent/toxin/zombiepowder/on_mob_end_metabolize(mob/living/L)
|
||||
L.cure_fakedeath(id)
|
||||
..()
|
||||
|
||||
@@ -178,11 +178,11 @@
|
||||
toxpwr = 0.8
|
||||
taste_description = "death"
|
||||
|
||||
/datum/reagent/toxin/ghoulpowder/on_mob_add(mob/living/L)
|
||||
/datum/reagent/toxin/ghoulpowder/on_mob_metabolize(mob/living/L)
|
||||
..()
|
||||
ADD_TRAIT(L, TRAIT_FAKEDEATH, id)
|
||||
|
||||
/datum/reagent/toxin/ghoulpowder/on_mob_delete(mob/living/L)
|
||||
/datum/reagent/toxin/ghoulpowder/on_mob_end_metabolize(mob/living/L)
|
||||
REMOVE_TRAIT(L, TRAIT_FAKEDEATH, id)
|
||||
..()
|
||||
|
||||
@@ -626,7 +626,7 @@
|
||||
toxpwr = 0
|
||||
metabolization_rate = 0.5 * REAGENTS_METABOLISM
|
||||
|
||||
/datum/reagent/toxin/amanitin/on_mob_delete(mob/living/M)
|
||||
/datum/reagent/toxin/amanitin/on_mob_end_metabolize(mob/living/M)
|
||||
var/toxdamage = current_cycle*3*REM
|
||||
M.log_message("has taken [toxdamage] toxin damage from amanitin toxin", LOG_ATTACK)
|
||||
M.adjustToxLoss(toxdamage)
|
||||
@@ -742,7 +742,7 @@
|
||||
animate(transform = matrix(-rotation, MATRIX_ROTATE), time = 5, easing = QUAD_EASING)
|
||||
return ..()
|
||||
|
||||
/datum/reagent/toxin/rotatium/on_mob_delete(mob/living/M)
|
||||
/datum/reagent/toxin/rotatium/on_mob_end_metabolize(mob/living/M)
|
||||
if(M && M.hud_used)
|
||||
var/list/screens = list(M.hud_used.plane_masters["[FLOOR_PLANE]"], M.hud_used.plane_masters["[GAME_PLANE]"], M.hud_used.plane_masters["[LIGHTING_PLANE]"])
|
||||
for(var/whole_screen in screens)
|
||||
@@ -779,7 +779,7 @@
|
||||
*/
|
||||
return ..()
|
||||
|
||||
/datum/reagent/toxin/skewium/on_mob_delete(mob/living/M)
|
||||
/datum/reagent/toxin/skewium/on_mob_end_metabolize(mob/living/M)
|
||||
if(M && M.hud_used)
|
||||
var/list/screens = list(M.hud_used.plane_masters["[FLOOR_PLANE]"], M.hud_used.plane_masters["[GAME_PLANE]"], M.hud_used.plane_masters["[LIGHTING_PLANE]"])
|
||||
for(var/whole_screen in screens)
|
||||
@@ -798,7 +798,7 @@
|
||||
|
||||
/datum/reagent/toxin/anacea/on_mob_life(mob/living/carbon/M)
|
||||
var/remove_amt = 5
|
||||
if(holder.has_reagent("calomel") || holder.has_reagent("pen_acid"))
|
||||
if(holder.has_reagent("calomel") || holder.has_reagent("pen_acid") || holder.has_reagent("pen_jelly"))
|
||||
remove_amt = 0.5
|
||||
for(var/datum/reagent/medicine/R in M.reagents.reagent_list)
|
||||
M.reagents.remove_reagent(R.id,remove_amt)
|
||||
@@ -882,8 +882,8 @@
|
||||
toxpwr = 0
|
||||
taste_description = "stillness"
|
||||
|
||||
/datum/reagent/toxin/mimesbane/on_mob_add(mob/living/L)
|
||||
/datum/reagent/toxin/mimesbane/on_mob_metabolize(mob/living/L)
|
||||
ADD_TRAIT(L, TRAIT_EMOTEMUTE, id)
|
||||
|
||||
/datum/reagent/toxin/mimesbane/on_mob_delete(mob/living/L)
|
||||
/datum/reagent/toxin/mimesbane/on_mob_end_metabolize(mob/living/L)
|
||||
REMOVE_TRAIT(L, TRAIT_EMOTEMUTE, id)
|
||||
|
||||
@@ -94,6 +94,12 @@
|
||||
results = list("pen_acid" = 6)
|
||||
required_reagents = list("welding_fuel" = 1, "chlorine" = 1, "ammonia" = 1, "formaldehyde" = 1, "sodium" = 1, "cyanide" = 1)
|
||||
|
||||
/datum/chemical_reaction/pen_jelly
|
||||
name = "Pentetic Jelly"
|
||||
id = "pen_jelly"
|
||||
results = list("pen_jelly" = 2)
|
||||
required_reagents = list("pen_acid" = 1, "slimejelly" = 1)
|
||||
|
||||
/datum/chemical_reaction/sal_acid
|
||||
name = "Salicyclic Acid"
|
||||
id = "sal_acid"
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
GLOBAL_LIST_INIT(food_reagents, build_reagents_to_food()) //reagentid = related food types
|
||||
|
||||
/proc/build_reagents_to_food()
|
||||
. = list()
|
||||
for (var/type in subtypesof(/obj/item/reagent_containers/food))
|
||||
var/obj/item/reagent_containers/food/item = new type()
|
||||
for(var/r in item.list_reagents)
|
||||
if (!.[r])
|
||||
.[r] = list()
|
||||
.[r] += type
|
||||
qdel(item)
|
||||
//dang plant snowflake
|
||||
for (var/type in subtypesof(/obj/item/seeds))
|
||||
var/obj/item/seeds/item = new type()
|
||||
for(var/r in item.reagents_add)
|
||||
if (!.[r])
|
||||
.[r] = list()
|
||||
.[r] += type
|
||||
qdel(item)
|
||||
|
||||
|
||||
#define RNGCHEM_INPUT "input"
|
||||
#define RNGCHEM_CATALYSTS "catalysts"
|
||||
#define RNGCHEM_OUTPUT "output"
|
||||
|
||||
/datum/chemical_reaction/randomized
|
||||
name = "semi randomized reaction"
|
||||
|
||||
var/persistent = FALSE
|
||||
var/persistence_period = 7 //Will reset every x days
|
||||
var/created //creation timestamp
|
||||
|
||||
var/randomize_container = FALSE
|
||||
var/list/possible_containers = list()
|
||||
|
||||
var/randomize_req_temperature = TRUE
|
||||
var/min_temp = 1
|
||||
var/max_temp = 600
|
||||
|
||||
var/randomize_inputs = TRUE
|
||||
var/min_input_reagent_amount = 1
|
||||
var/max_input_reagent_amount = 10
|
||||
var/min_input_reagents = 2
|
||||
var/max_input_reagents = 5
|
||||
var/list/possible_reagents = list()
|
||||
var/min_catalysts = 0
|
||||
var/max_catalysts = 2
|
||||
var/list/possible_catalysts = list()
|
||||
|
||||
var/randomize_results = FALSE
|
||||
var/min_output_reagent_amount = 1
|
||||
var/max_output_reagent_amount = 5
|
||||
var/min_result_reagents = 1
|
||||
var/max_result_reagents = 1
|
||||
var/list/possible_results = list()
|
||||
|
||||
/datum/chemical_reaction/randomized/proc/GenerateRecipe()
|
||||
created = world.time
|
||||
if(randomize_container)
|
||||
required_container = pick(possible_containers)
|
||||
if(randomize_req_temperature)
|
||||
required_temp = rand(min_temp,max_temp)
|
||||
is_cold_recipe = pick(TRUE,FALSE)
|
||||
|
||||
if(randomize_results)
|
||||
results = list()
|
||||
var/list/remaining_possible_results = GetPossibleReagents(RNGCHEM_OUTPUT)
|
||||
var/out_reagent_count = min(rand(min_result_reagents,max_result_reagents),remaining_possible_results.len)
|
||||
for(var/i in 1 to out_reagent_count)
|
||||
var/r_id = pick_n_take(remaining_possible_results)
|
||||
results[r_id] = rand(min_output_reagent_amount,max_output_reagent_amount)
|
||||
|
||||
if(randomize_inputs)
|
||||
var/list/remaining_possible_reagents = GetPossibleReagents(RNGCHEM_INPUT)
|
||||
var/list/remaining_possible_catalysts = GetPossibleReagents(RNGCHEM_CATALYSTS)
|
||||
|
||||
//We're going to assume we're not doing any weird partial reactions for now.
|
||||
for(var/reagent_type in results)
|
||||
remaining_possible_catalysts -= reagent_type
|
||||
remaining_possible_reagents -= reagent_type
|
||||
|
||||
var/in_reagent_count = min(rand(min_input_reagents,max_input_reagents),remaining_possible_reagents.len)
|
||||
if(in_reagent_count <= 0)
|
||||
return FALSE
|
||||
|
||||
required_reagents = list()
|
||||
for(var/i in 1 to in_reagent_count)
|
||||
var/r_id = pick_n_take(remaining_possible_reagents)
|
||||
required_reagents[r_id] = rand(min_input_reagent_amount,max_input_reagent_amount)
|
||||
remaining_possible_catalysts -= r_id //Can't have same reagents both as catalyst and reagent. Or can we ?
|
||||
|
||||
required_catalysts = list()
|
||||
var/in_catalyst_count = min(rand(min_catalysts,max_catalysts),remaining_possible_catalysts.len)
|
||||
for(var/i in 1 to in_catalyst_count)
|
||||
var/r_id = pick_n_take(remaining_possible_catalysts)
|
||||
required_catalysts[r_id] = rand(min_input_reagent_amount,max_input_reagent_amount)
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/chemical_reaction/randomized/proc/GetPossibleReagents(kind)
|
||||
switch(kind)
|
||||
if(RNGCHEM_INPUT)
|
||||
return possible_reagents.Copy()
|
||||
if(RNGCHEM_CATALYSTS)
|
||||
return possible_catalysts.Copy()
|
||||
if(RNGCHEM_OUTPUT)
|
||||
return possible_results.Copy()
|
||||
|
||||
/datum/chemical_reaction/randomized/proc/HasConflicts()
|
||||
for(var/x in required_reagents)
|
||||
for(var/datum/chemical_reaction/R in GLOB.chemical_reactions_list[x])
|
||||
if(chem_recipes_do_conflict(R,src))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/chemical_reaction/randomized/proc/unwrap_reagent_list(list/textreagents)
|
||||
. = list()
|
||||
for(var/R in textreagents)
|
||||
var/pathR = text2path(R)
|
||||
if(!pathR)
|
||||
return null
|
||||
.[pathR] = textreagents[R]
|
||||
|
||||
/datum/chemical_reaction/randomized/proc/LoadOldRecipe(recipe_data)
|
||||
created = text2num(recipe_data["timestamp"])
|
||||
|
||||
var/req_reag = unwrap_reagent_list(recipe_data["required_reagents"])
|
||||
if(!req_reag)
|
||||
return FALSE
|
||||
required_reagents = req_reag
|
||||
|
||||
var/req_catalysts = unwrap_reagent_list(recipe_data["required_catalysts"])
|
||||
if(!req_catalysts)
|
||||
return FALSE
|
||||
required_catalysts = req_catalysts
|
||||
|
||||
required_temp = recipe_data["required_temp"]
|
||||
is_cold_recipe = recipe_data["is_cold_recipe"]
|
||||
|
||||
var/temp_results = unwrap_reagent_list(recipe_data["results"])
|
||||
if(!temp_results)
|
||||
return FALSE
|
||||
results = temp_results
|
||||
var/containerpath = text2path(recipe_data["required_container"])
|
||||
if(!containerpath)
|
||||
return FALSE
|
||||
required_container = containerpath
|
||||
return TRUE
|
||||
|
||||
/datum/chemical_reaction/randomized/secret_sauce
|
||||
name = "secret sauce creation"
|
||||
id = "secretsauce"
|
||||
persistent = TRUE
|
||||
persistence_period = 7 //Reset every week
|
||||
randomize_container = TRUE
|
||||
possible_containers = list(/obj/item/reagent_containers/glass/bucket) //easy way to ensure no common conflicts
|
||||
randomize_req_temperature = TRUE
|
||||
results = list("secret_sauce" =1)
|
||||
|
||||
/datum/chemical_reaction/randomized/secret_sauce/GetPossibleReagents(kind)
|
||||
switch(kind)
|
||||
if(RNGCHEM_INPUT,RNGCHEM_CATALYSTS)
|
||||
var/food_reagent_ids = list()
|
||||
for(var/key in GLOB.food_reagents)
|
||||
food_reagent_ids += key
|
||||
return food_reagent_ids
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/item/paper/secretrecipe
|
||||
name = "old recipe"
|
||||
var/recipe_id = "secretsauce"
|
||||
|
||||
/obj/item/paper/secretrecipe/examine(mob/user) //Extra secret
|
||||
if(isobserver(user))
|
||||
return
|
||||
. = ..()
|
||||
|
||||
/obj/item/paper/secretrecipe/Initialize()
|
||||
. = ..()
|
||||
if(SSpersistence.initialized)
|
||||
UpdateInfo()
|
||||
else
|
||||
SSticker.OnRoundstart(CALLBACK(src,.proc/UpdateInfo))
|
||||
|
||||
/obj/item/paper/secretrecipe/proc/UpdateInfo()
|
||||
var/datum/chemical_reaction/recipe = get_chemical_reaction(recipe_id)
|
||||
if(!recipe)
|
||||
info = "This recipe is illegible."
|
||||
var/list/dat = list("<ul>")
|
||||
for(var/rid in recipe.required_reagents)
|
||||
var/datum/reagent/R = GLOB.chemical_reagents_list[rid]
|
||||
dat += "<li>[recipe.required_reagents[rid]]u of [R.name]</li>"
|
||||
dat += "</ul>"
|
||||
if(recipe.required_catalysts.len)
|
||||
dat += "With following present: <ul>"
|
||||
for(var/rid in recipe.required_catalysts)
|
||||
var/datum/reagent/R = GLOB.chemical_reagents_list[rid]
|
||||
dat += "<li>[recipe.required_catalysts[rid]]u of [R.name]</li>"
|
||||
dat += "</ul>"
|
||||
dat += "Mix slowly"
|
||||
if(recipe.required_container)
|
||||
var/obj/item/I = recipe.required_container
|
||||
dat += " in [initial(I.name)]"
|
||||
if(recipe.required_temp != 0)
|
||||
if(recipe.is_cold_recipe)
|
||||
dat += " below [recipe.required_temp] degrees"
|
||||
else
|
||||
dat += " above [recipe.required_temp] degrees"
|
||||
dat += "."
|
||||
info = dat.Join("")
|
||||
update_icon()
|
||||
@@ -259,3 +259,92 @@
|
||||
|
||||
/obj/item/reagent_containers/syringe/get_belt_overlay()
|
||||
return mutable_appearance('icons/obj/clothing/belt_overlays.dmi', "pouch")
|
||||
|
||||
/obj/item/reagent_containers/syringe/dart
|
||||
name = "medicinal smartdart"
|
||||
desc = "A non-harmful dart that can administer medication from a range. Once it hits a patient using it's smart nanofilter technology only medicines contained within the dart are administered to the patient. Additonally, due to capillary action, injection of chemicals past the overdose limit is prevented."
|
||||
volume = 20
|
||||
amount_per_transfer_from_this = 20
|
||||
icon_state = "empty"
|
||||
item_state = "syringe_empty"
|
||||
var/emptrig = FALSE
|
||||
|
||||
/obj/item/reagent_containers/syringe/dart/afterattack(atom/target, mob/user , proximity)
|
||||
|
||||
if(busy)
|
||||
return
|
||||
if(!proximity)
|
||||
return
|
||||
if(!target.reagents)
|
||||
return
|
||||
|
||||
var/mob/living/L
|
||||
if(isliving(target))
|
||||
L = target
|
||||
if(!L.can_inject(user, 1))
|
||||
return
|
||||
|
||||
switch(mode)
|
||||
if(SYRINGE_DRAW)
|
||||
|
||||
if(reagents.total_volume >= reagents.maximum_volume)
|
||||
to_chat(user, "<span class='notice'>The dart is full!</span>")
|
||||
return
|
||||
|
||||
if(L) //living mob
|
||||
to_chat(user, "<span class='warning'>You can't draw blood using a dart!</span>")
|
||||
return
|
||||
|
||||
else //if not mob
|
||||
if(!target.reagents.total_volume)
|
||||
to_chat(user, "<span class='warning'>[target] is empty!</span>")
|
||||
return
|
||||
|
||||
if(!target.is_drawable())
|
||||
to_chat(user, "<span class='warning'>You cannot directly remove reagents from [target]!</span>")
|
||||
return
|
||||
|
||||
var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this)
|
||||
|
||||
to_chat(user, "<span class='notice'>You soak the [src] with [trans] units of the solution. It now contains [reagents.total_volume] units.</span>")
|
||||
if (reagents.total_volume >= reagents.maximum_volume)
|
||||
mode=!mode
|
||||
update_icon()
|
||||
|
||||
if(SYRINGE_INJECT)
|
||||
src.visible_message("<span class='danger'>The smartdart gives a frustrated boop! It's fully saturated; You need to shoot someone with it!</span>")
|
||||
|
||||
/obj/item/reagent_containers/syringe/dart/attack_self(mob/user)
|
||||
return
|
||||
|
||||
/obj/item/reagent_containers/syringe/dart/update_icon()
|
||||
cut_overlays()
|
||||
var/rounded_vol
|
||||
|
||||
rounded_vol = "empty"
|
||||
if(reagents && reagents.total_volume)
|
||||
if(volume/reagents.total_volume == 1)
|
||||
rounded_vol="full"
|
||||
|
||||
icon_state = "[rounded_vol]"
|
||||
item_state = "syringe_[rounded_vol]"
|
||||
if(ismob(loc))
|
||||
var/mob/M = loc
|
||||
var/injoverlay
|
||||
switch(mode)
|
||||
if (SYRINGE_DRAW)
|
||||
injoverlay = "draw"
|
||||
if (SYRINGE_INJECT)
|
||||
injoverlay = "ready"
|
||||
add_overlay(injoverlay)
|
||||
M.update_inv_hands()
|
||||
|
||||
/obj/item/reagent_containers/syringe/dart/emp_act(severity)
|
||||
emptrig = TRUE
|
||||
..()
|
||||
|
||||
/obj/item/reagent_containers/syringe/dart/bluespace
|
||||
name = "bluespace smartdart"
|
||||
desc = "A non-harmful dart that can administer medication from a range. Once it hits a patient using it's smart nanofilter technology only medicines contained within the dart are administered to the patient. Additonally, due to capillary action, injection of chemicals past the overdose limit is prevented. Has an extended volume capacity thanks to bluespace foam."
|
||||
amount_per_transfer_from_this = 50
|
||||
volume = 50
|
||||
|
||||
@@ -92,6 +92,36 @@
|
||||
category = list("Medical Designs")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
|
||||
|
||||
/datum/design/medicinalsmartdart
|
||||
name = "Medicinal Smartdart"
|
||||
desc = "A non-harmful dart that can administer medication from a range. Once it hits a patient using it's smart nanofilter technology only medicines contained within the dart are administered to the patient. Additonally, due to capillary action, injection of chemicals past the overdose limit is prevented."
|
||||
id = "medicinalsmartdart"
|
||||
build_type = PROTOLATHE
|
||||
materials = list(MAT_GLASS = 100, MAT_PLASTIC = 100, MAT_METAL = 100)
|
||||
build_path = /obj/item/reagent_containers/syringe/dart
|
||||
category = list("Medical Designs")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
|
||||
|
||||
/datum/design/bluespacesmartdart
|
||||
name = "bluespace smartdart"
|
||||
desc = "A non-harmful dart that can administer medication from a range. Once it hits a patient using it's smart nanofilter technology only medicines contained within the dart are administered to the patient. Additonally, due to capillary action, injection of chemicals past the overdose limit is prevented. Has an extended volume capacity thanks to bluespace foam."
|
||||
id = "bluespacesmartdart"
|
||||
build_type = PROTOLATHE
|
||||
materials = list(MAT_GLASS = 250, MAT_PLASTIC = 250, MAT_METAL = 250, MAT_BLUESPACE = 250)
|
||||
build_path = /obj/item/reagent_containers/syringe/dart/bluespace
|
||||
category = list("Medical Designs")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
|
||||
|
||||
/datum/design/smartdartgun
|
||||
name = "dart gun"
|
||||
desc = "A compressed air gun, designed to fit medicinal darts for application of medicine for those patients just out of reach."
|
||||
id = "smartdartgun"
|
||||
build_type = PROTOLATHE
|
||||
materials = list(MAT_GLASS = 500, MAT_PLASTIC = 1000, MAT_METAL = 500)
|
||||
build_path = /obj/item/gun/syringe/dart
|
||||
category = list("Medical Designs")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
|
||||
|
||||
/datum/design/bluespacebodybag
|
||||
name = "Bluespace Body Bag"
|
||||
desc = "A bluespace body bag, powered by experimental bluespace technology. It can hold loads of bodies and the largest of creatures."
|
||||
@@ -172,6 +202,16 @@
|
||||
category = list("Medical Designs")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
|
||||
|
||||
/datum/design/organbox
|
||||
name = "Empty Organ Box"
|
||||
desc = "A large cool box that can hold large amouts of medical tools or organs."
|
||||
id = "organbox"
|
||||
build_type = PROTOLATHE
|
||||
materials = list(MAT_METAL = 3000, MAT_GLASS = 1000, MAT_SILVER= 3500, MAT_GOLD = 3500, MAT_PLASTIC = 5000)
|
||||
build_path = /obj/item/storage/belt/organbox
|
||||
category = list("Medical Designs")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
|
||||
|
||||
////////////////////////////////////////
|
||||
//////////Defibrillator Tech////////////
|
||||
////////////////////////////////////////
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
deactivate()
|
||||
if(passive_enabled)
|
||||
disable_passive_effect()
|
||||
on_mob_remove()
|
||||
if(nanites)
|
||||
nanites.programs -= src
|
||||
return ..()
|
||||
@@ -107,6 +108,9 @@
|
||||
if(activated) //apply activation effects if it starts active
|
||||
activate()
|
||||
|
||||
datum/nanite_program/proc/on_mob_remove()
|
||||
return
|
||||
|
||||
/datum/nanite_program/proc/toggle()
|
||||
if(!activated)
|
||||
activate()
|
||||
@@ -115,6 +119,7 @@
|
||||
|
||||
/datum/nanite_program/proc/activate()
|
||||
activated = TRUE
|
||||
timer_counter = activation_delay
|
||||
|
||||
/datum/nanite_program/proc/deactivate()
|
||||
if(passive_enabled)
|
||||
@@ -135,8 +140,10 @@
|
||||
if(timer && timer_counter > timer)
|
||||
if(timer_type == NANITE_TIMER_DEACTIVATE)
|
||||
deactivate()
|
||||
return
|
||||
else if(timer_type == NANITE_TIMER_SELFDELETE)
|
||||
qdel(src)
|
||||
return
|
||||
else if(can_trigger && timer_type == NANITE_TIMER_TRIGGER)
|
||||
trigger()
|
||||
timer_counter = activation_delay
|
||||
@@ -251,4 +258,3 @@
|
||||
return "Trigger"
|
||||
if(NANITE_TIMER_RESET)
|
||||
return "Reset Activation Timer"
|
||||
|
||||
|
||||
@@ -237,7 +237,11 @@
|
||||
if(prob(10))
|
||||
var/list/mob/living/target_hosts = list()
|
||||
for(var/mob/living/L in oview(5, host_mob))
|
||||
if(!(MOB_ORGANIC in L.mob_biotypes) && !(MOB_UNDEAD in L.mob_biotypes))
|
||||
continue
|
||||
target_hosts += L
|
||||
if(!target_hosts.len)
|
||||
return
|
||||
var/mob/living/infectee = pick(target_hosts)
|
||||
if(prob(100 - (infectee.get_permeability_protection() * 100)))
|
||||
//this will potentially take over existing nanites!
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
display_name = "Advanced Biotechnology"
|
||||
description = "Advanced Biotechnology"
|
||||
prereq_ids = list("biotech")
|
||||
design_ids = list("piercesyringe", "crewpinpointer", "smoke_machine", "plasmarefiller", "limbgrower", "defibrillator", "meta_beaker", "healthanalyzer_advanced","harvester","holobarrier_med")
|
||||
design_ids = list("piercesyringe", "crewpinpointer", "smoke_machine", "plasmarefiller", "limbgrower", "defibrillator", "meta_beaker", "healthanalyzer_advanced","harvester","holobarrier_med","smartdartgun","medicinalsmartdart")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
|
||||
export_price = 5000
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
display_name = "Advanced Surgery"
|
||||
description = "When simple medicine doesn't cut it."
|
||||
prereq_ids = list("adv_biotech")
|
||||
design_ids = list("surgery_lobotomy", "surgery_reconstruction")
|
||||
design_ids = list("surgery_lobotomy", "surgery_reconstruction", "organbox")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
|
||||
export_price = 5000
|
||||
|
||||
@@ -255,7 +255,7 @@
|
||||
display_name = "Applied Bluespace Research"
|
||||
description = "Using bluespace to make things faster and better."
|
||||
prereq_ids = list("bluespace_basic", "engineering")
|
||||
design_ids = list("bs_rped","biobag_holding","minerbag_holding", "bluespacebeaker", "bluespacesyringe", "phasic_scanning", "roastingstick", "ore_silo", "xenobio_slimeadv")
|
||||
design_ids = list("bs_rped","biobag_holding","minerbag_holding", "bluespacebeaker", "bluespacesyringe", "phasic_scanning", "roastingstick", "ore_silo", "bluespacesmartdart", "xenobio_slimeadv")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 7500)
|
||||
export_price = 5000
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
icon_state = "datadisk1"
|
||||
max_blueprints = 1
|
||||
|
||||
/obj/item/disk/design_disk/golem_shell/Initialize()
|
||||
/obj/item/disk/design_disk/plant_disk/Initialize()
|
||||
. = ..()
|
||||
var/datum/design/diskplantgene/P = new
|
||||
blueprints[1] = P
|
||||
|
||||
@@ -146,11 +146,14 @@
|
||||
clothes_req = 0
|
||||
invocation = "none"
|
||||
invocation_type = "none"
|
||||
proj_type = /obj/effect/proc_holder/spell/targeted/inflict_handler/magic_missile/lesser
|
||||
proj_lifespan = 10
|
||||
max_targets = 6
|
||||
action_icon_state = "magicm"
|
||||
action_background_icon_state = "bg_demon"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/inflict_handler/magic_missile/lesser
|
||||
amt_knockdown = 84
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/smoke/disable
|
||||
name = "Paralysing Smoke"
|
||||
@@ -304,7 +307,8 @@
|
||||
name = "Gauntlet Echo"
|
||||
alpha = 180
|
||||
amt_dam_brute = 30
|
||||
amt_knockdown = 50
|
||||
amt_knockdown = 84
|
||||
amt_dam_stam = 30
|
||||
sound = 'sound/weapons/punch3.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/inflict_handler/juggernaut/cast(list/targets,mob/user = usr)
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
desc = "This spell blinds and/or destroys/damages/heals and/or knockdowns/stuns the target."
|
||||
|
||||
var/amt_knockdown = 0
|
||||
var/amt_hardstun
|
||||
var/amt_unconscious = 0
|
||||
var/amt_stun = 0
|
||||
|
||||
//set to negatives for healing
|
||||
var/amt_dam_stam
|
||||
var/amt_dam_fire = 0
|
||||
var/amt_dam_brute = 0
|
||||
var/amt_dam_oxy = 0
|
||||
@@ -41,7 +43,10 @@
|
||||
target.adjustToxLoss(amt_dam_tox)
|
||||
target.adjustOxyLoss(amt_dam_oxy)
|
||||
//disabling
|
||||
target.Knockdown(amt_knockdown)
|
||||
if(!amt_knockdown && amt_dam_stam)
|
||||
target.adjustStaminaLoss(amt_dam_stam)
|
||||
else
|
||||
target.Knockdown(amt_knockdown, override_hardstun = amt_hardstun, amt_dam_stam)
|
||||
target.Unconscious(amt_unconscious)
|
||||
target.Stun(amt_stun)
|
||||
|
||||
|
||||
@@ -28,7 +28,8 @@
|
||||
sound = 'sound/magic/magic_missile.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/inflict_handler/magic_missile
|
||||
amt_knockdown = 60
|
||||
amt_knockdown = 120
|
||||
amt_hardstun = 5
|
||||
sound = 'sound/magic/mm_hit.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/genetic/mutate
|
||||
@@ -262,7 +263,7 @@
|
||||
|
||||
action_icon_state = "repulse"
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/repulse/cast(list/targets,mob/user = usr, var/stun_amt = 40)
|
||||
/obj/effect/proc_holder/spell/aoe_turf/repulse/cast(list/targets,mob/user = usr, stun_amt = 50)
|
||||
var/list/thrownatoms = list()
|
||||
var/atom/throwtarget
|
||||
var/distfromcaster
|
||||
@@ -286,14 +287,14 @@
|
||||
if(distfromcaster == 0)
|
||||
if(isliving(AM))
|
||||
var/mob/living/M = AM
|
||||
M.Knockdown(100)
|
||||
M.Knockdown(100, override_hardstun = 20)
|
||||
M.adjustBruteLoss(5)
|
||||
to_chat(M, "<span class='userdanger'>You're slammed into the floor by [user]!</span>")
|
||||
else
|
||||
new sparkle_path(get_turf(AM), get_dir(user, AM)) //created sparkles will disappear on their own
|
||||
if(isliving(AM))
|
||||
var/mob/living/M = AM
|
||||
M.Knockdown(stun_amt)
|
||||
M.Knockdown(stun_amt, override_hardstun = stun_amt * 0.2)
|
||||
to_chat(M, "<span class='userdanger'>You're thrown back by [user]!</span>")
|
||||
AM.throw_at(throwtarget, ((CLAMP((maxthrow - (CLAMP(distfromcaster - 2, 0, distfromcaster))), 3, maxthrow))), 1,user)//So stuff gets tossed around at the same time.
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
var/held_index = 0 //are we a hand? if so, which one!
|
||||
var/is_pseudopart = FALSE //For limbs that don't really exist, eg chainsaws
|
||||
|
||||
var/disabled = FALSE //If TRUE, limb is as good as missing
|
||||
var/disabled = BODYPART_NOT_DISABLED //If disabled, limb is as good as missing
|
||||
var/body_damage_coeff = 1 //Multiplier of the limb's damage that gets applied to the mob
|
||||
var/stam_damage_coeff = 0.5
|
||||
var/brutestate = 0
|
||||
@@ -189,7 +189,7 @@
|
||||
if(stamina > DAMAGE_PRECISION)
|
||||
owner.update_stamina()
|
||||
consider_processing()
|
||||
check_disabled()
|
||||
update_disabled()
|
||||
return update_bodypart_damage_state()
|
||||
|
||||
//Heals brute and burn damage for the organ. Returns 1 if the damage-icon states changed at all.
|
||||
@@ -209,7 +209,7 @@
|
||||
if(owner && updating_health)
|
||||
owner.updatehealth()
|
||||
consider_processing()
|
||||
check_disabled()
|
||||
update_disabled()
|
||||
return update_bodypart_damage_state()
|
||||
|
||||
//Returns total damage.
|
||||
@@ -220,7 +220,24 @@
|
||||
return total
|
||||
|
||||
//Checks disabled status thresholds
|
||||
/obj/item/bodypart/proc/check_disabled()
|
||||
|
||||
//Checks disabled status thresholds
|
||||
/obj/item/bodypart/proc/update_disabled()
|
||||
set_disabled(is_disabled())
|
||||
|
||||
/obj/item/bodypart/proc/is_disabled()
|
||||
if(HAS_TRAIT(owner, TRAIT_PARALYSIS))
|
||||
return BODYPART_DISABLED_PARALYSIS
|
||||
if(can_dismember() && !HAS_TRAIT(owner, TRAIT_NODISMEMBER))
|
||||
. = disabled //inertia, to avoid limbs healing 0.1 damage and being re-enabled
|
||||
if((get_damage(TRUE) >= max_damage))
|
||||
return BODYPART_DISABLED_DAMAGE
|
||||
if(disabled && (get_damage(TRUE) <= (max_damage * 0.5)))
|
||||
return BODYPART_NOT_DISABLED
|
||||
else
|
||||
return BODYPART_NOT_DISABLED
|
||||
|
||||
/obj/item/bodypart/proc/check_disabled() //This might be depreciated and should be safe to remove.
|
||||
if(!can_dismember() || HAS_TRAIT(owner, TRAIT_NODISMEMBER))
|
||||
return
|
||||
if(!disabled && (get_damage(TRUE) >= max_damage))
|
||||
@@ -228,7 +245,8 @@
|
||||
else if(disabled && (get_damage(TRUE) <= (max_damage * 0.5)))
|
||||
set_disabled(FALSE)
|
||||
|
||||
/obj/item/bodypart/proc/set_disabled(new_disabled = TRUE)
|
||||
|
||||
/obj/item/bodypart/proc/set_disabled(new_disabled)
|
||||
if(disabled == new_disabled)
|
||||
return
|
||||
disabled = new_disabled
|
||||
@@ -546,6 +564,11 @@
|
||||
max_stamina_damage = 200
|
||||
var/obj/item/cavity_item
|
||||
|
||||
/obj/item/bodypart/chest/can_dismember(obj/item/I)
|
||||
if(!((owner.stat == DEAD) || owner.InFullCritical()))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/item/bodypart/chest/Destroy()
|
||||
if(cavity_item)
|
||||
qdel(cavity_item)
|
||||
@@ -601,13 +624,27 @@
|
||||
px_y = 0
|
||||
stam_heal_tick = 2
|
||||
|
||||
/obj/item/bodypart/l_arm/set_disabled(new_disabled = TRUE)
|
||||
..()
|
||||
if(disabled)
|
||||
to_chat(owner, "<span class='userdanger'>Your [name] is too damaged to function!</span>")
|
||||
owner.emote("scream")
|
||||
/obj/item/bodypart/l_arm/is_disabled()
|
||||
if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_ARM))
|
||||
return BODYPART_DISABLED_PARALYSIS
|
||||
return ..()
|
||||
|
||||
/obj/item/bodypart/l_arm/set_disabled(new_disabled)
|
||||
. = ..()
|
||||
if(disabled == new_disabled)
|
||||
return
|
||||
if(disabled == BODYPART_DISABLED_DAMAGE)
|
||||
if(owner.stat > UNCONSCIOUS)
|
||||
owner.emote("scream")
|
||||
if(. && (owner.stat > DEAD))
|
||||
to_chat(owner, "<span class='userdanger'>Your [name] is too damaged to function!</span>")
|
||||
if(held_index)
|
||||
owner.dropItemToGround(owner.get_item_for_held_index(held_index))
|
||||
else if(disabled == BODYPART_DISABLED_PARALYSIS)
|
||||
if(. && (owner.stat > DEAD))
|
||||
to_chat(owner, "<span class='userdanger'>You can't feel your [name]!</span>")
|
||||
if(held_index)
|
||||
owner.dropItemToGround(owner.get_item_for_held_index(held_index))
|
||||
if(owner.hud_used)
|
||||
var/obj/screen/inventory/hand/L = owner.hud_used.hand_slots["[held_index]"]
|
||||
if(L)
|
||||
@@ -652,18 +689,33 @@
|
||||
stam_heal_tick = 2
|
||||
max_stamina_damage = 50
|
||||
|
||||
/obj/item/bodypart/r_arm/set_disabled(new_disabled = TRUE)
|
||||
..()
|
||||
if(disabled)
|
||||
to_chat(owner, "<span class='userdanger'>Your [name] is too damaged to function!</span>")
|
||||
owner.emote("scream")
|
||||
/obj/item/bodypart/r_arm/is_disabled()
|
||||
if(HAS_TRAIT(owner, TRAIT_PARALYSIS_R_ARM))
|
||||
return BODYPART_DISABLED_PARALYSIS
|
||||
return ..()
|
||||
|
||||
/obj/item/bodypart/r_arm/set_disabled(new_disabled)
|
||||
. = ..()
|
||||
if(disabled == new_disabled)
|
||||
return
|
||||
if(disabled == BODYPART_DISABLED_DAMAGE)
|
||||
if(owner.stat > UNCONSCIOUS)
|
||||
owner.emote("scream")
|
||||
if(. && (owner.stat > DEAD))
|
||||
to_chat(owner, "<span class='userdanger'>Your [name] is too damaged to function!</span>")
|
||||
if(held_index)
|
||||
owner.dropItemToGround(owner.get_item_for_held_index(held_index))
|
||||
else if(disabled == BODYPART_DISABLED_PARALYSIS)
|
||||
if(. && (owner.stat > DEAD))
|
||||
to_chat(owner, "<span class='userdanger'>You can't feel your [name]!</span>")
|
||||
if(held_index)
|
||||
owner.dropItemToGround(owner.get_item_for_held_index(held_index))
|
||||
if(owner.hud_used)
|
||||
var/obj/screen/inventory/hand/R = owner.hud_used.hand_slots["[held_index]"]
|
||||
if(R)
|
||||
R.update_icon()
|
||||
|
||||
|
||||
/obj/item/bodypart/r_arm/monkey
|
||||
icon = 'icons/mob/animal_parts.dmi'
|
||||
icon_state = "default_monkey_r_arm"
|
||||
@@ -700,11 +752,24 @@
|
||||
stam_heal_tick = 2
|
||||
max_stamina_damage = 50
|
||||
|
||||
/obj/item/bodypart/l_leg/set_disabled(new_disabled = TRUE)
|
||||
..()
|
||||
if(disabled)
|
||||
to_chat(owner, "<span class='userdanger'>Your [name] is too damaged to function!</span>")
|
||||
owner.emote("scream")
|
||||
/obj/item/bodypart/l_leg/is_disabled()
|
||||
if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_LEG))
|
||||
return BODYPART_DISABLED_PARALYSIS
|
||||
return ..()
|
||||
|
||||
/obj/item/bodypart/l_leg/set_disabled(new_disabled)
|
||||
. = ..()
|
||||
if(disabled == new_disabled)
|
||||
return
|
||||
if(disabled == BODYPART_DISABLED_DAMAGE)
|
||||
if(owner.stat > UNCONSCIOUS)
|
||||
owner.emote("scream")
|
||||
if(. && (owner.stat > DEAD))
|
||||
to_chat(owner, "<span class='userdanger'>Your [name] is too damaged to function!</span>")
|
||||
else if(disabled == BODYPART_DISABLED_PARALYSIS)
|
||||
if(. && (owner.stat > DEAD))
|
||||
to_chat(owner, "<span class='userdanger'>You can't feel your [name]!</span>")
|
||||
|
||||
|
||||
/obj/item/bodypart/l_leg/digitigrade
|
||||
name = "left digitigrade leg"
|
||||
@@ -747,11 +812,23 @@
|
||||
max_stamina_damage = 50
|
||||
stam_heal_tick = 2
|
||||
|
||||
/obj/item/bodypart/r_leg/set_disabled(new_disabled = TRUE)
|
||||
..()
|
||||
if(disabled)
|
||||
to_chat(owner, "<span class='userdanger'>Your [name] is too damaged to function!</span>")
|
||||
owner.emote("scream")
|
||||
/obj/item/bodypart/r_leg/is_disabled()
|
||||
if(HAS_TRAIT(owner, TRAIT_PARALYSIS_R_LEG))
|
||||
return BODYPART_DISABLED_PARALYSIS
|
||||
return ..()
|
||||
|
||||
/obj/item/bodypart/r_leg/set_disabled(new_disabled)
|
||||
. = ..()
|
||||
if(disabled == new_disabled)
|
||||
return
|
||||
if(disabled == BODYPART_DISABLED_DAMAGE)
|
||||
if(owner.stat > UNCONSCIOUS)
|
||||
owner.emote("scream")
|
||||
if(. && (owner.stat > DEAD))
|
||||
to_chat(owner, "<span class='userdanger'>Your [name] is too damaged to function!</span>")
|
||||
else if(disabled == BODYPART_DISABLED_PARALYSIS)
|
||||
if(. && (owner.stat > DEAD))
|
||||
to_chat(owner, "<span class='userdanger'>You can't feel your [name]!</span>")
|
||||
|
||||
/obj/item/bodypart/r_leg/digitigrade
|
||||
name = "right digitigrade leg"
|
||||
|
||||
@@ -129,11 +129,14 @@
|
||||
holder = null
|
||||
if(contents.len == 1)
|
||||
Extend(contents[1])
|
||||
else // TODO: make it similar to borg's storage-like module selection
|
||||
var/obj/item/choise = input("Activate which item?", "Arm Implant", null, null) as null|anything in items_list
|
||||
if(owner && owner == usr && owner.stat != DEAD && (src in owner.internal_organs) && !holder && istype(choise) && (choise in contents))
|
||||
// This monster sanity check is a nice example of how bad input() is.
|
||||
Extend(choise)
|
||||
else
|
||||
var/list/choice_list = list()
|
||||
for(var/obj/item/I in items_list)
|
||||
choice_list[I] = getFlatIcon(I)
|
||||
var/obj/item/choice = show_radial_menu(owner, owner, choice_list)
|
||||
if(owner && owner == usr && owner.stat != DEAD && (src in owner.internal_organs) && !holder && (choice in contents))
|
||||
// This monster sanity check is a nice example of how bad input is.
|
||||
Extend(choice)
|
||||
else
|
||||
Retract()
|
||||
|
||||
|
||||
@@ -11,57 +11,5 @@
|
||||
for(var/i2 in (i+1) to reactions.len)
|
||||
var/datum/chemical_reaction/r1 = reactions[i]
|
||||
var/datum/chemical_reaction/r2 = reactions[i2]
|
||||
if(recipes_do_conflict(r1, r2))
|
||||
if(chem_recipes_do_conflict(r1, r2))
|
||||
Fail("Chemical recipe conflict between [r1.type] and [r2.type]")
|
||||
|
||||
/datum/unit_test/reagent_recipe_collisions/proc/recipes_do_conflict(datum/chemical_reaction/r1, datum/chemical_reaction/r2)
|
||||
//do the non-list tests first, because they are cheaper
|
||||
if(r1.required_container != r2.required_container)
|
||||
return FALSE
|
||||
if(r1.is_cold_recipe == r2.is_cold_recipe)
|
||||
if(r1.required_temp != r2.required_temp)
|
||||
//one reaction requires a more extreme temperature than the other, so there is no conflict
|
||||
return FALSE
|
||||
else
|
||||
var/datum/chemical_reaction/cold_one = r1.is_cold_recipe ? r1 : r2
|
||||
var/datum/chemical_reaction/warm_one = r1.is_cold_recipe ? r2 : r1
|
||||
if(cold_one.required_temp < warm_one.required_temp)
|
||||
//the range of temperatures does not overlap, so there is no conflict
|
||||
return FALSE
|
||||
|
||||
//find the reactions with the shorter and longer required_reagents list
|
||||
var/datum/chemical_reaction/long_req
|
||||
var/datum/chemical_reaction/short_req
|
||||
if(r1.required_reagents.len > r2.required_reagents.len)
|
||||
long_req = r1
|
||||
short_req = r2
|
||||
else if(r1.required_reagents.len < r2.required_reagents.len)
|
||||
long_req = r2
|
||||
short_req = r1
|
||||
else
|
||||
//if they are the same length, sort instead by the length of the catalyst list
|
||||
//this is important if the required_reagents lists are the same
|
||||
if(r1.required_catalysts.len > r2.required_catalysts.len)
|
||||
long_req = r1
|
||||
short_req = r2
|
||||
else
|
||||
long_req = r2
|
||||
short_req = r1
|
||||
|
||||
|
||||
//check if the shorter reaction list is a subset of the longer one
|
||||
var/list/overlap = r1.required_reagents & r2.required_reagents
|
||||
if(overlap.len != short_req.required_reagents.len)
|
||||
//there is at least one reagent in the short list that is not in the long list, so there is no conflict
|
||||
return FALSE
|
||||
|
||||
//check to see if the shorter reaction's catalyst list is also a subset of the longer reaction's catalyst list
|
||||
//if the longer reaction's catalyst list is a subset of the shorter ones, that is fine
|
||||
//if the reaction lists are the same, the short reaction will have the shorter required_catalysts list, so it will register as a conflict
|
||||
var/list/short_minus_long_catalysts = short_req.required_catalysts - long_req.required_catalysts
|
||||
if(short_minus_long_catalysts.len)
|
||||
//there is at least one unique catalyst for the short reaction, so there is no conflict
|
||||
return FALSE
|
||||
|
||||
//if we got this far, the longer reaction will be impossible to create if the shorter one is earlier in GLOB.chemical_reactions_list, and will require the reagents to be added in a particular order otherwise
|
||||
return TRUE
|
||||
+1143
-1037
File diff suppressed because it is too large
Load Diff
@@ -31,6 +31,19 @@
|
||||
occupant_actions = list()
|
||||
generate_actions()
|
||||
|
||||
/obj/vehicle/examine(mob/user)
|
||||
..()
|
||||
if(resistance_flags & ON_FIRE)
|
||||
to_chat(user, "<span class='warning'>It's on fire!</span>")
|
||||
var/healthpercent = obj_integrity/max_integrity * 100
|
||||
switch(healthpercent)
|
||||
if(50 to 99)
|
||||
to_chat(user, "It looks slightly damaged.")
|
||||
if(25 to 50)
|
||||
to_chat(user, "It appears heavily damaged.")
|
||||
if(0 to 25)
|
||||
to_chat(user, "<span class='warning'>It's falling apart!</span>")
|
||||
|
||||
/obj/vehicle/proc/is_key(obj/item/I)
|
||||
return I? (key_type_exact? (I.type == key_type) : istype(I, key_type)) : FALSE
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
max_buckled_mobs = 1
|
||||
buckle_lying = FALSE
|
||||
default_driver_move = FALSE
|
||||
var/legs_required = 2
|
||||
var/arms_requires = 0 //why not?
|
||||
var/legs_required = 1
|
||||
var/arms_required = 0 //why not?
|
||||
|
||||
/obj/vehicle/ridden/Initialize()
|
||||
. = ..()
|
||||
@@ -31,6 +31,9 @@
|
||||
|
||||
/obj/vehicle/ridden/post_buckle_mob(mob/living/M)
|
||||
add_occupant(M)
|
||||
if(M.get_num_legs() < legs_required)
|
||||
to_chat(M, "<span class='warning'>You don't have enough legs to operate the pedals!</span>")
|
||||
unbuckle_mob(M)
|
||||
return ..()
|
||||
|
||||
/obj/vehicle/ridden/attackby(obj/item/I, mob/user, params)
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
/obj/vehicle/ridden/wheelchair //ported from Hippiestation (by Jujumatic) Then ported by Fermis from tg!
|
||||
name = "wheelchair"
|
||||
desc = "A chair with big wheels. It looks like you can move in this on your own."
|
||||
icon = 'icons/obj/vehicles.dmi'
|
||||
icon_state = "wheelchair"
|
||||
layer = OBJ_LAYER
|
||||
max_integrity = 100
|
||||
armor = list("melee" = 10, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 20, "acid" = 30) //Wheelchairs aren't super tough yo
|
||||
legs_required = 0 //You'll probably be using this if you don't have legs
|
||||
canmove = TRUE
|
||||
density = FALSE //Thought I couldn't fix this one easily, phew
|
||||
arms_required = 1
|
||||
|
||||
/obj/vehicle/ridden/wheelchair/Initialize()
|
||||
. = ..()
|
||||
var/datum/component/riding/D = LoadComponent(/datum/component/riding)
|
||||
D.vehicle_move_delay = 0
|
||||
D.set_vehicle_dir_layer(SOUTH, OBJ_LAYER)
|
||||
D.set_vehicle_dir_layer(NORTH, ABOVE_MOB_LAYER)
|
||||
D.set_vehicle_dir_layer(EAST, OBJ_LAYER)
|
||||
D.set_vehicle_dir_layer(WEST, OBJ_LAYER)
|
||||
|
||||
/obj/vehicle/ridden/wheelchair/ComponentInitialize() //Since it's technically a chair I want it to have chair properties
|
||||
. = ..()
|
||||
AddComponent(/datum/component/simple_rotation,ROTATION_ALTCLICK | ROTATION_CLOCKWISE, CALLBACK(src, .proc/can_user_rotate),CALLBACK(src, .proc/can_be_rotated),null)
|
||||
|
||||
/obj/vehicle/ridden/wheelchair/obj_destruction(damage_flag)
|
||||
new /obj/item/stack/rods(drop_location(), 1)
|
||||
new /obj/item/stack/sheet/metal(drop_location(), 1)
|
||||
..()
|
||||
|
||||
/obj/vehicle/ridden/wheelchair/Destroy()
|
||||
if(has_buckled_mobs())
|
||||
var/mob/living/carbon/H = buckled_mobs[1]
|
||||
unbuckle_mob(H)
|
||||
return ..()
|
||||
|
||||
/obj/vehicle/ridden/wheelchair/driver_move(mob/living/user, direction)
|
||||
if(istype(user))
|
||||
if(canmove && (user.get_num_arms() < arms_required))
|
||||
to_chat(user, "<span class='warning'>You don't have enough arms to operate the wheels!</span>")
|
||||
canmove = FALSE
|
||||
addtimer(VARSET_CALLBACK(src, canmove, TRUE), 20)
|
||||
return FALSE
|
||||
var/datum/component/riding/D = GetComponent(/datum/component/riding)
|
||||
//1.5 (movespeed as of this change) multiplied by 6.7 gets ABOUT 10 (rounded), the old constant for the wheelchair that gets divided by how many arms they have
|
||||
//if that made no sense this simply makes the wheelchair speed change along with movement speed delay
|
||||
D.vehicle_move_delay = round(CONFIG_GET(number/movedelay/run_delay) * 6.7) / min(user.get_num_arms(), 2)
|
||||
return ..()
|
||||
|
||||
/obj/vehicle/ridden/wheelchair/Moved()
|
||||
. = ..()
|
||||
cut_overlays()
|
||||
playsound(src, 'sound/effects/roll.ogg', 75, 1)
|
||||
if(has_buckled_mobs())
|
||||
handle_rotation_overlayed()
|
||||
|
||||
|
||||
/obj/vehicle/ridden/wheelchair/post_buckle_mob(mob/living/user)
|
||||
. = ..()
|
||||
handle_rotation_overlayed()
|
||||
|
||||
/obj/vehicle/ridden/wheelchair/post_unbuckle_mob()
|
||||
. = ..()
|
||||
cut_overlays()
|
||||
|
||||
/obj/vehicle/ridden/wheelchair/setDir(newdir)
|
||||
..()
|
||||
handle_rotation(newdir)
|
||||
|
||||
/obj/vehicle/ridden/wheelchair/wrench_act(mob/living/user, obj/item/I) //Attackby should stop it attacking the wheelchair after moving away during decon
|
||||
to_chat(user, "<span class='notice'>You begin to detach the wheels...</span>")
|
||||
if(I.use_tool(src, user, 40, volume=50))
|
||||
to_chat(user, "<span class='notice'>You detach the wheels and deconstruct the chair.</span>")
|
||||
new /obj/item/stack/rods(drop_location(), 6)
|
||||
new /obj/item/stack/sheet/metal(drop_location(), 4)
|
||||
qdel(src)
|
||||
return TRUE
|
||||
|
||||
/obj/vehicle/ridden/wheelchair/proc/handle_rotation(direction)
|
||||
if(has_buckled_mobs())
|
||||
handle_rotation_overlayed()
|
||||
for(var/m in buckled_mobs)
|
||||
var/mob/living/buckled_mob = m
|
||||
buckled_mob.setDir(direction)
|
||||
|
||||
/obj/vehicle/ridden/wheelchair/proc/handle_rotation_overlayed()
|
||||
cut_overlays()
|
||||
var/image/V = image(icon = icon, icon_state = "wheelchair_overlay", layer = FLY_LAYER, dir = src.dir)
|
||||
add_overlay(V)
|
||||
|
||||
|
||||
|
||||
/obj/vehicle/ridden/wheelchair/proc/can_be_rotated(mob/living/user)
|
||||
return TRUE
|
||||
|
||||
/obj/vehicle/ridden/wheelchair/proc/can_user_rotate(mob/living/user)
|
||||
var/mob/living/L = user
|
||||
if(istype(L))
|
||||
if(!user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
|
||||
return FALSE
|
||||
if(isobserver(user) && CONFIG_GET(flag/ghost_interaction))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/vehicle/ridden/wheelchair/the_whip/driver_move(mob/living/user, direction)
|
||||
if(istype(user))
|
||||
var/datum/component/riding/D = GetComponent(/datum/component/riding)
|
||||
D.vehicle_move_delay = round(CONFIG_GET(number/movedelay/run_delay) * 6.7) / user.get_num_arms()
|
||||
return ..()
|
||||
@@ -32,7 +32,10 @@
|
||||
/obj/item/reagent_containers/hypospray/medipen = 3,
|
||||
/obj/item/storage/belt/medical = 3,
|
||||
/obj/item/wrench/medical = 1,
|
||||
/obj/item/storage/briefcase/medical = 2)
|
||||
/obj/item/storage/belt/medolier/full = 2,
|
||||
/obj/item/gun/syringe/dart = 2,
|
||||
/obj/item/storage/briefcase/medical = 2)
|
||||
|
||||
armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50)
|
||||
resistance_flags = FIRE_PROOF
|
||||
refill_canister = /obj/item/vending_refill/medical
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
/obj/item/reagent_containers/medspray/styptic = 2,
|
||||
/obj/item/reagent_containers/medspray/silver_sulf = 2,
|
||||
/obj/item/reagent_containers/pill/charcoal = 2,
|
||||
/obj/item/reagent_containers/medspray/sterilizine = 1)
|
||||
/obj/item/reagent_containers/medspray/sterilizine = 1,
|
||||
/obj/item/reagent_containers/syringe/dart = 10)
|
||||
contraband = list(/obj/item/reagent_containers/pill/tox = 2,
|
||||
/obj/item/reagent_containers/pill/morphine = 2)
|
||||
premium = list(/obj/item/reagent_containers/medspray/synthflesh = 2)
|
||||
|
||||
Reference in New Issue
Block a user