Merge remote-tracking branch 'upstream/dev' into mercenary

This commit is contained in:
mwerezak
2015-02-21 13:22:51 -05:00
70 changed files with 1818 additions and 1020 deletions

View File

@@ -173,7 +173,7 @@
use_power = !use_power
if(signal.data["panic_siphon"]) //must be before if("scrubbing" thing
panic = text2num(signal.data["panic_siphon"] != null)
panic = text2num(signal.data["panic_siphon"])
if(panic)
use_power = 1
scrubbing = 0
@@ -189,8 +189,12 @@
if(signal.data["scrubbing"] != null)
scrubbing = text2num(signal.data["scrubbing"])
if(scrubbing)
panic = 0
if(signal.data["toggle_scrubbing"])
scrubbing = !scrubbing
if(scrubbing)
panic = 0
var/list/toggle = list()

View File

@@ -27,18 +27,15 @@
ninja.special_role = "Ninja"
ninja.original = ninja.current
/*if(ninjastart.len == 0)
ninja.current << "<B>\red A proper starting location for you could not be found, please report this bug!</B>"
ninja.current << "<B>\red Attempting to place at a carpspawn.</B>"*/
if(ninjastart.len == 0)
for(var/obj/effect/landmark/L in landmarks_list)
if(L.name == "carpspawn")
ninjastart.Add(L)
//Until such a time as people want to place ninja spawn points, carpspawn will do fine.
for(var/obj/effect/landmark/L in landmarks_list)
if(L.name == "carpspawn")
ninjastart.Add(L)
if(ninjastart.len == 0 && latejoin.len > 0)
ninja.current << "<B>\red No spawneable locations could be found. Defaulting to latejoin.</B>"
return 1
else if (ninjastart.len == 0)
else
ninja.current << "<B>\red No spawneable locations could be found. Aborting.</B>"
return 0

View File

