Merge branch 'master' into reaction-scaling

This commit is contained in:
lass9030
2018-10-21 14:36:32 +02:00
132 changed files with 4007 additions and 3881 deletions
+10 -1
View File
@@ -663,8 +663,17 @@ Traitors and the like can also be revived with the previous role mostly intact.
return
if(job_master)
var/currentpositiontally
var/totalpositiontally
to_chat(src, "<span class='notice'>Job Name: Filled job slot / Total job slots <b>(Free job slots)</b></span>")
for(var/datum/job/job in job_master.occupations)
to_chat(src, "[job.title]: [job.total_positions]")
to_chat(src, "<span class='notice'>[job.title]: [job.current_positions] / \
[job.total_positions == -1 ? "<b>UNLIMITED</b>" : job.total_positions] \
<b>([job.total_positions == -1 ? "UNLIMITED" : job.total_positions - job.current_positions])</b></span>")
if(job.total_positions != -1) // Only count position that isn't unlimited
currentpositiontally += job.current_positions
totalpositiontally += job.total_positions
to_chat(src, "<b>Currently filled job slots (Excluding unlimited): [currentpositiontally] / [totalpositiontally] ([totalpositiontally - currentpositiontally])</b>")
feedback_add_details("admin_verb","LFS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_admin_explosion(atom/O as obj|mob|turf in view())
+368 -366
View File
@@ -13,216 +13,216 @@
var/list/datum/automation/automations = list()
receive_signal(datum/signal/signal)
if(!signal || signal.encryption) return
/obj/machinery/computer/general_air_control/atmos_automation/receive_signal(datum/signal/signal)
if(!signal || signal.encryption) return
var/id_tag = signal.data["tag"]
if(!id_tag)
return
var/id_tag = signal.data["tag"]
if(!id_tag)
return
sensor_information[id_tag] = signal.data
sensor_information[id_tag] = signal.data
process()
if(on)
for(var/datum/automation/A in automations)
A.process()
/obj/machinery/computer/general_air_control/atmos_automation/process()
if(on)
for(var/datum/automation/A in automations)
A.process()
update_icon()
/obj/machinery/computer/general_air_control/atmos_automation/update_icon()
icon_state = initial(icon_state)
// Broken
if(stat & BROKEN)
icon_state += "b"
// Powered
else if(stat & NOPOWER)
icon_state = initial(icon_state)
// Broken
if(stat & BROKEN)
icon_state += "b"
icon_state += "0"
else if(on)
icon_state += "_active"
// Powered
else if(stat & NOPOWER)
icon_state = initial(icon_state)
icon_state += "0"
else if(on)
icon_state += "_active"
/obj/machinery/computer/general_air_control/atmos_automation/proc/request_device_refresh(device)
send_signal(list("tag"=device, "status"))
proc/request_device_refresh(var/device)
send_signal(list("tag"=device, "status"))
/obj/machinery/computer/general_air_control/atmos_automation/proc/send_signal(list/data, filter = RADIO_ATMOSIA)//filter's here so the AAC can cross communicate to things like vents, which have a different filter
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.source = src
signal.data=data
signal.data["sigtype"]="command"
signal.data["advcontrol"]=1//AAC balancing, you need to manually get up to the machine to make it listen to this
radio_connection.post_signal(src, signal, range = 8, filter = filter)
proc/send_signal(var/list/data, var/filter = RADIO_ATMOSIA)//filter's here so the AAC can cross communicate to things like vents, which have a different filter
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.source = src
signal.data=data
signal.data["sigtype"]="command"
signal.data["advcontrol"]=1//AAC balancing, you need to manually get up to the machine to make it listen to this
radio_connection.post_signal(src, signal, range = 8, filter = filter)
/obj/machinery/computer/general_air_control/atmos_automation/proc/selectValidChildFor(datum/automation/parent, mob/user, list/valid_returntypes)
var/list/choices=list()
for(var/childtype in automation_types)
var/datum/automation/A = new childtype(src)
if(A.returntype == null)
continue
if(!(A.returntype in valid_returntypes))
continue
choices[A.name]=A
if(choices.len==0)
testing("Unable to find automations with returntype in [english_list(valid_returntypes)]!")
return 0
var/label=input(user, "Select new automation:", "Automations", "Cancel") as null|anything in choices
if(!label)
return 0
return choices[label]
proc/selectValidChildFor(var/datum/automation/parent, var/mob/user, var/list/valid_returntypes)
var/list/choices=list()
for(var/childtype in automation_types)
var/datum/automation/A = new childtype(src)
if(A.returntype == null)
continue
if(!(A.returntype in valid_returntypes))
continue
choices[A.name]=A
if(choices.len==0)
testing("Unable to find automations with returntype in [english_list(valid_returntypes)]!")
return 0
var/label=input(user, "Select new automation:", "Automations", "Cancel") as null|anything in choices
if(!label)
return 0
return choices[label]
/obj/machinery/computer/general_air_control/atmos_automation/return_text()
var/out=..()
return_text()
var/out=..()
if(on)
out += "<a href=\"?src=[UID()];on=1\" style=\"font-size:large;font-weight:bold;color:red;\">RUNNING</a>"
else
out += "<a href=\"?src=[UID()];on=1\" style=\"font-size:large;font-weight:bold;color:green;\">STOPPED</a>"
if(on)
out += "<a href=\"?src=[UID()];on=1\" style=\"font-size:large;font-weight:bold;color:red;\">RUNNING</a>"
else
out += "<a href=\"?src=[UID()];on=1\" style=\"font-size:large;font-weight:bold;color:green;\">STOPPED</a>"
out += {"
<h2>Automations</h2>
<p>\[
<a href="?src=[UID()];add=1">
Add
</a>
|
<a href="?src=[UID()];reset=*">
Reset All
</a>
|
<a href="?src=[UID()];remove=*">
Clear
</a>
\]</p>
<p>\[
<a href="?src=[UID()];dump=1">
Export
</a>
|
<a href="?src=[UID()];read=1">
Import
</a>
\]</p>"}
if(automations.len==0)
out += "<i>No automations present.</i>"
else
for(var/datum/automation/A in automations)
out += {"
<fieldset>
<legend>
<a href="?src=[UID()];label=\ref[A]">[A.label]</a>
(<a href="?src=[UID()];reset=\ref[A]">Reset</a> |
<a href="?src=[UID()];remove=\ref[A]">&times;</a>)
</legend>
[A.GetText()]
</fieldset>
"}
return out
out += {"
<h2>Automations</h2>
<p>\[
<a href="?src=[UID()];add=1">
Add
</a>
|
<a href="?src=[UID()];reset=*">
Reset All
</a>
|
<a href="?src=[UID()];remove=*">
Clear
</a>
\]</p>
<p>\[
<a href="?src=[UID()];dump=1">
Export
</a>
|
<a href="?src=[UID()];read=1">
Import
</a>
\]</p>"}
if(automations.len==0)
out += "<i>No automations present.</i>"
else
/obj/machinery/computer/general_air_control/atmos_automation/Topic(href,href_list)
if(..())
return 1
if(href_list["on"])
on = !on
updateUsrDialog()
update_icon()
return 1
if(href_list["add"])
var/new_child=selectValidChildFor(null,usr,list(0))
if(!new_child)
return 1
automations += new_child
updateUsrDialog()
return 1
if(href_list["label"])
var/datum/automation/A=locate(href_list["label"])
if(!A) return 1
var/nl=input(usr, "Please enter a label for this automation task.") as text|null
if(!nl) return 1
nl = copytext(sanitize(nl), 1, 50)
A.label=nl
updateUsrDialog()
return 1
if(href_list["reset"])
if(href_list["reset"]=="*")
for(var/datum/automation/A in automations)
out += {"
<fieldset>
<legend>
<a href="?src=[UID()];label=\ref[A]">[A.label]</a>
(<a href="?src=[UID()];reset=\ref[A]">Reset</a> |
<a href="?src=[UID()];remove=\ref[A]">&times;</a>)
</legend>
[A.GetText()]
</fieldset>
"}
return out
Topic(href,href_list)
if(..())
return 1
if(href_list["on"])
on = !on
updateUsrDialog()
update_icon()
return 1
if(href_list["add"])
var/new_child=selectValidChildFor(null,usr,list(0))
if(!new_child)
return 1
automations += new_child
updateUsrDialog()
return 1
if(href_list["label"])
var/datum/automation/A=locate(href_list["label"])
if(!A) return 1
var/nl=input(usr, "Please enter a label for this automation task.") as text|null
if(!nl) return 1
nl = copytext(sanitize(nl), 1, 50)
A.label=nl
updateUsrDialog()
return 1
if(href_list["reset"])
if(href_list["reset"]=="*")
for(var/datum/automation/A in automations)
if(!A) continue
A.OnReset()
else
var/datum/automation/A=locate(href_list["reset"])
if(!A) return 1
if(!A) continue
A.OnReset()
updateUsrDialog()
return 1
else
var/datum/automation/A=locate(href_list["reset"])
if(!A) return 1
A.OnReset()
updateUsrDialog()
return 1
if(href_list["remove"])
if(href_list["remove"]=="*")
var/confirm=alert("Are you sure you want to remove ALL automations?","Automations","Yes","No")
if(confirm == "No") return 0
for(var/datum/automation/A in automations)
if(!A) continue
A.OnRemove()
automations.Remove(A)
else
var/datum/automation/A=locate(href_list["remove"])
if(!A) return 1
if(href_list["remove"])
if(href_list["remove"]=="*")
var/confirm=alert("Are you sure you want to remove ALL automations?","Automations","Yes","No")
if(confirm == "No") return 0
for(var/datum/automation/A in automations)
if(!A) continue
A.OnRemove()
automations.Remove(A)
updateUsrDialog()
return 1
else
var/datum/automation/A=locate(href_list["remove"])
if(!A) return 1
A.OnRemove()
automations.Remove(A)
updateUsrDialog()
return 1
if(href_list["read"])
var/code = input("Input exported AAC code.","Automations","") as message|null
if(!code) return 0
ReadCode(code)
updateUsrDialog()
return 1
if(href_list["read"])
var/code = input("Input exported AAC code.","Automations","") as message|null
if(!code) return 0
ReadCode(code)
updateUsrDialog()
return 1
if(href_list["dump"])
input("Exported AAC code:","Automations",DumpCode()) as message|null
return 0
if(href_list["dump"])
input("Exported AAC code:","Automations",DumpCode()) as message|null
return 0
proc/MakeCompare(var/datum/automation/a, var/datum/automation/b, var/comparetype)
var/datum/automation/compare/compare=new(src)
compare.comparator = comparetype
compare.children[1] = a
compare.children[2] = b
return compare
/obj/machinery/computer/general_air_control/atmos_automation/proc/MakeCompare(datum/automation/a, datum/automation/b, comparetype)
var/datum/automation/compare/compare=new(src)
compare.comparator = comparetype
compare.children[1] = a
compare.children[2] = b
return compare
proc/MakeNumber(var/value)
var/datum/automation/static_value/val = new(src)
val.value=value
return val
/obj/machinery/computer/general_air_control/atmos_automation/proc/MakeNumber(value)
var/datum/automation/static_value/val = new(src)
val.value=value
return val
proc/MakeGetSensorData(var/sns_tag,var/field)
var/datum/automation/get_sensor_data/sensor=new(src)
sensor.sensor=sns_tag
sensor.field=field
return sensor
/obj/machinery/computer/general_air_control/atmos_automation/proc/MakeGetSensorData(sns_tag,field)
var/datum/automation/get_sensor_data/sensor=new(src)
sensor.sensor=sns_tag
sensor.field=field
return sensor
proc/DumpCode()
var/list/json[0]
for(var/datum/automation/A in automations)
json += list(A.Export())
return json_encode(json)
/obj/machinery/computer/general_air_control/atmos_automation/proc/DumpCode()
var/list/json[0]
for(var/datum/automation/A in automations)
json += list(A.Export())
return json_encode(json)
proc/ReadCode(var/jsonStr)
automations.Cut()
var/list/json = json_decode(jsonStr)
if(json.len>0)
for(var/list/cData in json)
if(isnull(cData) || !("type" in cData))
testing("AAC: Null cData in root JS array.")
continue
var/Atype=text2path(cData["type"])
if(!(Atype in automation_types))
testing("AAC: Unrecognized Atype [Atype].")
continue
var/datum/automation/A = new Atype(src)
A.Import(cData)
automations += A
/obj/machinery/computer/general_air_control/atmos_automation/proc/ReadCode(jsonStr)
automations.Cut()
var/list/json = json_decode(jsonStr)
if(json.len>0)
for(var/list/cData in json)
if(isnull(cData) || !("type" in cData))
testing("AAC: Null cData in root JS array.")
continue
var/Atype=text2path(cData["type"])
if(!(Atype in automation_types))
testing("AAC: Unrecognized Atype [Atype].")
continue
var/datum/automation/A = new Atype(src)
A.Import(cData)
automations += A
/obj/machinery/computer/general_air_control/atmos_automation/burnchamber
var/injector_tag="inc_in"
@@ -230,79 +230,80 @@
var/sensor_tag="inc_sensor"
frequency=1449
var/temperature=1000
New()
..()
// On State
// Pretty much this:
/*
if(get_sensor("inc_sensor","temperature") < 200)
set_injector_state("inc_in",1)
set_vent_pump_power("inc_out",0)
else
set_vent_pump_power("inc_out",1
*/
/obj/machinery/computer/general_air_control/atmos_automation/burnchamber/New()
..()
var/datum/automation/get_sensor_data/sensor=new(src)
sensor.sensor=sensor_tag
sensor.field="temperature"
// On State
// Pretty much this:
/*
if(get_sensor("inc_sensor","temperature") < 200)
set_injector_state("inc_in",1)
set_vent_pump_power("inc_out",0)
else
set_vent_pump_power("inc_out",1
*/
var/datum/automation/static_value/val = new(src)
val.value=temperature - 800
var/datum/automation/get_sensor_data/sensor=new(src)
sensor.sensor=sensor_tag
sensor.field="temperature"
var/datum/automation/compare/compare=new(src)
compare.comparator = "Less Than"
compare.children[1] = sensor
compare.children[2] = val
var/datum/automation/static_value/val = new(src)
val.value=temperature - 800
var/datum/automation/set_injector_power/inj_on=new(src)
inj_on.injector=injector_tag
inj_on.state=1
var/datum/automation/compare/compare=new(src)
compare.comparator = "Less Than"
compare.children[1] = sensor
compare.children[2] = val
var/datum/automation/set_vent_pump_power/vp_on=new(src)
vp_on.vent_pump=output_tag
vp_on.state=1
var/datum/automation/set_injector_power/inj_on=new(src)
inj_on.injector=injector_tag
inj_on.state=1
var/datum/automation/set_vent_pump_power/vp_off=new(src)
vp_off.vent_pump=output_tag
vp_off.state=0
var/datum/automation/set_vent_pump_power/vp_on=new(src)
vp_on.vent_pump=output_tag
vp_on.state=1
var/datum/automation/if_statement/i = new (src)
i.label = "Fuel Injector On"
i.condition = compare
i.children_then.Add(inj_on)
i.children_then.Add(vp_off)
i.children_else.Add(vp_on)
var/datum/automation/set_vent_pump_power/vp_off=new(src)
vp_off.vent_pump=output_tag
vp_off.state=0
automations += i
var/datum/automation/if_statement/i = new (src)
i.label = "Fuel Injector On"
i.condition = compare
i.children_then.Add(inj_on)
i.children_then.Add(vp_off)
i.children_else.Add(vp_on)
// Off state
/*
if(get_sensor("inc_sensor","temperature") > 1000)
set_injector_state("inc_in",0)
*/
sensor=new(src)
sensor.sensor=sensor_tag
sensor.field="temperature"
automations += i
val = new(src)
val.value=temperature
// Off state
/*
if(get_sensor("inc_sensor","temperature") > 1000)
set_injector_state("inc_in",0)
*/
sensor=new(src)
sensor.sensor=sensor_tag
sensor.field="temperature"
compare=new(src)
compare.comparator = "Greater Than"
compare.children[1] = sensor
compare.children[2] = val
val = new(src)
val.value=temperature
var/datum/automation/set_injector_power/inj_off=new(src)
inj_off.injector=injector_tag
inj_off.state=0
compare=new(src)
compare.comparator = "Greater Than"
compare.children[1] = sensor
compare.children[2] = val
i = new (src)
i.label = "Fuel Injector Off"
i.condition = compare
i.children_then.Add(inj_off)
var/datum/automation/set_injector_power/inj_off=new(src)
inj_off.injector=injector_tag
inj_off.state=0
automations += i
i = new (src)
i.label = "Fuel Injector Off"
i.condition = compare
i.children_then.Add(inj_off)
automations += i
/obj/machinery/computer/general_air_control/atmos_automation/air_mixing
var/n2_injector_tag="air_n2_in"
@@ -311,142 +312,143 @@
var/sensor_tag="air_sensor"
frequency=1443
var/temperature=1000
New()
..()
buildO2()
buildN2()
buildOutletVent()
proc/buildO2()
///////////////////////////////////////////////////////////////
// Oxygen Injection
///////////////////////////////////////////////////////////////
/obj/machinery/computer/general_air_control/atmos_automation/air_mixing/New()
..()
buildO2()
buildN2()
buildOutletVent()
var/datum/automation/set_injector_power/inj_on=new(src)
inj_on.injector=o2_injector_tag
inj_on.state=1
/obj/machinery/computer/general_air_control/atmos_automation/air_mixing/proc/buildO2()
///////////////////////////////////////////////////////////////
// Oxygen Injection
///////////////////////////////////////////////////////////////
var/datum/automation/set_injector_power/inj_off=new(src)
inj_off.injector=o2_injector_tag
inj_off.state=0
var/datum/automation/set_injector_power/inj_on=new(src)
inj_on.injector=o2_injector_tag
inj_on.state=1
var/datum/automation/if_statement/i = new (src)
i.label = "Oxygen Injection"
i.condition = MakeCompare(
var/datum/automation/set_injector_power/inj_off=new(src)
inj_off.injector=o2_injector_tag
inj_off.state=0
var/datum/automation/if_statement/i = new (src)
i.label = "Oxygen Injection"
i.condition = MakeCompare(
MakeGetSensorData(sensor_tag,"oxygen"),
MakeNumber(20),
"Less Than or Equal to"
)
i.children_then.Add(inj_on)
i.children_else.Add(inj_off)
automations += i
/obj/machinery/computer/general_air_control/atmos_automation/air_mixing/proc/buildN2()
///////////////////////////////////////////////////////////////
// Nitrogen Injection
///////////////////////////////////////////////////////////////
/*
if(get_sensor_data("pressure") < 100)
injector_on()
else
if(get_sensor_data("pressure") > 5000)
injector_off()
*/
var/datum/automation/set_injector_power/inj_on=new(src)
inj_on.injector=n2_injector_tag
inj_on.state=1
var/datum/automation/set_injector_power/inj_off=new(src)
inj_off.injector=n2_injector_tag
inj_off.state=0
var/datum/automation/if_statement/if_on = new (src)
if_on.label = "Nitrogen Injection"
if_on.condition = MakeCompare(
MakeGetSensorData(sensor_tag,"pressure"),
MakeNumber(100),
"Less Than"
)
if_on.children_then.Add(inj_on)
var/datum/automation/if_statement/if_off=new(src)
if_off.condition=MakeCompare(
MakeGetSensorData(sensor_tag,"pressure"),
MakeNumber(5000),
"Greater Than"
)
if_off.children_then.Add(inj_off)
if_on.children_else.Add(if_off)
automations += if_on
/obj/machinery/computer/general_air_control/atmos_automation/air_mixing/proc/buildOutletVent()
///////////////////////////////////////////////////////////////
// Outlet Management
///////////////////////////////////////////////////////////////
/*
if(get_sensor_data("pressure") >= 5000 && get_sensor_data("oxygen") >= 20)
vent_on()
else
if(get_sensor_data("oxygen") < 20 || get_sensor_data("pressure") < 100)
vent_off()
*/
var/datum/automation/set_vent_pump_power/vp_on=new(src)
vp_on.vent_pump=output_tag
vp_on.state=1
var/datum/automation/set_vent_pump_power/vp_off=new(src)
vp_off.vent_pump=output_tag
vp_off.state=0
var/datum/automation/if_statement/if_on=new(src)
if_on.label="Air Output"
var/datum/automation/and/and_on=new(src)
and_on.children.Add(
MakeCompare(
MakeGetSensorData(sensor_tag,"pressure"),
MakeNumber(5000),
"Greater Than or Equal to"
)
)
and_on.children.Add(
MakeCompare(
MakeGetSensorData(sensor_tag,"oxygen"),
MakeNumber(20),
"Less Than or Equal to"
"Greater Than or Equal to"
)
i.children_then.Add(inj_on)
i.children_else.Add(inj_off)
)
if_on.condition=and_on
if_on.children_then.Add(vp_on)
automations += i
//////////////////////////////
proc/buildN2()
///////////////////////////////////////////////////////////////
// Nitrogen Injection
///////////////////////////////////////////////////////////////
/*
if(get_sensor_data("pressure") < 100)
injector_on()
else
if(get_sensor_data("pressure") > 5000)
injector_off()
*/
var/datum/automation/if_statement/if_off=new(src)
var/datum/automation/set_injector_power/inj_on=new(src)
inj_on.injector=n2_injector_tag
inj_on.state=1
var/datum/automation/set_injector_power/inj_off=new(src)
inj_off.injector=n2_injector_tag
inj_off.state=0
var/datum/automation/if_statement/if_on = new (src)
if_on.label = "Nitrogen Injection"
if_on.condition = MakeCompare(
var/datum/automation/or/or_off=new(src)
or_off.children.Add(
MakeCompare(
MakeGetSensorData(sensor_tag,"pressure"),
MakeNumber(100),
"Less Than"
)
if_on.children_then.Add(inj_on)
var/datum/automation/if_statement/if_off=new(src)
if_off.condition=MakeCompare(
MakeGetSensorData(sensor_tag,"pressure"),
MakeNumber(5000),
"Greater Than"
)
or_off.children.Add(
MakeCompare(
MakeGetSensorData(sensor_tag,"oxygen"),
MakeNumber(20),
"Less Than"
)
if_off.children_then.Add(inj_off)
)
if_off.condition=or_off
if_off.children_then.Add(vp_off)
if_on.children_else.Add(if_off)
if_on.children_else.Add(if_off)
automations += if_on
proc/buildOutletVent()
///////////////////////////////////////////////////////////////
// Outlet Management
///////////////////////////////////////////////////////////////
/*
if(get_sensor_data("pressure") >= 5000 && get_sensor_data("oxygen") >= 20)
vent_on()
else
if(get_sensor_data("oxygen") < 20 || get_sensor_data("pressure") < 100)
vent_off()
*/
var/datum/automation/set_vent_pump_power/vp_on=new(src)
vp_on.vent_pump=output_tag
vp_on.state=1
var/datum/automation/set_vent_pump_power/vp_off=new(src)
vp_off.vent_pump=output_tag
vp_off.state=0
var/datum/automation/if_statement/if_on=new(src)
if_on.label="Air Output"
var/datum/automation/and/and_on=new(src)
and_on.children.Add(
MakeCompare(
MakeGetSensorData(sensor_tag,"pressure"),
MakeNumber(5000),
"Greater Than or Equal to"
)
)
and_on.children.Add(
MakeCompare(
MakeGetSensorData(sensor_tag,"oxygen"),
MakeNumber(20),
"Greater Than or Equal to"
)
)
if_on.condition=and_on
if_on.children_then.Add(vp_on)
//////////////////////////////
var/datum/automation/if_statement/if_off=new(src)
var/datum/automation/or/or_off=new(src)
or_off.children.Add(
MakeCompare(
MakeGetSensorData(sensor_tag,"pressure"),
MakeNumber(100),
"Less Than"
)
)
or_off.children.Add(
MakeCompare(
MakeGetSensorData(sensor_tag,"oxygen"),
MakeNumber(20),
"Less Than"
)
)
if_off.condition=or_off
if_off.children_then.Add(vp_off)
if_on.children_else.Add(if_off)
automations += if_on
automations += if_on
+2 -2
View File
@@ -17,11 +17,11 @@ var/global/list/potentialRandomZlevels = generateMapList(filename = "config/away
log_debug("Smoothing tiles")
for(var/turf/T in smoothTurfs)
if(T.smooth)
smooth_icon(T)
queue_smooth(T)
for(var/R in T)
var/atom/A = R
if(A.smooth)
smooth_icon(A)
queue_smooth(A)
if(istype(T, /turf/simulated/mineral)) // For the listening post, among other maps
var/turf/simulated/mineral/MT = T
MT.add_edges()
@@ -13,14 +13,14 @@ var/list/spawntypes = list()
var/list/restrict_job = null
var/list/disallow_job = null
proc/check_job_spawning(job)
if(restrict_job && !(job in restrict_job))
return 0
/datum/spawnpoint/proc/check_job_spawning(job)
if(restrict_job && !(job in restrict_job))
return 0
if(disallow_job && (job in disallow_job))
return 0
if(disallow_job && (job in disallow_job))
return 0
return 1
return 1
/datum/spawnpoint/arrivals
display_name = "Arrivals Shuttle"
@@ -54,4 +54,4 @@ var/list/spawntypes = list()
/datum/spawnpoint/cyborg/New()
..()
turfs = latejoin_cyborg
turfs = latejoin_cyborg
+1 -1
View File
@@ -69,7 +69,7 @@
else
if(istype(I, /obj/item/reagent_containers))
var/obj/item/reagent_containers/RC = I
if(RC.flags & OPENCONTAINER)
if(RC.container_type & OPENCONTAINER)
for(var/datum/reagent/A in RC.reagents.reagent_list)
.[A.type] += A.volume
.[I.type] += 1
@@ -19,7 +19,8 @@
possible_transfer_amounts = list(5)
volume = 5
can_be_placed_into = null
flags = OPENCONTAINER | NOBLUDGEON
flags = NOBLUDGEON
container_type = OPENCONTAINER
var/wipespeed = 30
/obj/item/reagent_containers/glass/rag/attack(atom/target as obj|turf|area, mob/user as mob , flag)
+65 -70
View File
@@ -474,7 +474,7 @@
//Finally, report the full examine_message constructed from the above reports
to_chat(user, "[examine_message]")
to_chat(user, "<span class='notice'>[examine_message]</span>")
return examine_message
//////////////////////////////
@@ -485,37 +485,37 @@
if(istype(M, /mob/living/simple_animal/pet/cat))
if(M.a_intent == INTENT_HELP) //Cats can try to fish in open tanks on help intent
if(lid_switch) //Can't fish in a closed tank. Fishbowls are ALWAYS open.
M.visible_message("[M.name] stares at into [src] while sitting perfectly still.", "The lid is closed, so you stare into [src] intently.")
M.visible_message("<span class='notice'>[M.name] stares at into [src] while sitting perfectly still.</span>", "<span class='notice'>The lid is closed, so you stare into [src] intently.</span>")
else
if(fish_count) //Tank must actually have fish to try catching one
M.visible_message("[M.name] leaps up onto [src] and attempts to fish through the opening!", "You jump up onto [src] and begin fishing through the opening!")
M.visible_message("<span class='warning'>[M.name] leaps up onto [src] and attempts to fish through the opening!</span>", "<span class='notice'>You jump up onto [src] and begin fishing through the opening!</span>")
if(water_level && prob(45)) //If there is water, there is a chance the cat will slip, Syndicat will spark like E-N when this happens
M.visible_message("[M.name] slipped and got soaked!", "You slipped and got soaked!")
M.visible_message("<span class='notice'>[M.name] slipped and got soaked!</span>", "<span class='notice'>You slipped and got soaked!</span>")
if(istype(M, /mob/living/simple_animal/pet/cat/Syndi))
do_sparks(3, 1, src)
else //No water or didn't slip, get that fish!
M.visible_message("[M.name] catches and devours a live fish!", "You catch and devour a live fish, yum!")
M.visible_message("<span class='warning'>[M.name] catches and devours a live fish!</span>", "<span class='notice'>You catch and devour a live fish, yum!</span>")
kill_fish() //Kill a random fish
M.health = M.maxHealth //Eating fish heals the predator
else
to_chat(M, "There are no fish in [src]!")
to_chat(M, "<span class='warning'>There are no fish in [src]!</span>")
else
return ..()
else if(istype(M, /mob/living/simple_animal/hostile/bear))
if(M.a_intent == INTENT_HELP) //Bears can try to fish in open tanks on help intent
if(lid_switch) //Can't fish in a closed tank. Fishbowls are ALWAYS open.
M.visible_message("[M.name] scrapes it's claws along [src]'s lid.", "The lid is closed, so you scrape your claws against [src]'s lid.")
M.visible_message("<span class='notice'>[M.name] scrapes it's claws along [src]'s lid.</span>", "<span class='notice'>The lid is closed, so you scrape your claws against [src]'s lid.</span>")
else
if(fish_count) //Tank must actually have fish to try catching one
M.visible_message("[M.name] reaches into [src] and attempts to fish through the opening!", "You reach into [src] and begin fishing through the opening!")
M.visible_message("<span class='warning'>[M.name] reaches into [src] and attempts to fish through the opening!</span>", "<span class='warning'>You reach into [src] and begin fishing through the opening!</span>")
if(water_level && prob(5)) //Bears are good at catching fish, only a 5% chance to fail
M.visible_message("[M.name] swipes at the water!", "You just barely missed that fish!")
M.visible_message("<span class='warning'>[M.name] swipes at the water!</span>", "<span class='notice'>You just barely missed that fish!</span>")
else //No water or didn't slip, get that fish!
M.visible_message("[M.name] catches and devours a live fish!", "You catch and devour a live fish, yum!")
M.visible_message("<span class='warning'>[M.name] catches and devours a live fish!</span>", "<span class='notice'>You catch and devour a live fish, yum!</span>")
kill_fish() //Kill a random fish
M.health = M.maxHealth //Eating fish heals the predator
else
to_chat(M, "There are no fish in [src]!")
to_chat(M, "<span class='warning'>There are no fish in [src]!</span>")
else
return ..()
else
@@ -530,8 +530,8 @@
"You hear a banging sound.")
else
playsound(loc, 'sound/effects/glassknock.ogg', 80, 1)
user.visible_message("[user.name] taps on the [name].", \
"You tap on the [name].", \
user.visible_message("<span class='notice'>[user.name] taps on the [name].</span>", \
"<span class='notice'>You tap on the [name].</span>", \
"You hear a knocking sound.")
/obj/machinery/fishtank/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1)
@@ -571,62 +571,57 @@
if(W.isOn())
if(obj_integrity < max_integrity)
playsound(loc, W.usesound, 50, 1)
to_chat(user, "You repair some of the cracks on [src].")
to_chat(user, "<span class='notice'>You repair some of the cracks on [src].</span>")
obj_integrity = min(obj_integrity + 20, max_integrity)
check_health()
else
to_chat(user, "There is no damage to fix!")
to_chat(user, "<span class='notice'>There is no damage to fix!</span>")
else
if(obj_integrity < max_integrity)
to_chat(user, "[W] must be on to repair this damage.")
to_chat(user, "<span class='notice'>[W] must be on to repair this damage.</span>")
else
return ..()
//Open reagent containers add and remove water
else if(O.is_open_container())
if(istype(O, /obj/item/reagent_containers/glass))
if(lid_switch)
to_chat(user, "Open the lid on [src] first!")
return
var/obj/item/reagent_containers/glass/C = O
//Containers with any reagents will get dumped in
if(C.reagents.total_volume)
var/water_value = 0
water_value += C.reagents.get_reagent_amount("water") //Water is full value
water_value += C.reagents.get_reagent_amount("holywater") *1.1 //Holywater is (somehow) better. Who said religion had to make sense?
water_value += C.reagents.get_reagent_amount("tonic") * 0.25 //Tonic water is 25% value
water_value += C.reagents.get_reagent_amount("sodawater") * 0.50 //Sodawater is 50% value
water_value += C.reagents.get_reagent_amount("fishwater") * 0.75 //Fishwater is 75% value, to account for the fish poo
water_value += C.reagents.get_reagent_amount("ice") * 0.80 //Ice is 80% value
var/message = ""
if(!water_value) //The container has no water value, clear everything in it
message = "The filtration process removes everything, leaving the water level unchanged."
C.reagents.clear_reagents()
else
if(water_level == water_capacity)
to_chat(user, "[src] is already full!")
else
message = "The filtration process purifies the water, raising the water level."
if((water_level + water_value) == water_capacity)
message += " You filled [src] to the brim!"
if((water_level + water_value) > water_capacity)
message += " You overfilled [src] and some water runs down the side, wasted."
C.reagents.clear_reagents()
adjust_water_level(water_value)
user.visible_message("[user.name] pours the contents of [C.name] into [src].", "[message]")
//Empty containers will scoop out water, filling the container as much as possible from the water_level
else if(O.is_drainable())
//Containers with any reagents will get dumped in
if(O.reagents.total_volume)
var/water_value = 0
water_value += O.reagents.get_reagent_amount("water") //Water is full value
water_value += O.reagents.get_reagent_amount("holywater") *1.1 //Holywater is (somehow) better. Who said religion had to make sense?
water_value += O.reagents.get_reagent_amount("tonic") * 0.25 //Tonic water is 25% value
water_value += O.reagents.get_reagent_amount("sodawater") * 0.50 //Sodawater is 50% value
water_value += O.reagents.get_reagent_amount("fishwater") * 0.75 //Fishwater is 75% value, to account for the fish poo
water_value += O.reagents.get_reagent_amount("ice") * 0.80 //Ice is 80% value
var/message = ""
if(!water_value) //The container has no water value, clear everything in it
message = "The filtration process removes everything, leaving the water level unchanged."
O.reagents.clear_reagents()
else
if(!water_level)
to_chat(user, "[src] is empty!")
if(water_level == water_capacity)
to_chat(user, "<span class='notice'>[src] is already full!</span>")
else
if(water_level >= C.volume) //Enough to fill the container completely
C.reagents.add_reagent("fishwater", C.volume)
adjust_water_level(-C.volume)
user.visible_message("[user.name] scoops out some water from [src].", "You completely fill [C.name] from [src].")
else //Fill the container as much as possible with the water_level
C.reagents.add_reagent("fishwater", water_level)
adjust_water_level(-water_level)
user.visible_message("[user.name] scoops out some water from [src].", "You fill [C.name] with the last of the water in [src].")
message = "The filtration process purifies the water, raising the water level."
if((water_level + water_value) == water_capacity)
message += " You filled [src] to the brim!"
if((water_level + water_value) > water_capacity)
message += " You overfilled [src] and some water runs down the side, wasted."
O.reagents.clear_reagents()
adjust_water_level(water_value)
user.visible_message("<span class='notice'>[user.name] pours the contents of [O.name] into [src].</span>", "<span class='notice'>[message]</span>")
//Empty containers will scoop out water, filling the container as much as possible from the water_level
else if(O.is_refillable())
if(!water_level)
to_chat(user, "<span class='notice'>[src] is empty!</span>")
else
if(water_level >= O.reagents.maximum_volume) //Enough to fill the container completely
O.reagents.add_reagent("fishwater", O.reagents.maximum_volume)
adjust_water_level(-O.reagents.maximum_volume)
user.visible_message("<span class='notice'>[user.name] scoops out some water from [src].</span>", "<span class='notice'>You completely fill [O.name] from [src].</span>")
else //Fill the container as much as possible with the water_level
O.reagents.add_reagent("fishwater", water_level)
adjust_water_level(-water_level)
user.visible_message("<span class='notice'>[user.name] scoops out some water from [src].</span>", "<span class='notice'>You fill [O.name] with the last of the water in [src].</span>")
//Wrenches can deconstruct empty tanks, but not tanks with any water. Kills any fish left inside and destroys any unharvested eggs in the process
else if(iswrench(O))
if(!water_level)
@@ -635,17 +630,17 @@
if(do_after(user, 50 * O.toolspeed, target = src))
deconstruct(TRUE)
else
to_chat(user, "[src] must be empty before you disassemble it!")
to_chat(user, "<span class='warning'>[src] must be empty before you disassemble it!</span>")
//Fish eggs
else if(istype(O, /obj/item/fish_eggs))
var/obj/item/fish_eggs/egg = O
//Don't add eggs if there is no water (they kinda need that to live)
if(!water_level)
to_chat(user, "[src] has no water; [egg.name] won't hatch without water!")
to_chat(user, "<span class='warning'>[src] has no water; [egg.name] won't hatch without water!</span>")
else
//Don't add eggs if the tank already has the max number of fish
if(fish_count >= max_fish)
to_chat(user, "[src] can't hold any more fish.")
to_chat(user, "<span class='notice'>[src] can't hold any more fish.</span>")
else
add_fish(egg.fish_type)
qdel(egg)
@@ -655,30 +650,30 @@
if(water_level)
if(food_level < 10)
if(fish_count == 0)
user.visible_message("[user.name] shakes some fish food into the empty [src]... How sad.", "You shake some fish food into the empty [src]... If only it had fish.")
user.visible_message("<span class='notice'>[user.name] shakes some fish food into the empty [src]... How sad.</span>", "<span class='notice'>You shake some fish food into the empty [src]... If only it had fish.</span>")
else
user.visible_message("[user.name] feeds the fish in [src]. The fish look excited!", "You feed the fish in [src]. They look excited!")
user.visible_message("<span class='notice'>[user.name] feeds the fish in [src]. The fish look excited!</span>", "<span class='notice'>You feed the fish in [src]. They look excited!</span>")
adjust_food_level(10)
else
to_chat(user, "[src] already has plenty of food in it. You decide to not add more.")
to_chat(user, "<span class='notice'>[src] already has plenty of food in it. You decide to not add more.</span>")
else
to_chat(user, "[src] doesn't have any water in it. You should fill it with water first.")
to_chat(user, "<span class='notice'>[src] doesn't have any water in it. You should fill it with water first.</span>")
//Fish egg scoop
else if(istype(O, /obj/item/egg_scoop))
if(egg_count)
user.visible_message("[user.name] harvests some fish eggs from [src].", "You scoop the fish eggs out of [src].")
user.visible_message("<span class='notice'>[user.name] harvests some fish eggs from [src].</span>", "<span class='notice'>You scoop the fish eggs out of [src].</span>")
harvest_eggs(user)
else
user.visible_message("[user.name] fails to harvest any fish eggs from [src].", "There are no fish eggs in [src] to scoop out.")
user.visible_message("<span class='notice'>[user.name] fails to harvest any fish eggs from [src].</span>", "<span class='notice'>There are no fish eggs in [src] to scoop out.</span>")
//Fish net
else if(istype(O, /obj/item/fish_net))
harvest_fish(user)
//Tank brush
else if(istype(O, /obj/item/tank_brush))
if(filth_level == 0)
to_chat(user, "[src] is already spotless!")
to_chat(user, "<span class='warning'>[src] is already spotless!</span>")
else
adjust_filth_level(-filth_level)
user.visible_message("[user.name] scrubs the inside of [src], cleaning the filth.", "You scrub the inside of [src], cleaning the filth.")
user.visible_message("<span class='notice'>[user.name] scrubs the inside of [src], cleaning the filth.</span>", "<span class='notice'>You scrub the inside of [src], cleaning the filth.</span>")
else
return ..()
@@ -235,7 +235,7 @@
//empties aren't sealed, so let's open it quietly
drink_container = new drink_container()
drink_container.canopened = 1
drink_container.flags |= OPENCONTAINER
drink_container.container_type |= OPENCONTAINER
drink_container.forceMove(loc)
containers[con_type]--
+39 -44
View File
@@ -6,7 +6,7 @@
desc = "yummy"
icon = 'icons/obj/drinks.dmi'
icon_state = null
flags = OPENCONTAINER
container_type = OPENCONTAINER
consume_sound = 'sound/items/drink.ogg'
possible_transfer_amounts = list(5,10,15,20,25,30,50)
volume = 50
@@ -26,7 +26,11 @@
/obj/item/reagent_containers/food/drinks/attack(mob/M, mob/user, def_zone)
if(!reagents || !reagents.total_volume)
to_chat(user, "<span class='warning'> None of [src] left, oh no!</span>")
return 0
return FALSE
if(!is_drainable())
to_chat(user, "<span class='warning'> You need to open [src] first!</span>")
return FALSE
if(istype(M, /mob/living/carbon))
var/mob/living/carbon/C = M
@@ -35,15 +39,14 @@
var/mob/living/silicon/robot/borg = user
borg.cell.use(30)
var/refill = reagents.get_master_reagent_id()
if(refill in drinks) // Only synthesize drinks
spawn(600)
reagents.add_reagent(refill, bitesize)
return 1
return 0
if(refill in GLOB.drinks) // Only synthesize drinks
addtimer(CALLBACK(reagents, /datum/reagents.proc/add_reagent, refill, bitesize), 600)
return TRUE
return FALSE
/obj/item/reagent_containers/food/drinks/MouseDrop(atom/over_object) //CHUG! CHUG! CHUG!
var/mob/living/carbon/chugger = over_object
if (!(flags & OPENCONTAINER))
if (!(container_type & DRAINABLE))
to_chat(chugger, "<span class='notice'>You need to open [src] first!</span>")
return
if(istype(chugger) && loc == chugger && src == chugger.get_active_hand() && reagents.total_volume)
@@ -56,39 +59,18 @@
break
/obj/item/reagent_containers/food/drinks/afterattack(obj/target, mob/user, proximity)
if(!proximity) return
if(!proximity)
return
// Moved from the can code; not necessary since closed cans aren't open containers now, but, eh.
if(istype(target, /obj/item/reagent_containers/food/drinks/cans))
var/obj/item/reagent_containers/food/drinks/cans/cantarget = target
if(cantarget.canopened == 0)
to_chat(user, "<span class='notice'>You need to open the drink you want to pour into!</span>")
return
if(istype(target, /obj/structure/reagent_dispensers)) //A dispenser. Transfer FROM it TO us.
if(!target.reagents.total_volume)
to_chat(user, "<span class='warning'> [target] is empty.</span>")
return
if(reagents.total_volume >= reagents.maximum_volume)
to_chat(user, "<span class='warning'> [src] is full.</span>")
return
var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this)
to_chat(user, "<span class='notice'> You fill [src] with [trans] units of the contents of [target].</span>")
else if(target.is_open_container()) //Something like a glass. Player probably wants to transfer TO it.
if(target.is_open_container()) //Something like a glass. Player probably wants to transfer TO it.
if(!reagents.total_volume)
to_chat(user, "<span class='warning'> [src] is empty.</span>")
return
return FALSE
if(target.reagents.total_volume >= target.reagents.maximum_volume)
if(target.reagents.holder_full())
to_chat(user, "<span class='warning'> [target] is full.</span>")
return
return FALSE
var/datum/reagent/refill
var/datum/reagent/refillName
if(isrobot(user))
@@ -99,22 +81,34 @@
to_chat(user, "<span class='notice'> You transfer [trans] units of the solution to [target].</span>")
if(isrobot(user)) //Cyborg modules that include drinks automatically refill themselves, but drain the borg's cell
if(refill in drinks) // Only synthesize drinks
if(refill in GLOB.drinks) // Only synthesize drinks
var/mob/living/silicon/robot/bro = user
var/chargeAmount = max(30,4*trans)
bro.cell.use(chargeAmount)
to_chat(user, "Now synthesizing [trans] units of [refillName]...")
to_chat(user, "<span class='notice'>Now synthesizing [trans] units of [refillName]...</span>")
addtimer(CALLBACK(reagents, /datum/reagents.proc/add_reagent, refill, trans), 300)
addtimer(CALLBACK(GLOBAL_PROC, .proc/__to_chat, user, "<span class='notice'>Cyborg [src] refilled.</span>"), 300)
else if(target.is_drainable()) //A dispenser. Transfer FROM it TO us.
if(!is_refillable())
to_chat(user, "<span class='warning'>[src]'s tab isn't open!</span>")
return FALSE
if(!target.reagents.total_volume)
to_chat(user, "<span class='warning'>[target] is empty.</span>")
return FALSE
spawn(300)
reagents.add_reagent(refill, trans)
to_chat(user, "Cyborg [src] refilled.")
if(reagents.holder_full())
to_chat(user, "<span class='warning'>[src] is full.</span>")
return FALSE
return
var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this)
to_chat(user, "<span class='notice'>You fill [src] with [trans] units of the contents of [target].</span>")
return FALSE
/obj/item/reagent_containers/food/drinks/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/clothing/mask/cigarette)) //ciggies are weird
return
return FALSE
if(is_hot(I))
if(reagents)
reagents.chem_temp += 15
@@ -151,7 +145,8 @@
materials = list(MAT_METAL=100)
possible_transfer_amounts = list()
volume = 5
flags = CONDUCT | OPENCONTAINER
flags = CONDUCT
container_type = OPENCONTAINER
/obj/item/reagent_containers/food/drinks/trophy/gold_cup
name = "gold cup"
@@ -10,7 +10,7 @@
desc = "Just your average condiment container."
icon = 'icons/obj/food/containers.dmi'
icon_state = "emptycondiment"
flags = OPENCONTAINER
container_type = OPENCONTAINER
possible_transfer_amounts = list(1, 5, 10, 15, 20, 25, 30, 50)
volume = 50
//Possible_states has the reagent id as key and a list of, in order, the icon_state, the name and the desc as values. Used in the on_reagent_change() to change names, descs and sprites.
@@ -47,7 +47,7 @@
if(!reagents || !reagents.total_volume)
return // The condiment might be empty after the delay.
user.visible_message("<span class='warning'>[user] feeds [M] from [src].</span>")
add_attack_logs(user, M, "Fed [src] containing [reagentlist()]")
add_attack_logs(user, M, "Fed [src] containing [reagents.log_list()]")
var/fraction = min(10/reagents.total_volume, 1)
reagents.reaction(M, INGEST, fraction)
@@ -75,7 +75,7 @@
to_chat(user, "<span class='notice'>You fill [src] with [trans] units of the contents of [target].</span>")
//Something like a glass or a food item. Player probably wants to transfer TO it.
else if(target.is_open_container() || istype(target, /obj/item/reagent_containers/food/snacks))
else if(target.is_drainable() || istype(target, /obj/item/reagent_containers/food/snacks))
if(!reagents.total_volume)
to_chat(user, "<span class='warning'>[src] is empty!</span>")
return
@@ -8,7 +8,7 @@
use_power = IDLE_POWER_USE
idle_power_usage = 5
active_power_usage = 100
flags = OPENCONTAINER
container_type = OPENCONTAINER
var/operating = 0 // Is it on?
var/dirty = 0 // = {0..100} Does it need cleaning?
var/broken = 0 // ={0,1,2} How broken is it???
@@ -93,7 +93,7 @@
icon_state = off_icon
broken = 0 // Fix it!
dirty = 0 // just to be sure
flags = OPENCONTAINER
container_type = OPENCONTAINER
else
to_chat(user, "<span class='alert'>It's broken!</span>")
return 1
@@ -105,7 +105,7 @@
dirty = 0 // It's clean!
broken = 0 // just to be sure
icon_state = off_icon
flags = OPENCONTAINER
container_type = OPENCONTAINER
else //Otherwise bad luck!!
to_chat(user, "<span class='alert'>It's dirty!</span>")
return 1
+1 -1
View File
@@ -81,7 +81,7 @@
/obj/item/reagent_containers/food/snacks/grown/mushroom/angel
seed = /obj/item/seeds/angel
name = "destroying angel"
desc = "<I>Amanita Virosa</I>: Deadly poisonous basidiomycete fungus filled with alpha amatoxins."
desc = "<I>Amanita Virosa</I>: Deadly poisonous basidiomycete fungus filled with alpha amanitin."
icon_state = "angel"
filling_color = "#C0C0C0"
+2 -2
View File
@@ -21,7 +21,7 @@
icon_state = "weedspray"
item_state = "plantbgone"
volume = 100
flags = OPENCONTAINER
container_type = OPENCONTAINER
slot_flags = SLOT_BELT
throwforce = 0
w_class = WEIGHT_CLASS_SMALL
@@ -43,7 +43,7 @@
icon_state = "pestspray"
item_state = "plantbgone"
volume = 100
flags = OPENCONTAINER
container_type = OPENCONTAINER
slot_flags = SLOT_BELT
throwforce = 0
w_class = WEIGHT_CLASS_SMALL
+2 -2
View File
@@ -763,8 +763,8 @@
else if(transfer_amount) // Droppers, cans, beakers, what have you.
visi_msg="[user] uses [reagent_source] on [target]"
irrigate = 1
// Beakers, bottles, buckets, etc. Can't use is_open_container though.
if(istype(reagent_source, /obj/item/reagent_containers/glass/))
// Beakers, bottles, buckets, etc.
if(reagent_source.is_drainable())
playsound(loc, 'sound/effects/slosh.ogg', 25, 1)
if(irrigate && transfer_amount > 30 && reagent_source.reagents.total_volume >= 30 && using_irrigation)
+1 -1
View File
@@ -1019,7 +1019,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump,
return 1
/mob/living/carbon/proc/forceFedAttackLog(var/obj/item/reagent_containers/food/toEat, mob/user)
add_attack_logs(user, src, "Fed [toEat]. Reagents: [toEat.reagentlist(toEat)]", ATKLOG_MOST)
add_attack_logs(user, src, "Fed [toEat]. Reagents: [toEat.reagents.log_list(toEat)]", ATKLOG_MOST)
if(!iscarbon(user))
LAssailant = null
else
+7 -1
View File
@@ -329,7 +329,13 @@
/mob/living/proc/can_inject()
return 1
return TRUE
/mob/living/is_injectable(allowmobs = TRUE)
return (allowmobs && reagents && can_inject())
/mob/living/is_drawable(allowmobs = TRUE)
return (allowmobs && reagents && can_inject())
/mob/living/proc/get_organ_target()
var/mob/shooter = src
+318 -318
View File
@@ -22,104 +22,235 @@ var/datum/paiController/paiController // Global handler for pAI candidates
var/askDelay = 10 * 60 * 1 // One minute [ms * sec * min]
Topic(href, href_list[])
if("signup" in href_list)
var/mob/dead/observer/O = locate(href_list["signup"])
if(!O) return
if(!(O in GLOB.respawnable_list))
to_chat(O, "You've given up your ability to respawn!")
return
if(!check_recruit(O)) return
recruitWindow(O)
/datum/paiController/Topic(href, href_list[])
if("signup" in href_list)
var/mob/dead/observer/O = locate(href_list["signup"])
if(!O) return
if(!(O in GLOB.respawnable_list))
to_chat(O, "You've given up your ability to respawn!")
return
if(!check_recruit(O)) return
recruitWindow(O)
return
if(href_list["download"])
var/datum/paiCandidate/candidate = locate(href_list["candidate"])
var/obj/item/paicard/card = locate(href_list["device"])
if(card.pai)
if(href_list["download"])
var/datum/paiCandidate/candidate = locate(href_list["candidate"])
var/obj/item/paicard/card = locate(href_list["device"])
if(card.pai)
return
if(usr.incapacitated() || isobserver(usr) || !card.Adjacent(usr))
return
if(istype(card,/obj/item/paicard) && istype(candidate,/datum/paiCandidate))
var/mob/living/silicon/pai/pai = new(card)
if(!candidate.name)
pai.name = pick(GLOB.ninja_names)
else
pai.name = candidate.name
pai.real_name = pai.name
pai.key = candidate.key
card.setPersonality(pai)
card.looking_for_personality = 0
ticker.mode.update_cult_icons_removed(card.pai.mind)
ticker.mode.update_rev_icons_removed(card.pai.mind)
pai_candidates -= candidate
usr << browse(null, "window=findPai")
if(href_list["new"])
var/datum/paiCandidate/candidate = locate(href_list["candidate"])
var/option = href_list["option"]
var/t = ""
switch(option)
if("name")
t = input("Enter a name for your pAI", "pAI Name", candidate.name) as text
if(t)
candidate.name = sanitize(copytext(t,1,MAX_NAME_LEN))
if("desc")
t = input("Enter a description for your pAI", "pAI Description", candidate.description) as message
if(t)
candidate.description = sanitize(copytext(t,1,MAX_MESSAGE_LEN))
if("role")
t = input("Enter a role for your pAI", "pAI Role", candidate.role) as text
if(t)
candidate.role = sanitize(copytext(t,1,MAX_MESSAGE_LEN))
if("ooc")
t = input("Enter any OOC comments", "pAI OOC Comments", candidate.comments) as message
if(t)
candidate.comments = sanitize(copytext(t,1,MAX_MESSAGE_LEN))
if("save")
candidate.savefile_save(usr)
if("load")
candidate.savefile_load(usr)
//In case people have saved unsanitized stuff.
if(candidate.name)
candidate.name = sanitize(copytext(candidate.name,1,MAX_NAME_LEN))
if(candidate.description)
candidate.description = sanitize(copytext(candidate.description,1,MAX_MESSAGE_LEN))
if(candidate.role)
candidate.role = sanitize(copytext(candidate.role,1,MAX_MESSAGE_LEN))
if(candidate.comments)
candidate.comments = sanitize(copytext(candidate.comments,1,MAX_MESSAGE_LEN))
if("submit")
if(candidate)
candidate.ready = 1
for(var/obj/item/paicard/p in world)
if(p.looking_for_personality == 1)
p.alertUpdate()
usr << browse(null, "window=paiRecruit")
return
if(usr.incapacitated() || isobserver(usr) || !card.Adjacent(usr))
return
if(istype(card,/obj/item/paicard) && istype(candidate,/datum/paiCandidate))
var/mob/living/silicon/pai/pai = new(card)
if(!candidate.name)
pai.name = pick(GLOB.ninja_names)
else
pai.name = candidate.name
pai.real_name = pai.name
pai.key = candidate.key
recruitWindow(usr)
card.setPersonality(pai)
card.looking_for_personality = 0
ticker.mode.update_cult_icons_removed(card.pai.mind)
ticker.mode.update_rev_icons_removed(card.pai.mind)
pai_candidates -= candidate
usr << browse(null, "window=findPai")
if(href_list["new"])
var/datum/paiCandidate/candidate = locate(href_list["candidate"])
var/option = href_list["option"]
var/t = ""
switch(option)
if("name")
t = input("Enter a name for your pAI", "pAI Name", candidate.name) as text
if(t)
candidate.name = reject_bad_name(sanitize(copytext(t,1,MAX_NAME_LEN)))
if("desc")
t = input("Enter a description for your pAI", "pAI Description", candidate.description) as message
if(t)
candidate.description = sanitize(copytext(t,1,MAX_MESSAGE_LEN))
if("role")
t = input("Enter a role for your pAI", "pAI Role", candidate.role) as text
if(t)
candidate.role = sanitize(copytext(t,1,MAX_MESSAGE_LEN))
if("ooc")
t = input("Enter any OOC comments", "pAI OOC Comments", candidate.comments) as message
if(t)
candidate.comments = sanitize(copytext(t,1,MAX_MESSAGE_LEN))
if("save")
candidate.savefile_save(usr)
if("load")
candidate.savefile_load(usr)
//In case people have saved unsanitized stuff.
if(candidate.name)
candidate.name = reject_bad_name(sanitize(copytext(candidate.name,1,MAX_NAME_LEN)))
if(candidate.description)
candidate.description = sanitize(copytext(candidate.description,1,MAX_MESSAGE_LEN))
if(candidate.role)
candidate.role = sanitize(copytext(candidate.role,1,MAX_MESSAGE_LEN))
if(candidate.comments)
candidate.comments = sanitize(copytext(candidate.comments,1,MAX_MESSAGE_LEN))
if("submit")
if(candidate)
candidate.ready = 1
for(var/obj/item/paicard/p in world)
if(p.looking_for_personality == 1)
p.alertUpdate()
usr << browse(null, "window=paiRecruit")
return
recruitWindow(usr)
proc/recruitWindow(var/mob/M as mob)
var/datum/paiCandidate/candidate
for(var/datum/paiCandidate/c in pai_candidates)
if(!istype(c) || !istype(M))
break
if(c.key == M.key)
candidate = c
if(!candidate)
candidate = new /datum/paiCandidate()
candidate.key = M.key
pai_candidates.Add(candidate)
/datum/paiController/proc/recruitWindow(var/mob/M as mob)
var/datum/paiCandidate/candidate
for(var/datum/paiCandidate/c in pai_candidates)
if(!istype(c) || !istype(M))
break
if(c.key == M.key)
candidate = c
if(!candidate)
candidate = new /datum/paiCandidate()
candidate.key = M.key
pai_candidates.Add(candidate)
var/dat = ""
dat += {"
<style type="text/css">
var/dat = ""
dat += {"
<style type="text/css">
body {
margin-top:5px;
font-family:Verdana;
color:white;
font-size:13px;
background-image:url('uiBackground.png');
background-repeat:repeat-x;
background-color:#272727;
background-position:center top;
}
table {
border-collapse:collapse;
font-size:13px;
}
th, td {
border: 1px solid #333333;
}
p.top {
background-color: none;
color: white;
}
tr.d0 td {
background-color: #c0c0c0;
color: black;
border:0px;
border: 1px solid #333333;
}
tr.d0 th {
background-color: none;
color: #4477E0;
text-align:right;
vertical-align:top;
width:120px;
border:0px;
}
tr.d1 td {
background-color: #555555;
color: white;
}
td.button {
border: 1px solid #161616;
background-color: #40628a;
}
td.desc {
font-weight:bold;
}
a {
color:#4477E0;
}
a.button {
color:white;
text-decoration: none;
}
</style>
"}
dat += {"
<body>
<b><font size="3px">pAI Personality Configuration</font></b>
<p class="top">Please configure your pAI personality's options. Remember, what you enter here could determine whether or not the user requesting a personality chooses you!</p>
<table>
<tr class="d0">
<th rowspan="2"><a href='byond://?src=[UID()];option=name;new=1;candidate=\ref[candidate]'>Name</a>:</th>
<td class="desc">[candidate.name]&nbsp;</td>
</tr>
<tr class="d1">
<td>What you plan to call yourself. Suggestions: Any character name you would choose for a station character OR an AI.</td>
</tr>
<tr class="d0">
<th rowspan="2"><a href='byond://?src=[UID()];option=desc;new=1;candidate=\ref[candidate]'>Description</a>:</th>
<td class="desc">[candidate.description]&nbsp;</td>
</tr>
<tr class="d1">
<td>What sort of pAI you typically play; your mannerisms, your quirks, etc. This can be as sparse or as detailed as you like.</td>
</tr>
<tr class="d0">
<th rowspan="2"><a href='byond://?src=[UID()];option=role;new=1;candidate=\ref[candidate]'>Preferred Role</a>:</th>
<td class="desc">[candidate.role]&nbsp;</td>
</tr>
<tr class="d1">
<td>Do you like to partner with sneaky social ninjas? Like to help security hunt down thugs? Enjoy watching an engineer's back while he saves the station yet again? This doesn't have to be limited to just station jobs. Pretty much any general descriptor for what you'd like to be doing works here.</td>
</tr>
<tr class="d0">
<th rowspan="2"><a href='byond://?src=[UID()];option=ooc;new=1;candidate=\ref[candidate]'>OOC Comments</a>:</th>
<td class="desc">[candidate.comments]&nbsp;</td>
</tr>
<tr class="d1">
<td>Anything you'd like to address specifically to the player reading this in an OOC manner. \"I prefer more serious RP.\", \"I'm still learning the interface!\", etc. Feel free to leave this blank if you want.</td>
</tr>
</table>
<br>
<table>
<tr>
<td class="button">
<a href='byond://?src=[UID()];option=save;new=1;candidate=\ref[candidate]' class="button">Save Personality</a>
</td>
</tr>
<tr>
<td class="button">
<a href='byond://?src=[UID()];option=load;new=1;candidate=\ref[candidate]' class="button">Load Personality</a>
</td>
</tr>
</table><br>
<table>
<td class="button"><a href='byond://?src=[UID()];option=submit;new=1;candidate=\ref[candidate]' class="button"><b><font size="4px">Submit Personality</font></b></a></td>
</table><br>
</body>
"}
M << browse(dat, "window=paiRecruit;size=580x580;")
/datum/paiController/proc/findPAI(var/obj/item/paicard/p, var/mob/user)
requestRecruits(p, user)
var/list/available = list()
for(var/datum/paiCandidate/c in paiController.pai_candidates)
if(c.ready)
var/found = 0
for(var/mob/o in GLOB.respawnable_list)
if(o.key == c.key)
found = 1
if(found)
available.Add(c)
var/dat = ""
dat += {"
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">
<html>
<head>
<style>
body {
margin-top:5px;
font-family:Verdana;
@@ -131,257 +262,126 @@ var/datum/paiController/paiController // Global handler for pAI candidates
background-position:center top;
}
table {
border-collapse:collapse;
font-size:13px;
}
th, td {
border: 1px solid #333333;
table.desc {
border-collapse:collapse;
font-size:13px;
border: 1px solid #161616;
width:100%;
}
p.top {
background-color: none;
table.download {
border-collapse:collapse;
font-size:13px;
border: 1px solid #161616;
width:100%;
}
tr.d0 td, tr.d0 th {
background-color: #506070;
color: white;
}
tr.d0 td {
background-color: #c0c0c0;
color: black;
border:0px;
border: 1px solid #333333;
}
tr.d0 th {
background-color: none;
color: #4477E0;
text-align:right;
vertical-align:top;
width:120px;
border:0px;
}
tr.d1 td {
background-color: #555555;
tr.d1 td, tr.d1 th {
background-color: #708090;
color: white;
}
tr.d2 td {
background-color: #00FF00;
color: white;
text-align:center;
}
td.button {
border: 1px solid #161616;
background-color: #40628a;
text-align: center;
}
td.desc {
font-weight:bold;
td.download {
border: 1px solid #161616;
background-color: #40628a;
text-align: center;
}
a {
color:#4477E0;
th {
text-align:left;
width:125px;
vertical-align:top;
}
a.button {
color:white;
text-decoration: none;
}
</style>
"}
</head>
<body>
<b><font size='3px'>pAI Availability List</font></b><br><br>
"}
dat += "<p>Displaying available AI personalities from central database... If there are no entries, or if a suitable entry is not listed, check again later as more personalities may be added.</p>"
for(var/datum/paiCandidate/c in available)
dat += {"
<body>
<b><font size="3px">pAI Personality Configuration</font></b>
<p class="top">Please configure your pAI personality's options. Remember, what you enter here could determine whether or not the user requesting a personality chooses you!</p>
<table>
<tr class="d0">
<th rowspan="2"><a href='byond://?src=[UID()];option=name;new=1;candidate=\ref[candidate]'>Name</a>:</th>
<td class="desc">[candidate.name]&nbsp;</td>
</tr>
<tr class="d1">
<td>What you plan to call yourself. Suggestions: Any character name you would choose for a station character OR an AI.</td>
</tr>
<tr class="d0">
<th rowspan="2"><a href='byond://?src=[UID()];option=desc;new=1;candidate=\ref[candidate]'>Description</a>:</th>
<td class="desc">[candidate.description]&nbsp;</td>
</tr>
<tr class="d1">
<td>What sort of pAI you typically play; your mannerisms, your quirks, etc. This can be as sparse or as detailed as you like.</td>
</tr>
<tr class="d0">
<th rowspan="2"><a href='byond://?src=[UID()];option=role;new=1;candidate=\ref[candidate]'>Preferred Role</a>:</th>
<td class="desc">[candidate.role]&nbsp;</td>
</tr>
<tr class="d1">
<td>Do you like to partner with sneaky social ninjas? Like to help security hunt down thugs? Enjoy watching an engineer's back while he saves the station yet again? This doesn't have to be limited to just station jobs. Pretty much any general descriptor for what you'd like to be doing works here.</td>
</tr>
<tr class="d0">
<th rowspan="2"><a href='byond://?src=[UID()];option=ooc;new=1;candidate=\ref[candidate]'>OOC Comments</a>:</th>
<td class="desc">[candidate.comments]&nbsp;</td>
</tr>
<tr class="d1">
<td>Anything you'd like to address specifically to the player reading this in an OOC manner. \"I prefer more serious RP.\", \"I'm still learning the interface!\", etc. Feel free to leave this blank if you want.</td>
</tr>
</table>
<br>
<table>
<tr>
<td class="button">
<a href='byond://?src=[UID()];option=save;new=1;candidate=\ref[candidate]' class="button">Save Personality</a>
<table class="desc">
<tr class="d0">
<th>Name:</th>
<td>[c.name]</td>
</tr>
<tr class="d1">
<th>Description:</th>
<td>[c.description]</td>
</tr>
<tr class="d0">
<th>Preferred Role:</th>
<td>[c.role]</td>
</tr>
<tr class="d1">
<th>OOC Comments:</th>
<td>[c.comments]</td>
</tr>
</table>
<table class="download">
<td class="download"><a href='byond://?src=[UID()];download=1;candidate=\ref[c];device=\ref[p]' class="button"><b>Download [c.name]</b></a>
</td>
</tr>
<tr>
<td class="button">
<a href='byond://?src=[UID()];option=load;new=1;candidate=\ref[candidate]' class="button">Load Personality</a>
</td>
</tr>
</table><br>
<table>
<td class="button"><a href='byond://?src=[UID()];option=submit;new=1;candidate=\ref[candidate]' class="button"><b><font size="4px">Submit Personality</font></b></a></td>
</table><br>
</body>
</table>
<br>
"}
M << browse(dat, "window=paiRecruit;size=580x580;")
dat += {"
</body>
</html>
"}
proc/findPAI(var/obj/item/paicard/p, var/mob/user)
requestRecruits(p, user)
var/list/available = list()
for(var/datum/paiCandidate/c in paiController.pai_candidates)
if(c.ready)
var/found = 0
for(var/mob/o in GLOB.respawnable_list)
if(o.key == c.key)
found = 1
if(found)
available.Add(c)
var/dat = ""
user << browse(dat, "window=findPai")
dat += {"
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">
<html>
<head>
<style>
body {
margin-top:5px;
font-family:Verdana;
color:white;
font-size:13px;
background-image:url('uiBackground.png');
background-repeat:repeat-x;
background-color:#272727;
background-position:center top;
}
table {
font-size:13px;
}
table.desc {
border-collapse:collapse;
font-size:13px;
border: 1px solid #161616;
width:100%;
}
table.download {
border-collapse:collapse;
font-size:13px;
border: 1px solid #161616;
width:100%;
}
tr.d0 td, tr.d0 th {
background-color: #506070;
color: white;
}
tr.d1 td, tr.d1 th {
background-color: #708090;
color: white;
}
tr.d2 td {
background-color: #00FF00;
color: white;
text-align:center;
}
td.button {
border: 1px solid #161616;
background-color: #40628a;
text-align: center;
}
td.download {
border: 1px solid #161616;
background-color: #40628a;
text-align: center;
}
th {
text-align:left;
width:125px;
vertical-align:top;
}
a.button {
color:white;
text-decoration: none;
}
</style>
</head>
<body>
<b><font size='3px'>pAI Availability List</font></b><br><br>
"}
dat += "<p>Displaying available AI personalities from central database... If there are no entries, or if a suitable entry is not listed, check again later as more personalities may be added.</p>"
/datum/paiController/proc/requestRecruits(var/obj/item/paicard/P, mob/user)
for(var/mob/dead/observer/O in GLOB.player_list)
if(O.client && (ROLE_PAI in O.client.prefs.be_special))
if(player_old_enough_antag(O.client,ROLE_PAI))
if(check_recruit(O))
to_chat(O, "<span class='boldnotice'>A pAI card activated by [user.real_name] is looking for personalities. (<a href='?src=[O.UID()];jump=\ref[P]'>Teleport</a> | <a href='?src=[UID()];signup=\ref[O]'>Sign Up</a>)</span>")
//question(O.client)
for(var/datum/paiCandidate/c in available)
dat += {"
<table class="desc">
<tr class="d0">
<th>Name:</th>
<td>[c.name]</td>
</tr>
<tr class="d1">
<th>Description:</th>
<td>[c.description]</td>
</tr>
<tr class="d0">
<th>Preferred Role:</th>
<td>[c.role]</td>
</tr>
<tr class="d1">
<th>OOC Comments:</th>
<td>[c.comments]</td>
</tr>
</table>
<table class="download">
<td class="download"><a href='byond://?src=[UID()];download=1;candidate=\ref[c];device=\ref[p]' class="button"><b>Download [c.name]</b></a>
</td>
</table>
<br>
"}
dat += {"
</body>
</html>
"}
user << browse(dat, "window=findPai")
proc/requestRecruits(var/obj/item/paicard/P, mob/user)
for(var/mob/dead/observer/O in GLOB.player_list)
if(O.client && (ROLE_PAI in O.client.prefs.be_special))
if(player_old_enough_antag(O.client,ROLE_PAI))
if(check_recruit(O))
to_chat(O, "<span class='boldnotice'>A pAI card activated by [user.real_name] is looking for personalities. (<a href='?src=[O.UID()];jump=\ref[P]'>Teleport</a> | <a href='?src=[UID()];signup=\ref[O]'>Sign Up</a>)</span>")
//question(O.client)
proc/check_recruit(var/mob/dead/observer/O)
if(jobban_isbanned(O, ROLE_PAI) || jobban_isbanned(O,"nonhumandept"))
return 0
if(!player_old_enough_antag(O.client,ROLE_PAI))
return 0
if(cannotPossess(O))
return 0
if(!(O in GLOB.respawnable_list))
return 0
if(O.client)
return 1
/datum/paiController/proc/check_recruit(var/mob/dead/observer/O)
if(jobban_isbanned(O, ROLE_PAI) || jobban_isbanned(O,"nonhumandept"))
return 0
if(!player_old_enough_antag(O.client,ROLE_PAI))
return 0
if(cannotPossess(O))
return 0
if(!(O in GLOB.respawnable_list))
return 0
if(O.client)
return 1
return 0
proc/question(var/client/C)
spawn(0)
if(!C) return
asked.Add(C.key)
asked[C.key] = world.time
var/response = alert(C, "Someone is requesting a pAI personality. Would you like to play as a personal AI?", "pAI Request", "Yes", "No", "Never for this round")
if(!C) return //handle logouts that happen whilst the alert is waiting for a response.
if(response == "Yes")
recruitWindow(C.mob)
else if(response == "Never for this round")
var/warning = alert(C, "Are you sure? This action will be undoable and you will need to wait until next round.", "You sure?", "Yes", "No")
if(warning == "Yes")
asked[C.key] = INFINITY
else
question(C)
/datum/paiController/proc/question(var/client/C)
spawn(0)
if(!C) return
asked.Add(C.key)
asked[C.key] = world.time
var/response = alert(C, "Someone is requesting a pAI personality. Would you like to play as a personal AI?", "pAI Request", "Yes", "No", "Never for this round")
if(!C) return //handle logouts that happen whilst the alert is waiting for a response.
if(response == "Yes")
recruitWindow(C.mob)
else if(response == "Never for this round")
var/warning = alert(C, "Are you sure? This action will be undoable and you will need to wait until next round.", "You sure?", "Yes", "No")
if(warning == "Yes")
asked[C.key] = INFINITY
else
question(C)
@@ -6,7 +6,7 @@
act = copytext(act, 1, t1)
//Emote Cooldown System (it's so simple!)
// proc/handle_emote_CD() located in [code\modules\mob\emote.dm]
//proc/handle_emote_CD() located in [code\modules\mob\emote.dm]
var/on_CD = 0
act = lowertext(act)
switch(act)
@@ -174,4 +174,4 @@
"You announce you are operating in low power mode.")
playsound(loc, 'sound/machines/buzz-two.ogg', 50, 0)
else
to_chat(src, "<span class='warning'>You can only use this emote when you're out of charge.</span>")
to_chat(src, "<span class='warning'>You can only use this emote when you're out of charge.</span>")
@@ -9,7 +9,7 @@
act = copytext(act,1,length(act))
//Emote Cooldown System (it's so simple!)
// proc/handle_emote_CD() located in [code\modules\mob\emote.dm]
//proc/handle_emote_CD() located in [code\modules\mob\emote.dm]
var/on_CD = 0
act = lowertext(act)
switch(act)
@@ -69,4 +69,4 @@
playsound(src.loc, 'sound/goonstation/voice/robot_scream.ogg', 80, 0)
m_type = 2
..(act, m_type, message)
..(act, m_type, message)
+1 -1
View File
@@ -123,7 +123,7 @@
* Sleepypens
*/
/obj/item/pen/sleepy
flags = OPENCONTAINER
container_type = OPENCONTAINER
origin_tech = "engineering=4;syndicate=2"
@@ -242,11 +242,11 @@
name = "shotgun dart"
desc = "A dart for use in shotguns. Can be injected with up to 30 units of any chemical."
icon_state = "cshell"
container_type = OPENCONTAINER
projectile_type = /obj/item/projectile/bullet/dart
/obj/item/ammo_casing/shotgun/dart/New()
..()
flags |= OPENCONTAINER
create_reagents(30)
/obj/item/ammo_casing/shotgun/dart/attackby()
+3 -3
View File
@@ -29,7 +29,7 @@
var/obj/item/dart_cartridge/cartridge = null //Container of darts.
var/max_beakers = 3
var/dart_reagent_amount = 15
var/container_type = /obj/item/reagent_containers/glass/beaker
var/containers_type = /obj/item/reagent_containers/glass/beaker
var/list/starting_chems = null
/obj/item/gun/dartgun/update_icon()
@@ -49,7 +49,7 @@
..()
if(starting_chems)
for(var/chem in starting_chems)
var/obj/B = new container_type(src)
var/obj/B = new containers_type(src)
B.reagents.add_reagent(chem, 50)
beakers += B
cartridge = new /obj/item/dart_cartridge(src)
@@ -87,7 +87,7 @@
update_icon()
return
if(istype(I, /obj/item/reagent_containers/glass))
if(!istype(I, container_type))
if(!istype(I, containers_type))
to_chat(user, "<span class='warning'>[I] doesn't seem to fit into [src].</span>")
return
if(beakers.len >= max_beakers)
@@ -143,7 +143,8 @@
fire_sound = 'sound/weapons/laser.ogg'
usesound = 'sound/items/Welder.ogg'
toolspeed = 1
flags = CONDUCT | OPENCONTAINER
container_type = OPENCONTAINER
flags = CONDUCT
attack_verb = list("attacked", "slashed", "cut", "sliced")
force = 12
sharp = 1
+15
View File
@@ -683,6 +683,16 @@ var/const/INGEST = 2
stuff += A.id
return english_list(stuff)
/datum/reagents/proc/log_list()
if(!length(reagent_list))
return "no reagents"
var/list/data = list()
for(var/r in reagent_list) //no reagents will be left behind
var/datum/reagent/R = r
data += "[R.id] ([round(R.volume, 0.1)]u)"
//Using IDs because SOME chemicals (I'm looking at you, chlorhydrate-beer) have the same names as other chemicals.
return english_list(data)
//two helper functions to preserve data across reactions (needed for xenoarch)
/datum/reagents/proc/get_data(reagent_id)
for(var/datum/reagent/D in reagent_list)
@@ -744,6 +754,11 @@ var/const/INGEST = 2
break
return result
/datum/reagents/proc/holder_full()
if(total_volume >= maximum_volume)
return TRUE
return FALSE
/datum/reagents/Destroy()
. = ..()
processing_objects -= src
@@ -378,7 +378,7 @@
/obj/machinery/chem_master/proc/chemical_safety_check(datum/reagents/R)
var/all_safe = 1
for(var/datum/reagent/A in R.reagent_list)
if(!safe_chem_list.Find(A.id))
if(!GLOB.safe_chem_list.Find(A.id))
all_safe = 0
return all_safe
@@ -30,7 +30,6 @@
if(BL.data && BL.data["viruses"])
var/list/viruses = BL.data["viruses"]
return viruses[index]
return null
/obj/machinery/computer/pandemic/proc/GetResistancesByIndex(index)
if(beaker && beaker.reagents)
@@ -40,13 +39,11 @@
if(BL.data && BL.data["resistances"])
var/list/resistances = BL.data["resistances"]
return resistances[index]
return null
/obj/machinery/computer/pandemic/proc/GetVirusTypeByIndex(index)
var/datum/disease/D = GetVirusByIndex(index)
if(D)
return D.GetDiseaseID()
return null
/obj/machinery/computer/pandemic/proc/replicator_cooldown(waittime)
wait = 1
@@ -175,7 +172,6 @@
return
add_fingerprint(usr)
return
//Prints a nice virus release form. Props to Urbanliner for the layout
/obj/machinery/computer/pandemic/proc/print_form(var/datum/disease/advance/D, mob/living/user)
@@ -319,12 +315,12 @@
popup.set_content(dat)
popup.open(0)
onclose(user, "pandemic")
return
/obj/machinery/computer/pandemic/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/reagent_containers) && (I.flags & OPENCONTAINER))
if(stat & (NOPOWER|BROKEN)) return
if(istype(I, /obj/item/reagent_containers) && (I.container_type & OPENCONTAINER))
if(stat & (NOPOWER|BROKEN))
return
if(beaker)
to_chat(user, "<span class='warning'>A beaker is already loaded into the machine!</span>")
return
@@ -112,7 +112,7 @@
if(default_unfasten_wrench(user, I))
return
if (istype(I, /obj/item/reagent_containers) && (I.flags & OPENCONTAINER) )
if (istype(I, /obj/item/reagent_containers) && (I.container_type & OPENCONTAINER) )
if (!beaker)
if(!user.drop_item())
return 1
@@ -238,12 +238,4 @@ About the Tools:
It simply tells us how much to transfer when
'pouring' our reagents into something else.
atom/proc/is_open_container()
Checks atom/var/flags & OPENCONTAINER.
If this returns 1 , you can use syringes, beakers etc
to manipulate the contents of this object.
If it's 0, you'll need to write your own custom reagent
transfer code since you will not be able to use the standard
tools to manipulate it.
*/
@@ -551,10 +551,10 @@
update_flags |= M.AdjustEyeBlurry(-1, FALSE)
update_flags |= M.AdjustEarDamage(-1, FALSE)
if(prob(50))
update_flags |= M.CureNearsighted(FALSE)
update_flags |= M.CureNearsighted()
if(prob(30))
update_flags |= M.CureBlind(FALSE)
update_flags |= M.SetEyeBlind(0, FALSE)
update_flags |= M.CureBlind()
update_flags |= M.SetEyeBlind(0)
if(M.ear_damage <= 25)
if(prob(30))
M.SetEarDeaf(0)
@@ -7,7 +7,7 @@
/datum/reagent/toxin/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
update_flags |= M.adjustToxLoss(2, FALSE)
update_flags |= M.adjustToxLoss(2*REAGENTS_EFFECT_MULTIPLIER, FALSE)
return ..() | update_flags
/datum/reagent/spider_venom
@@ -61,14 +61,6 @@
/obj/item/reagent_containers/afterattack(obj/target, mob/user , flag)
return
/obj/item/reagent_containers/proc/reagentlist() //Return reagents in a reagent_container, default to source
var/data
if(reagents && reagents.reagent_list && reagents.reagent_list.len) //find a reagent list if there is and check if it has entries
for(var/datum/reagent/R in reagents.reagent_list) //no reagents will be left behind
data += "[R.id]([R.volume] units); " //Using IDs because SOME chemicals(I'm looking at you, chlorhydrate-beer) have the same names as other chemicals.
return data
else return "No reagents"
/obj/item/reagent_containers/wash(mob/user, atom/source)
if(is_open_container())
if(reagents.total_volume >= volume)
@@ -85,7 +85,7 @@
var/datum/reagent/injected = GLOB.chemical_reagents_list[reagent_ids[mode]]
var/contained = injected.name
var/trans = R.trans_to(M, amount_per_transfer_from_this)
add_attack_logs(M, user, "Injected with [name] containing [contained], transfered [trans] units")
add_attack_logs(user, M, "Injected with [name] containing [contained], transfered [trans] units")
M.LAssailant = user
to_chat(user, "<span class='notice'>[trans] units injected. [R.total_volume] units remaining.</span>")
return
@@ -9,7 +9,7 @@
item_state = "atoxinbottle"
amount_per_transfer_from_this = 10
possible_transfer_amounts = list(5,10,15,25,30)
flags = OPENCONTAINER
container_type = OPENCONTAINER
volume = 30
/obj/item/reagent_containers/glass/bottle/on_reagent_change()
@@ -108,4 +108,37 @@
icon_state = "pipette"
amount_per_transfer_from_this = 1
possible_transfer_amounts = list(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1)
volume = 1
volume = 1
//Syndicate item. Virus transmitting mini hypospray
/obj/item/reagent_containers/dropper/precision/viral_injector
/obj/item/reagent_containers/dropper/precision/viral_injector/attack(mob/living/M, mob/living/user, def_zone)
if(M.can_inject(user, 1))
to_chat(user, "<span class='warning'>You stab [M] with the [src].</span>")
if(reagents.total_volume && M.reagents)
var/list/injected = list()
for(var/datum/reagent/R in reagents.reagent_list)
injected += R.name
var/datum/reagent/blood/B = R
if(istype(B) && B.data["viruses"])
var/virList = list()
for(var/dis in B.data["viruses"])
var/datum/disease/D = dis
var/virusData = D.name
var/english_symptoms = list()
var/datum/disease/advance/A = D
if(A)
for(var/datum/symptom/S in A.symptoms)
english_symptoms += S.name
virusData += " ([english_list(english_symptoms)])"
virList += virusData
var/str = english_list(virList)
add_attack_logs(user, M, "Infected with [str].")
reagents.reaction(M, INGEST, reagents.total_volume)
reagents.trans_to(M, 1)
var/contained = english_list(injected)
add_attack_logs(user, M, "Injected with [src] containing ([contained])")
@@ -11,7 +11,7 @@
amount_per_transfer_from_this = 10
possible_transfer_amounts = list(5,10,15,25,30,50)
volume = 50
flags = OPENCONTAINER
container_type = OPENCONTAINER
var/label_text = ""
// the fucking asshole who designed this can go die in a fire - Iamgoofball
@@ -59,10 +59,10 @@
..()
if(is_open_container())
to_chat(usr, "<span class='notice'>You put the lid on [src].</span>")
flags ^= OPENCONTAINER
container_type ^= REFILLABLE | DRAINABLE
else
to_chat(usr, "<span class='notice'>You take the lid off [src].</span>")
flags |= OPENCONTAINER
container_type |= REFILLABLE | DRAINABLE
update_icon()
/obj/item/reagent_containers/glass/afterattack(obj/target, mob/user, proximity)
@@ -262,7 +262,7 @@
volume = 100
amount_per_transfer_from_this = 10
possible_transfer_amounts = list(5,10,15,25,30,50,100)
flags = OPENCONTAINER
container_type = OPENCONTAINER
/obj/item/reagent_containers/glass/beaker/vial
name = "vial"
@@ -272,7 +272,7 @@
volume = 25
amount_per_transfer_from_this = 10
possible_transfer_amounts = list(5,10,15,25)
flags = OPENCONTAINER
container_type = OPENCONTAINER
can_assembly = 0
/obj/item/reagent_containers/glass/beaker/drugs
@@ -282,7 +282,7 @@
amount_per_transfer_from_this = 2
possible_transfer_amounts = 2
volume = 10
flags = OPENCONTAINER
container_type = OPENCONTAINER
can_assembly = 0
/obj/item/reagent_containers/glass/beaker/noreact
@@ -293,7 +293,7 @@
volume = 50
amount_per_transfer_from_this = 10
origin_tech = "materials=2;engineering=3;plasmatech=3"
flags = OPENCONTAINER
container_type = OPENCONTAINER
/obj/item/reagent_containers/glass/beaker/noreact/New()
..()
@@ -307,7 +307,7 @@
volume = 300
amount_per_transfer_from_this = 10
possible_transfer_amounts = list(5,10,15,25,30,50,100,300)
flags = OPENCONTAINER
container_type = OPENCONTAINER
origin_tech = "bluespace=5;materials=4;plasmatech=4"
/obj/item/reagent_containers/glass/beaker/cryoxadone
@@ -337,7 +337,7 @@
volume = 120
armor = list(melee = 10, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0)
slot_flags = SLOT_HEAD
flags = OPENCONTAINER
container_type = OPENCONTAINER
/obj/item/reagent_containers/glass/bucket/equipped(mob/user, slot)
..()
@@ -11,7 +11,7 @@
amount_per_transfer_from_this = 5
volume = 30
possible_transfer_amounts = list(1,2,3,4,5,10,15,20,25,30)
flags = OPENCONTAINER
container_type = OPENCONTAINER
slot_flags = SLOT_BELT
var/ignore_flags = FALSE
var/emagged = FALSE
@@ -52,7 +52,7 @@
if(safety_hypo && !emagged)
var/found_forbidden_reagent = FALSE
for(var/datum/reagent/R in reagents.reagent_list)
if(!safe_chem_list.Find(R.id))
if(!GLOB.safe_chem_list.Find(R.id))
reagents.del_reagent(R.id)
found_forbidden_reagent = TRUE
if(found_forbidden_reagent)
@@ -4,7 +4,8 @@
icon = 'icons/obj/janitor.dmi'
icon_state = "cleaner"
item_state = "cleaner"
flags = OPENCONTAINER | NOBLUDGEON
flags = NOBLUDGEON
container_type = OPENCONTAINER
slot_flags = SLOT_BELT
throwforce = 0
w_class = WEIGHT_CLASS_SMALL
@@ -16,6 +16,7 @@
volume = 15
w_class = WEIGHT_CLASS_TINY
sharp = 1
container_type = TRANSPARENT
var/busy = 0
var/mode = SYRINGE_DRAW
var/projectile_type = /obj/item/projectile/bullet/dart/syringe
@@ -78,7 +79,7 @@
switch(mode)
if(SYRINGE_DRAW)
if(reagents.total_volume >= reagents.maximum_volume)
if(reagents.holder_full())
to_chat(user, "<span class='notice'>The syringe is full.</span>")
return
@@ -91,7 +92,7 @@
if(!do_mob(user, target))
busy = 0
return
if(reagents.total_volume >= reagents.maximum_volume)
if(reagents.holder_full())
return
busy = 0
if(L.transfer_blood_to(src, drawn_amount))
@@ -104,14 +105,14 @@
to_chat(user, "<span class='warning'>[target] is empty!</span>")
return
if(!target.is_open_container() && !istype(target,/obj/structure/reagent_dispensers) && !istype(target,/obj/item/slime_extract))
if(!target.is_drawable())
to_chat(user, "<span class='warning'>You cannot directly remove reagents from [target]!</span>")
return
var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this) // transfer from, transfer to - who cares?
to_chat(user, "<span class='notice'>You fill [src] with [trans] units of the solution.</span>")
if(reagents.total_volume >= reagents.maximum_volume)
if(reagents.holder_full())
mode=!mode
update_icon()
@@ -120,7 +121,7 @@
to_chat(user, "<span class='notice'>[src] is empty.</span>")
return
if(!target.is_open_container() && !ismob(target) && !istype(target, /obj/item/reagent_containers/food) && !istype(target, /obj/item/slime_extract) && !istype(target, /obj/item/clothing/mask/cigarette) && !istype(target, /obj/item/storage/fancy/cigarettes))
if(!L && !target.is_injectable())
to_chat(user, "<span class='warning'>You cannot directly fill [target]!</span>")
return
if(target.reagents.total_volume >= target.reagents.maximum_volume)
+5 -11
View File
@@ -6,28 +6,22 @@
density = 1
anchored = 0
pressure_resistance = 2*ONE_ATMOSPHERE
container_type = DRAINABLE | AMOUNT_VISIBLE
var/tank_volume = 1000 //In units, how much the dispenser can hold
var/reagent_id = "water" //The ID of the reagent that the dispenser uses
var/lastrigger = "" // The last person to rig this fuel tank - Stored with the object. Only the last person matter for investigation
/obj/structure/reagent_dispensers/attackby(obj/item/W, mob/user, params)
return
/obj/structure/reagent_dispensers/attackby(obj/item/I, mob/user, params)
. = ..()
if(I.is_refillable())
return FALSE //so we can refill them via their afterattack.
/obj/structure/reagent_dispensers/New()
create_reagents(tank_volume)
reagents.add_reagent(reagent_id, tank_volume)
..()
/obj/structure/reagent_dispensers/examine(mob/user)
if(!..(user, 2))
return
if(reagents.total_volume)
to_chat(user, "<span class='notice'>It has [reagents.total_volume] units left.</span>")
else
to_chat(user, "<span class='danger'>It's empty.</span>")
/obj/structure/reagent_dispensers/proc/boom()
visible_message("<span class='danger'>[src] ruptures!</span>")
chem_splash(loc, 5, list(reagents))
+207 -234
View File
@@ -511,154 +511,152 @@
var/tomail = 0 //changes if contains wrapped package
var/hasmob = 0 //If it contains a mob
Destroy()
QDEL_NULL(gas)
active = 0
return ..()
/obj/structure/disposalholder/Destroy()
QDEL_NULL(gas)
active = 0
return ..()
// initialize a holder from the contents of a disposal unit
proc/init(var/obj/machinery/disposal/D)
gas = D.air_contents// transfer gas resv. into holder object
/obj/structure/disposalholder/proc/init(var/obj/machinery/disposal/D)
gas = D.air_contents// transfer gas resv. into holder object
//Check for any living mobs trigger hasmob.
//hasmob effects whether the package goes to cargo or its tagged destination.
for(var/mob/living/M in D)
if(M && M.stat != 2 && !istype(M,/mob/living/silicon/robot/drone))
hasmob = 1
//Check for any living mobs trigger hasmob.
//hasmob effects whether the package goes to cargo or its tagged destination.
for(var/mob/living/M in D)
if(M && M.stat != 2 && !istype(M,/mob/living/silicon/robot/drone))
hasmob = 1
//Checks 1 contents level deep. This means that players can be sent through disposals...
//...but it should require a second person to open the package. (i.e. person inside a wrapped locker)
for(var/obj/O in D)
if(O.contents)
for(var/mob/living/M in O.contents)
if(M && M.stat != 2 && !istype(M,/mob/living/silicon/robot/drone))
hasmob = 1
//Checks 1 contents level deep. This means that players can be sent through disposals...
//...but it should require a second person to open the package. (i.e. person inside a wrapped locker)
for(var/obj/O in D)
if(O.contents)
for(var/mob/living/M in O.contents)
if(M && M.stat != 2 && !istype(M,/mob/living/silicon/robot/drone))
hasmob = 1
// now everything inside the disposal gets put into the holder
// note AM since can contain mobs or objs
for(var/atom/movable/AM in D)
AM.loc = src
if(istype(AM, /mob/living/carbon/human))
var/mob/living/carbon/human/H = AM
if(FAT in H.mutations) // is a human and fat?
has_fat_guy = 1 // set flag on holder
if(istype(AM, /obj/structure/bigDelivery) && !hasmob)
var/obj/structure/bigDelivery/T = AM
destinationTag = T.sortTag
if(istype(AM, /obj/item/smallDelivery) && !hasmob)
var/obj/item/smallDelivery/T = AM
destinationTag = T.sortTag
//Drones can mail themselves through maint.
if(istype(AM, /mob/living/silicon/robot/drone))
var/mob/living/silicon/robot/drone/drone = AM
destinationTag = drone.mail_destination
if(istype(AM, /obj/item/shippingPackage) && !hasmob)
var/obj/item/shippingPackage/sp = AM
if(sp.sealed) //only sealed packages get delivered to their intended destination
destinationTag = sp.sortTag
// now everything inside the disposal gets put into the holder
// note AM since can contain mobs or objs
for(var/atom/movable/AM in D)
AM.loc = src
if(istype(AM, /mob/living/carbon/human))
var/mob/living/carbon/human/H = AM
if(FAT in H.mutations) // is a human and fat?
has_fat_guy = 1 // set flag on holder
if(istype(AM, /obj/structure/bigDelivery) && !hasmob)
var/obj/structure/bigDelivery/T = AM
destinationTag = T.sortTag
if(istype(AM, /obj/item/smallDelivery) && !hasmob)
var/obj/item/smallDelivery/T = AM
destinationTag = T.sortTag
//Drones can mail themselves through maint.
if(istype(AM, /mob/living/silicon/robot/drone))
var/mob/living/silicon/robot/drone/drone = AM
destinationTag = drone.mail_destination
if(istype(AM, /obj/item/shippingPackage) && !hasmob)
var/obj/item/shippingPackage/sp = AM
if(sp.sealed) //only sealed packages get delivered to their intended destination
destinationTag = sp.sortTag
// start the movement process
// argument is the disposal unit the holder started in
proc/start(var/obj/machinery/disposal/D)
if(!D.trunk)
D.expel(src) // no trunk connected, so expel immediately
return
loc = D.trunk
active = 1
dir = DOWN
spawn(1)
move() // spawn off the movement process
/obj/structure/disposalholder/proc/start(var/obj/machinery/disposal/D)
if(!D.trunk)
D.expel(src) // no trunk connected, so expel immediately
return
loc = D.trunk
active = 1
dir = DOWN
spawn(1)
move() // spawn off the movement process
return
// movement process, persists while holder is moving through pipes
proc/move()
var/obj/structure/disposalpipe/last
while(active)
/* if(hasmob && prob(3))
for(var/mob/living/H in src)
if(!istype(H,/mob/living/silicon/robot/drone)) //Drones use the mailing code to move through the disposal system,
H.take_overall_damage(20, 0, TRUE, "Blunt Trauma") */ //horribly maim any living creature jumping down disposals. c'est la vie
/obj/structure/disposalholder/proc/move()
var/obj/structure/disposalpipe/last
while(active)
/* if(hasmob && prob(3))
for(var/mob/living/H in src)
if(!istype(H,/mob/living/silicon/robot/drone)) //Drones use the mailing code to move through the disposal system,
H.take_overall_damage(20, 0, "Blunt Trauma") */ //horribly maim any living creature jumping down disposals. c'est la vie
if(has_fat_guy && prob(2)) // chance of becoming stuck per segment if contains a fat guy
active = 0
// find the fat guys
for(var/mob/living/carbon/human/H in src)
if(has_fat_guy && prob(2)) // chance of becoming stuck per segment if contains a fat guy
active = 0
// find the fat guys
for(var/mob/living/carbon/human/H in src)
break
sleep(1) // was 1
var/obj/structure/disposalpipe/curr = loc
last = curr
curr = curr.transfer(src)
if(!curr)
last.expel(src, loc, dir)
break
sleep(1) // was 1
var/obj/structure/disposalpipe/curr = loc
last = curr
curr = curr.transfer(src)
if(!curr)
last.expel(src, loc, dir)
//
if(!(count--))
active = 0
return
//
if(!(count--))
active = 0
return
// find the turf which should contain the next pipe
proc/nextloc()
return get_step(loc,dir)
/obj/structure/disposalholder/proc/nextloc()
return get_step(loc,dir)
// find a matching pipe on a turf
proc/findpipe(var/turf/T)
if(!T)
return null
var/fdir = turn(dir, 180) // flip the movement direction
for(var/obj/structure/disposalpipe/P in T)
if(fdir & P.dpdir) // find pipe direction mask that matches flipped dir
return P
// if no matching pipe, return null
/obj/structure/disposalholder/proc/findpipe(var/turf/T)
if(!T)
return null
var/fdir = turn(dir, 180) // flip the movement direction
for(var/obj/structure/disposalpipe/P in T)
if(fdir & P.dpdir) // find pipe direction mask that matches flipped dir
return P
// if no matching pipe, return null
return null
// merge two holder objects
// used when a a holder meets a stuck holder
proc/merge(var/obj/structure/disposalholder/other)
for(var/atom/movable/AM in other)
AM.loc = src // move everything in other holder to this one
if(ismob(AM))
var/mob/M = AM
if(M.client) // if a client mob, update eye to follow this holder
M.client.eye = src
/obj/structure/disposalholder/proc/merge(var/obj/structure/disposalholder/other)
for(var/atom/movable/AM in other)
AM.loc = src // move everything in other holder to this one
if(ismob(AM))
var/mob/M = AM
if(M.client) // if a client mob, update eye to follow this holder
M.client.eye = src
if(other.has_fat_guy)
has_fat_guy = 1
qdel(other)
if(other.has_fat_guy)
has_fat_guy = 1
qdel(other)
// called when player tries to move while in a pipe
relaymove(mob/user as mob)
/obj/structure/disposalholder/relaymove(mob/user as mob)
if(!istype(user,/mob/living))
return
if(!istype(user,/mob/living))
return
var/mob/living/U = user
var/mob/living/U = user
if(U.stat || U.last_special <= world.time)
return
if(U.stat || U.last_special <= world.time)
return
U.last_special = world.time+100
U.last_special = world.time+100
if(src.loc)
for(var/mob/M in hearers(src.loc.loc))
to_chat(M, "<FONT size=[max(0, 5 - get_dist(src, M))]>CLONG, clong!</FONT>")
if(src.loc)
for(var/mob/M in hearers(src.loc.loc))
to_chat(M, "<FONT size=[max(0, 5 - get_dist(src, M))]>CLONG, clong!</FONT>")
playsound(src.loc, 'sound/effects/clang.ogg', 50, 0, 0)
playsound(src.loc, 'sound/effects/clang.ogg', 50, 0, 0)
// called to vent all gas in holder to a location
proc/vent_gas(var/atom/location)
if(location)
location.assume_air(gas) // vent all gas to turf
air_update_turf()
return
/obj/structure/disposalholder/proc/vent_gas(var/atom/location)
if(location)
location.assume_air(gas) // vent all gas to turf
air_update_turf()
return
// Disposal pipes
@@ -1000,44 +998,44 @@
var/negdir = 0
var/sortdir = 0
proc/updatedesc()
desc = "An underfloor disposal pipe with a package sorting mechanism."
if(sortType>0)
var/tag = uppertext(GLOB.TAGGERLOCATIONS[sortType])
desc += "\nIt's tagged with [tag]"
/obj/structure/disposalpipe/sortjunction/proc/updatedesc()
desc = "An underfloor disposal pipe with a package sorting mechanism."
if(sortType>0)
var/tag = uppertext(GLOB.TAGGERLOCATIONS[sortType])
desc += "\nIt's tagged with [tag]"
proc/updatedir()
posdir = dir
negdir = turn(posdir, 180)
/obj/structure/disposalpipe/sortjunction/proc/updatedir()
posdir = dir
negdir = turn(posdir, 180)
if(icon_state == "pipe-j1s")
sortdir = turn(posdir, -90)
else
icon_state = "pipe-j2s"
sortdir = turn(posdir, 90)
if(icon_state == "pipe-j1s")
sortdir = turn(posdir, -90)
else
icon_state = "pipe-j2s"
sortdir = turn(posdir, 90)
dpdir = sortdir | posdir | negdir
dpdir = sortdir | posdir | negdir
New()
..()
updatedir()
updatedesc()
update()
/obj/structure/disposalpipe/sortjunction/New()
..()
updatedir()
updatedesc()
update()
return
/obj/structure/disposalpipe/sortjunction/attackby(var/obj/item/I, var/mob/user, params)
if(..())
return
attackby(var/obj/item/I, var/mob/user, params)
if(..())
return
if(istype(I, /obj/item/destTagger))
var/obj/item/destTagger/O = I
if(istype(I, /obj/item/destTagger))
var/obj/item/destTagger/O = I
if(O.currTag > 0)// Tag set
sortType = O.currTag
playsound(src.loc, 'sound/machines/twobeep.ogg', 100, 1)
var/tag = uppertext(GLOB.TAGGERLOCATIONS[O.currTag])
to_chat(user, "<span class='notice'>Changed filter to [tag]</span>")
updatedesc()
if(O.currTag > 0)// Tag set
sortType = O.currTag
playsound(src.loc, 'sound/machines/twobeep.ogg', 100, 1)
var/tag = uppertext(GLOB.TAGGERLOCATIONS[O.currTag])
to_chat(user, "<span class='notice'>Changed filter to [tag]</span>")
updatedesc()
// next direction to move
@@ -1045,61 +1043,59 @@
// if coming in from posdir, then flip around and go back to posdir
// if coming in from sortdir, go to posdir
nextdir(var/fromdir, var/sortTag)
//var/flipdir = turn(fromdir, 180)
if(fromdir != sortdir) // probably came from the negdir
/obj/structure/disposalpipe/sortjunction/nextdir(var/fromdir, var/sortTag)
//var/flipdir = turn(fromdir, 180)
if(fromdir != sortdir) // probably came from the negdir
if(src.sortType == sortTag) //if destination matches filtered type...
return sortdir // exit through sortdirection
else
return posdir
else // came from sortdir
// so go with the flow to positive direction
if(src.sortType == sortTag) //if destination matches filtered type...
return sortdir // exit through sortdirection
else
return posdir
else // came from sortdir
// so go with the flow to positive direction
return posdir
transfer(var/obj/structure/disposalholder/H)
var/nextdir = nextdir(H.dir, H.destinationTag)
H.dir = nextdir
var/turf/T = H.nextloc()
var/obj/structure/disposalpipe/P = H.findpipe(T)
/obj/structure/disposalpipe/sortjunction/transfer(var/obj/structure/disposalholder/H)
var/nextdir = nextdir(H.dir, H.destinationTag)
H.dir = nextdir
var/turf/T = H.nextloc()
var/obj/structure/disposalpipe/P = H.findpipe(T)
if(P)
// find other holder in next loc, if inactive merge it with current
var/obj/structure/disposalholder/H2 = locate() in P
if(H2 && !H2.active)
H.merge(H2)
if(P)
// find other holder in next loc, if inactive merge it with current
var/obj/structure/disposalholder/H2 = locate() in P
if(H2 && !H2.active)
H.merge(H2)
H.loc = P
else // if wasn't a pipe, then set loc to turf
H.loc = T
return null
H.loc = P
else // if wasn't a pipe, then set loc to turf
H.loc = T
return null
return P
return P
//a three-way junction that sorts objects destined for the mail office mail table (tomail = 1)
/obj/structure/disposalpipe/wrapsortjunction
desc = "An underfloor disposal pipe which sorts wrapped and unwrapped objects."
icon_state = "pipe-j1s"
var/posdir = 0
var/negdir = 0
var/sortdir = 0
New()
..()
posdir = dir
if(icon_state == "pipe-j1s")
sortdir = turn(posdir, -90)
negdir = turn(posdir, 180)
else
icon_state = "pipe-j2s"
sortdir = turn(posdir, 90)
negdir = turn(posdir, 180)
dpdir = sortdir | posdir | negdir
/obj/structure/disposalpipe/wrapsortjunction/New()
..()
posdir = dir
if(icon_state == "pipe-j1s")
sortdir = turn(posdir, -90)
negdir = turn(posdir, 180)
else
icon_state = "pipe-j2s"
sortdir = turn(posdir, 90)
negdir = turn(posdir, 180)
dpdir = sortdir | posdir | negdir
update()
return
update()
return
// next direction to move
@@ -1107,40 +1103,34 @@
// if coming in from posdir, then flip around and go back to posdir
// if coming in from sortdir, go to posdir
nextdir(var/fromdir, var/istomail)
//var/flipdir = turn(fromdir, 180)
if(fromdir != sortdir) // probably came from the negdir
if(istomail) //if destination matches filtered type...
return sortdir // exit through sortdirection
else
return posdir
else // came from sortdir
// so go with the flow to positive direction
/obj/structure/disposalpipe/wrapsortjunction/nextdir(var/fromdir, var/istomail)
//var/flipdir = turn(fromdir, 180)
if(fromdir != sortdir) // probably came from the negdir
if(istomail) //if destination matches filtered type...
return sortdir // exit through sortdirection
else
return posdir
else // came from sortdir
return posdir // so go with the flow to positive direction
transfer(var/obj/structure/disposalholder/H)
var/nextdir = nextdir(H.dir, H.tomail)
H.dir = nextdir
var/turf/T = H.nextloc()
var/obj/structure/disposalpipe/P = H.findpipe(T)
if(P)
// find other holder in next loc, if inactive merge it with current
var/obj/structure/disposalholder/H2 = locate() in P
if(H2 && !H2.active)
H.merge(H2)
H.loc = P
else // if wasn't a pipe, then set loc to turf
H.loc = T
return null
return P
/obj/structure/disposalpipe/wrapsortjunction/transfer(var/obj/structure/disposalholder/H)
var/nextdir = nextdir(H.dir, H.tomail)
H.dir = nextdir
var/turf/T = H.nextloc()
var/obj/structure/disposalpipe/P = H.findpipe(T)
if(P)
// find other holder in next loc, if inactive merge it with current
var/obj/structure/disposalholder/H2 = locate() in P
if(H2 && !H2.active)
H.merge(H2)
H.loc = P
else // if wasn't a pipe, then set loc to turf
H.loc = T
return null
return P
//a trunk joining to a disposal bin or outlet on the same turf
/obj/structure/disposalpipe/trunk
@@ -1203,18 +1193,6 @@
/obj/structure/disposalpipe/trunk/attackby(var/obj/item/I, var/mob/user, params)
//Disposal bins or chutes
/*
These shouldn't be required
var/obj/machinery/disposal/D = locate() in src.loc
if(D && D.anchored)
return
//Disposal outlet
var/obj/structure/disposaloutlet/O = locate() in src.loc
if(O && O.anchored)
return
*/
//Disposal constructors
var/obj/structure/disposalconstruct/C = locate() in src.loc
if(C && C.anchored)
@@ -1275,18 +1253,13 @@
// i.e. will be treated as an empty turf
desc = "A broken piece of disposal pipe."
New()
..()
update()
return
/obj/structure/disposalpipe/broken/New()
..()
update()
return
// called when welded
// for broken pipe, remove and turn into scrap
welded()
// var/obj/item/scrap/S = new(src.loc)
// S.set_components(200,0,0)
qdel(src)
/obj/structure/disposalpipe/broken/welded()
qdel(src)
// the disposal outlet machine
+19 -19
View File
@@ -223,31 +223,31 @@
flags = CONDUCT
slot_flags = SLOT_BELT
proc/openwindow(mob/user as mob)
var/dat = "<tt><center><h1><b>TagMaster 2.2</b></h1></center>"
/obj/item/destTagger/proc/openwindow(mob/user as mob)
var/dat = "<tt><center><h1><b>TagMaster 2.2</b></h1></center>"
dat += "<table style='width:100%; padding:4px;'><tr>"
for(var/i = 1, i <= GLOB.TAGGERLOCATIONS.len, i++)
dat += "<td><a href='?src=[UID()];nextTag=[i]'>[GLOB.TAGGERLOCATIONS[i]]</a></td>"
dat += "<table style='width:100%; padding:4px;'><tr>"
for(var/i = 1, i <= GLOB.TAGGERLOCATIONS.len, i++)
dat += "<td><a href='?src=[UID()];nextTag=[i]'>[GLOB.TAGGERLOCATIONS[i]]</a></td>"
if(i%4==0)
dat += "</tr><tr>"
if(i%4==0)
dat += "</tr><tr>"
dat += "</tr></table><br>Current Selection: [currTag ? GLOB.TAGGERLOCATIONS[currTag] : "None"]</tt>"
dat += "</tr></table><br>Current Selection: [currTag ? GLOB.TAGGERLOCATIONS[currTag] : "None"]</tt>"
user << browse(dat, "window=destTagScreen;size=450x350")
onclose(user, "destTagScreen")
user << browse(dat, "window=destTagScreen;size=450x350")
onclose(user, "destTagScreen")
attack_self(mob/user as mob)
openwindow(user)
return
/obj/item/destTagger/attack_self(mob/user as mob)
openwindow(user)
return
Topic(href, href_list)
src.add_fingerprint(usr)
if(href_list["nextTag"])
var/n = text2num(href_list["nextTag"])
src.currTag = n
openwindow(usr)
/obj/item/destTagger/Topic(href, href_list)
src.add_fingerprint(usr)
if(href_list["nextTag"])
var/n = text2num(href_list["nextTag"])
src.currTag = n
openwindow(usr)
/obj/machinery/disposal/deliveryChute
name = "Delivery chute"
+1 -1
View File
@@ -8,7 +8,7 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis).
name = "Circuit Imprinter"
desc = "Manufactures circuit boards for the construction of machines."
icon_state = "circuit_imprinter"
flags = OPENCONTAINER
container_type = OPENCONTAINER
var/efficiency_coeff
+1 -1
View File
@@ -11,7 +11,7 @@ Note: Must be placed west/left of and R&D console to function.
name = "Protolathe"
desc = "Converts raw materials into useful objects."
icon_state = "protolathe"
flags = OPENCONTAINER
container_type = OPENCONTAINER
var/efficiency_coeff
@@ -8,6 +8,7 @@
icon_state = "grey slime extract"
force = 1
w_class = WEIGHT_CLASS_TINY
container_type = INJECTABLE | DRAWABLE
throwforce = 0
throw_speed = 3
throw_range = 6
+1 -1
View File
@@ -52,7 +52,7 @@
// After docking //
/atom/proc/postDock(obj/docking_port/S1)
if(smooth)
smooth_icon(src)
queue_smooth(src)
/obj/machinery/door/airlock/postDock(obj/docking_port/stationary/S1)
. = ..()
+1 -1
View File
@@ -15,5 +15,5 @@
/obj/effect/temp_visual/ripple/New()
. = ..()
smooth_icon(src)
queue_smooth(src)
animate(src, alpha=255, time=SHUTTLE_RIPPLE_TIME)
+1 -1
View File
@@ -46,7 +46,7 @@
owner.adjustToxLoss(0.1 * PROCESS_ACCURACY)
// Can't cope with toxins at all
for(var/toxin in list("toxin", "plasma", "sacid", "facid", "cyanide", "amanitin", "carpotoxin"))
for(var/toxin in GLOB.liver_toxins)
if(owner.reagents.has_reagent(toxin))
owner.adjustToxLoss(0.3 * PROCESS_ACCURACY)