Merge remote-tracking branch 'origin/master' into what-should-i-name-this-branch

This commit is contained in:
LetterN
2021-12-21 07:59:33 +08:00
164 changed files with 128258 additions and 912 deletions
+105 -77
View File
@@ -387,8 +387,7 @@
log_combat(user, M, "used a cult spell on", source.name, "")
M.set_last_attacker(user)
/obj/item/melee/blood_magic/afterattack(atom/target, mob/living/carbon/user, proximity)
. = ..()
/obj/item/melee/blood_magic/proc/post_cast(atom/target, mob/living/carbon/user, proximity)
if(invocation)
user.whisper(invocation, language = /datum/language/common)
if(health_cost)
@@ -467,6 +466,7 @@
to_chat(user, "<span class='cultitalic'>In an brilliant flash of red, [L] [is_servant_of_ratvar(L) ? "writhes in pain!" : "falls to the ground!"]</span>")
uses--
..()
post_cast(target, user, proximity)
//Teleportation
/obj/item/melee/blood_magic/teleport
@@ -480,40 +480,45 @@
to_chat(user, "<span class='warning'>You can only teleport adjacent cultists with this spell!</span>")
return
if(iscultist(user))
var/list/potential_runes = list()
var/list/teleportnames = list()
for(var/R in GLOB.teleport_runes)
var/obj/effect/rune/teleport/T = R
potential_runes[avoid_assoc_duplicate_keys(T.listkey, teleportnames)] = T
if(!potential_runes.len)
to_chat(user, "<span class='warning'>There are no valid runes to teleport to!</span>")
log_game("Teleport talisman failed - no other teleport runes")
return
var/turf/T = get_turf(src)
if(is_away_level(T.z))
to_chat(user, "<span class='cultitalic'>You are not in the right dimension!</span>")
log_game("Teleport spell failed - user in away mission")
return
var/input_rune_key = input(user, "Choose a rune to teleport to.", "Rune to Teleport to") as null|anything in potential_runes //we know what key they picked
var/obj/effect/rune/teleport/actual_selected_rune = potential_runes[input_rune_key] //what rune does that key correspond to?
if(QDELETED(src) || !user || !user.is_holding(src) || user.incapacitated() || !actual_selected_rune || !proximity)
return
var/turf/dest = get_turf(actual_selected_rune)
if(is_blocked_turf(dest, TRUE))
to_chat(user, "<span class='warning'>The target rune is blocked. Attempting to teleport to it would be massively unwise.</span>")
return
uses--
var/turf/origin = get_turf(user)
var/mob/living/L = target
if(do_teleport(L, dest, channel = TELEPORT_CHANNEL_CULT))
origin.visible_message("<span class='warning'>Dust flows from [user]'s hand, and [user.p_they()] disappear[user.p_s()] with a sharp crack!</span>", \
"<span class='cultitalic'>You speak the words of the talisman and find yourself somewhere else!</span>", "<i>You hear a sharp crack.</i>")
dest.visible_message("<span class='warning'>There is a boom of outrushing air as something appears above the rune!</span>", null, "<i>You hear a boom.</i>")
try_teleport(target, user, proximity)
..()
/obj/item/melee/blood_magic/teleport/proc/try_teleport(atom/target, mob/living/carbon/user, proximity)
set waitfor = FALSE
var/list/potential_runes = list()
var/list/teleportnames = list()
for(var/R in GLOB.teleport_runes)
var/obj/effect/rune/teleport/T = R
potential_runes[avoid_assoc_duplicate_keys(T.listkey, teleportnames)] = T
if(!potential_runes.len)
to_chat(user, "<span class='warning'>There are no valid runes to teleport to!</span>")
log_game("Teleport talisman failed - no other teleport runes")
return
var/turf/T = get_turf(src)
if(is_away_level(T.z))
to_chat(user, "<span class='cultitalic'>You are not in the right dimension!</span>")
log_game("Teleport spell failed - user in away mission")
return
var/input_rune_key = input(user, "Choose a rune to teleport to.", "Rune to Teleport to") as null|anything in potential_runes //we know what key they picked
var/obj/effect/rune/teleport/actual_selected_rune = potential_runes[input_rune_key] //what rune does that key correspond to?
if(QDELETED(src) || !user || !user.is_holding(src) || user.incapacitated() || !actual_selected_rune || !proximity)
return
var/turf/dest = get_turf(actual_selected_rune)
if(is_blocked_turf(dest, TRUE))
to_chat(user, "<span class='warning'>The target rune is blocked. Attempting to teleport to it would be massively unwise.</span>")
return
uses--
var/turf/origin = get_turf(user)
var/mob/living/L = target
if(do_teleport(L, dest, channel = TELEPORT_CHANNEL_CULT))
origin.visible_message("<span class='warning'>Dust flows from [user]'s hand, and [user.p_they()] disappear[user.p_s()] with a sharp crack!</span>", \
"<span class='cultitalic'>You speak the words of the talisman and find yourself somewhere else!</span>", "<i>You hear a sharp crack.</i>")
dest.visible_message("<span class='warning'>There is a boom of outrushing air as something appears above the rune!</span>", null, "<i>You hear a boom.</i>")
post_cast(target, user, proximity)
//Shackles
/obj/item/melee/blood_magic/shackles
name = "Binding Aura"
@@ -530,6 +535,7 @@
user.visible_message("<span class='cultitalic'>This victim doesn't have enough arms to complete the restraint!</span>")
return
..()
post_cast(target, user, proximity)
/obj/item/melee/blood_magic/shackles/proc/CuffAttack(mob/living/carbon/C, mob/living/user)
if(!C.handcuffed)
@@ -583,6 +589,7 @@
to_chat(user, "<span class='warning'>A dark cloud emanates from your hand and swirls around the metal, twisting it into a construct shell!</span>")
new /obj/structure/constructshell(T)
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
post_cast(target, proximity_flag, user)
else
to_chat(user, "<span class='warning'>You need 50 metal to produce a construct shell!</span>")
else if(istype(target, /obj/item/stack/sheet/plasteel))
@@ -593,56 +600,73 @@
new /obj/item/stack/sheet/runed_metal(T,quantity)
to_chat(user, "<span class='warning'>A dark cloud emanates from you hand and swirls around the plasteel, transforming it into runed metal!</span>")
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
post_cast(target, user, proximity_flag)
if(istype(target, /obj/item/clothing/suit/hooded/wintercoat) && target.type != /obj/item/clothing/suit/hooded/wintercoat/narsie)
if (do_after(user,30,target=target))
new /obj/item/clothing/suit/hooded/wintercoat/narsie(T)
qdel(target)
to_chat(user, "<span class='warning'>A dark cloud emanates from you hand and swirls around [target], transforming it into a narsian winter coat!</span>")
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
convert_coat(target, user, proximity_flag, T)
else if(istype(target,/mob/living/silicon/robot))
var/mob/living/silicon/robot/candidate = target
if(!iscultist(user, TRUE))
to_chat(user, "<span class='warning'>You are not strongly connected enough to Nar'sie to use make constructs...</span>")
else if(candidate.mmi)
user.visible_message("<span class='danger'>A dark cloud emanates from [user]'s hand and swirls around [candidate]!</span>")
playsound(T, 'sound/machines/airlock_alien_prying.ogg', 80, 1)
var/prev_color = candidate.color
candidate.color = "black"
if(do_after(user, 90, target = candidate))
candidate.emp_act(80)
var/construct_class = alert(user, "Please choose which type of construct you wish to create.",,"Juggernaut","Wraith","Artificer")
user.visible_message("<span class='danger'>The dark cloud receedes from what was formerly [candidate], revealing a\n [construct_class]!</span>")
switch(construct_class)
if("Juggernaut")
makeNewConstruct(/mob/living/simple_animal/hostile/construct/armored, candidate, user, 0, T)
if("Wraith")
makeNewConstruct(/mob/living/simple_animal/hostile/construct/wraith, candidate, user, 0, T)
if("Artificer")
makeNewConstruct(/mob/living/simple_animal/hostile/construct/builder, candidate, user, 0, T)
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
uses--
candidate.mmi = null
qdel(candidate)
else
candidate.color = prev_color
else
uses--
to_chat(user, "<span class='warning'>A dark cloud emanates from you hand and swirls around [candidate] - twisting it into a construct shell!</span>")
new /obj/structure/constructshell(T)
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
convert_borg(target, user, proximity_flag, T)
else if(istype(target,/obj/machinery/door/airlock))
playsound(T, 'sound/machines/airlockforced.ogg', 50, 1)
do_sparks(5, TRUE, target)
if(do_after(user, 50, target = user))
target.narsie_act()
uses--
user.visible_message("<span class='warning'>Black ribbons suddenly emanate from [user]'s hand and cling to the airlock - twisting and corrupting it!</span>")
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
convert_door(target, user, proximity_flag, T)
else
to_chat(user, "<span class='warning'>The spell will not work on [target]!</span>")
return
..()
/obj/item/melee/blood_magic/construction/proc/convert_coat(atom/target, mob/user, proximity_flag, turf/T)
set waitfor = FALSE
if(do_after(user,30,target=target))
new /obj/item/clothing/suit/hooded/wintercoat/narsie(T)
qdel(target)
to_chat(user, "<span class='warning'>A dark cloud emanates from you hand and swirls around [target], transforming it into a narsian winter coat!</span>")
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
post_cast(target, user, proximity_flag)
/obj/item/melee/blood_magic/construction/proc/convert_door(atom/target, mob/user, proximity_flag, turf/T)
set waitfor = FALSE
playsound(T, 'sound/machines/airlockforced.ogg', 50, 1)
do_sparks(5, TRUE, target)
if(do_after(user, 50, target = user))
target.narsie_act()
uses--
user.visible_message("<span class='warning'>Black ribbons suddenly emanate from [user]'s hand and cling to the airlock - twisting and corrupting it!</span>")
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
post_cast(target, user, proximity_flag)
/obj/item/melee/blood_magic/construction/proc/convert_borg(atom/target, mob/user, proximity_flag, turf/T)
set waitfor = FALSE
var/mob/living/silicon/robot/candidate = target
if(!iscultist(user, TRUE))
to_chat(user, "<span class='warning'>You are not strongly connected enough to Nar'sie to use make constructs...</span>")
return
else if(candidate.mmi)
user.visible_message("<span class='danger'>A dark cloud emanates from [user]'s hand and swirls around [candidate]!</span>")
playsound(T, 'sound/machines/airlock_alien_prying.ogg', 80, 1)
var/prev_color = candidate.color
candidate.color = "black"
if(do_after(user, 90, target = candidate))
candidate.emp_act(80)
var/construct_class = alert(user, "Please choose which type of construct you wish to create.",,"Juggernaut","Wraith","Artificer")
user.visible_message("<span class='danger'>The dark cloud receedes from what was formerly [candidate], revealing a\n [construct_class]!</span>")
switch(construct_class)
if("Juggernaut")
makeNewConstruct(/mob/living/simple_animal/hostile/construct/armored, candidate, user, 0, T)
if("Wraith")
makeNewConstruct(/mob/living/simple_animal/hostile/construct/wraith, candidate, user, 0, T)
if("Artificer")
makeNewConstruct(/mob/living/simple_animal/hostile/construct/builder, candidate, user, 0, T)
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
uses--
candidate.mmi = null
qdel(candidate)
else
candidate.color = prev_color
else
uses--
to_chat(user, "<span class='warning'>A dark cloud emanates from you hand and swirls around [candidate] - twisting it into a construct shell!</span>")
new /obj/structure/constructshell(T)
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
post_cast(target, user, proximity_flag)
//Armor: Gives the target a basic cultist combat loadout
/obj/item/melee/blood_magic/armor
name = "Bladed Aura"
@@ -665,6 +689,7 @@
C.put_in_hands(new /obj/item/melee/cultblade(user))
C.put_in_hands(new /obj/item/restraints/legcuffs/bola/cult(user))
..()
post_cast(target, user, proximity)
/obj/item/melee/blood_magic/manipulator
name = "Ritual Aura"
@@ -693,7 +718,9 @@
H.adjust_integration_blood(uses * 2)
to_chat(user,"<span class='danger'>You use the last of your blood rites to restore what blood you could!</span>")
uses = 0
return ..()
..()
post_cast(target, user, proximity)
return
else
H.blood_volume = (BLOOD_VOLUME_SAFE*H.blood_ratio)
uses -= round(restore_blood/2)
@@ -758,6 +785,7 @@
if(istype(target, /obj/effect/decal/cleanable/blood))
blood_draw(target, user)
..()
post_cast()
/obj/item/melee/blood_magic/manipulator/proc/blood_draw(atom/target, mob/living/carbon/human/user)
var/temp = 0
+31 -29
View File
@@ -660,40 +660,42 @@
return
if(istype(A, /obj/item))
var/list/cultists = list()
for(var/datum/mind/M in SSticker.mode.cult)
if(M.current && M.current.stat != DEAD)
cultists |= M.current
var/mob/living/cultist_to_receive = input(user, "Who do you wish to call to [src]?", "Followers of the Geometer") as null|anything in (cultists - user)
if(!Adjacent(user) || !src || QDELETED(src) || user.incapacitated())
return
if(!cultist_to_receive)
to_chat(user, "<span class='cult italic'>You require a destination!</span>")
log_game("Void torch failed - no target")
return
if(cultist_to_receive.stat == DEAD)
to_chat(user, "<span class='cult italic'>[cultist_to_receive] has died!</span>")
log_game("Void torch failed - target died")
return
if(!iscultist(cultist_to_receive))
to_chat(user, "<span class='cult italic'>[cultist_to_receive] is not a follower of the Geometer!</span>")
log_game("Void torch failed - target was deconverted")
return
if(A in user.GetAllContents())
to_chat(user, "<span class='cult italic'>[A] must be on a surface in order to teleport it!</span>")
return
to_chat(user, "<span class='cult italic'>You ignite [A] with \the [src], turning it to ash, but through the torch's flames you see that [A] has reached [cultist_to_receive]!")
cultist_to_receive.put_in_hands(A)
charges--
to_chat(user, "\The [src] now has [charges] charge\s.")
if(charges == 0)
qdel(src)
transmit_item(A, user, proximity)
else
..()
to_chat(user, "<span class='warning'>\The [src] can only transport items!</span>")
/obj/item/flashlight/flare/culttorch/proc/transmit_item(atom/movable/A, mob/user, proximity)
set waitfor = FALSE
var/list/cultists = list()
for(var/datum/mind/M in SSticker.mode.cult)
if(M.current && M.current.stat != DEAD)
cultists |= M.current
var/mob/living/cultist_to_receive = input(user, "Who do you wish to call to [src]?", "Followers of the Geometer") as null|anything in (cultists - user)
if(!Adjacent(user) || !src || QDELETED(src) || user.incapacitated())
return
if(!cultist_to_receive)
to_chat(user, "<span class='cult italic'>You require a destination!</span>")
log_game("Void torch failed - no target")
return
if(cultist_to_receive.stat == DEAD)
to_chat(user, "<span class='cult italic'>[cultist_to_receive] has died!</span>")
log_game("Void torch failed - target died")
return
if(!iscultist(cultist_to_receive))
to_chat(user, "<span class='cult italic'>[cultist_to_receive] is not a follower of the Geometer!</span>")
log_game("Void torch failed - target was deconverted")
return
if(A in user.GetAllContents())
to_chat(user, "<span class='cult italic'>[A] must be on a surface in order to teleport it!</span>")
return
to_chat(user, "<span class='cult italic'>You ignite [A] with \the [src], turning it to ash, but through the torch's flames you see that [A] has reached [cultist_to_receive]!")
cultist_to_receive.put_in_hands(A)
charges--
to_chat(user, "\The [src] now has [charges] charge\s.")
if(charges == 0)
qdel(src)
/obj/item/cult_spear
name = "blood halberd"
+12 -8
View File
@@ -34,14 +34,16 @@
/obj/item/assembly/proc/on_attach()
/obj/item/assembly/proc/on_detach() //call this when detaching it from a device. handles any special functions that need to be updated ex post facto
///Call this when detaching it from a device. handles any special functions that need to be updated ex post facto
/obj/item/assembly/proc/on_detach()
if(!holder)
return FALSE
forceMove(holder.drop_location())
holder = null
return TRUE
/obj/item/assembly/proc/holder_movement() //Called when the holder is moved
///Called when the holder is moved
/obj/item/assembly/proc/holder_movement()
if(!holder)
return FALSE
setDir(holder.dir)
@@ -53,7 +55,6 @@
return FALSE
return TRUE
//Called when another assembly acts on this one, var/radio will determine where it came from for wire calcs
/obj/item/assembly/proc/pulsed(radio = FALSE)
if(wire_type & WIRE_RECEIVE)
@@ -62,7 +63,6 @@
INVOKE_ASYNC(src, .proc/activate)
return TRUE
//Called when this device attempts to act on another device, var/radio determines if it was sent via radio or direct
/obj/item/assembly/proc/pulse(radio = FALSE)
if(connected && wire_type)
@@ -74,7 +74,6 @@
holder.process_activation(src, 0, 1)
return TRUE
// What the device does when turned on
/obj/item/assembly/proc/activate()
if(QDELETED(src) || !secured || (next_activate > world.time))
@@ -82,13 +81,11 @@
next_activate = world.time + activate_cooldown
return TRUE
/obj/item/assembly/proc/toggle_secure()
secured = !secured
update_icon()
return secured
/obj/item/assembly/attackby(obj/item/W, mob/user, params)
if(isassembly(W))
var/obj/item/assembly/A = W
@@ -115,7 +112,6 @@
. = ..()
. += "<span class='notice'>\The [src] [secured? "is secured and ready to be used!" : "can be attached to other things."]</span>"
/obj/item/assembly/attack_self(mob/user)
if(!user)
return FALSE
@@ -125,3 +121,11 @@
/obj/item/assembly/interact(mob/user)
return ui_interact(user)
/obj/item/assembly/ui_host(mob/user)
if(holder)
return holder
return src
/obj/item/assembly/ui_state(mob/user)
return GLOB.hands_state
+3 -3
View File
@@ -88,14 +88,14 @@
if(a_right)
a_right.dropped(user)
/obj/item/assembly_holder/on_attack_hand()//Perhapse this should be a holder_pickup proc instead, can add if needbe I guess
/obj/item/assembly_holder/on_attack_hand(user, act_intent)//Perhapse this should be a holder_pickup proc instead, can add if needbe I guess
. = ..()
if(.)
return
if(a_left)
a_left.attack_hand()
a_left.attack_hand(user, act_intent)
if(a_right)
a_right.attack_hand()
a_right.attack_hand(user, act_intent)
/obj/item/assembly_holder/screwdriver_act(mob/user, obj/item/tool)
if(..())
@@ -0,0 +1,65 @@
GLOBAL_VAR_INIT(save_area_executing, FALSE)
/datum/mapGenerator/save_area
buildmode_name = "Save Area"
modules = list(/datum/mapGeneratorModule/save_area)
var/min_x = 0
var/min_y = 0
var/max_x = 0
var/max_y = 0
/datum/mapGenerator/save_area/defineRegion(turf/Start, turf/End, replace = 0)
min_x = min(Start.x,End.x)
min_y = min(Start.y,End.y)
max_x = max(Start.x,End.x)
max_y = max(Start.y,End.y)
..()
/datum/mapGeneratorModule/save_area
var/areaName = "default.dm"
//This could be optimised by making turfs that are the same go in the same, but this is a quick bodge solution so yea, fun job for coder here :)
/datum/mapGeneratorModule/save_area/generate()
var/datum/mapGenerator/save_area/L = mother
if(!istype(L))
return
//If someone somehow gets build mode, stop them from using this.
if(!check_rights(R_ADMIN))
message_admins("[ckey(usr)] tried to run the map save generator but was rejected due to insufficient perms.")
to_chat(usr, "<span class='warning'>You must have R_ADMIN privellages to use this.</span>")
return
//Emergency check
if(L.map.len > 1600)
var/confirm = alert("Uhm, are you sure, the area is quiet large?", "Run generator", "Yes", "No")
if(confirm != "Yes")
return
if(GLOB.save_area_executing)
to_chat(usr, "<span class='warning'>Someone is already running the generator! Try again in a bit.</span>")
return
to_chat(usr, "<span class='warning'>Saving, please wait...</span>")
GLOB.save_area_executing = TRUE
//Log just in case something happens
log_game("[key_name(usr)] ran the save level map generator on [L.map.len] turfs.")
message_admins("[key_name(usr)] ran the save level map generator on [L.map.len] turfs.")
//Step 1: Get the data (This can take a while)
var/dat = "//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE\n"
dat += convert_map_to_tgm(L.map)
//Step 2: Write the data to a file
var/filedir = file("data/temp.dmm")
if(fexists(filedir))
fdel(filedir)
WRITE_FILE(filedir, "[dat]")
//Step 3: Give the file to client for download
usr << ftp(filedir)
//Step 4: Remove the file from the server (hopefully we can find a way to avoid step)
fdel(filedir)
log_game("[L.map.len] turfs have been saved by [ckey(usr)]")
alert("Area saved successfully.", "Action Successful!", "Ok")
GLOB.save_area_executing = FALSE
-2
View File
@@ -21,8 +21,6 @@
var/active_sound = null
var/toggle_cooldown = null
var/cooldown = 0
var/obj/item/flashlight/F = null
var/can_flashlight = 0
var/blocks_shove_knockdown = FALSE //Whether wearing the clothing item blocks the ability for shove to knock down.
+30
View File
@@ -0,0 +1,30 @@
/obj/item/clothing/gloves/mittens
desc = "These gloves will keep your hands warm!"
name = "mittens"
icon_state = "mittens"
item_state = "wgloves"
//item_color = "white"
cold_protection = HANDS
min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT
resistance_flags = NONE
/obj/item/clothing/gloves/mittens/random
/obj/item/clothing/gloves/mittens/random/Initialize()
..()
var/colours = list("black", "yellow", "lightbrown", "brown", "orange", "red", "purple", "green", "blue", "kitten")
var/picked_c = pick(colours)
if(picked_c == "kitten")
new /obj/item/clothing/gloves/mittens/kitten(loc)
qdel(src)
return INITIALIZE_HINT_QDEL
item_state = "[picked_c]gloves"
//item_color = "[picked_c]"
color = picked_c
/obj/item/clothing/gloves/mittens/kitten
name = "Kitten mittens"
desc = "These gloves will keep your hands warm, and feature cute kittens"
icon_state = "kittenmittens"
item_state = "blackgloves"
//item_color = "black"
+70 -40
View File
@@ -16,17 +16,47 @@
dog_fashion = /datum/dog_fashion/head/helmet
var/can_flashlight = FALSE //if a flashlight can be mounted. if it has a flashlight and this is false, it is permanently attached.
var/obj/item/flashlight/seclite/attached_light
var/datum/action/item_action/toggle_helmet_flashlight/alight
/obj/item/clothing/head/helmet/Initialize(mapload)
. = ..()
if(attached_light)
alight = new(src)
/obj/item/clothing/head/helmet/ComponentInitialize()
. = ..()
AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_HEAD))
/obj/item/clothing/head/helmet/examine(mob/user)
. = ..()
if(attached_light)
. += "It has \a [attached_light] [can_flashlight ? "" : "permanently "]mounted on it."
if(can_flashlight)
. += "<span class='info'>[attached_light] looks like it can be <b>unscrewed</b> from [src].</span>"
else if(can_flashlight)
. += "It has a mounting point for a <b>seclite</b>."
/obj/item/clothing/head/helmet/Destroy()
QDEL_NULL(attached_light)
return ..()
/obj/item/clothing/head/helmet/handle_atom_del(atom/A)
if(A == attached_light)
attached_light = null
update_helmlight()
update_icon()
QDEL_NULL(alight)
return ..()
/obj/item/clothing/head/helmet/sec
can_flashlight = 1
/obj/item/clothing/head/helmet/sec/attackby(obj/item/I, mob/user, params)
if(issignaler(I))
var/obj/item/assembly/signaler/S = I
if(F) //Has a flashlight. Player must remove it, else it will be lost forever.
if(attached_light) //Has a flashlight. Player must remove it, else it will be lost forever.
to_chat(user, "<span class='warning'>The mounted flashlight is in the way, remove it first!</span>")
return
@@ -280,8 +310,8 @@
/obj/item/clothing/head/helmet/update_icon_state()
var/state = "[initial(icon_state)]"
if(F)
if(F.on)
if(attached_light)
if(attached_light.on)
state += "-flight-on" //"helmet-flight-on" // "helmet-cam-flight-on"
else
state += "-flight" //etc.
@@ -289,7 +319,7 @@
icon_state = state
/obj/item/clothing/head/helmet/ui_action_click(mob/user, action)
if(istype(action, /datum/action/item_action/toggle_helmet_flashlight))
if(istype(action, alight))
toggle_helmlight()
else
..()
@@ -297,60 +327,60 @@
/obj/item/clothing/head/helmet/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/flashlight/seclite))
var/obj/item/flashlight/seclite/S = I
if(can_flashlight)
if(!F)
if(!user.transferItemToLoc(S, src))
return
to_chat(user, "<span class='notice'>You click [S] into place on [src].</span>")
if(S.on)
set_light(0)
F = S
update_icon()
update_helmlight(user)
verbs += /obj/item/clothing/head/helmet/proc/toggle_helmlight
var/datum/action/A = new /datum/action/item_action/toggle_helmet_flashlight(src)
if(loc == user)
A.Grant(user)
if(can_flashlight && !attached_light)
if(!user.transferItemToLoc(S, src))
return
to_chat(user, "<span class='notice'>You click [S] into place on [src].</span>")
if(S.on)
set_light(0)
attached_light = S
update_icon()
update_helmlight()
alight = new(src)
if(loc == user)
alight.Grant(user)
return
if(I.tool_behaviour == TOOL_SCREWDRIVER)
if(F)
for(var/obj/item/flashlight/seclite/S in src)
to_chat(user, "<span class='notice'>You unscrew the seclite from [src].</span>")
F = null
S.forceMove(user.drop_location())
update_helmlight(user)
S.update_brightness(user)
update_icon()
usr.update_inv_head()
verbs -= /obj/item/clothing/head/helmet/proc/toggle_helmlight
for(var/datum/action/item_action/toggle_helmet_flashlight/THL in actions)
qdel(THL)
return
return ..()
/obj/item/clothing/head/helmet/screwdriver_act(mob/living/user, obj/item/I)
..()
if(can_flashlight && attached_light) //if it has a light but can_flashlight is false, the light is permanently attached.
I.play_tool_sound(src)
to_chat(user, "<span class='notice'>You unscrew [attached_light] from [src].</span>")
attached_light.forceMove(drop_location())
if(Adjacent(user) && !issilicon(user))
user.put_in_hands(attached_light)
var/obj/item/flashlight/removed_light = attached_light
attached_light = null
update_helmlight()
removed_light.update_brightness(user)
update_icon()
user.update_inv_head()
QDEL_NULL(alight)
return TRUE
/obj/item/clothing/head/helmet/proc/toggle_helmlight()
set name = "Toggle Helmetlight"
set category = "Object"
set desc = "Click to toggle your helmet's attached flashlight."
if(!F)
if(!attached_light)
return
var/mob/user = usr
if(user.incapacitated())
return
F.on = !F.on
to_chat(user, "<span class='notice'>You toggle the helmetlight [F.on ? "on":"off"].</span>")
attached_light.on = !attached_light.on
to_chat(user, "<span class='notice'>You toggle the helmet-light [attached_light.on ? "on":"off"].</span>")
playsound(user, 'sound/weapons/empty.ogg', 100, 1)
update_helmlight(user)
/obj/item/clothing/head/helmet/proc/update_helmlight(mob/user = null)
if(F)
if(F.on)
set_light(F.brightness_on, F.flashlight_power, F.light_color)
if(attached_light)
if(attached_light.on)
set_light(attached_light.brightness_on, attached_light.flashlight_power, attached_light.light_color)
else
set_light(0)
update_icon()
+1 -1
View File
@@ -53,5 +53,5 @@
desc = "An ironically skimpy blue dress with gold markings denoting the rank of \"Captain\"."
icon_state = "lewdcap"
item_state = "lewdcap"
can_adjust = FALSE
alt_covers_chest = TRUE
mutantrace_variation = STYLE_DIGITIGRADE|USE_TAUR_CLIP_MASK
+1 -1
View File
@@ -1,4 +1,4 @@
#define RANDOM_EVENT_ADMIN_INTERVENTION_TIME 10
#define RANDOM_EVENT_ADMIN_INTERVENTION_TIME 30
//this datum is used by the events controller to dictate how it selects events
/datum/round_event_control
+148 -1
View File
@@ -511,7 +511,150 @@
. |= MOBILITY_MOVE
mobility_flags = .
//Christmas car spawner
/mob/living/simple_animal/jacq/car_spawner
name = "Jacqueline cars terminal"
icon_state = "jacq_cars_spawner"
AIStatus = AI_OFF
spawn_cars = TRUE
active = FALSE
/mob/living/simple_animal/jacq/car_spawner/Destroy()
visible_message("The <b>[src]</b> gives out an error sound, <span class='spooky'>\"Ey! Bugger off!\"</span>")
fully_heal(FALSE)
return ..()
/mob/living/simple_animal/jacq/car_spawner/death()
visible_message("The <b>[src]</b> gives out an error sound, <span class='spooky'>\"Ey! Bugger off!\"</span>")
fully_heal(FALSE)
/mob/living/simple_animal/jacq/car_spawner/poof()
if(!active)//if disabled, don't poof
return
var/datum/reagents/R = new/datum/reagents(100)//Hey, just in case.
var/datum/effect_system/smoke_spread/chem/s = new()
R.add_reagent(/datum/reagent/fermi/secretcatchem, 10)
s.set_up(R, 0, loc)
s.start()
stopmove()
health = 25
/mob/living/simple_animal/jacq/car_spawner/spawn_cars(mob/living/carbon/C)
visible_message("<b>[src]</b> boots up and displays jacq's glowing smile, <span class='spooky'>\"Hallo there user! Merry Christmas! What ken type o' craft ken Ah offer ye? I can magic up a vectorcraft in manual, automatic or customise it if yer feeling technical.\"</span>")
jacqrunes("Hallo there user! What ken type o' craft ken Ah offer ye? I can magic up a vectorcraft in manual, automatic or customise it if yer feeling technical.", C)
var/choices_reward = list("Manual", "Automatic", "Customise", "Are you a computer now Jacq?", "Nothing, thanks")
var/choice_reward = input(usr, "Merry Trick_or_Treat.exe initiated!", "Merry Trick_or_Treat.exe initiated!") in choices_reward
switch(choice_reward)
if("Manual")
visible_message("The <b>[src]</b> makes a magical booping sound, <span class='spooky'>\"Great choice! 'Ere's yer car.\"</span>")
jacqrunes("Great choice! 'Ere's yer car.", C)
new /obj/vehicle/sealed/vectorcraft(loc)
if("Automatic")
visible_message("<b>[src]</b> makes a magical booping sound, <span class='spooky'>\"'Ere's yer car. Not as fast as an automatic mind.\"</span>")
jacqrunes("'Ere's yer car. Not as fast as an automatic mind.", C)
new /obj/vehicle/sealed/vectorcraft/auto(loc)
if("Are you a computer now Jacq?")
visible_message("<b>[src]</b> makes a frustrated error sound, <span class='spooky'>\"Nae, are ye daft? Ah built these thingies tae magic up cars fer ye. Well, I got a speccy four eyes tae do it fer me, but me names on it like cause it was me idea.\"</span>")
jacqrunes("Nae, are ye daft? Ah built these thingies tae magic up cars fer ye. Well, I got a speccy four eyes tae do it fer me, but me names on it like cause it was me idea.", C)
if("Customise")
visible_message("The <b>[src]</b> pings, <span class='spooky'>\"Arright, Manual or Automatic?\"</span>")
var/choices_transm = list("Manual", "Automatic")
var/choice_transm = input(usr, "Choose transmission", "Choose transmission") in choices_transm
var/points = 0
var/obj/vehicle/sealed/vectorcraft/VC
switch(choice_transm)
if("Manual")
VC = new /obj/vehicle/sealed/vectorcraft(loc)
if("Automatic")
VC = new /obj/vehicle/sealed/vectorcraft/auto(loc)
points += 500
visible_message("The <b>[src]</b> pings, <span class='spooky'>\"Maximum acceleration? (default [VC.max_acceleration], max 10)\"</span>")
var/max_accl = text2num(input(usr, "Maximum acceleration? (default [VC.max_acceleration], max 10)", "[VC.max_acceleration]"))
max_accl = clamp(max_accl, 0, 10)
VC.max_acceleration = max_accl
VC.i_m_acell = max_accl
points += max_accl*10
/* This is internally used
visible_message("The <b>[src]</b> pings, <span class='spooky'>\"Acceleration step? (default 0.3, max 1)\"</span>")
var/max_accl_s = text2num(input(usr, "Acceleration step? (default 0.3, max 1)", "[VC.accel_step]"))
max_accl_s = clamp(max_accl_s, 0, 1)
VC.max_acceleration = max_accl_s
points += max_accl_s*100
*/
visible_message("The <b>[src]</b> pings, <span class='spooky'>\"Acceleration? (default [VC.acceleration], max 2)\"</span>")
var/accl = text2num(input(usr, "Acceleration? (default [VC.acceleration], max 2)", "[VC.acceleration]"))
accl = clamp(accl, 0, 2)
VC.acceleration = accl
VC.i_acell = accl
points += accl*100
visible_message("The <b>[src]</b> pings, <span class='spooky'>\"Maximum deceleration? (default [VC.max_deceleration], max 15)\"</span>")
var/deaccl = text2num(input(usr, "Max_deceleration? (default [VC.max_deceleration], max 15)", "[VC.max_deceleration]"))
deaccl = clamp(deaccl, 0, 15)
VC.max_deceleration = deaccl
VC.i_m_decell = deaccl
points += deaccl*10
visible_message("The <b>[src]</b> pings, <span class='spooky'>\"Maximum velocity? (default [VC.max_velocity], max 200)\"</span>")
var/m_velo = text2num(input(usr, "Maximum velocity? (default [VC.max_velocity], max 200)", "[VC.max_velocity]"))
m_velo = clamp(m_velo, 0, 200)
VC.max_velocity = m_velo
points += m_velo
visible_message("The <b>[src]</b> pings, <span class='spooky'>\"Boost power? (default [VC.boost_power], max 200)\"</span>")
var/boost = text2num(input(usr, "Boost power? (default [VC.boost_power], max 200)", "[VC.boost_power]"))
boost = clamp(boost, 0, 200)
VC.boost_power = boost
VC.i_boost = boost
points += boost
visible_message("The <b>[src]</b> pings, <span class='spooky'>\"Health points? (default [VC.max_integrity], max 1000)\"</span>")
var/health = text2num(input(usr, "Health points? (default [VC.max_integrity], max 1000)", "[VC.max_integrity]"))
health = clamp(health, 0, 500)
VC.max_integrity = health
points += health/2
visible_message("The <b>[src]</b> pings, <span class='spooky'>\"Arright, 'ow do ye want it tae look?\"</span>")
var/choices_icon = list("Racer", "Truck", "Cyber", "Ambulance", "Pod", "Clown")
var/choice_icon = input(usr, "Choose body", "Choose body") in choices_icon
switch(choice_icon)
if("Truck")
VC.icon_state = "truck"
if("Cyber")
VC.icon_state = "cyber"
if("Ambulance")
VC.icon_state = "ambutruck"
if("Pod")
VC.icon_state = "engineering_pod"
if("Clown")
VC.icon_state = "clowncar"
visible_message("The <b>[src]</b> pings, <span class='spooky'>\"Finally; what name are ye gonna give it?\"</span>")
var/choice_name = input(usr, "Pick a name!", "")
choice_name += " (Points cost:[points])"
VC.name = choice_name
visible_message("The <b>[src]</b> gives a final boop, <span class='spooky'>\"There ye be, enjoy!\"</span>")
if("How do Automatics work?")
visible_message("The image of Jacq on the <b>[src]</b> smiles, <span class='spooky'>\"Hold wasd to gain speed in a direction, c to enable/disable the clutch, 1 2 3 4 to change gears (help is gear 1, disarm is gear 2, grab is gear 3 and harm is gear 4) while holding a direction (make sure the clutch is enabled when you change gears, you should hear a sound when you've successfully changed gears), r to toggle handbrake, hold alt for brake and press shift for boost (the machine will beep when the boost is recharged)! If you hear an ebbing sound like \"brbrbrbrbr\" you need to gear down, the whining sound means you need to gear up. Hearing a pleasant \"whumwhumwhum\" is optimal gearage! It can be a lil slow to start, so make sure you're in the 1st gear, andusing a boost to get you started is a good idea. If you've got a good speed you'll likely never need to dip down to gear 1 again, and make sure to hold the acceleration pedal down while changing gears (hold a direction). 1st gear is for slow movement, and it's a good idea to mvoe to 2nd gear as quick as you can, you can coldstart a car from gear one by slowly moving, then using the boost to jump you up to gear 2 speeds. The upper gears are for unlimiting your top speed.\"</span>")
jacqrunes("They're a bit tricky, aye. Basically;", C)
if("Nothing, thanks")
visible_message("The image of Jacq on the <b>[src]</b> shrugs, <span class='spooky'>\"Suit yerself.\"</span>")
jacqrunes("Suit yerself.", C)
visible_message("The <b>[src]</b> beeps, <span class='spooky'>\"Oh and look after the crafts, aye? They can get a wee bit... explosive if banged up a tad too much. They move slower damaged too like. Ye can repair 'em with the welders o'er there.\"</span>")
jacqrunes("Oh and look after the crafts, aye? They can get a wee bit... explosive if banged up a tad too much. They move slower damaged too like. Ye can repair 'em with the welders o'er there. ", C)
/obj/item/clothing/head/hardhat/pumpkinhead/jaqc
name = "Jacq o' latern"
@@ -588,9 +731,13 @@
/obj/item/reagent_containers/potion_container/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
..()
delayed_release_smoke()
/obj/item/reagent_containers/potion_container/proc/delayed_release_smoke()
set waitfor = FALSE
sleep(20)
var/datum/effect_system/smoke_spread/chem/s = new()
s.set_up(src.reagents, 3, src.loc)
s.set_up(src.reagents, 3, get_turf(src))
s.start()
qdel(src)
+184
View File
@@ -0,0 +1,184 @@
//Map exporter
//Inputting a list of turfs into convert_map_to_tgm() will output a string
//with the turfs and their objects / areas on said turf into the TGM mapping format
//for .dmm files. This file can then be opened in the map editor or imported
//back into the game.
//============================
//This has been made semi-modular so you should be able to use these functions
//elsewhere in code if you ever need to get a file in the .dmm format
/atom/proc/get_save_vars()
return
GLOBAL_LIST_INIT(save_file_chars, list(
"a","b","c","d","e",
"f","g","h","i","j",
"k","l","m","n","o",
"p","q","r","s","t",
"u","v","w","x","y",
"z","A","B","C","D",
"E","F","G","H","I",
"J","K","L","M","N",
"O","P","Q","R","S",
"T","U","V","W","X",
"Y","Z"
))
//Converts a list of turfs into TGM file format
/proc/convert_map_to_tgm(list/map,\
save_flag = SAVE_ALL, \
shuttle_area_flag = SAVE_SHUTTLEAREA_DONTCARE, \
list/vars_to_save = list("pixel_x", "pixel_y", "dir", "name", "req_access", "req_access_txt", "piping_layer", "color", "icon_state", "pipe_color", "amount"),\
list/obj_blacklist = list())
//Calculate the bounds
var/minx = 1024
var/miny = 1024
var/maxx = -1
var/maxy = -1
for(var/turf/place in map)
minx = min(place.x, minx)
miny = min(place.y, miny)
maxx = max(place.x, maxx)
maxy = max(place.y, maxy)
var/width = maxx - minx + 1
var/height = maxy - miny + 1
//Sort the map so weird shaped / bad inputted maps can be handled
var/list/sortedmap = sort_map(map, minx, miny, maxx, maxy)
//Step 0: Calculate the amount of letters we need (26 ^ n > turf count)
var/turfsNeeded = width * height
var/layers = FLOOR(log(GLOB.save_file_chars.len, turfsNeeded) + 0.999,1)
//Step 1: Run through the area and generate file data
var/list/header_chars = list() //The characters of the header
var/list/header_dat = list() //The data of the header, lines up with chars
var/header = "" //The actual header in text
var/contents = "" //The contents in text (bit at the end)
var/index = 1
for(var/x in 1 to width)
contents += "\n([x],1,1) = {\"\n"
for(var/y in height to 1 step -1)
//====Get turfs Data====
var/turf/place = sortedmap[x][y]
var/area/location
var/list/objects
//If there is nothing there, save as a noop (For odd shapes)
if(!place)
place = /turf/template_noop
location = /area/template_noop
objects = list()
//Ignore things in space, must be a space turf and the area has to be empty space
else if(istype(place, /turf/open/space) && istype(get_area(place), /area/space) && !(save_flag & SAVE_SPACE))
place = /turf/template_noop
location = /area/template_noop
//Stuff to add
else
var/area/location_type = get_area(place)
location = location_type.type
objects = place
place = place.type
//====Saving shuttles only / non shuttles only====
var/is_shuttle_area = istype(location, /area/shuttle)
if((is_shuttle_area && shuttle_area_flag == SAVE_SHUTTLEAREA_IGNORE) || (!is_shuttle_area && shuttle_area_flag == SAVE_SHUTTLEAREA_ONLY))
place = /turf/template_noop
location = /area/template_noop
objects = list()
//====For toggling not saving areas and turfs====
if(!(save_flag & SAVE_AREAS))
location = /area/template_noop
if(!(save_flag & SAVE_TURFS))
place = /turf/template_noop
//====Generate Header Character====
var/header_char = calculate_tgm_header_index(index, layers) //The characters of the header
var/current_header = "(\n" //The actual stuff inside the header
//Add objects to the header file
var/empty = TRUE
//====SAVING OBJECTS====
if(save_flag & SAVE_OBJECTS)
for(var/obj/thing in objects)
if(thing.type in obj_blacklist)
continue
var/metadata = generate_tgm_metadata(thing, vars_to_save)
current_header += "[empty?"":",\n"][thing.type][metadata]"
empty = FALSE
//====SAVING SPECIAL DATA====
//This is what causes lockers and machines to save stuff inside of them
if(save_flag & SAVE_OBJECT_PROPERTIES)
var/custom_data = thing.on_object_saved()
current_header += "[custom_data ? ",\n[custom_data]" : ""]"
//====SAVING MOBS====
if(save_flag & SAVE_MOBS)
for(var/mob/living/thing in objects)
if(istype(thing, /mob/living/carbon)) //Ignore people, but not animals
continue
var/metadata = generate_tgm_metadata(thing, vars_to_save)
current_header += "[empty?"":",\n"][thing.type][metadata]"
empty = FALSE
current_header += "[empty?"":",\n"][place],\n[location])\n"
//====Fill the contents file====
//Compression is done here
var/position_of_header = header_dat.Find(current_header)
if(position_of_header)
//If the header has already been saved, change the character to the other saved header
header_char = header_chars[position_of_header]
else
header += "\"[header_char]\" = [current_header]"
header_chars += header_char
header_dat += current_header
index ++
contents += "[header_char]\n"
contents += "\"}"
return "[header][contents]"
//Sorts maps in terms of their positions, so scrambled / odd shaped maps can be saved
/proc/sort_map(list/map, minx, miny, maxx, maxy)
var/width = maxx - minx + 1
var/height = maxy - miny + 1
var/allTurfs = new/list(width, height)
for(var/turf/place in map)
allTurfs[place.x - minx + 1][place.y - miny + 1] = place
return allTurfs
//vars_to_save = list() to save all vars
/proc/generate_tgm_metadata(atom/O, list/vars_to_save = list("pixel_x", "pixel_y", "dir", "name", "req_access", "req_access_txt", "piping_layer", "color", "icon_state", "pipe_color", "amount"))
var/dat = ""
var/data_to_add = list()
for(var/V in O.vars)
if(O.get_save_vars())
if(!(V in O.get_save_vars()))
continue
else
if(!(V in vars_to_save) && vars_to_save)
continue
var/value = O.vars[V]
if(!value)
continue
if(value == initial(O.vars[V]) || !issaved(O.vars[V]))
continue
var/symbol = ""
if(istext(value))
symbol = "\""
value = sanitize_simple(value, list("{"="", "}"="", "\""="", ";"="", ","=""))
else if(isicon(value) || isfile(value))
symbol = "'"
else if(!(isnum(value) || ispath(value)))
continue
//Prevent symbols from being because otherwise you can name something [";},/obj/item/gun/energy/laser/instakill{name="da epic gun] and spawn yourself an instakill gun.
data_to_add += "[V] = [symbol][value][symbol]"
//Process data to add
var/first = TRUE
for(var/data in data_to_add)
dat += "[first ? "" : ";\n"]\t[data]"
first = FALSE
if(dat)
dat = "{\n[dat]\n\t}"
return dat
/proc/calculate_tgm_header_index(index, layers)
var/output = ""
for(var/i in 1 to layers)
var/l = GLOB.save_file_chars.len
var/c = FLOOR((index-1) / (l ** (i - 1)), 1)
c = (c % l) + 1
output = "[GLOB.save_file_chars[c]][output]"
return output
@@ -190,6 +190,10 @@
icon = 'icons/obj/lavaland/survival_pod.dmi'
icon_state = "bed"
/obj/structure/bed/double/pod
icon = 'icons/obj/lavaland/survival_pod.dmi'
icon_state = "bed_double"
//Survival Storage Unit
/obj/machinery/smartfridge/survival_pod
name = "survival pod storage"
+79 -76
View File
@@ -60,83 +60,86 @@ GLOBAL_LIST_EMPTY(total_extraction_beacons)
return
if(A.anchored || (A.move_resist > max_force_fulton))
return
to_chat(user, "<span class='notice'>You start attaching the pack to [A]...</span>")
if(do_after(user,50,target=A))
to_chat(user, "<span class='notice'>You attach the pack to [A] and activate it.</span>")
if(loc == user && istype(user.back, /obj/item/storage/backpack))
var/obj/item/storage/backpack/B = user.back
SEND_SIGNAL(B, COMSIG_TRY_STORAGE_INSERT, src, user, FALSE, FALSE)
uses_left--
if(uses_left <= 0)
user.transferItemToLoc(src, A, TRUE)
var/mutable_appearance/balloon
var/mutable_appearance/balloon2
var/mutable_appearance/balloon3
if(isliving(A))
var/mob/living/M = A
M.DefaultCombatKnockdown(320) // Keep them from moving during the duration of the extraction
M.buckled = 0 // Unbuckle them to prevent anchoring problems
else
A.anchored = TRUE
A.density = FALSE
var/obj/effect/extraction_holder/holder_obj = new(A.loc)
holder_obj.appearance = A.appearance
A.forceMove(holder_obj)
balloon2 = mutable_appearance('icons/obj/fulton_balloon.dmi', "fulton_expand")
balloon2.pixel_y = 10
balloon2.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
holder_obj.add_overlay(balloon2)
sleep(4)
balloon = mutable_appearance('icons/obj/fulton_balloon.dmi', "fulton_balloon")
balloon.pixel_y = 10
balloon.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
holder_obj.cut_overlay(balloon2)
holder_obj.add_overlay(balloon)
playsound(holder_obj.loc, 'sound/items/fulext_deploy.wav', 50, 1, -3)
animate(holder_obj, pixel_z = 10, time = 20)
sleep(20)
animate(holder_obj, pixel_z = 15, time = 10)
sleep(10)
animate(holder_obj, pixel_z = 10, time = 10)
sleep(10)
animate(holder_obj, pixel_z = 15, time = 10)
sleep(10)
animate(holder_obj, pixel_z = 10, time = 10)
sleep(10)
playsound(holder_obj.loc, 'sound/items/fultext_launch.wav', 50, 1, -3)
animate(holder_obj, pixel_z = 1000, time = 30)
if(ishuman(A))
var/mob/living/carbon/human/L = A
L.SetUnconscious(0)
L.drowsyness = 0
L.SetSleeping(0)
sleep(30)
var/list/flooring_near_beacon = list()
for(var/turf/open/floor in orange(1, beacon))
flooring_near_beacon += floor
holder_obj.forceMove(pick(flooring_near_beacon))
animate(holder_obj, pixel_z = 10, time = 50)
sleep(50)
animate(holder_obj, pixel_z = 15, time = 10)
sleep(10)
animate(holder_obj, pixel_z = 10, time = 10)
sleep(10)
balloon3 = mutable_appearance('icons/obj/fulton_balloon.dmi', "fulton_retract")
balloon3.pixel_y = 10
balloon3.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
holder_obj.cut_overlay(balloon)
holder_obj.add_overlay(balloon3)
sleep(4)
holder_obj.cut_overlay(balloon3)
A.anchored = FALSE // An item has to be unanchored to be extracted in the first place.
A.density = initial(A.density)
animate(holder_obj, pixel_z = 0, time = 5)
sleep(5)
A.forceMove(holder_obj.loc)
qdel(holder_obj)
if(uses_left <= 0)
qdel(src)
attach_fulton(A, user, flag, params)
/obj/item/extraction_pack/proc/attach_fulton(atom/movable/A, mob/living/carbon/human/user, flag, params)
set waitfor = FALSE
to_chat(user, "<span class='notice'>You start attaching the pack to [A]...</span>")
if(do_after(user,50,target=A))
to_chat(user, "<span class='notice'>You attach the pack to [A] and activate it.</span>")
if(loc == user && istype(user.back, /obj/item/storage/backpack))
var/obj/item/storage/backpack/B = user.back
SEND_SIGNAL(B, COMSIG_TRY_STORAGE_INSERT, src, user, FALSE, FALSE)
uses_left--
if(uses_left <= 0)
user.transferItemToLoc(src, A, TRUE)
var/mutable_appearance/balloon
var/mutable_appearance/balloon2
var/mutable_appearance/balloon3
if(isliving(A))
var/mob/living/M = A
M.DefaultCombatKnockdown(320) // Keep them from moving during the duration of the extraction
M.buckled = 0 // Unbuckle them to prevent anchoring problems
else
A.anchored = TRUE
A.density = FALSE
var/obj/effect/extraction_holder/holder_obj = new(A.loc)
holder_obj.appearance = A.appearance
A.forceMove(holder_obj)
balloon2 = mutable_appearance('icons/obj/fulton_balloon.dmi', "fulton_expand")
balloon2.pixel_y = 10
balloon2.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
holder_obj.add_overlay(balloon2)
sleep(4)
balloon = mutable_appearance('icons/obj/fulton_balloon.dmi', "fulton_balloon")
balloon.pixel_y = 10
balloon.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
holder_obj.cut_overlay(balloon2)
holder_obj.add_overlay(balloon)
playsound(holder_obj.loc, 'sound/items/fulext_deploy.wav', 50, 1, -3)
animate(holder_obj, pixel_z = 10, time = 20)
sleep(20)
animate(holder_obj, pixel_z = 15, time = 10)
sleep(10)
animate(holder_obj, pixel_z = 10, time = 10)
sleep(10)
animate(holder_obj, pixel_z = 15, time = 10)
sleep(10)
animate(holder_obj, pixel_z = 10, time = 10)
sleep(10)
playsound(holder_obj.loc, 'sound/items/fultext_launch.wav', 50, 1, -3)
animate(holder_obj, pixel_z = 1000, time = 30)
if(ishuman(A))
var/mob/living/carbon/human/L = A
L.SetUnconscious(0)
L.drowsyness = 0
L.SetSleeping(0)
sleep(30)
var/list/flooring_near_beacon = list()
for(var/turf/open/floor in orange(1, beacon))
flooring_near_beacon += floor
holder_obj.forceMove(pick(flooring_near_beacon))
animate(holder_obj, pixel_z = 10, time = 50)
sleep(50)
animate(holder_obj, pixel_z = 15, time = 10)
sleep(10)
animate(holder_obj, pixel_z = 10, time = 10)
sleep(10)
balloon3 = mutable_appearance('icons/obj/fulton_balloon.dmi', "fulton_retract")
balloon3.pixel_y = 10
balloon3.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
holder_obj.cut_overlay(balloon)
holder_obj.add_overlay(balloon3)
sleep(4)
holder_obj.cut_overlay(balloon3)
A.anchored = FALSE // An item has to be unanchored to be extracted in the first place.
A.density = initial(A.density)
animate(holder_obj, pixel_z = 0, time = 5)
sleep(5)
A.forceMove(holder_obj.loc)
qdel(holder_obj)
if(uses_left <= 0)
qdel(src)
/obj/item/fulton_core
name = "extraction beacon signaller"
+14
View File
@@ -243,3 +243,17 @@ GLOBAL_LIST_EMPTY(silo_access_logs)
sep = ", "
msg += "[amount < 0 ? "-" : "+"][val] [M.name]"
formatted = msg.Join()
/obj/machinery/ore_silo/on_object_saved(var/depth = 0)
if(depth >= 10)
return ""
var/dat
var/datum/component/material_container/material_holder = GetComponent(/datum/component/material_container)
for(var/each in material_holder.materials)
var/amount = material_holder.materials[each] / MINERAL_MATERIAL_AMOUNT
var/datum/material/material_datum = each
while(amount > 0)
var/amount_in_stack = max(1, min(50, amount))
amount -= amount_in_stack
dat += "[dat ? ",\n" : ""][material_datum.sheet_type]{\n\tamount = [amount_in_stack]\n\t}"
return dat
@@ -2193,9 +2193,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
H.throw_alert("tempfeel", /atom/movable/screen/alert/cold, 2)
if(-35 to -20)
H.throw_alert("tempfeel", /atom/movable/screen/alert/cold, 1)
if(-20 to 0) //This is the sweet spot where air is considered normal
if(-20 to 1) //This is the sweet spot where air is considered normal
H.clear_alert("tempfeel")
if(0 to 15) //When the air around you matches your body's temperature, you'll start to feel warm.
if(1 to 15) //When the air around you matches your body's temperature, you'll start to feel warm.
H.throw_alert("tempfeel", /atom/movable/screen/alert/hot, 1)
if(15 to 30)
H.throw_alert("tempfeel", /atom/movable/screen/alert/hot, 2)
@@ -48,3 +48,4 @@
miss_sound = 'sound/weapons/slashmiss.ogg'
allowed_limb_ids = list("mammal","aquatic","avian", "human")
species_category = "robot"
+1 -1
View File
@@ -39,7 +39,7 @@
//Procs called while dead
/mob/living/carbon/proc/handle_death()
for(var/datum/reagent/R in reagents.reagent_list)
if(R.chemical_flags & REAGENT_DEAD_PROCESS)
if(R.chemical_flags & REAGENT_DEAD_PROCESS && !is_reagent_processing_invalid(R, src))
R.on_mob_dead(src)
///////////////
+1 -1
View File
@@ -125,7 +125,7 @@
if(IS_STAMCRIT(src))
to_chat(src, "<span class='warning'>You're too exhausted to crawl [(CHECK_MOBILITY(L, MOBILITY_STAND)) ? "under": "over"] [L].</span>")
return TRUE
combat_flags &= COMBAT_FLAG_ATTEMPTING_CRAWL
combat_flags |= COMBAT_FLAG_ATTEMPTING_CRAWL
visible_message("<span class='notice'>[src] is attempting to crawl [(CHECK_MOBILITY(L, MOBILITY_STAND)) ? "under" : "over"] [L].</span>",
"<span class='notice'>You are now attempting to crawl [(CHECK_MOBILITY(L, MOBILITY_STAND)) ? "under": "over"] [L].</span>",
target = L, target_message = "<span class='notice'>[src] is attempting to crawl [(CHECK_MOBILITY(L, MOBILITY_STAND)) ? "under" : "over"] you.</span>")
@@ -36,6 +36,8 @@
if(ismob(mover))
if(mover in buckled_mobs)
return TRUE
if(HAS_TRAIT(mover, TRAIT_BEING_CARRIED))
return TRUE //We're being carried and our carrier managed to pass, ergo, let us pass aswell.
var/mob/living/L = mover //typecast first, check isliving and only check this if living using short circuit
if(isliving(L) && lying && L.lying) //if we're both lying down and aren't already being thrown/shipped around, don't pass
return FALSE
+1
View File
@@ -15,6 +15,7 @@
/datum/movespeed_modifier/hunger
variable = TRUE
blacklisted_movetypes = FLOATING|FLYING
/datum/movespeed_modifier/slaughter
multiplicative_slowdown = -1
+4
View File
@@ -148,6 +148,10 @@
/obj/item/pen/afterattack(obj/O, mob/living/user, proximity)
. = ..()
//Changing name/description of items. Only works if they have the UNIQUE_RENAME object flag set
try_modify_object(O, user, proximity)
/obj/item/pen/proc/try_modify_object(obj/O, mob/living/user, proximity)
set waitfor = FALSE
if(isobj(O) && proximity && (O.obj_flags & UNIQUE_RENAME))
var/penchoice = input(user, "What would you like to edit?", "Rename, change description or reset both?") as null|anything in list("Rename","Change description","Reset")
if(QDELETED(O) || !user.canUseTopic(O, BE_CLOSE))
+2 -2
View File
@@ -235,10 +235,10 @@
if(POOL_SCALDING) //Scalding
M.adjust_bodytemperature(50,0,500)
if(POOL_WARM) //Warm
M.adjust_bodytemperature(20,0,360) //Heats up mobs till the thermometer shows up
M.adjust_bodytemperature(20,0,323.15) //Heats up mobs till the thermometer shows up
//Normal temp does nothing, because it's just room temperature water.
if(POOL_COOL)
M.adjust_bodytemperature(-20,250) //Cools mobs till the thermometer shows up
M.adjust_bodytemperature(-20,274.15) //Cools mobs till the thermometer shows up
if(POOL_FRIGID) //Freezing
M.adjust_bodytemperature(-60) //cool mob at -35k per cycle, less would not affect the mob enough.
if(M.bodytemperature <= 50 && !M.stat)
+158 -36
View File
@@ -1,5 +1,6 @@
#define DUALWIELD_PENALTY_EXTRA_MULTIPLIER 1.4
#define FIRING_PIN_REMOVAL_DELAY 50
/obj/item/gun
name = "gun"
@@ -63,7 +64,7 @@
var/obj/item/firing_pin/pin = /obj/item/firing_pin //standard firing pin for most guns
var/no_pin_required = FALSE //whether the gun can be fired without a pin
var/obj/item/flashlight/gun_light
var/obj/item/flashlight/seclite/gun_light
var/can_flashlight = FALSE
var/gunlight_state = "flight"
var/obj/item/kitchen/knife/bayonet
@@ -115,23 +116,28 @@
QDEL_NULL(chambered)
return ..()
/obj/item/gun/CheckParts(list/parts_list)
..()
var/obj/item/gun/G = locate(/obj/item/gun) in contents
if(G)
G.forceMove(loc)
QDEL_NULL(G.pin)
visible_message("[G] can now fit a new pin, but the old one was destroyed in the process.", null, null, 3)
qdel(src)
/obj/item/gun/examine(mob/user)
. = ..()
if(no_pin_required)
return
if(pin)
. += "It has \a [pin] installed."
else
. += "It doesn't have a firing pin installed, and won't fire."
if(!no_pin_required)
if(pin)
. += "It has \a [pin] installed."
. += "<span class='info'>[pin] looks like it could be removed with some <b>tools</b>.</span>"
else
. += "It doesn't have a firing pin installed, and won't fire."
if(gun_light)
. += "It has \a [gun_light] [can_flashlight ? "" : "permanently "]mounted on it."
if(can_flashlight) //if it has a light and this is false, the light is permanent.
. += "<span class='info'>[gun_light] looks like it can be <b>unscrewed</b> from [src].</span>"
else if(can_flashlight)
. += "It has a mounting point for a <b>seclite</b>."
if(bayonet)
. += "It has \a [bayonet] [can_bayonet ? "" : "permanently "]affixed to it."
if(can_bayonet) //if it has a bayonet and this is false, the bayonet is permanent.
. += "<span class='info'>[bayonet] looks like it can be <b>unscrewed</b> from [src].</span>"
else if(can_bayonet)
. += "It has a <b>bayonet</b> lug on it."
/obj/item/gun/equipped(mob/living/user, slot)
. = ..()
@@ -239,7 +245,7 @@
return
if(weapon_weight == WEAPON_HEAVY && user.get_inactive_held_item())
to_chat(user, "<span class='userdanger'>You need both hands free to fire \the [src]!</span>")
to_chat(user, "<span class='userdanger'>You need both hands free to fire [src]!</span>")
return
user.DelayNextAction()
@@ -417,12 +423,12 @@
if(!gun_light)
if(!user.transferItemToLoc(I, src))
return
to_chat(user, "<span class='notice'>You click \the [S] into place on \the [src].</span>")
to_chat(user, "<span class='notice'>You click [S] into place on [src].</span>")
if(S.on)
set_light(0)
gun_light = S
set_gun_light(S)
update_gunlight(user)
alight = new /datum/action/item_action/toggle_gunlight(src)
alight = new(src)
if(loc == user)
alight.Grant(user)
else if(istype(I, /obj/item/kitchen/knife))
@@ -431,27 +437,133 @@
return ..()
if(!user.transferItemToLoc(I, src))
return
to_chat(user, "<span class='notice'>You attach \the [K] to the front of \the [src].</span>")
to_chat(user, "<span class='notice'>You attach [K] to [src]'s bayonet lug.</span>")
bayonet = K
update_icon()
else if(I.tool_behaviour == TOOL_SCREWDRIVER)
if(gun_light)
var/obj/item/flashlight/seclite/S = gun_light
to_chat(user, "<span class='notice'>You unscrew the seclite from \the [src].</span>")
gun_light = null
S.forceMove(get_turf(user))
update_gunlight(user)
S.update_brightness(user)
QDEL_NULL(alight)
if(bayonet)
to_chat(user, "<span class='notice'>You unscrew the bayonet from \the [src].</span>")
var/obj/item/kitchen/knife/K = bayonet
K.forceMove(get_turf(user))
bayonet = null
update_icon()
else
return ..()
/obj/item/gun/screwdriver_act(mob/living/user, obj/item/I)
. = ..()
if(.)
return
if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
if((can_flashlight && gun_light) && (can_bayonet && bayonet)) //give them a choice instead of removing both
var/list/possible_items = list(gun_light, bayonet)
var/obj/item/item_to_remove = input(user, "Select an attachment to remove", "Attachment Removal") as null|obj in possible_items
if(!item_to_remove || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
return remove_gun_attachment(user, I, item_to_remove)
else if(gun_light && can_flashlight) //if it has a gun_light and can_flashlight is false, the flashlight is permanently attached.
return remove_gun_attachment(user, I, gun_light, "unscrewed")
else if(bayonet && can_bayonet) //if it has a bayonet, and the bayonet can be removed
return remove_gun_attachment(user, I, bayonet, "unfix")
else if(pin && user.is_holding(src))
user.visible_message(span_warning("[user] attempts to remove [pin] from [src] with [I]."),
span_notice("You attempt to remove [pin] from [src]. (It will take [DisplayTimeText(FIRING_PIN_REMOVAL_DELAY)].)"), null, 3)
if(I.use_tool(src, user, FIRING_PIN_REMOVAL_DELAY, volume = 50))
if(!pin) //check to see if the pin is still there, or we can spam messages by clicking multiple times during the tool delay
return
user.visible_message(span_notice("[pin] is pried out of [src] by [user], destroying the pin in the process."),
span_warning("You pry [pin] out with [I], destroying the pin in the process."), null, 3)
QDEL_NULL(pin)
return TRUE
/obj/item/gun/welder_act(mob/living/user, obj/item/I)
. = ..()
if(.)
return
if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
if(pin && user.is_holding(src))
user.visible_message(span_warning("[user] attempts to remove [pin] from [src] with [I]."),
span_notice("You attempt to remove [pin] from [src]. (It will take [DisplayTimeText(FIRING_PIN_REMOVAL_DELAY)].)"), null, 3)
if(I.use_tool(src, user, FIRING_PIN_REMOVAL_DELAY, 5, volume = 50))
if(!pin) //check to see if the pin is still there, or we can spam messages by clicking multiple times during the tool delay
return
user.visible_message(span_notice("[pin] is spliced out of [src] by [user], melting part of the pin in the process."),
span_warning("You splice [pin] out of [src] with [I], melting part of the pin in the process."), null, 3)
QDEL_NULL(pin)
return TRUE
/obj/item/gun/wirecutter_act(mob/living/user, obj/item/I)
. = ..()
if(.)
return
if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
if(pin && user.is_holding(src))
user.visible_message(span_warning("[user] attempts to remove [pin] from [src] with [I]."),
span_notice("You attempt to remove [pin] from [src]. (It will take [DisplayTimeText(FIRING_PIN_REMOVAL_DELAY)].)"), null, 3)
if(I.use_tool(src, user, FIRING_PIN_REMOVAL_DELAY, volume = 50))
if(!pin) //check to see if the pin is still there, or we can spam messages by clicking multiple times during the tool delay
return
user.visible_message(span_notice("[pin] is ripped out of [src] by [user], mangling the pin in the process."),
span_warning("You rip [pin] out of [src] with [I], mangling the pin in the process."), null, 3)
QDEL_NULL(pin)
return TRUE
/obj/item/gun/proc/remove_gun_attachment(mob/living/user, obj/item/tool_item, obj/item/item_to_remove, removal_verb)
if(tool_item)
tool_item.play_tool_sound(src)
to_chat(user, span_notice("You [removal_verb ? removal_verb : "remove"] [item_to_remove] from [src]."))
item_to_remove.forceMove(drop_location())
if(Adjacent(user) && !issilicon(user))
user.put_in_hands(item_to_remove)
if(item_to_remove == bayonet)
return clear_bayonet()
else if(item_to_remove == gun_light)
return clear_gunlight()
/obj/item/gun/proc/clear_bayonet()
if(!bayonet)
return
bayonet = null
update_appearance()
return TRUE
/obj/item/gun/proc/clear_gunlight()
if(!gun_light)
return
var/obj/item/flashlight/seclite/removed_light = gun_light
set_gun_light(null)
update_gunlight()
removed_light.update_brightness()
QDEL_NULL(alight)
return TRUE
/**
* Swaps the gun's seclight, dropping the old seclight if it has not been qdel'd.
*
* Returns the former gun_light that has now been replaced by this proc.
* Arguments:
* * new_light - The new light to attach to the weapon. Can be null, which will mean the old light is removed with no replacement.
*/
/obj/item/gun/proc/set_gun_light(obj/item/flashlight/seclite/new_light)
// Doesn't look like this should ever happen? We're replacing our old light with our old light?
if(gun_light == new_light)
CRASH("Tried to set a new gun light when the old gun light was also the new gun light.")
. = gun_light
// If there's an old gun light that isn't being QDELETED, detatch and drop it to the floor.
if(!QDELETED(gun_light))
if(gun_light.loc == src)
gun_light.forceMove(get_turf(src))
// If there's a new gun light to be added, attach and move it to the gun.
if(new_light)
if(new_light.loc != src)
new_light.forceMove(src)
gun_light = new_light
/obj/item/gun/ui_action_click(mob/user, action)
if(istype(action, /datum/action/item_action/toggle_scope_zoom))
zoom(user, user.dir)
@@ -606,9 +718,16 @@
user.client.view_size.zoomIn()
/obj/item/gun/handle_atom_del(atom/A)
if(A == pin)
pin = null
if(A == chambered)
chambered = null
update_icon()
if(A == bayonet)
clear_bayonet()
if(A == gun_light)
clear_gunlight()
return ..()
/obj/item/gun/proc/getinaccuracy(mob/living/user, bonus_spread, stamloss)
return 0 // Replacement TBD: Exponential curved aim instability system.
@@ -642,3 +761,6 @@
. = recoil
if(user && !user.has_gravity())
. = recoil*5
#undef FIRING_PIN_REMOVAL_DELAY
#undef DUALWIELD_PENALTY_EXTRA_MULTIPLIER
+1 -1
View File
@@ -215,7 +215,7 @@
if(isliving(target))
var/mob/living/L = target
hit_limb = L.check_limb_hit(def_zone)
SEND_SIGNAL(src, COMSIG_PROJECTILE_SELF_ON_HIT, firer, target, Angle, hit_limb)
SEND_SIGNAL(src, COMSIG_PROJECTILE_SELF_ON_HIT, firer, target, Angle, hit_limb, blocked)
var/turf/target_loca = get_turf(target)
var/hitx
@@ -345,6 +345,8 @@
if(owner && reagent)
if(!owner.reagent_check(reagent, delta_time, times_fired) != TRUE)
return
if(is_reagent_processing_invalid(reagent, owner))
return reagent.on_invalid_process(owner, delta_time, times_fired)
if(liverless && !reagent.self_consuming) //need to be metabolized
return
if(!reagent.metabolizing)
@@ -398,14 +398,23 @@
state = "Gas"
var/const/P = 3 //The number of seconds between life ticks
var/T = initial(R.metabolization_rate) * (60 / P)
var/processtype
if(CHECK_MULTIPLE_BITFIELDS(R.chemical_flags, (REAGENT_ROBOTIC_PROCESS | REAGENT_ORGANIC_PROCESS)))
processtype = "Both robots and organics"
else if(R.chemical_flags & REAGENT_ROBOTIC_PROCESS)
processtype = "Robots only"
else if(R.chemical_flags & REAGENT_ORGANIC_PROCESS)
processtype = "Organics only"
else
processtype = "Noone?! (Report this to Nanotrasen's spacetime department immediately)"
if(istype(R, /datum/reagent/fermi))
fermianalyze = TRUE
var/datum/chemical_reaction/Rcr = get_chemical_reaction(reagent)
var/pHpeakCache = (Rcr.OptimalpHMin + Rcr.OptimalpHMax)/2
analyzeVars = list("name" = initial(R.name), "state" = state, "color" = initial(R.color), "description" = initial(R.description), "metaRate" = T, "overD" = initial(R.overdose_threshold), "addicD" = initial(R.addiction_threshold), "purityF" = R.purity, "inverseRatioF" = initial(R.inverse_chem_val), "purityE" = initial(Rcr.PurityMin), "minTemp" = initial(Rcr.OptimalTempMin), "maxTemp" = initial(Rcr.OptimalTempMax), "eTemp" = initial(Rcr.ExplodeTemp), "pHpeak" = pHpeakCache)
analyzeVars = list("name" = initial(R.name), "state" = state, "color" = initial(R.color), "description" = initial(R.description), "metaRate" = T, "overD" = initial(R.overdose_threshold), "addicD" = initial(R.addiction_threshold), "processType" = processtype, "purityF" = R.purity, "inverseRatioF" = initial(R.inverse_chem_val), "purityE" = initial(Rcr.PurityMin), "minTemp" = initial(Rcr.OptimalTempMin), "maxTemp" = initial(Rcr.OptimalTempMax), "eTemp" = initial(Rcr.ExplodeTemp), "pHpeak" = pHpeakCache)
else
fermianalyze = FALSE
analyzeVars = list("name" = initial(R.name), "state" = state, "color" = initial(R.color), "description" = initial(R.description), "metaRate" = T, "overD" = initial(R.overdose_threshold), "addicD" = initial(R.addiction_threshold), "purityF" = R.purity)
analyzeVars = list("name" = initial(R.name), "state" = state, "color" = initial(R.color), "description" = initial(R.description), "metaRate" = T, "overD" = initial(R.overdose_threshold), "addicD" = initial(R.addiction_threshold), "processType" = processtype, "purityF" = R.purity)
screen = "analyze"
return TRUE
+6 -1
View File
@@ -50,7 +50,7 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent())
var/inverse_chem_val = 0 // If the impurity is below 0.5, replace ALL of the chem with inverse_chemupon metabolising
var/inverse_chem // What chem is metabolised when purity is below inverse_chem_val, this shouldn't be made, but if it does, well, I guess I'll know about it.
var/metabolizing = FALSE
var/chemical_flags // See fermi/readme.dm REAGENT_DEAD_PROCESS, REAGENT_DONOTSPLIT, REAGENT_ONLYINVERSE, REAGENT_ONMOBMERGE, REAGENT_INVISIBLE, REAGENT_FORCEONNEW, REAGENT_SNEAKYNAME
var/chemical_flags = REAGENT_ORGANIC_PROCESS // See fermi/readme.dm REAGENT_DEAD_PROCESS, REAGENT_DONOTSPLIT, REAGENT_ONLYINVERSE, REAGENT_ONMOBMERGE, REAGENT_INVISIBLE, REAGENT_FORCEONNEW, REAGENT_SNEAKYNAME, REAGENT_ORGANIC_PROCESS, REAGENT_ROBOTIC_PROCESS
var/value = REAGENT_VALUE_NONE //How much does it sell for in cargo?
var/datum/material/material //are we made of material?
@@ -87,6 +87,11 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent())
if(holder)
holder.remove_reagent(type, metabolization_rate * M.metabolism_efficiency) //By default it slowly disappears.
//Called when an reagent is incompatible with its processing carbon (e.g. robot carbon and reagent with only organic processing)
/datum/reagent/proc/on_invalid_process(mob/living/carbon/M)
if(holder)
holder.remove_reagent(type, INVALID_REAGENT_DISSIPATION) //Not influenced by normal metab rate nor efficiency.
//called when a mob processes chems when dead.
/datum/reagent/proc/on_mob_dead(mob/living/carbon/M)
if(!(chemical_flags & REAGENT_DEAD_PROCESS)) //justincase
@@ -41,10 +41,6 @@ All effects don't start immediately, but rather get worse over time; the rate is
if(!iscarbon(L))
return
var/mob/living/carbon/C = L
if(HAS_TRAIT(C, TRAIT_ROBOTIC_ORGANISM))
C.reagents.remove_reagent(type, amount, FALSE)
/datum/reagent/consumable/ethanol/on_mob_life(mob/living/carbon/C)
if(HAS_TRAIT(C, TRAIT_TOXIC_ALCOHOL))
C.adjustToxLoss((boozepwr/25)*REAGENTS_EFFECT_MULTIPLIER,forced = TRUE)
@@ -3,7 +3,7 @@
//Invert = Whole conversion
/datum/reagent/impure
chemical_flags = REAGENT_INVISIBLE | REAGENT_SNEAKYNAME //by default, it will stay hidden on splitting, but take the name of the source on inverting
chemical_flags = REAGENT_INVISIBLE | REAGENT_SNEAKYNAME | REAGENT_ORGANIC_PROCESS //by default, it will stay hidden on splitting, but take the name of the source on inverting
/datum/reagent/impure/fermiTox
@@ -17,6 +17,7 @@
/datum/reagent/medicine/leporazine
name = "Leporazine"
description = "Leporazine will effectively regulate a patient's body temperature, ensuring it never leaves safe levels."
chemical_flags = REAGENT_ALL_PROCESS
pH = 8.4
color = "#82b8aa"
value = REAGENT_VALUE_COMMON
@@ -32,6 +33,7 @@
name = "Adminordrazine"
description = "It's magic. We don't have to explain it."
color = "#ffffff"
chemical_flags = REAGENT_ALL_PROCESS
can_synth = FALSE
taste_description = "badmins"
value = REAGENT_VALUE_GLORIOUS
@@ -103,6 +105,7 @@
name = "Synaptizine"
description = "Increases resistance to stuns as well as reducing drowsiness and hallucinations."
color = "#FF00FF"
chemical_flags = REAGENT_ALL_PROCESS
pH = 4
/datum/reagent/medicine/synaptizine/on_mob_life(mob/living/carbon/M)
@@ -121,6 +124,7 @@
name = "Diphen-Synaptizine"
description = "Reduces drowsiness, hallucinations, and Histamine from body."
color = "#EC536D" // rgb: 236, 83, 109
chemical_flags = REAGENT_ALL_PROCESS
pH = 5.2
value = REAGENT_VALUE_COMMON
@@ -140,6 +144,7 @@
name = "Inacusiate"
description = "Instantly restores all hearing to the patient, but does not cure deafness."
color = "#6600FF" // rgb: 100, 165, 255
chemical_flags = REAGENT_ALL_PROCESS
pH = 2
value = 10
@@ -152,6 +157,7 @@
description = "A chemical mixture with almost magical healing powers. Its main limitation is that the patient's body temperature must be under 270K for it to metabolise correctly."
color = "#0000C8"
taste_description = "sludge"
chemical_flags = REAGENT_ALL_PROCESS
pH = 11
value = REAGENT_VALUE_COMMON
@@ -183,6 +189,7 @@
color = "#0000C8"
taste_description = "muscle"
metabolization_rate = 1.5 * REAGENTS_METABOLISM
chemical_flags = REAGENT_ALL_PROCESS
pH = 13
value = REAGENT_VALUE_COMMON
@@ -199,6 +206,7 @@
description = "A mixture of cryoxadone and slime jelly, that apparently inverses the requirement for its activation."
color = "#f7832a"
taste_description = "spicy jelly"
chemical_flags = REAGENT_ALL_PROCESS
pH = 12
value = REAGENT_VALUE_UNCOMMON
@@ -232,6 +240,7 @@
description = "A powder derived from fish toxin, Rezadone can effectively treat genetic damage as well as restoring minor wounds. Overdose will cause intense nausea and minor toxin damage."
reagent_state = SOLID
color = "#669900" // rgb: 102, 153, 0
chemical_flags = REAGENT_ALL_PROCESS
overdose_threshold = 30
taste_description = "fish"
pH = 12.2
@@ -265,6 +274,7 @@
description = "Spaceacillin will prevent a patient from conventionally spreading any diseases they are currently infected with. Also reduces infection in serious burns."
color = "#f2f2f2"
metabolization_rate = 0.1 * REAGENTS_METABOLISM
chemical_flags = REAGENT_ALL_PROCESS
pH = 8.1
//Goon Chems. Ported mainly from Goonstation. Easily mixable (or not so easily) and provide a variety of effects.
@@ -394,6 +404,7 @@
reagent_state = LIQUID
color = "#DCDCDC"
metabolization_rate = 0.5 * REAGENTS_METABOLISM
chemical_flags = REAGENT_ALL_PROCESS
overdose_threshold = 60
taste_description = "sweetness and salt"
var/extra_regen = 0.25 // in addition to acting as temporary blood, also add this much to their actual blood per tick
@@ -527,6 +538,7 @@
reagent_state = LIQUID
color = "#000000"
metabolization_rate = 0.5 * REAGENTS_METABOLISM
chemical_flags = REAGENT_ALL_PROCESS
taste_description = "ash"
pH = 5
@@ -578,6 +590,7 @@
reagent_state = LIQUID
color = "#19C832"
metabolization_rate = 0.5 * REAGENTS_METABOLISM
chemical_flags = REAGENT_ALL_PROCESS
taste_description = "acid"
pH = 1.5
@@ -597,6 +610,7 @@
reagent_state = LIQUID
color = "#14FF3C"
metabolization_rate = 2 * REAGENTS_METABOLISM
chemical_flags = REAGENT_ALL_PROCESS
pH = 12 //It's a reducing agent
/datum/reagent/medicine/potass_iodide/on_mob_life(mob/living/carbon/M)
@@ -610,6 +624,7 @@
reagent_state = LIQUID
color = "#003153" // RGB 0, 49, 83
metabolization_rate = 0.5 * REAGENTS_METABOLISM
chemical_flags = REAGENT_ALL_PROCESS
pH = 8.9
value = REAGENT_VALUE_COMMON //uncraftable
@@ -624,6 +639,7 @@
reagent_state = LIQUID
color = "#E6FFF0"
metabolization_rate = 0.5 * REAGENTS_METABOLISM
chemical_flags = REAGENT_ALL_PROCESS
pH = 1 //One of the best buffers, NEVERMIND!
value = REAGENT_VALUE_UNCOMMON
var/healtoxinlover = FALSE
@@ -677,6 +693,7 @@
reagent_state = LIQUID
color = "#00FFFF"
metabolization_rate = 0.25 * REAGENTS_METABOLISM
chemical_flags = REAGENT_ALL_PROCESS
pH = 2
/datum/reagent/medicine/salbutamol/on_mob_life(mob/living/carbon/M)
@@ -693,6 +710,7 @@
reagent_state = LIQUID
color = "#FF6464"
metabolization_rate = 0.25 * REAGENTS_METABOLISM
chemical_flags = REAGENT_ALL_PROCESS
pH = 11
/datum/reagent/medicine/perfluorodecalin/on_mob_life(mob/living/carbon/human/M)
@@ -871,6 +889,7 @@
reagent_state = LIQUID
color = "#FFFFFF"
metabolization_rate = 0.25 * REAGENTS_METABOLISM
chemical_flags = REAGENT_ALL_PROCESS
taste_description = "dull toxin"
pH = 10
@@ -901,6 +920,7 @@
reagent_state = LIQUID
color = "#000000"
metabolization_rate = 0.25 * REAGENTS_METABOLISM
chemical_flags = REAGENT_ALL_PROCESS
overdose_threshold = 35
pH = 12
value = REAGENT_VALUE_UNCOMMON
@@ -931,6 +951,7 @@
reagent_state = LIQUID
color = "#D2FFFA"
metabolization_rate = 0.25 * REAGENTS_METABOLISM
chemical_flags = REAGENT_ALL_PROCESS
overdose_threshold = 30
pH = 10.2
@@ -966,6 +987,7 @@
reagent_state = LIQUID
color = "#A0E85E"
metabolization_rate = 0.5 * REAGENTS_METABOLISM
chemical_flags = REAGENT_ALL_PROCESS
taste_description = "magnets"
pH = 0
value = REAGENT_VALUE_RARE
@@ -1031,6 +1053,7 @@
description = "Efficiently restores brain damage."
color = "#DCDCFF"
pH = 10.4
chemical_flags = REAGENT_ALL_PROCESS
/datum/reagent/medicine/mannitol/on_mob_life(mob/living/carbon/C)
C.adjustOrganLoss(ORGAN_SLOT_BRAIN, -2*REAGENTS_EFFECT_MULTIPLIER)
@@ -1042,6 +1065,7 @@
name = "Neurine"
description = "Reacts with neural tissue, helping reform damaged connections. Can cure minor traumas."
color = "#EEFF8F"
chemical_flags = REAGENT_ALL_PROCESS
/datum/reagent/medicine/neurine/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
if(!(method == INJECT))
@@ -1071,6 +1095,7 @@
color = "#5096C8"
taste_description = "acid"
pH = 2
chemical_flags = REAGENT_ALL_PROCESS
/datum/reagent/medicine/mutadone/on_mob_life(mob/living/carbon/M)
M.jitteriness = 0
@@ -1106,6 +1131,7 @@
metabolization_rate = 0.5 * REAGENTS_METABOLISM
overdose_threshold = 60
pH = 8.7
chemical_flags = REAGENT_ALL_PROCESS
value = REAGENT_VALUE_RARE
/datum/reagent/medicine/stimulants/on_mob_metabolize(mob/living/L)
@@ -1144,6 +1170,7 @@
reagent_state = LIQUID
color = "#FFFFF0"
metabolization_rate = 0.5 * REAGENTS_METABOLISM
chemical_flags = REAGENT_ALL_PROCESS
pH = 6.7
/datum/reagent/medicine/insulin/on_mob_life(mob/living/carbon/M)
@@ -1176,6 +1203,7 @@
description = "Restores oxygen loss. Overdose causes it instead."
reagent_state = LIQUID
color = "#13d2f0"
chemical_flags = REAGENT_ALL_PROCESS
overdose_threshold = 30
pH = 9.7
@@ -1239,6 +1267,7 @@
reagent_state = LIQUID
pH = 8.5
color = "#5dc1f0"
chemical_flags = REAGENT_ALL_PROCESS
/datum/reagent/medicine/inaprovaline/on_mob_life(mob/living/carbon/M)
if(M.losebreath >= 5)
@@ -1292,6 +1321,7 @@
reagent_state = SOLID
color = "#555555"
pH = 11
chemical_flags = REAGENT_ALL_PROCESS
value = REAGENT_VALUE_EXCEPTIONAL
/datum/reagent/medicine/syndicate_nanites/on_mob_life(mob/living/carbon/M)
@@ -1313,6 +1343,7 @@
reagent_state = SOLID
color = "#555555"
pH = 11
chemical_flags = REAGENT_ALL_PROCESS
value = REAGENT_VALUE_VERY_RARE
/datum/reagent/medicine/lesser_syndicate_nanites/on_mob_life(mob/living/carbon/M)
@@ -1447,6 +1478,7 @@
color = "#C1151D"
overdose_threshold = 30
value = REAGENT_VALUE_VERY_RARE
chemical_flags = REAGENT_ALL_PROCESS
/datum/reagent/medicine/changelingadrenaline/on_mob_life(mob/living/carbon/metabolizer, delta_time, times_fired)
..()
@@ -1480,6 +1512,7 @@
description = "Drastically increases movement speed."
color = "#AE151D"
metabolization_rate = 2.5 * REAGENTS_METABOLISM
chemical_flags = REAGENT_ALL_PROCESS
/datum/reagent/medicine/changelinghaste/on_mob_metabolize(mob/living/L)
..()
@@ -1495,6 +1528,7 @@
name = "Corazone"
description = "A medication used to treat pain, fever, and inflammation, along with heart attacks."
color = "#F5F5F5"
chemical_flags = REAGENT_ALL_PROCESS
self_consuming = TRUE
pH = 12.5
@@ -1594,6 +1628,7 @@
reagent_state = LIQUID
color = "#07E79E"
metabolization_rate = 0.25 * REAGENTS_METABOLISM
chemical_flags = REAGENT_ALL_PROCESS
overdose_threshold = 30
pH = 9.12
value = REAGENT_VALUE_COMMON
@@ -1629,6 +1664,7 @@
reagent_state = SOLID
color = "#FFFFD0"
metabolization_rate = 1.5 * REAGENTS_METABOLISM
chemical_flags = REAGENT_ALL_PROCESS
value = REAGENT_VALUE_UNCOMMON
/datum/reagent/medicine/silibinin/on_mob_life(mob/living/carbon/M)
@@ -1642,6 +1678,7 @@
reagent_state = SOLID
color = "#9423FF"
metabolization_rate = 0.25 * REAGENTS_METABOLISM
chemical_flags = REAGENT_ALL_PROCESS
overdose_threshold = 50
taste_description = "numbing bitterness"
value = REAGENT_VALUE_RARE
@@ -1671,6 +1708,7 @@
taste_mult = 4
can_synth = FALSE
overdose_threshold = 30
chemical_flags = REAGENT_ALL_PROCESS
value = REAGENT_VALUE_UNCOMMON // while it's 'rare', it can be milked from the wisdom cow
/datum/reagent/medicine/liquid_wisdom/on_mob_life(mob/living/carbon/C) //slightly stronger mannitol, from the wisdom cow
@@ -1688,6 +1726,7 @@
reagent_state = LIQUID
color = "#bb2424"
metabolization_rate = 0.25 * REAGENTS_METABOLISM
chemical_flags = REAGENT_ALL_PROCESS
overdose_threshold = 20
/// How much base clotting we do per bleeding wound, multiplied by the below number for each bleeding wound
var/clot_rate = 0.25
@@ -1742,18 +1781,21 @@
reagent_state = LIQUID
color = "#D7C9C6"
metabolization_rate = 0.2 * REAGENTS_METABOLISM
chemical_flags = REAGENT_ALL_PROCESS
overdose_threshold = 30
/datum/reagent/medicine/system_cleaner/on_mob_life(mob/living/carbon/M)
. = ..()
if(HAS_TRAIT(M, TRAIT_ROBOTIC_ORGANISM))
M.adjustToxLoss(-0.2, toxins_type = TOX_SYSCORRUPT)
M.adjustToxLoss(-0.4*REAGENTS_EFFECT_MULTIPLIER, toxins_type = TOX_SYSCORRUPT)
else
M.adjustToxLoss(0.5)
M.adjustToxLoss(0.5*REAGENTS_EFFECT_MULTIPLIER)
. = 1
/datum/reagent/medicine/system_cleaner/overdose_process(mob/living/carbon/M)
. = ..()
if(HAS_TRAIT(M, TRAIT_ROBOTIC_ORGANISM))
M.adjustToxLoss(0.4, toxins_type = TOX_SYSCORRUPT) //inverts its positive effect on overdose, for organics it's just more toxic
M.adjustToxLoss(0.8*REAGENTS_EFFECT_MULTIPLIER, toxins_type = TOX_SYSCORRUPT) //inverts its positive effect on overdose, for organics it's just more toxic
else
M.adjustToxLoss(0.5)
M.adjustToxLoss(0.5*REAGENTS_EFFECT_MULTIPLIER)
. = 1
@@ -1,6 +1,7 @@
/datum/reagent/blood
data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_HUMAN, "blood_type"= null,"resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null,"quirks"=null)
name = "Blood"
chemical_flags = REAGENT_ALL_PROCESS
value = REAGENT_VALUE_UNCOMMON // $$$ blood ""donations"" $$$
color = BLOOD_COLOR_HUMAN // rgb: 200, 0, 0
description = "Blood from some creature."
@@ -223,6 +224,7 @@
/datum/reagent/vaccine
//data must contain virus type
name = "Vaccine"
chemical_flags = REAGENT_ALL_PROCESS
color = "#C81040" // rgb: 200, 16, 64
taste_description = "slime"
@@ -243,6 +245,7 @@
description = "An ubiquitous chemical substance that is composed of hydrogen and oxygen."
color = "#AAAAAA77" // rgb: 170, 170, 170, 77 (alpha)
taste_description = "water"
chemical_flags = REAGENT_ALL_PROCESS
overdose_threshold = 150 //Imagine drinking a gallon of water
var/cooling_temperature = 2
glass_icon_state = "glass_clear"
@@ -339,6 +342,7 @@
name = "Holy Water"
description = "Water blessed by some deity."
color = "#E0E8EF" // rgb: 224, 232, 239
chemical_flags = REAGENT_ALL_PROCESS
glass_icon_state = "glass_clear"
glass_name = "glass of holy water"
glass_desc = "A glass of holy water."
@@ -474,6 +478,7 @@
name = "Hell Water"
description = "YOUR FLESH! IT BURNS!"
taste_description = "burning"
chemical_flags = REAGENT_ALL_PROCESS
value = REAGENT_VALUE_VERY_RARE
/datum/reagent/hellwater/on_mob_life(mob/living/carbon/M)
@@ -533,6 +538,7 @@
/datum/reagent/lube
name = "Space Lube"
description = "Lubricant is a substance introduced between two moving surfaces to reduce the friction and wear between them. giggity."
chemical_flags = REAGENT_ALL_PROCESS
color = "#009CA8" // rgb: 0, 156, 168
taste_description = "cherry" // by popular demand
var/lube_kind = TURF_WET_LUBE ///What kind of slipperiness gets added to turfs.
@@ -644,6 +650,7 @@
description = "A humanizing toxin."
color = "#5EFF3B" //RGB: 94, 255, 59
metabolization_rate = INFINITY //So it instantly removes all of itself
chemical_flags = REAGENT_ALL_PROCESS
taste_description = "slime"
value = REAGENT_VALUE_RARE
var/datum/species/race = /datum/species/human
@@ -808,6 +815,7 @@
/datum/reagent/slime_toxin
name = "Slime Mutation Toxin"
description = "A toxin that turns organic material into slime."
chemical_flags = REAGENT_ALL_PROCESS
color = "#5EFF3B" //RGB: 94, 255, 59
taste_description = "slime"
metabolization_rate = 0.2
@@ -847,6 +855,7 @@
description = "This toxin will rapidly change the DNA of human beings. Commonly used by Syndicate spies and assassins in need of an emergency ID change."
color = "#5EFF3B" //RGB: 94, 255, 59
metabolization_rate = INFINITY
chemical_flags = REAGENT_ALL_PROCESS
taste_description = "slime"
value = REAGENT_VALUE_RARE
@@ -873,6 +882,7 @@
name = "Gluttony's Blessing"
description = "An advanced corruptive toxin produced by something terrible."
color = "#5EFF3B" //RGB: 94, 255, 59
chemical_flags = REAGENT_ALL_PROCESS
can_synth = FALSE
taste_description = "decay"
value = REAGENT_VALUE_GLORIOUS
@@ -1086,6 +1096,7 @@
/datum/reagent/radium
name = "Radium"
description = "Radium is an alkaline earth metal. It is extremely radioactive."
chemical_flags = REAGENT_ALL_PROCESS
reagent_state = SOLID
color = "#C7C7C7" // rgb: 199,199,199
taste_description = "the colour blue and regret"
@@ -1112,6 +1123,7 @@
/datum/reagent/space_cleaner/sterilizine
name = "Sterilizine"
description = "Sterilizes wounds in preparation for surgery."
chemical_flags = REAGENT_ALL_PROCESS
color = "#e6f1f5" // rgb: 200, 165, 220
taste_description = "bitterness"
pH = 10.5
@@ -1138,6 +1150,7 @@
reagent_state = SOLID
taste_description = "iron"
pH = 6
chemical_flags = REAGENT_ALL_PROCESS
overdose_threshold = 30
color = "#c2391d"
material = /datum/material/iron
@@ -1190,6 +1203,7 @@
/datum/reagent/uranium
name ="Uranium"
description = "A silvery-white metallic chemical element in the actinide series, weakly radioactive."
chemical_flags = REAGENT_ALL_PROCESS
reagent_state = SOLID
color = "#B8B8C0" // rgb: 184, 184, 192
taste_description = "the inside of a reactor"
@@ -1219,6 +1233,7 @@
/datum/reagent/bluespace
name = "Bluespace Dust"
description = "A dust composed of microscopic bluespace crystals, with minor space-warping properties."
chemical_flags = REAGENT_ALL_PROCESS
reagent_state = SOLID
color = "#0000CC"
taste_description = "fizzling blue"
@@ -1245,6 +1260,7 @@
/datum/reagent/telecrystal
name = "Telecrystal Dust"
description = "A blood-red dust comprised of something that was much more useful when it was intact."
chemical_flags = REAGENT_ALL_PROCESS //Sure?
reagent_state = SOLID
color = "#660000" // rgb: 102, 0, 0.
taste_description = "contraband"
@@ -1269,6 +1285,7 @@
name = "Welding fuel"
description = "Required for welders. Flamable."
color = "#660000" // rgb: 102, 0, 0
chemical_flags = REAGENT_ALL_PROCESS
taste_description = "gross metal"
glass_icon_state = "dr_gibb_glass"
glass_name = "glass of welder fuel"
@@ -1357,6 +1374,7 @@
name = "EZ Clean"
description = "A powerful, acidic cleaner sold by Waffle Co. Affects organic matter while leaving other objects unaffected."
metabolization_rate = 1.5 * REAGENTS_METABOLISM
chemical_flags = REAGENT_ALL_PROCESS
taste_description = "acid"
pH = 2
value = REAGENT_VALUE_RARE
@@ -1559,6 +1577,7 @@
description = "An unstable experimental gas that greatly increases the energy of those that inhale it"
reagent_state = GAS
metabolization_rate = 1.5 * REAGENTS_METABOLISM
chemical_flags = REAGENT_ALL_PROCESS
color = "E1A116"
taste_description = "sourness"
value = REAGENT_VALUE_EXCEPTIONAL
@@ -1827,6 +1846,7 @@
/datum/reagent/colorful_reagent
name = "Colorful Reagent"
description = "Thoroughly sample the rainbow."
chemical_flags = REAGENT_ALL_PROCESS
reagent_state = LIQUID
color = "#FFFF00"
var/list/random_color_list = list("#00aedb","#a200ff","#f47835","#d41243","#d11141","#00b159","#00aedb","#f37735","#ffc425","#008744","#0057e7","#d62d20","#ffa700")
@@ -2117,6 +2137,7 @@
color = "#123524" // RGB (18, 53, 36)
metabolization_rate = INFINITY
can_synth = FALSE
chemical_flags = REAGENT_ALL_PROCESS
taste_description = "brains"
pH = 0.5
value = REAGENT_VALUE_GLORIOUS
@@ -2132,6 +2153,7 @@
name = "Magillitis"
description = "An experimental serum which causes rapid muscular growth in Hominidae. Side-affects may include hypertrichosis, violent outbursts, and an unending affinity for bananas."
reagent_state = LIQUID
chemical_flags = REAGENT_ALL_PROCESS
color = "#00f041"
value = REAGENT_VALUE_EXCEPTIONAL
@@ -2145,6 +2167,7 @@
description = "A commercial chemical designed to help older men in the bedroom."//not really it just makes you a giant
color = "#ff0000"//strong red. rgb 255, 0, 0
var/current_size = RESIZE_DEFAULT_SIZE
chemical_flags = REAGENT_ALL_PROCESS
value = REAGENT_VALUE_COMMON
taste_description = "bitterness" // apparently what viagra tastes like
@@ -2233,6 +2256,7 @@
color = "#FAFF00"
taste_description = "acrid cinnamon"
metabolization_rate = 0.2 * REAGENTS_METABOLISM
chemical_flags = REAGENT_ALL_PROCESS //Sorry robot lings, but you still get this.
value = REAGENT_VALUE_UNCOMMON
/datum/reagent/bz_metabolites/on_mob_metabolize(mob/living/L)
@@ -2320,7 +2344,7 @@
can_synth = FALSE
var/datum/dna/original_dna
var/reagent_ticks = 0
chemical_flags = REAGENT_INVISIBLE
chemical_flags = REAGENT_INVISIBLE | REAGENT_ALL_PROCESS
value = REAGENT_VALUE_GLORIOUS
/datum/reagent/changeling_string/on_mob_metabolize(mob/living/carbon/C)
@@ -2377,6 +2401,7 @@
description = "A powerful preservation agent, utilizing the preservative effects of formaldehyde with significantly less of the histamine."
reagent_state = LIQUID
color = "#f7685e"
chemical_flags = REAGENT_ALL_PROCESS
metabolization_rate = REAGENTS_METABOLISM * 0.25
@@ -2428,6 +2453,7 @@
color = "#050096" // rgb: 5, 0, 150
taste_mult = 0 // oderless and tasteless
metabolization_rate = 0.1 * REAGENTS_METABOLISM //20 times as long, so it's actually viable to use
chemical_flags = REAGENT_ALL_PROCESS
var/time_multiplier = 1 MINUTES //1 minute per unit of gravitum on objects. Seems overpowered, but the whole thing is very niche
/datum/reagent/gravitum/reaction_obj(obj/O, volume)
@@ -2507,6 +2533,7 @@
reagent_state = LIQUID
color = "#D2FFFA"
metabolization_rate = 0.75 * REAGENTS_METABOLISM // 5u (WOUND_DETERMINATION_CRITICAL) will last for ~17 ticks
chemical_flags = REAGENT_ALL_PROCESS
/// Whether we've had at least WOUND_DETERMINATION_SEVERE (2.5u) of determination at any given time. No damage slowdown immunity or indication we're having a second wind if it's just a single moderate wound
var/significant = FALSE
self_consuming = TRUE
@@ -2540,6 +2567,7 @@
name = "Eldritch Essence"
description = "Strange liquid that defies the laws of physics"
taste_description = "Ag'hsj'saje'sh"
chemical_flags = REAGENT_ALL_PROCESS
color = "#1f8016"
/datum/reagent/eldritch/on_mob_life(mob/living/carbon/M)
@@ -2624,6 +2652,7 @@
description = "A unknown red liquid, linked to healing of most moral wounds."
color = "#c10000"
metabolization_rate = REAGENTS_METABOLISM * 2.5
chemical_flags = REAGENT_ALL_PROCESS
/datum/reagent/red_ichor/on_mob_life(mob/living/carbon/M)
M.adjustBruteLoss(-50)
@@ -2641,6 +2670,7 @@
description = "A unknown green liquid, linked to healing of most internal wounds."
color = "#158c00"
metabolization_rate = REAGENTS_METABOLISM * 2.5
chemical_flags = REAGENT_ALL_PROCESS
/datum/reagent/green_ichor/on_mob_life(mob/living/carbon/M)
M.adjustOrganLoss(ORGAN_SLOT_LUNGS, -100)
@@ -2658,6 +2688,7 @@
description = "A unknown blue liquid, linked to healing the mind."
color = "#0914e0"
metabolization_rate = REAGENTS_METABOLISM * 2.5
chemical_flags = REAGENT_ALL_PROCESS
/datum/reagent/blue_ichor/on_mob_life(mob/living/carbon/M)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, -100)
@@ -2,6 +2,7 @@
/datum/reagent/thermite
name = "Thermite"
description = "Thermite produces an aluminothermic reaction known as a thermite reaction. Can be used to melt walls."
chemical_flags = REAGENT_ALL_PROCESS
reagent_state = SOLID
color = "#550000"
taste_description = "sweet tasting metal"
@@ -44,6 +45,7 @@
reagent_state = LIQUID
color = "#FFC8C8"
metabolization_rate = 4
chemical_flags = REAGENT_ALL_PROCESS
taste_description = "burning"
value = REAGENT_VALUE_COMMON
@@ -146,6 +148,7 @@
/datum/reagent/phlogiston
name = "Phlogiston"
description = "Catches you on fire and makes you ignite."
chemical_flags = REAGENT_ALL_PROCESS
reagent_state = LIQUID
color = "#FA00AF"
taste_description = "burning"
@@ -168,6 +171,7 @@
/datum/reagent/napalm
name = "Napalm"
description = "Very flammable."
chemical_flags = REAGENT_ALL_PROCESS
reagent_state = LIQUID
color = "#FA00AF"
taste_description = "burning"
@@ -197,6 +201,7 @@
color = "#0000DC"
metabolization_rate = 0.5 * REAGENTS_METABOLISM
taste_description = "bitterness"
chemical_flags = REAGENT_ALL_PROCESS
value = REAGENT_VALUE_COMMON
/datum/reagent/cryostylane/on_mob_life(mob/living/carbon/M) //TODO: code freezing into an ice cube
@@ -215,6 +220,7 @@
description = "Comes into existence at 20K. As long as there is sufficient oxygen for it to react with, Pyrosium slowly heats all other reagents in the container."
color = "#64FAC8"
metabolization_rate = 0.5 * REAGENTS_METABOLISM
chemical_flags = REAGENT_ALL_PROCESS
taste_description = "bitterness"
value = REAGENT_VALUE_COMMON
@@ -230,6 +236,7 @@
reagent_state = LIQUID
color = "#20324D" //RGB: 32, 50, 77
metabolization_rate = 0.5 * REAGENTS_METABOLISM
chemical_flags = REAGENT_ALL_PROCESS
taste_description = "charged metal"
var/shock_timer = 0
value = REAGENT_VALUE_VERY_RARE
@@ -35,6 +35,7 @@
name = "Unstable mutagen"
description = "Might cause unpredictable mutations. Keep away from children."
color = "#00FF00"
chemical_flags = REAGENT_ALL_PROCESS
toxpwr = 0
taste_description = "slime"
taste_mult = 0.9
@@ -448,6 +449,7 @@
reagent_state = LIQUID
color = "#787878"
metabolization_rate = 0.125 * REAGENTS_METABOLISM
chemical_flags = REAGENT_ALL_PROCESS
toxpwr = 0
value = REAGENT_VALUE_VERY_RARE
@@ -495,6 +497,7 @@
reagent_state = LIQUID
color = "#B4004B"
metabolization_rate = 0.5 * REAGENTS_METABOLISM
chemical_flags = REAGENT_ALL_PROCESS
toxpwr = 1
/datum/reagent/toxin/formaldehyde/on_mob_life(mob/living/carbon/M)
@@ -869,6 +872,7 @@
description = "A strong mineral acid with the molecular formula H2SO4."
color = "#00FF32"
toxpwr = 1
chemical_flags = REAGENT_ALL_PROCESS //Ever injected acid into a robot?
var/acidpwr = 10 //the amount of protection removed from the armour
taste_description = "acid"
self_consuming = TRUE
+26 -8
View File
@@ -19,6 +19,7 @@
var/list/research_logs = list() //IC logs.
var/largest_bomb_value = 0
var/organization = "Third-Party" //Organization name, used for display.
var/list/next_income = list() //To be applied on the next passive techweb income
var/list/last_bitcoins = list() //Current per-second production, used for display only.
var/list/discovered_mutations = list() //Mutations discovered by genetics, this way they are shared and cant be destroyed by destroying a single console
var/list/tiers = list() //Assoc list, id = number, 1 is available, 2 is all reqs are 1, so on
@@ -105,10 +106,15 @@
V.rescan_views()
V.updateUsrDialog()
/datum/techweb/proc/add_point_list(list/pointlist)
for(var/i in pointlist)
if(SSresearch.point_types[i] && pointlist[i] > 0)
research_points[i] += pointlist[i]
/datum/techweb/proc/add_point_list(list/pointlist, income = TRUE)
if(income) // i DO NOT TRUST byond to optimize this way properly
for(var/i in pointlist)
if(SSresearch.point_types[i] && pointlist[i] > 0)
next_income[i] += pointlist[i]
else
for(var/i in pointlist)
if(SSresearch.point_types[i] && pointlist[i] > 0)
research_points[i] += pointlist[i]
/datum/techweb/proc/add_points_all(amount)
var/list/l = SSresearch.point_types.Copy()
@@ -116,6 +122,12 @@
l[i] = amount
add_point_list(l)
/datum/techweb/proc/commit_income()
. = next_income.Copy()
add_point_list(next_income, income = FALSE)
for(var/i in next_income)
next_income[i] = 0
/datum/techweb/proc/remove_point_list(list/pointlist)
for(var/i in pointlist)
if(SSresearch.point_types[i] && pointlist[i] > 0)
@@ -170,16 +182,22 @@
/datum/techweb/proc/get_researched_nodes()
return researched_nodes - hidden_nodes
/datum/techweb/proc/add_point_type(type, amount)
/datum/techweb/proc/add_point_type(type, amount, income = TRUE)
if(!SSresearch.point_types[type] || (amount <= 0))
return FALSE
research_points[type] += amount
if(income)
next_income[type] += amount
else
research_points[type] += amount
return TRUE
/datum/techweb/proc/modify_point_type(type, amount)
/datum/techweb/proc/modify_point_type(type, amount, income = TRUE)
if(!SSresearch.point_types[type])
return FALSE
research_points[type] = max(0, research_points[type] + amount)
if(income && amount > 0)
next_income[type] += amount
else
research_points[type] = max(0, research_points[type] + amount)
return TRUE
/datum/techweb/proc/remove_point_type(type, amount)
@@ -92,6 +92,10 @@
icon_state = "capturedevice"
/obj/item/capturedevice/attack(mob/living/M, mob/user)
try_catching(M, user)
/obj/item/capturedevice/proc/try_catching(mob/living/M, mob/user)
set waitfor = FALSE
if(length(contents))
to_chat(user, "<span class='warning'>The device already has something inside.</span>")
return
@@ -116,7 +120,7 @@
to_chat(user, "<span class='warning'>This creature is too aggressive to capture.</span>")
return
to_chat(user, "<span class='notice'>You store [M] in the capture device.</span>")
store(M)
store(M, user)
/obj/item/capturedevice/attack_self(mob/user)
if(contents.len)
@@ -125,7 +129,10 @@
else
to_chat(user, "<span class='warning'>The device is empty...</span>")
/obj/item/capturedevice/proc/store(var/mob/living/M)
/obj/item/capturedevice/proc/store(var/mob/living/M, mob/user)
if(length(contents))
to_chat(user, "<span class='warning'>The device already has something inside.</span>")
return
M.forceMove(src)
/obj/item/capturedevice/proc/release()
@@ -735,7 +735,10 @@
if(jb)
to_chat(user, "<span class='warning'>Your mind goes blank as you attempt to use the potion.</span>")
return
try_transfer_mind(SM, user)
/obj/item/slimepotion/transference/proc/try_transfer_mind(mob/living/simple_animal/SM, mob/user)
set waitfor = FALSE
prompted = 1
if(alert("This will permanently transfer your consciousness to [SM]. Are you sure you want to do this?",,"Yes","No")=="No")
prompted = 0
-1
View File
@@ -223,7 +223,6 @@
var/alert_type = null
if(ispath(breathing_class))
breathing_class = breathing_classes[breathing_class]
var/list/gases = breathing_class.gases
alert_category = breathing_class.high_alert_category
alert_type = breathing_class.high_alert_datum
danger_reagent = breathing_class.danger_reagent
+21
View File
@@ -13,3 +13,24 @@
desc = "A keyring with a small steel key, and a pink fob reading \"Pussy Wagon\"."
icon_state = "keyjanitor"
//START VECTORCARKEYS
/obj/item/key/CMO
desc = "A keyring with a small steel key to the CMO\'s race hovercar."
/obj/item/key/RD
desc = "A keyring with a small steel key to the RD\'s race hovercar."
/obj/item/key/hop
desc = "A keyring with a small steel key to the HOP\'s race hovercar."
/obj/item/key/hos
desc = "A keyring with a small steel key to the HOS\'s race hovercar."
/obj/item/key/CE
desc = "A keyring with a small steel key to the CE\'s race hovercar."
/obj/item/key/QM
desc = "A keyring with a small steel key to the QM\'s race hovercar."
/obj/item/key/CAPT
desc = "A keyring with a small steel key to the Captain\'s race hovercar."