@@ -195,7 +195,6 @@
if(RCON_YES)
remote_control = 1
updateDialog()
return
/obj/machinery/alarm/proc/handle_heating_cooling(var/datum/gas_mixture/environment)
@@ -468,7 +467,7 @@
frequency.post_signal(src, alert_signal)
/obj/machinery/alarm/attack_ai(mob/user)
return interact(user)
ui_interact(user)
/obj/machinery/alarm/attack_hand(mob/user)
. = ..()
@@ -477,315 +476,179 @@
return interact(user)
/obj/machinery/alarm/interact(mob/user)
user.set_machine(src)
ui_interact(user)
wires.Interact(user)
if(buildstage!=2)
return
/obj/machinery/alarm/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/custom_state = null)
var/data[0]
var/remote_connection = 0
var/remote_access = 0
if(custom_state)
var/list/state = custom_state.href_list(user)
remote_connection = state["remote_connection"] // Remote connection means we're non-adjacent/connecting from another computer
remote_access = state["remote_access"] // Remote access means we also have the privilege to alter the air alarm.
if((get_dist(src, user) > 1 ))
if (!istype(user, /mob/living/silicon))
user.machine = null
user << browse(null, "window=air_alarm")
user << browse(null, "window=AAlarmwires")
return
data["locked"] = locked && !user.isSilicon()
data["remote_connection"] = remote_connection
data["remote_access"] = remote_access
data["rcon"] = rcon_setting
data["screen"] = screen
populate_status(data)
else if (istype(user, /mob/living/silicon) && aidisabled)
user << "AI control for this Air Alarm interface has been disabled."
user << browse(null, "window=air_alarm")
return
if(!(locked && !remote_connection) || remote_access || user.isSilicon())
populate_controls(data)
if(wiresexposed && (!istype(user, /mob/living/silicon/ai)))
wires.Interact(user)
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if(!ui)
ui = new(user, src, ui_key, "air_alarm.tmpl", src.name, 625, 625, master_ui = master_ui, custom_state = custom_state)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
if(!shorted)
user << browse(return_text(user),"window=air_alarm")
onclose(user, "air_alarm")
return
/obj/machinery/alarm/proc/return_text(mob/user)
if(!(istype(user, /mob/living/silicon)) && locked)
return "<html><head><title>\The [src]</title></head><body>[return_status()]<hr>[rcon_text()]<hr><i>(Swipe ID card to unlock interface)</i></body></html>"
else
return "<html><head><title>\The [src]</title></head><body>[return_status()]<hr>[rcon_text()]<hr>[return_controls()]</body></html>"
/obj/machinery/alarm/proc/return_status()
/obj/machinery/alarm/proc/populate_status(var/data)
var/turf/location = get_turf(src)
var/datum/gas_mixture/environment = location.return_air()
var/total = environment.total_moles
var/output = "<b>Air Status:</b><br>"
if(total == 0)
output += "<font color='red'><b>Warning: Cannot obtain air sample for analysis.</b></font>"
return output
var/list/environment_data = new
data["has_environment"] = total
if(total)
var/partial_pressure = R_IDEAL_GAS_EQUATION*environment.temperature/environment.volume
output += {"
<style>
.dl0 { color: green; }
.dl1 { color: orange; }
.dl2 { color: red; font-weght: bold;}
</style>
"}
var/list/current_settings = TLV["pressure"]
var/pressure = environment.return_pressure()
var/pressure_danger = get_danger_level(pressure, current_settings)
environment_data[++environment_data.len] = list("name" = "Pressure", "value" = pressure, "unit" = "kPa", "danger_level" = pressure_danger)
data["total_danger"] = pressure_danger
var/partial_pressure = R_IDEAL_GAS_EQUATION*environment.temperature/environment.volume
current_settings = TLV["oxygen"]
var/oxygen_danger = get_danger_level(environment.gas["oxygen"]*partial_pressure, current_settings)
environment_data[++environment_data.len] = list("name" = "Oxygen", "value" = environment.gas["oxygen"] / total * 100, "unit" = "%", "danger_level" = oxygen_danger)
data["total_danger"] = max(oxygen_danger, data["total_danger"])
var/list/current_settings = TLV["pressure"]
var/environment_pressure = environment.return_pressure()
var/pressure_dangerlevel = get_danger_level(environment_pressure, current_settings)
current_settings = TLV["carbon dioxide"]
var/carbon_dioxide_danger = get_danger_level(environment.gas["carbon dioxide"]*partial_pressure, current_settings)
environment_data[++environment_data.len] = list("name" = "Carbon dioxide", "value" = environment.gas["carbon dioxide"] / total * 100, "unit" = "%", "danger_level" = carbon_dioxide_danger)
data["total_danger"] = max(carbon_dioxide_danger, data["total_danger"])
current_settings = TLV["oxygen"]
var/oxygen_dangerlevel = get_danger_level(environment.gas["oxygen"]*partial_pressure, current_settings)
var/oxygen_percent = round(environment.gas["oxygen"] / total * 100, 2)
current_settings = TLV["phoron"]
var/phoron_danger = get_danger_level(environment.gas["phoron"]*partial_pressure, current_settings)
environment_data[++environment_data.len] = list("name" = "Toxins", "value" = environment.gas["phoron"] / total * 100, "unit" = "%", "danger_level" = phoron_danger)
data["total_danger"] = max(phoron_danger, data["total_danger"])
current_settings = TLV["carbon dioxide"]
var/co2_dangerlevel = get_danger_level(environment.gas["carbon_dioxide"]*partial_pressure, current_settings)
var/co2_percent = round(environment.gas["carbon_dioxide"] / total * 100, 2)
current_settings = TLV["temperature"]
var/temperature_danger = get_danger_level(environment.temperature, current_settings)
environment_data[++environment_data.len] = list("name" = "Temperature", "value" = environment.temperature, "unit" = "K ([round(environment.temperature - T0C, 0.1)]C)", "danger_level" = temperature_danger)
data["total_danger"] = max(temperature_danger, data["total_danger"])
current_settings = TLV["phoron"]
var/phoron_dangerlevel = get_danger_level(environment.gas["phoron"]*partial_pressure, current_settings)
var/phoron_percent = round(environment.gas["phoron"] / total * 100, 2)
//current_settings = TLV["other"]
//var/other_moles = 0.0
//for(var/datum/gas/G in environment.trace_gases)
// other_moles+=G.moles
//var/other_dangerlevel = get_danger_level(other_moles*partial_pressure, current_settings)
current_settings = TLV["temperature"]
var/temperature_dangerlevel = get_danger_level(environment.temperature, current_settings)
output += {"
Pressure: <span class='dl[pressure_dangerlevel]'>[environment_pressure]</span>kPa<br>
Oxygen: <span class='dl[oxygen_dangerlevel]'>[oxygen_percent]</span>%<br>
Carbon dioxide: <span class='dl[co2_dangerlevel]'>[co2_percent]</span>%<br>
Toxins: <span class='dl[phoron_dangerlevel]'>[phoron_percent]</span>%<br>
"}
//if (other_dangerlevel==2)
// output += "Notice: <span class='dl2'>High Concentration of Unknown Particles Detected</span><br>"
//else if (other_dangerlevel==1)
// output += "Notice: <span class='dl1'>Low Concentration of Unknown Particles Detected</span><br>"
output += "Temperature: <span class='dl[temperature_dangerlevel]'>[environment.temperature]</span>K ([round(environment.temperature - T0C, 0.1)]C)<br>"
//'Local Status' should report the LOCAL status, damnit.
output += "Local Status: "
switch(max(pressure_dangerlevel,oxygen_dangerlevel,co2_dangerlevel,phoron_dangerlevel,other_dangerlevel,temperature_dangerlevel))
if(2)
output += "<span class='dl2'>DANGER: Internals Required</span><br>"
if(1)
output += "<span class='dl1'>Caution</span><br>"
if(0)
output += "<span class='dl0'>Optimal</span><br>"
output += "Area Status: "
if(alarm_area.atmosalm)
output += "<span class='dl1'>Atmos alert in area</span>"
else if (alarm_area.fire)
output += "<span class='dl1'>Fire alarm in area</span>"
else
output += "No alerts"
return output
/obj/machinery/alarm/proc/rcon_text()
var/dat = "<table width=\"100%\"><td align=\"center\"><b>Remote Control:</b><br>"
if(rcon_setting == RCON_NO)
dat += "<b>Off</b>"
else
dat += "<a href='?src=\ref[src];rcon=[RCON_NO]'>Off</a>"
dat += " | "
if(rcon_setting == RCON_AUTO)
dat += "<b>Auto</b>"
else
dat += "<a href='?src=\ref[src];rcon=[RCON_AUTO]'>Auto</a>"
dat += " | "
if(rcon_setting == RCON_YES)
dat += "<b>On</b>"
else
dat += "<a href='?src=\ref[src];rcon=[RCON_YES]'>On</a></td>"
//Hackish, I know. I didn't feel like bothering to rework all of this.
dat += "<td align=\"center\"><b>Thermostat:</b><br><a href='?src=\ref[src];temperature=1'>[target_temperature - T0C]C</a></td></table>"
return dat
/obj/machinery/alarm/proc/return_controls(var/source = src)
var/output = ""//"<B>[alarm_zone] Air [name]</B><HR>"
data["environment"] = environment_data
data["atmos_alarm"] = alarm_area.atmosalm
data["fire_alarm"] = alarm_area.fire != null
data["target_temperature"] = "[target_temperature - T0C]C"
/obj/machinery/alarm/proc/populate_controls(var/list/data)
switch(screen)
if (AALARM_SCREEN_MAIN)
if(alarm_area.atmosalm)
output += "<a href='?src=\ref[source];atmos_reset=1'>Reset - Area Atmospheric Alarm</a><hr>"
else
output += "<a href='?src=\ref[source];atmos_alarm=1'>Activate - Area Atmospheric Alarm</a><hr>"
if(AALARM_SCREEN_MAIN)
data["mode"] = mode
if(AALARM_SCREEN_VENT)
var/vents[0]
for(var/id_tag in alarm_area.air_vent_names)
var/long_name = alarm_area.air_vent_names[id_tag]
var/list/info = alarm_area.air_vent_info[id_tag]
if(!info)
continue
vents[++vents.len] = list(
"id_tag" = id_tag,
"long_name" = sanitize(long_name),
"power" = info["power"],
"checks" = info["checks"],
"direction" = info["direction"],
"external" = info["external"]
)
data["vents"] = vents
if(AALARM_SCREEN_SCRUB)
var/scrubbers[0]
for(var/id_tag in alarm_area.air_scrub_names)
var/long_name = alarm_area.air_scrub_names[id_tag]
var/list/info = alarm_area.air_scrub_info[id_tag]
if(!info)
continue
scrubbers[++scrubbers.len] = list(
"id_tag" = id_tag,
"long_name" = sanitize(long_name),
"power" = info["power"],
"scrubbing" = info["scrubbing"],
"panic" = info["panic"],
"filters" = list()
)
scrubbers[scrubbers.len]["filters"] += list(list("name" = "Oxygen", "command" = "o2_scrub", "val" = info["filter_o2"]))
scrubbers[scrubbers.len]["filters"] += list(list("name" = "Nitrogen", "command" = "n2_scrub", "val" = info["filter_n2"]))
scrubbers[scrubbers.len]["filters"] += list(list("name" = "Carbon Dioxide", "command" = "co2_scrub","val" = info["filter_co2"]))
scrubbers[scrubbers.len]["filters"] += list(list("name" = "Toxin" , "command" = "tox_scrub","val" = info["filter_phoron"]))
scrubbers[scrubbers.len]["filters"] += list(list("name" = "Nitrous Oxide", "command" = "n2o_scrub","val" = info["filter_n2o"]))
data["scrubbers"] = scrubbers
if(AALARM_SCREEN_MODE)
var/modes[0]
modes[++modes.len] = list("name" = "Filtering - Scrubs out contaminants", "mode" = AALARM_MODE_SCRUBBING, "selected" = mode == AALARM_MODE_SCRUBBING, "danger" = 0)
modes[++modes.len] = list("name" = "Replace Air - Siphons out air while replacing", "mode" = AALARM_MODE_REPLACEMENT, "selected" = mode == AALARM_MODE_REPLACEMENT, "danger" = 0)
modes[++modes.len] = list("name" = "Panic - Siphons air out of the room", "mode" = AALARM_MODE_PANIC, "selected" = mode == AALARM_MODE_PANIC, "danger" = 1)
modes[++modes.len] = list("name" = "Cycle - Siphons air before replacing", "mode" = AALARM_MODE_CYCLE, "selected" = mode == AALARM_MODE_CYCLE, "danger" = 1)
modes[++modes.len] = list("name" = "Fill - Shuts off scrubbers and opens vents", "mode" = AALARM_MODE_FILL, "selected" = mode == AALARM_MODE_FILL, "danger" = 0)
modes[++modes.len] = list("name" = "Off - Shuts off vents and scrubbers", "mode" = AALARM_MODE_OFF, "selected" = mode == AALARM_MODE_OFF, "danger" = 0)
data["modes"] = modes
data["mode"] = mode
if(AALARM_SCREEN_SENSORS)
var/list/selected
var/thresholds[0]
output += {"
<a href='?src=\ref[source];screen=[AALARM_SCREEN_SCRUB]'>Scrubbers Control</a><br>
<a href='?src=\ref[source];screen=[AALARM_SCREEN_VENT]'>Vents Control</a><br>
<a href='?src=\ref[source];screen=[AALARM_SCREEN_MODE]'>Set environmentals mode</a><br>
<a href='?src=\ref[source];screen=[AALARM_SCREEN_SENSORS]'>Sensor Settings</a><br>
<HR>
"}
if (mode==AALARM_MODE_PANIC)
output += "<font color='red'><B>PANIC SYPHON ACTIVE</B></font><br><A href='?src=\ref[source];mode=[AALARM_MODE_SCRUBBING]'>Turn syphoning off</A>"
else
output += "<A href='?src=\ref[source];mode=[AALARM_MODE_PANIC]'><font color='red'>ACTIVATE PANIC SYPHON IN AREA</font></A>"
if (AALARM_SCREEN_VENT)
var/sensor_data = ""
if(alarm_area.air_vent_names.len)
for(var/id_tag in alarm_area.air_vent_names)
var/long_name = alarm_area.air_vent_names[id_tag]
var/list/data = alarm_area.air_vent_info[id_tag]
if(!data)
continue;
var/state = ""
sensor_data += {"
<B>[long_name]</B>[state]<BR>
<B>Operating:</B>
<A href='?src=\ref[source];id_tag=[id_tag];command=power;val=[!data["power"]]'>[data["power"]?"on":"off"]</A>
<BR>
<B>Pressure checks:</B>
<A href='?src=\ref[source];id_tag=[id_tag];command=checks;val=[data["checks"]^1]' [(data["checks"]&1)?"style='font-weight:bold;'":""]>external</A>
<A href='?src=\ref[source];id_tag=[id_tag];command=checks;val=[data["checks"]^2]' [(data["checks"]&2)?"style='font-weight:bold;'":""]>internal</A>
<BR>
<B>External pressure bound:</B>
<A href='?src=\ref[source];id_tag=[id_tag];command=adjust_external_pressure;val=-1000'>-</A>
<A href='?src=\ref[source];id_tag=[id_tag];command=adjust_external_pressure;val=-100'>-</A>
<A href='?src=\ref[source];id_tag=[id_tag];command=adjust_external_pressure;val=-10'>-</A>
<A href='?src=\ref[source];id_tag=[id_tag];command=adjust_external_pressure;val=-1'>-</A>
[data["external"]]
<A href='?src=\ref[source];id_tag=[id_tag];command=adjust_external_pressure;val=+1'>+</A>
<A href='?src=\ref[source];id_tag=[id_tag];command=adjust_external_pressure;val=+10'>+</A>
<A href='?src=\ref[source];id_tag=[id_tag];command=adjust_external_pressure;val=+100'>+</A>
<A href='?src=\ref[source];id_tag=[id_tag];command=adjust_external_pressure;val=+1000'>+</A>
<A href='?src=\ref[source];id_tag=[id_tag];command=set_external_pressure;val=[ONE_ATMOSPHERE]'> (reset) </A>
<BR>
"}
if (data["direction"] == "siphon")
sensor_data += {"
<B>Direction:</B>
siphoning
<BR>
"}
sensor_data += {"<HR>"}
else
sensor_data = "No vents connected.<BR>"
output = {"<a href='?src=\ref[source];screen=[AALARM_SCREEN_MAIN]'>Main menu</a><br>[sensor_data]"}
if (AALARM_SCREEN_SCRUB)
var/sensor_data = ""
if(alarm_area.air_scrub_names.len)
for(var/id_tag in alarm_area.air_scrub_names)
var/long_name = alarm_area.air_scrub_names[id_tag]
var/list/data = alarm_area.air_scrub_info[id_tag]
if(!data)
continue;
var/state = ""
sensor_data += {"
<B>[long_name]</B>[state]<BR>
<B>Operating:</B>
<A href='?src=\ref[source];id_tag=[id_tag];command=power;val=[!data["power"]]'>[data["power"]?"on":"off"]</A><BR>
<B>Type:</B>
<A href='?src=\ref[source];id_tag=[id_tag];command=scrubbing;val=[!data["scrubbing"]]'>[data["scrubbing"]?"scrubbing":"syphoning"]</A><BR>
"}
if(data["scrubbing"])
sensor_data += {"
<B>Filtering:</B>
Oxygen
<A href='?src=\ref[source];id_tag=[id_tag];command=o2_scrub;val=[!data["filter_o2"]]'>[data["filter_o2"]?"on":"off"]</A>;
Nitrogen
<A href='?src=\ref[source];id_tag=[id_tag];command=n2_scrub;val=[!data["filter_n2"]]'>[data["filter_n2"]?"on":"off"]</A>;
Carbon Dioxide
<A href='?src=\ref[source];id_tag=[id_tag];command=co2_scrub;val=[!data["filter_co2"]]'>[data["filter_co2"]?"on":"off"]</A>;
Toxins
<A href='?src=\ref[source];id_tag=[id_tag];command=tox_scrub;val=[!data["filter_phoron"]]'>[data["filter_phoron"]?"on":"off"]</A>;
Nitrous Oxide
<A href='?src=\ref[source];id_tag=[id_tag];command=n2o_scrub;val=[!data["filter_n2o"]]'>[data["filter_n2o"]?"on":"off"]</A>
<BR>
"}
sensor_data += {"
<B>Panic syphon:</B> [data["panic"]?"<font color='red'><B>PANIC SYPHON ACTIVATED</B></font>":""]
<A href='?src=\ref[source];id_tag=[id_tag];command=panic_siphon;val=[!data["panic"]]'><font color='[(data["panic"]?"blue'>Dea":"red'>A")]ctivate</font></A><BR>
<HR>
"}
else
sensor_data = "No scrubbers connected.<BR>"
output = {"<a href='?src=\ref[source];screen=[AALARM_SCREEN_MAIN]'>Main menu</a><br>[sensor_data]"}
if (AALARM_SCREEN_MODE)
output += "<a href='?src=\ref[source];screen=[AALARM_SCREEN_MAIN]'>Main menu</a><br><b>Air machinery mode for the area:</b><ul>"
var/list/modes = list(AALARM_MODE_SCRUBBING = "Filtering - Scrubs out contaminants",\
AALARM_MODE_REPLACEMENT = "<font color='blue'>Replace Air - Siphons out air while replacing</font>",\
AALARM_MODE_PANIC = "<font color='red'>Panic - Siphons air out of the room</font>",\
AALARM_MODE_CYCLE = "<font color='red'>Cycle - Siphons air before replacing</font>",\
AALARM_MODE_FILL = "<font color='green'>Fill - Shuts off scrubbers and opens vents</font>",\
AALARM_MODE_OFF = "<font color='blue'>Off - Shuts off vents and scrubbers</font>",)
for (var/m=1,m<=modes.len,m++)
if (mode==m)
output += "<li><A href='?src=\ref[source];mode=[m]'><b>[modes[m]]</b></A> (selected)</li>"
else
output += "<li><A href='?src=\ref[source];mode=[m]'>[modes[m]]</A></li>"
output += "</ul>"
if (AALARM_SCREEN_SENSORS)
output += {"
<a href='?src=\ref[source];screen=[AALARM_SCREEN_MAIN]'>Main menu</a><br>
<b>Alarm thresholds:</b><br>
Partial pressure for gases
<style>/* some CSS woodoo here. Does not work perfect in ie6 but who cares? */
table td { border-left: 1px solid black; border-top: 1px solid black;}
table tr:first-child th { border-left: 1px solid black;}
table th:first-child { border-top: 1px solid black; font-weight: normal;}
table tr:first-child th:first-child { border: none;}
.dl0 { color: green; }
.dl1 { color: orange; }
.dl2 { color: red; font-weght: bold;}
</style>
<table cellspacing=0>
<TR><th></th><th class=dl2>min2</th><th class=dl1>min1</th><th class=dl1>max1</th><th class=dl2>max2</th></TR>
"}
var/list/gases = list(
var/list/gas_names = list(
"oxygen" = "O<sub>2</sub>",
"carbon dioxide" = "CO<sub>2</sub>",
"phoron" = "Toxin",
"other" = "Other",)
var/list/selected
for (var/g in gases)
output += "<TR><th>[gases[g]]</th>"
"other" = "Other")
for (var/g in gas_names)
thresholds[++thresholds.len] = list("name" = gas_names[g], "settings" = list())
selected = TLV[g]
for(var/i = 1, i <= 4, i++)
output += "<td><A href='?src=\ref[source];command=set_threshold;env=[g];var=[i]'>[selected[i] >= 0 ? selected[i] :"OFF"]</A></td>"
output += "</TR>"
thresholds[thresholds.len]["settings"] += list(list("env" = g, "val" = i, "selected" = selected[i]))
selected = TLV["pressure"]
output += " <TR><th>Pressure</th>"
thresholds[++thresholds.len] = list("name" = "Pressure", "settings" = list())
for(var/i = 1, i <= 4, i++)
output += "<td><A href='?src=\ref[source];command=set_threshold;env=pressure;var=[i]'>[selected[i] >= 0 ? selected[i] :"OFF"]</A></td>"
output += "</TR>"
thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = i, "selected" = selected[i]))
selected = TLV["temperature"]
output += "<TR><th>Temperature</th>"
thresholds[++thresholds.len] = list("name" = "Temperature", "settings" = list())
for(var/i = 1, i <= 4, i++)
output += "<td><A href='?src=\ref[source];command=set_threshold;env=temperature;var=[i]'>[selected[i] >= 0 ? selected[i] :"OFF"]</A></td>"
output += "</TR></table>"
thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = i, "selected" = selected[i]))
return output
/obj/machinery/alarm/Topic(href, href_list, var/nowindow = 0, var/remote = 0)
if(..(href, href_list, nowindow, !remote) || !( Adjacent(usr) || nowindow || istype(usr, /mob/living/silicon)) ) // dont forget calling super in machine Topics -walter0o
usr.machine = null
usr << browse(null, "window=air_alarm")
usr << browse(null, "window=AAlarmwires")
return
data["thresholds"] = thresholds
add_fingerprint(usr)
usr.set_machine(src)
/obj/machinery/alarm/CanUseTopic(var/mob/user, href_list, var/datum/topic_state/custom_state)
if(buildstage != 2)
return STATUS_CLOSE
if(aidisabled && user.isAI())
user << "<span class='warning'>AI control for \the [src] interface has been disabled.</span>"
return STATUS_CLOSE
. = shorted ? STATUS_DISABLED : STATUS_INTERACTIVE
if(. == STATUS_INTERACTIVE)
var/extra_href = custom_state.href_list(usr)
// Prevent remote users from altering RCON settings unless they already have access (I realize the risks)
if(href_list["rcon"] && extra_href["remote_connection"] && !extra_href["remote_access"])
. = STATUS_UPDATE
//TODO: Move the rest of if(!locked || extra_href["remote_access"] || usr.isAI()) and hrefs here
return min(..(), .)
/obj/machinery/alarm/Topic(href, href_list, var/nowindow = 0, var/datum/topic_state/custom_state)
if(..(href, href_list, nowindow, custom_state))
return 1
// hrefs that can always be called -walter0o
if(href_list["rcon"])
@@ -798,28 +661,38 @@ table tr:first-child th:first-child { border: none;}
rcon_setting = RCON_AUTO
if(RCON_YES)
rcon_setting = RCON_YES
else
return
return 1
if(href_list["temperature"])
var/list/selected = TLV["temperature"]
var/max_temperature = min(selected[3] - T0C, MAX_TEMPERATURE)
var/min_temperature = max(selected[2] - T0C, MIN_TEMPERATURE)
var/input_temperature = input("What temperature would you like the system to mantain? (Capped between [min_temperature]C and [max_temperature]C)", "Thermostat Controls") as num|null
if(!input_temperature || input_temperature > max_temperature || input_temperature < min_temperature)
usr << "Temperature must be between [min_temperature]C and [max_temperature]C"
else
target_temperature = input_temperature + T0C
var/input_temperature = input("What temperature would you like the system to mantain? (Capped between [min_temperature] and [max_temperature]C)", "Thermostat Controls", target_temperature - T0C) as num|null
if(isnum(input_temperature))
if(input_temperature > max_temperature || input_temperature < min_temperature)
usr << "Temperature must be between [min_temperature]C and [max_temperature]C"
else
target_temperature = input_temperature + T0C
return 1
// hrefs that need the AA unlocked -walter0o
if(!locked || remote || istype(usr, /mob/living/silicon))
var/extra_href = custom_state.href_list(usr)
if(!(locked && !extra_href["remote_connection"]) || extra_href["remote_access"] || usr.isSilicon())
if(href_list["command"])
var/device_id = href_list["id_tag"]
switch(href_list["command"])
if("set_external_pressure")
var/input_pressure = input("What pressure you like the system to mantain?", "Pressure Controls") as num|null
if(isnum(input_pressure))
send_signal(device_id, list(href_list["command"] = input_pressure))
return 1
if("reset_external_pressure")
send_signal(device_id, list(href_list["command"] = ONE_ATMOSPHERE))
return 1
if( "power",
"adjust_external_pressure",
"set_external_pressure",
"checks",
"o2_scrub",
"n2_scrub",
@@ -830,6 +703,7 @@ table tr:first-child th:first-child { border: none;}
"scrubbing")
send_signal(device_id, list(href_list["command"] = text2num(href_list["val"]) ) )
return 1
if("set_threshold")
var/env = href_list["env"]
@@ -838,7 +712,7 @@ table tr:first-child th:first-child { border: none;}
var/list/thresholds = list("lower bound", "low warning", "high warning", "upper bound")
var/newval = input("Enter [thresholds[threshold]] for [env]", "Alarm triggers", selected[threshold]) as null|num
if (isnull(newval))
return
return 1
if (newval<0)
selected[threshold] = -1.0
else if (env=="temperature" && newval>5000)
@@ -880,9 +754,11 @@ table tr:first-child th:first-child { border: none;}
selected[3] = selected[4]
apply_mode()
return 1
if(href_list["screen"])
screen = text2num(href_list["screen"])
return 1
if(href_list["atmos_unlock"])
switch(href_list["atmos_unlock"])
@@ -890,24 +766,24 @@ table tr:first-child th:first-child { border: none;}
alarm_area.air_doors_close()
if("1")
alarm_area.air_doors_open()
return 1
if(href_list["atmos_alarm"])
if (alarm_area.atmosalert(2))
apply_danger_level(2)
update_icon()
return 1
if(href_list["atmos_reset"])
if (alarm_area.atmosalert(0))
apply_danger_level(0)
update_icon()
return 1
if(href_list["mode"])
mode = text2num(href_list["mode"])
apply_mode()
if(!nowindow)
updateUsrDialog()
return 1
/obj/machinery/alarm/attackby(obj/item/W as obj, mob/user as mob)
src.add_fingerprint(user)
@@ -937,7 +813,6 @@ table tr:first-child th:first-child { border: none;}
if(allowed(usr) && !wires.IsIndexCut(AALARM_WIRE_IDSCAN))
locked = !locked
user << "\blue You [ locked ? "lock" : "unlock"] the Air Alarm interface."
updateUsrDialog()
else
user << "\red Access denied."
return

View File

@@ -1,6 +1,6 @@
/obj/machinery/computer/arcade
name = "arcade machine"
desc = "Does not support Pin ball."
desc = "Does not support pinball."
icon = 'icons/obj/computer.dmi'
icon_state = "arcade"
circuit = "/obj/item/weapon/circuitboard/arcade"
@@ -32,7 +32,10 @@
/obj/item/toy/prize/mauler = 1,
/obj/item/toy/prize/odysseus = 1,
/obj/item/toy/prize/phazon = 1,
/obj/item/toy/waterflower = 1
/obj/item/toy/waterflower = 1,
/obj/item/toy/figure = 1,
/obj/random/plushie = 1,
/obj/item/toy/cultsword = 1
)
/obj/machinery/computer/arcade

View File

@@ -9,11 +9,11 @@
density = 1
anchored = 1.0
circuit = "/obj/item/weapon/circuitboard/atmoscontrol"
var/obj/machinery/alarm/current
var/overridden = 0 //not set yet, can't think of a good way to do it
req_access = list(access_ce)
var/list/monitored_alarm_ids = null
var/list/monitored_alarms = null
var/ui_ref
/obj/machinery/computer/atmoscontrol/laptop
name = "Atmospherics Laptop"
@@ -32,36 +32,29 @@
monitored_alarms = dd_sortedObjectList(monitored_alarms)
/obj/machinery/computer/atmoscontrol/attack_ai(var/mob/user as mob)
return interact(user)
return ui_interact(user)
/obj/machinery/computer/atmoscontrol/attack_hand(mob/user)
if(..())
return
return interact(user)
return ui_interact(user)
/obj/machinery/computer/atmoscontrol/interact(mob/user)
user.set_machine(src)
if(allowed(user))
overridden = 1
else if(!emagged)
overridden = 0
var/dat = "<a href='?src=\ref[src]&reset=1'>Main Menu</a><hr>"
if(monitored_alarms && monitored_alarms.len == 1)
current = monitored_alarms[1]
if(current)
dat += specific()
else
for(var/obj/machinery/alarm/alarm in monitored_alarms ? monitored_alarms : machines)
dat += "<a href='?src=\ref[src]&alarm=\ref[alarm]'>"
switch(max(alarm.danger_level, alarm.alarm_area.atmosalm))
if (0)
dat += "<font color=green>"
if (1)
dat += "<font color=blue>"
if (2)
dat += "<font color=red>"
dat += "[sanitize(alarm.name)]</font></a><br/>"
user << browse(dat, "window=atmoscontrol")
/obj/machinery/computer/atmoscontrol/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
var/alarms[0]
// TODO: Move these to a cache, similar to cameras
for(var/obj/machinery/alarm/alarm in (monitored_alarms ? monitored_alarms : machines))
alarms[++alarms.len] = list("name" = sanitize(alarm.name), "ref"= "\ref[alarm]", "danger" = max(alarm.danger_level, alarm.alarm_area.atmosalm))
data["alarms"] = alarms
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if(!ui)
ui = new(user, src, ui_key, "atmos_control.tmpl", src.name, 625, 625)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
ui_ref = ui
/obj/machinery/computer/atmoscontrol/attackby(var/obj/item/I as obj, var/mob/user as mob)
if(istype(I, /obj/item/weapon/card/emag) && !emagged)
@@ -73,23 +66,33 @@
return
return ..()
/obj/machinery/computer/atmoscontrol/proc/specific()
if(!current)
return ""
var/dat = "<h3>[current.name]</h3><hr>"
dat += current.return_status()
if(current.remote_control || overridden)
dat += "<hr>[current.return_controls(src)]"
return dat
//a bunch of this is copied from atmos alarms
/obj/machinery/computer/atmoscontrol/Topic(href, href_list)
if(..())
return
if(href_list["reset"])
current = null
return 1
if(href_list["alarm"])
current = locate(href_list["alarm"])
else if(current)
current.Topic(href, href_list, 1, 1)
interact(usr)
if(ui_ref)
var/obj/machinery/alarm/alarm = locate(href_list["alarm"]) in (monitored_alarms ? monitored_alarms : machines)
if(alarm)
var/datum/topic_state/TS = generate_state(alarm)
alarm.ui_interact(usr, master_ui = ui_ref, custom_state = TS)
return 1
/obj/machinery/computer/atmoscontrol/proc/generate_state(var/alarm)
var/datum/topic_state/air_alarm/state = new()
state.atmos_control = src
state.air_alarm = alarm
return state
/datum/topic_state/air_alarm
flags = NANO_IGNORE_DISTANCE
var/obj/machinery/computer/atmoscontrol/atmos_control = null
var/obj/machinery/alarm/air_alarm = null
/datum/topic_state/air_alarm/href_list(var/mob/user)
var/list/extra_href = list()
extra_href["remote_connection"] = 1
extra_href["remote_access"] = user && (atmos_control.allowed(user) || atmos_control.emagged || air_alarm.rcon_setting == RCON_YES || (air_alarm.alarm_area.atmosalm && air_alarm.rcon_setting == RCON_AUTO))
return extra_href

View File

@@ -23,6 +23,10 @@
var/id = 1.0
dir = 1
explosion_resistance = 25
//Most blast doors are infrequently toggled and sometimes used with regular doors anyways,
//turning this off prevents awkward zone geometry in places like medbay lobby, for example.
block_air_zones = 0
// Proc: Bumped()
// Parameters: 1 (AM - Atom that tried to walk through this object)
@@ -150,6 +154,13 @@
if(stat & BROKEN)
stat &= ~BROKEN
/obj/machinery/door/blast/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(air_group) return 1
return ..()
// SUBTYPE: Regular
// Your classical blast door, found almost everywhere.
obj/machinery/door/blast/regular

View File

@@ -31,6 +31,7 @@
var/min_force = 10 //minimum amount of force needed to damage the door with a melee weapon
var/hitsound = 'sound/weapons/smash.ogg' //sound door makes when hit with a weapon
var/obj/item/stack/sheet/metal/repairing
var/block_air_zones = 1 //If set, air zones cannot merge across the door even when it is opened.
//Multi-tile doors
dir = EAST
@@ -114,7 +115,7 @@
/obj/machinery/door/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(air_group) return 0
if(air_group) return !block_air_zones
if(istype(mover) && mover.checkpass(PASSGLASS))
return !opacity
return !density

View File

@@ -22,6 +22,10 @@
open_layer = DOOR_OPEN_LAYER - 0.01 // Just below doors when open
closed_layer = DOOR_CLOSED_LAYER + 0.01 // Just above doors when closed
//These are frequenly used with windows, so make sure zones can pass.
//Generally if a firedoor is at a place where there should be a zone boundery then there will be a regular door underneath it.
block_air_zones = 0
var/blocked = 0
var/lockdown = 0 // When the door has detected a problem, it locks.
var/pdiff_alert = 0
@@ -381,9 +385,9 @@
overlays += "welded_open"
return
//These are playing merry hell on ZAS. Sorry fellas :(
/obj/machinery/door/firedoor/border_only
//These are playing merry hell on ZAS. Sorry fellas :(
/*
icon = 'icons/obj/doors/edge_Doorfire.dmi'
glass = 1 //There is a glass window so you can see through the door

View File

@@ -24,7 +24,6 @@
program.process()
update_icon()
src.updateDialog()
/obj/machinery/embedded_controller/attack_ai(mob/user as mob)
src.ui_interact(user)

View File

@@ -182,13 +182,18 @@ Class Procs:
/obj/machinery/proc/inoperable(var/additional_flags = 0)
return (stat & (NOPOWER|BROKEN|additional_flags))
/obj/machinery/CanUseTopic(var/mob/user, var/be_close)
if(!interact_offline && (stat & (NOPOWER|BROKEN)))
return STATUS_CLOSE
/obj/machinery/Topic(href, href_list, var/nowindow = 0, var/checkrange = 1)
if(..())
return 1
if(!interact_offline && stat & (NOPOWER|BROKEN))
return 1
return 0
return ..()
/obj/machinery/CouldUseTopic(var/mob/user)
..()
user.set_machine(src)
/obj/machinery/CouldNotUseTopic(var/mob/user)
usr.unset_machine()
////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -162,7 +162,7 @@
if(istype(occupant, /mob/living/silicon/robot))
var/mob/living/silicon/robot/R = occupant
if(R.module)
R.module.respawn_consumable(R)
R.module.respawn_consumable(R, charge_rate / 250)
if(!R.cell)
return
if(!R.cell.fully_charged())

View File

@@ -6,7 +6,6 @@
unacidable = 1
/obj/effect/landmark/New()
..()
tag = text("landmark*[]", name)
invisibility = 101
@@ -113,6 +112,13 @@
return 1
/obj/effect/landmark/start/ninja
name = "ninja"
/obj/effect/landmark/start/ninja/New()
..()
ninjastart += loc
//Costume spawner landmarks
/obj/effect/landmark/costume/New() //costume spawner, selects a random subclass and disappears

View File

@@ -55,7 +55,7 @@
var/uses = 0
var/emagged = 0
var/failmsg = ""
var/charge = 1
var/charge = 0
/obj/item/device/lightreplacer/New()
uses = max_uses / 2
@@ -122,11 +122,11 @@
/obj/item/device/lightreplacer/proc/AddUses(var/amount = 1)
uses = min(max(uses + amount, 0), max_uses)
/obj/item/device/lightreplacer/proc/Charge(var/mob/user)
charge += 1
if(charge > 7)
/obj/item/device/lightreplacer/proc/Charge(var/mob/user, var/amount = 1)
charge += amount
if(charge > 6)
AddUses(1)
charge = 1
charge = 0
/obj/item/device/lightreplacer/proc/ReplaceLight(var/obj/machinery/light/target, var/mob/living/U)

View File

@@ -0,0 +1,50 @@
/datum/matter_synth
var/name = "Generic Synthesizer"
var/max_energy = 60000
var/recharge_rate = 2000
var/energy
/datum/matter_synth/New(var/store = 0)
if(store)
max_energy = store
energy = max_energy
return
/datum/matter_synth/proc/get_charge()
return energy
/datum/matter_synth/proc/use_charge(var/amount)
if (energy >= amount)
energy -= amount
return 1
return 0
/datum/matter_synth/proc/add_charge(var/amount)
energy = min(energy + amount, max_energy)
/datum/matter_synth/proc/emp_act(var/severity)
use_charge(max_energy * 0.1 / severity)
/datum/matter_synth/medicine
name = "Medicine Synthesizer"
/datum/matter_synth/metal
name = "Metal Synthesizer"
/datum/matter_synth/plasteel
name = "Plasteel Synthesizer"
max_energy = 10000
/datum/matter_synth/glass
name = "Glass Synthesizer"
/datum/matter_synth/wood
name = "Wood Synthesizer"
/datum/matter_synth/plastic
name = "Plastic Synthesizer"
/datum/matter_synth/wire
name = "Wire Synthesizer"
max_energy = 50
recharge_rate = 2

View File

@@ -13,12 +13,21 @@
max_amount = 60
attack_verb = list("hit", "bludgeoned", "whacked")
/obj/item/stack/rods/cyborg
name = "metal rod synthesizer"
desc = "A device that makes metal rods."
gender = NEUTER
matter = null
uses_charge = 1
charge_costs = list(500)
stacktype = /obj/item/stack/rods
/obj/item/stack/rods/attackby(obj/item/W as obj, mob/user as mob)
..()
if (istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W
if(amount < 2)
if(get_amount() < 2)
user << "\red You need at least two rods to do this."
return
@@ -54,7 +63,7 @@
return 1
else if(!in_use)
if(amount < 2)
if(get_amount() < 2)
user << "\blue You need at least two rods to do this."
return
usr << "\blue Assembling grille..."

View File

@@ -22,12 +22,13 @@
var/list/construction_options = list("One Direction", "Full Window")
/obj/item/stack/sheet/glass/cyborg
name = "glass"
desc = "HOLY SHEET! That is a lot of glass."
singular_name = "glass sheet"
icon_state = "sheet-glass"
name = "glass synthesizer"
desc = "A device that makes glass."
gender = NEUTER
singular_name = "glass"
matter = null
created_window = /obj/structure/window/basic
uses_charge = 1
charge_costs = list(1000)
stacktype = /obj/item/stack/sheet/glass
/obj/item/stack/sheet/glass/attack_self(mob/user as mob)
@@ -69,7 +70,7 @@
if(!user.IsAdvancedToolUser())
return 0
var/title = "Sheet-[name]"
title += " ([src.amount] sheet\s left)"
title += " ([src.get_amount()] sheet\s left)"
switch(input(title, "What would you like to construct?") as null|anything in construction_options)
if("One Direction")
if(!src) return 1
@@ -102,7 +103,7 @@
if("Full Window")
if(!src) return 1
if(src.loc != user) return 1
if(src.amount < 4)
if(src.get_amount() < 4)
user << "\red You need more glass to do that."
return 1
if(locate(/obj/structure/window) in user.loc)
@@ -124,7 +125,7 @@
user << "\red There is already a windoor in that location."
return 1
if(src.amount < 5)
if(src.get_amount() < 5)
user << "\red You need more glass to do that."
return 1
@@ -151,10 +152,15 @@
construction_options = list("One Direction", "Full Window", "Windoor")
/obj/item/stack/sheet/glass/reinforced/cyborg
name = "reinforced glass"
desc = "Glass which has been reinforced with metal rods."
name = "reinforced glass synthesizer"
desc = "A device that makes reinforced glass."
gender = NEUTER
matter = null
uses_charge = 2
charge_costs = list(1000)
singular_name = "reinforced glass sheet"
icon_state = "sheet-rglass"
charge_costs = list(500, 1000)
/*
* Phoron Glass sheets

View File

@@ -137,9 +137,10 @@ obj/item/stack/sheet/mineral/iron/New()
recipes = plastic_recipes
/obj/item/stack/sheet/mineral/plastic/cyborg
name = "plastic sheets"
icon_state = "sheet-plastic"
perunit = 2000
name = "plastic sheets synthesizer"
gender = NEUTER
uses_charge = 1
charge_costs = list(1000)
stacktype = /obj/item/stack/sheet/mineral/plastic
/obj/item/stack/sheet/mineral/gold

View File

@@ -86,12 +86,12 @@ var/global/list/datum/stack_recipe/metal_recipes = list ( \
origin_tech = "materials=1"
/obj/item/stack/sheet/metal/cyborg
name = "metal"
desc = "Sheets made out off metal. It has been dubbed Metal Sheets."
singular_name = "metal sheet"
icon_state = "sheet-metal"
throwforce = 14.0
flags = CONDUCT
name = "metal synthesizer"
desc = "A device that makes metal sheets."
gender = NEUTER
matter = null
uses_charge = 1
charge_costs = list(1000)
stacktype = /obj/item/stack/sheet/metal
/obj/item/stack/sheet/metal/New(var/loc, var/amount=null)
@@ -121,9 +121,19 @@ var/global/list/datum/stack_recipe/plasteel_recipes = list ( \
flags = CONDUCT
origin_tech = "materials=2"
/obj/item/stack/sheet/plasteel/cyborg
name = "plasteel synthesizer"
desc = "A device that makes plasteel sheets."
gender = NEUTER
singular_name = "plasteel sheet"
matter = null
uses_charge = 1
charge_costs = list(1000)
stacktype = /obj/item/stack/sheet/plasteel
/obj/item/stack/sheet/plasteel/New(var/loc, var/amount=null)
recipes = plasteel_recipes
return ..()
recipes = plasteel_recipes
return ..()
/*
* Wood
@@ -149,10 +159,13 @@ var/global/list/datum/stack_recipe/wood_recipes = list ( \
origin_tech = "materials=1;biotech=1"
/obj/item/stack/sheet/wood/cyborg
name = "wooden plank"
desc = "One can only guess that this is a bunch of wood."
name = "wood synthesizer"
desc = "A device that makes wooden planks."
gender = NEUTER
singular_name = "wood plank"
icon_state = "sheet-wood"
uses_charge = 1
charge_costs = list(1000)
stacktype = /obj/item/stack/sheet/wood
/obj/item/stack/sheet/wood/New(var/loc, var/amount=null)

View File

@@ -17,6 +17,9 @@
var/amount = 1
var/max_amount //also see stack recipes initialisation, param "max_res_amount" must be equal to this max_amount
var/stacktype //determines whether different stack types can merge
var/uses_charge = 0
var/list/charge_costs = null
var/list/datum/matter_synth/synths = null
/obj/item/stack/New(var/loc, var/amount=null)
..()
@@ -27,13 +30,18 @@
return
/obj/item/stack/Del()
if(uses_charge)
return
if (src && usr && usr.machine == src)
usr << browse(null, "window=stack")
..()
/obj/item/stack/examine(mob/user)
if(..(user, 1))
user << "There are [src.amount] [src.singular_name]\s in the stack."
if(!uses_charge)
user << "There are [src.amount] [src.singular_name]\s in the stack."
else
user << "There is enough charge for [get_amount()]."
/obj/item/stack/attack_self(mob/user as mob)
list_recipes(user)
@@ -41,14 +49,14 @@
/obj/item/stack/proc/list_recipes(mob/user as mob, recipes_sublist)
if (!recipes)
return
if (!src || amount<=0)
if (!src || get_amount() <= 0)
user << browse(null, "window=stack")
user.set_machine(src) //for correct work of onclose
var/list/recipe_list = recipes
if (recipes_sublist && recipe_list[recipes_sublist] && istype(recipe_list[recipes_sublist], /datum/stack_recipe_list))
var/datum/stack_recipe_list/srl = recipe_list[recipes_sublist]
recipe_list = srl.recipes
var/t1 = text("<HTML><HEAD><title>Constructions from []</title></HEAD><body><TT>Amount Left: []<br>", src, src.amount)
var/t1 = text("<HTML><HEAD><title>Constructions from []</title></HEAD><body><TT>Amount Left: []<br>", src, src.get_amount())
for(var/i=1;i<=recipe_list.len,i++)
var/E = recipe_list[i]
if (isnull(E))
@@ -60,14 +68,14 @@
if (istype(E, /datum/stack_recipe_list))
var/datum/stack_recipe_list/srl = E
if (src.amount >= srl.req_amount)
if (src.get_amount() >= srl.req_amount)
t1 += "<a href='?src=\ref[src];sublist=[i]'>[srl.title] ([srl.req_amount] [src.singular_name]\s)</a>"
else
t1 += "[srl.title] ([srl.req_amount] [src.singular_name]\s)<br>"
if (istype(E, /datum/stack_recipe))
var/datum/stack_recipe/R = E
var/max_multiplier = round(src.amount / R.req_amount)
var/max_multiplier = round(src.get_amount() / R.req_amount)
var/title as text
var/can_build = 1
can_build = can_build && (max_multiplier>0)
@@ -142,7 +150,7 @@
list_recipes(usr, text2num(href_list["sublist"]))
if (href_list["make"])
if (src.amount < 1) del(src) //Never should happen
if (src.get_amount() < 1) del(src) //Never should happen
var/list/recipes_list = recipes
if (href_list["sublist"])
@@ -165,28 +173,44 @@
//Return 1 if an immediate subsequent call to use() would succeed.
//Ensures that code dealing with stacks uses the same logic
/obj/item/stack/proc/can_use(var/used)
if (amount < used)
if (get_amount() < used)
return 0
return 1
/obj/item/stack/proc/use(var/used)
if (!can_use(used))
return 0
amount -= used
if (amount <= 0)
spawn(0) //delete the empty stack once the current context yields
if (amount <= 0) //check again in case someone transferred stuff to us
if(usr)
usr.before_take_item(src)
del(src)
return 1
if(!uses_charge)
amount -= used
if (amount <= 0)
spawn(0) //delete the empty stack once the current context yields
if (amount <= 0) //check again in case someone transferred stuff to us
if(usr)
usr.before_take_item(src)
del(src)
return 1
else
if(get_amount() < used)
return 0
for(var/i = 1 to uses_charge)
var/datum/matter_synth/S = synths[i]
S.use_charge(charge_costs[i] * used) // Doesn't need to be deleted
return 1
return 0
/obj/item/stack/proc/add(var/extra)
if(amount + extra > max_amount)
if(!uses_charge)
if(amount + extra > get_max_amount())
return 0
else
amount += extra
return 1
else if(!synths || synths.len < uses_charge)
return 0
else
amount += extra
return 1
for(var/i = 1 to uses_charge)
var/datum/matter_synth/S = synths[i]
S.add_charge(charge_costs[i] * extra)
/*
The transfer and split procs work differently than use() and add().
@@ -196,16 +220,16 @@
//attempts to transfer amount to S, and returns the amount actually transferred
/obj/item/stack/proc/transfer_to(obj/item/stack/S, var/tamount=null)
if (!amount)
if (!get_amount())
return 0
if (stacktype != S.stacktype)
return 0
if (isnull(tamount))
tamount = src.amount
tamount = src.get_amount()
var/transfer = max(min(tamount, src.amount, (S.max_amount - S.amount)), 0)
var/transfer = max(min(tamount, src.get_amount(), (S.get_max_amount() - S.get_amount())), 0)
var/orig_amount = src.amount
var/orig_amount = src.get_amount()
if (transfer && src.use(transfer))
S.add(transfer)
if (prob(transfer/orig_amount * 100))
@@ -220,6 +244,8 @@
/obj/item/stack/proc/split(var/tamount)
if (!amount)
return null
if(uses_charge)
return null
var/transfer = max(min(tamount, src.amount, initial(max_amount)), 0)
@@ -234,8 +260,31 @@
return null
/obj/item/stack/proc/get_amount()
if(uses_charge)
if(!synths || synths.len < uses_charge)
return 0
var/datum/matter_synth/S = synths[1]
. = round(S.get_charge() / charge_costs[1])
if(uses_charge > 1)
for(var/i = 2 to uses_charge)
S = synths[i]
. = min(., round(S.get_charge() / charge_costs[i]))
return
return amount
/obj/item/stack/proc/get_max_amount()
if(uses_charge)
if(!synths || synths.len < uses_charge)
return 0
var/datum/matter_synth/S = synths[1]
. = round(S.max_energy / charge_costs[1])
if(uses_charge > 1)
for(var/i = 2 to uses_charge)
S = synths[i]
. = min(., round(S.max_energy / charge_costs[i]))
return
return max_amount
/obj/item/stack/proc/add_to_stacks(mob/usr as mob)
for (var/obj/item/stack/item in usr.loc)
if (item==src)

View File

@@ -3,14 +3,12 @@
singular_name = "floor tile"
desc = "Those could work as a pretty decent throwing weapon"
icon_state = "tile"
w_class = 3.0
force = 6.0
matter = list("metal" = 937.5)
throwforce = 15.0
throw_speed = 5
throw_range = 20
flags = CONDUCT
max_amount = 60
/obj/item/stack/tile/plasteel/New(var/loc, var/amount=null)
..()
@@ -18,6 +16,16 @@
src.pixel_y = rand(1, 14)
return
/obj/item/stack/tile/plasteel/cyborg
name = "floor tile synthesizer"
desc = "A device that makes floor tiles."
gender = NEUTER
matter = null
uses_charge = 1
charge_costs = list(250)
stacktype = /obj/item/stack/tile/plasteel
build_type = /obj/item/stack/tile/plasteel
/*
/obj/item/stack/tile/plasteel/attack_self(mob/user as mob)
if (usr.stat)

View File

@@ -1,9 +1,18 @@
/* Diffrent misc types of tiles
* Contains:
* Prototype
* Grass
* Wood
* Carpet
*/
/obj/item/stack/tile
name = "tile"
singular_name = "tile"
desc = "A non-descript floor tile"
w_class = 3
max_amount = 60
var/build_type = null
/*
* Grass
@@ -13,13 +22,11 @@
singular_name = "grass floor tile"
desc = "A patch of grass like they often use on golf courses."
icon_state = "tile_grass"
w_class = 3.0
force = 1.0
throwforce = 1.0
throw_speed = 5
throw_range = 20
flags = CONDUCT
max_amount = 60
origin_tech = "biotech=1"
/*
@@ -30,13 +37,19 @@
singular_name = "wood floor tile"
desc = "An easy to fit wooden floor tile."
icon_state = "tile-wood"
w_class = 3.0
force = 1.0
throwforce = 1.0
throw_speed = 5
throw_range = 20
flags = CONDUCT
max_amount = 60
/obj/item/stack/tile/wood/cyborg
name = "wood floor tile synthesizer"
desc = "A device that makes wood floor tiles."
uses_charge = 1
charge_costs = list(250)
stacktype = /obj/item/stack/tile/wood
build_type = /obj/item/stack/tile/wood
/*
* Carpets
@@ -46,10 +59,8 @@
singular_name = "carpet"
desc = "A piece of carpet. It is the same size as a normal floor tile!"
icon_state = "tile-carpet"
w_class = 3.0
force = 1.0
throwforce = 1.0
throw_speed = 5
throw_range = 20
flags = CONDUCT
max_amount = 60

View File

@@ -6,6 +6,7 @@
* Toy gun
* Toy crossbow
* Toy swords
* Toy bosun's whistle
* Toy mechs
* Crayons
* Snap pops
@@ -13,6 +14,9 @@
* Therapy dolls
* Toddler doll
* Inflatable duck
* Action figures
* Plushies
* Toy cult sword
*/
@@ -98,7 +102,7 @@
icon_state = "syndballoon"
item_state = "syndballoon"
w_class = 4.0
/obj/item/toy/nanotrasenballoon
name = "criminal balloon"
desc = "Across the balloon the following is printed: \"Man, I love NT soooo much. I use only NanoTrasen products. You have NO idea.\""
@@ -498,6 +502,22 @@
if(..(user, 0))
user << text("\icon[] [] units of water left!", src, src.reagents.total_volume)
/*
* Bosun's whistle
*/
/obj/item/toy/bosunwhistle
name = "bosun's whistle"
desc = "A genuine Admiral Krush Bosun's Whistle, for the aspiring ship's captain! Suitable for ages 8 and up, do not swallow."
icon = 'icons/obj/toy.dmi'
icon_state = "bosunwhistle"
var/cooldown = 0
/obj/item/toy/bosunwhistle/attack_self(mob/user as mob)
if(cooldown < world.time - 35)
user << "<span class='notice'>You blow on [src], creating an ear-splitting noise!</span>"
playsound(user, 'sound/misc/boatswain.ogg', 20, 1)
cooldown = world.time
/*
* Mech prizes
@@ -542,7 +562,6 @@
desc = "Mini-Mecha action figure! Collect them all! 4/11."
icon_state = "gygaxtoy"
/obj/item/toy/prize/durand
name = "toy durand"
desc = "Mini-Mecha action figure! Collect them all! 5/11."
@@ -578,6 +597,206 @@
desc = "Mini-Mecha action figure! Collect them all! 11/11."
icon_state = "phazonprize"
/*
* Action figures
*/
/obj/item/toy/figure
name = "Completely Glitched action figure"
desc = "A \"Space Life\" brand... wait, what the hell is this thing? It seems to be requesting the sweet release of death."
icon_state = "assistant"
icon = 'icons/obj/toy.dmi'
/obj/item/toy/figure/cmo
name = "Chief Medical Officer action figure"
desc = "A \"Space Life\" brand Chief Medical Officer action figure."
icon_state = "cmo"
/obj/item/toy/figure/assistant
name = "Assistant action figure"
desc = "A \"Space Life\" brand Assistant action figure."
icon_state = "assistant"
/obj/item/toy/figure/atmos
name = "Atmospheric Technician action figure"
desc = "A \"Space Life\" brand Atmospheric Technician action figure."
icon_state = "atmos"
/obj/item/toy/figure/bartender
name = "Bartender action figure"
desc = "A \"Space Life\" brand Bartender action figure."
icon_state = "bartender"
/obj/item/toy/figure/borg
name = "Cyborg action figure"
desc = "A \"Space Life\" brand Cyborg action figure."
icon_state = "borg"
/obj/item/toy/figure/gardener
name = "Gardener action figure"
desc = "A \"Space Life\" brand Gardener action figure."
icon_state = "botanist"
/obj/item/toy/figure/captain
name = "Captain action figure"
desc = "A \"Space Life\" brand Captain action figure."
icon_state = "captain"
/obj/item/toy/figure/cargotech
name = "Cargo Technician action figure"
desc = "A \"Space Life\" brand Cargo Technician action figure."
icon_state = "cargotech"
/obj/item/toy/figure/ce
name = "Chief Engineer action figure"
desc = "A \"Space Life\" brand Chief Engineer action figure."
icon_state = "ce"
/obj/item/toy/figure/chaplain
name = "Chaplain action figure"
desc = "A \"Space Life\" brand Chaplain action figure."
icon_state = "chaplain"
/obj/item/toy/figure/chef
name = "Chef action figure"
desc = "A \"Space Life\" brand Chef action figure."
icon_state = "chef"
/obj/item/toy/figure/chemist
name = "Chemist action figure"
desc = "A \"Space Life\" brand Chemist action figure."
icon_state = "chemist"
/obj/item/toy/figure/clown
name = "Clown action figure"
desc = "A \"Space Life\" brand Clown action figure."
icon_state = "clown"
/obj/item/toy/figure/corgi
name = "Corgi action figure"
desc = "A \"Space Life\" brand Corgi action figure."
icon_state = "ian"
/obj/item/toy/figure/detective
name = "Detective action figure"
desc = "A \"Space Life\" brand Detective action figure."
icon_state = "detective"
/obj/item/toy/figure/dsquad
name = "Space Commando action figure"
desc = "A \"Space Life\" brand Space Commando action figure."
icon_state = "dsquad"
/obj/item/toy/figure/engineer
name = "Engineer action figure"
desc = "A \"Space Life\" brand Engineer action figure."
icon_state = "engineer"
/obj/item/toy/figure/geneticist
name = "Geneticist action figure"
desc = "A \"Space Life\" brand Geneticist action figure, which was recently dicontinued."
icon_state = "geneticist"
/obj/item/toy/figure/hop
name = "Head of Personel action figure"
desc = "A \"Space Life\" brand Head of Personel action figure."
icon_state = "hop"
/obj/item/toy/figure/hos
name = "Head of Security action figure"
desc = "A \"Space Life\" brand Head of Security action figure."
icon_state = "hos"
/obj/item/toy/figure/qm
name = "Quartermaster action figure"
desc = "A \"Space Life\" brand Quartermaster action figure."
icon_state = "qm"
/obj/item/toy/figure/janitor
name = "Janitor action figure"
desc = "A \"Space Life\" brand Janitor action figure."
icon_state = "janitor"
/obj/item/toy/figure/agent
name = "Internal Affairs Agent action figure"
desc = "A \"Space Life\" brand Internal Affairs Agent action figure."
icon_state = "agent"
/obj/item/toy/figure/librarian
name = "Librarian action figure"
desc = "A \"Space Life\" brand Librarian action figure."
icon_state = "librarian"
/obj/item/toy/figure/md
name = "Medical Doctor action figure"
desc = "A \"Space Life\" brand Medical Doctor action figure."
icon_state = "md"
/obj/item/toy/figure/mime
name = "Mime action figure"
desc = "A \"Space Life\" brand Mime action figure."
icon_state = "mime"
/obj/item/toy/figure/miner
name = "Shaft Miner action figure"
desc = "A \"Space Life\" brand Shaft Miner action figure."
icon_state = "miner"
/obj/item/toy/figure/ninja
name = "Space Ninja action figure"
desc = "A \"Space Life\" brand Space Ninja action figure."
icon_state = "ninja"
/obj/item/toy/figure/wizard
name = "Wizard action figure"
desc = "A \"Space Life\" brand Wizard action figure."
icon_state = "wizard"
/obj/item/toy/figure/rd
name = "Research Director action figure"
desc = "A \"Space Life\" brand Research Director action figure."
icon_state = "rd"
/obj/item/toy/figure/roboticist
name = "Roboticist action figure"
desc = "A \"Space Life\" brand Roboticist action figure."
icon_state = "roboticist"
/obj/item/toy/figure/scientist
name = "Scientist action figure"
desc = "A \"Space Life\" brand Scientist action figure."
icon_state = "scientist"
/obj/item/toy/figure/syndie
name = "Doom Operative action figure"
desc = "A \"Space Life\" brand Doom Operative action figure."
icon_state = "syndie"
/obj/item/toy/figure/secofficer
name = "Security Officer action figure"
desc = "A \"Space Life\" brand Security Officer action figure."
icon_state = "secofficer"
/obj/item/toy/figure/warden
name = "Warden action figure"
desc = "A \"Space Life\" brand Warden action figure."
icon_state = "warden"
/obj/item/toy/figure/psychologist
name = "Psychologist action figure"
desc = "A \"Space Life\" brand Psychologist action figure."
icon_state = "psychologist"
/obj/item/toy/figure/paramedic
name = "Paramedic action figure"
desc = "A \"Space Life\" brand Paramedic action figure."
icon_state = "paramedic"
/obj/item/toy/figure/ert
name = "Emergency Response Team Commander action figure"
desc = "A \"Space Life\" brand Emergency Response Team Commander action figure."
icon_state = "ert"
/obj/item/toy/katana
name = "replica katana"
desc = "Woefully underpowered in D20."
@@ -639,6 +858,106 @@
item_state = "egg3" // It's the green egg in items_left/righthand
w_class = 1
/*
* Plushies
*/
//Large plushies.
/obj/structure/plushie
name = "generic plush"
desc = "A very generic plushie. It seems to not want to exist."
icon = 'icons/obj/toy.dmi'
icon_state = "ianplushie"
anchored = 0
density = 1
var/phrase = "I don't want to exist anymore!"
/obj/structure/plushie/attack_hand(mob/user)
if(user.a_intent == "help")
user.visible_message("<span class='notice'><b>[user]</b> hugs [src]!</span>","<span class='notice'>You hug [src]!</span>")
else if (user.a_intent == "hurt")
user.visible_message("<span class='warning'><b>[user]</b> punches [src]!</span>","<span class='warning'>You punch [src]!</span>")
else if (user.a_intent == "grab")
user.visible_message("<span class='warning'><b>[user]</b> attempts to strangle [src]!</span>","<span class='warning'>You attempt to strangle [src]!</span>")
else
user.visible_message("<span class='notice'><b>[user]</b> pokes the [src].</span>","<span class='notice'>You poke the [src].</span>")
visible_message("[src] says, \"[phrase]\"")
/obj/structure/plushie/ian
name = "plush corgi"
desc = "A plushie of an adorable corgi! Don't you just want to hug it and squeeze it and call it \"Ian\"?"
icon_state = "ianplushie"
phrase = "Arf!"
/obj/structure/plushie/drone
name = "plush drone"
desc = "A plushie of a happy drone! It appears to be smiling, and has a small tag which reads \"N.D.V. Icarus Gift Shop\"."
icon_state = "droneplushie"
phrase = "Beep boop!"
/obj/structure/plushie/carp
name = "plush carp"
desc = "A plushie of an elated carp! Straight from the wilds of the Nyx frontier, now right here in your hands."
icon_state = "carpplushie"
phrase = "Glorf!"
/obj/structure/plushie/beepsky
name = "plush Officer Sweepsky"
desc = "A plushie of a popular industrious cleaning robot! If it could feel emotions, it would love you."
icon_state = "beepskyplushie"
phrase = "Ping!"
//Small plushies.
/obj/item/toy/plushie
name = "generic small plush"
desc = "A very generic small plushie. It seems to not want to exist."
icon = 'icons/obj/toy.dmi'
icon_state = "nymphplushie"
/obj/item/toy/plushie/attack_self(mob/user as mob)
if(user.a_intent == "help")
user.visible_message("<span class='notice'><b>[user]</b> hugs [src]!</span>","<span class='notice'>You hug [src]!</span>")
else if (user.a_intent == "hurt")
user.visible_message("<span class='warning'><b>[user]</b> punches [src]!</span>","<span class='warning'>You punch [src]!</span>")
else if (user.a_intent == "grab")
user.visible_message("<span class='warning'><b>[user]</b> attempts to strangle [src]!</span>","<span class='warning'>You attempt to strangle [src]!</span>")
else
user.visible_message("<span class='notice'><b>[user]</b> pokes the [src].</span>","<span class='notice'>You poke the [src].</span>")
/obj/item/toy/plushie/nymph
name = "diona nymph plush"
desc = "A plushie of an adorable diona nymph! While its level of self-awareness is still being debated, its level of cuteness is not."
icon_state = "nymphplushie"
/obj/item/toy/plushie/mouse
name = "mouse plush"
desc = "A plushie of a delightful mouse! What was once considered a vile rodent is now your very best friend."
icon_state = "mouseplushie"
/obj/item/toy/plushie/kitten
name = "kitten plush"
desc = "A plushie of a cute kitten! Watch as it purrs it's way right into your heart."
icon_state = "kittenplushie"
/obj/item/toy/plushie/lizard
name = "lizard plush"
desc = "A plushie of a scaly lizard! Very controversial, after being accused as \"racist\" by some Unathi."
icon_state = "lizardplushie"
/obj/item/toy/plushie/spider
name = "spider plush"
desc = "A plushie of a fuzzy spider! It has eight legs - all the better to hug you with."
icon_state = "spiderplushie"
//Toy cult sword
/obj/item/toy/cultsword
name = "foam sword"
desc = "An arcane weapon (made of foam) wielded by the followers of the hit Saturday morning cartoon \"King Nursee and the Acolytes of Heroism\"."
icon = 'icons/obj/weapons.dmi'
icon_state = "cultblade"
item_state = "cultblade"
w_class = 4
attack_verb = list("attacked", "slashed", "stabbed", "poked")
/* NYET.
/obj/item/weapon/toddler

View File

@@ -118,7 +118,6 @@ CIGARETTE PACKETS ARE IN FANCY.DM
reagents.reaction(C)
else // else just remove some of the reagents
reagents.remove_any(REAGENTS_METABOLISM)
return
/obj/item/clothing/mask/smokable/proc/light(var/flavor_text = "[usr] lights the [name].")
if(!src.lit)
@@ -304,6 +303,10 @@ CIGARETTE PACKETS ARE IN FANCY.DM
/obj/item/clothing/mask/smokable/cigarette/cigar/attackby(obj/item/weapon/W as obj, mob/user as mob)
..()
user.update_inv_wear_mask(0)
user.update_inv_l_hand(0)
user.update_inv_r_hand(1)
/////////////////
//SMOKING PIPES//
/////////////////
@@ -376,6 +379,23 @@ CIGARETTE PACKETS ARE IN FANCY.DM
name = "[G.name]-packed [initial(name)]"
del(G)
else if(istype(W, /obj/item/weapon/flame/lighter))
var/obj/item/weapon/flame/lighter/L = W
if(L.lit)
light("<span class='notice'>[user] manages to light their [name] with [W].</span>")
else if(istype(W, /obj/item/weapon/flame/match))
var/obj/item/weapon/flame/match/M = W
if(M.lit)
light("<span class='notice'>[user] lights their [name] with their [W].</span>")
else if(istype(W, /obj/item/device/assembly/igniter))
light("<span class='notice'>[user] fiddles with [W], and manages to light their [name] with the power of science.</span>")
user.update_inv_wear_mask(0)
user.update_inv_l_hand(0)
user.update_inv_r_hand(1)
/obj/item/clothing/mask/smokable/pipe/cobpipe
name = "corn cob pipe"
desc = "A nicotine delivery system popularized by folksy backwoodsmen, kept popular in the modern age and beyond by space hipsters."

View File

@@ -71,6 +71,7 @@
name = "purple comb"
desc = "A pristine purple comb made from flexible plastic."
w_class = 1.0
icon = 'icons/obj/items.dmi'
icon_state = "purplecomb"
item_state = "purplecomb"

View File

@@ -16,15 +16,30 @@
var/damtype = "brute"
var/force = 0
/obj/Topic(href, href_list, var/nowindow = 0, var/checkrange = 1)
/obj/Topic(href, href_list, var/nowindow = 0, var/datum/topic_state/custom_state)
// Calling Topic without a corresponding window open causes runtime errors
if(!nowindow && ..())
return 1
if(usr.can_interact_with_interface(nano_host(), checkrange) != STATUS_INTERACTIVE)
return 1
add_fingerprint(usr)
return 0
if(!custom_state)
custom_state = default_state
// In the far future no checks are made in an overriding Topic() beyond if(..()) return
// Instead any such checks are made in CanUseTopic()
var/obj/host = nano_host()
if(host.CanUseTopic(usr, href_list, custom_state) == STATUS_INTERACTIVE)
CouldUseTopic(usr)
return 0
CouldNotUseTopic(usr)
return 1
/obj/proc/CouldUseTopic(var/mob/user)
var/atom/host = nano_host()
host.add_fingerprint(user)
/obj/proc/CouldNotUseTopic(var/mob/user)
// Nada
/obj/item/proc/is_used_on(obj/O, mob/user)

View File

@@ -225,4 +225,18 @@
prob(2);/obj/item/clothing/suit/storage/vest/heavy/hos,\
prob(2);/obj/item/clothing/suit/storage/vest/heavy/pcrc)
/obj/random/plushie
name = "random plushie"
desc = "This is a random plushie."
icon = 'icons/obj/toy.dmi'
icon_state = "nymphplushie"
item_to_spawn()
return pick(/obj/structure/plushie/ian,\
/obj/structure/plushie/drone,\
/obj/structure/plushie/carp,\
/obj/structure/plushie/beepsky,\
/obj/item/toy/plushie/nymph,\
/obj/item/toy/plushie/mouse,\
/obj/item/toy/plushie/kitten,\
/obj/item/toy/plushie/lizard)

View File

@@ -519,7 +519,10 @@ turf/simulated/floor/proc/update_icon()
var/obj/item/stack/tile/T = C
if (T.get_amount() < 1)
return
floor_type = T.type
if(!T.build_type)
floor_type = T.type
else
floor_type = T.build_type
intact = 1
if(istype(T,/obj/item/stack/tile/light))
var/obj/item/stack/tile/light/L = T

View File

@@ -3,11 +3,13 @@
set desc = "Fires a laser bolt at your position. You should only do this as a(n) (a)ghost"
set category = "Fun"
var/turf/target = get_turf(src.mob)
admin_log_and_message_admins("has fired the Icarus point defense laser at [target.x]-[target.y]-[target.z]")
if(!src.holder)
src << "Only administrators may use this command."
return
Icarus_FireLaser(get_turf(src.mob))
Icarus_FireLaser(target)
/client/proc/FireCannons()
@@ -15,11 +17,13 @@
set desc = "Fires an explosive missile at your position. You should only do this as a(n) (a)ghost."
set category = "Fun"
var/turf/target = get_turf(src.mob)
admin_log_and_message_admins("has fired the Icarus main gun projectile at [target.x]-[target.y]-[target.z]")
if(!src.holder)
src << "Only administrators may use this command."
return
Icarus_FireCannon(get_turf(src.mob))
Icarus_FireCannon(target)
/client/proc/ChangeIcarusPosition()
@@ -27,6 +31,7 @@
set desc = "Lets you chose the position of the Icarus in regards to the map."
set category = "Fun"
admin_log_and_message_admins("is changing the Icarus position.")
if(!src.holder)
src << "Only administrators may use this command."
return
@@ -122,4 +127,4 @@ proc/Icarus_SetPosition(var/user)
if(!direction)
return
icarus_position = directions[direction]
icarus_position = directions[direction]

View File

@@ -191,9 +191,11 @@
if(isnull(species) || !(species in playable_species))
species = "Human"
if(isnum(underwear))
var/list/undies = gender == MALE ? underwear_m : underwear_f
underwear = undies[undies[underwear]]
if(isnum(undershirt))
undershirt = undershirt_t[undershirt_t[undershirt]]
@@ -219,8 +221,6 @@
r_eyes = sanitize_integer(r_eyes, 0, 255, initial(r_eyes))
g_eyes = sanitize_integer(g_eyes, 0, 255, initial(g_eyes))
b_eyes = sanitize_integer(b_eyes, 0, 255, initial(b_eyes))
underwear = sanitize_integer(underwear, 1, underwear_m.len, initial(underwear))
undershirt = sanitize_integer(undershirt, 1, undershirt_t.len, initial(undershirt))
backbag = sanitize_integer(backbag, 1, backbaglist.len, initial(backbag))
b_type = sanitize_text(b_type, initial(b_type))

View File

@@ -208,6 +208,7 @@
return 1
//Attemps to remove an object on a mob. Will not move it to another area or such, just removes from the mob.
//It does call u_equip() though. So it can drop items to the floor but only if src is human.
/mob/proc/remove_from_mob(var/obj/O)
src.u_equip(O)
if (src.client)
@@ -242,16 +243,7 @@
/** BS12's proc to get the item in the active hand. Couldn't find the /tg/ equivalent. **/
/mob/proc/equipped()
if(issilicon(src))
if(isrobot(src))
if(src:module_active)
return src:module_active
else
if (hand)
return l_hand
else
return r_hand
return
return get_active_hand() //TODO: get rid of this proc
/mob/living/carbon/human/proc/equip_if_possible(obj/item/W, slot, del_on_fail = 1) // since byond doesn't seem to have pointers, this seems like the best way to do this :/
//warning: icky code

View File

@@ -116,6 +116,7 @@
if(src.grabbed_by.len || src.buckled || !src.canmove || src==H)
accurate = 1 // certain circumstances make it impossible for us to evade punches
rand_damage = 5
// Process evasion and blocking
var/miss_type = 0

View File

@@ -38,9 +38,9 @@ emp_act
return -1 // complete projectile permutation
//Shrapnel
if (P.can_embed())
if(P.can_embed())
var/armor = getarmor_organ(organ, "bullet")
if(P.embed && prob(20 + max(P.damage - armor, -10)))
if(prob(20 + max(P.damage - armor, -10)))
var/obj/item/weapon/shard/shrapnel/SP = new()
SP.name = (P.name != "shrapnel")? "[P.name] shrapnel" : "shrapnel"
SP.desc = "[SP.desc] It looks like it was fired from [P.shot_from]."

View File

@@ -771,13 +771,7 @@ It can still be worn/put on as normal.
if(slot_to_process)
if(strip_item) //Stripping an item from the mob
var/obj/item/W = strip_item
target.u_equip(W)
if (target.client)
target.client.screen -= W
if (W)
W.loc = target.loc
W.layer = initial(W.layer)
W.dropped(target)
target.remove_from_mob(W)
W.add_fingerprint(source)
if(slot_to_process == slot_l_store) //pockets! Needs to process the other one too. Snowflake code, wooo! It's not like anyone will rewrite this anytime soon. If I'm wrong then... CONGRATULATIONS! ;)
if(target.r_store)

View File

@@ -64,7 +64,7 @@
target.apply_effects(stutter = attack_damage * 2, agony = attack_damage* 3, blocked = armour)
if("l_leg", "l_foot", "r_leg", "r_foot")
if(!target.lying)
target.visible_message("<span class='warning'>[src] gives way slightly.</span>")
target.visible_message("<span class='warning'>[target] gives way slightly.</span>")
target.apply_effect(attack_damage*3, AGONY, armour)
else if(attack_damage >= 5 && !(target == user) && (stun_chance + attack_damage * 5 >= 100) && armour < 2) // Chance to get the usual throwdown as well (25% standard chance)
if(!target.lying)
@@ -118,22 +118,28 @@
user.visible_message("<span class='danger'>[user] slapped [target] across \his cheek!</span>")
if(3 to 4)
user.visible_message(pick(
80; "<span class='danger'>[user] [pick(attack_verb)] [target] in the head!</span>", //striking someone with a 'closed fist' is called punching them.
20; "<span class='danger'>[user] struck [target] in the head[pick("", " with a closed fist")]!</span>"
40; "<span class='danger'>[user] [pick(attack_verb)] [target] in the head!</span>",
30; "<span class='danger'>[user] struck [target] in the head[pick("", " with a closed fist")]!</span>",
30; "<span class='danger'>[user] threw a hook against [target]'s head!</span>"
))
if(5)
user.visible_message(pick(
10; "<span class='danger'>[user] gave [target] a resounding slap to the face!</span>",
90; "<span class='danger'>[user] smashed \his [pick(attack_noun)] into [target]'s [organ]!</span>"
30; "<span class='danger'>[user] gave [target] a resounding [pick("slap", "punch")] to the face!</span>",
40; "<span class='danger'>[user] smashed \his [pick(attack_noun)] into [target]'s face!</span>",
30; "<span class='danger'>[user] gave a strong blow against [target]'s jaw!</span>"
))
else
// ----- BODY ----- //
switch(attack_damage)
if(1 to 2) user.visible_message("<span class='danger'>[user] slapped [target]'s [organ]!</span>")
if(3 to 4) user.visible_message("<span class='danger'>[user] [pick(attack_verb)] [target] in \his [organ]!</span>")
if(5) user.visible_message("<span class='danger'>[user] smashed \his [pick(attack_noun)] into [target]'s [organ]!</span>")
if(1 to 2) user.visible_message("<span class='danger'>[user] threw a glancing punch at [target]'s [organ]!</span>")
if(1 to 4) user.visible_message("<span class='danger'>[user] [pick(attack_verb)] [target] in \his [organ]!</span>")
if(5)
user.visible_message(pick(
50; "<span class='danger'>[user] smashed \his [pick(attack_noun)] into [target]'s [organ]!</span>",
50; "<span class='danger'>[user] landed a striking [pick(attack_noun)] on [target]'s [organ]!</span>"
))
else
user.visible_message("<span class='danger'>[user] [pick("punched", "threw a punch", "struck", "slapped", "slammed their [pick(attack_noun)] into")] [target]'s [organ]!</span>") //why do we have a separate set of verbs for lying targets?
user.visible_message("<span class='danger'>[user] [pick("punched", "threw a punch against", "struck", "slammed their [pick(attack_noun)] into")] [target]'s [organ]!</span>") //why do we have a separate set of verbs for lying targets?
/datum/unarmed_attack/kick
attack_verb = list("kicked", "kicked", "kicked", "kneed")
@@ -177,7 +183,7 @@
/datum/unarmed_attack/stomp
attack_verb = null
attack_noun = list("kick")
attack_noun = list("stomp")
attack_sound = "swing_hit"
damage = 0
@@ -189,7 +195,7 @@
if(!istype(target))
return 0
if (!user.lying && (target.lying || zone in list("l_foot", "r_foot")))
if (!user.lying && (target.lying || (zone in list("l_foot", "r_foot"))))
if(target.grabbed_by == user && target.lying)
return 0
var/datum/organ/external/E = user.organs_by_name["l_foot"]
@@ -214,6 +220,5 @@
attack_damage = Clamp(attack_damage, 1, 5)
switch(attack_damage)
if(1 to 2) user.visible_message("<span class='danger'>[user] [pick("stepped on", "treaded on")] [target]'s [organ]!</span>") //stepped on conveys the same meaning and is more recognizable as an actual word than "clomped"
if(3 to 4) user.visible_message("<span class='danger'>[pick("[user] stomped on", "[user] slammed \his [shoes ? copytext(shoes.name, 1, -1) : "foot"] down onto")] [target]'s [organ]!</span>")
if(1 to 4) user.visible_message("<span class='danger'>[pick("[user] stomped on", "[user] slammed \his [shoes ? copytext(shoes.name, 1, -1) : "foot"] down onto")] [target]'s [organ]!</span>")
if(5) user.visible_message("<span class='danger'>[pick("[user] landed a powerful stomp on", "[user] stomped down hard on", "[user] slammed \his [shoes ? copytext(shoes.name, 1, -1) : "foot"] down hard onto")] [target]'s [organ]!</span>") //Devastated lol. No. We want to say that the stomp was powerful or forceful, not that it /wrought devastation/

View File

@@ -107,28 +107,29 @@ Please contact me on #coderbus IRC. ~Carn x
//Human Overlays Indexes/////////
#define MUTATIONS_LAYER 1
#define DAMAGE_LAYER 2
#define UNIFORM_LAYER 3
#define TAIL_LAYER 4 //bs12 specific. this hack is probably gonna come back to haunt me
#define ID_LAYER 5
#define SHOES_LAYER 6
#define GLOVES_LAYER 7
#define SUIT_LAYER 8
#define GLASSES_LAYER 9
#define BELT_LAYER 10 //Possible make this an overlay of somethign required to wear a belt?
#define SUIT_STORE_LAYER 11
#define BACK_LAYER 12
#define HAIR_LAYER 13 //TODO: make part of head layer?
#define EARS_LAYER 14
#define FACEMASK_LAYER 15
#define HEAD_LAYER 16
#define COLLAR_LAYER 17
#define HANDCUFF_LAYER 18
#define LEGCUFF_LAYER 19
#define L_HAND_LAYER 20
#define R_HAND_LAYER 21
#define FIRE_LAYER 22 //If you're on fire
#define TARGETED_LAYER 23 //BS12: Layer for the target overlay from weapon targeting system
#define TOTAL_LAYERS 23
#define SURGERY_LEVEL 3 //bs12 specific.
#define UNIFORM_LAYER 4
#define TAIL_LAYER 5 //bs12 specific. this hack is probably gonna come back to haunt me
#define ID_LAYER 6
#define SHOES_LAYER 7
#define GLOVES_LAYER 8
#define SUIT_LAYER 9
#define GLASSES_LAYER 10
#define BELT_LAYER 11 //Possible make this an overlay of somethign required to wear a belt?
#define SUIT_STORE_LAYER 12
#define BACK_LAYER 13
#define HAIR_LAYER 14 //TODO: make part of head layer?
#define EARS_LAYER 15
#define FACEMASK_LAYER 16
#define HEAD_LAYER 17
#define COLLAR_LAYER 18
#define HANDCUFF_LAYER 19
#define LEGCUFF_LAYER 20
#define L_HAND_LAYER 21
#define R_HAND_LAYER 22
#define FIRE_LAYER 23 //If you're on fire
#define TARGETED_LAYER 24 //BS12: Layer for the target overlay from weapon targeting system
#define TOTAL_LAYERS 24
//////////////////////////////////
/mob/living/carbon/human
@@ -509,6 +510,7 @@ proc/get_damage_icon_part(damage_state, body_part)
update_inv_legcuffed(0)
update_inv_pockets(0)
update_fire(0)
update_surgery(0)
UpdateDamageIcon()
update_icons()
//Hud Stuff
@@ -547,16 +549,9 @@ proc/get_damage_icon_part(damage_state, body_part)
overlays_standing[UNIFORM_LAYER] = null
// This really, really seems like it should not be mixed in the middle of display code...
// Automatically drop anything in store / id / belt if you're not wearing a uniform. //CHECK IF NECESARRY
for( var/obj/item/thing in list(r_store, l_store, wear_id, belt) ) //
if(thing) //
u_equip(thing) //
if (client) //
client.screen -= thing //
//
if (thing) //
thing.loc = loc //
thing.dropped(src) //
thing.layer = initial(thing.layer)
for( var/obj/item/thing in list(r_store, l_store, wear_id, belt) )
if(thing)
remove_from_mob(thing)
if(update_icons) update_icons()
/mob/living/carbon/human/update_inv_wear_id(var/update_icons=1)
@@ -929,6 +924,16 @@ proc/get_damage_icon_part(damage_state, body_part)
if(update_icons) update_icons()
/mob/living/carbon/human/proc/update_surgery(var/update_icons=1)
overlays_standing[SURGERY_LEVEL] = null
var/image/total = new
for(var/datum/organ/external/E in organs)
if(E.open)
var/image/I = image("icon"='icons/mob/surgery.dmi', "icon_state"="[E.name][round(E.open)]", "layer"=-SURGERY_LEVEL)
total.overlays += I
overlays_standing[SURGERY_LEVEL] = total
if(update_icons) update_icons()
// Used mostly for creating head items
/mob/living/carbon/human/proc/generate_head_icon()
//gender no longer matters for the mouth, although there should probably be seperate base head icons.
@@ -967,6 +972,7 @@ proc/get_damage_icon_part(damage_state, body_part)
//Human Overlays Indexes/////////
#undef MUTATIONS_LAYER
#undef DAMAGE_LAYER
#undef SURGERY_LEVEL
#undef UNIFORM_LAYER
#undef TAIL_LAYER
#undef ID_LAYER

View File

@@ -16,8 +16,8 @@
if(stat == DEAD || paralysis || weakened || stunned || restrained())
return
if (layer != TURF_LAYER+0.2)
layer = TURF_LAYER+0.2
if (layer != 2.45)
layer = 2.45 //Just above cables with their 2.44
src << text("\blue You are now hiding.")
else
layer = MOB_LAYER

View File

@@ -23,14 +23,6 @@
integrated_light_power = 2
local_transmit = 1
// We need to keep track of a few module items so we don't need to do list operations
// every time we need them. These get set in New() after the module is chosen.
var/obj/item/stack/sheet/metal/cyborg/stack_metal = null
var/obj/item/stack/sheet/wood/cyborg/stack_wood = null
var/obj/item/stack/sheet/glass/cyborg/stack_glass = null
var/obj/item/stack/sheet/mineral/plastic/cyborg/stack_plastic = null
var/obj/item/weapon/matter_decompiler/decompiler = null
//Used for self-mailing.
var/mail_destination = ""
@@ -63,15 +55,6 @@
verbs -= /mob/living/silicon/robot/verb/Namepick
module = new /obj/item/weapon/robot_module/drone(src)
//Grab stacks.
stack_metal = locate(/obj/item/stack/sheet/metal/cyborg) in src.module
stack_wood = locate(/obj/item/stack/sheet/wood/cyborg) in src.module
stack_glass = locate(/obj/item/stack/sheet/glass/cyborg) in src.module
stack_plastic = locate(/obj/item/stack/sheet/mineral/plastic/cyborg) in src.module
//Grab decompiler.
decompiler = locate(/obj/item/weapon/matter_decompiler) in src.module
//Some tidying-up.
flavor_text = "It's a tiny little repair drone. The casing is stamped with an NT logo and the subscript: 'NanoTrasen Recursive Repair Systems: Fixing Tomorrow's Problem, Today!'"
updateicon()

View File

@@ -2,7 +2,7 @@
/mob/living/silicon/robot/drone/verb/set_mail_tag()
set name = "Set Mail Tag"
set desc = "Tag yourself for delivery through the disposals system."
set category = "Drone"
set category = "Robot Commands"
var/new_tag = input("Select the desired destination.", "Set Mail Tag", null) as null|anything in tagger_locations

View File

@@ -57,7 +57,7 @@
set name = "Drop Item"
set desc = "Release an item from your magnetic gripper."
set category = "Drone"
set category = "Robot Commands"
if(!wrapped)
//There's some weirdness with items being lost inside the arm. Trying to fix all cases. ~Z
@@ -151,12 +151,10 @@
icon_state = "decompiler"
//Metal, glass, wood, plastic.
var/list/stored_comms = list(
"metal" = 0,
"glass" = 0,
"wood" = 0,
"plastic" = 0
)
var/datum/matter_synth/metal = null
var/datum/matter_synth/glass = null
var/datum/matter_synth/wood = null
var/datum/matter_synth/plastic = null
/obj/item/weapon/matter_decompiler/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob)
return
@@ -178,10 +176,10 @@
src.loc.visible_message("\red [src.loc] sucks [M] into its decompiler. There's a horrible crunching noise.","\red It's a bit of a struggle, but you manage to suck [M] into your decompiler. It makes a series of visceral crunching noises.")
new/obj/effect/decal/cleanable/blood/splatter(get_turf(src))
del(M)
stored_comms["wood"]++
stored_comms["wood"]++
stored_comms["plastic"]++
stored_comms["plastic"]++
if(wood)
wood.add_charge(2000)
if(plastic)
plastic.add_charge(2000)
return
else if(istype(M,/mob/living/silicon/robot/drone) && !M.client)
@@ -203,61 +201,66 @@
del(M)
new/obj/effect/decal/cleanable/blood/oil(get_turf(src))
stored_comms["metal"] += 15
stored_comms["glass"] += 15
stored_comms["wood"] += 5
stored_comms["plastic"] += 5
if(metal)
metal.add_charge(15000)
if(glass)
glass.add_charge(15000)
if(wood)
wood.add_charge(2000)
if(plastic)
plastic.add_charge(1000)
return
else
continue
for(var/obj/W in T)
//Different classes of items give different commodities.
if (istype(W,/obj/item/weapon/cigbutt))
stored_comms["plastic"]++
if(istype(W,/obj/item/weapon/cigbutt))
if(plastic)
plastic.add_charge(500)
else if(istype(W,/obj/effect/spider/spiderling))
stored_comms["wood"]++
stored_comms["wood"]++
stored_comms["plastic"]++
stored_comms["plastic"]++
if(wood)
wood.add_charge(2000)
if(plastic)
plastic.add_charge(2000)
else if(istype(W,/obj/item/weapon/light))
var/obj/item/weapon/light/L = W
if(L.status >= 2) //In before someone changes the inexplicably local defines. ~ Z
stored_comms["metal"]++
stored_comms["glass"]++
if(metal)
metal.add_charge(250)
if(glass)
glass.add_charge(250)
else
continue
else if(istype(W,/obj/effect/decal/remains/robot))
stored_comms["metal"]++
stored_comms["metal"]++
stored_comms["plastic"]++
stored_comms["plastic"]++
stored_comms["glass"]++
if(metal)
metal.add_charge(2000)
if(plastic)
plastic.add_charge(2000)
if(glass)
glass.add_charge(1000)
else if(istype(W,/obj/item/trash))
stored_comms["metal"]++
stored_comms["plastic"]++
stored_comms["plastic"]++
stored_comms["plastic"]++
if(metal)
metal.add_charge(1000)
if(plastic)
plastic.add_charge(3000)
else if(istype(W,/obj/effect/decal/cleanable/blood/gibs/robot))
stored_comms["metal"]++
stored_comms["metal"]++
stored_comms["glass"]++
stored_comms["glass"]++
if(metal)
metal.add_charge(2000)
if(glass)
glass.add_charge(2000)
else if(istype(W,/obj/item/ammo_casing))
stored_comms["metal"]++
if(metal)
metal.add_charge(1000)
else if(istype(W,/obj/item/weapon/shard/shrapnel))
stored_comms["metal"]++
stored_comms["metal"]++
stored_comms["metal"]++
if(metal)
metal.add_charge(1000)
else if(istype(W,/obj/item/weapon/shard))
stored_comms["glass"]++
stored_comms["glass"]++
stored_comms["glass"]++
if(glass)
glass.add_charge(1000)
else if(istype(W,/obj/item/weapon/reagent_containers/food/snacks/grown))
stored_comms["wood"]++
stored_comms["wood"]++
stored_comms["wood"]++
stored_comms["wood"]++
if(wood)
wood.add_charge(4000)
else if(istype(W,/obj/item/pipe))
// This allows drones and engiborgs to clear pipe assemblies from floors.
else
@@ -325,39 +328,3 @@
dat += resources
src << browse(dat, "window=robotmod")
//Putting the decompiler here to avoid doing list checks every tick.
/mob/living/silicon/robot/drone/use_power()
..()
if(!src.has_power || !decompiler)
return
//The decompiler replenishes drone stores from hoovered-up junk each tick.
for(var/type in decompiler.stored_comms)
if(decompiler.stored_comms[type] > 0)
var/obj/item/stack/sheet/stack
switch(type)
if("metal")
if(!stack_metal)
stack_metal = new /obj/item/stack/sheet/metal/cyborg(src.module)
stack_metal.amount = 1
stack = stack_metal
if("glass")
if(!stack_glass)
stack_glass = new /obj/item/stack/sheet/glass/cyborg(src.module)
stack_glass.amount = 1
stack = stack_glass
if("wood")
if(!stack_wood)
stack_wood = new /obj/item/stack/sheet/wood/cyborg(src.module)
stack_wood.amount = 1
stack = stack_wood
if("plastic")
if(!stack_plastic)
stack_plastic = new /obj/item/stack/sheet/mineral/plastic/cyborg(src.module)
stack_plastic.amount = 1
stack = stack_plastic
stack.amount++
decompiler.stored_comms[type]--;

View File

@@ -579,6 +579,9 @@ var/list/robot_verbs_default = list(
show_cell_power()
show_jetpack_pressure()
stat(null, text("Lights: [lights_on ? "ON" : "OFF"]"))
if(module)
for(var/datum/matter_synth/ms in module.synths)
stat("[ms.name]: [ms.energy]/[ms.max_energy]")
/mob/living/silicon/robot/restrained()
return 0

View File

@@ -7,9 +7,9 @@
flags = CONDUCT
var/channels = list()
var/list/modules = list()
var/list/datum/matter_synth/synths = list()
var/obj/item/emag = null
var/obj/item/borg/upgrade/jetpack = null
var/list/stacktypes
/obj/item/weapon/robot_module/emp_act(severity)
if(modules)
@@ -17,40 +17,19 @@
O.emp_act(severity)
if(emag)
emag.emp_act(severity)
if(synths)
for(var/datum/matter_synth/S in synths)
S.emp_act(severity)
..()
return
/obj/item/weapon/robot_module/New()
..()
// Build initial inventory.
if(stacktypes && stacktypes.len)
for(var/stack_type in stacktypes)
var/obj/item/stack/new_stack = new stack_type (src)
new_stack.amount = stacktypes[stack_type]
modules |= new_stack
/obj/item/weapon/robot_module/proc/respawn_consumable(var/mob/living/silicon/robot/R, var/rate)
/obj/item/weapon/robot_module/proc/respawn_consumable(var/mob/living/silicon/robot/R)
if(!synths || !synths.len)
return
if(!stacktypes || !stacktypes.len) return
for(var/T in stacktypes)
var/obj/item/stack/S
for(var/obj/O in src.modules)
if(O.type == T)
S = O
break
if(!S)
src.modules -= null
S = new T(src)
src.modules |= S
S.amount = 1
if(!istype(S))
continue
if(S && S.amount < stacktypes[T])
S.amount++
for(var/datum/matter_synth/T in synths)
T.add_charge(T.recharge_rate * rate)
/obj/item/weapon/robot_module/proc/rebuild()//Rebuilds the list so it's possible to add/remove items from the module
var/list/temp_list = modules
@@ -84,10 +63,6 @@
/obj/item/weapon/robot_module/surgeon
name = "surgeon robot module"
stacktypes = list(
/obj/item/stack/medical/advanced/bruise_pack = 5,
/obj/item/stack/nanopaste = 5
)
/obj/item/weapon/robot_module/surgeon/New()
..()
@@ -104,26 +79,34 @@
src.modules += new /obj/item/weapon/circular_saw(src)
src.modules += new /obj/item/weapon/surgicaldrill(src)
src.modules += new /obj/item/weapon/extinguisher/mini(src)
src.modules += new /obj/item/stack/medical/advanced/bruise_pack(src)
src.modules += new /obj/item/stack/nanopaste(src)
src.emag = new /obj/item/weapon/reagent_containers/spray(src)
src.emag.reagents.add_reagent("pacid", 250)
src.emag.name = "Polyacid spray"
var/datum/matter_synth/medicine = new /datum/matter_synth/medicine(10000)
synths += medicine
var/obj/item/stack/nanopaste/N = new /obj/item/stack/nanopaste(src)
var/obj/item/stack/medical/advanced/bruise_pack/B = new /obj/item/stack/medical/advanced/bruise_pack(src)
N.uses_charge = 1
N.charge_costs = list(1000)
N.synths = list(medicine)
B.uses_charge = 1
B.charge_costs = list(1000)
B.synths = list(medicine)
src.modules += N
src.modules += B
return
/obj/item/weapon/robot_module/surgeon/respawn_consumable(var/mob/living/silicon/robot/R)
/obj/item/weapon/robot_module/surgeon/respawn_consumable(var/mob/living/silicon/robot/R, var/amount)
if(src.emag)
var/obj/item/weapon/reagent_containers/spray/PS = src.emag
PS.reagents.add_reagent("pacid", 2)
PS.reagents.add_reagent("pacid", 2 * amount)
..()
/obj/item/weapon/robot_module/crisis
name = "crisis robot module"
stacktypes = list(
/obj/item/stack/medical/ointment = 5,
/obj/item/stack/medical/bruise_pack = 5,
/obj/item/stack/medical/splint = 5
)
/obj/item/weapon/robot_module/crisis/New()
..()
@@ -132,9 +115,6 @@
src.modules += new /obj/item/device/healthanalyzer(src)
src.modules += new /obj/item/device/reagent_scanner/adv(src)
src.modules += new /obj/item/roller_holder(src)
src.modules += new /obj/item/stack/medical/ointment(src)
src.modules += new /obj/item/stack/medical/bruise_pack(src)
src.modules += new /obj/item/stack/medical/splint(src)
src.modules += new /obj/item/weapon/reagent_containers/borghypo/crisis(src)
src.modules += new /obj/item/weapon/reagent_containers/glass/beaker/large(src)
src.modules += new /obj/item/weapon/reagent_containers/robodropper(src)
@@ -143,9 +123,29 @@
src.emag = new /obj/item/weapon/reagent_containers/spray(src)
src.emag.reagents.add_reagent("pacid", 250)
src.emag.name = "Polyacid spray"
var/datum/matter_synth/medicine = new /datum/matter_synth/medicine(15000)
synths += medicine
var/obj/item/stack/medical/ointment/O = new /obj/item/stack/medical/ointment(src)
var/obj/item/stack/medical/bruise_pack/B = new /obj/item/stack/medical/bruise_pack(src)
var/obj/item/stack/medical/splint/S = new /obj/item/stack/medical/splint(src)
O.uses_charge = 1
O.charge_costs = list(1000)
O.synths = list(medicine)
B.uses_charge = 1
B.charge_costs = list(1000)
B.synths = list(medicine)
S.uses_charge = 1
S.charge_costs = list(1000)
S.synths = list(medicine)
src.modules += O
src.modules += B
src.modules += S
return
/obj/item/weapon/robot_module/crisis/respawn_consumable(var/mob/living/silicon/robot/R)
/obj/item/weapon/robot_module/crisis/respawn_consumable(var/mob/living/silicon/robot/R, var/amount)
var/obj/item/weapon/reagent_containers/syringe/S = locate() in src.modules
if(S.mode == 2)
@@ -156,20 +156,13 @@
if(src.emag)
var/obj/item/weapon/reagent_containers/spray/PS = src.emag
PS.reagents.add_reagent("pacid", 2)
PS.reagents.add_reagent("pacid", 2 * amount)
..()
/obj/item/weapon/robot_module/construction
name = "construction robot module"
stacktypes = list(
/obj/item/stack/sheet/metal = 50,
/obj/item/stack/sheet/plasteel = 10,
/obj/item/stack/sheet/glass/reinforced = 50,
/obj/item/stack/rods = 50
)
/obj/item/weapon/robot_module/construction/New()
..()
src.modules += new /obj/item/device/flash(src)
@@ -182,18 +175,32 @@
src.modules += new /obj/item/weapon/pickaxe/plasmacutter(src)
src.modules += new /obj/item/device/pipe_painter(src)
var/datum/matter_synth/metal = new /datum/matter_synth/metal()
var/datum/matter_synth/plasteel = new /datum/matter_synth/plasteel()
var/datum/matter_synth/glass = new /datum/matter_synth/glass()
synths += metal
synths += plasteel
synths += glass
var/obj/item/stack/sheet/metal/cyborg/M = new /obj/item/stack/sheet/metal/cyborg(src)
M.synths = list(metal)
src.modules += M
var/obj/item/stack/rods/cyborg/R = new /obj/item/stack/rods/cyborg(src)
R.synths = list(metal)
src.modules += R
var/obj/item/stack/sheet/plasteel/cyborg/S = new /obj/item/stack/sheet/plasteel/cyborg(src)
S.synths = list(metal)
src.modules += S
var/obj/item/stack/sheet/glass/reinforced/cyborg/RG = new /obj/item/stack/sheet/glass/reinforced/cyborg(src)
RG.synths = list(metal, glass)
src.modules += R
/obj/item/weapon/robot_module/engineering
name = "engineering robot module"
stacktypes = list(
/obj/item/stack/sheet/metal = 50,
/obj/item/stack/sheet/glass = 50,
/obj/item/stack/sheet/glass/reinforced = 50,
/obj/item/stack/cable_coil/robot = 50,
/obj/item/stack/rods = 15,
/obj/item/stack/tile/plasteel = 15
)
/obj/item/weapon/robot_module/engineering/New()
..()
src.modules += new /obj/item/device/flash(src)
@@ -209,9 +216,45 @@
src.modules += new /obj/item/device/analyzer(src)
src.modules += new /obj/item/taperoll/engineering(src)
src.modules += new /obj/item/weapon/gripper(src)
src.modules += new /obj/item/weapon/matter_decompiler(src)
src.modules += new /obj/item/device/pipe_painter(src)
src.emag = new /obj/item/borg/stun(src)
var/datum/matter_synth/metal = new /datum/matter_synth/metal(40000)
var/datum/matter_synth/glass = new /datum/matter_synth/glass(40000)
var/datum/matter_synth/wire = new /datum/matter_synth/wire()
synths += metal
synths += glass
synths += wire
var/obj/item/weapon/matter_decompiler/MD = new /obj/item/weapon/matter_decompiler(src)
MD.metal = metal
MD.glass = glass
src.modules += MD
var/obj/item/stack/sheet/metal/cyborg/M = new /obj/item/stack/sheet/metal/cyborg(src)
M.synths = list(metal)
src.modules += M
var/obj/item/stack/sheet/glass/cyborg/G = new /obj/item/stack/sheet/glass/cyborg(src)
G.synths = list(glass)
src.modules += G
var/obj/item/stack/rods/cyborg/R = new /obj/item/stack/rods/cyborg(src)
R.synths = list(metal)
src.modules += R
var/obj/item/stack/cable_coil/cyborg/C = new /obj/item/stack/cable_coil/cyborg(src)
C.synths = list(wire)
src.modules += C
var/obj/item/stack/tile/plasteel/cyborg/S = new /obj/item/stack/tile/plasteel/cyborg(src)
S.synths = list(metal)
src.modules += S
var/obj/item/stack/sheet/glass/reinforced/cyborg/RG = new /obj/item/stack/sheet/glass/reinforced/cyborg(src)
RG.synths = list(metal, glass)
src.modules += RG
return
/obj/item/weapon/robot_module/security
@@ -228,7 +271,7 @@
src.emag = new /obj/item/weapon/gun/energy/laser/mounted(src)
return
/obj/item/weapon/robot_module/security/respawn_consumable(var/mob/living/silicon/robot/R)
/obj/item/weapon/robot_module/security/respawn_consumable(var/mob/living/silicon/robot/R, var/amount)
var/obj/item/device/flash/F = locate() in src.modules
if(F.broken)
F.broken = 0
@@ -238,7 +281,7 @@
F.times_used--
var/obj/item/weapon/gun/energy/taser/mounted/cyborg/T = locate() in src.modules
if(T.power_supply.charge < T.power_supply.maxcharge)
T.power_supply.give(T.charge_cost)
T.power_supply.give(T.charge_cost * amount)
T.update_icon()
else
T.charge_tick = 0
@@ -258,12 +301,12 @@
src.emag.name = "Lube spray"
return
/obj/item/weapon/robot_module/janitor/respawn_consumable(var/mob/living/silicon/robot/R)
/obj/item/weapon/robot_module/janitor/respawn_consumable(var/mob/living/silicon/robot/R, var/amount)
var/obj/item/device/lightreplacer/LR = locate() in src.modules
LR.Charge(R)
LR.Charge(R, amount)
if(src.emag)
var/obj/item/weapon/reagent_containers/spray/S = src.emag
S.reagents.add_reagent("lube", 2)
S.reagents.add_reagent("lube", 2 * amount)
/obj/item/weapon/robot_module/butler
name = "service robot module"
@@ -327,12 +370,12 @@
R.add_language("Tradeband", 1)
R.add_language("Gutter", 1)
/obj/item/weapon/robot_module/butler/respawn_consumable(var/mob/living/silicon/robot/R)
/obj/item/weapon/robot_module/butler/respawn_consumable(var/mob/living/silicon/robot/R, var/amount)
var/obj/item/weapon/reagent_containers/food/condiment/enzyme/E = locate() in src.modules
E.reagents.add_reagent("enzyme", 2)
E.reagents.add_reagent("enzyme", 2 * amount)
if(src.emag)
var/obj/item/weapon/reagent_containers/food/drinks/cans/beer/B = src.emag
B.reagents.add_reagent("beer2", 2)
B.reagents.add_reagent("beer2", 2 * amount)
/obj/item/weapon/robot_module/miner
name = "miner robot module"
@@ -392,17 +435,6 @@
/obj/item/weapon/robot_module/drone
name = "drone module"
stacktypes = list(
/obj/item/stack/sheet/wood = 1,
/obj/item/stack/sheet/mineral/plastic = 1,
/obj/item/stack/sheet/glass/reinforced = 5,
/obj/item/stack/tile/wood = 5,
/obj/item/stack/rods = 15,
/obj/item/stack/tile/plasteel = 15,
/obj/item/stack/sheet/metal = 20,
/obj/item/stack/sheet/glass = 20,
/obj/item/stack/cable_coil/robot = 30
)
/obj/item/weapon/robot_module/drone/New()
..()
@@ -414,20 +446,73 @@
src.modules += new /obj/item/device/multitool(src)
src.modules += new /obj/item/device/lightreplacer(src)
src.modules += new /obj/item/weapon/gripper(src)
src.modules += new /obj/item/weapon/matter_decompiler(src)
src.modules += new /obj/item/weapon/reagent_containers/spray/cleaner/drone(src)
src.emag = new /obj/item/weapon/pickaxe/plasmacutter(src)
src.emag.name = "Plasma Cutter"
var/datum/matter_synth/metal = new /datum/matter_synth/metal(25000)
var/datum/matter_synth/glass = new /datum/matter_synth/glass(25000)
var/datum/matter_synth/wood = new /datum/matter_synth/wood(2000)
var/datum/matter_synth/plastic = new /datum/matter_synth/plastic(1000)
var/datum/matter_synth/wire = new /datum/matter_synth/wire(30)
synths += metal
synths += glass
synths += wood
synths += plastic
synths += wire
var/obj/item/weapon/matter_decompiler/MD = new /obj/item/weapon/matter_decompiler(src)
MD.metal = metal
MD.glass = glass
MD.wood = wood
MD.plastic = plastic
src.modules += MD
var/obj/item/stack/sheet/metal/cyborg/M = new /obj/item/stack/sheet/metal/cyborg(src)
M.synths = list(metal)
src.modules += M
var/obj/item/stack/sheet/glass/cyborg/G = new /obj/item/stack/sheet/glass/cyborg(src)
G.synths = list(glass)
src.modules += G
var/obj/item/stack/rods/cyborg/R = new /obj/item/stack/rods/cyborg(src)
R.synths = list(metal)
src.modules += R
var/obj/item/stack/cable_coil/cyborg/C = new /obj/item/stack/cable_coil/cyborg(src)
C.synths = list(wire)
src.modules += C
var/obj/item/stack/tile/plasteel/cyborg/S = new /obj/item/stack/tile/plasteel/cyborg(src)
S.synths = list(metal)
src.modules += S
var/obj/item/stack/sheet/glass/reinforced/cyborg/RG = new /obj/item/stack/sheet/glass/reinforced/cyborg(src)
RG.synths = list(metal, glass)
src.modules += RG
var/obj/item/stack/tile/wood/cyborg/WT = new /obj/item/stack/tile/wood/cyborg(src)
WT.synths = list(wood)
src.modules += WT
var/obj/item/stack/sheet/wood/cyborg/W = new /obj/item/stack/sheet/wood/cyborg(src)
W.synths = list(wood)
src.modules += W
var/obj/item/stack/sheet/mineral/plastic/cyborg/P = new /obj/item/stack/sheet/mineral/plastic/cyborg(src)
P.synths = list(plastic)
src.modules += P
/obj/item/weapon/robot_module/drone/add_languages(var/mob/living/silicon/robot/R)
return //not much ROM to spare in that tiny microprocessor!
/obj/item/weapon/robot_module/drone/respawn_consumable(var/mob/living/silicon/robot/R)
/obj/item/weapon/robot_module/drone/respawn_consumable(var/mob/living/silicon/robot/R, var/amount)
var/obj/item/weapon/reagent_containers/spray/cleaner/C = locate() in src.modules
C.reagents.add_reagent("cleaner", 3)
C.reagents.add_reagent("cleaner", 3 * amount)
var/obj/item/device/lightreplacer/LR = locate() in src.modules
LR.Charge(R)
LR.Charge(R, amount)
..()
return

View File

@@ -183,7 +183,7 @@ var/list/slot_equipment_priority = list( \
if(!istype(W)) return 0
for(var/slot in slot_equipment_priority)
if(equip_to_slot_if_possible(W, slot, 0, 1, 1)) //del_on_fail = 0; disable_warning = 0; redraw_mob = 1
if(equip_to_slot_if_possible(W, slot, del_on_fail=0, disable_warning=1, redraw_mob=1))
return 1
return 0

View File

@@ -80,6 +80,18 @@
return 1
return 0
/mob/proc/isSilicon()
return 0
/mob/living/silicon/isSilicon()
return 1
/mob/proc/isAI()
return 0
/mob/living/silicon/ai/isAI()
return 1
/proc/ispAI(A)
if(istype(A, /mob/living/silicon/pai))
return 1

View File

@@ -1,5 +1,5 @@
// This file contains all Nano procs/definitions for external classes/objects
// This file contains all Nano procs/definitions for external classes/objects
/**
* Called when a Nano UI window is closed
* This is how Nano handles closed windows
@@ -15,7 +15,7 @@
if (istype(ui))
ui.close()
if(ui.ref)
var/href = "close=1"
src.Topic(href, params2list(href), ui.ref) // this will direct to the atom's Topic() proc via client.Topic()
@@ -31,14 +31,14 @@
* ui_interact is currently defined for /atom/movable
*
* @param user /mob The mob who is interacting with this ui
* @param ui_key string A string key to use for this ui. Allows for multiple unique uis on one obj/mob (defaut value "main")
* @param ui /datum/nanoui This parameter is passed by the nanoui process() proc when updating an open ui
* @param ui_key string A string key to use for this ui. Allows for multiple unique uis on one obj/mob (defaut value "main")
* @param ui /datum/nanoui This parameter is passed by the nanoui process() proc when updating an open ui
* @param force_open boolean Force the UI to (re)open, even if it's already open
*
* @return nothing
*/
/atom/movable/proc/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
/atom/movable/proc/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/nano_ui/master_ui = null, var/datum/topic_state/custom_state = null)
return
// Used by the Nano UI Manager (/datum/nanomanager) to track UIs opened by this mob
/mob/var/list/open_uis = list()

View File

@@ -0,0 +1,120 @@
/atom/movable/proc/nano_host()
return src
/obj/nano_module/nano_host()
return loc
/atom/movable/proc/CanUseTopic(var/mob/user, href_list, var/datum/topic_state/custom_state)
return user.can_use_topic(nano_host(), custom_state)
/mob/proc/can_use_topic(var/mob/user, var/datum/topic_state/custom_state)
return STATUS_CLOSE // By default no mob can do anything with NanoUI
/mob/dead/observer/can_use_topic()
if(check_rights(R_ADMIN, 0))
return STATUS_INTERACTIVE // Admins are more equal
return STATUS_UPDATE // Ghosts can view updates
/mob/living/silicon/pai/can_use_topic(var/src_object)
if(src_object == src && !stat)
return STATUS_INTERACTIVE
else
return ..()
/mob/living/silicon/robot/can_use_topic(var/src_object, var/datum/topic_state/custom_state)
if(stat || !client)
return STATUS_CLOSE
if(lockcharge || stunned || weakened)
return STATUS_DISABLED
// robots can interact with things they can see within their view range
if(!(custom_state.flags & NANO_IGNORE_DISTANCE) && (src_object in view(src)))
return STATUS_INTERACTIVE // interactive (green visibility)
return STATUS_DISABLED // no updates, completely disabled (red visibility)
/mob/living/silicon/robot/syndicate/can_use_topic(var/src_object)
. = ..()
if(. != STATUS_INTERACTIVE)
return
if(z in config.admin_levels) // Syndicate borgs can interact with everything on the admin level
return STATUS_INTERACTIVE
if(istype(get_area(src), /area/syndicate_station)) // If elsewhere, they can interact with everything on the syndicate shuttle
return STATUS_INTERACTIVE
if(istype(src_object, /obj/machinery)) // Otherwise they can only interact with emagged machinery
var/obj/machinery/Machine = src_object
if(Machine.emagged)
return STATUS_INTERACTIVE
return STATUS_UPDATE
/mob/living/silicon/ai/can_use_topic(var/src_object)
if(!client || check_unable(1))
return STATUS_CLOSE
// Prevents the AI from using Topic on admin levels (by for example viewing through the court/thunderdome cameras)
// unless it's on the same level as the object it's interacting with.
var/turf/T = get_turf(src_object)
if(!T || !(z == T.z || (T.z in config.player_levels)))
return STATUS_CLOSE
// If an object is in view then we can interact with it
if(src_object in view(client.view, src))
return STATUS_INTERACTIVE
// If we're installed in a chassi, rather than transfered to an inteliCard or other container, then check if we have camera view
if(is_in_chassis())
//stop AIs from leaving windows open and using then after they lose vision
//apc_override is needed here because AIs use their own APC when powerless
if(cameranet && !cameranet.checkTurfVis(get_turf(src_object)))
return apc_override ? STATUS_INTERACTIVE : STATUS_CLOSE
return STATUS_INTERACTIVE
return STATUS_CLOSE
/mob/living/proc/shared_living_nano_interaction(var/src_object)
if (src.stat != CONSCIOUS)
return STATUS_CLOSE // no updates, close the interface
else if (restrained() || lying || stat || stunned || weakened)
return STATUS_UPDATE // update only (orange visibility)
return STATUS_INTERACTIVE
/mob/living/proc/shared_living_nano_distance(var/atom/movable/src_object)
if(!isturf(src_object.loc))
if(src_object.loc == src) // Item in the inventory
return STATUS_INTERACTIVE
if(src.contents.Find(src_object.loc)) // A hidden uplink inside an item
return STATUS_INTERACTIVE
if (!(src_object in view(4, src))) // If the src object is not in visable, disable updates
return STATUS_CLOSE
var/dist = get_dist(src_object, src)
if (dist <= 1)
return STATUS_INTERACTIVE // interactive (green visibility)
else if (dist <= 2)
return STATUS_UPDATE // update only (orange visibility)
else if (dist <= 4)
return STATUS_DISABLED // no updates, completely disabled (red visibility)
return STATUS_CLOSE
/mob/living/can_use_topic(var/src_object, var/datum/topic_state/custom_state)
. = shared_living_nano_interaction(src_object)
if(. == STATUS_INTERACTIVE && !(custom_state.flags & NANO_IGNORE_DISTANCE))
. = shared_living_nano_distance(src_object)
if(STATUS_INTERACTIVE)
return STATUS_UPDATE
/mob/living/carbon/human/can_use_topic(var/src_object, var/datum/topic_state/custom_state)
. = shared_living_nano_interaction(src_object)
if(. == STATUS_INTERACTIVE && !(custom_state.flags & NANO_IGNORE_DISTANCE))
. = shared_living_nano_distance(src_object)
if(. == STATUS_UPDATE && (TK in mutations)) // If we have telekinesis and remain close enough, allow interaction.
return STATUS_INTERACTIVE
/var/global/datum/topic_state/default_state = new()
/datum/topic_state
var/flags = 0
/datum/topic_state/proc/href_list(var/mob/user)
return list()

View File

@@ -186,7 +186,8 @@
return 0 // wasn't open
processing_uis.Remove(ui)
ui.user.open_uis.Remove(ui)
if(ui.user) // Sanity check in case a user has been deleted (say a blown up borg watching the alarm interface)
ui.user.open_uis.Remove(ui)
var/list/uis = open_uis[src_object_key][ui.ui_key]
uis.Remove(ui)

View File

@@ -1,11 +0,0 @@
/atom/movable/proc/nano_host()
return src
/obj/nano_module/nano_host()
return loc
/atom/movable/proc/nano_can_update()
return 1
/obj/machinery/nano_can_update()
return !(stat & (NOPOWER|BROKEN))

View File

@@ -52,6 +52,11 @@ nanoui is used to open and update nano browser uis
// the current status/visibility of the ui
var/status = STATUS_INTERACTIVE
// Relationship between a master interface and its children. Used in update_status
var/datum/nanoui/master_ui
var/list/datum/nanoui/children = list()
var/datum/topic_state/custom_state = null
var/cached_data = null
/**
@@ -68,17 +73,22 @@ nanoui is used to open and update nano browser uis
*
* @return /nanoui new nanoui object
*/
/datum/nanoui/New(nuser, nsrc_object, nui_key, ntemplate_filename, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null)
/datum/nanoui/New(nuser, nsrc_object, nui_key, ntemplate_filename, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null, var/datum/nanoui/master_ui = null, var/datum/topic_state/custom_state = null)
user = nuser
src_object = nsrc_object
ui_key = nui_key
window_id = "[ui_key]\ref[src_object]"
src.master_ui = master_ui
if(master_ui)
master_ui.children += src
src.custom_state = custom_state ? custom_state : new/datum/topic_state()
// add the passed template filename as the "main" template, this is required
add_template("main", ntemplate_filename)
if (ntitle)
title = ntitle
title = sanitize(ntitle)
if (nwidth)
width = nwidth
if (nheight)
@@ -133,120 +143,13 @@ nanoui is used to open and update nano browser uis
*/
/datum/nanoui/proc/update_status(var/push_update = 0)
var/atom/movable/host = src_object.nano_host()
if(!host.nano_can_update())
close()
return
var/status = user.can_interact_with_interface(host.nano_host())
if(status == STATUS_CLOSE)
var/new_status = host.CanUseTopic(user, list(), custom_state)
if(master_ui)
new_status = min(new_status, master_ui.status)
if(new_status == STATUS_CLOSE)
close()
else
set_status(status, push_update)
/*
Procs called by update_status()
*/
/mob/living/silicon/pai/can_interact_with_interface(src_object)
if(src_object == src && !stat)
return STATUS_INTERACTIVE
else
return ..()
/mob/proc/can_interact_with_interface(var/src_object)
return STATUS_CLOSE // By default no mob can do anything with NanoUI
/mob/dead/observer/can_interact_with_interface()
if(check_rights(R_ADMIN, 0))
return STATUS_INTERACTIVE // Admins are more equal
return STATUS_UPDATE // Ghosts can view updates
/mob/living/silicon/robot/can_interact_with_interface(var/src_object)
if(stat || !client)
return STATUS_CLOSE
if(lockcharge || stunned || weakened)
return STATUS_DISABLED
if (src_object in view(client.view, src)) // robots can see and interact with things they can see within their view range
return STATUS_INTERACTIVE // interactive (green visibility)
return STATUS_DISABLED // no updates, completely disabled (red visibility)
/mob/living/silicon/robot/syndicate/can_interact_with_interface(var/src_object)
. = ..()
if(. != STATUS_INTERACTIVE)
return
if(z in config.admin_levels) // Syndicate borgs can interact with everything on the admin level
return STATUS_INTERACTIVE
if(istype(get_area(src), /area/syndicate_station)) // If elsewhere, they can interact with everything on the syndicate shuttle
return STATUS_INTERACTIVE
if(istype(src_object, /obj/machinery)) // Otherwise they can only interact with emagged machinery
var/obj/machinery/Machine = src_object
if(Machine.emagged)
return STATUS_INTERACTIVE
return STATUS_UPDATE
/mob/living/silicon/ai/can_interact_with_interface(var/src_object)
if(!client || check_unable(1))
return STATUS_CLOSE
// Prevents the AI from using Topic on admin levels (by for example viewing through the court/thunderdome cameras)
// unless it's on the same level as the object it's interacting with.
var/turf/T = get_turf(src_object)
if(!T || !(z == T.z || (T.z in config.player_levels)))
return STATUS_CLOSE
// If an object is in view then we can interact with it
if(src_object in view(client.view, src))
return STATUS_INTERACTIVE
// If we're installed in a chassi, rather than transfered to an inteliCard or other container, then check if we have camera view
if(is_in_chassis())
//stop AIs from leaving windows open and using then after they lose vision
//apc_override is needed here because AIs use their own APC when powerless
if(cameranet && !cameranet.checkTurfVis(get_turf(src_object)))
return apc_override ? STATUS_INTERACTIVE : STATUS_CLOSE
return STATUS_INTERACTIVE
return STATUS_CLOSE
/mob/living/proc/shared_living_nano_interaction(var/src_object)
if (src.stat != CONSCIOUS)
return STATUS_CLOSE // no updates, close the interface
else if (restrained() || lying || stat || stunned || weakened)
return STATUS_UPDATE // update only (orange visibility)
return STATUS_INTERACTIVE
/mob/living/proc/shared_living_nano_distance(var/atom/movable/src_object)
if(!isturf(src_object.loc))
if(src_object.loc == src) // Item in the inventory
return STATUS_INTERACTIVE
if(src.contents.Find(src_object.loc)) // A hidden uplink inside an item
return STATUS_INTERACTIVE
if (!(src_object in view(4, src))) // If the src object is not in visable, disable updates
return STATUS_CLOSE
var/dist = get_dist(src_object, src)
if (dist <= 1)
return STATUS_INTERACTIVE // interactive (green visibility)
else if (dist <= 2)
return STATUS_UPDATE // update only (orange visibility)
else if (dist <= 4)
return STATUS_DISABLED // no updates, completely disabled (red visibility)
return STATUS_CLOSE
/mob/living/can_interact_with_interface(var/src_object, var/be_close = 1)
. = shared_living_nano_interaction(src_object)
if(. == STATUS_INTERACTIVE && be_close)
. = shared_living_nano_distance(src_object)
if(STATUS_INTERACTIVE)
return STATUS_UPDATE
/mob/living/carbon/human/can_interact_with_interface(var/src_object, var/be_close = 1)
. = shared_living_nano_interaction(src_object)
if(. == STATUS_INTERACTIVE && be_close)
. = shared_living_nano_distance(src_object)
if(. == STATUS_UPDATE && (TK in mutations)) // If we have telekinesis and remain close enough, allow interaction.
return STATUS_INTERACTIVE
set_status(new_status, push_update)
/**
* Set the ui to auto update (every master_controller tick)
@@ -489,7 +392,6 @@ nanoui is used to open and update nano browser uis
* @return nothing
*/
/datum/nanoui/proc/open()
var/window_size = ""
if (width && height)
window_size = "size=[width]x[height];"
@@ -509,6 +411,8 @@ nanoui is used to open and update nano browser uis
is_auto_updating = 0
nanomanager.ui_closed(src)
user << browse(null, "window=[window_id]")
for(var/datum/nanoui/child in children)
child.close()
/**
* Set the UI window to call the nanoclose verb when the window is closed
@@ -573,7 +477,7 @@ nanoui is used to open and update nano browser uis
set_map_z_level(text2num(href_list["mapZLevel"]))
map_update = 1
if ((src_object && src_object.Topic(href, href_list)) || map_update)
if ((src_object && src_object.Topic(href, href_list, 0, custom_state)) || map_update)
nanomanager.update_uis(src_object) // update all UIs attached to src_object
/**
@@ -600,5 +504,4 @@ nanoui is used to open and update nano browser uis
* @return nothing
*/
/datum/nanoui/proc/update(var/force_open = 0)
src_object.ui_interact(user, ui_key, src, force_open)
src_object.ui_interact(user, ui_key, src, force_open, master_ui, custom_state)

View File

@@ -596,14 +596,11 @@ Note that amputating the affected organ does in fact remove the infection from t
update_damages()
var/obj/organ //Dropped limb object
var/list/dropped_items
switch(body_part)
if(HEAD)
organ= new /obj/item/weapon/organ/head(owner.loc, owner)
owner.u_equip(owner.glasses)
owner.u_equip(owner.head)
owner.u_equip(owner.l_ear)
owner.u_equip(owner.r_ear)
owner.u_equip(owner.wear_mask)
organ = new /obj/item/weapon/organ/head(owner.loc, owner)
dropped_items = list(owner.glasses, owner.head, owner.l_ear, owner.r_ear, owner.wear_mask)
if(ARM_RIGHT)
if(status & ORGAN_ROBOT)
organ = new /obj/item/robot_parts/r_arm(owner.loc)
@@ -627,19 +624,22 @@ Note that amputating the affected organ does in fact remove the infection from t
if(HAND_RIGHT)
if(!(status & ORGAN_ROBOT))
organ= new /obj/item/weapon/organ/r_hand(owner.loc, owner)
owner.u_equip(owner.gloves)
dropped_items = list(owner.gloves) //should probably make it so that you can still wear gloves if you have one hand
if(HAND_LEFT)
if(!(status & ORGAN_ROBOT))
organ= new /obj/item/weapon/organ/l_hand(owner.loc, owner)
owner.u_equip(owner.gloves)
dropped_items = list(owner.gloves)
if(FOOT_RIGHT)
if(!(status & ORGAN_ROBOT))
organ= new /obj/item/weapon/organ/r_foot/(owner.loc, owner)
owner.u_equip(owner.shoes)
dropped_items = list(owner.shoes)
if(FOOT_LEFT)
if(!(status & ORGAN_ROBOT))
organ = new /obj/item/weapon/organ/l_foot(owner.loc, owner)
owner.u_equip(owner.shoes)
dropped_items = list(owner.shoes)
if(dropped_items)
for(var/obj/O in dropped_items)
owner.remove_from_mob(O)
destspawn = 1
//Robotic limbs explode if sabotaged.

View File

@@ -482,6 +482,15 @@ obj/structure/cable/proc/cableColor(var/colorC)
item_state = "coil"
attack_verb = list("whipped", "lashed", "disciplined", "flogged")
/obj/item/stack/cable_coil/cyborg
name = "cable coil synthesizer"
desc = "A device that makes cable."
gender = NEUTER
matter = null
uses_charge = 1
charge_costs = list(1)
stacktype = /obj/item/stack/cable_coil
/obj/item/stack/cable_coil/suicide_act(mob/user)
if(locate(/obj/item/weapon/stool) in user.loc)
user.visible_message("<span class='suicide'>[user] is making a noose with the [src.name]! It looks like \he's trying to commit suicide.</span>")
@@ -576,7 +585,7 @@ obj/structure/cable/proc/cableColor(var/colorC)
usr << "\blue You cannot do that."
..()
/obj/item/stack/cable_coil/robot/verb/set_colour()
/obj/item/stack/cable_coil/cyborg/verb/set_colour()
set name = "Change Colour"
set category = "Object"
@@ -606,26 +615,26 @@ obj/structure/cable/proc/cableColor(var/colorC)
// - Cable coil : merge cables
/obj/item/stack/cable_coil/attackby(obj/item/weapon/W, mob/user)
..()
if( istype(W, /obj/item/weapon/wirecutters) && src.amount > 1)
src.amount--
if( istype(W, /obj/item/weapon/wirecutters) && src.get_amount() > 1)
src.use(1)
new/obj/item/stack/cable_coil(user.loc, 1,color)
user << "You cut a piece off the cable coil."
src.update_icon()
return
else if(istype(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C = W
if(C.amount >= MAXCOIL)
if(C.get_amount() >= get_max_amount())
user << "The coil is too long, you cannot add any more cable to it."
return
if( (C.amount + src.amount <= MAXCOIL) )
if( (C.get_amount() + src.get_amount() <= get_max_amount()) )
user << "You join the cable coils together."
C.give(src.amount) // give it cable
src.use(src.amount) // make sure this one cleans up right
C.give(src.get_amount()) // give it cable
src.use(src.get_amount()) // make sure this one cleans up right
return
else
var/amt = MAXCOIL - C.amount
var/amt = get_max_amount() - C.get_amount()
user << "You transfer [amt] length\s of cable from one coil to the other."
C.give(amt)
src.use(amt)

View File

@@ -118,14 +118,14 @@
/obj/item/ammo_casing/a145
name = "shell casing"
desc = "A 14.5mm AP shell."
desc = "A 14.5mm shell."
icon_state = "lcasing"
spent_icon = "lcasing-spent"
caliber = "14.5mm"
projectile_type = /obj/item/projectile/bullet/rifle/a145
/obj/item/ammo_casing/a556
desc = "A 5.56 bullet casing."
desc = "A 5.56mm bullet casing."
caliber = "a556"
projectile_type = /obj/item/projectile/bullet/rifle/a556

View File

@@ -1,6 +1,6 @@
/obj/item/weapon/syringe_cartridge
name = "syringe gun cartridge"
desc = "An impact-triggered compressed gas cartridge that can fitted to a syringe for rapid injection."
desc = "An impact-triggered compressed gas cartridge that can be fitted to a syringe for rapid injection."
icon = 'icons/obj/ammo.dmi'
icon_state = "syringe-cartridge"
var/icon_flight = "syringe-cartridge-flight" //so it doesn't look so weird when shot
@@ -25,6 +25,7 @@
user.remove_from_mob(syringe)
syringe.loc = src
sharp = 1
name = "syringe dart"
update_icon()
/obj/item/weapon/syringe_cartridge/attack_self(mob/user)
@@ -33,6 +34,7 @@
user.put_in_hands(syringe)
syringe = null
sharp = initial(sharp)
name = initial(name)
update_icon()
/obj/item/weapon/syringe_cartridge/proc/prime()

View File

@@ -70,15 +70,16 @@
/obj/item/weapon/gun/projectile/automatic/z8
name = "\improper Z8 Bulldog"
desc = "An older model bullpup carbine, made by the now defunct Zendai Foundries. Uses armor piercing 5.56 rounds. Makes you feel like a space marine when you hold it."
desc = "An older model bullpup carbine, made by the now defunct Zendai Foundries. Uses armor piercing 5.56mm rounds. Makes you feel like a space marine when you hold it."
icon_state = "carbine"
item_state = "shotgun"
w_class = 4.0
w_class = 4
force = 10
caliber = "a556"
origin_tech = "combat=8;materials=3"
ammo_type = "/obj/item/ammo_casing/a556"
fire_sound = 'sound/weapons/Gunshot.ogg'
slot_flags = SLOT_BACK
load_method = MAGAZINE
magazine_type = /obj/item/ammo_magazine/a556
@@ -92,13 +93,13 @@
/obj/item/weapon/gun/projectile/automatic/sts35
name = "\improper STS-35 automatic rifle"
desc = "A durable, rugged looking automatic weapon of make popular on the frontier, despite it's bulk. Uses 7.62mm rounds. It is unmarked."
desc = "A durable, rugged looking automatic weapon of a make popular on the frontier. Uses 7.62mm rounds. It is unmarked."
icon_state = "assltrifle"
item_state = "shotgun"
w_class = 4
force = 10
caliber = "a762"
origin_tech = "combat=5;materials=1;syndicate=8"
origin_tech = "combat=6;materials=1;syndicate=4"
slot_flags = SLOT_BACK
load_method = MAGAZINE
magazine_type = /obj/item/ammo_magazine/c762
@@ -117,7 +118,7 @@
slot_flags = 0
max_shells = 50
caliber = "a762"
origin_tech = "combat=5;materials=1;syndicate=2"
origin_tech = "combat=6;materials=1;syndicate=2"
slot_flags = SLOT_BACK
ammo_type = "/obj/item/ammo_casing/a762"
fire_sound = 'sound/weapons/Gunshot_smg.ogg'

View File

@@ -1,6 +1,6 @@
/obj/item/weapon/gun/projectile/heavysniper
name = "\improper PTRS-7 rifle"
desc = "A portable anti-armour rifle fitted with a scope. Originally designed to used against armoured exosuits, it is capable of punching through non-reinforced walls with ease. Fires 14.5mm AP shells."
desc = "A portable anti-armour rifle fitted with a scope. Originally designed to used against armoured exosuits, it is capable of punching through non-reinforced walls with ease. Fires armor piercing 14.5mm shells."
icon_state = "heavysniper"
item_state = "shotgun"
w_class = 4

View File

@@ -66,14 +66,10 @@
return
//Checks if the projectile is eligible for embedding. Not that it necessarily will.
//Mainly used to ensure that projectiles won't embed if they are penetrating the mob.
/obj/item/projectile/proc/can_embed()
//embed must be enabled and damage type must be brute
if(!embed || damage_type != BRUTE)
return 0
//can't embed if the projectile is penetrating through the mob
if(penetrating > 0 && damage > 20 && prob(damage))
return 0
return 1
//return 1 if the projectile should be allowed to pass through after all, 0 if not.
@@ -167,9 +163,12 @@
target_mob.attack_log += "\[[time_stamp()]\] <b>[firer]/[firer.ckey]</b> shot <b>[target_mob]/[target_mob.ckey]</b> with a <b>[src.type]</b>"
firer.attack_log += "\[[time_stamp()]\] <b>[firer]/[firer.ckey]</b> shot <b>[target_mob]/[target_mob.ckey]</b> with a <b>[src.type]</b>"
msg_admin_attack("[firer] ([firer.ckey]) shot [target_mob] ([target_mob.ckey]) with a [src] (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[firer.x];Y=[firer.y];Z=[firer.z]'>JMP</a>)") //BS12 EDIT ALG
else
else if(firer)
target_mob.attack_log += "\[[time_stamp()]\] <b>UNKNOWN SUBJECT (No longer exists)</b> shot <b>[target_mob]/[target_mob.ckey]</b> with a <b>[src]</b>"
msg_admin_attack("UNKNOWN shot [target_mob] ([target_mob.ckey]) with a [src] (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[firer.x];Y=[firer.y];Z=[firer.z]'>JMP</a>)") //BS12 EDIT ALG
else
target_mob.attack_log += "\[[time_stamp()]\] <b>UNKNOWN SUBJECT (No longer exists)</b> shot <b>[target_mob]/[target_mob.ckey]</b> with a <b>[src]</b>"
msg_admin_attack("UNKNOWN shot [target_mob] ([target_mob.ckey]) with a [src] (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[target_mob.x];Y=[target_mob.y];Z=[target_mob.z]'>JMP</a>)") //BS12 EDIT ALG
//sometimes bullet_act() will want the projectile to continue flying
if (target_mob.bullet_act(src, def_zone) == -1)
@@ -206,9 +205,9 @@
for(var/mob/M in A)
attack_mob(M, distance)
//penetrating projectiles can pass through things that otherwise would not let them
//penetrating projectiles can pass through things that otherwise would not let them
if(!passthrough && penetrating > 0)
if(check_penetrate(A))
if(check_penetrate(A))
passthrough = 1
penetrating--
@@ -311,4 +310,4 @@
trace.firer = user
var/output = trace.process() //Test it!
del(trace) //No need for it anymore
return output //Send it back to the gun!
return output //Send it back to the gun!

View File

@@ -7,12 +7,26 @@
check_armour = "bullet"
embed = 1
sharp = 1
var/mob_passthrough_check = 0
/obj/item/projectile/bullet/on_hit(var/atom/target, var/blocked = 0)
if (..(target, blocked))
var/mob/living/L = target
shake_camera(L, 3, 2)
/obj/item/projectile/bullet/attack_mob(var/mob/living/target_mob, var/distance, var/miss_modifier)
if(penetrating > 0 && damage > 20 && prob(damage))
mob_passthrough_check = 1
else
mob_passthrough_check = 0
..()
/obj/item/projectile/bullet/can_embed()
//prevent embedding if the projectile is passing through the mob
if(mob_passthrough_check)
return 0
return ..()
/obj/item/projectile/bullet/check_penetrate(var/atom/A)
if(!A || !A.density) return 1 //if whatever it was got destroyed when we hit it, then I guess we can just keep going
@@ -20,10 +34,10 @@
return 1 //mecha have their own penetration handling
if(ismob(A))
if(iscarbon(A))
//squishy mobs absorb KE
if(can_embed()) return 0
damage *= 0.7
if(!mob_passthrough_check)
return 0
if(iscarbon(A))
damage *= 0.7 //squishy mobs absorb KE
return 1
var/chance = 0

View File

@@ -103,6 +103,9 @@ proc/do_surgery(mob/living/carbon/M, mob/living/user, obj/item/tool)
else // This failing silently was a pain.
user << "\red You must remain close to your patient to conduct surgery."
M.op_stage.in_progress = 0 // Clear the in-progress flag.
if (ishuman(M))
var/mob/living/carbon/human/H = M
H.update_surgery()
return 1 //don't want to do weapony things after surgery
if (user.a_intent == "help")

View File

@@ -759,3 +759,4 @@ var/list/be_special_flags = list(
#define STATUS_DISABLED 0 // RED Visability
#define STATUS_CLOSE -1 // Close the interface
#define NANO_IGNORE_DISTANCE 1