Merge branch 'master' into patch-185
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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -790,3 +790,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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -725,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
|
||||
@@ -856,13 +856,16 @@
|
||||
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, bypass_piggybacking = FALSE)
|
||||
/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)
|
||||
@@ -879,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(force || 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>")
|
||||
|
||||
@@ -1300,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
|
||||
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -246,7 +246,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")
|
||||
design_ids = list("bs_rped","biobag_holding","minerbag_holding", "bluespacebeaker", "bluespacesyringe", "phasic_scanning", "roastingstick", "ore_silo", "bluespacesmartdart")
|
||||
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.
|
||||
|
||||
|
||||
@@ -564,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)
|
||||
|
||||
@@ -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
|
||||
+1163
-1057
File diff suppressed because it is too large
Load Diff
@@ -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