diff --git a/baystation12.dme b/baystation12.dme
index 2f3bcb9bfd..832b4460e0 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -629,9 +629,11 @@
#include "code\game\objects\items\weapons\circuitboards\computer\research.dm"
#include "code\game\objects\items\weapons\circuitboards\computer\supply.dm"
#include "code\game\objects\items\weapons\circuitboards\computer\telecomms.dm"
+#include "code\game\objects\items\weapons\circuitboards\machinery\biogenerator.dm"
#include "code\game\objects\items\weapons\circuitboards\machinery\cloning.dm"
#include "code\game\objects\items\weapons\circuitboards\machinery\pacman.dm"
#include "code\game\objects\items\weapons\circuitboards\machinery\power.dm"
+#include "code\game\objects\items\weapons\circuitboards\machinery\recharge_station.dm"
#include "code\game\objects\items\weapons\circuitboards\machinery\research.dm"
#include "code\game\objects\items\weapons\circuitboards\machinery\shieldgen.dm"
#include "code\game\objects\items\weapons\circuitboards\machinery\telecomms.dm"
@@ -786,6 +788,7 @@
#include "code\modules\admin\verbs\debug.dm"
#include "code\modules\admin\verbs\diagnostics.dm"
#include "code\modules\admin\verbs\getlogs.dm"
+#include "code\modules\admin\verbs\icarus.dm"
#include "code\modules\admin\verbs\mapping.dm"
#include "code\modules\admin\verbs\massmodvar.dm"
#include "code\modules\admin\verbs\modifyvariables.dm"
@@ -895,7 +898,10 @@
#include "code\modules\clothing\under\miscellaneous.dm"
#include "code\modules\clothing\under\shorts.dm"
#include "code\modules\clothing\under\syndicate.dm"
-#include "code\modules\clothing\under\ties.dm"
+#include "code\modules\clothing\under\accessories\accessory.dm"
+#include "code\modules\clothing\under\accessories\armband.dm"
+#include "code\modules\clothing\under\accessories\holster.dm"
+#include "code\modules\clothing\under\accessories\storage.dm"
#include "code\modules\clothing\under\jobs\civilian.dm"
#include "code\modules\clothing\under\jobs\engineering.dm"
#include "code\modules\clothing\under\jobs\medsci.dm"
@@ -1107,6 +1113,7 @@
#include "code\modules\mob\living\carbon\metroid\emote.dm"
#include "code\modules\mob\living\carbon\metroid\examine.dm"
#include "code\modules\mob\living\carbon\metroid\hud.dm"
+#include "code\modules\mob\living\carbon\metroid\items.dm"
#include "code\modules\mob\living\carbon\metroid\life.dm"
#include "code\modules\mob\living\carbon\metroid\login.dm"
#include "code\modules\mob\living\carbon\metroid\metroid.dm"
@@ -1153,6 +1160,7 @@
#include "code\modules\mob\living\silicon\pai\recruit.dm"
#include "code\modules\mob\living\silicon\pai\say.dm"
#include "code\modules\mob\living\silicon\pai\software.dm"
+#include "code\modules\mob\living\silicon\pai\software_modules.dm"
#include "code\modules\mob\living\silicon\robot\analyzer.dm"
#include "code\modules\mob\living\silicon\robot\component.dm"
#include "code\modules\mob\living\silicon\robot\death.dm"
diff --git a/code/ATMOSPHERICS/components/unary/cold_sink.dm b/code/ATMOSPHERICS/components/unary/cold_sink.dm
index 766279a630..82d7d41b7b 100644
--- a/code/ATMOSPHERICS/components/unary/cold_sink.dm
+++ b/code/ATMOSPHERICS/components/unary/cold_sink.dm
@@ -7,52 +7,47 @@
icon = 'icons/obj/Cryogenic2.dmi'
icon_state = "freezer_0"
density = 1
-
- anchored = 1.0
-
- var/heatsink_temperature = T20C //the constant temperature resevoir into which the freezer pumps heat. Probably the hull of the station or something.
- var/internal_volume = 600 //L
-
+ anchored = 1
use_power = 0
- idle_power_usage = 5 //5 Watts for thermostat related circuitry
+ idle_power_usage = 5 // 5 Watts for thermostat related circuitry
- var/max_power_rating = 20000 //power rating when the usage is turned up to 100
+ var/heatsink_temperature = T20C // The constant temperature reservoir into which the freezer pumps heat. Probably the hull of the station or something.
+ var/internal_volume = 600 // L
+
+ var/max_power_rating = 20000 // Power rating when the usage is turned up to 100
var/power_setting = 100
- var/set_temperature = T20C //thermostat
+ var/set_temperature = T20C // Thermostat
var/cooling = 0
- var/opened = 0 //for deconstruction
/obj/machinery/atmospherics/unary/freezer/New()
..()
- air_contents.volume = internal_volume
initialize_directions = dir
-
component_parts = list()
component_parts += new /obj/item/weapon/circuitboard/unary_atmos/cooler(src)
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
-
- power_rating = max_power_rating * (power_setting/100)
+ component_parts += new /obj/item/stack/cable_coil(src, 2)
+ RefreshParts()
/obj/machinery/atmospherics/unary/freezer/initialize()
- if(node) return
+ if(node)
+ return
var/node_connect = dir
- for(var/obj/machinery/atmospherics/target in get_step(src,node_connect))
- if(target.initialize_directions & get_dir(target,src))
+ for(var/obj/machinery/atmospherics/target in get_step(src, node_connect))
+ if(target.initialize_directions & get_dir(target, src))
node = target
break
update_icon()
-
/obj/machinery/atmospherics/unary/freezer/update_icon()
- if(src.node)
- if(src.use_power && cooling)
+ if(node)
+ if(use_power && cooling)
icon_state = "freezer_1"
else
icon_state = "freezer"
@@ -61,10 +56,10 @@
return
/obj/machinery/atmospherics/unary/freezer/attack_ai(mob/user as mob)
- src.ui_interact(user)
+ ui_interact(user)
/obj/machinery/atmospherics/unary/freezer/attack_hand(mob/user as mob)
- src.ui_interact(user)
+ ui_interact(user)
/obj/machinery/atmospherics/unary/freezer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
// this is the data which will be sent to the ui
@@ -78,15 +73,15 @@
data["powerSetting"] = power_setting
var/temp_class = "good"
- if (air_contents.temperature > (T0C - 20))
+ if(air_contents.temperature > (T0C - 20))
temp_class = "bad"
- else if (air_contents.temperature < (T0C - 20) && air_contents.temperature > (T0C - 100))
+ else if(air_contents.temperature < (T0C - 20) && air_contents.temperature > (T0C - 100))
temp_class = "average"
data["gasTemperatureClass"] = temp_class
// update the ui if it exists, returns null if no ui is passed/found
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
- if (!ui)
+ if(!ui)
// the ui does not exist, so we'll create a new() one
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
ui = new(user, src, ui_key, "freezer.tmpl", "Gas Cooling System", 440, 300)
@@ -98,30 +93,31 @@
ui.set_auto_update(1)
/obj/machinery/atmospherics/unary/freezer/Topic(href, href_list)
- if (href_list["toggleStatus"])
- src.use_power = !src.use_power
+ if(href_list["toggleStatus"])
+ use_power = !use_power
update_icon()
if(href_list["temp"])
var/amount = text2num(href_list["temp"])
if(amount > 0)
- src.set_temperature = min(src.set_temperature+amount, 1000)
+ set_temperature = min(set_temperature + amount, 1000)
else
- src.set_temperature = max(src.set_temperature+amount, 0)
+ set_temperature = max(set_temperature + amount, 0)
if(href_list["setPower"]) //setting power to 0 is redundant anyways
var/new_setting = between(0, text2num(href_list["setPower"]), 100)
set_power_level(new_setting)
- src.add_fingerprint(usr)
+ add_fingerprint(usr)
return 1
/obj/machinery/atmospherics/unary/freezer/process()
..()
+
if(stat & (NOPOWER|BROKEN) || !use_power)
cooling = 0
update_icon()
return
- if (network && air_contents.temperature > set_temperature)
+ if(network && air_contents.temperature > set_temperature)
cooling = 1
var/heat_transfer = max( -air_contents.get_thermal_energy_change(set_temperature - 5), 0 )
@@ -132,7 +128,7 @@
heat_transfer = min(heat_transfer, cop * power_rating) //limit heat transfer by available power
var/removed = -air_contents.add_thermal_energy(-heat_transfer) //remove the heat
- if (debug)
+ if(debug)
visible_message("[src]: Removing [removed] W.")
use_power(power_rating)
@@ -147,49 +143,37 @@
/obj/machinery/atmospherics/unary/freezer/RefreshParts()
..()
var/cap_rating = 0
- var/cap_count = 0
var/manip_rating = 0
- var/manip_count = 0
var/bin_rating = 0
- var/bin_count = 0
for(var/obj/item/weapon/stock_parts/P in component_parts)
if(istype(P, /obj/item/weapon/stock_parts/capacitor))
cap_rating += P.rating
- cap_count++
if(istype(P, /obj/item/weapon/stock_parts/manipulator))
manip_rating += P.rating
- manip_count++
if(istype(P, /obj/item/weapon/stock_parts/matter_bin))
bin_rating += P.rating
- bin_count++
- cap_rating /= cap_count
- bin_rating /= bin_count
- manip_rating /= manip_count
- power_rating = initial(power_rating)*cap_rating //more powerful
- heatsink_temperature = initial(heatsink_temperature)/((manip_rating+bin_rating)/2) //more efficient
- air_contents.volume = max(initial(internal_volume) - 200, 0) + 200*bin_rating
+ power_rating = initial(power_rating) * cap_rating / 2 //more powerful
+ heatsink_temperature = initial(heatsink_temperature) / ((manip_rating + bin_rating) / 2) //more efficient
+ air_contents.volume = max(initial(internal_volume) - 200, 0) + 200 * bin_rating
set_power_level(power_setting)
/obj/machinery/atmospherics/unary/freezer/proc/set_power_level(var/new_power_setting)
power_setting = new_power_setting
power_rating = max_power_rating * (power_setting/100)
-//dismantling code. copied from autolathe
/obj/machinery/atmospherics/unary/freezer/attackby(var/obj/item/O as obj, var/mob/user as mob)
- if(istype(O, /obj/item/weapon/screwdriver))
- opened = !opened
- user << "You [opened ? "open" : "close"] the maintenance hatch of [src]."
+ if(default_deconstruction_screwdriver(user, O))
return
-
- if (opened && istype(O, /obj/item/weapon/crowbar))
- dismantle()
+ if(default_deconstruction_crowbar(user, O))
+ return
+ if(default_part_replacement(user, O))
return
..()
/obj/machinery/atmospherics/unary/freezer/examine(mob/user)
..(user)
- if (opened)
+ if(panel_open)
user << "The maintenance hatch is open."
diff --git a/code/ATMOSPHERICS/components/unary/heat_source.dm b/code/ATMOSPHERICS/components/unary/heat_source.dm
index 891a19cc74..829f06f420 100644
--- a/code/ATMOSPHERICS/components/unary/heat_source.dm
+++ b/code/ATMOSPHERICS/components/unary/heat_source.dm
@@ -7,25 +7,21 @@
icon = 'icons/obj/Cryogenic2.dmi'
icon_state = "heater_0"
density = 1
-
- anchored = 1.0
-
- var/set_temperature = T20C //thermostat
- var/max_temperature = T20C + 680
- var/internal_volume = 600 //L
-
+ anchored = 1
use_power = 0
idle_power_usage = 5 //5 Watts for thermostat related circuitry
+ var/max_temperature = T20C + 680
+ var/internal_volume = 600 //L
+
var/max_power_rating = 20000 //power rating when the usage is turned up to 100
var/power_setting = 100
+ var/set_temperature = T20C //thermostat
var/heating = 0 //mainly for icon updates
- var/opened = 0 //for deconstruction
/obj/machinery/atmospherics/unary/heater/New()
..()
- air_contents.volume = internal_volume
initialize_directions = dir
component_parts = list()
@@ -33,16 +29,18 @@
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
+ component_parts += new /obj/item/stack/cable_coil(src, 5)
- power_rating = max_power_rating * (power_setting/100)
+ RefreshParts()
/obj/machinery/atmospherics/unary/heater/initialize()
- if(node) return
+ if(node)
+ return
var/node_connect = dir
- for(var/obj/machinery/atmospherics/target in get_step(src,node_connect))
- if(target.initialize_directions & get_dir(target,src))
+ for(var/obj/machinery/atmospherics/target in get_step(src, node_connect))
+ if(target.initialize_directions & get_dir(target, src))
node = target
break
@@ -50,8 +48,8 @@
/obj/machinery/atmospherics/unary/heater/update_icon()
- if(src.node)
- if(src.use_power && src.heating)
+ if(node)
+ if(use_power && heating)
icon_state = "heater_1"
else
icon_state = "heater"
@@ -68,7 +66,7 @@
update_icon()
return
- if (network && air_contents.total_moles && air_contents.temperature < set_temperature)
+ if(network && air_contents.total_moles && air_contents.temperature < set_temperature)
air_contents.add_thermal_energy(power_rating * HEATER_PERF_MULT)
use_power(power_rating)
@@ -80,10 +78,10 @@
update_icon()
/obj/machinery/atmospherics/unary/heater/attack_ai(mob/user as mob)
- src.ui_interact(user)
+ ui_interact(user)
/obj/machinery/atmospherics/unary/heater/attack_hand(mob/user as mob)
- src.ui_interact(user)
+ ui_interact(user)
/obj/machinery/atmospherics/unary/heater/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
// this is the data which will be sent to the ui
@@ -97,13 +95,13 @@
data["powerSetting"] = power_setting
var/temp_class = "normal"
- if (air_contents.temperature > (T20C+40))
+ if(air_contents.temperature > (T20C+40))
temp_class = "bad"
data["gasTemperatureClass"] = temp_class
// update the ui if it exists, returns null if no ui is passed/found
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
- if (!ui)
+ if(!ui)
// the ui does not exist, so we'll create a new() one
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
ui = new(user, src, ui_key, "freezer.tmpl", "Gas Heating System", 440, 300)
@@ -115,63 +113,54 @@
ui.set_auto_update(1)
/obj/machinery/atmospherics/unary/heater/Topic(href, href_list)
- if (href_list["toggleStatus"])
- src.use_power = !src.use_power
+ if(href_list["toggleStatus"])
+ use_power = !use_power
update_icon()
if(href_list["temp"])
var/amount = text2num(href_list["temp"])
if(amount > 0)
- src.set_temperature = min(src.set_temperature+amount, max_temperature)
+ set_temperature = min(set_temperature + amount, max_temperature)
else
- src.set_temperature = max(src.set_temperature+amount, 0)
+ set_temperature = max(set_temperature + amount, 0)
if(href_list["setPower"]) //setting power to 0 is redundant anyways
var/new_setting = between(0, text2num(href_list["setPower"]), 100)
set_power_level(new_setting)
- src.add_fingerprint(usr)
+ add_fingerprint(usr)
return 1
//upgrading parts
/obj/machinery/atmospherics/unary/heater/RefreshParts()
..()
-
var/cap_rating = 0
- var/cap_count = 0
var/bin_rating = 0
- var/bin_count = 0
+
for(var/obj/item/weapon/stock_parts/P in component_parts)
if(istype(P, /obj/item/weapon/stock_parts/capacitor))
cap_rating += P.rating
- cap_count++
if(istype(P, /obj/item/weapon/stock_parts/matter_bin))
bin_rating += P.rating
- bin_count++
- cap_rating /= cap_count
- bin_rating /= bin_count
- max_power_rating = initial(max_power_rating)*cap_rating
- max_temperature = max(initial(max_temperature) - T20C, 0)*((bin_rating*2 + cap_rating)/3) + T20C
- air_contents.volume = max(initial(internal_volume) - 200, 0) + 200*bin_rating
+ max_power_rating = initial(max_power_rating) * cap_rating / 2
+ max_temperature = max(initial(max_temperature) - T20C, 0) * ((bin_rating * 4 + cap_rating) / 5) + T20C
+ air_contents.volume = max(initial(internal_volume) - 200, 0) + 200 * bin_rating
set_power_level(power_setting)
/obj/machinery/atmospherics/unary/heater/proc/set_power_level(var/new_power_setting)
power_setting = new_power_setting
power_rating = max_power_rating * (power_setting/100)
-//dismantling code. copied from autolathe
/obj/machinery/atmospherics/unary/heater/attackby(var/obj/item/O as obj, var/mob/user as mob)
- if(istype(O, /obj/item/weapon/screwdriver))
- opened = !opened
- user << "You [opened ? "open" : "close"] the maintenance hatch of [src]."
+ if(default_deconstruction_screwdriver(user, O))
return
-
- if (opened && istype(O, /obj/item/weapon/crowbar))
- dismantle()
+ if(default_deconstruction_crowbar(user, O))
+ return
+ if(default_part_replacement(user, O))
return
..()
/obj/machinery/atmospherics/unary/heater/examine(mob/user)
..(user)
- if (opened)
+ if(panel_open)
user << "The maintenance hatch is open."
diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm
index ab37fa4867..3f00db9ce0 100644
--- a/code/_onclick/hud/hud.dm
+++ b/code/_onclick/hud/hud.dm
@@ -241,6 +241,8 @@ datum/hud/New(mob/owner)
brain_hud(ui_style)
else if(isalien(mymob))
larva_hud()
+ else if(isslime(mymob))
+ slime_hud()
else if(isAI(mymob))
ai_hud()
else if(isrobot(mymob))
diff --git a/code/_onclick/hud/other_mobs.dm b/code/_onclick/hud/other_mobs.dm
index cd19e78d7e..cd5a859715 100644
--- a/code/_onclick/hud/other_mobs.dm
+++ b/code/_onclick/hud/other_mobs.dm
@@ -33,3 +33,71 @@
mymob.client.screen = null
mymob.client.screen += list(blobpwrdisplay, blobhealthdisplay)
+
+/datum/hud/proc/slime_hud(ui_style = 'icons/mob/screen1_Midnight.dmi')
+
+ src.adding = list()
+
+ var/obj/screen/using
+
+ using = new /obj/screen()
+ using.name = "act_intent"
+ using.set_dir(SOUTHWEST)
+ using.icon = ui_style
+ using.icon_state = "intent_"+mymob.a_intent
+ using.screen_loc = ui_zonesel
+ using.layer = 20
+ src.adding += using
+ action_intent = using
+
+ //intent small hud objects
+ var/icon/ico
+
+ ico = new(ui_style, "black")
+ ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1)
+ ico.DrawBox(rgb(255,255,255,1),1,ico.Height()/2,ico.Width()/2,ico.Height())
+ using = new /obj/screen( src )
+ using.name = "help"
+ using.icon = ico
+ using.screen_loc = ui_zonesel
+ using.layer = 21
+ src.adding += using
+ help_intent = using
+
+ ico = new(ui_style, "black")
+ ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1)
+ ico.DrawBox(rgb(255,255,255,1),ico.Width()/2,ico.Height()/2,ico.Width(),ico.Height())
+ using = new /obj/screen( src )
+ using.name = "disarm"
+ using.icon = ico
+ using.screen_loc = ui_zonesel
+ using.layer = 21
+ src.adding += using
+ disarm_intent = using
+
+ ico = new(ui_style, "black")
+ ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1)
+ ico.DrawBox(rgb(255,255,255,1),ico.Width()/2,1,ico.Width(),ico.Height()/2)
+ using = new /obj/screen( src )
+ using.name = "grab"
+ using.icon = ico
+ using.screen_loc = ui_zonesel
+ using.layer = 21
+ src.adding += using
+ grab_intent = using
+
+ ico = new(ui_style, "black")
+ ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1)
+ ico.DrawBox(rgb(255,255,255,1),1,1,ico.Width()/2,ico.Height()/2)
+ using = new /obj/screen( src )
+ using.name = "harm"
+ using.icon = ico
+ using.screen_loc = ui_zonesel
+ using.layer = 21
+ src.adding += using
+ hurt_intent = using
+
+ mymob.client.screen = null
+ mymob.client.screen += src.adding
+
+ return
\ No newline at end of file
diff --git a/code/_onclick/other_mobs.dm b/code/_onclick/other_mobs.dm
index 479e097251..496553558d 100644
--- a/code/_onclick/other_mobs.dm
+++ b/code/_onclick/other_mobs.dm
@@ -120,45 +120,61 @@
// Eating
if(Victim)
+ if (Victim == A)
+ Feedstop()
return
- // Basic attack.
- A.attack_generic(src, (is_adult ? rand(20,40) : rand(5,25)), "glomped")
-
- // Handle mob shocks.
var/mob/living/M = A
- if(istype(M) && powerlevel > 0 && !istype(A,/mob/living/carbon/slime))
+ if (istype(M))
- if(ishuman(M))
- var/mob/living/carbon/human/H = M
- if(H.species.flags & IS_SYNTHETIC || (H.species.siemens_coefficient<0.5))
- return
+ switch(src.a_intent)
+ if ("help") // We just poke the other
+ M.visible_message("[src] gently pokes [M]!", "[src] gently pokes you!")
+ if ("disarm") // We stun the target, with the intention to feed
+ var/stunprob = 1
+ var/power = max(0, min(10, (powerlevel + rand(0, 3))))
+ if (powerlevel > 0 && !istype(A, /mob/living/carbon/slime))
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ if(H.species.flags & IS_SYNTHETIC)
+ return
+ stunprob *= H.species.siemens_coefficient
- var/power = max(0,min(10,(powerlevel+rand(0,3))))
- var/stunprob = 10
- switch(power*10)
- if(1 to 2) stunprob = 20
- if(3 to 4) stunprob = 30
- if(5 to 6) stunprob = 40
- if(7 to 8) stunprob = 60
- if(9) stunprob = 70
- if(10) stunprob = 95
+ switch(power * 10)
+ if(0) stunprob *= 10
+ if(1 to 2) stunprob *= 20
+ if(3 to 4) stunprob *= 30
+ if(5 to 6) stunprob *= 40
+ if(7 to 8) stunprob *= 60
+ if(9) stunprob *= 70
+ if(10) stunprob *= 95
- if(prob(stunprob))
- powerlevel = max(0,powerlevel-3)
- src.visible_message("\red The [name] has shocked [M]!")
- M.Weaken(power)
- M.Stun(power)
- if (M.stuttering < power) M.stuttering = power
+ if(prob(stunprob))
+ powerlevel = max(0, powerlevel-3)
+ M.visible_message("[src] has shocked [M]!", "[src] has shocked you!")
+ M.Weaken(power)
+ M.Stun(power)
+ M.stuttering = max(M.stuttering, power)
- var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
- s.set_up(5, 1, M)
- s.start()
+ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
+ s.set_up(5, 1, M)
+ s.start()
- if(prob(stunprob) && powerlevel >= 8)
- M.adjustFireLoss(powerlevel * rand(6,10))
- M.updatehealth()
+ if(prob(stunprob) && powerlevel >= 8)
+ M.adjustFireLoss(powerlevel * rand(6,10))
+ else if(prob(40))
+ M.visible_message("[src] has pounced at [M]!", "[src] has pounced at you!")
+ M.Weaken(power)
+ else
+ M.visible_message("[src] has tried to pounce at [M]!", "[src] has tried to pounce at you!")
+ M.updatehealth()
+ if ("grab") // We feed
+ Wrap(M)
+ if ("hurt") // Attacking
+ A.attack_generic(src, (is_adult ? rand(20,40) : rand(5,25)), "glomped")
+ else
+ A.attack_generic(src, (is_adult ? rand(20,40) : rand(5,25)), "glomped") // Basic attack.
/*
New Players:
Have no reason to click on anything at all.
diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm
index bcb3c7c7d1..3320a8c354 100644
--- a/code/datums/supplypacks.dm
+++ b/code/datums/supplypacks.dm
@@ -732,9 +732,6 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/obj/item/weapon/shield/riot,
/obj/item/weapon/shield/riot,
/obj/item/weapon/shield/riot,
- /obj/item/weapon/storage/box/flashbangs,
- /obj/item/weapon/storage/box/flashbangs,
- /obj/item/weapon/storage/box/flashbangs,
/obj/item/weapon/handcuffs,
/obj/item/weapon/handcuffs,
/obj/item/weapon/handcuffs,
@@ -743,13 +740,26 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/obj/item/clothing/head/helmet/riot,
/obj/item/clothing/suit/armor/riot,
/obj/item/clothing/head/helmet/riot,
- /obj/item/clothing/suit/armor/riot)
+ /obj/item/clothing/suit/armor/riot,
+ /obj/item/weapon/storage/box/flashbangs,
+ /obj/item/weapon/storage/box/beanbags,
+ /obj/item/weapon/storage/box/handcuffs)
cost = 60
containertype = /obj/structure/closet/crate/secure
containername = "Riot gear crate"
access = access_armory
group = "Security"
+/datum/supply_packs/energyweapons
+ name = "Energy weapons crate"
+ contains = list(/obj/item/weapon/gun/energy/laser,
+ /obj/item/weapon/gun/energy/laser,
+ /obj/item/weapon/gun/energy/gun)
+ cost = 50
+ containertype = /obj/structure/closet/crate/secure
+ containername = "energy weapons crate"
+ access = access_armory
+ group = "Security"
/datum/supply_packs/ballistic
name = "Ballistic gear crate"
@@ -776,13 +786,14 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
group = "Security"
/datum/supply_packs/shotgunammo
- name = "Shotgun shells"
+ name = "Ballistic ammunition crate"
contains = list(/obj/item/weapon/storage/box/shotgunammo,
/obj/item/weapon/storage/box/shotgunammo,
- /obj/item/weapon/storage/box/shotgunammo)
+ /obj/item/weapon/storage/box/shotgunshells,
+ /obj/item/weapon/storage/box/shotgunshells)
cost = 60
containertype = /obj/structure/closet/crate/secure
- containername = "Shotgun shells"
+ containername = "ballistic ammunition crate"
access = access_armory
group = "Security"
@@ -888,10 +899,9 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/obj/item/weapon/reagent_containers/glass/paint/green,
/obj/item/weapon/reagent_containers/glass/paint/blue,
/obj/item/weapon/reagent_containers/glass/paint/yellow,
- /obj/item/weapon/reagent_containers/glass/paint/violet,
+ /obj/item/weapon/reagent_containers/glass/paint/purple,
/obj/item/weapon/reagent_containers/glass/paint/black,
/obj/item/weapon/reagent_containers/glass/paint/white,
- /obj/item/weapon/reagent_containers/glass/paint/remover,
/obj/item/weapon/contraband/poster,
/obj/item/weapon/wrapping_paper,
/obj/item/weapon/wrapping_paper,
@@ -1385,10 +1395,10 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/datum/supply_packs/randomised/webbing
name = "Webbing crate"
num_contained = 1
- contains = list(/obj/item/clothing/tie/holster,
- /obj/item/clothing/tie/storage/brown_vest,
- /obj/item/clothing/tie/storage/webbing,
- /obj/item/clothing/tie/storage)
+ contains = list(/obj/item/clothing/accessory/holster,
+ /obj/item/clothing/accessory/storage/brown_vest,
+ /obj/item/clothing/accessory/storage/webbing,
+ /obj/item/clothing/accessory/storage)
cost = 15
containertype = /obj/structure/closet/crate
containername = "Webbing crate"
diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm
index 10f92f521d..281e4566d2 100644
--- a/code/defines/obj/weapon.dm
+++ b/code/defines/obj/weapon.dm
@@ -384,6 +384,22 @@
///////////////////////////////////////Stock Parts /////////////////////////////////
+/obj/item/weapon/storage/part_replacer
+ name = "rapid part exchange device"
+ desc = "Special mechanical module made to store, sort, and apply standard machine parts."
+ icon_state = "RPED"
+ item_state = "RPED"
+ w_class = 5
+ can_hold = list("/obj/item/weapon/stock_parts")
+ storage_slots = 50
+ use_to_pickup = 1
+ allow_quick_gather = 1
+ allow_quick_empty = 1
+ collection_mode = 1
+ display_contents_with_number = 1
+ max_w_class = 3
+ max_combined_w_class = 100
+
/obj/item/weapon/stock_parts
name = "stock part"
desc = "What?"
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index df288f2cc4..bd0c9cdb54 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -409,6 +409,7 @@ its easier to just keep the beam vertical.
/atom/proc/clean_blood()
+ src.color = initial(src.color) //paint
src.germ_level = 0
if(istype(blood_DNA, /list))
del(blood_DNA)
diff --git a/code/game/gamemodes/meteor/meteors.dm b/code/game/gamemodes/meteor/meteors.dm
index fce27f393c..1edb533daa 100644
--- a/code/game/gamemodes/meteor/meteors.dm
+++ b/code/game/gamemodes/meteor/meteors.dm
@@ -85,6 +85,9 @@
density = 1
anchored = 1.0
var/hits = 1
+ var/detonation_chance = 15
+ var/power = 4
+ var/power_step = 1
var/dest
pass_flags = PASSTABLE
@@ -92,6 +95,7 @@
name = "small meteor"
icon_state = "smallf"
pass_flags = PASSTABLE | PASSGRILLE
+ power = 2
/obj/effect/meteor/Bump(atom/A)
spawn(0)
@@ -105,8 +109,8 @@
//Changing emitter and generator ex_act would result in them being bomb and C4 proof.
if(!istype(A,/obj/machinery/power/emitter) && \
!istype(A,/obj/machinery/field_generator) && \
- prob(15))
- explosion(src.loc, 4, 5, 6, 7, 0)
+ prob(detonation_chance))
+ explosion(loc, power, power + power_step, power + power_step * 2, power + power_step * 3, 0)
del(src)
return
@@ -120,6 +124,7 @@
/obj/effect/meteor/big
name = "big meteor"
hits = 5
+ power = 1
ex_act(severity)
return
@@ -143,8 +148,8 @@
explosion(src.loc, 0, 1, 2, 3, 0)
if (--src.hits <= 0)
- if(prob(15) && !istype(A, /obj/structure/grille))
- explosion(src.loc, 1, 2, 3, 4, 0)
+ if(prob(detonation_chance) && !istype(A, /obj/structure/grille))
+ explosion(loc, power, power + power_step, power + power_step * 2, power + power_step * 3, 0)
del(src)
return
diff --git a/code/game/jobs/job/captain.dm b/code/game/jobs/job/captain.dm
index a43056fa96..06513c05f9 100644
--- a/code/game/jobs/job/captain.dm
+++ b/code/game/jobs/job/captain.dm
@@ -24,7 +24,7 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1)
H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H.back), slot_in_backpack)
var/obj/item/clothing/under/U = new /obj/item/clothing/under/rank/captain(H)
if(H.age>49)
- U.hastie = new /obj/item/clothing/tie/medal/gold/captain(U)
+ U.accessories += new /obj/item/clothing/accessory/medal/gold/captain(U)
H.equip_to_slot_or_del(U, slot_w_uniform)
H.equip_to_slot_or_del(new /obj/item/device/pda/captain(H), slot_belt)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(H), slot_shoes)
diff --git a/code/game/jobs/job/medical.dm b/code/game/jobs/job/medical.dm
index a63363f779..1370291152 100644
--- a/code/game/jobs/job/medical.dm
+++ b/code/game/jobs/job/medical.dm
@@ -196,3 +196,44 @@
else
H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H.back), slot_in_backpack)
H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/toggle/labcoat(H), slot_wear_suit)
+
+
+/datum/job/Paramedic
+ title = "Paramedic"
+ flag = PARAMEDIC
+ department_flag = MEDSCI
+ faction = "Station"
+ total_positions = 2
+ spawn_positions = 2
+ supervisors = "the chief medical officer"
+ selection_color = "#ffeef0"
+ access = list(access_medical, access_morgue, access_surgery, access_chemistry, access_virology, access_eva, access_maint_tunnels, access_external_airlocks, access_psychiatrist)
+ minimal_access = list(access_medical, access_morgue, access_eva, access_maint_tunnels, access_external_airlocks)
+ alt_titles = list("Emergency Medical Technician")
+
+ equip(var/mob/living/carbon/human/H)
+ if(!H) return 0
+ H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_med(H), slot_l_ear)
+ H.equip_to_slot_or_del(new /obj/item/clothing/shoes/jackboots(H), slot_shoes)
+ H.equip_to_slot_or_del(new /obj/item/weapon/storage/firstaid/adv(H), slot_l_hand)
+ switch(H.backbag)
+ if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/medic(H), slot_back)
+ if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_med(H), slot_back)
+ if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back)
+ if (H.mind.role_alt_title)
+ switch(H.mind.role_alt_title)
+ if("Emergency Medical Technician")
+ H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/medical/fluff/short(H), slot_w_uniform)
+ H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/toggle/fr_jacket(H), slot_wear_suit)
+ if("Paramedic")
+ H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/medical/black(H), slot_w_uniform)
+ H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/toggle/fr_jacket(H), slot_wear_suit)
+ else
+ H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/medical(H), slot_w_uniform)
+ H.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/medical/emt(H), slot_belt)
+ H.equip_to_slot_or_del(new /obj/item/device/pda/medical(H), slot_l_store)
+ if(H.backbag == 1)
+ H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/engineer(H), slot_r_hand)
+ else
+ H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/engineer(H.back), slot_in_backpack)
+ return 1
diff --git a/code/game/jobs/jobs.dm b/code/game/jobs/jobs.dm
index a90f3ad716..e1c42254a6 100644
--- a/code/game/jobs/jobs.dm
+++ b/code/game/jobs/jobs.dm
@@ -25,6 +25,7 @@ var/const/VIROLOGIST =(1<<6)
var/const/PSYCHIATRIST =(1<<7)
var/const/ROBOTICIST =(1<<8)
var/const/XENOBIOLOGIST =(1<<9)
+var/const/PARAMEDIC =(1<<10)
var/const/CIVILIAN =(1<<2)
diff --git a/code/game/machinery/atmoalter/canister.dm b/code/game/machinery/atmoalter/canister.dm
index 32e1d77f44..12ad5d1c3b 100644
--- a/code/game/machinery/atmoalter/canister.dm
+++ b/code/game/machinery/atmoalter/canister.dm
@@ -224,6 +224,9 @@ update_flag
return
/obj/machinery/portable_atmospherics/canister/bullet_act(var/obj/item/projectile/Proj)
+ if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN))
+ return
+
if(Proj.damage)
src.health -= round(Proj.damage / 2)
healthcheck()
diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm
index 7b44e443c4..5361bea23a 100644
--- a/code/game/machinery/autolathe.dm
+++ b/code/game/machinery/autolathe.dm
@@ -13,14 +13,30 @@
var/list/storage_capacity = list("metal" = 0, "glass" = 0)
var/show_category = "All"
- var/panel_open = 0
var/hacked = 0
var/disabled = 0
var/shocked = 0
var/busy = 0
+ var/mat_efficiency = 1
+ var/build_time = 50
+
var/datum/wires/autolathe/wires = null
+/obj/machinery/autolathe/New()
+
+ ..()
+ wires = new(src)
+ //Create parts for lathe.
+ component_parts = list()
+ component_parts += new /obj/item/weapon/circuitboard/autolathe(src)
+ component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
+ component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
+ component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
+ component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
+ component_parts += new /obj/item/weapon/stock_parts/console_screen(src)
+ RefreshParts()
+
/obj/machinery/autolathe/proc/update_recipe_list()
if(!machine_recipes)
machine_recipes = autolathe_recipes
@@ -33,8 +49,8 @@
user << "\The [src] is disabled!"
return
- if (shocked)
- shock(user,50)
+ if(shocked)
+ shock(user, 50)
var/dat = "
Autolathe Control Panel
"
@@ -65,16 +81,16 @@
else
//Make sure it's buildable and list requires resources.
for(var/material in R.resources)
- var/sheets = round(stored_material[material]/R.resources[material])
+ var/sheets = round(stored_material[material]/round(R.resources[material]*mat_efficiency))
if(isnull(max_sheets) || max_sheets > sheets)
max_sheets = sheets
- if(!isnull(stored_material[material]) && stored_material[material] < R.resources[material])
+ if(!isnull(stored_material[material]) && stored_material[material] < round(R.resources[material]*mat_efficiency))
can_make = 0
if(!comma)
comma = 1
else
material_string += ", "
- material_string += "[R.resources[material]] [material]"
+ material_string += "[round(R.resources[material] * mat_efficiency)] [material]"
material_string += ".
"
//Build list of multipliers for sheets.
if(R.is_stack)
@@ -99,31 +115,27 @@
/obj/machinery/autolathe/attackby(var/obj/item/O as obj, var/mob/user as mob)
- if (stat)
- return
-
- if (busy)
+ if(busy)
user << "\The [src] is busy. Please wait for completion of previous operation."
return
- if(istype(O, /obj/item/weapon/screwdriver))
- panel_open = !panel_open
- icon_state = (panel_open ? "autolathe_t": "autolathe")
- user << "You [panel_open ? "open" : "close"] the maintenance hatch of [src]."
+ if(default_deconstruction_screwdriver(user, O))
updateUsrDialog()
return
+ if(default_deconstruction_crowbar(user, O))
+ return
+ if(default_part_replacement(user, O))
+ return
- if (panel_open)
+ if(stat)
+ return
+
+ if(panel_open)
//Don't eat multitools or wirecutters used on an open lathe.
if(istype(O, /obj/item/device/multitool) || istype(O, /obj/item/weapon/wirecutters))
attack_hand(user)
return
- //Dismantle the frame.
- if(istype(O, /obj/item/weapon/crowbar))
- dismantle()
- return
-
if(O.loc != user && !(istype(O,/obj/item/stack)))
return 0
@@ -170,11 +182,11 @@
else
user << "You fill \the [src] with \the [eating]."
- flick("autolathe_o",src) // Plays metal insertion animation. Work out a good way to work out a fitting animation. ~Z
+ flick("autolathe_o", src) // Plays metal insertion animation. Work out a good way to work out a fitting animation. ~Z
if(istype(eating,/obj/item/stack))
var/obj/item/stack/stack = eating
- stack.use(max(1,round(total_used/mass_per_sheet))) // Always use at least 1 to prevent infinite materials.
+ stack.use(max(1, round(total_used/mass_per_sheet))) // Always use at least 1 to prevent infinite materials.
else
user.drop_item(O)
del(O)
@@ -227,18 +239,18 @@
//Check if we still have the materials.
for(var/material in making.resources)
if(!isnull(stored_material[material]))
- if(stored_material[material] < (making.resources[material]*multiplier))
+ if(stored_material[material] < round(making.resources[material] * mat_efficiency) * multiplier)
return
//Consume materials.
for(var/material in making.resources)
if(!isnull(stored_material[material]))
- stored_material[material] = max(0,stored_material[material]-(making.resources[material]*multiplier))
+ stored_material[material] = max(0, stored_material[material] - round(making.resources[material] * mat_efficiency) * multiplier)
//Fancy autolathe animation.
- flick("autolathe_n",src)
+ flick("autolathe_n", src)
- sleep(50)
+ sleep(build_time)
busy = 0
@@ -247,39 +259,31 @@
//Create the desired item.
var/obj/item/I = new making.path(get_step(loc, get_dir(src,usr)))
- if(multiplier>1 && istype(I,/obj/item/stack))
+ if(multiplier > 1 && istype(I, /obj/item/stack))
var/obj/item/stack/S = I
S.amount = multiplier
updateUsrDialog()
-
-/obj/machinery/autolathe/New()
-
- ..()
- wires = new(src)
- //Create parts for lathe.
- component_parts = list()
- component_parts += new /obj/item/weapon/circuitboard/autolathe(src)
- component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
- component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
- component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
- component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
- component_parts += new /obj/item/weapon/stock_parts/console_screen(src)
- RefreshParts()
+/obj/machinery/autolathe/update_icon()
+ icon_state = (panel_open ? "autolathe_t" : "autolathe")
//Updates overall lathe storage size.
/obj/machinery/autolathe/RefreshParts()
..()
- var/tot_rating = 0
+ var/mb_rating = 0
+ var/man_rating = 0
for(var/obj/item/weapon/stock_parts/matter_bin/MB in component_parts)
- tot_rating += MB.rating
+ mb_rating += MB.rating
+ for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts)
+ man_rating += M.rating
- storage_capacity["metal"] = tot_rating * 25000
- storage_capacity["glass"] = tot_rating * 12500
+ storage_capacity["metal"] = mb_rating * 25000
+ storage_capacity["glass"] = mb_rating * 12500
+ build_time = 50 / man_rating
+ mat_efficiency = 1.1 - man_rating * 0.1// Normally, price is 1.25 the amount of material, so this shouldn't go higher than 0.8. Maximum rating of parts is 3
/obj/machinery/autolathe/dismantle()
- ..()
var/list/sheets = list("metal" = /obj/item/stack/sheet/metal, "glass" = /obj/item/stack/sheet/glass)
for(var/mat in stored_material)
@@ -288,3 +292,4 @@
if(stored_material[mat] > S.perunit)
S.amount = round(stored_material[mat] / S.perunit)
S.loc = loc
+ ..()
diff --git a/code/game/machinery/autolathe_datums.dm b/code/game/machinery/autolathe_datums.dm
index 996daa2d10..f13c3dc634 100644
--- a/code/game/machinery/autolathe_datums.dm
+++ b/code/game/machinery/autolathe_datums.dm
@@ -15,7 +15,7 @@
if(I.matter && !recipe.resources) //This can be overidden in the datums.
recipe.resources = list()
for(var/material in I.matter)
- recipe.resources[material] = round(I.matter[material]*1.25) // More expensive to produce than they are to recycle.
+ recipe.resources[material] = I.matter[material]*1.25 // More expensive to produce than they are to recycle.
del(I)
/datum/autolathe/recipe
@@ -202,7 +202,7 @@
category = "Medical"
/datum/autolathe/recipe/shotgun_blanks
- name = "ammunition (shotgun, blanks)"
+ name = "ammunition (shotgun, blank)"
path = /obj/item/ammo_casing/shotgun/blank
category = "Arms and Ammunition"
@@ -211,11 +211,21 @@
path = /obj/item/ammo_casing/shotgun/beanbag
category = "Arms and Ammunition"
+/datum/autolathe/recipe/shotgun_flash
+ name = "ammunition (shotgun, flash)"
+ path = /obj/item/ammo_casing/shotgun/flash
+ category = "Arms and Ammunition"
+
/datum/autolathe/recipe/magazine_rubber
name = "ammunition (rubber)"
path = /obj/item/ammo_magazine/c45r
category = "Arms and Ammunition"
+/datum/autolathe/recipe/magazine_flash
+ name = "ammunition (flash)"
+ path = /obj/item/ammo_magazine/c45f
+ category = "Arms and Ammunition"
+
/datum/autolathe/recipe/consolescreen
name = "console screen"
path = /obj/item/weapon/stock_parts/console_screen
@@ -285,14 +295,14 @@
category = "Arms and Ammunition"
/datum/autolathe/recipe/shotgun
- name = "ammunition (shell, shotgun)"
+ name = "ammunition (slug, shotgun)"
path = /obj/item/ammo_casing/shotgun
hidden = 1
category = "Arms and Ammunition"
-/datum/autolathe/recipe/shotgun_dart
- name = "ammunition (dart, shotgun)"
- path = /obj/item/ammo_casing/shotgun/dart
+/datum/autolathe/recipe/shotgun_pellet
+ name = "ammunition (shell, shotgun)"
+ path = /obj/item/ammo_casing/shotgun/pellet
hidden = 1
category = "Arms and Ammunition"
diff --git a/code/game/machinery/biogenerator.dm b/code/game/machinery/biogenerator.dm
index 263f797a95..4afd4f0e44 100644
--- a/code/game/machinery/biogenerator.dm
+++ b/code/game/machinery/biogenerator.dm
@@ -11,66 +11,80 @@
var/obj/item/weapon/reagent_containers/glass/beaker = null
var/points = 0
var/menustat = "menu"
+ var/build_eff = 1
+ var/eat_eff = 1
- New()
- ..()
- var/datum/reagents/R = new/datum/reagents(1000)
- reagents = R
- R.my_atom = src
- beaker = new /obj/item/weapon/reagent_containers/glass/beaker/large(src)
+/obj/machinery/biogenerator/New()
+ ..()
+ var/datum/reagents/R = new/datum/reagents(1000)
+ reagents = R
+ R.my_atom = src
+ beaker = new /obj/item/weapon/reagent_containers/glass/bottle(src)
- on_reagent_change() //When the reagents change, change the icon as well.
- update_icon()
+ component_parts = list()
+ component_parts += new /obj/item/weapon/circuitboard/biogenerator(src)
+ component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
+ component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
+ RefreshParts()
+
+/obj/machinery/biogenerator/on_reagent_change() //When the reagents change, change the icon as well.
update_icon()
- if(!src.beaker)
- icon_state = "biogen-empty"
- else if(!src.processing)
- icon_state = "biogen-stand"
- else
- icon_state = "biogen-work"
- return
+
+/obj/machinery/biogenerator/update_icon()
+ if(!beaker)
+ icon_state = "biogen-empty"
+ else if(!processing)
+ icon_state = "biogen-stand"
+ else
+ icon_state = "biogen-work"
+ return
/obj/machinery/biogenerator/attackby(var/obj/item/O as obj, var/mob/user as mob)
+ if(default_deconstruction_screwdriver(user, O))
+ return
+ if(default_deconstruction_crowbar(user, O))
+ return
+ if(default_part_replacement(user, O))
+ return
if(istype(O, /obj/item/weapon/reagent_containers/glass))
if(beaker)
- user << "\red The biogenerator is already loaded."
+ user << "]The [src] is already loaded."
else
user.before_take_item(O)
O.loc = src
beaker = O
updateUsrDialog()
else if(processing)
- user << "\red The biogenerator is currently processing."
+ user << "\The [src] is currently processing."
else if(istype(O, /obj/item/weapon/storage/bag/plants))
var/i = 0
for(var/obj/item/weapon/reagent_containers/food/snacks/grown/G in contents)
i++
if(i >= 10)
- user << "\red The biogenerator is already full! Activate it."
+ user << "\The [src] is already full! Activate it."
else
for(var/obj/item/weapon/reagent_containers/food/snacks/grown/G in O.contents)
G.loc = src
i++
if(i >= 10)
- user << "\blue You fill the biogenerator to its capacity."
+ user << "You fill \the [src] to its capacity."
break
- if(i<10)
- user << "\blue You empty the plant bag into the biogenerator."
-
+ if(i < 10)
+ user << "You empty \the [O] into \the [src]."
else if(!istype(O, /obj/item/weapon/reagent_containers/food/snacks/grown))
- user << "\red You cannot put this in [src.name]"
+ user << "You cannot put this in \the [src]."
else
var/i = 0
for(var/obj/item/weapon/reagent_containers/food/snacks/grown/G in contents)
i++
if(i >= 10)
- user << "\red The biogenerator is full! Activate it."
+ user << "\The [src] is full! Activate it."
else
user.before_take_item(O)
O.loc = src
- user << "\blue You put [O.name] in [src.name]"
+ user << "You put \the [O] in \the [src]"
update_icon()
return
@@ -89,18 +103,18 @@
dat += "Activate Biogenerator!
"
dat += "Detach Container
"
dat += "Food
"
- dat += "10 milk (20)
"
- dat += "Slab of meat (50)
"
+ dat += "10 milk ([round(20/build_eff)])
"
+ dat += "Slab of meat ([round(50/build_eff)])
"
dat += "Nutrient
"
- dat += "E-Z-Nutrient (10) | x5
"
- dat += "Left 4 Zed (20) | x5
"
- dat += "Robust Harvest (25) | x5
"
+ dat += "E-Z-Nutrient ([round(10/build_eff)]) | x5
"
+ dat += "Left 4 Zed ([round(20/build_eff)]) | x5
"
+ dat += "Robust Harvest ([round(25/build_eff)]) | x5
"
dat += "Leather
"
- dat += "Wallet (100)
"
- dat += "Botanical gloves (250)
"
- dat += "Utility belt (300)
"
- dat += "Leather Satchel (400)
"
- dat += "Cash Bag (400)
"
+ dat += "Wallet ([round(100/build_eff)])
"
+ dat += "Botanical gloves ([round(250/build_eff)])
"
+ dat += "Utility belt ([round(300/build_eff)])
"
+ dat += "Leather Satchel ([round(400/build_eff)])
"
+ dat += "Cash Bag ([round(400/build_eff)])
"
//dat += "Other
"
//dat += "Monkey (500)
"
else
@@ -122,34 +136,35 @@
interact(user)
/obj/machinery/biogenerator/proc/activate()
- if (usr.stat != 0)
+ if (usr.stat)
return
- if (src.stat != 0) //NOPOWER etc
+ if (stat) //NOPOWER etc
return
- if(src.processing)
- usr << "\red The biogenerator is in the process of working."
+ if(processing)
+ usr << "The biogenerator is in the process of working."
return
var/S = 0
for(var/obj/item/weapon/reagent_containers/food/snacks/grown/I in contents)
S += 5
if(I.reagents.get_reagent_amount("nutriment") < 0.1)
points += 1
- else points += I.reagents.get_reagent_amount("nutriment")*10
+ else points += I.reagents.get_reagent_amount("nutriment") * 10 * eat_eff
del(I)
if(S)
processing = 1
update_icon()
updateUsrDialog()
playsound(src.loc, 'sound/machines/blender.ogg', 50, 1)
- use_power(S*30)
- sleep(S+15)
+ use_power(S * 30)
+ sleep((S + 15) / eat_eff)
processing = 0
update_icon()
else
menustat = "void"
return
-/obj/machinery/biogenerator/proc/create_product(var/item,var/cost)
+/obj/machinery/biogenerator/proc/create_product(var/item, var/cost)
+ cost = round(cost/build_eff)
if(cost > points)
menustat = "nopoints"
return 0
@@ -160,45 +175,45 @@
sleep(30)
switch(item)
if("milk")
- beaker.reagents.add_reagent("milk",10)
+ beaker.reagents.add_reagent("milk", 10)
if("meat")
- new/obj/item/weapon/reagent_containers/food/snacks/meat(src.loc)
+ new/obj/item/weapon/reagent_containers/food/snacks/meat(loc)
if("ez")
- new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(src.loc)
+ new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(loc)
if("l4z")
- new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(src.loc)
+ new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(loc)
if("rh")
- new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(src.loc)
+ new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(loc)
if("ez5") //It's not an elegant method, but it's safe and easy. -Cheridan
- new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(src.loc)
- new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(src.loc)
- new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(src.loc)
- new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(src.loc)
- new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(src.loc)
+ new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(loc)
+ new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(loc)
+ new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(loc)
+ new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(loc)
+ new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(loc)
if("l4z5")
- new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(src.loc)
- new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(src.loc)
- new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(src.loc)
- new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(src.loc)
- new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(src.loc)
+ new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(loc)
+ new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(loc)
+ new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(loc)
+ new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(loc)
+ new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(loc)
if("rh5")
- new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(src.loc)
- new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(src.loc)
- new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(src.loc)
- new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(src.loc)
- new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(src.loc)
+ new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(loc)
+ new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(loc)
+ new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(loc)
+ new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(loc)
+ new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(loc)
if("wallet")
- new/obj/item/weapon/storage/wallet(src.loc)
+ new/obj/item/weapon/storage/wallet(loc)
if("gloves")
- new/obj/item/clothing/gloves/botanic_leather(src.loc)
+ new/obj/item/clothing/gloves/botanic_leather(loc)
if("tbelt")
- new/obj/item/weapon/storage/belt/utility(src.loc)
+ new/obj/item/weapon/storage/belt/utility(loc)
if("satchel")
- new/obj/item/weapon/storage/backpack/satchel(src.loc)
+ new/obj/item/weapon/storage/backpack/satchel(loc)
if("cashbag")
- new/obj/item/weapon/storage/bag/cash(src.loc)
+ new/obj/item/weapon/storage/bag/cash(loc)
if("monkey")
- new/mob/living/carbon/monkey(src.loc)
+ new/mob/living/carbon/monkey(loc)
processing = 0
menustat = "complete"
update_icon()
@@ -220,7 +235,21 @@
beaker = null
update_icon()
if("create")
- create_product(href_list["item"],text2num(href_list["cost"]))
+ create_product(href_list["item"], text2num(href_list["cost"]))
if("menu")
menustat = "menu"
updateUsrDialog()
+
+/obj/machinery/biogenerator/RefreshParts()
+ ..()
+ var/man_rating = 0
+ var/bin_rating = 0
+
+ for(var/obj/item/weapon/stock_parts/P in component_parts)
+ if(istype(P, /obj/item/weapon/stock_parts/matter_bin))
+ bin_rating += P.rating
+ if(istype(P, /obj/item/weapon/stock_parts/manipulator))
+ man_rating += P.rating
+
+ build_eff = man_rating
+ eat_eff = bin_rating
diff --git a/code/game/machinery/bots/bots.dm b/code/game/machinery/bots/bots.dm
index c4007c6994..f87ae33ee0 100644
--- a/code/game/machinery/bots/bots.dm
+++ b/code/game/machinery/bots/bots.dm
@@ -81,6 +81,8 @@
..()
/obj/machinery/bot/bullet_act(var/obj/item/projectile/Proj)
+ if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN))
+ return
health -= Proj.damage
..()
healthcheck()
diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm
index d631ca46df..3b3104201f 100644
--- a/code/game/machinery/camera/camera.dm
+++ b/code/game/machinery/camera/camera.dm
@@ -13,7 +13,6 @@
var/c_tag_order = 999
var/status = 1
anchored = 1.0
- var/panel_open = 0 // 0 = Closed / 1 = Open
var/invuln = null
var/bugged = 0
var/obj/item/weapon/camera_assembly/assembly = null
@@ -57,7 +56,7 @@
/obj/machinery/camera/Del()
if(!alarm_on)
triggerCameraAlarm()
-
+
cancelCameraAlarm()
..()
@@ -70,7 +69,7 @@
kick_viewers()
triggerCameraAlarm()
update_icon()
-
+
spawn(900)
stat &= ~EMPED
cancelCameraAlarm()
@@ -85,11 +84,11 @@
/obj/machinery/camera/ex_act(severity)
if(src.invuln)
return
-
+
//camera dies if an explosion touches it!
if(severity <= 2 || prob(50))
destroy()
-
+
..() //and give it the regular chance of being deleted outright
@@ -174,7 +173,7 @@
if (S.current == src)
O << "[U] holds \a [itemname] up to one of the cameras ..."
O << browse(text("[][]", itemname, info), text("window=[]", itemname))
-
+
else if (istype(W, /obj/item/weapon/camera_bug))
if (!src.can_use())
user << "\blue Camera non-functional"
@@ -185,7 +184,7 @@
else
user << "\blue Camera bugged."
src.bugged = 1
-
+
else if(W.damtype == BRUTE || W.damtype == BURN) //bashing cameras
if (W.force >= src.toughness)
visible_message("[src] has been [pick(W.attack_verb)] with [W] by [user]!")
@@ -194,7 +193,7 @@
if (I.hitsound)
playsound(loc, I.hitsound, 50, 1, -1)
take_damage(W.force)
-
+
else
..()
@@ -221,14 +220,14 @@
if (force >= toughness && (force > toughness*4 || prob(25)))
destroy()
-//Used when someone breaks a camera
+//Used when someone breaks a camera
/obj/machinery/camera/proc/destroy()
invalidateCameraCache()
stat |= BROKEN
kick_viewers()
triggerCameraAlarm()
update_icon()
-
+
//sparks
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, loc)
@@ -266,7 +265,7 @@
alarm_on = 1
if(!get_area(src))
return
-
+
for(var/mob/living/silicon/S in mob_list)
S.triggerAlarm("Camera", get_area(src), list(src), src)
@@ -275,7 +274,7 @@
alarm_on = 0
if(!get_area(src))
return
-
+
for(var/mob/living/silicon/S in mob_list)
S.cancelAlarm("Camera", get_area(src), src)
@@ -355,7 +354,7 @@
/obj/machinery/camera/interact(mob/living/user as mob)
if(!panel_open || istype(user, /mob/living/silicon/ai))
return
-
+
if(stat & BROKEN)
user << "\The [src] is broken."
return
diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm
index 454e6e44fc..343c8ab2db 100644
--- a/code/game/machinery/cloning.dm
+++ b/code/game/machinery/cloning.dm
@@ -3,18 +3,41 @@
//Potential replacement for genetics revives or something I dunno (?)
+//Find a dead mob with a brain and client.
+/proc/find_dead_player(var/find_key)
+ if(isnull(find_key))
+ return
+
+ var/mob/selected = null
+ for(var/mob/living/M in player_list)
+ //Dead people only thanks!
+ if((M.stat != 2) || (!M.client))
+ continue
+ //They need a brain!
+ if(istype(M, /mob/living/carbon/human))
+ var/mob/living/carbon/human/H = M
+ if(H.species.has_organ["brain"] && !H.has_brain())
+ continue
+ if(M.ckey == find_key)
+ selected = M
+ break
+ return selected
+
#define CLONE_BIOMASS 150
/obj/machinery/clonepod
- anchored = 1
name = "cloning pod"
desc = "An electronically-lockable pod for growing organic tissue."
density = 1
+ anchored = 1
icon = 'icons/obj/cloning.dmi'
icon_state = "pod_0"
req_access = list(access_genetics) //For premature unlocking.
+
var/mob/living/occupant
- var/heal_level = 90 //The clone is released once its health reaches this level.
+ var/heal_level = 20 //The clone is released once its health reaches this level.
+ var/heal_rate = 1
+ var/notoxin = 0
var/locked = 0
var/obj/machinery/computer/cloning/connected = null //So we remember the connected clone machine.
var/mess = 0 //Need to clean out it if it's full of exploded clone.
@@ -22,6 +45,366 @@
var/eject_wait = 0 //Don't eject them as soon as they are created fuckkk
var/biomass = CLONE_BIOMASS * 3
+/obj/machinery/clonepod/New()
+ ..()
+ component_parts = list()
+ component_parts += new /obj/item/weapon/circuitboard/clonepod(src)
+ component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
+ component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
+ component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
+ component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
+ component_parts += new /obj/item/weapon/stock_parts/console_screen(src)
+ component_parts += new /obj/item/stack/cable_coil(src, 2)
+
+ RefreshParts()
+
+/obj/machinery/clonepod/attack_ai(mob/user as mob)
+ add_hiddenprint(user)
+ return attack_hand(user)
+
+/obj/machinery/clonepod/attack_hand(mob/user as mob)
+ if((isnull(occupant)) || (stat & NOPOWER))
+ return
+ if((!isnull(occupant)) && (occupant.stat != 2))
+ var/completion = (100 * ((occupant.health + 50) / (heal_level + 100))) // Clones start at -150 health
+ user << "Current clone cycle is [round(completion)]% complete."
+ return
+
+//Clonepod
+
+//Start growing a human clone in the pod!
+/obj/machinery/clonepod/proc/growclone(var/datum/dna2/record/R)
+ if(mess || attempting)
+ return 0
+ var/datum/mind/clonemind = locate(R.mind)
+ if(!istype(clonemind, /datum/mind)) //not a mind
+ return 0
+ if(clonemind.current && clonemind.current.stat != DEAD) //mind is associated with a non-dead body
+ return 0
+ if(clonemind.active) //somebody is using that mind
+ if(ckey(clonemind.key) != R.ckey)
+ return 0
+ else
+ for(var/mob/dead/observer/G in player_list)
+ if(G.ckey == R.ckey)
+ if(G.can_reenter_corpse)
+ break
+ else
+ return 0
+
+ attempting = 1 //One at a time!!
+ locked = 1
+
+ eject_wait = 1
+ spawn(30)
+ eject_wait = 0
+
+ var/mob/living/carbon/human/H = new /mob/living/carbon/human(src, R.dna.species)
+ occupant = H
+
+ if(!R.dna.real_name) //to prevent null names
+ R.dna.real_name = "clone ([rand(0,999)])"
+ H.real_name = R.dna.real_name
+
+ icon_state = "pod_1"
+ //Get the clone body ready
+ H.adjustCloneLoss(150) // New damage var so you can't eject a clone early then stab them to abuse the current damage system --NeoFite
+ H.adjustBrainLoss(80) // Even if healed to full health, it will have some brain damage
+ H.Paralyse(4)
+
+ //Here let's calculate their health so the pod doesn't immediately eject them!!!
+ H.updatehealth()
+
+ clonemind.transfer_to(H)
+ H.ckey = R.ckey
+ H << "Consciousness slowly creeps over you as your body regenerates.
So this is what cloning feels like?"
+
+ // -- Mode/mind specific stuff goes here
+ callHook("clone", list(H))
+
+ switch(ticker.mode.name)
+ if("revolution")
+ if((H.mind in ticker.mode:revolutionaries) || (H.mind in ticker.mode:head_revolutionaries))
+ ticker.mode.update_all_rev_icons() //So the icon actually appears
+ if("mercenary")
+ if(H.mind in ticker.mode.syndicates)
+ ticker.mode.update_all_synd_icons()
+ if("cult")
+ if(H.mind in ticker.mode.cult)
+ ticker.mode.add_cultist(occupant.mind)
+ ticker.mode.update_all_cult_icons() //So the icon actually appears
+
+ // -- End mode specific stuff
+
+ if(!R.dna)
+ H.dna = new /datum/dna()
+ H.dna.real_name = H.real_name
+ else
+ H.dna = R.dna
+ H.UpdateAppearance()
+ if(heal_level < 60)
+ randmutb(H) //Sometimes the clones come out wrong.
+ H.dna.UpdateSE()
+ H.dna.UpdateUI()
+
+ H.set_cloned_appearance()
+
+ for(var/datum/language/L in R.languages)
+ H.add_language(L.name)
+ H.flavor_texts = R.flavor.Copy()
+ H.suiciding = 0
+ attempting = 0
+ return 1
+
+//Grow clones to maturity then kick them out. FREELOADERS
+/obj/machinery/clonepod/process()
+
+ if(stat & NOPOWER) //Autoeject if power is lost
+ if(occupant)
+ locked = 0
+ go_out()
+ return
+
+ if((occupant) && (occupant.loc == src))
+ if((occupant.stat == DEAD) || (occupant.suiciding) || !occupant.key) //Autoeject corpses and suiciding dudes.
+ locked = 0
+ go_out()
+ connected_message("Clone Rejected: Deceased.")
+ return
+
+ else if(occupant.health < heal_level && occupant.getCloneLoss() > 0)
+ occupant.Paralyse(4)
+
+ //Slowly get that clone healed and finished.
+ occupant.adjustCloneLoss(-2 * heal_rate)
+
+ //Premature clones may have brain damage.
+ occupant.adjustBrainLoss(-1 * heal_rate)
+
+ //So clones don't die of oxyloss in a running pod.
+ if(occupant.reagents.get_reagent_amount("inaprovaline") < 30)
+ occupant.reagents.add_reagent("inaprovaline", 60)
+
+ //So clones will remain asleep for long enough to get them into cryo (Bay RP edit)
+ if(occupant.reagents.get_reagent_amount("stoxin") < 10)
+ occupant.reagents.add_reagent("stoxin", 5)
+ if(occupant.reagents.get_reagent_amount("chloralhydrate") < 1)
+ occupant.reagents.add_reagent("chloralhydrate", 1)
+
+ //Also heal some oxyloss ourselves because inaprovaline is so bad at preventing it!!
+ occupant.adjustOxyLoss(-4)
+ if(notoxin)
+ occupant.adjustToxLoss(-2) // If sufficiently upgraded - remove toxin damage from chloral
+
+ use_power(7500) //This might need tweaking.
+ return
+
+ else if((occupant.health >= heal_level) && (!eject_wait))
+ connected_message("Cloning Process Complete.")
+ locked = 0
+ go_out()
+ return
+
+ else if((!occupant) || (occupant.loc != src))
+ occupant = null
+ if(locked)
+ locked = 0
+ if(!mess)
+ icon_state = "pod_0"
+ //use_power(200)
+ return
+
+ return
+
+//Let's unlock this early I guess. Might be too early, needs tweaking.
+/obj/machinery/clonepod/attackby(obj/item/weapon/W as obj, mob/user as mob)
+ if(isnull(occupant))
+ if(default_deconstruction_screwdriver(user, W))
+ return
+ if(default_deconstruction_crowbar(user, W))
+ return
+ if(default_part_replacement(user, W))
+ return
+ if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda))
+ if(!check_access(W))
+ user << "Access Denied."
+ return
+ if((!locked) || (isnull(occupant)))
+ return
+ if((occupant.health < -20) && (occupant.stat != 2))
+ user << "Access Refused."
+ return
+ else
+ locked = 0
+ user << "System unlocked."
+ else if(istype(W, /obj/item/weapon/card/emag))
+ if(isnull(occupant))
+ return
+ user << "You force an emergency ejection."
+ locked = 0
+ go_out()
+ return
+ else if(istype(W, /obj/item/weapon/reagent_containers/food/snacks/meat))
+ user << "\The [src] processes \the [W]."
+ biomass += 50
+ user.drop_item()
+ del(W)
+ return
+ else if(istype(W, /obj/item/weapon/wrench))
+ if(locked && (anchored || occupant))
+ user << "Can not do that while [src] is in use."
+ else
+ if(anchored)
+ anchored = 0
+ connected.pod1 = null
+ connected = null
+ else
+ anchored = 1
+ playsound(loc, 'sound/items/Ratchet.ogg', 100, 1)
+ if(anchored)
+ user.visible_message("[user] secures [src] to the floor.", "You secure [src] to the floor.")
+ else
+ user.visible_message("[user] unsecures [src] from the floor.", "You unsecure [src] from the floor.")
+ else
+ ..()
+
+//Put messages in the connected computer's temp var for display.
+/obj/machinery/clonepod/proc/connected_message(var/message)
+ if((isnull(connected)) || (!istype(connected, /obj/machinery/computer/cloning)))
+ return 0
+ if(!message)
+ return 0
+
+ connected.temp = message
+ connected.updateUsrDialog()
+ return 1
+
+/obj/machinery/clonepod/RefreshParts()
+ ..()
+ var/rating = 0
+ for(var/obj/item/weapon/stock_parts/P in component_parts)
+ if(istype(P, /obj/item/weapon/stock_parts/scanning_module) || istype(P, /obj/item/weapon/stock_parts/manipulator))
+ rating += P.rating
+
+ heal_level = rating * 10 - 20
+ heal_rate = round(rating / 4)
+ if(rating >= 8)
+ notoxin = 1
+ else
+ notoxin = 0
+
+/obj/machinery/clonepod/verb/eject()
+ set name = "Eject Cloner"
+ set category = "Object"
+ set src in oview(1)
+
+ if(usr.stat != 0)
+ return
+ go_out()
+ add_fingerprint(usr)
+ return
+
+/obj/machinery/clonepod/proc/go_out()
+ if(locked)
+ return
+
+ if(mess) //Clean that mess and dump those gibs!
+ mess = 0
+ gibs(loc)
+ icon_state = "pod_0"
+
+ /*
+ for(var/obj/O in src)
+ O.loc = loc
+ */
+ return
+
+ if(!(occupant))
+ return
+
+ /*
+ for(var/obj/O in src)
+ O.loc = loc
+ */
+
+ if(occupant.client)
+ occupant.client.eye = occupant.client.mob
+ occupant.client.perspective = MOB_PERSPECTIVE
+ occupant.loc = loc
+ icon_state = "pod_0"
+ eject_wait = 0 //If it's still set somehow.
+ domutcheck(occupant) //Waiting until they're out before possible monkeyizing.
+// occupant.add_side_effect("Bad Stomach") // Give them an extra side-effect for free.
+ occupant = null
+
+ biomass -= CLONE_BIOMASS
+
+ return
+
+/obj/machinery/clonepod/proc/malfunction()
+ if(occupant)
+ connected_message("Critical Error!")
+ mess = 1
+ icon_state = "pod_g"
+ occupant.ghostize()
+ spawn(5)
+ del(occupant)
+ return
+
+/obj/machinery/clonepod/relaymove(mob/user as mob)
+ if(user.stat)
+ return
+ go_out()
+ return
+
+/obj/machinery/clonepod/emp_act(severity)
+ if(prob(100/severity))
+ malfunction()
+ ..()
+
+/obj/machinery/clonepod/ex_act(severity)
+ switch(severity)
+ if(1.0)
+ for(var/atom/movable/A as mob|obj in src)
+ A.loc = loc
+ ex_act(severity)
+ del(src)
+ return
+ if(2.0)
+ if(prob(50))
+ for(var/atom/movable/A as mob|obj in src)
+ A.loc = loc
+ ex_act(severity)
+ del(src)
+ return
+ if(3.0)
+ if(prob(25))
+ for(var/atom/movable/A as mob|obj in src)
+ A.loc = loc
+ ex_act(severity)
+ del(src)
+ return
+ else
+ return
+
+//Health Tracker Implant
+
+/obj/item/weapon/implant/health
+ name = "health implant"
+ var/healthstring = ""
+
+/obj/item/weapon/implant/health/proc/sensehealth()
+ if(!implanted)
+ return "ERROR"
+ else
+ if(isliving(implanted))
+ var/mob/living/L = implanted
+ healthstring = "[round(L.getOxyLoss())] - [round(L.getFireLoss())] - [round(L.getToxLoss())] - [round(L.getBruteLoss())]"
+ if(!healthstring)
+ healthstring = "ERROR"
+ return healthstring
+
+//Disk stuff.
//The return of data disks?? Just for transferring between genetics machine/cloning machine.
//TO-DO: Make the genetics machine accept them.
/obj/item/weapon/disk/data
@@ -30,7 +413,7 @@
icon_state = "datadisk0" //Gosh I hope syndies don't mistake them for the nuke disk.
item_state = "card-id"
w_class = 2.0
- var/datum/dna2/record/buf=null
+ var/datum/dna2/record/buf = null
var/read_only = 0 //Well,it's still a floppy disk
/obj/item/weapon/disk/data/proc/initializeDisk()
@@ -65,363 +448,18 @@
buf.dna.SE=new_SE
buf.dna.SetSEValueRange(MONKEYBLOCK,0xDAC, 0xFFF)
-
-//Find a dead mob with a brain and client.
-/proc/find_dead_player(var/find_key)
- if (isnull(find_key))
- return
-
- var/mob/selected = null
- for(var/mob/living/M in player_list)
- //Dead people only thanks!
- if ((M.stat != 2) || (!M.client))
- continue
- //They need a brain!
- if(istype(M, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = M
- if(H.species.has_organ["brain"] && !H.has_brain())
- continue
- if (M.ckey == find_key)
- selected = M
- break
- return selected
-
-//Disk stuff.
/obj/item/weapon/disk/data/New()
..()
var/diskcolor = pick(0,1,2)
- src.icon_state = "datadisk[diskcolor]"
+ icon_state = "datadisk[diskcolor]"
/obj/item/weapon/disk/data/attack_self(mob/user as mob)
- src.read_only = !src.read_only
- user << "You flip the write-protect tab to [src.read_only ? "protected" : "unprotected"]."
+ read_only = !read_only
+ user << "You flip the write-protect tab to [read_only ? "protected" : "unprotected"]."
/obj/item/weapon/disk/data/examine(mob/user)
..(user)
- user << text("The write-protect tab is set to [src.read_only ? "protected" : "unprotected"].")
- return
-
-//Health Tracker Implant
-
-/obj/item/weapon/implant/health
- name = "health implant"
- var/healthstring = ""
-
-/obj/item/weapon/implant/health/proc/sensehealth()
- if (!src.implanted)
- return "ERROR"
- else
- if(isliving(src.implanted))
- var/mob/living/L = src.implanted
- src.healthstring = "[round(L.getOxyLoss())] - [round(L.getFireLoss())] - [round(L.getToxLoss())] - [round(L.getBruteLoss())]"
- if (!src.healthstring)
- src.healthstring = "ERROR"
- return src.healthstring
-
-/obj/machinery/clonepod/attack_ai(mob/user as mob)
- src.add_hiddenprint(user)
- return attack_hand(user)
-
-/obj/machinery/clonepod/attack_hand(mob/user as mob)
- if ((isnull(src.occupant)) || (stat & NOPOWER))
- return
- if ((!isnull(src.occupant)) && (src.occupant.stat != 2))
- var/completion = (100 * ((src.occupant.health + 100) / (src.heal_level + 100)))
- user << "Current clone cycle is [round(completion)]% complete."
- return
-
-//Clonepod
-
-//Start growing a human clone in the pod!
-/obj/machinery/clonepod/proc/growclone(var/datum/dna2/record/R)
- if(mess || attempting)
- return 0
- var/datum/mind/clonemind = locate(R.mind)
- if(!istype(clonemind,/datum/mind)) //not a mind
- return 0
- if( clonemind.current && clonemind.current.stat != DEAD ) //mind is associated with a non-dead body
- return 0
- if(clonemind.active) //somebody is using that mind
- if( ckey(clonemind.key)!=R.ckey )
- return 0
- else
- for(var/mob/dead/observer/G in player_list)
- if(G.ckey == R.ckey)
- if(G.can_reenter_corpse)
- break
- else
- return 0
-
-
- src.heal_level = rand(10,40) //Randomizes what health the clone is when ejected
- src.attempting = 1 //One at a time!!
- src.locked = 1
-
- src.eject_wait = 1
- spawn(30)
- src.eject_wait = 0
-
- var/mob/living/carbon/human/H = new /mob/living/carbon/human(src, R.dna.species)
- occupant = H
-
- if(!R.dna.real_name) //to prevent null names
- R.dna.real_name = "clone ([rand(0,999)])"
- H.real_name = R.dna.real_name
-
- src.icon_state = "pod_1"
- //Get the clone body ready
- H.adjustCloneLoss(150) //new damage var so you can't eject a clone early then stab them to abuse the current damage system --NeoFite
- H.adjustBrainLoss(src.heal_level + 50 + rand(10, 30)) // The rand(10, 30) will come out as extra brain damage
- H.Paralyse(4)
-
- //Here let's calculate their health so the pod doesn't immediately eject them!!!
- H.updatehealth()
-
- clonemind.transfer_to(H)
- H.ckey = R.ckey
- H << "Consciousness slowly creeps over you as your body regenerates.
So this is what cloning feels like?"
-
- // -- Mode/mind specific stuff goes here
- callHook("clone", list(H))
-
- switch(ticker.mode.name)
- if("revolution")
- if((H.mind in ticker.mode:revolutionaries) || (H.mind in ticker.mode:head_revolutionaries))
- ticker.mode.update_all_rev_icons() //So the icon actually appears
- if("mercenary")
- if(H.mind in ticker.mode.syndicates)
- ticker.mode.update_all_synd_icons()
- if("cult")
- if (H.mind in ticker.mode.cult)
- ticker.mode.add_cultist(src.occupant.mind)
- ticker.mode.update_all_cult_icons() //So the icon actually appears
-
- // -- End mode specific stuff
-
- if(!R.dna)
- H.dna = new /datum/dna()
- H.dna.real_name = H.real_name
- else
- H.dna=R.dna
- H.UpdateAppearance()
- randmutb(H) //Sometimes the clones come out wrong.
- H.dna.UpdateSE()
- H.dna.UpdateUI()
-
- H.set_cloned_appearance()
-
- for(var/datum/language/L in R.languages)
- H.add_language(L.name)
- H.flavor_texts = R.flavor.Copy()
- H.suiciding = 0
- src.attempting = 0
- return 1
-
-//Grow clones to maturity then kick them out. FREELOADERS
-/obj/machinery/clonepod/process()
-
- if(stat & NOPOWER) //Autoeject if power is lost
- if (src.occupant)
- src.locked = 0
- src.go_out()
- return
-
- if((src.occupant) && (src.occupant.loc == src))
- if((src.occupant.stat == DEAD) || (src.occupant.suiciding) || !occupant.key) //Autoeject corpses and suiciding dudes.
- src.locked = 0
- src.go_out()
- src.connected_message("Clone Rejected: Deceased.")
- return
-
- else if(src.occupant.health < src.heal_level)
- src.occupant.Paralyse(4)
-
- //Slowly get that clone healed and finished.
- src.occupant.adjustCloneLoss(-2)
-
- //Premature clones may have brain damage.
- src.occupant.adjustBrainLoss(-1)
-
- //So clones don't die of oxyloss in a running pod.
- if (src.occupant.reagents.get_reagent_amount("inaprovaline") < 30)
- src.occupant.reagents.add_reagent("inaprovaline", 60)
-
- //So clones will remain asleep for long enough to get them into cryo (Bay RP edit)
- if (src.occupant.reagents.get_reagent_amount("stoxin") < 10)
- src.occupant.reagents.add_reagent("stoxin", 5)
- if (src.occupant.reagents.get_reagent_amount("chloralhydrate") < 1)
- src.occupant.reagents.add_reagent("chloralhydrate", 1)
-
- //Also heal some oxyloss ourselves because inaprovaline is so bad at preventing it!!
- src.occupant.adjustOxyLoss(-4)
-
- use_power(7500) //This might need tweaking.
- return
-
- else if((src.occupant.health >= src.heal_level) && (!src.eject_wait))
- src.connected_message("Cloning Process Complete.")
- src.locked = 0
- src.go_out()
- return
-
- else if ((!src.occupant) || (src.occupant.loc != src))
- src.occupant = null
- if (src.locked)
- src.locked = 0
- if (!src.mess)
- icon_state = "pod_0"
- //use_power(200)
- return
-
- return
-
-//Let's unlock this early I guess. Might be too early, needs tweaking.
-/obj/machinery/clonepod/attackby(obj/item/weapon/W as obj, mob/user as mob)
- if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda))
- if (!src.check_access(W))
- user << "\red Access Denied."
- return
- if ((!src.locked) || (isnull(src.occupant)))
- return
- if ((src.occupant.health < -20) && (src.occupant.stat != 2))
- user << "\red Access Refused."
- return
- else
- src.locked = 0
- user << "System unlocked."
- else if (istype(W, /obj/item/weapon/card/emag))
- if (isnull(src.occupant))
- return
- user << "You force an emergency ejection."
- src.locked = 0
- src.go_out()
- return
- else if (istype(W, /obj/item/weapon/reagent_containers/food/snacks/meat))
- user << "\blue \The [src] processes \the [W]."
- biomass += 50
- user.drop_item()
- del(W)
- return
- else if (istype(W, /obj/item/weapon/wrench))
- if(src.locked && (src.anchored || src.occupant))
- user << "\red Can not do that while [src] is in use."
- else
- if(src.anchored)
- src.anchored = 0
- connected.pod1 = null
- connected = null
- else
- src.anchored = 1
- playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1)
- if(anchored)
- user.visible_message("[user] secures [src] to the floor.", "You secure [src] to the floor.")
- else
- user.visible_message("[user] unsecures [src] from the floor.", "You unsecure [src] from the floor.")
- else
- ..()
-
-//Put messages in the connected computer's temp var for display.
-/obj/machinery/clonepod/proc/connected_message(var/message)
- if ((isnull(src.connected)) || (!istype(src.connected, /obj/machinery/computer/cloning)))
- return 0
- if (!message)
- return 0
-
- src.connected.temp = message
- src.connected.updateUsrDialog()
- return 1
-
-/obj/machinery/clonepod/verb/eject()
- set name = "Eject Cloner"
- set category = "Object"
- set src in oview(1)
-
- if (usr.stat != 0)
- return
- src.go_out()
- add_fingerprint(usr)
- return
-
-/obj/machinery/clonepod/proc/go_out()
- if (src.locked)
- return
-
- if (src.mess) //Clean that mess and dump those gibs!
- src.mess = 0
- gibs(src.loc)
- src.icon_state = "pod_0"
-
- /*
- for(var/obj/O in src)
- O.loc = src.loc
- */
- return
-
- if (!(src.occupant))
- return
-
- /*
- for(var/obj/O in src)
- O.loc = src.loc
- */
-
- if (src.occupant.client)
- src.occupant.client.eye = src.occupant.client.mob
- src.occupant.client.perspective = MOB_PERSPECTIVE
- src.occupant.loc = src.loc
- src.icon_state = "pod_0"
- src.eject_wait = 0 //If it's still set somehow.
- domutcheck(src.occupant) //Waiting until they're out before possible monkeyizing.
-// src.occupant.add_side_effect("Bad Stomach") // Give them an extra side-effect for free.
- src.occupant = null
-
- src.biomass -= CLONE_BIOMASS
-
- return
-
-/obj/machinery/clonepod/proc/malfunction()
- if(src.occupant)
- src.connected_message("Critical Error!")
- src.mess = 1
- src.icon_state = "pod_g"
- src.occupant.ghostize()
- spawn(5)
- del(src.occupant)
- return
-
-/obj/machinery/clonepod/relaymove(mob/user as mob)
- if (user.stat)
- return
- src.go_out()
- return
-
-/obj/machinery/clonepod/emp_act(severity)
- if(prob(100/severity)) malfunction()
- ..()
-
-/obj/machinery/clonepod/ex_act(severity)
- switch(severity)
- if(1.0)
- for(var/atom/movable/A as mob|obj in src)
- A.loc = src.loc
- ex_act(severity)
- del(src)
- return
- if(2.0)
- if (prob(50))
- for(var/atom/movable/A as mob|obj in src)
- A.loc = src.loc
- ex_act(severity)
- del(src)
- return
- if(3.0)
- if (prob(25))
- for(var/atom/movable/A as mob|obj in src)
- A.loc = src.loc
- ex_act(severity)
- del(src)
- return
- else
+ user << text("The write-protect tab is set to [read_only ? "protected" : "unprotected"].")
return
/*
diff --git a/code/game/machinery/computer/RCON_Console.dm b/code/game/machinery/computer/RCON_Console.dm
index e1ecdb28d2..a28b6ad42d 100644
--- a/code/game/machinery/computer/RCON_Console.dm
+++ b/code/game/machinery/computer/RCON_Console.dm
@@ -45,7 +45,8 @@
"output_load" = round(SMES.output_used),
"RCON_tag" = SMES.RCon_tag
)))
- data["smes_info"] = smeslist
+
+ data["smes_info"] = sortByKey(smeslist, "RCON_tag")
// BREAKER DATA (simplified view)
var/list/breakerlist[0]
diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm
index 68009eec60..2d5b9394d0 100644
--- a/code/game/machinery/hologram.dm
+++ b/code/game/machinery/hologram.dm
@@ -114,6 +114,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
hologram.anchored = 1//So space wind cannot drag it.
hologram.name = "[A.name] (Hologram)"//If someone decides to right click.
hologram.SetLuminosity(2) //hologram lighting
+ hologram.color = color //painted holopad gives coloured holograms
SetLuminosity(2) //pad lighting
icon_state = "holopad1"
A.holo = src
diff --git a/code/game/machinery/kitchen/smartfridge.dm b/code/game/machinery/kitchen/smartfridge.dm
index 8e86678ef2..7b186bcc9c 100644
--- a/code/game/machinery/kitchen/smartfridge.dm
+++ b/code/game/machinery/kitchen/smartfridge.dm
@@ -19,7 +19,6 @@
var/seconds_electrified = 0;
var/shoot_inventory = 0
var/locked = 0
- var/panel_open = 0 //Hacking a smartfridge
var/scan_id = 1
var/is_secure = 0
var/datum/wires/smartfridge/wires = null
diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm
index c5eaf35497..819cc05632 100644
--- a/code/game/machinery/machinery.dm
+++ b/code/game/machinery/machinery.dm
@@ -28,6 +28,9 @@ Class Variables:
component_parts (list)
A list of component parts of machine used by frame based machines.
+ panel_open (num)
+ Whether the panel is open
+
uid (num)
Unique id of machine across all machines.
@@ -43,9 +46,6 @@ Class Variables:
MAINT:8 -- machine is currently under going maintenance.
EMPED:16 -- temporary broken by EMP pulse
- manual (num)
- Currently unused.
-
Class Procs:
New() 'game/machinery/machine.dm'
@@ -104,13 +104,12 @@ Class Procs:
//2 = run auto, use active
var/idle_power_usage = 0
var/active_power_usage = 0
- var/power_channel = EQUIP
- //EQUIP,ENVIRON or LIGHT
- var/list/component_parts = list() //list of all the parts used to build it, if made from certain kinds of frames.
+ var/power_channel = EQUIP //EQUIP, ENVIRON or LIGHT
+ var/list/component_parts = null //list of all the parts used to build it, if made from certain kinds of frames.
var/uid
- var/manual = 0
- var/interact_offline = 0 // Can the machine be interacted with while de-powered.
+ var/panel_open = 0
var/global/gl_uid = 1
+ var/interact_offline = 0 // Can the machine be interacted with while de-powered.
/obj/machinery/New(l, d=0)
..(l)
@@ -238,15 +237,15 @@ Class Procs:
gl_uid++
/obj/machinery/proc/state(var/msg)
- for(var/mob/O in hearers(src, null))
- O.show_message("\icon[src] [msg]", 2)
+ for(var/mob/O in hearers(src, null))
+ O.show_message("\icon[src] [msg]", 2)
/obj/machinery/proc/ping(text=null)
- if (!text)
- text = "\The [src] pings."
+ if (!text)
+ text = "\The [src] pings."
- state(text, "blue")
- playsound(src.loc, 'sound/machines/ping.ogg', 50, 0)
+ state(text, "blue")
+ playsound(src.loc, 'sound/machines/ping.ogg', 50, 0)
/obj/machinery/proc/shock(mob/user, prb)
if(inoperable())
@@ -267,6 +266,54 @@ Class Procs:
else
return 0
+/obj/machinery/proc/default_deconstruction_crowbar(var/mob/user, var/obj/item/weapon/crowbar/C)
+ if(!istype(C))
+ return 0
+ if(!panel_open)
+ return 0
+ . = dismantle()
+
+/obj/machinery/proc/default_deconstruction_screwdriver(var/mob/user, var/obj/item/weapon/screwdriver/S)
+ if(!istype(S))
+ return 0
+ playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ panel_open = !panel_open
+ user << "You [panel_open ? "open" : "close"] the maintenance hatch of [src]."
+ update_icon()
+ return 1
+
+/obj/machinery/proc/default_part_replacement(var/mob/user, var/obj/item/weapon/storage/part_replacer/R)
+ if(!istype(R))
+ return 0
+ if(!component_parts)
+ return 0
+ if(panel_open)
+ var/obj/item/weapon/circuitboard/CB = locate(/obj/item/weapon/circuitboard) in component_parts
+ var/P
+ for(var/obj/item/weapon/stock_parts/A in component_parts)
+ for(var/D in CB.req_components)
+ var/T = text2path(D)
+ if(ispath(A.type, T))
+ P = T
+ break
+ for(var/obj/item/weapon/stock_parts/B in R.contents)
+ if(istype(B, P) && istype(A, P))
+ if(B.rating > A.rating)
+ R.remove_from_storage(B, src)
+ R.handle_item_insertion(A, 1)
+ component_parts -= A
+ component_parts += B
+ B.loc = null
+ user << "[A.name] replaced with [B.name]."
+ break
+ update_icon()
+ RefreshParts()
+ else
+ user << "Following parts detected in the machine:"
+ for(var/var/obj/item/C in component_parts)
+ user << " [C.name]"
+ return 1
+
/obj/machinery/proc/dismantle()
playsound(loc, 'sound/items/Crowbar.ogg', 50, 1)
var/obj/machinery/constructable_frame/machine_frame/M = new /obj/machinery/constructable_frame/machine_frame(loc)
diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm
index 3049a6f694..e4d29467e0 100644
--- a/code/game/machinery/rechargestation.dm
+++ b/code/game/machinery/rechargestation.dm
@@ -3,187 +3,227 @@
icon = 'icons/obj/objects.dmi'
icon_state = "borgcharger0"
density = 1
- anchored = 1.0
+ anchored = 1
use_power = 1
idle_power_usage = 50
active_power_usage = 50
var/mob/occupant = null
- var/max_internal_charge = 15000 // Two charged borgs in a row with default cell
- var/current_internal_charge = 15000 // Starts charged, to prevent power surges on round start
- var/charging_cap_active = 25000 // Active Cap - When cyborg is inside
- var/charging_cap_passive = 2500 // Passive Cap - Recharging internal capacitor when no cyborg is inside
+ var/obj/item/weapon/cell/cell = null
+ //var/max_internal_charge = 15000 // Two charged borgs in a row with default cell
+ //var/current_internal_charge = 15000 // Starts charged, to prevent power surges on round start
+ var/charging_cap_active = 1000 // Active Cap - When cyborg is inside
+ var/charging_cap_passive = 250 // Passive Cap - Recharging internal capacitor when no cyborg is inside
var/icon_update_tick = 0 // Used to update icon only once every 10 ticks
+ var/charge_rate = 250 // How much charge is restored per tick
+ var/weld_rate = 0 // How much brute damage is repaired per tick
+ var/wire_rate = 0 // How much burn damage is repaired per tick
+/obj/machinery/recharge_station/New()
+ ..()
+ component_parts = list()
+ component_parts += new /obj/item/weapon/circuitboard/recharge_station(src)
+ component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
+ component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
+ component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
+ component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
+ component_parts += new /obj/item/weapon/cell/high(src)
+ component_parts += new /obj/item/stack/cable_coil(src, 5)
- New()
- ..()
- build_icon()
- update_icon()
+ build_icon()
+ update_icon()
- process()
- if(stat & (BROKEN))
- return
+ RefreshParts()
- if((stat & (NOPOWER)) && !current_internal_charge) // No Power.
- return
-
- var/chargemode = 0
- if(src.occupant)
- process_occupant()
- chargemode = 1
- // Power Stuff
-
- if(stat & NOPOWER)
- current_internal_charge = max(0, (current_internal_charge - (50 * CELLRATE))) // Internal Circuitry, 50W load. No power - Runs from internal cell
- return // No external power = No charging
-
-
-
- if(max_internal_charge < current_internal_charge)
- current_internal_charge = max_internal_charge// Safety check if varedit adminbus or something screws up
- // Calculating amount of power to draw
- var/charge_diff = max_internal_charge - current_internal_charge // OK we have charge differences
- charge_diff = charge_diff / CELLRATE // Deconvert from Charge to Joules
- if(chargemode) // Decide if use passive or active power
- charge_diff = between(0, charge_diff, charging_cap_active) // Trim the values to limits
- else // We should have load for this tick in Watts
- charge_diff = between(0, charge_diff, charging_cap_passive)
-
- charge_diff += 50 // 50W for circuitry
-
- if(idle_power_usage != charge_diff) // Force update, but only when our power usage changed this tick.
- idle_power_usage = charge_diff
- update_use_power(1,1)
-
- current_internal_charge = min((current_internal_charge + ((charge_diff - 50) * CELLRATE)), max_internal_charge)
-
- if(icon_update_tick >= 10)
- update_icon()
- icon_update_tick = 0
- else
- icon_update_tick++
-
- return 1
-
-
- allow_drop()
- return 0
-
- examine(mob/user)
- ..(user)
- user << "The charge meter reads: [round(chargepercentage())]%"
-
- proc/chargepercentage()
- return ((current_internal_charge / max_internal_charge) * 100)
-
- relaymove(mob/user as mob)
- if(user.stat)
- return
- src.go_out()
+/obj/machinery/recharge_station/process()
+ if(stat & (BROKEN))
return
- emp_act(severity)
- if(stat & (BROKEN|NOPOWER))
- ..(severity)
- return
- if(occupant)
- occupant.emp_act(severity)
- go_out()
- ..(severity)
-
- update_icon()
- ..()
- overlays.Cut()
- switch(round(chargepercentage()))
- if(1 to 20)
- overlays += image('icons/obj/objects.dmi', "statn_c0")
- if(21 to 40)
- overlays += image('icons/obj/objects.dmi', "statn_c20")
- if(41 to 60)
- overlays += image('icons/obj/objects.dmi', "statn_c40")
- if(61 to 80)
- overlays += image('icons/obj/objects.dmi', "statn_c60")
- if(81 to 98)
- overlays += image('icons/obj/objects.dmi', "statn_c80")
- if(99 to 110)
- overlays += image('icons/obj/objects.dmi', "statn_c100")
-
- proc
- build_icon()
- if(NOPOWER|BROKEN)
- if(src.occupant)
- icon_state = "borgcharger1"
- else
- icon_state = "borgcharger0"
- else
- icon_state = "borgcharger0"
+ if((stat & (NOPOWER)) && (!cell || cell.percent() <= 0)) // No Power.
+ return
+ var/chargemode = 0
+ if(occupant)
process_occupant()
- if(src.occupant)
- if (istype(occupant, /mob/living/silicon/robot))
- var/mob/living/silicon/robot/R = occupant
- if(R.module)
- R.module.respawn_consumable(R)
- if(!R.cell)
- return
- if(!R.cell.fully_charged())
- var/diff = min(R.cell.maxcharge - R.cell.charge, 250) // Capped at 250 charge / tick
- diff = min(diff, current_internal_charge) // No over-discharging
- R.cell.give(diff)
- current_internal_charge -= diff
- else
- update_use_power(1)
+ chargemode = 1
+ // Power Stuff
+
+ if(!cell) // Shouldn't be possible, but sanity check
+ return
+
+ if(stat & NOPOWER)
+ cell.use(50 * CELLRATE) // Internal Circuitry, 50W load. No power - Runs from internal cell
+ return // No external power = No charging
+
+ // Calculating amount of power to draw
+ var/charge_diff = (chargemode ? charging_cap_active : charging_cap_passive) + 50 // 50W for circuitry
+
+ charge_diff = cell.give(charge_diff)
+
+ if(idle_power_usage != charge_diff) // Force update, but only when our power usage changed this tick.
+ idle_power_usage = charge_diff
+ update_use_power(1, 1)
+
+ if(icon_update_tick >= 10)
+ update_icon()
+ icon_update_tick = 0
+ else
+ icon_update_tick++
+
+ return 1
+
+
+/obj/machinery/recharge_station/allow_drop()
+ return 0
+
+/obj/machinery/recharge_station/examine(mob/user)
+ ..(user)
+ user << "The charge meter reads: [round(chargepercentage())]%"
+
+/obj/machinery/recharge_station/proc/chargepercentage()
+ if(!cell)
+ return 0
+ return cell.percent()
+
+/obj/machinery/recharge_station/relaymove(mob/user as mob)
+ if(user.stat)
+ return
+ go_out()
+ return
+
+/obj/machinery/recharge_station/emp_act(severity)
+ if(stat & (BROKEN|NOPOWER))
+ ..(severity)
+ return
+ if(occupant)
+ occupant.emp_act(severity)
go_out()
- if(!( src.occupant ))
- return
- //for(var/obj/O in src)
- // O.loc = src.loc
- if (src.occupant.client)
- src.occupant.client.eye = src.occupant.client.mob
- src.occupant.client.perspective = MOB_PERSPECTIVE
- src.occupant.loc = src.loc
- src.occupant = null
- build_icon()
- update_use_power(1)
+ if(cell)
+ cell.emp_act(severity)
+ ..(severity)
+
+/obj/machinery/recharge_station/attackby(var/obj/item/O as obj, var/mob/user as mob)
+ if(!occupant)
+ if(default_deconstruction_screwdriver(user, O))
+ return
+ if(default_deconstruction_crowbar(user, O))
+ return
+ if(default_part_replacement(user, O))
return
+ ..()
- verb
- move_eject()
- set category = "Object"
- set src in oview(1)
- if (usr.stat != 0)
- return
- src.go_out()
- add_fingerprint(usr)
- return
+/obj/machinery/recharge_station/RefreshParts()
+ ..()
+ var/man_rating = 0
+ var/cap_rating = 0
- move_inside()
- set category = "Object"
- set src in oview(1)
- if (usr.stat == 2)
- //Whoever had it so that a borg with a dead cell can't enter this thing should be shot. --NEO
+ for(var/obj/item/weapon/stock_parts/P in component_parts)
+ if(istype(P, /obj/item/weapon/stock_parts/capacitor))
+ cap_rating += P.rating
+ if(istype(P, /obj/item/weapon/stock_parts/manipulator))
+ man_rating += P.rating
+ cell = locate(/obj/item/weapon/cell) in component_parts
+
+ charge_rate = 125 * cap_rating
+ charging_cap_passive = charge_rate
+ weld_rate = max(0, man_rating - 3)
+ wire_rate = max(0, man_rating - 5)
+
+/obj/machinery/recharge_station/update_icon()
+ ..()
+ overlays.Cut()
+ switch(round(chargepercentage()))
+ if(1 to 20)
+ overlays += image('icons/obj/objects.dmi', "statn_c0")
+ if(21 to 40)
+ overlays += image('icons/obj/objects.dmi', "statn_c20")
+ if(41 to 60)
+ overlays += image('icons/obj/objects.dmi', "statn_c40")
+ if(61 to 80)
+ overlays += image('icons/obj/objects.dmi', "statn_c60")
+ if(81 to 98)
+ overlays += image('icons/obj/objects.dmi', "statn_c80")
+ if(99 to 110)
+ overlays += image('icons/obj/objects.dmi', "statn_c100")
+
+
+/obj/machinery/recharge_station/proc/build_icon()
+ if(NOPOWER|BROKEN)
+ if(occupant)
+ icon_state = "borgcharger1"
+ else
+ icon_state = "borgcharger0"
+ else
+ icon_state = "borgcharger0"
+
+/obj/machinery/recharge_station/proc/process_occupant()
+ if(occupant)
+ if(istype(occupant, /mob/living/silicon/robot))
+ var/mob/living/silicon/robot/R = occupant
+ if(R.module)
+ R.module.respawn_consumable(R)
+ if(!R.cell)
return
- if (!(istype(usr, /mob/living/silicon/)))
- usr << "\blue Only non-organics may enter the recharger!"
- return
- if (src.occupant)
- usr << "\blue The cell is already occupied!"
- return
- if (!usr:cell)
- usr<<"\blue Without a powercell, you can't be recharged."
- //Make sure they actually HAVE a cell, now that they can get in while powerless. --NEO
- return
- usr.stop_pulling()
- if(usr && usr.client)
- usr.client.perspective = EYE_PERSPECTIVE
- usr.client.eye = src
- usr.loc = src
- src.occupant = usr
- /*for(var/obj/O in src)
- O.loc = src.loc*/
- src.add_fingerprint(usr)
- build_icon()
- update_use_power(1)
- return
\ No newline at end of file
+ if(!R.cell.fully_charged())
+ var/diff = min(R.cell.maxcharge - R.cell.charge, charge_rate) // Capped at charge_rate charge / tick
+ if (cell.use(diff))
+ R.cell.give(diff)
+ if(weld_rate && R.getBruteLoss())
+ R.adjustBruteLoss(-1)
+ if(wire_rate && R.getFireLoss())
+ R.adjustFireLoss(-1)
+ else
+ update_use_power(1)
+
+/obj/machinery/recharge_station/proc/go_out()
+ if(!(occupant))
+ return
+ //for(var/obj/O in src)
+ // O.loc = loc
+ if(occupant.client)
+ occupant.client.eye = occupant.client.mob
+ occupant.client.perspective = MOB_PERSPECTIVE
+ occupant.loc = loc
+ occupant = null
+ build_icon()
+ update_use_power(1)
+ return
+
+/obj/machinery/recharge_station/verb/move_eject()
+ set category = "Object"
+ set src in oview(1)
+ if(usr.stat != 0)
+ return
+ go_out()
+ add_fingerprint(usr)
+ return
+
+/obj/machinery/recharge_station/verb/move_inside()
+ set category = "Object"
+ set src in oview(1)
+ if(usr.stat == 2)
+ //Whoever had it so that a borg with a dead cell can't enter this thing should be shot. --NEO
+ return
+ if(!(istype(usr, /mob/living/silicon/)))
+ usr << "Only non-organics may enter the recharger!"
+ return
+ if(occupant)
+ usr << "The cell is already occupied!"
+ return
+ if(!usr:cell)
+ usr << "Without a powercell, you can't be recharged."
+ //Make sure they actually HAVE a cell, now that they can get in while powerless. --NEO
+ return
+ usr.stop_pulling()
+ if(usr && usr.client)
+ usr.client.perspective = EYE_PERSPECTIVE
+ usr.client.eye = src
+ usr.loc = src
+ occupant = usr
+ /*for(var/obj/O in src)
+ O.loc = loc*/
+ add_fingerprint(usr)
+ build_icon()
+ update_use_power(1)
+ return
\ No newline at end of file
diff --git a/code/game/machinery/spaceheater.dm b/code/game/machinery/spaceheater.dm
index ab4967d04e..c5d389c66e 100644
--- a/code/game/machinery/spaceheater.dm
+++ b/code/game/machinery/spaceheater.dm
@@ -7,7 +7,6 @@
desc = "Made by Space Amish using traditional space techniques, this heater is guaranteed not to set the station on fire."
var/obj/item/weapon/cell/cell
var/on = 0
- var/open = 0
var/set_temperature = T0C + 50 //K
var/heating_power = 40000
@@ -20,14 +19,14 @@
/obj/machinery/space_heater/update_icon()
overlays.Cut()
icon_state = "sheater[on]"
- if(open)
+ if(panel_open)
overlays += "sheater-open"
/obj/machinery/space_heater/examine(mob/user)
..(user)
- user << "The heater is [on ? "on" : "off"] and the hatch is [open ? "open" : "closed"]."
- if(open)
+ user << "The heater is [on ? "on" : "off"] and the hatch is [panel_open ? "open" : "closed"]."
+ if(panel_open)
user << "The power cell is [cell ? "installed" : "missing"]."
else
user << "The charge meter reads [cell ? round(cell.percent(),1) : 0]%"
@@ -43,7 +42,7 @@
/obj/machinery/space_heater/attackby(obj/item/I, mob/user)
if(istype(I, /obj/item/weapon/cell))
- if(open)
+ if(panel_open)
if(cell)
user << "There is already a power cell inside."
return
@@ -61,10 +60,10 @@
user << "The hatch must be open to insert a power cell."
return
else if(istype(I, /obj/item/weapon/screwdriver))
- open = !open
- user.visible_message("\blue [user] [open ? "opens" : "closes"] the hatch on the [src].", "\blue You [open ? "open" : "close"] the hatch on the [src].")
+ panel_open = !panel_open
+ user.visible_message("\blue [user] [panel_open ? "opens" : "closes"] the hatch on the [src].", "\blue You [panel_open ? "open" : "close"] the hatch on the [src].")
update_icon()
- if(!open && user.machine == src)
+ if(!panel_open && user.machine == src)
user << browse(null, "window=spaceheater")
user.unset_machine()
else
@@ -77,7 +76,7 @@
/obj/machinery/space_heater/interact(mob/user as mob)
- if(open)
+ if(panel_open)
var/dat
dat = "Power cell: "
@@ -120,7 +119,7 @@
set_temperature = dd_range(T0C, T0C + 90, set_temperature + value)
if("cellremove")
- if(open && cell && !usr.get_active_hand())
+ if(panel_open && cell && !usr.get_active_hand())
usr.visible_message("\blue [usr] removes \the [cell] from \the [src].", "\blue You remove \the [cell] from \the [src].")
cell.updateicon()
usr.put_in_hands(cell)
@@ -129,7 +128,7 @@
if("cellinstall")
- if(open && !cell)
+ if(panel_open && !cell)
var/obj/item/weapon/cell/C = usr.get_active_hand()
if(istype(C))
usr.drop_item()
diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm
index 4bf1c07abc..f8ae293bba 100644
--- a/code/game/machinery/suit_storage_unit.dm
+++ b/code/game/machinery/suit_storage_unit.dm
@@ -589,7 +589,6 @@
var/radiation_level = 2 // 1 is removing germs, 2 is removing blood, 3 is removing phoron.
var/model_text = "" // Some flavour text for the topic box.
var/locked = 1 // If locked, nothing can be taken from or added to the cycler.
- var/panel_open = 0 // Hacking!
var/can_repair // If set, the cycler can repair voidsuits.
var/electrified = 0
diff --git a/code/game/machinery/turrets.dm b/code/game/machinery/turrets.dm
index cb76c7921a..8f81c414de 100644
--- a/code/game/machinery/turrets.dm
+++ b/code/game/machinery/turrets.dm
@@ -89,7 +89,7 @@
return
/obj/machinery/turret/bullet_act(var/obj/item/projectile/Proj)
- if(Proj.damage_type == HALLOSS)
+ if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN))
return
take_damage(Proj.damage)
..()
@@ -299,7 +299,7 @@
popping = 0
/obj/machinery/turret/bullet_act(var/obj/item/projectile/Proj)
- if(Proj.damage_type == HALLOSS)
+ if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN))
return
src.health -= Proj.damage
..()
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index 26f1c620c7..7d7ee3113d 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -54,7 +54,6 @@
var/shoot_inventory = 0 //Fire items at customers! We're broken!
var/shut_up = 1 //Stop spouting those godawful pitches!
var/extended_inventory = 0 //can we access the hidden inventory?
- var/panel_open = 0 //Hacking that vending machine. Gonna get a free candy bar.
var/scan_id = 1
var/obj/item/weapon/coin/coin
var/datum/wires/vending/wires = null
diff --git a/code/game/mecha/equipment/tools/tools.dm b/code/game/mecha/equipment/tools/tools.dm
index e66796fa9c..5b71a34ec6 100644
--- a/code/game/mecha/equipment/tools/tools.dm
+++ b/code/game/mecha/equipment/tools/tools.dm
@@ -1083,6 +1083,7 @@
/obj/item/mecha_parts/mecha_equipment/tool/passenger/destroy()
for(var/atom/movable/AM in src)
AM.forceMove(get_turf(src))
+ AM << "You tumble out of the destroyed [src.name]!"
return ..()
/obj/item/mecha_parts/mecha_equipment/tool/passenger/Exit(atom/movable/O)
diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm
index bcb907a040..324637cdd3 100644
--- a/code/game/mecha/equipment/weapons/weapons.dm
+++ b/code/game/mecha/equipment/weapons/weapons.dm
@@ -199,7 +199,7 @@
name = "\improper LBX AC 10 \"Scattershot\""
icon_state = "mecha_scatter"
equip_cooldown = 20
- projectile = /obj/item/projectile/bullet/midbullet
+ projectile = /obj/item/projectile/bullet/pistol/medium
fire_sound = 'sound/weapons/Gunshot.ogg'
fire_volume = 80
projectiles = 40
@@ -211,7 +211,7 @@
name = "\improper Ultra AC 2"
icon_state = "mecha_uac2"
equip_cooldown = 10
- projectile = /obj/item/projectile/bullet/weakbullet
+ projectile = /obj/item/projectile/bullet/pistol/medium
fire_sound = 'sound/weapons/Gunshot.ogg'
projectiles = 300
projectiles_per_shot = 3
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index 3285218baf..4790550700 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -506,8 +506,25 @@
var/ignore_threshold
if(istype(Proj, /obj/item/projectile/beam/pulse))
ignore_threshold = 1
- src.take_damage(Proj.damage,Proj.flag)
+ src.take_damage(Proj.damage, Proj.flag)
+ if(prob(25)) spark_system.start()
src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),ignore_threshold)
+
+ //AP projectiles have a chance to cause additional damage
+ if(Proj.penetrating)
+ var/distance = get_dist(Proj.starting, get_turf(loc))
+ var/hit_occupant = 1 //only allow the occupant to be hit once
+ for(var/i in 1 to min(Proj.penetrating, round(Proj.damage/15)))
+ if(src.occupant && hit_occupant && prob(20))
+ Proj.attack_mob(src.occupant, distance)
+ hit_occupant = 0
+ else
+ src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT), 1)
+
+ Proj.penetrating--
+
+ if(prob(15))
+ break //give a chance to exit early
Proj.on_hit(src)
return
diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm
index 82d27968db..ea9af2f70f 100644
--- a/code/game/objects/effects/effect_system.dm
+++ b/code/game/objects/effects/effect_system.dm
@@ -233,6 +233,21 @@ steam.start() -- spawns the effect
return 0
return 1
+/////////////////////////////////////////////
+// Illumination
+/////////////////////////////////////////////
+
+/obj/effect/effect/smoke/illumination
+ name = "illumination"
+ opacity = 0
+ icon = 'icons/effects/effects.dmi'
+ icon_state = "sparks"
+
+/obj/effect/effect/smoke/illumination/New(var/newloc, var/brightness=15, var/lifetime=10)
+ time_to_live=lifetime
+ ..()
+ SetLuminosity(brightness)
+
/////////////////////////////////////////////
// Bad smoke
/////////////////////////////////////////////
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 13081d6abb..eb2e5c65a6 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -411,9 +411,9 @@
H << "You need a jumpsuit before you can attach this [name]."
return 0
var/obj/item/clothing/under/uniform = H.w_uniform
- if(uniform.hastie)
+ if(uniform.accessories.len && !uniform.can_attach_accessory(src))
if (!disable_warning)
- H << "You already have [uniform.hastie] attached to your [uniform]."
+ H << "You already have an accessory of this type attached to your [uniform]."
return 0
if( !(slot_flags & SLOT_TIE) )
return 0
diff --git a/code/game/objects/items/devices/paicard.dm b/code/game/objects/items/devices/paicard.dm
index a938d6b977..d3c667b9aa 100644
--- a/code/game/objects/items/devices/paicard.dm
+++ b/code/game/objects/items/devices/paicard.dm
@@ -281,6 +281,8 @@
src.overlays.Cut()
src.overlays += "pai-off"
+/obj/item/device/paicard
+ var/current_emotion = 1
/obj/item/device/paicard/proc/setEmotion(var/emotion)
if(pai)
src.overlays.Cut()
@@ -294,6 +296,7 @@
if(7) src.overlays += "pai-sad"
if(8) src.overlays += "pai-angry"
if(9) src.overlays += "pai-what"
+ current_emotion = emotion
/obj/item/device/paicard/proc/alertUpdate()
var/turf/T = get_turf_or_move(src.loc)
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index cee5076a55..6cd12cf137 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -380,6 +380,10 @@
viewers(user) << "\red [user] is jamming the [src.name] up \his nose and into \his brain. It looks like \he's trying to commit suicide."
return (BRUTELOSS|OXYLOSS)
+ New()
+ name = "[colourName] crayon"
+ ..()
+
/*
* Snap pops
*/
diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm
index 8d63998722..9f95abdc8c 100644
--- a/code/game/objects/items/weapons/cards_ids.dm
+++ b/code/game/objects/items/weapons/cards_ids.dm
@@ -81,7 +81,7 @@
/obj/item/device/taperecorder,
/obj/item/device/hailer,
/obj/item/device/megaphone,
- /obj/item/clothing/tie/holobadge,
+ /obj/item/clothing/accessory/holobadge,
/obj/structure/closet/crate/secure,
/obj/structure/closet/secure_closet,
/obj/machinery/librarycomp,
diff --git a/code/game/objects/items/weapons/circuitboards/machinery/biogenerator.dm b/code/game/objects/items/weapons/circuitboards/machinery/biogenerator.dm
new file mode 100644
index 0000000000..c01893b158
--- /dev/null
+++ b/code/game/objects/items/weapons/circuitboards/machinery/biogenerator.dm
@@ -0,0 +1,13 @@
+#ifndef T_BOARD
+#error T_BOARD macro is not defined but we need it!
+#endif
+
+/obj/item/weapon/circuitboard/biogenerator
+ name = T_BOARD("biogenerator")
+ build_path = "/obj/machinery/biogenerator"
+ board_type = "machine"
+ origin_tech = "programming=2"
+ frame_desc = "Requires 1 Manipulator, and 1 Matter Bin."
+ req_components = list(
+ "/obj/item/weapon/stock_parts/matter_bin" = 1,
+ "/obj/item/weapon/stock_parts/manipulator" = 1)
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/circuitboards/machinery/recharge_station.dm b/code/game/objects/items/weapons/circuitboards/machinery/recharge_station.dm
new file mode 100644
index 0000000000..5a0dc01bc1
--- /dev/null
+++ b/code/game/objects/items/weapons/circuitboards/machinery/recharge_station.dm
@@ -0,0 +1,15 @@
+#ifndef T_BOARD
+#error T_BOARD macro is not defined but we need it!
+#endif
+
+/obj/item/weapon/circuitboard/recharge_station
+ name = T_BOARD("cyborg recharging station")
+ build_path = "/obj/machinery/recharge_station"
+ board_type = "machine"
+ origin_tech = "programming=3;engineering=3"
+ frame_desc = "Requires 2 Manipulator, 2 Capacitor, 1 Cell, and 5 pieces of cable."
+ req_components = list(
+ "/obj/item/stack/cable_coil" = 5,
+ "/obj/item/weapon/stock_parts/capacitor" = 2,
+ "/obj/item/weapon/stock_parts/manipulator" = 2,
+ "/obj/item/weapon/cell" = 1)
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/explosives.dm b/code/game/objects/items/weapons/explosives.dm
index 71fb259dcd..030437b446 100644
--- a/code/game/objects/items/weapons/explosives.dm
+++ b/code/game/objects/items/weapons/explosives.dm
@@ -38,7 +38,7 @@
/obj/item/weapon/plastique/afterattack(atom/movable/target, mob/user, flag)
if (!flag)
return
- if (ismob(target) || istype(target, /turf/unsimulated) || istype(target, /turf/simulated/shuttle) || istype(target, /obj/item/weapon/storage/) || istype(target, /obj/item/clothing/tie/storage/) || istype(target, /obj/item/clothing/under))
+ if (ismob(target) || istype(target, /turf/unsimulated) || istype(target, /turf/simulated/shuttle) || istype(target, /obj/item/weapon/storage/) || istype(target, /obj/item/clothing/accessory/storage/) || istype(target, /obj/item/clothing/under))
return
user << "Planting explosives..."
diff --git a/code/game/objects/items/weapons/gift_wrappaper.dm b/code/game/objects/items/weapons/gift_wrappaper.dm
index f89dd73d0e..8127d9736d 100644
--- a/code/game/objects/items/weapons/gift_wrappaper.dm
+++ b/code/game/objects/items/weapons/gift_wrappaper.dm
@@ -102,7 +102,7 @@
/obj/item/device/paicard,
/obj/item/device/violin,
/obj/item/weapon/storage/belt/utility/full,
- /obj/item/clothing/tie/horrible)
+ /obj/item/clothing/accessory/horrible)
if(!ispath(gift_type,/obj/item)) return
diff --git a/code/game/objects/items/weapons/grenades/flashbang.dm b/code/game/objects/items/weapons/grenades/flashbang.dm
index f9120d5491..a332f6fa92 100644
--- a/code/game/objects/items/weapons/grenades/flashbang.dm
+++ b/code/game/objects/items/weapons/grenades/flashbang.dm
@@ -21,11 +21,11 @@
B.health -= damage
B.update_icon()
- new/obj/effect/effect/smoke/flashbang(src.loc)
+ new/obj/effect/effect/smoke/illumination(src.loc, brightness=15)
del(src)
return
- proc/bang(var/turf/T , var/mob/living/carbon/M) // Added a new proc called 'bang' that takes a location and a person to be banged.
+ proc/bang(var/turf/T , var/mob/living/carbon/M) // Added a new proc called 'bang' that takes a location and a person to be banged.
if (locate(/obj/item/weapon/cloaking_device, M)) // Called during the loop that bangs people in lockers/containers and when banging
for(var/obj/item/weapon/cloaking_device/S in M) // people in normal view. Could theroetically be called during other explosions.
S.active = 0 // -- Polymorph
@@ -100,16 +100,6 @@
M << "\red Your ears start to ring!"
M.update_icons()
-/obj/effect/effect/smoke/flashbang
- name = "illumination"
- time_to_live = 10
- opacity = 0
- icon_state = "sparks"
-
-/obj/effect/effect/smoke/flashbang/New()
- ..()
- SetLuminosity(15)
-
/obj/item/weapon/grenade/flashbang/clusterbang//Created by Polymorph, fixed by Sieve
desc = "Use of this weapon may constiute a war crime in your area, consult your local captain."
name = "clusterbang"
diff --git a/code/game/objects/items/weapons/paint.dm b/code/game/objects/items/weapons/paint.dm
index 0606569c4f..77f8172f8f 100644
--- a/code/game/objects/items/weapons/paint.dm
+++ b/code/game/objects/items/weapons/paint.dm
@@ -1,4 +1,5 @@
//NEVER USE THIS IT SUX -PETETHEGOAT
+//THE GOAT WAS RIGHT - RKF
var/global/list/cached_icons = list()
@@ -11,10 +12,10 @@ var/global/list/cached_icons = list()
matter = list("metal" = 200)
w_class = 3.0
amount_per_transfer_from_this = 10
- possible_transfer_amounts = list(10,20,30,50,70)
+ possible_transfer_amounts = list(10,20,30,60)
volume = 60
flags = OPENCONTAINER
- var/paint_type = ""
+ var/paint_type = "red"
afterattack(turf/simulated/target, mob/user, proximity)
if(!proximity) return
@@ -28,24 +29,19 @@ var/global/list/cached_icons = list()
return ..()
New()
- if(paint_type == "remover")
- name = "paint remover bucket"
- else if(paint_type && lentext(paint_type) > 0)
+ if(paint_type && lentext(paint_type) > 0)
name = paint_type + " " + name
..()
reagents.add_reagent("water", volume*3/5)
reagents.add_reagent("plasticide", volume/5)
if(paint_type == "white") //why don't white crayons exist
reagents.add_reagent("aluminum", volume/5)
+ else if (paint_type == "black")
+ reagents.add_reagent("carbon", volume/5)
else
reagents.add_reagent("crayon_dust_[paint_type]", volume/5)
reagents.handle_reactions()
- on_reagent_change() //Until we have a generic "paint", this will give new colours to all paints in the can
- var/mixedcolor = mix_color_from_reagents(reagents.reagent_list)
- for(var/datum/reagent/paint/P in reagents.reagent_list)
- P.color = mixedcolor
-
red
icon_state = "paint_red"
paint_type = "red"
@@ -62,110 +58,15 @@ var/global/list/cached_icons = list()
icon_state = "paint_blue"
paint_type = "blue"
- violet
+ purple
icon_state = "paint_violet"
paint_type = "purple"
black
icon_state = "paint_black"
- paint_type = "gray"
+ paint_type = "black"
white
icon_state = "paint_white"
paint_type = "white"
- remover
- paint_type = "remover"
-/*
-/obj/item/weapon/paint
- gender= PLURAL
- name = "paint"
- desc = "Used to recolor floors and walls. Can not be removed by the janitor."
- icon = 'icons/obj/items.dmi'
- icon_state = "paint_neutral"
- color = "FFFFFF"
- item_state = "paintcan"
- w_class = 3.0
-
-/obj/item/weapon/paint/afterattack(turf/target, mob/user as mob, proximity)
- if(!proximity) return
- if(!istype(target) || istype(target, /turf/space))
- return
- var/ind = "[initial(target.icon)][color]"
- if(!cached_icons[ind])
- var/icon/overlay = new/icon(initial(target.icon))
- overlay.Blend("#[color]",ICON_MULTIPLY)
- overlay.SetIntensity(1.4)
- target.icon = overlay
- cached_icons[ind] = target.icon
- else
- target.icon = cached_icons[ind]
- return
-
-/obj/item/weapon/paint/paint_remover
- gender = PLURAL
- name = "paint remover"
- icon_state = "paint_neutral"
-
- afterattack(turf/target, mob/user as mob)
- if(istype(target) && target.icon != initial(target.icon))
- target.icon = initial(target.icon)
- return
-*/
-/*
-datum/reagent/paint
- name = "Paint"
- id = "paint_"
- reagent_state = 2
- color = "#808080"
- description = "This paint will only adhere to floor tiles."
-
-
-
- red
- name = "Red Paint"
- id = "paint_red"
- color = "#FE191A"
-
- green
- name = "Green Paint"
- color = "#18A31A"
- id = "paint_green"
-
- blue
- name = "Blue Paint"
- color = "#247CFF"
- id = "paint_blue"
-
- yellow
- name = "Yellow Paint"
- color = "#FDFE7D"
- id = "paint_yellow"
-
- violet
- name = "Violet Paint"
- color = "#CC0099"
- id = "paint_violet"
-
- black
- name = "Black Paint"
- color = "#333333"
- id = "paint_black"
-
- white
- name = "White Paint"
- color = "#F0F8FF"
- id = "paint_white"
-
-datum/reagent/paint_remover
- name = "Paint Remover"
- id = "paint_remover"
- description = "Paint remover is used to remove floor paint from floor tiles."
- reagent_state = 2
- color = "#808080"
-
- reaction_turf(var/turf/T, var/volume)
- if(istype(T) && T.icon != initial(T.icon))
- T.icon = initial(T.icon)
- return
-*/
diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm
index 0c4a94eb86..e190ac1e02 100644
--- a/code/game/objects/items/weapons/storage/belt.dm
+++ b/code/game/objects/items/weapons/storage/belt.dm
@@ -70,9 +70,16 @@
"/obj/item/device/flashlight/pen",
"/obj/item/clothing/mask/surgical",
"/obj/item/clothing/gloves/latex",
- "/obj/item/weapon/reagent_containers/hypospray"
+ "/obj/item/weapon/reagent_containers/hypospray"
)
+/obj/item/weapon/storage/belt/medical/emt
+ name = "EMT utility belt"
+ desc = "A sturdy black webbing belt with attached pouches."
+ icon = 'icons/obj/custom_items.dmi'
+ icon_state = "emsbelt"
+ item_state = "emsbelt"
+
/obj/item/weapon/storage/belt/security
name = "security belt"
diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm
index ced886bedd..9692cacf69 100644
--- a/code/game/objects/items/weapons/storage/boxes.dm
+++ b/code/game/objects/items/weapons/storage/boxes.dm
@@ -149,7 +149,7 @@
new /obj/item/ammo_casing/shotgun/beanbag(src)
/obj/item/weapon/storage/box/shotgunammo
- name = "box of shotgun shells"
+ name = "box of shotgun slugs"
desc = "It has a picture of a gun and several warning symbols on the front.
WARNING: Live ammunition. Misuse may result in serious injury or death."
New()
@@ -162,6 +162,20 @@
new /obj/item/ammo_casing/shotgun(src)
new /obj/item/ammo_casing/shotgun(src)
+/obj/item/weapon/storage/box/shotgunshells
+ name = "box of shotgun shells"
+ desc = "It has a picture of a gun and several warning symbols on the front.
WARNING: Live ammunition. Misuse may result in serious injury or death."
+
+ New()
+ ..()
+ new /obj/item/ammo_casing/shotgun/pellet(src)
+ new /obj/item/ammo_casing/shotgun/pellet(src)
+ new /obj/item/ammo_casing/shotgun/pellet(src)
+ new /obj/item/ammo_casing/shotgun/pellet(src)
+ new /obj/item/ammo_casing/shotgun/pellet(src)
+ new /obj/item/ammo_casing/shotgun/pellet(src)
+ new /obj/item/ammo_casing/shotgun/pellet(src)
+
/obj/item/weapon/storage/box/flashbangs
name = "box of flashbangs (WARNING)"
desc = "WARNING: These devices are extremely dangerous and can cause blindness or deafness in repeated use."
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index d9abac8979..40163e7c78 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -161,6 +161,9 @@
del(src)
/obj/structure/closet/bullet_act(var/obj/item/projectile/Proj)
+ if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN))
+ return
+
health -= Proj.damage
..()
if(health <= 0)
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
index 803f07616e..d583e77547 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
@@ -16,9 +16,9 @@
else
new /obj/item/weapon/storage/backpack/satchel_eng(src)
if (prob(70))
- new /obj/item/clothing/tie/storage/brown_vest(src)
+ new /obj/item/clothing/accessory/storage/brown_vest(src)
else
- new /obj/item/clothing/tie/storage/webbing(src)
+ new /obj/item/clothing/accessory/storage/webbing(src)
new /obj/item/blueprints(src)
new /obj/item/clothing/under/rank/chief_engineer(src)
new /obj/item/clothing/head/hardhat/white(src)
@@ -109,9 +109,9 @@
else
new /obj/item/weapon/storage/backpack/satchel_eng(src)
if (prob(70))
- new /obj/item/clothing/tie/storage/brown_vest(src)
+ new /obj/item/clothing/accessory/storage/brown_vest(src)
else
- new /obj/item/clothing/tie/storage/webbing(src)
+ new /obj/item/clothing/accessory/storage/webbing(src)
new /obj/item/weapon/storage/toolbox/mechanical(src)
new /obj/item/device/radio/headset/headset_eng(src)
new /obj/item/clothing/suit/storage/hazardvest(src)
@@ -138,9 +138,9 @@
else
new /obj/item/weapon/storage/backpack/satchel_eng(src)
if (prob(70))
- new /obj/item/clothing/tie/storage/brown_vest(src)
+ new /obj/item/clothing/accessory/storage/brown_vest(src)
else
- new /obj/item/clothing/tie/storage/webbing(src)
+ new /obj/item/clothing/accessory/storage/webbing(src)
new /obj/item/clothing/suit/fire/firefighter(src)
new /obj/item/device/flashlight(src)
new /obj/item/weapon/extinguisher(src)
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
index b5b8796b3c..6ee564d76b 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
@@ -119,7 +119,7 @@
new /obj/item/device/flash(src)
new /obj/item/weapon/melee/baton/loaded(src)
new /obj/item/weapon/gun/energy/gun(src)
- new /obj/item/clothing/tie/holster/waist(src)
+ new /obj/item/clothing/accessory/holster/waist(src)
new /obj/item/weapon/melee/telebaton(src)
new /obj/item/clothing/head/beret/sec/hos(src)
return
@@ -192,7 +192,7 @@
new /obj/item/clothing/glasses/sunglasses/sechud(src)
new /obj/item/taperoll/police(src)
new /obj/item/device/hailer(src)
- new /obj/item/clothing/tie/storage/black_vest(src)
+ new /obj/item/clothing/accessory/storage/black_vest(src)
new /obj/item/clothing/head/soft/sec/corp(src)
new /obj/item/clothing/under/rank/security/corp(src)
return
@@ -202,7 +202,7 @@
New()
..()
- new /obj/item/clothing/tie/armband/cargo(src)
+ new /obj/item/clothing/accessory/armband/cargo(src)
new /obj/item/device/encryptionkey/headset_cargo(src)
return
@@ -210,7 +210,7 @@
New()
..()
- new /obj/item/clothing/tie/armband/engine(src)
+ new /obj/item/clothing/accessory/armband/engine(src)
new /obj/item/device/encryptionkey/headset_eng(src)
return
@@ -218,7 +218,7 @@
New()
..()
- new /obj/item/clothing/tie/armband/science(src)
+ new /obj/item/clothing/accessory/armband/science(src)
new /obj/item/device/encryptionkey/headset_sci(src)
return
@@ -226,7 +226,7 @@
New()
..()
- new /obj/item/clothing/tie/armband/medgreen(src)
+ new /obj/item/clothing/accessory/armband/medgreen(src)
new /obj/item/device/encryptionkey/headset_med(src)
return
@@ -262,7 +262,7 @@
new /obj/item/ammo_magazine/c45r(src)
new /obj/item/taperoll/police(src)
new /obj/item/weapon/gun/projectile/detective/semiauto(src)
- new /obj/item/clothing/tie/holster/armpit(src)
+ new /obj/item/clothing/accessory/holster/armpit(src)
return
/obj/structure/closet/secure_closet/detective/update_icon()
diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm
index db0a5acc91..0512b814b2 100644
--- a/code/game/objects/structures/girders.dm
+++ b/code/game/objects/structures/girders.dm
@@ -5,6 +5,7 @@
layer = 2
var/state = 0
var/health = 200
+ var/cover = 50 //how much cover the girder provides against projectiles.
/obj/structure/girder/attack_generic(var/mob/user, var/damage, var/attack_message = "smashes apart", var/wallbreaker)
if(!damage || !wallbreaker)
@@ -14,19 +15,25 @@
return 1
/obj/structure/girder/bullet_act(var/obj/item/projectile/Proj)
+ //Girders only provide partial cover. There's a chance that the projectiles will just pass through. (unless you are trying to shoot the girder)
+ if(Proj.original != src && !prob(cover))
+ return -1 //pass through
//Tasers and the like should not damage girders.
- if(Proj.damage_type == HALLOSS || Proj.damage_type == TOX || Proj.damage_type == CLONE)
+ if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN))
return
- if(istype(Proj, /obj/item/projectile/beam))
- health -= Proj.damage
- ..()
- if(health <= 0)
- new /obj/item/stack/sheet/metal(get_turf(src))
- del(src)
+ var/damage = Proj.damage
+ if(!istype(Proj, /obj/item/projectile/beam))
+ damage *= 0.4 //non beams do reduced damage
+
+ health -= damage
+ ..()
+ if(health <= 0)
+ new /obj/item/stack/sheet/metal(get_turf(src))
+ del(src)
- return
+ return
/obj/structure/girder/attackby(obj/item/W as obj, mob/user as mob)
if(istype(W, /obj/item/weapon/wrench) && state == 0)
@@ -209,11 +216,13 @@
icon_state = "displaced"
anchored = 0
health = 50
+ cover = 25
/obj/structure/girder/reinforced
icon_state = "reinforced"
state = 2
health = 500
+ cover = 80
/obj/structure/cultgirder
icon= 'icons/obj/cult.dmi'
@@ -222,6 +231,7 @@
density = 1
layer = 2
var/health = 250
+ var/cover = 70
/obj/structure/cultgirder/attack_generic(var/mob/user, var/damage, var/attack_message = "smashes apart", var/wallbreaker)
if(!damage || !wallbreaker)
@@ -258,6 +268,14 @@
dismantle()
/obj/structure/cultgirder/bullet_act(var/obj/item/projectile/Proj) //No beam check- How else will you destroy the cult girder with silver bullets?????
+ //Girders only provide partial cover. There's a chance that the projectiles will just pass through. (unless you are trying to shoot the girder)
+ if(Proj.original != src && !prob(cover))
+ return -1 //pass through
+
+ //Tasers and the like should not damage cultgirders.
+ if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN))
+ return
+
health -= Proj.damage
..()
if(health <= 0)
diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm
index 2b06bcb534..76eac1b6b4 100644
--- a/code/game/objects/structures/grille.dm
+++ b/code/game/objects/structures/grille.dm
@@ -59,16 +59,33 @@
return !density
/obj/structure/grille/bullet_act(var/obj/item/projectile/Proj)
-
if(!Proj) return
//Tasers and the like should not damage grilles.
- if(Proj.damage_type == HALLOSS)
+ if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN))
return
- src.health -= Proj.damage*0.2
- healthcheck()
- return 0
+ //Flimsy grilles aren't so great at stopping projectiles. However they can absorb some of the impact
+ var/damage = Proj.damage
+ var/passthrough
+ if(damage > 30)
+ passthrough = 1
+ if(prob(20))
+ Proj.damage *= 0.5 //weaken the projectile
+ else
+ //weaker bullets are affected to a greater extent
+ if(prob(20))
+ passthrough = 0
+ else
+ Proj.damage *= 0.5 //weaken the projectile
+ passthrough = 1
+
+ if(passthrough)
+ . = -1
+ damage *= 0.1 //if the bullet passes through then the grille avoids most of the damage
+
+ src.health -= damage*0.2
+ spawn(0) healthcheck() //spawn to make sure we return properly if the grille is deleted
/obj/structure/grille/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(iswirecutter(W))
diff --git a/code/game/objects/structures/inflatable.dm b/code/game/objects/structures/inflatable.dm
index 9c5182382b..5df70a54bb 100644
--- a/code/game/objects/structures/inflatable.dm
+++ b/code/game/objects/structures/inflatable.dm
@@ -38,6 +38,9 @@
return 0
/obj/structure/inflatable/bullet_act(var/obj/item/projectile/Proj)
+ if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN))
+ return
+
health -= Proj.damage
..()
if(health <= 0)
diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm
index 58e1a81b97..93868d720d 100644
--- a/code/game/objects/structures/mirror.dm
+++ b/code/game/objects/structures/mirror.dm
@@ -1,7 +1,7 @@
//wip wip wup
/obj/structure/mirror
- name = "\improper SalonPro Nano-Mirror(TM)"
- desc = "The leading technology in hair salon products, utilizing nano-machinery to style your hair just right."
+ name = "mirror"
+ desc = "A SalonPro Nano-Mirror(TM) brand mirror! The leading technology in hair salon products, utilizing nano-machinery to style your hair just right."
icon = 'icons/obj/watercloset.dmi'
icon_state = "mirror"
density = 0
@@ -70,6 +70,9 @@
/obj/structure/mirror/bullet_act(var/obj/item/projectile/Proj)
+ if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN))
+ return
+
if(prob(Proj.damage * 2))
if(!shattered)
shatter()
diff --git a/code/game/objects/structures/safe.dm b/code/game/objects/structures/safe.dm
index a219268d04..199635cd0f 100644
--- a/code/game/objects/structures/safe.dm
+++ b/code/game/objects/structures/safe.dm
@@ -90,7 +90,7 @@ FLOOR SAFES
var/mob/living/carbon/human/user = usr
var/canhear = 0
- if(istype(user.l_hand, /obj/item/clothing/tie/stethoscope) || istype(user.r_hand, /obj/item/clothing/tie/stethoscope))
+ if(istype(user.l_hand, /obj/item/clothing/accessory/stethoscope) || istype(user.r_hand, /obj/item/clothing/accessory/stethoscope))
canhear = 1
if(href_list["open"])
@@ -155,7 +155,7 @@ FLOOR SAFES
user << "[I] won't fit in [src]."
return
else
- if(istype(I, /obj/item/clothing/tie/stethoscope))
+ if(istype(I, /obj/item/clothing/accessory/stethoscope))
user << "Hold [I] in one of your hands while you manipulate the dial."
return
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index 028773b33b..6b7e5bd457 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -100,7 +100,7 @@
/obj/structure/window/bullet_act(var/obj/item/projectile/Proj)
//Tasers and the like should not damage windows.
- if(Proj.damage_type == HALLOSS)
+ if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN))
return
..()
@@ -504,4 +504,4 @@
if (W.id == src.id || !W.id)
spawn( 0 )
W.toggle()
- return
\ No newline at end of file
+ return
diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm
index 572ed0ff8d..9b85c90e16 100644
--- a/code/game/turfs/simulated/walls.dm
+++ b/code/game/turfs/simulated/walls.dm
@@ -6,8 +6,7 @@
var/rotting = 0
var/damage = 0
- var/damage_cap = 100 //Wall will break down to girders if damage reaches this point
- var/armor = 0.5 // Damage is multiplied by this
+ var/damage_cap = 150 //Wall will break down to girders if damage reaches this point
var/damage_overlay
var/global/damage_overlays[8]
@@ -30,7 +29,7 @@
return
//cap the amount of damage, so that things like emitters can't destroy walls in one hit.
- var/damage = min(Proj.damage, 100) * armor
+ var/damage = min(Proj.damage, 100)
take_damage(damage)
return
@@ -39,12 +38,12 @@
..()
if(ismob(AM))
return
-
+
var/tforce = AM:throwforce * (speed/THROWFORCE_SPEED_DIVISOR)
if (tforce < 15)
return
-
- take_damage(tforce * armor)
+
+ take_damage(tforce)
/turf/simulated/wall/Del()
for(var/obj/effect/E in src) if(E.name == "Wallrot") del E
@@ -475,7 +474,7 @@
else if(istype(W,/obj/item/weapon/rcd)) //I bitterly resent having to write this. ~Z
return
-
+
else if(istype(W, /obj/item/weapon/reagent_containers))
return // They tend to have meaningful afterattack - let them apply it without destroying a rotting wall
diff --git a/code/game/turfs/simulated/walls_reinforced.dm b/code/game/turfs/simulated/walls_reinforced.dm
index b08363a715..5eddfc8b71 100644
--- a/code/game/turfs/simulated/walls_reinforced.dm
+++ b/code/game/turfs/simulated/walls_reinforced.dm
@@ -5,9 +5,8 @@
opacity = 1
density = 1
- damage_cap = 500
+ damage_cap = 800
max_temperature = 6000
- armor = 0.1 // Only 10% damage from gunfire, it's made from strong alloys and stuff.
walltype = "rwall"
@@ -294,7 +293,7 @@
else if(istype(W, /obj/item/weapon/reagent_containers))
return // They tend to have meaningful afterattack - let them apply it without destroying a rotting wall
-
+
//Finally, CHECKING FOR FALSE WALLS if it isn't damaged
else if(!d_state)
return attack_hand(user)
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index 1f86703322..dfd2b480d6 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -54,18 +54,6 @@
step(user.pulling, get_dir(user.pulling.loc, src))
return 1
-/turf/bullet_act(var/obj/item/projectile/Proj)
- if(istype(Proj ,/obj/item/projectile/beam/pulse))
- src.ex_act(2)
- ..()
- return 0
-
-/turf/bullet_act(var/obj/item/projectile/Proj)
- if(istype(Proj ,/obj/item/projectile/bullet/gyro))
- explosion(src, -1, 0, 2)
- ..()
- return 0
-
/turf/Enter(atom/movable/mover as mob|obj, atom/forget as mob|obj|turf|area)
if(movement_disabled && usr.ckey != movement_disabled_exception)
usr << "\red Movement is admin-disabled." //This is to identify lag problems
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 0509b7b915..14c70df792 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -111,6 +111,9 @@ var/list/admin_verbs_spawn = list(
/datum/admins/proc/spawn_plant,
/datum/admins/proc/spawn_atom, /*allows us to spawn instances*/
/client/proc/respawn_character,
+ /client/proc/FireLaser,
+ /client/proc/FireCannons,
+ /client/proc/ChangeIcarusPosition,
/client/proc/virus2_editor
)
var/list/admin_verbs_server = list(
diff --git a/code/modules/admin/verbs/icarus.dm b/code/modules/admin/verbs/icarus.dm
new file mode 100644
index 0000000000..cccda899b3
--- /dev/null
+++ b/code/modules/admin/verbs/icarus.dm
@@ -0,0 +1,125 @@
+/client/proc/FireLaser()
+ set name = "Fire the Icarus lasers"
+ set desc = "Fires a laser bolt at your position. You should only do this as a(n) (a)ghost"
+ set category = "Fun"
+
+ if(!src.holder)
+ src << "Only administrators may use this command."
+ return
+
+ Icarus_FireLaser(get_turf(src.mob))
+
+
+/client/proc/FireCannons()
+ set name = "Fire the Icarus cannons"
+ set desc = "Fires an explosive missile at your position. You should only do this as a(n) (a)ghost."
+ set category = "Fun"
+
+ if(!src.holder)
+ src << "Only administrators may use this command."
+ return
+
+ Icarus_FireCannon(get_turf(src.mob))
+
+
+/client/proc/ChangeIcarusPosition()
+ set name = "Adjust Icarus Position"
+ set desc = "Lets you chose the position of the Icarus in regards to the map."
+ set category = "Fun"
+
+ if(!src.holder)
+ src << "Only administrators may use this command."
+ return
+
+ Icarus_SetPosition(src)
+
+var/icarus_position = SOUTH
+
+proc/Icarus_FireLaser(var/turf/target)
+ // Find the world edge to fire from.
+ var/x = icarus_position & EAST ? world.maxx : icarus_position & WEST ? 1 : target.x
+ var/y = icarus_position & NORTH ? world.maxy : icarus_position & SOUTH ? 1 : target.y
+ var/x_off = x != target.x ? abs(target.x - x) : INFINITY
+ var/y_off = y != target.y ? abs(target.y - y) : INFINITY
+ // Get the minimum number of steps using the rise/run shit.
+ var/iterations = round(min(x_off, y_off)) - 14 // We cannot fire straight from the edge since teleport thing.
+
+ // Now we can get the location of the start.
+ x = target.x + (icarus_position & EAST ? iterations : icarus_position & WEST ? -iterations : 0)
+ y = target.y + (icarus_position & NORTH ? iterations : icarus_position & SOUTH ? -iterations : 0)
+
+ var/turf/start = locate(x, y, target.z)
+
+ // should step down as:
+ // 1000, 500, 333, 250, 200, 167, 142, 125, 111, 100, 90
+ var/damage = 1000
+ for(var/i in 2 to 12)
+ var/obj/item/projectile/beam/in_chamber = new (start)
+ in_chamber.original = target
+ in_chamber.starting = start
+ in_chamber.silenced = 1
+ in_chamber.yo = icarus_position & NORTH ? -1 : icarus_position & SOUTH ? 1 : 0
+ in_chamber.xo = icarus_position & EAST ? -1 : icarus_position & WEST ? 1 : 0
+ in_chamber.damage = damage
+ in_chamber.kill_count = 500
+ in_chamber.process()
+ damage -= damage / i
+ sleep(-1)
+
+ // Let everyone know what hit them.
+ var/obj/item/projectile/beam/in_chamber = new (start)
+ in_chamber.original = target
+ in_chamber.starting = start
+ in_chamber.silenced = 0
+ in_chamber.yo = icarus_position & NORTH ? -1 : icarus_position & SOUTH ? 1 : 0
+ in_chamber.xo = icarus_position & EAST ? -1 : icarus_position & WEST ? 1 : 0
+ in_chamber.kill_count = 500
+ in_chamber.damage = 0
+ in_chamber.name = "point defense laser"
+ in_chamber.firer = "Icarus" // Never displayed, but we want this to display the hit message.
+ in_chamber.process()
+
+proc/Icarus_FireCannon(var/turf/target)
+ // Find the world edge to fire from.
+ var/x = icarus_position & EAST ? world.maxx : icarus_position & WEST ? 1 : target.x
+ var/y = icarus_position & NORTH ? world.maxy : icarus_position & SOUTH ? 1 : target.y
+ var/x_off = x != target.x ? abs(target.x - x) : INFINITY
+ var/y_off = y != target.y ? abs(target.y - y) : INFINITY
+ // Get the minimum number of steps using the rise/run shit.
+ var/iterations = round(min(x_off, y_off)) - 14 // We cannot fire straight from the edge since teleport thing.
+
+ // Now we can get the location of the start.
+ x = target.x + (icarus_position & EAST ? iterations : icarus_position & WEST ? -iterations : 0)
+ y = target.y + (icarus_position & NORTH ? iterations : icarus_position & SOUTH ? -iterations : 0)
+
+ var/turf/start = locate(x, y, target.z)
+
+ // Now we find the corresponding turf on the other side of the level.
+ // Yeah, yeah. Overuse of the terinary operator. So sue me.
+ x = icarus_position & EAST ? 1 : icarus_position & WEST ? world.maxx : target.x
+ y = icarus_position & NORTH ? 1 : icarus_position & SOUTH ? world.maxy : target.y
+ x_off = x != target.x ? abs(target.x - x) : INFINITY
+ y_off = y != target.y ? abs(target.y - y) : INFINITY
+ iterations = round(min(x_off, y_off))
+ x = target.x + (icarus_position & EAST ? -iterations : icarus_position & WEST ? iterations : 0)
+ y = target.y + (icarus_position & NORTH ? -iterations : icarus_position & SOUTH ? iterations : 0)
+ target = locate(x, y, target.z)
+
+ // Finally fire the fucker.
+ var/obj/effect/meteor/small/projectile = new (start)
+ projectile.dest = target
+ projectile.name = "main gun projectile" // stealthy
+ projectile.hits = 6
+ projectile.detonation_chance = 99 // it's a missile/cannon round thing!
+
+ // Make sure it travels
+ spawn(0)
+ walk_towards(projectile, projectile.dest, 1)
+
+proc/Icarus_SetPosition(var/user)
+ var/global/list/directions = list("North" = 1, "North East" = 5, "East" = 4, "South East" = 6, "South" = 2, "South West" = 10, "West" = 8, "North West" = 9)
+ var/direction = input(user, "Where should the Icarus fire from?", "Icarus Comms") as null|anything in directions
+ if(!direction)
+ return
+
+ icarus_position = directions[direction]
\ No newline at end of file
diff --git a/code/modules/client/preferences_gear.dm b/code/modules/client/preferences_gear.dm
index d265babc1b..d788a41cc9 100644
--- a/code/modules/client/preferences_gear.dm
+++ b/code/modules/client/preferences_gear.dm
@@ -375,88 +375,88 @@ var/global/list/gear_datums = list()
/datum/gear/armband_cargo
display_name = "armband, cargo"
- path = /obj/item/clothing/tie/armband/cargo
+ path = /obj/item/clothing/accessory/armband/cargo
slot = slot_tie
cost = 1
/datum/gear/armband_emt
display_name = "armband, EMT"
- path = /obj/item/clothing/tie/armband/medgreen
+ path = /obj/item/clothing/accessory/armband/medgreen
slot = slot_tie
cost = 2
/datum/gear/armband_engineering
display_name = "armband, engineering"
- path = /obj/item/clothing/tie/armband/engine
+ path = /obj/item/clothing/accessory/armband/engine
slot = slot_tie
cost = 1
/datum/gear/armband_hydroponics
display_name = "armband, hydroponics"
- path = /obj/item/clothing/tie/armband/hydro
+ path = /obj/item/clothing/accessory/armband/hydro
slot = slot_tie
cost = 1
/datum/gear/armband_medical
display_name = "armband, medical"
- path = /obj/item/clothing/tie/armband/med
+ path = /obj/item/clothing/accessory/armband/med
slot = slot_tie
cost = 1
/datum/gear/armband
display_name = "armband, red"
- path = /obj/item/clothing/tie/armband
+ path = /obj/item/clothing/accessory/armband
slot = slot_tie
cost = 1
/datum/gear/armband_science
display_name = "armband, science"
- path = /obj/item/clothing/tie/armband/science
+ path = /obj/item/clothing/accessory/armband/science
slot = slot_tie
cost = 1
/datum/gear/armpit
display_name = "shoulder holster"
- path = /obj/item/clothing/tie/holster/armpit
+ path = /obj/item/clothing/accessory/holster/armpit
slot = slot_tie
cost = 2
allowed_roles = list("Captain", "Head of Personnel", "Security Officer", "Warden", "Head of Security")
/datum/gear/tie_blue
display_name = "tie, blue"
- path = /obj/item/clothing/tie/blue
+ path = /obj/item/clothing/accessory/blue
slot = slot_tie
cost = 1
/datum/gear/tie_red
display_name = "tie, red"
- path = /obj/item/clothing/tie/red
+ path = /obj/item/clothing/accessory/red
slot = slot_tie
cost = 1
/datum/gear/tie_horrible
display_name = "tie, socially disgraceful"
- path = /obj/item/clothing/tie/horrible
+ path = /obj/item/clothing/accessory/horrible
slot = slot_tie
cost = 1
/datum/gear/brown_vest
display_name = "webbing, engineering"
- path = /obj/item/clothing/tie/storage/brown_vest
+ path = /obj/item/clothing/accessory/storage/brown_vest
slot = slot_tie
cost = 2
allowed_roles = list("Station Engineer","Atmospheric Technician","Chief Engineer")
/datum/gear/black_vest
display_name = "webbing, security"
- path = /obj/item/clothing/tie/storage/black_vest
+ path = /obj/item/clothing/accessory/storage/black_vest
slot = slot_tie
cost = 2
allowed_roles = list("Security Officer","Head of Security","Warden")
/datum/gear/webbing
display_name = "webbing, simple"
- path = /obj/item/clothing/tie/storage/webbing
+ path = /obj/item/clothing/accessory/storage/webbing
slot = slot_tie
cost = 2
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index 6741fdb780..673189ff79 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -68,7 +68,7 @@
/obj/item/clothing/head/helmet/refit_for_species(var/target_species)
if(!species_restricted)
return //this item doesn't use the species_restricted system
-
+
//Set species_restricted list
switch(target_species)
if("Skrell")
@@ -404,7 +404,7 @@ BLIND // can't see anything
2 = Report detailed damages
3 = Report location
*/
- var/obj/item/clothing/tie/hastie = null
+ var/list/accessories = list()
var/displays_id = 1
sprite_sheets = list("Vox" = 'icons/mob/species/vox/uniform.dmi')
@@ -413,28 +413,44 @@ BLIND // can't see anything
var/mob/M = src.loc
M.update_inv_w_uniform()
+/obj/item/clothing/under/proc/can_attach_accessory(obj/item/clothing/accessory/A)
+ if(istype(A))
+ .=1
+ else
+ return 0
+ if(accessories.len && (A.slot in list("utility","armband")))
+ for(var/obj/item/clothing/accessory/AC in accessories)
+ if (AC.slot == A.slot)
+ return 0
+
/obj/item/clothing/under/attackby(obj/item/I, mob/user)
- if(hastie)
- hastie.attackby(I, user)
- return
+ if(istype(I, /obj/item/clothing/accessory))
+ var/obj/item/clothing/accessory/A = I
+ if(can_attach_accessory(A))
+ user.drop_item()
+ accessories += A
+ A.on_attached(src, user)
- if(!hastie && istype(I, /obj/item/clothing/tie))
- user.drop_item()
- hastie = I
- hastie.on_attached(src, user)
+ if(istype(loc, /mob/living/carbon/human))
+ var/mob/living/carbon/human/H = loc
+ H.update_inv_w_uniform()
- if(istype(loc, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = loc
- H.update_inv_w_uniform()
+ return
+ else
+ user << "You cannot attach more accessories of this type to [src]."
+ if(accessories.len)
+ for(var/obj/item/clothing/accessory/A in accessories)
+ A.attackby(I, user)
return
..()
/obj/item/clothing/under/attack_hand(mob/user as mob)
//only forward to the attached accessory if the clothing is equipped (not in a storage)
- if(hastie && src.loc == user)
- hastie.attack_hand(user)
+ if(accessories.len && src.loc == user)
+ for(var/obj/item/clothing/accessory/A in accessories)
+ A.attack_hand(user)
return
if ((ishuman(usr) || ismonkey(usr)) && src.loc == user) //make it harder to accidentally undress yourself
@@ -471,8 +487,9 @@ BLIND // can't see anything
user << "Its vital tracker appears to be enabled."
if(3)
user << "Its vital tracker and tracking beacon appear to be enabled."
- if(hastie)
- user << "\A [hastie] is clipped to it."
+ if(accessories.len)
+ for(var/obj/item/clothing/accessory/A in accessories)
+ user << "\A [A] is attached to it."
/obj/item/clothing/under/proc/set_sensors(mob/usr as mob)
var/mob/M = usr
@@ -543,12 +560,12 @@ BLIND // can't see anything
else
usr << "You cannot roll down the uniform!"
-/obj/item/clothing/under/proc/remove_accessory(mob/user as mob)
- if(!hastie)
+/obj/item/clothing/under/proc/remove_accessory(mob/user, obj/item/clothing/accessory/A)
+ if(!(A in accessories))
return
- hastie.on_removed(user)
- hastie = null
+ A.on_removed(user)
+ accessories -= A
update_clothing_icon()
/obj/item/clothing/under/verb/removetie()
@@ -557,14 +574,20 @@ BLIND // can't see anything
set src in usr
if(!istype(usr, /mob/living)) return
if(usr.stat) return
-
- src.remove_accessory(usr)
+ if(!accessories.len) return
+ var/obj/item/clothing/accessory/A
+ if(accessories.len > 1)
+ A = input("Select an accessory to remove from [src]") as null|anything in accessories
+ else
+ A = accessories[1]
+ src.remove_accessory(usr,A)
/obj/item/clothing/under/rank/New()
sensor_mode = pick(0,1,2,3)
..()
/obj/item/clothing/under/emp_act(severity)
- if (hastie)
- hastie.emp_act(severity)
+ if(accessories.len)
+ for(var/obj/item/clothing/accessory/A in accessories)
+ A.emp_act(severity)
..()
\ No newline at end of file
diff --git a/code/modules/clothing/spacesuits/rig/modules/rig_weapons.dm b/code/modules/clothing/spacesuits/rig/modules/rig_weapons.dm
index d8373e8bbe..792a6ed0d0 100644
--- a/code/modules/clothing/spacesuits/rig/modules/rig_weapons.dm
+++ b/code/modules/clothing/spacesuits/rig/modules/rig_weapons.dm
@@ -28,7 +28,7 @@
var/obj/item/weapon/rig/suit = H.back
if(istype(suit) && suit.cell && suit.cell.charge >= 250)
suit.cell.use(250)
- var/prog_path = text2path(projectile_type)
+ var/prog_path = projectile_type
in_chamber = new prog_path(src)
return 1
return 0
@@ -45,7 +45,7 @@
var/obj/item/weapon/rig/suit = H.back
if(istype(suit) && suit.cell && suit.cell.charge >= 250)
suit.cell.use(250)
- var/prog_path = text2path(projectile_type)
+ var/prog_path = projectile_type
in_chamber = new prog_path(src)
return 1
return 0
\ No newline at end of file
diff --git a/code/modules/clothing/under/accessories/accessory.dm b/code/modules/clothing/under/accessories/accessory.dm
new file mode 100644
index 0000000000..e1c9a25c24
--- /dev/null
+++ b/code/modules/clothing/under/accessories/accessory.dm
@@ -0,0 +1,226 @@
+/obj/item/clothing/accessory
+ name = "tie"
+ desc = "A neosilk clip-on tie."
+ icon = 'icons/obj/clothing/ties.dmi'
+ icon_state = "bluetie"
+ item_state = "" //no inhands
+ item_color = "bluetie"
+ slot_flags = SLOT_TIE
+ w_class = 2.0
+ var/slot = "decor"
+ var/obj/item/clothing/under/has_suit = null //the suit the tie may be attached to
+ var/image/inv_overlay = null //overlay used when attached to clothing.
+
+/obj/item/clothing/accessory/New()
+ ..()
+ inv_overlay = image("icon" = 'icons/obj/clothing/ties_overlay.dmi', "icon_state" = "[item_color? "[item_color]" : "[icon_state]"]")
+
+//when user attached an accessory to S
+/obj/item/clothing/accessory/proc/on_attached(obj/item/clothing/under/S, mob/user as mob)
+ if(!istype(S))
+ return
+ has_suit = S
+ loc = has_suit
+ has_suit.overlays += inv_overlay
+
+ user << "You attach [src] to [has_suit]."
+ src.add_fingerprint(user)
+
+/obj/item/clothing/accessory/proc/on_removed(mob/user as mob)
+ if(!has_suit)
+ return
+ has_suit.overlays -= inv_overlay
+ has_suit = null
+ usr.put_in_hands(src)
+ src.add_fingerprint(user)
+
+//default attackby behaviour
+/obj/item/clothing/accessory/attackby(obj/item/I, mob/user)
+ ..()
+
+//default attack_hand behaviour
+/obj/item/clothing/accessory/attack_hand(mob/user as mob)
+ if(has_suit)
+ return //we aren't an object on the ground so don't call parent
+ ..()
+
+/obj/item/clothing/accessory/blue
+ name = "blue tie"
+ icon_state = "bluetie"
+ item_color = "bluetie"
+
+/obj/item/clothing/accessory/red
+ name = "red tie"
+ icon_state = "redtie"
+ item_color = "redtie"
+
+/obj/item/clothing/accessory/horrible
+ name = "horrible tie"
+ desc = "A neosilk clip-on tie. This one is disgusting."
+ icon_state = "horribletie"
+ item_color = "horribletie"
+
+/obj/item/clothing/accessory/stethoscope
+ name = "stethoscope"
+ desc = "An outdated medical apparatus for listening to the sounds of the human body. It also makes you look like you know what you're doing."
+ icon_state = "stethoscope"
+ item_color = "stethoscope"
+
+/obj/item/clothing/accessory/stethoscope/attack(mob/living/carbon/human/M, mob/living/user)
+ if(ishuman(M) && isliving(user))
+ if(user.a_intent == "help")
+ var/body_part = parse_zone(user.zone_sel.selecting)
+ if(body_part)
+ var/their = "their"
+ switch(M.gender)
+ if(MALE) their = "his"
+ if(FEMALE) their = "her"
+
+ var/sound = "pulse"
+ var/sound_strength
+
+ if(M.stat == DEAD || (M.status_flags&FAKEDEATH))
+ sound_strength = "cannot hear"
+ sound = "anything"
+ else
+ sound_strength = "hear a weak"
+ switch(body_part)
+ if("chest")
+ if(M.oxyloss < 50)
+ sound_strength = "hear a healthy"
+ sound = "pulse and respiration"
+ if("eyes","mouth")
+ sound_strength = "cannot hear"
+ sound = "anything"
+ else
+ sound_strength = "hear a weak"
+
+ user.visible_message("[user] places [src] against [M]'s [body_part] and listens attentively.", "You place [src] against [their] [body_part]. You [sound_strength] [sound].")
+ return
+ return ..(M,user)
+
+
+//Medals
+/obj/item/clothing/accessory/medal
+ name = "bronze medal"
+ desc = "A bronze medal."
+ icon_state = "bronze"
+ item_color = "bronze"
+
+/obj/item/clothing/accessory/medal/conduct
+ name = "distinguished conduct medal"
+ desc = "A bronze medal awarded for distinguished conduct. Whilst a great honor, this is most basic award given by Nanotrasen. It is often awarded by a captain to a member of his crew."
+
+/obj/item/clothing/accessory/medal/bronze_heart
+ name = "bronze heart medal"
+ desc = "A bronze heart-shaped medal awarded for sacrifice. It is often awarded posthumously or for severe injury in the line of duty."
+ icon_state = "bronze_heart"
+
+/obj/item/clothing/accessory/medal/nobel_science
+ name = "nobel sciences award"
+ desc = "A bronze medal which represents significant contributions to the field of science or engineering."
+
+/obj/item/clothing/accessory/medal/silver
+ name = "silver medal"
+ desc = "A silver medal."
+ icon_state = "silver"
+ item_color = "silver"
+
+/obj/item/clothing/accessory/medal/silver/valor
+ name = "medal of valor"
+ desc = "A silver medal awarded for acts of exceptional valor."
+
+/obj/item/clothing/accessory/medal/silver/security
+ name = "robust security award"
+ desc = "An award for distinguished combat and sacrifice in defence of Nanotrasen's commercial interests. Often awarded to security staff."
+
+/obj/item/clothing/accessory/medal/gold
+ name = "gold medal"
+ desc = "A prestigious golden medal."
+ icon_state = "gold"
+ item_color = "gold"
+
+/obj/item/clothing/accessory/medal/gold/captain
+ name = "medal of captaincy"
+ desc = "A golden medal awarded exclusively to those promoted to the rank of captain. It signifies the codified responsibilities of a captain to Nanotrasen, and their undisputable authority over their crew."
+
+/obj/item/clothing/accessory/medal/gold/heroism
+ name = "medal of exceptional heroism"
+ desc = "An extremely rare golden medal awarded only by CentComm. To recieve such a medal is the highest honor and as such, very few exist. This medal is almost never awarded to anybody but commanders."
+
+/*
+ Holobadges are worn on the belt or neck, and can be used to show that the holder is an authorized
+ Security agent - the user details can be imprinted on the badge with a Security-access ID card,
+ or they can be emagged to accept any ID for use in disguises.
+*/
+
+/obj/item/clothing/accessory/holobadge
+ name = "holobadge"
+ desc = "This glowing blue badge marks the holder as THE LAW."
+ icon_state = "holobadge"
+ item_color = "holobadge"
+ slot_flags = SLOT_BELT | SLOT_TIE
+
+ var/emagged = 0 //Emagging removes Sec check.
+ var/stored_name = null
+
+/obj/item/clothing/accessory/holobadge/cord
+ icon_state = "holobadge-cord"
+ item_color = "holobadge-cord"
+ slot_flags = SLOT_MASK | SLOT_TIE
+
+/obj/item/clothing/accessory/holobadge/attack_self(mob/user as mob)
+ if(!stored_name)
+ user << "Waving around a badge before swiping an ID would be pretty pointless."
+ return
+ if(isliving(user))
+ user.visible_message("\red [user] displays their NanoTrasen Internal Security Legal Authorization Badge.\nIt reads: [stored_name], NT Security.","\red You display your NanoTrasen Internal Security Legal Authorization Badge.\nIt reads: [stored_name], NT Security.")
+
+/obj/item/clothing/accessory/holobadge/attackby(var/obj/item/O as obj, var/mob/user as mob)
+
+ if (istype(O, /obj/item/weapon/card/emag))
+ if (emagged)
+ user << "\red [src] is already cracked."
+ return
+ else
+ emagged = 1
+ user << "\red You swipe [O] and crack the holobadge security checks."
+ return
+
+ else if(istype(O, /obj/item/weapon/card/id) || istype(O, /obj/item/device/pda))
+
+ var/obj/item/weapon/card/id/id_card = null
+
+ if(istype(O, /obj/item/weapon/card/id))
+ id_card = O
+ else
+ var/obj/item/device/pda/pda = O
+ id_card = pda.id
+
+ if(access_security in id_card.access || emagged)
+ user << "You imprint your ID details onto the badge."
+ stored_name = id_card.registered_name
+ name = "holobadge ([stored_name])"
+ desc = "This glowing blue badge marks [stored_name] as THE LAW."
+ else
+ user << "[src] rejects your insufficient access rights."
+ return
+ ..()
+
+/obj/item/clothing/accessory/holobadge/attack(mob/living/carbon/human/M, mob/living/user)
+ if(isliving(user))
+ user.visible_message("\red [user] invades [M]'s personal space, thrusting [src] into their face insistently.","\red You invade [M]'s personal space, thrusting [src] into their face insistently. You are the law.")
+
+/obj/item/weapon/storage/box/holobadge
+ name = "holobadge box"
+ desc = "A box claiming to contain holobadges."
+ New()
+ new /obj/item/clothing/accessory/holobadge(src)
+ new /obj/item/clothing/accessory/holobadge(src)
+ new /obj/item/clothing/accessory/holobadge(src)
+ new /obj/item/clothing/accessory/holobadge(src)
+ new /obj/item/clothing/accessory/holobadge/cord(src)
+ new /obj/item/clothing/accessory/holobadge/cord(src)
+ ..()
+ return
+
diff --git a/code/modules/clothing/under/accessories/armband.dm b/code/modules/clothing/under/accessories/armband.dm
new file mode 100644
index 0000000000..67d0208b6d
--- /dev/null
+++ b/code/modules/clothing/under/accessories/armband.dm
@@ -0,0 +1,42 @@
+/obj/item/clothing/accessory/armband
+ name = "red armband"
+ desc = "A fancy red armband!"
+ icon_state = "red"
+ item_color = "red"
+ slot = "armband"
+
+/obj/item/clothing/accessory/armband/cargo
+ name = "cargo armband"
+ desc = "An armband, worn by the crew to display which department they're assigned to. This one is brown."
+ icon_state = "cargo"
+ item_color = "cargo"
+
+/obj/item/clothing/accessory/armband/engine
+ name = "engineering armband"
+ desc = "An armband, worn by the crew to display which department they're assigned to. This one is orange with a reflective strip!"
+ icon_state = "engie"
+ item_color = "engie"
+
+/obj/item/clothing/accessory/armband/science
+ name = "science armband"
+ desc = "An armband, worn by the crew to display which department they're assigned to. This one is purple."
+ icon_state = "rnd"
+ item_color = "rnd"
+
+/obj/item/clothing/accessory/armband/hydro
+ name = "hydroponics armband"
+ desc = "An armband, worn by the crew to display which department they're assigned to. This one is green and blue."
+ icon_state = "hydro"
+ item_color = "hydro"
+
+/obj/item/clothing/accessory/armband/med
+ name = "medical armband"
+ desc = "An armband, worn by the crew to display which department they're assigned to. This one is white."
+ icon_state = "med"
+ item_color = "med"
+
+/obj/item/clothing/accessory/armband/medgreen
+ name = "EMT armband"
+ desc = "An armband, worn by the crew to display which department they're assigned to. This one is white and green."
+ icon_state = "medgreen"
+ item_color = "medgreen"
diff --git a/code/modules/clothing/under/accessories/holster.dm b/code/modules/clothing/under/accessories/holster.dm
new file mode 100644
index 0000000000..af2743e43f
--- /dev/null
+++ b/code/modules/clothing/under/accessories/holster.dm
@@ -0,0 +1,119 @@
+/obj/item/clothing/accessory/holster
+ name = "shoulder holster"
+ desc = "A handgun holster."
+ icon_state = "holster"
+ item_color = "holster"
+ slot = "utility"
+ var/obj/item/weapon/gun/holstered = null
+
+//subtypes can override this to specify what can be holstered
+/obj/item/clothing/accessory/holster/proc/can_holster(obj/item/weapon/gun/W)
+ return W.isHandgun()
+
+/obj/item/clothing/accessory/holster/proc/holster(obj/item/I, mob/user as mob)
+ if(holstered)
+ user << "There is already a [holstered] holstered here!"
+ return
+
+ if (!istype(I, /obj/item/weapon/gun))
+ user << "Only guns can be holstered!"
+ return
+
+ var/obj/item/weapon/gun/W = I
+ if (!can_holster(W))
+ user << "This [W] won't fit in the [src]!"
+ return
+
+ holstered = W
+ user.drop_from_inventory(holstered)
+ holstered.loc = src
+ holstered.add_fingerprint(user)
+ user.visible_message("[user] holsters the [holstered].", "You holster the [holstered].")
+
+/obj/item/clothing/accessory/holster/proc/unholster(mob/user as mob)
+ if(!holstered)
+ return
+
+ if(istype(user.get_active_hand(),/obj) && istype(user.get_inactive_hand(),/obj))
+ user << "You need an empty hand to draw the [holstered]!"
+ else
+ if(user.a_intent == "hurt")
+ usr.visible_message("\red [user] draws the [holstered], ready to shoot!", \
+ "You draw the [holstered], ready to shoot!")
+ else
+ user.visible_message("[user] draws the [holstered], pointing it at the ground.", \
+ "You draw the [holstered], pointing it at the ground.")
+ user.put_in_hands(holstered)
+ holstered.add_fingerprint(user)
+ holstered = null
+
+/obj/item/clothing/accessory/holster/attack_hand(mob/user as mob)
+ if (has_suit) //if we are part of a suit
+ if (holstered)
+ unholster(user)
+ return
+
+ ..(user)
+
+/obj/item/clothing/accessory/holster/attackby(obj/item/W as obj, mob/user as mob)
+ holster(W, user)
+
+/obj/item/clothing/accessory/holster/emp_act(severity)
+ if (holstered)
+ holstered.emp_act(severity)
+ ..()
+
+/obj/item/clothing/accessory/holster/examine(mob/user)
+ ..(user)
+ if (holstered)
+ user << "A [holstered] is holstered here."
+ else
+ user << "It is empty."
+
+/obj/item/clothing/accessory/holster/on_attached(obj/item/clothing/under/S, mob/user as mob)
+ ..()
+ has_suit.verbs += /obj/item/clothing/accessory/holster/verb/holster_verb
+
+/obj/item/clothing/accessory/holster/on_removed(mob/user as mob)
+ has_suit.verbs -= /obj/item/clothing/accessory/holster/verb/holster_verb
+ ..()
+
+//For the holster hotkey
+/obj/item/clothing/accessory/holster/verb/holster_verb()
+ set name = "Holster"
+ set category = "Object"
+ set src in usr
+ if(!istype(usr, /mob/living)) return
+ if(usr.stat) return
+
+ var/obj/item/clothing/accessory/holster/H = null
+ if (istype(src, /obj/item/clothing/accessory/holster))
+ H = src
+ else if (istype(src, /obj/item/clothing/under))
+ var/obj/item/clothing/under/S = src
+ if (S.accessories.len)
+ H = locate() in S.accessories
+
+ if (!H)
+ usr << "Something is very wrong."
+
+ if(!H.holstered)
+ if(!istype(usr.get_active_hand(), /obj/item/weapon/gun))
+ usr << "You need your gun equiped to holster it."
+ return
+ var/obj/item/weapon/gun/W = usr.get_active_hand()
+ H.holster(W, usr)
+ else
+ H.unholster(usr)
+
+/obj/item/clothing/accessory/holster/armpit
+ name = "shoulder holster"
+ desc = "A worn-out handgun holster. Perfect for concealed carry"
+ icon_state = "holster"
+ item_color = "holster"
+
+/obj/item/clothing/accessory/holster/waist
+ name = "shoulder holster"
+ desc = "A handgun holster. Made of expensive leather."
+ icon_state = "holster"
+ item_color = "holster_low"
\ No newline at end of file
diff --git a/code/modules/clothing/under/accessories/storage.dm b/code/modules/clothing/under/accessories/storage.dm
new file mode 100644
index 0000000000..32313e985d
--- /dev/null
+++ b/code/modules/clothing/under/accessories/storage.dm
@@ -0,0 +1,86 @@
+/obj/item/clothing/accessory/storage
+ name = "load bearing equipment"
+ desc = "Used to hold things when you don't have enough hands."
+ icon_state = "webbing"
+ item_color = "webbing"
+ slot = "utility"
+ var/slots = 3
+ var/obj/item/weapon/storage/internal/hold
+
+/obj/item/clothing/accessory/storage/New()
+ ..()
+ hold = new/obj/item/weapon/storage/internal(src)
+ hold.storage_slots = slots
+
+/obj/item/clothing/accessory/storage/attack_hand(mob/user as mob)
+ if (has_suit) //if we are part of a suit
+ hold.open(user)
+ return
+
+ if (hold.handle_attack_hand(user)) //otherwise interact as a regular storage item
+ ..(user)
+
+/obj/item/clothing/accessory/storage/MouseDrop(obj/over_object as obj)
+ if (has_suit)
+ return
+
+ if (hold.handle_mousedrop(usr, over_object))
+ ..(over_object)
+
+/obj/item/clothing/accessory/storage/attackby(obj/item/W as obj, mob/user as mob)
+ return hold.attackby(W, user)
+
+/obj/item/clothing/accessory/storage/emp_act(severity)
+ hold.emp_act(severity)
+ ..()
+
+/obj/item/clothing/accessory/storage/hear_talk(mob/M, var/msg, verb, datum/language/speaking)
+ hold.hear_talk(M, msg, verb, speaking)
+ ..()
+
+/obj/item/clothing/accessory/storage/attack_self(mob/user as mob)
+ user << "You empty [src]."
+ var/turf/T = get_turf(src)
+ hold.hide_from(usr)
+ for(var/obj/item/I in hold.contents)
+ hold.remove_from_storage(I, T)
+ src.add_fingerprint(user)
+
+/obj/item/clothing/accessory/storage/webbing
+ name = "webbing"
+ desc = "Strudy mess of synthcotton belts and buckles, ready to share your burden."
+ icon_state = "webbing"
+ item_color = "webbing"
+
+/obj/item/clothing/accessory/storage/black_vest
+ name = "black webbing vest"
+ desc = "Robust black synthcotton vest with lots of pockets to hold whatever you need, but cannot hold in hands."
+ icon_state = "vest_black"
+ item_color = "vest_black"
+ slots = 5
+
+/obj/item/clothing/accessory/storage/brown_vest
+ name = "brown webbing vest"
+ desc = "Worn brownish synthcotton vest with lots of pockets to unload your hands."
+ icon_state = "vest_brown"
+ item_color = "vest_brown"
+ slots = 5
+
+/obj/item/clothing/accessory/storage/knifeharness
+ name = "decorated harness"
+ desc = "A heavily decorated harness of sinew and leather with two knife-loops."
+ icon_state = "unathiharness2"
+ item_color = "unathiharness2"
+ slots = 2
+
+/obj/item/clothing/accessory/storage/knifeharness/New()
+ ..()
+ hold.max_combined_w_class = 4
+ hold.can_hold = list("/obj/item/weapon/hatchet/unathiknife",\
+ "/obj/item/weapon/kitchen/utensil/knife",\
+ "/obj/item/weapon/kitchen/utensil/pknife",\
+ "/obj/item/weapon/kitchenknife",\
+ "/obj/item/weapon/kitchenknife/ritual")
+
+ new /obj/item/weapon/hatchet/unathiknife(hold)
+ new /obj/item/weapon/hatchet/unathiknife(hold)
\ No newline at end of file
diff --git a/code/modules/clothing/under/jobs/medsci.dm b/code/modules/clothing/under/jobs/medsci.dm
index 40bc087429..b1554dd02a 100644
--- a/code/modules/clothing/under/jobs/medsci.dm
+++ b/code/modules/clothing/under/jobs/medsci.dm
@@ -130,6 +130,12 @@
icon_state = "scrubspurple"
item_color = "scrubspurple"
+/obj/item/clothing/under/rank/medical/black
+ name = "medical scrubs"
+ desc = "It's made of a special fiber that provides minor protection against biohazards. This one is in black."
+ icon_state = "scrubsblack"
+ item_color = "scrubsblack"
+
/obj/item/clothing/under/rank/psych
desc = "A basic white jumpsuit. It has turqouise markings that denote the wearer as a psychiatrist."
name = "psychiatrist's jumpsuit"
diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm
index 390ec7f541..bc4d37c672 100644
--- a/code/modules/clothing/under/miscellaneous.dm
+++ b/code/modules/clothing/under/miscellaneous.dm
@@ -479,9 +479,9 @@
/obj/item/clothing/under/serviceoveralls
name = "Workman outfit"
desc = "The very image of a working man. Not that you're probably doing work."
- icon_state = "mechanic_s"
- item_state = "mechanic_s"
- item_color = "mechanic_s"
+ icon_state = "mechanic"
+ item_state = "mechanic"
+ item_color = "mechanic"
/obj/item/clothing/under/cheongsam
name = "White Cheongsam"
diff --git a/code/modules/clothing/under/ties.dm b/code/modules/clothing/under/ties.dm
deleted file mode 100644
index 050a2716e0..0000000000
--- a/code/modules/clothing/under/ties.dm
+++ /dev/null
@@ -1,474 +0,0 @@
-/obj/item/clothing/tie
- name = "tie"
- desc = "A neosilk clip-on tie."
- icon = 'icons/obj/clothing/ties.dmi'
- icon_state = "bluetie"
- item_state = "" //no inhands
- item_color = "bluetie"
- slot_flags = SLOT_TIE
- w_class = 2.0
- var/obj/item/clothing/under/has_suit = null //the suit the tie may be attached to
- var/image/inv_overlay = null //overlay used when attached to clothing.
-
-/obj/item/clothing/tie/New()
- ..()
- inv_overlay = image("icon" = 'icons/obj/clothing/ties_overlay.dmi', "icon_state" = "[item_color? "[item_color]" : "[icon_state]"]")
-
-//when user attached an accessory to S
-/obj/item/clothing/tie/proc/on_attached(obj/item/clothing/under/S, mob/user as mob)
- if(!istype(S))
- return
- has_suit = S
- loc = has_suit
- has_suit.overlays += inv_overlay
-
- user << "You attach [src] to [has_suit]."
- src.add_fingerprint(user)
-
-/obj/item/clothing/tie/proc/on_removed(mob/user as mob)
- if(!has_suit)
- return
- has_suit.overlays -= inv_overlay
- has_suit = null
- usr.put_in_hands(src)
- src.add_fingerprint(user)
-
-//default attackby behaviour
-/obj/item/clothing/tie/attackby(obj/item/I, mob/user)
- ..()
-
-//default attack_hand behaviour
-/obj/item/clothing/tie/attack_hand(mob/user as mob)
- if(has_suit)
- has_suit.remove_accessory(user)
- return //we aren't an object on the ground so don't call parent
- ..()
-
-/obj/item/clothing/tie/blue
- name = "blue tie"
- icon_state = "bluetie"
- item_color = "bluetie"
-
-/obj/item/clothing/tie/red
- name = "red tie"
- icon_state = "redtie"
- item_color = "redtie"
-
-/obj/item/clothing/tie/horrible
- name = "horrible tie"
- desc = "A neosilk clip-on tie. This one is disgusting."
- icon_state = "horribletie"
- item_color = "horribletie"
-
-/obj/item/clothing/tie/stethoscope
- name = "stethoscope"
- desc = "An outdated medical apparatus for listening to the sounds of the human body. It also makes you look like you know what you're doing."
- icon_state = "stethoscope"
- item_color = "stethoscope"
-
-/obj/item/clothing/tie/stethoscope/attack(mob/living/carbon/human/M, mob/living/user)
- if(ishuman(M) && isliving(user))
- if(user.a_intent == "help")
- var/body_part = parse_zone(user.zone_sel.selecting)
- if(body_part)
- var/their = "their"
- switch(M.gender)
- if(MALE) their = "his"
- if(FEMALE) their = "her"
-
- var/sound = "pulse"
- var/sound_strength
-
- if(M.stat == DEAD || (M.status_flags&FAKEDEATH))
- sound_strength = "cannot hear"
- sound = "anything"
- else
- sound_strength = "hear a weak"
- switch(body_part)
- if("chest")
- if(M.oxyloss < 50)
- sound_strength = "hear a healthy"
- sound = "pulse and respiration"
- if("eyes","mouth")
- sound_strength = "cannot hear"
- sound = "anything"
- else
- sound_strength = "hear a weak"
-
- user.visible_message("[user] places [src] against [M]'s [body_part] and listens attentively.", "You place [src] against [their] [body_part]. You [sound_strength] [sound].")
- return
- return ..(M,user)
-
-
-//Medals
-/obj/item/clothing/tie/medal
- name = "bronze medal"
- desc = "A bronze medal."
- icon_state = "bronze"
- item_color = "bronze"
-
-/obj/item/clothing/tie/medal/conduct
- name = "distinguished conduct medal"
- desc = "A bronze medal awarded for distinguished conduct. Whilst a great honor, this is most basic award given by Nanotrasen. It is often awarded by a captain to a member of his crew."
-
-/obj/item/clothing/tie/medal/bronze_heart
- name = "bronze heart medal"
- desc = "A bronze heart-shaped medal awarded for sacrifice. It is often awarded posthumously or for severe injury in the line of duty."
- icon_state = "bronze_heart"
-
-/obj/item/clothing/tie/medal/nobel_science
- name = "nobel sciences award"
- desc = "A bronze medal which represents significant contributions to the field of science or engineering."
-
-/obj/item/clothing/tie/medal/silver
- name = "silver medal"
- desc = "A silver medal."
- icon_state = "silver"
- item_color = "silver"
-
-/obj/item/clothing/tie/medal/silver/valor
- name = "medal of valor"
- desc = "A silver medal awarded for acts of exceptional valor."
-
-/obj/item/clothing/tie/medal/silver/security
- name = "robust security award"
- desc = "An award for distinguished combat and sacrifice in defence of Nanotrasen's commercial interests. Often awarded to security staff."
-
-/obj/item/clothing/tie/medal/gold
- name = "gold medal"
- desc = "A prestigious golden medal."
- icon_state = "gold"
- item_color = "gold"
-
-/obj/item/clothing/tie/medal/gold/captain
- name = "medal of captaincy"
- desc = "A golden medal awarded exclusively to those promoted to the rank of captain. It signifies the codified responsibilities of a captain to Nanotrasen, and their undisputable authority over their crew."
-
-/obj/item/clothing/tie/medal/gold/heroism
- name = "medal of exceptional heroism"
- desc = "An extremely rare golden medal awarded only by CentComm. To recieve such a medal is the highest honor and as such, very few exist. This medal is almost never awarded to anybody but commanders."
-
-//Armbands
-/obj/item/clothing/tie/armband
- name = "red armband"
- desc = "A fancy red armband!"
- icon_state = "red"
- item_color = "red"
-
-/obj/item/clothing/tie/armband/cargo
- name = "cargo armband"
- desc = "An armband, worn by the crew to display which department they're assigned to. This one is brown."
- icon_state = "cargo"
- item_color = "cargo"
-
-/obj/item/clothing/tie/armband/engine
- name = "engineering armband"
- desc = "An armband, worn by the crew to display which department they're assigned to. This one is orange with a reflective strip!"
- icon_state = "engie"
- item_color = "engie"
-
-/obj/item/clothing/tie/armband/science
- name = "science armband"
- desc = "An armband, worn by the crew to display which department they're assigned to. This one is purple."
- icon_state = "rnd"
- item_color = "rnd"
-
-/obj/item/clothing/tie/armband/hydro
- name = "hydroponics armband"
- desc = "An armband, worn by the crew to display which department they're assigned to. This one is green and blue."
- icon_state = "hydro"
- item_color = "hydro"
-
-/obj/item/clothing/tie/armband/med
- name = "medical armband"
- desc = "An armband, worn by the crew to display which department they're assigned to. This one is white."
- icon_state = "med"
- item_color = "med"
-
-/obj/item/clothing/tie/armband/medgreen
- name = "EMT armband"
- desc = "An armband, worn by the crew to display which department they're assigned to. This one is white and green."
- icon_state = "medgreen"
- item_color = "medgreen"
-
-//holsters
-/obj/item/clothing/tie/holster
- name = "shoulder holster"
- desc = "A handgun holster."
- icon_state = "holster"
- item_color = "holster"
- var/obj/item/weapon/gun/holstered = null
-
-//subtypes can override this to specify what can be holstered
-/obj/item/clothing/tie/holster/proc/can_holster(obj/item/weapon/gun/W)
- return W.isHandgun()
-
-/obj/item/clothing/tie/holster/proc/holster(obj/item/I, mob/user as mob)
- if(holstered)
- user << "\red There is already a [holstered] holstered here!"
- return
-
- if (!istype(I, /obj/item/weapon/gun))
- user << "\red Only guns can be holstered!"
- return
-
- var/obj/item/weapon/gun/W = I
- if (!can_holster(W))
- user << "\red This [W] won't fit in the [src]!"
- return
-
- holstered = W
- user.drop_from_inventory(holstered)
- holstered.loc = src
- holstered.add_fingerprint(user)
- user.visible_message("\blue [user] holsters the [holstered].", "You holster the [holstered].")
-
-/obj/item/clothing/tie/holster/proc/unholster(mob/user as mob)
- if(!holstered)
- return
-
- if(istype(user.get_active_hand(),/obj) && istype(user.get_inactive_hand(),/obj))
- user << "\red You need an empty hand to draw the [holstered]!"
- else
- if(user.a_intent == "hurt")
- usr.visible_message("\red [user] draws the [holstered], ready to shoot!", \
- "\red You draw the [holstered], ready to shoot!")
- else
- user.visible_message("\blue [user] draws the [holstered], pointing it at the ground.", \
- "\blue You draw the [holstered], pointing it at the ground.")
- user.put_in_hands(holstered)
- holstered.add_fingerprint(user)
- holstered = null
-
-/obj/item/clothing/tie/holster/attack_hand(mob/user as mob)
- if (has_suit) //if we are part of a suit
- if (holstered)
- unholster(user)
- return
-
- ..(user)
-
-/obj/item/clothing/tie/holster/attackby(obj/item/W as obj, mob/user as mob)
- holster(W, user)
-
-/obj/item/clothing/tie/holster/emp_act(severity)
- if (holstered)
- holstered.emp_act(severity)
- ..()
-
-/obj/item/clothing/tie/holster/examine(mob/user)
- ..(user)
- if (holstered)
- user << "A [holstered] is holstered here."
- else
- user << "It is empty."
-
-/obj/item/clothing/tie/holster/on_attached(obj/item/clothing/under/S, mob/user as mob)
- ..()
- has_suit.verbs += /obj/item/clothing/tie/holster/verb/holster_verb
-
-/obj/item/clothing/tie/holster/on_removed(mob/user as mob)
- has_suit.verbs -= /obj/item/clothing/tie/holster/verb/holster_verb
- ..()
-
-//For the holster hotkey
-/obj/item/clothing/tie/holster/verb/holster_verb()
- set name = "Holster"
- set category = "Object"
- set src in usr
- if(!istype(usr, /mob/living)) return
- if(usr.stat) return
-
- var/obj/item/clothing/tie/holster/H = null
- if (istype(src, /obj/item/clothing/tie/holster))
- H = src
- else if (istype(src, /obj/item/clothing/under))
- var/obj/item/clothing/under/S = src
- if (S.hastie)
- H = S.hastie
-
- if (!H)
- usr << "/red Something is very wrong."
-
- if(!H.holstered)
- if(!istype(usr.get_active_hand(), /obj/item/weapon/gun))
- usr << "\blue You need your gun equiped to holster it."
- return
- var/obj/item/weapon/gun/W = usr.get_active_hand()
- H.holster(W, usr)
- else
- H.unholster(usr)
-
-/obj/item/clothing/tie/holster/armpit
- name = "shoulder holster"
- desc = "A worn-out handgun holster. Perfect for concealed carry"
- icon_state = "holster"
- item_color = "holster"
-
-/obj/item/clothing/tie/holster/waist
- name = "shoulder holster"
- desc = "A handgun holster. Made of expensive leather."
- icon_state = "holster"
- item_color = "holster_low"
-
-/obj/item/clothing/tie/storage
- name = "load bearing equipment"
- desc = "Used to hold things when you don't have enough hands."
- icon_state = "webbing"
- item_color = "webbing"
- var/slots = 3
- var/obj/item/weapon/storage/internal/hold
-
-/obj/item/clothing/tie/storage/New()
- ..()
- hold = new/obj/item/weapon/storage/internal(src)
- hold.storage_slots = slots
-
-/obj/item/clothing/tie/storage/attack_hand(mob/user as mob)
- if (has_suit) //if we are part of a suit
- hold.open(user)
- return
-
- if (hold.handle_attack_hand(user)) //otherwise interact as a regular storage item
- ..(user)
-
-/obj/item/clothing/tie/storage/MouseDrop(obj/over_object as obj)
- if (has_suit)
- return
-
- if (hold.handle_mousedrop(usr, over_object))
- ..(over_object)
-
-/obj/item/clothing/tie/storage/attackby(obj/item/W as obj, mob/user as mob)
- return hold.attackby(W, user)
-
-/obj/item/clothing/tie/storage/emp_act(severity)
- hold.emp_act(severity)
- ..()
-
-/obj/item/clothing/tie/storage/hear_talk(mob/M, var/msg, verb, datum/language/speaking)
- hold.hear_talk(M, msg, verb, speaking)
- ..()
-
-/obj/item/clothing/tie/storage/attack_self(mob/user as mob)
- user << "You empty [src]."
- var/turf/T = get_turf(src)
- hold.hide_from(usr)
- for(var/obj/item/I in hold.contents)
- hold.remove_from_storage(I, T)
- src.add_fingerprint(user)
-
-/obj/item/clothing/tie/storage/webbing
- name = "webbing"
- desc = "Strudy mess of synthcotton belts and buckles, ready to share your burden."
- icon_state = "webbing"
- item_color = "webbing"
-
-/obj/item/clothing/tie/storage/black_vest
- name = "black webbing vest"
- desc = "Robust black synthcotton vest with lots of pockets to hold whatever you need, but cannot hold in hands."
- icon_state = "vest_black"
- item_color = "vest_black"
- slots = 5
-
-/obj/item/clothing/tie/storage/brown_vest
- name = "brown webbing vest"
- desc = "Worn brownish synthcotton vest with lots of pockets to unload your hands."
- icon_state = "vest_brown"
- item_color = "vest_brown"
- slots = 5
-/*
- Holobadges are worn on the belt or neck, and can be used to show that the holder is an authorized
- Security agent - the user details can be imprinted on the badge with a Security-access ID card,
- or they can be emagged to accept any ID for use in disguises.
-*/
-
-/obj/item/clothing/tie/holobadge
-
- name = "holobadge"
- desc = "This glowing blue badge marks the holder as THE LAW."
- icon_state = "holobadge"
- item_color = "holobadge"
- slot_flags = SLOT_BELT | SLOT_TIE
-
- var/emagged = 0 //Emagging removes Sec check.
- var/stored_name = null
-
-/obj/item/clothing/tie/holobadge/cord
- icon_state = "holobadge-cord"
- item_color = "holobadge-cord"
- slot_flags = SLOT_MASK | SLOT_TIE
-
-/obj/item/clothing/tie/holobadge/attack_self(mob/user as mob)
- if(!stored_name)
- user << "Waving around a badge before swiping an ID would be pretty pointless."
- return
- if(isliving(user))
- user.visible_message("\red [user] displays their NanoTrasen Internal Security Legal Authorization Badge.\nIt reads: [stored_name], NT Security.","\red You display your NanoTrasen Internal Security Legal Authorization Badge.\nIt reads: [stored_name], NT Security.")
-
-/obj/item/clothing/tie/holobadge/attackby(var/obj/item/O as obj, var/mob/user as mob)
-
- if (istype(O, /obj/item/weapon/card/emag))
- if (emagged)
- user << "\red [src] is already cracked."
- return
- else
- emagged = 1
- user << "\red You swipe [O] and crack the holobadge security checks."
- return
-
- else if(istype(O, /obj/item/weapon/card/id) || istype(O, /obj/item/device/pda))
-
- var/obj/item/weapon/card/id/id_card = null
-
- if(istype(O, /obj/item/weapon/card/id))
- id_card = O
- else
- var/obj/item/device/pda/pda = O
- id_card = pda.id
-
- if(access_security in id_card.access || emagged)
- user << "You imprint your ID details onto the badge."
- stored_name = id_card.registered_name
- name = "holobadge ([stored_name])"
- desc = "This glowing blue badge marks [stored_name] as THE LAW."
- else
- user << "[src] rejects your insufficient access rights."
- return
- ..()
-
-/obj/item/clothing/tie/holobadge/attack(mob/living/carbon/human/M, mob/living/user)
- if(isliving(user))
- user.visible_message("\red [user] invades [M]'s personal space, thrusting [src] into their face insistently.","\red You invade [M]'s personal space, thrusting [src] into their face insistently. You are the law.")
-
-/obj/item/weapon/storage/box/holobadge
- name = "holobadge box"
- desc = "A box claiming to contain holobadges."
- New()
- new /obj/item/clothing/tie/holobadge(src)
- new /obj/item/clothing/tie/holobadge(src)
- new /obj/item/clothing/tie/holobadge(src)
- new /obj/item/clothing/tie/holobadge(src)
- new /obj/item/clothing/tie/holobadge/cord(src)
- new /obj/item/clothing/tie/holobadge/cord(src)
- ..()
- return
-
-/obj/item/clothing/tie/storage/knifeharness
- name = "decorated harness"
- desc = "A heavily decorated harness of sinew and leather with two knife-loops."
- icon_state = "unathiharness2"
- item_color = "unathiharness2"
- slots = 2
-
-/obj/item/clothing/tie/storage/knifeharness/New()
- ..()
- hold.max_combined_w_class = 4
- hold.can_hold = list("/obj/item/weapon/hatchet/unathiknife",\
- "/obj/item/weapon/kitchen/utensil/knife",\
- "/obj/item/weapon/kitchen/utensil/pknife",\
- "/obj/item/weapon/kitchenknife",\
- "/obj/item/weapon/kitchenknife/ritual")
-
- new /obj/item/weapon/hatchet/unathiknife(hold)
- new /obj/item/weapon/hatchet/unathiknife(hold)
diff --git a/code/modules/customitems/item_defines.dm b/code/modules/customitems/item_defines.dm
index 510417c0fb..11a3fa03d4 100644
--- a/code/modules/customitems/item_defines.dm
+++ b/code/modules/customitems/item_defines.dm
@@ -114,7 +114,7 @@
/////////////////////// Cataguettes - Lucy's Stethoscope - Lucy Kemmerer //////
-/obj/item/clothing/tie/stethoscope/fluff/lucystethos
+/obj/item/clothing/accessory/stethoscope/fluff/lucystethos
name = "Lucy's Stethoscope"
desc = "A medical apparatus intended to ease in listening to the sounds of the human body. This one looks cleaner and sparklier than the rest. There is a small silver plaque attached to the tubing, with the words 'Lucy Kemmerer' engraved on it."
icon_state = "lucystethos"
@@ -1111,22 +1111,33 @@
item_color = "lillian_dress"
body_parts_covered = UPPER_TORSO|LOWER_TORSO
-////// Cybernetic Casings - Parker Eliza - MrSnapwalk
+////// Tailored Security Uniform - Parker Eliza - MrSnapwalk
+
/obj/item/clothing/under/fluff/parkereliza
- name = "cybernetic casings"
- desc = "A set of somewhat bulky white casings for robotic limbs, paired with a basic blue tank top and black cargo pants. The arms have a small label on the inner elbow, which reads \"Bishop Corporation Cybernetic Solutions\"."
+ name = "tailored security uniform"
+ desc = "A red uniform shirt (tailored for easy access to the shoulder joint) and black cargo pants, paired with a set of somewhat bulky white casings for robotic limbs. The arms have a small label on the inner elbow, which reads \"Bishop Corporation Cybernetic Solutions\"."
icon = 'icons/obj/custom_items.dmi'
icon_state = "parker_eliza"
item_state = "parker_eliza"
item_color = "parker_eliza"
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS
+////// Bishop "GOLEM" V2200 Industrial Limb Augments - Parker Eliza - MrSnapwalk
+
+/obj/item/clothing/suit/fluff/parkereliza
+ name = "Bishop \"GOLEM\" V2200 Industrial Limb Augments"
+ desc = "A set of top-of-the-line cyberlimbs, only usable to someone with extensive bone structure augmentation. Often used in industrial applications, they are capable of throwing a man clear across a room. The load limitation circuit in this set appears to be modified."
+ icon = 'icons/obj/custom_items.dmi'
+ icon_state = "parker_eliza_arms"
+ item_state = "parker_eliza_arms"
+ item_color = "parker_eliza_arms"
+
////////////// Accessories /////
//////////////////// Blood Red Pendant - Mewth - Mu'taz Radi ////////////////
-/obj/item/clothing/tie/fluff/radi
+/obj/item/clothing/accessory/fluff/radi
name = "Blood Red Pendant"
desc = "A blue chained necklace with a ruby in the middle, it looks pretty!"
icon = 'icons/obj/custom_items.dmi'
@@ -1168,7 +1179,7 @@
////// Small locket - Altair An-Nasaqan - Serithi
-/obj/item/clothing/tie/fluff/altair_locket
+/obj/item/clothing/accessory/fluff/altair_locket
name = "small locket"
desc = "A small golden locket attached to an Ii'rka-reed string. Inside the locket is a holo-picture of a female Tajaran, and an inscription writtin in Siik'mas."
icon = 'icons/obj/custom_items.dmi'
@@ -1181,7 +1192,7 @@
////// Silver locket - Konaa Hirano - Konaa_Hirano
-/obj/item/clothing/tie/fluff/konaa_hirano
+/obj/item/clothing/accessory/fluff/konaa_hirano
name = "silver locket"
desc = "This oval shaped, argentium sterling silver locket hangs on an incredibly fine, refractive string, almost thin as hair and microweaved from links to a deceptive strength, of similar material. The edges are engraved very delicately with an elegant curving design, but overall the main is unmarked and smooth to the touch, leaving room for either remaining as a stolid piece or future alterations. There is an obvious internal place for a picture or lock of some sort, but even behind that is a very thin compartment unhinged with the pinch of a thumb and forefinger."
icon = 'icons/obj/custom_items.dmi'
@@ -1193,13 +1204,13 @@
slot_flags = SLOT_MASK | SLOT_TIE
var/obj/item/held //Item inside locket.
-/obj/item/clothing/tie/fluff/konaa_hirano/attack_self(mob/user as mob)
+/obj/item/clothing/accessory/fluff/konaa_hirano/attack_self(mob/user as mob)
if(held)
user << "You open [src] and [held] falls out."
held.loc = get_turf(user)
src.held = null
-/obj/item/clothing/tie/fluff/konaa_hirano/attackby(var/obj/item/O as obj, mob/user as mob)
+/obj/item/clothing/accessory/fluff/konaa_hirano/attackby(var/obj/item/O as obj, mob/user as mob)
if(istype(O,/obj/item/weapon/paper))
if(held)
usr << "[src] already has something inside it."
@@ -1213,7 +1224,7 @@
////// Medallion - Nasir Khayyam - Jamini
-/obj/item/clothing/tie/fluff/nasir_khayyam_1
+/obj/item/clothing/accessory/fluff/nasir_khayyam_1
name = "medallion"
desc = "This silvered medallion bears the symbol of the Hadii Clan of the Tajaran."
icon = 'icons/obj/custom_items.dmi'
diff --git a/code/modules/mining/abandonedcrates.dm b/code/modules/mining/abandonedcrates.dm
index 9b4c660e76..7f3a5033d5 100644
--- a/code/modules/mining/abandonedcrates.dm
+++ b/code/modules/mining/abandonedcrates.dm
@@ -52,7 +52,7 @@
if(46 to 50)
new/obj/item/clothing/under/chameleon(src)
for(var/i = 0, i < 7, i++)
- new/obj/item/clothing/tie/horrible(src)
+ new/obj/item/clothing/accessory/horrible(src)
if(51 to 52) // Uncommon, 2% each
new/obj/item/weapon/melee/classic_baton(src)
if(53 to 54)
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index 0f06e979ad..687314f1dd 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -63,8 +63,8 @@
var/tie_msg
if(istype(w_uniform,/obj/item/clothing/under))
var/obj/item/clothing/under/U = w_uniform
- if(U.hastie)
- tie_msg += " with \icon[U.hastie] \a [U.hastie]"
+ if(U.accessories.len)
+ tie_msg += " with [lowertext(english_list(U.accessories))]"
if(w_uniform.blood_DNA)
msg += "[t_He] [t_is] wearing \icon[w_uniform] [w_uniform.gender==PLURAL?"some":"a"] [(w_uniform.blood_color != "#030303") ? "blood" : "oil"]-stained [w_uniform.name][tie_msg]!\n"
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 738a5ea8b7..dd5bfe7d59 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -241,7 +241,7 @@
Suit Storage: [(s_store ? s_store : "Nothing")] [((istype(wear_mask, /obj/item/clothing/mask) && istype(s_store, /obj/item/weapon/tank) && !( internal )) ? text(" Set Internal", src) : "")]
[(handcuffed ? text("Handcuffed") : text("Not Handcuffed"))]
[(legcuffed ? text("Legcuffed") : text(""))]
-
[(suit) ? ((suit.hastie) ? text(" Remove Accessory", src) : "") :]
+
[(suit) ? ((suit.accessories.len) ? text(" Remove Accessory", src) : "") :]
[(internal ? text("Remove Internal") : "")]
Remove Splints
Empty Pockets
@@ -1301,4 +1301,4 @@
/mob/living/carbon/human/slip(var/slipped_on, stun_duration=8)
if((species.flags & NO_SLIP) || (shoes && (shoes.flags & NOSLIP)))
return 0
- ..(slipped_on,stun_duration)
+ ..(slipped_on,stun_duration)
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 414f7e2bfb..a45a11f453 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -24,7 +24,7 @@ emp_act
if(!(def_zone in list("chest", "groin")))
reflectchance /= 2
if(prob(reflectchance))
- visible_message("\red The [P.name] gets reflected by [src]'s [wear_suit.name]!")
+ visible_message("\red \The [P] gets reflected by \the [src]'s [wear_suit.name]!")
// Find a turf near or on the original location to bounce to
if(P.starting)
@@ -33,12 +33,7 @@ emp_act
var/turf/curloc = get_turf(src)
// redirect the projectile
- P.original = locate(new_x, new_y, P.z)
- P.starting = curloc
- P.current = curloc
- P.firer = src
- P.yo = new_y - curloc.y
- P.xo = new_x - curloc.x
+ P.redirect(new_x, new_y, curloc, src)
return -1 // complete projectile permutation
@@ -47,9 +42,9 @@ emp_act
var/armor = getarmor_organ(organ, "bullet")
if((P.embed && prob(20 + max(P.damage - armor, -10))))
var/obj/item/weapon/shard/shrapnel/SP = new()
- (SP.name) = "[P.name] shrapnel"
- (SP.desc) = "[SP.desc] It looks like it was fired from [P.shot_from]."
- (SP.loc) = organ
+ SP.name = (P.name != "shrapnel")? "[P.name] shrapnel" : "shrapnel"
+ SP.desc = "[SP.desc] It looks like it was fired from [P.shot_from]."
+ SP.loc = organ
organ.embed(SP)
return (..(P , def_zone))
diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm
index 8516b11a7f..b4c2a18c1d 100644
--- a/code/modules/mob/living/carbon/human/inventory.dm
+++ b/code/modules/mob/living/carbon/human/inventory.dm
@@ -497,15 +497,17 @@
message = "\red [source] is trying to unlegcuff [target]!"
if("tie")
var/obj/item/clothing/under/suit = target.w_uniform
- target.attack_log += text("\[[time_stamp()]\] Has had their accessory ([suit.hastie]) removed by [source.name] ([source.ckey])")
- source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) accessory ([suit.hastie])")
- if(istype(suit.hastie, /obj/item/clothing/tie/holobadge) || istype(suit.hastie, /obj/item/clothing/tie/medal))
- for(var/mob/M in viewers(target, null))
- M.show_message("\red [source] tears off \the [suit.hastie] from [target]'s suit!" , 1)
- done()
- return
- else
- message = "\red [source] is trying to take off \a [suit.hastie] from [target]'s suit!"
+ if(suit.accessories.len)
+ var/obj/item/clothing/accessory/A = suit.accessories[1]
+ target.attack_log += "\[[time_stamp()]\] Has had their accessory ([A]) removed by [source.name] ([source.ckey])"
+ source.attack_log += "\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) accessory ([A])"
+ if(istype(A, /obj/item/clothing/accessory/holobadge) || istype(A, /obj/item/clothing/accessory/medal))
+ for(var/mob/M in viewers(target, null))
+ M.show_message("\red [source] tears off \the [A] from [target]'s [suit]!" , 1)
+ done()
+ return
+ else
+ message = "\red [source] is trying to take off \a [A] from [target]'s [suit]!"
if("pockets")
target.attack_log += text("\[[time_stamp()]\] Has had their pockets emptied by [source.name] ([source.ckey])")
source.attack_log += text("\[[time_stamp()]\] Attempted to empty [target.name]'s ([target.ckey]) pockets")
@@ -634,17 +636,18 @@ It can still be worn/put on as normal.
strip_item = target.wear_suit
if("tie")
var/obj/item/clothing/under/suit = target.w_uniform
- //var/obj/item/clothing/tie/tie = suit.hastie
+ //var/obj/item/clothing/accessory/tie = suit.hastie
/*if(tie)
- if (istype(tie,/obj/item/clothing/tie/storage))
- var/obj/item/clothing/tie/storage/W = tie
+ if (istype(tie,/obj/item/clothing/accessory/storage))
+ var/obj/item/clothing/accessory/storage/W = tie
if (W.hold)
W.hold.close(usr)
usr.put_in_hands(tie)
suit.hastie = null*/
- if(suit && suit.hastie)
- suit.hastie.on_removed(usr)
- suit.hastie = null
+ if(suit && suit.accessories.len)
+ var/obj/item/clothing/accessory/A = suit.accessories[1]
+ A.on_removed(usr)
+ suit.accessories -= A
target.update_inv_w_uniform()
if("id")
slot_to_process = slot_wear_id
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index 303f9b1f76..10b13d8736 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -537,10 +537,11 @@ proc/get_damage_icon_part(damage_state, body_part)
bloodsies.color = w_uniform.blood_color
standing.overlays += bloodsies
- if(w_uniform:hastie) //WE CHECKED THE TYPE ABOVE. THIS REALLY SHOULD BE FINE.
- var/tie_color = w_uniform:hastie.item_color
- if(!tie_color) tie_color = w_uniform:hastie.icon_state
- standing.overlays += image("icon" = 'icons/mob/ties.dmi', "icon_state" = "[tie_color]")
+ if(w_uniform:accessories.len) //WE CHECKED THE TYPE ABOVE. THIS REALLY SHOULD BE FINE.
+ for(var/obj/item/clothing/accessory/A in w_uniform:accessories)
+ var/tie_color = A.item_color
+ if(!tie_color) tie_color = A.icon_state
+ standing.overlays += image("icon" = 'icons/mob/ties.dmi', "icon_state" = "[tie_color]")
overlays_standing[UNIFORM_LAYER] = standing
else
@@ -780,7 +781,7 @@ proc/get_damage_icon_part(damage_state, body_part)
/mob/living/carbon/human/update_inv_wear_mask(var/update_icons=1)
- if( wear_mask && ( istype(wear_mask, /obj/item/clothing/mask) || istype(wear_mask, /obj/item/clothing/tie) ) && !(head && head.flags_inv & HIDEMASK))
+ if( wear_mask && ( istype(wear_mask, /obj/item/clothing/mask) || istype(wear_mask, /obj/item/clothing/accessory) ) && !(head && head.flags_inv & HIDEMASK))
wear_mask.screen_loc = ui_mask //TODO
var/image/standing
diff --git a/code/modules/mob/living/carbon/metroid/death.dm b/code/modules/mob/living/carbon/metroid/death.dm
index 2ebc5c576b..022726b00a 100644
--- a/code/modules/mob/living/carbon/metroid/death.dm
+++ b/code/modules/mob/living/carbon/metroid/death.dm
@@ -1,22 +1,23 @@
/mob/living/carbon/slime/death(gibbed)
if(stat == DEAD) return
- stat = DEAD
- if(!gibbed)
- if(is_adult)
- var/mob/living/carbon/slime/M = new /mob/living/carbon/slime(loc)
- M.colour = colour
- M.rabid = 1
- is_adult = 0
- maxHealth = 150
- revive()
- regenerate_icons()
- number = rand(1, 1000)
- name = "[colour] [is_adult ? "adult" : "baby"] slime ([number])"
- return
+ if(!gibbed && is_adult)
+ var/mob/living/carbon/slime/M = new /mob/living/carbon/slime(loc, colour)
+ M.rabid = 1
+ M.Friends = Friends.Copy()
+ step_away(M, src)
+ is_adult = 0
+ maxHealth = 150
+ revive()
+ regenerate_icons()
+ if (!client) rabid = 1
+ number = rand(1, 1000)
+ name = "[colour] [is_adult ? "adult" : "baby"] slime ([number])"
+ return
- icon_state = "[colour] baby slime dead"
- overlays.Cut()
+ . = ..(gibbed, "seizes up and falls limp...")
- return ..(gibbed)
\ No newline at end of file
+ regenerate_icons()
+
+ return
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/metroid/emote.dm b/code/modules/mob/living/carbon/metroid/emote.dm
index 2cbc139f5a..a6ea5498cd 100644
--- a/code/modules/mob/living/carbon/metroid/emote.dm
+++ b/code/modules/mob/living/carbon/metroid/emote.dm
@@ -1,6 +1,5 @@
/mob/living/carbon/slime/emote(var/act, var/m_type=1, var/message = null)
-
if (findtext(act, "-", 1, null))
var/t1 = findtext(act, "-", 1, null)
//param = copytext(act, t1 + 1, length(act) + 1)
@@ -9,6 +8,8 @@
if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_'
act = copytext(act,1,length(act))
+ var/updateicon = 0
+
switch(act) //Alphabetical please
if ("me")
if(silent)
@@ -59,8 +60,32 @@
message = "The [src.name] vibrates!"
m_type = 1
+ if("nomood")
+ mood = null
+ updateicon = 1
+
+ if("pout")
+ mood = "pout"
+ updateicon = 1
+
+ if("sad")
+ mood = "sad"
+ updateicon = 1
+
+ if("angry")
+ mood = "angry"
+ updateicon = 1
+
+ if("frown")
+ mood = "mischevous"
+ updateicon = 1
+
+ if("smile")
+ mood = ":3"
+ updateicon = 1
+
if ("help") //This is an exception
- src << "Help for slime emotes. You can use these emotes with say \"*emote\":\n\nbounce, custom, jiggle, light, moan, shiver, sway, twitch, vibrate"
+ src << "Help for slime emotes. You can use these emotes with say \"*emote\":\n\nbounce, custom, jiggle, light, moan, shiver, sway, twitch, vibrate. You can also set your face with: \n\nnomood, pout, sad, angry, frown, smile"
else
src << "\blue Unusable emote '[act]'. Say *help for a list."
@@ -68,9 +93,9 @@
if (m_type & 1)
for(var/mob/O in viewers(src, null))
O.show_message(message, m_type)
- //Foreach goto(703)
else
for(var/mob/O in hearers(src, null))
O.show_message(message, m_type)
- //Foreach goto(746)
+ if(updateicon)
+ regenerate_icons()
return
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/metroid/items.dm b/code/modules/mob/living/carbon/metroid/items.dm
new file mode 100644
index 0000000000..4c7aed74f4
--- /dev/null
+++ b/code/modules/mob/living/carbon/metroid/items.dm
@@ -0,0 +1,366 @@
+/obj/item/slime_extract
+ name = "slime extract"
+ desc = "Goo extracted from a slime. Legends claim these to have \"magical powers\"."
+ icon = 'icons/mob/slimes.dmi'
+ icon_state = "grey slime extract"
+ force = 1.0
+ w_class = 1.0
+ throwforce = 0
+ throw_speed = 3
+ throw_range = 6
+ origin_tech = "biotech=4"
+ var/Uses = 1 // uses before it goes inert
+ var/enhanced = 0 //has it been enhanced before?
+
+ attackby(obj/item/O as obj, mob/user as mob)
+ if(istype(O, /obj/item/weapon/slimesteroid2))
+ if(enhanced == 1)
+ user << " This extract has already been enhanced!"
+ return ..()
+ if(Uses == 0)
+ user << " You can't enhance a used extract!"
+ return ..()
+ user <<"You apply the enhancer. It now has triple the amount of uses."
+ Uses = 3
+ enhanced = 1
+ del(O)
+
+/obj/item/slime_extract/New()
+ ..()
+ create_reagents(100)
+
+/obj/item/slime_extract/grey
+ name = "grey slime extract"
+ icon_state = "grey slime extract"
+
+/obj/item/slime_extract/gold
+ name = "gold slime extract"
+ icon_state = "gold slime extract"
+
+/obj/item/slime_extract/silver
+ name = "silver slime extract"
+ icon_state = "silver slime extract"
+
+/obj/item/slime_extract/metal
+ name = "metal slime extract"
+ icon_state = "metal slime extract"
+
+/obj/item/slime_extract/purple
+ name = "purple slime extract"
+ icon_state = "purple slime extract"
+
+/obj/item/slime_extract/darkpurple
+ name = "dark purple slime extract"
+ icon_state = "dark purple slime extract"
+
+/obj/item/slime_extract/orange
+ name = "orange slime extract"
+ icon_state = "orange slime extract"
+
+/obj/item/slime_extract/yellow
+ name = "yellow slime extract"
+ icon_state = "yellow slime extract"
+
+/obj/item/slime_extract/red
+ name = "red slime extract"
+ icon_state = "red slime extract"
+
+/obj/item/slime_extract/blue
+ name = "blue slime extract"
+ icon_state = "blue slime extract"
+
+/obj/item/slime_extract/darkblue
+ name = "dark blue slime extract"
+ icon_state = "dark blue slime extract"
+
+/obj/item/slime_extract/pink
+ name = "pink slime extract"
+ icon_state = "pink slime extract"
+
+/obj/item/slime_extract/green
+ name = "green slime extract"
+ icon_state = "green slime extract"
+
+/obj/item/slime_extract/lightpink
+ name = "light pink slime extract"
+ icon_state = "light pink slime extract"
+
+/obj/item/slime_extract/black
+ name = "black slime extract"
+ icon_state = "black slime extract"
+
+/obj/item/slime_extract/oil
+ name = "oil slime extract"
+ icon_state = "oil slime extract"
+
+/obj/item/slime_extract/adamantine
+ name = "adamantine slime extract"
+ icon_state = "adamantine slime extract"
+
+/obj/item/slime_extract/bluespace
+ name = "bluespace slime extract"
+ icon_state = "bluespace slime extract"
+
+/obj/item/slime_extract/pyrite
+ name = "pyrite slime extract"
+ icon_state = "pyrite slime extract"
+
+/obj/item/slime_extract/cerulean
+ name = "cerulean slime extract"
+ icon_state = "cerulean slime extract"
+
+/obj/item/slime_extract/sepia
+ name = "sepia slime extract"
+ icon_state = "sepia slime extract"
+
+/obj/item/slime_extract/rainbow
+ name = "rainbow slime extract"
+ icon_state = "rainbow slime extract"
+
+////Pet Slime Creation///
+
+/obj/item/weapon/slimepotion
+ name = "docility potion"
+ desc = "A potent chemical mix that will nullify a slime's powers, causing it to become docile and tame."
+ icon = 'icons/obj/chemical.dmi'
+ icon_state = "bottle19"
+
+ attack(mob/living/carbon/slime/M as mob, mob/user as mob)
+ if(!istype(M, /mob/living/carbon/slime))//If target is not a slime.
+ user << " The potion only works on baby slimes!"
+ return ..()
+ if(M.is_adult) //Can't tame adults
+ user << " Only baby slimes can be tamed!"
+ return..()
+ if(M.stat)
+ user << " The slime is dead!"
+ return..()
+ if(M.mind)
+ user << " The slime resists!"
+ return ..()
+ var/mob/living/simple_animal/slime/pet = new /mob/living/simple_animal/slime(M.loc)
+ pet.icon_state = "[M.colour] baby slime"
+ pet.icon_living = "[M.colour] baby slime"
+ pet.icon_dead = "[M.colour] baby slime dead"
+ pet.colour = "[M.colour]"
+ user <<"You feed the slime the potion, removing it's powers and calming it."
+ del(M)
+ var/newname = sanitize(copytext(input(user, "Would you like to give the slime a name?", "Name your new pet", "pet slime") as null|text,1,MAX_NAME_LEN))
+
+ if (!newname)
+ newname = "pet slime"
+ pet.name = newname
+ pet.real_name = newname
+ del(src)
+
+/obj/item/weapon/slimepotion2
+ name = "advanced docility potion"
+ desc = "A potent chemical mix that will nullify a slime's powers, causing it to become docile and tame. This one is meant for adult slimes"
+ icon = 'icons/obj/chemical.dmi'
+ icon_state = "bottle19"
+
+ attack(mob/living/carbon/slime/M as mob, mob/user as mob)
+ if(!istype(M, /mob/living/carbon/slime/))//If target is not a slime.
+ user << " The potion only works on slimes!"
+ return ..()
+ if(M.stat)
+ user << " The slime is dead!"
+ return..()
+ if(M.mind)
+ user << " The slime resists!"
+ return ..()
+ var/mob/living/simple_animal/adultslime/pet = new /mob/living/simple_animal/adultslime(M.loc)
+ pet.icon_state = "[M.colour] adult slime"
+ pet.icon_living = "[M.colour] adult slime"
+ pet.icon_dead = "[M.colour] baby slime dead"
+ pet.colour = "[M.colour]"
+ user <<"You feed the slime the potion, removing it's powers and calming it."
+ del(M)
+ var/newname = sanitize(copytext(input(user, "Would you like to give the slime a name?", "Name your new pet", "pet slime") as null|text,1,MAX_NAME_LEN))
+
+ if (!newname)
+ newname = "pet slime"
+ pet.name = newname
+ pet.real_name = newname
+ del(src)
+
+
+/obj/item/weapon/slimesteroid
+ name = "slime steroid"
+ desc = "A potent chemical mix that will cause a slime to generate more extract."
+ icon = 'icons/obj/chemical.dmi'
+ icon_state = "bottle16"
+
+ attack(mob/living/carbon/slime/M as mob, mob/user as mob)
+ if(!istype(M, /mob/living/carbon/slime))//If target is not a slime.
+ user << " The steroid only works on baby slimes!"
+ return ..()
+ if(M.is_adult) //Can't tame adults
+ user << " Only baby slimes can use the steroid!"
+ return..()
+ if(M.stat)
+ user << " The slime is dead!"
+ return..()
+ if(M.cores == 3)
+ user <<" The slime already has the maximum amount of extract!"
+ return..()
+
+ user <<"You feed the slime the steroid. It now has triple the amount of extract."
+ M.cores = 3
+ del(src)
+
+/obj/item/weapon/slimesteroid2
+ name = "extract enhancer"
+ desc = "A potent chemical mix that will give a slime extract three uses."
+ icon = 'icons/obj/chemical.dmi'
+ icon_state = "bottle17"
+
+ /*afterattack(obj/target, mob/user , flag)
+ if(istype(target, /obj/item/slime_extract))
+ if(target.enhanced == 1)
+ user << " This extract has already been enhanced!"
+ return ..()
+ if(target.Uses == 0)
+ user << " You can't enhance a used extract!"
+ return ..()
+ user <<"You apply the enhancer. It now has triple the amount of uses."
+ target.Uses = 3
+ target.enahnced = 1
+ del(src)*/
+
+/obj/effect/golemrune
+ anchored = 1
+ desc = "a strange rune used to create golems. It glows when spirits are nearby."
+ name = "rune"
+ icon = 'icons/obj/rune.dmi'
+ icon_state = "golem"
+ unacidable = 1
+ layer = TURF_LAYER
+
+ New()
+ ..()
+ processing_objects.Add(src)
+
+ process()
+ var/mob/dead/observer/ghost
+ for(var/mob/dead/observer/O in src.loc)
+ if(!O.client) continue
+ if(O.mind && O.mind.current && O.mind.current.stat != DEAD) continue
+ ghost = O
+ break
+ if(ghost)
+ icon_state = "golem2"
+ else
+ icon_state = "golem"
+
+ attack_hand(mob/living/user as mob)
+ var/mob/dead/observer/ghost
+ for(var/mob/dead/observer/O in src.loc)
+ if(!O.client) continue
+ if(O.mind && O.mind.current && O.mind.current.stat != DEAD) continue
+ ghost = O
+ break
+ if(!ghost)
+ user << "The rune fizzles uselessly. There is no spirit nearby."
+ return
+ var/mob/living/carbon/human/G = new(src.loc)
+ G.set_species("Golem")
+ G.key = ghost.key
+ G << "You are an adamantine golem. You move slowly, but are highly resistant to heat and cold as well as blunt trauma. You are unable to wear clothes, but can still use most tools. Serve [user], and assist them in completing their goals at any cost."
+ del (src)
+
+
+ proc/announce_to_ghosts()
+ for(var/mob/dead/observer/G in player_list)
+ if(G.client)
+ var/area/A = get_area(src)
+ if(A)
+ G << "Golem rune created in [A.name]."
+
+/mob/living/carbon/slime/has_eyes()
+ return 0
+
+//////////////////////////////Old shit from metroids/RoRos, and the old cores, would not take much work to re-add them////////////////////////
+
+/*
+// Basically this slime Core catalyzes reactions that normally wouldn't happen anywhere
+/obj/item/slime_core
+ name = "slime extract"
+ desc = "Goo extracted from a slime. Legends claim these to have \"magical powers\"."
+ icon = 'icons/mob/slimes.dmi'
+ icon_state = "slime extract"
+ force = 1.0
+ w_class = 1.0
+ throwforce = 1.0
+ throw_speed = 2
+ throw_range = 6
+ origin_tech = "biotech=4"
+ var/POWERFLAG = 0 // sshhhhhhh
+ var/Flush = 30
+ var/Uses = 5 // uses before it goes inert
+
+/obj/item/slime_core/New()
+ ..()
+ create_reagents(100)
+ POWERFLAG = rand(1,10)
+ Uses = rand(7, 25)
+ //flags |= NOREACT
+/*
+ spawn()
+ Life()
+
+ proc/Life()
+ while(src)
+ sleep(25)
+ Flush--
+ if(Flush <= 0)
+ reagents.clear_reagents()
+ Flush = 30
+*/
+
+
+
+/obj/item/weapon/reagent_containers/food/snacks/egg/slime
+ name = "slime egg"
+ desc = "A small, gelatinous egg."
+ icon = 'icons/mob/mob.dmi'
+ icon_state = "slime egg-growing"
+ bitesize = 12
+ origin_tech = "biotech=4"
+ var/grown = 0
+
+/obj/item/weapon/reagent_containers/food/snacks/egg/slime/New()
+ ..()
+ reagents.add_reagent("nutriment", 4)
+ reagents.add_reagent("slimejelly", 1)
+ spawn(rand(1200,1500))//the egg takes a while to "ripen"
+ Grow()
+
+/obj/item/weapon/reagent_containers/food/snacks/egg/slime/proc/Grow()
+ grown = 1
+ icon_state = "slime egg-grown"
+ processing_objects.Add(src)
+ return
+
+/obj/item/weapon/reagent_containers/food/snacks/egg/slime/proc/Hatch()
+ processing_objects.Remove(src)
+ var/turf/T = get_turf(src)
+ src.visible_message(" The [name] pulsates and quivers!")
+ spawn(rand(50,100))
+ src.visible_message(" The [name] bursts open!")
+ new/mob/living/carbon/slime(T)
+ del(src)
+
+
+/obj/item/weapon/reagent_containers/food/snacks/egg/slime/process()
+ var/turf/location = get_turf(src)
+ var/datum/gas_mixture/environment = location.return_air()
+ if (environment.phoron > MOLES_PHORON_VISIBLE)//phoron exposure causes the egg to hatch
+ src.Hatch()
+
+/obj/item/weapon/reagent_containers/food/snacks/egg/slime/attackby(obj/item/weapon/W as obj, mob/user as mob)
+ if(istype( W, /obj/item/toy/crayon ))
+ return
+ else
+ ..()
+*/
diff --git a/code/modules/mob/living/carbon/metroid/life.dm b/code/modules/mob/living/carbon/metroid/life.dm
index de34d74afa..22b61291ef 100644
--- a/code/modules/mob/living/carbon/metroid/life.dm
+++ b/code/modules/mob/living/carbon/metroid/life.dm
@@ -1,10 +1,3 @@
-/mob/living/carbon/slime
- var/AIproc = 0 // determines if the AI loop is activated
- var/Atkcool = 0 // attack cooldown
- var/Tempstun = 0 // temporary temperature stuns
- var/Discipline = 0 // if a slime has been hit with a freeze gun, or wrestled/attacked off a human, they become disciplined and don't attack anymore for a while
- var/SStun = 0 // stun variable
-
/mob/living/carbon/slime/Life()
set invisibility = 0
set background = 1
@@ -15,113 +8,27 @@
..()
if(stat != DEAD)
- //Chemicals in the body
handle_chemicals_in_body()
-
handle_nutrition()
- handle_targets()
-
- if (!ckey)
+ if (!client)
+ handle_targets()
+ if (!AIproc)
+ spawn()
+ handle_AI()
handle_speech_and_mood()
var/datum/gas_mixture/environment
if(src.loc)
environment = loc.return_air()
- //Apparently, the person who wrote this code designed it so that
- //blinded get reset each cycle and then get activated later in the
- //code. Very ugly. I dont care. Moving this stuff here so its easy
- //to find it.
- src.blinded = null
-
- regular_hud_updates() // Basically just deletes any screen objects :<
+ regular_hud_updates()
if(environment)
handle_environment(environment) // Handle temperature/pressure differences between body and environment
handle_regular_status_updates() // Status updates, death etc.
-/mob/living/carbon/slime/proc/AIprocess() // the master AI process
-
- if(AIproc || stat == DEAD || client) return
-
- var/hungry = 0
- if (nutrition < get_starve_nutrition())
- hungry = 2
- else if (nutrition < get_grow_nutrition() && prob(25) || nutrition < get_hunger_nutrition())
- hungry = 1
-
- AIproc = 1
-
- while(AIproc && stat != 2 && (attacked || hungry || rabid || Victim))
- if(Victim) // can't eat AND have this little process at the same time
- break
-
- if(!Target || client)
- break
-
- if(Target.health <= -70 || Target.stat == 2)
- Target = null
- AIproc = 0
- break
-
- if(Target)
- for(var/mob/living/carbon/slime/M in view(1,Target))
- if(M.Victim == Target)
- Target = null
- AIproc = 0
- break
- if(!AIproc)
- break
-
- if(Target in view(1,src))
- if(istype(Target, /mob/living/silicon))
- if(!Atkcool)
- Atkcool = 1
- spawn(45)
- Atkcool = 0
-
- if(Target.Adjacent(src))
- UnarmedAttack(Target)
- return
- if(!Target.lying && prob(80))
-
- if(Target.client && Target.health >= 20)
- if(!Atkcool)
- Atkcool = 1
- spawn(45)
- Atkcool = 0
-
- if(Target.Adjacent(src))
- UnarmedAttack(Target)
-
- else
- if(!Atkcool && Target.Adjacent(src))
- Feedon(Target)
-
- else
- if(!Atkcool && Target.Adjacent(src))
- Feedon(Target)
-
- else
- if(Target in view(7, src))
- if(!Target.Adjacent(src)) // Bug of the month candidate: slimes were attempting to move to target only if it was directly next to them, which caused them to target things, but not approach them
- step_to(src, Target)
- sleep(5)
-
- else
- Target = null
- AIproc = 0
- break
-
- var/sleeptime = movement_delay()
- if(sleeptime <= 0) sleeptime = 1
-
- sleep(sleeptime + 2) // this is about as fast as a player slime can go
-
- AIproc = 0
-
/mob/living/carbon/slime/proc/handle_environment(datum/gas_mixture/environment)
if(!environment)
adjustToxLoss(rand(10,20))
@@ -146,8 +53,6 @@
//Account for massive pressure differences
if(bodytemperature < (T0C + 5)) // start calculating temperature damage etc
- if(bodytemperature <= (T0C - 40)) // stun temperature
- Tempstun = 1
if(bodytemperature <= (T0C - 50)) // hurt temperature
if(bodytemperature <= 50) // sqrting negative numbers is bad
@@ -155,9 +60,6 @@
else
adjustToxLoss(round(sqrt(bodytemperature)) * 2)
- else
- Tempstun = 0
-
updatehealth()
return //TODO: DEFERRED
@@ -189,22 +91,16 @@
/mob/living/carbon/slime/proc/handle_regular_status_updates()
- if(is_adult)
- health = 200 - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss())
- else
- health = 150 - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss())
+ src.blinded = null
- if(health < config.health_threshold_dead && stat != 2)
+ health = maxHealth - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss())
+
+ if(health < 0 && stat != DEAD)
death()
return
- else if(src.health < config.health_threshold_crit)
-
- if(!src.reagents.has_reagent("inaprovaline"))
- src.adjustOxyLoss(10)
-
- if(src.stat != DEAD)
- src.stat = UNCONSCIOUS
+ if (halloss)
+ halloss = 0
if(prob(30))
adjustOxyLoss(-1)
@@ -267,27 +163,16 @@
if(nutrition <= 0)
nutrition = 0
- if(prob(75))
- adjustToxLoss(rand(0,5))
+ adjustToxLoss(rand(1,3))
+ if (client && prob(5))
+ src << "You are starving!"
else if (nutrition >= get_grow_nutrition() && amount_grown < 10)
nutrition -= 20
amount_grown++
- if(amount_grown >= 10 && !Victim && !Target && !ckey)
- if(is_adult)
- Reproduce()
- else
- Evolve()
-
/mob/living/carbon/slime/proc/handle_targets()
- if(Tempstun)
- if(!Victim) // not while they're eating!
- canmove = 0
- else
- canmove = 1
-
- if(attacked > 50) attacked = 50
+ if(attacked > 50) attacked = 50 // Let's not get into absurdly long periods of rage
if(attacked > 0)
attacked--
@@ -300,106 +185,180 @@
if(prob(10))
Discipline--
- if(!client)
- if(!canmove) return
+ if(!canmove) return
- if(Victim) return // if it's eating someone already, continue eating!
+ if(Victim) return // if it's eating someone already, continue eating!
- if(Target)
- --target_patience
- if (target_patience <= 0 || SStun || Discipline || attacked) // Tired of chasing or something draws out attention
- target_patience = 0
- Target = null
+ if(Target)
+ --target_patience
+ if (target_patience <= 0 || SStun || Discipline || attacked) // Tired of chasing or something draws out attention
+ target_patience = 0
+ Target = null
- if(AIproc && SStun) return
+ var/hungry = 0 // determines if the slime is hungry
- var/hungry = 0 // determines if the slime is hungry
+ if (nutrition < get_starve_nutrition())
+ hungry = 2
+ else if (nutrition < get_grow_nutrition() && prob(25) || nutrition < get_hunger_nutrition())
+ hungry = 1
- if (nutrition < get_starve_nutrition())
- hungry = 2
- else if (nutrition < get_grow_nutrition() && prob(25) || nutrition < get_hunger_nutrition())
- hungry = 1
+ if(hungry == 2 && !client) // if a slime is starving, it starts losing its friends
+ if(Friends.len > 0 && prob(1))
+ var/mob/nofriend = pick(Friends)
+ --Friends[nofriend]
+ if (Friends[nofriend] <= 0)
+ Friends -= nofriend
- if(hungry == 2 && !client) // if a slime is starving, it starts losing its friends
- if(Friends.len > 0 && prob(1))
- var/mob/nofriend = pick(Friends)
- --Friends[nofriend]
+ if(!Target)
+ if(will_hunt(hungry) || attacked || rabid) // Only add to the list if we need to
+ var/list/targets = list()
- if(!Target)
- if(will_hunt() && hungry || attacked || rabid) // Only add to the list if we need to
- var/list/targets = list()
+ for(var/mob/living/L in view(7,src))
- for(var/mob/living/L in view(7,src))
+ if(isslime(L) || L.stat == DEAD) // Ignore other slimes and dead mobs
+ continue
- if(isslime(L) || L.stat == DEAD) // Ignore other slimes and dead mobs
- continue
-
- if(L in Friends) // No eating friends!
- continue
-
- if(issilicon(L) && (rabid || attacked)) // They can't eat silicons, but they can glomp them in defence
- targets += L // Possible target found!
-
- if(istype(L, /mob/living/carbon/human) && dna) //Ignore slime(wo)men
- var/mob/living/carbon/human/H = L
- if(H.species.name == "Slime")
- continue
-
- if(!L.canmove) // Only one slime can latch on at a time.
- var/notarget = 0
- for(var/mob/living/carbon/slime/M in view(1,L))
- if(M.Victim == L)
- notarget = 1
- if(notarget)
- continue
+ if(L in Friends) // No eating friends!
+ continue
+ if(issilicon(L) && (rabid || attacked)) // They can't eat silicons, but they can glomp them in defence
targets += L // Possible target found!
- if(targets.len > 0)
- if(attacked || rabid || hungry == 2)
- Target = targets[1] // I am attacked and am fighting back or so hungry I don't even care
- else
- for(var/mob/living/carbon/C in targets)
- if(!Discipline && prob(5))
- if(ishuman(C))
- Target = C
- break
+ if(istype(L, /mob/living/carbon/human) && dna) //Ignore slime(wo)men
+ var/mob/living/carbon/human/H = L
+ if(H.species.name == "Slime")
+ continue
- if(isalien(C) || ismonkey(C))
- Target = C
- break
+ if(!L.canmove) // Only one slime can latch on at a time.
+ var/notarget = 0
+ for(var/mob/living/carbon/slime/M in view(1,L))
+ if(M.Victim == L)
+ notarget = 1
+ if(notarget)
+ continue
- if (Target)
- target_patience = rand(5,7)
- if (is_adult)
- target_patience += 3
+ targets += L // Possible target found!
- if(!Target) // If we have no target, we are wandering or following orders
- if (Leader)
- if (holding_still)
- holding_still = max(holding_still - 1, 0)
- else if(canmove && isturf(loc))
- step_to(src, Leader)
+ if(targets.len > 0)
+ if(attacked || rabid || hungry == 2)
+ Target = targets[1] // I am attacked and am fighting back or so hungry I don't even care
+ else
+ for(var/mob/living/carbon/C in targets)
+ if(ishuman(C) && !Discipline && prob(5))
+ Target = C
+ break
- else if(hungry)
- if (holding_still)
- holding_still = max(holding_still - hungry, 0)
- else if(canmove && isturf(loc) && prob(50))
- step(src, pick(cardinal))
+ if(isalien(C) || ismonkey(C) || isanimal(C))
+ Target = C
+ break
+
+ if (Target)
+ target_patience = rand(5,7)
+ if (is_adult)
+ target_patience += 3
+
+ if(!Target) // If we have no target, we are wandering or following orders
+ if (Leader)
+ if (holding_still)
+ holding_still = max(holding_still - 1, 0)
+ else if(canmove && isturf(loc))
+ step_to(src, Leader)
+
+ else if(hungry)
+ if (holding_still)
+ holding_still = max(holding_still - 1 - hungry, 0)
+ else if(canmove && isturf(loc) && prob(50))
+ step(src, pick(cardinal))
+
+ else
+ if (holding_still)
+ holding_still = max(holding_still - 1, 0)
+ else if(canmove && isturf(loc) && prob(33))
+ step(src, pick(cardinal))
+
+/mob/living/carbon/slime/proc/handle_AI() // the master AI process
+
+ if(stat == DEAD || client || Victim) return // If we're dead or have a client, we don't need AI, if we're feeding, we continue feeding
+ AIproc = 1
+
+ if(amount_grown >= 10 && !Target)
+ if(is_adult)
+ Reproduce()
+ else
+ Evolve()
+ AIproc = 0
+ return
+
+ if(Target) // We're chasing the target
+ if(Target.stat == DEAD)
+ Target = null
+ AIproc = 0
+ return
+
+ for(var/mob/living/carbon/slime/M in view(1, Target))
+ if(M.Victim == Target)
+ Target = null
+ AIproc = 0
+ return
+
+ if(Target.Adjacent(src))
+ if(istype(Target, /mob/living/silicon)) // Glomp the silicons
+ if(!Atkcool)
+ a_intent = "hurt"
+ UnarmedAttack(Target)
+ Atkcool = 1
+ spawn(45)
+ Atkcool = 0
+ AIproc = 0
+ return
+
+ if(Target.client && !Target.lying && prob(60 + powerlevel * 4)) // Try to take down the target first
+ if(!Atkcool)
+ Atkcool = 1
+ spawn(45)
+ Atkcool = 0
+
+ a_intent = "disarm"
+ UnarmedAttack(Target)
else
- if (holding_still)
- holding_still = max(holding_still - 1, 0)
- else if(canmove && isturf(loc) && prob(33))
- step(src, pick(cardinal))
- else if(!AIproc)
- spawn()
- AIprocess()
+ if(!Atkcool)
+ a_intent = "grab"
+ UnarmedAttack(Target)
+
+ else if(Target in view(7, src))
+ step_to(src, Target)
+
+ else
+ Target = null
+ AIproc = 0
+ return
+
+ else
+ var/mob/living/carbon/slime/frenemy
+ for (var/mob/living/carbon/slime/S in view(1, src))
+ if (S != src)
+ frenemy = S
+ if (frenemy && prob(1))
+ if (frenemy.colour == colour)
+ a_intent = "help"
+ else
+ a_intent = "hurt"
+ UnarmedAttack(frenemy)
+
+ var/sleeptime = movement_delay()
+ if(sleeptime <= 5) sleeptime = 5 // Maximum one action per half a second
+ spawn (sleeptime)
+ handle_AI()
+ return
/mob/living/carbon/slime/proc/handle_speech_and_mood()
//Mood starts here
var/newmood = ""
- if (rabid || attacked) newmood = "angry"
+ a_intent = "help"
+ if (rabid || attacked)
+ newmood = "angry"
+ a_intent = "hurt"
else if (Target) newmood = "mischevous"
if (!newmood)
@@ -569,11 +528,13 @@
if (is_adult) return 300
else return 200
-/mob/living/carbon/slime/proc/will_hunt(var/hunger = -1) // Check for being stopped from feeding and chasing
+/mob/living/carbon/slime/proc/will_hunt(var/hunger) // Check for being stopped from feeding and chasing
if (hunger == 2 || rabid || attacked) return 1
if (Leader) return 0
if (holding_still) return 0
- return 1
+ if (hunger == 1 || prob(25))
+ return 1
+ return 0
/mob/living/carbon/slime/slip() //Can't slip something without legs.
return 0
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/metroid/metroid.dm b/code/modules/mob/living/carbon/metroid/metroid.dm
index 14a963cfdc..d6c8c226c4 100644
--- a/code/modules/mob/living/carbon/metroid/metroid.dm
+++ b/code/modules/mob/living/carbon/metroid/metroid.dm
@@ -4,10 +4,9 @@
icon_state = "grey baby slime"
pass_flags = PASSTABLE
var/is_adult = 0
- speak_emote = list("telepathically chirps")
+ speak_emote = list("chirps")
layer = 5
-
maxHealth = 150
health = 150
gender = NEUTER
@@ -25,7 +24,7 @@
var/cores = 1 // the number of /obj/item/slime_extract's the slime has left inside
var/mutation_chance = 30 // Chance of mutating, should be between 25 and 35
- var/powerlevel = 0 // 1-10 controls how much electricity they are generating
+ var/powerlevel = 0 // 0-10 controls how much electricity they are generating
var/amount_grown = 0 // controls how long the slime has been overfed, if 10, grows or reproduces
var/number = 0 // Used to understand when someone is talking to it
@@ -45,6 +44,11 @@
var/mood = "" // To show its face
+ var/AIproc = 0 // If it's 0, we need to launch an AI proc
+ var/Atkcool = 0 // attack cooldown
+ var/SStun = 0 // NPC stun variable. Used to calm them down when they are attacked while feeding, or they will immediately re-attach
+ var/Discipline = 0 // if a slime has been hit with a freeze gun, or wrestled/attacked off a human, they become disciplined and don't attack anymore for a while. The part about freeze gun is a lie
+
///////////TIME FOR SUBSPECIES
var/colour = "grey"
@@ -53,28 +57,21 @@
var/core_removal_stage = 0 //For removing cores.
-/mob/living/carbon/slime/New()
+/mob/living/carbon/slime/New(var/location, var/colour="grey")
verbs += /mob/living/proc/ventcrawl
create_reagents(100)
- spawn (0)
- number = rand(1, 1000)
- name = "[colour] [is_adult ? "adult" : "baby"] slime ([number])"
- icon_state = "[colour] [is_adult ? "adult" : "baby"] slime"
- real_name = name
- slime_mutation = mutation_table(colour)
- mutation_chance = rand(25, 35)
- var/sanitizedcolour = replacetext(colour, " ", "")
- coretype = text2path("/obj/item/slime_extract/[sanitizedcolour]")
- ..()
-/mob/living/carbon/slime/regenerate_icons()
- icon_state = "[colour] [is_adult ? "adult" : "baby"] slime"
- overlays.len = 0
- if (mood)
- overlays += image('icons/mob/slimes.dmi', icon_state = "aslime-[mood]")
- ..()
+ src.colour = colour
+ number = rand(1, 1000)
+ name = "[colour] [is_adult ? "adult" : "baby"] slime ([number])"
+ real_name = name
+ slime_mutation = mutation_table(colour)
+ mutation_chance = rand(25, 35)
+ var/sanitizedcolour = replacetext(colour, " ", "")
+ coretype = text2path("/obj/item/slime_extract/[sanitizedcolour]")
+ ..(location)
/mob/living/carbon/slime/movement_delay()
if (bodytemperature >= 330.23) // 135 F
@@ -82,8 +79,8 @@
var/tally = 0
- var/health_deficiency = (100 - health)
- if(health_deficiency >= 45) tally += (health_deficiency / 25)
+ var/health_deficiency = (maxHealth - health)
+ if(health_deficiency >= 30) tally += (health_deficiency / 25)
if (bodytemperature < 183.222)
tally += (283.222 - bodytemperature) / 10 * 1.75
@@ -105,25 +102,23 @@
return
now_pushing = 1
- if(isobj(AM))
- if(!client && powerlevel > 0)
- var/probab = 10
- switch(powerlevel)
- if(1 to 2) probab = 20
- if(3 to 4) probab = 30
- if(5 to 6) probab = 40
- if(7 to 8) probab = 60
- if(9) probab = 70
- if(10) probab = 95
- if(prob(probab))
- if(istype(AM, /obj/structure/window) || istype(AM, /obj/structure/grille))
- if(nutrition <= get_hunger_nutrition() && !Atkcool)
- if (is_adult || prob(5))
- UnarmedAttack(AM)
- spawn()
- Atkcool = 1
- sleep(45)
- Atkcool = 0
+ if(isobj(AM) && !client && powerlevel > 0)
+ var/probab = 10
+ switch(powerlevel)
+ if(1 to 2) probab = 20
+ if(3 to 4) probab = 30
+ if(5 to 6) probab = 40
+ if(7 to 8) probab = 60
+ if(9) probab = 70
+ if(10) probab = 95
+ if(prob(probab))
+ if(istype(AM, /obj/structure/window) || istype(AM, /obj/structure/grille))
+ if(nutrition <= get_hunger_nutrition() && !Atkcool)
+ if (is_adult || prob(5))
+ UnarmedAttack(AM)
+ Atkcool = 1
+ spawn(45)
+ Atkcool = 0
if(ismob(AM))
var/mob/tmob = AM
@@ -139,21 +134,8 @@
return
now_pushing = 0
+
..()
- if (!istype(AM, /atom/movable))
- return
- if (!( now_pushing ))
- now_pushing = 1
- if (!( AM.anchored ))
- var/t = get_dir(src, AM)
- if (istype(AM, /obj/structure/window))
- var/obj/structure/window/W = AM
- if(W.is_full_window())
- for(var/obj/structure/window/win in get_step(AM,t))
- now_pushing = 0
- return
- step(AM, t)
- now_pushing = null
/mob/living/carbon/slime/Process_Spacemove()
return 2
@@ -162,10 +144,8 @@
..()
statpanel("Status")
- if(is_adult)
- stat(null, "Health: [round((health / 200) * 100)]%")
- else
- stat(null, "Health: [round((health / 150) * 100)]%")
+ stat(null, "Health: [round((health / maxHealth) * 100)]%")
+ stat(null, "Intent: [a_intent]")
if (client.statpanel == "Status")
stat(null, "Nutrition: [nutrition]/[get_max_nutrition()]")
@@ -227,9 +207,7 @@
if(shielded)
damage /= 4
- //paralysis += 1
-
- show_message(" The blob attacks you!")
+ show_message(" The blob attacks you!")
adjustFireLoss(damage)
@@ -244,14 +222,12 @@
return
/mob/living/carbon/slime/meteorhit(O as obj)
- for(var/mob/M in viewers(src, null))
- if ((M.client && !( M.blinded )))
- M.show_message(text("\red [] has been hit by []", src, O), 1)
- if (health > 0)
- adjustBruteLoss((istype(O, /obj/effect/meteor/small) ? 10 : 25))
- adjustFireLoss(30)
+ visible_message("[src] has been hit by [O]")
- updatehealth()
+ adjustBruteLoss((istype(O, /obj/effect/meteor/small) ? 10 : 25))
+ adjustFireLoss(30)
+
+ updatehealth()
return
/mob/living/carbon/slime/attack_hand(mob/living/carbon/human/M as mob)
@@ -271,11 +247,9 @@
if(prob(90) && !client)
Discipline++
- spawn()
- SStun = 1
- sleep(rand(45,60))
- if(src)
- SStun = 0
+ SStun = 1
+ spawn(rand(45,60))
+ SStun = 0
Victim = null
anchored = 0
@@ -299,11 +273,9 @@
if(Discipline == 1)
attacked = 0
- spawn()
- SStun = 1
- sleep(rand(55,65))
- if(src)
- SStun = 0
+ SStun = 1
+ spawn(rand(55,65))
+ SStun = 0
Victim = null
anchored = 0
@@ -345,15 +317,13 @@
if(prob(80) && !client)
Discipline++
spawn(0)
-
step_away(src,M,15)
sleep(3)
step_away(src,M,15)
-
playsound(loc, "punch", 25, 1, -1)
visible_message("[M] has punched [src]!", \
- "[M] has punched [src]!")
+ "[M] has punched [src]!")
adjustBruteLoss(damage)
updatehealth()
@@ -381,9 +351,8 @@
Target = null
anchored = 0
- spawn()
- SStun = 1
- sleep(rand(5,20))
+ SStun = 1
+ spawn(rand(5,20))
SStun = 0
spawn(0)
@@ -403,9 +372,8 @@
Discipline++
if(Discipline == 1)
attacked = 0
- spawn()
- SStun = 1
- sleep(rand(5,20))
+ SStun = 1
+ spawn(rand(5,20))
SStun = 0
Victim = null
@@ -426,8 +394,8 @@
/mob/living/carbon/slime/restrained()
return 0
-mob/living/carbon/slime/var/co2overloadtime = null
-mob/living/carbon/slime/var/temperature_resistance = T0C+75
+/mob/living/carbon/slime/var/co2overloadtime = null
+/mob/living/carbon/slime/var/temperature_resistance = T0C+75
/mob/living/carbon/slime/show_inv(mob/user)
return
@@ -435,8 +403,17 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75
/mob/living/carbon/slime/toggle_throw_mode()
return
-/mob/living/carbon/slime/proc/apply_water()
- adjustToxLoss(rand(15,20))
+/mob/living/carbon/slime/proc/gain_nutrition(var/amount)
+ nutrition += amount
+ if(prob(amount * 2)) // Gain around one level per 50 nutrition
+ powerlevel++
+ if(powerlevel > 10)
+ powerlevel = 10
+ adjustToxLoss(-10)
+ nutrition = max(nutrition, get_max_nutrition())
+
+/mob/living/carbon/slime/proc/apply_water(var/amount)
+ adjustToxLoss(15 + amount)
if (!client)
if (Target) // Like cats
Target = null
@@ -446,371 +423,4 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75
/mob/living/carbon/slime/can_use_vents()
if(Victim)
return "You cannot ventcrawl while feeding."
- ..()
-
-/obj/item/slime_extract
- name = "slime extract"
- desc = "Goo extracted from a slime. Legends claim these to have \"magical powers\"."
- icon = 'icons/mob/slimes.dmi'
- icon_state = "grey slime extract"
- force = 1.0
- w_class = 1.0
- throwforce = 0
- throw_speed = 3
- throw_range = 6
- origin_tech = "biotech=4"
- var/Uses = 1 // uses before it goes inert
- var/enhanced = 0 //has it been enhanced before?
-
- attackby(obj/item/O as obj, mob/user as mob)
- if(istype(O, /obj/item/weapon/slimesteroid2))
- if(enhanced == 1)
- user << " This extract has already been enhanced!"
- return ..()
- if(Uses == 0)
- user << " You can't enhance a used extract!"
- return ..()
- user <<"You apply the enhancer. It now has triple the amount of uses."
- Uses = 3
- enhanced = 1
- del(O)
-
-/obj/item/slime_extract/New()
- ..()
- create_reagents(100)
-
-/obj/item/slime_extract/grey
- name = "grey slime extract"
- icon_state = "grey slime extract"
-
-/obj/item/slime_extract/gold
- name = "gold slime extract"
- icon_state = "gold slime extract"
-
-/obj/item/slime_extract/silver
- name = "silver slime extract"
- icon_state = "silver slime extract"
-
-/obj/item/slime_extract/metal
- name = "metal slime extract"
- icon_state = "metal slime extract"
-
-/obj/item/slime_extract/purple
- name = "purple slime extract"
- icon_state = "purple slime extract"
-
-/obj/item/slime_extract/darkpurple
- name = "dark purple slime extract"
- icon_state = "dark purple slime extract"
-
-/obj/item/slime_extract/orange
- name = "orange slime extract"
- icon_state = "orange slime extract"
-
-/obj/item/slime_extract/yellow
- name = "yellow slime extract"
- icon_state = "yellow slime extract"
-
-/obj/item/slime_extract/red
- name = "red slime extract"
- icon_state = "red slime extract"
-
-/obj/item/slime_extract/blue
- name = "blue slime extract"
- icon_state = "blue slime extract"
-
-/obj/item/slime_extract/darkblue
- name = "dark blue slime extract"
- icon_state = "dark blue slime extract"
-
-/obj/item/slime_extract/pink
- name = "pink slime extract"
- icon_state = "pink slime extract"
-
-/obj/item/slime_extract/green
- name = "green slime extract"
- icon_state = "green slime extract"
-
-/obj/item/slime_extract/lightpink
- name = "light pink slime extract"
- icon_state = "light pink slime extract"
-
-/obj/item/slime_extract/black
- name = "black slime extract"
- icon_state = "black slime extract"
-
-/obj/item/slime_extract/oil
- name = "oil slime extract"
- icon_state = "oil slime extract"
-
-/obj/item/slime_extract/adamantine
- name = "adamantine slime extract"
- icon_state = "adamantine slime extract"
-
-/obj/item/slime_extract/bluespace
- name = "bluespace slime extract"
- icon_state = "bluespace slime extract"
-
-/obj/item/slime_extract/pyrite
- name = "pyrite slime extract"
- icon_state = "pyrite slime extract"
-
-/obj/item/slime_extract/cerulean
- name = "cerulean slime extract"
- icon_state = "cerulean slime extract"
-
-/obj/item/slime_extract/sepia
- name = "sepia slime extract"
- icon_state = "sepia slime extract"
-
-/obj/item/slime_extract/rainbow
- name = "rainbow slime extract"
- icon_state = "rainbow slime extract"
-
-////Pet Slime Creation///
-
-/obj/item/weapon/slimepotion
- name = "docility potion"
- desc = "A potent chemical mix that will nullify a slime's powers, causing it to become docile and tame."
- icon = 'icons/obj/chemical.dmi'
- icon_state = "bottle19"
-
- attack(mob/living/carbon/slime/M as mob, mob/user as mob)
- if(!istype(M, /mob/living/carbon/slime))//If target is not a slime.
- user << " The potion only works on baby slimes!"
- return ..()
- if(M.is_adult) //Can't tame adults
- user << " Only baby slimes can be tamed!"
- return..()
- if(M.stat)
- user << " The slime is dead!"
- return..()
- if(M.mind)
- user << " The slime resists!"
- return ..()
- var/mob/living/simple_animal/slime/pet = new /mob/living/simple_animal/slime(M.loc)
- pet.icon_state = "[M.colour] baby slime"
- pet.icon_living = "[M.colour] baby slime"
- pet.icon_dead = "[M.colour] baby slime dead"
- pet.colour = "[M.colour]"
- user <<"You feed the slime the potion, removing it's powers and calming it."
- del(M)
- var/newname = sanitize(copytext(input(user, "Would you like to give the slime a name?", "Name your new pet", "pet slime") as null|text,1,MAX_NAME_LEN))
-
- if (!newname)
- newname = "pet slime"
- pet.name = newname
- pet.real_name = newname
- del(src)
-
-/obj/item/weapon/slimepotion2
- name = "advanced docility potion"
- desc = "A potent chemical mix that will nullify a slime's powers, causing it to become docile and tame. This one is meant for adult slimes"
- icon = 'icons/obj/chemical.dmi'
- icon_state = "bottle19"
-
- attack(mob/living/carbon/slime/M as mob, mob/user as mob)
- if(!istype(M, /mob/living/carbon/slime/))//If target is not a slime.
- user << " The potion only works on slimes!"
- return ..()
- if(M.stat)
- user << " The slime is dead!"
- return..()
- if(M.mind)
- user << " The slime resists!"
- return ..()
- var/mob/living/simple_animal/adultslime/pet = new /mob/living/simple_animal/adultslime(M.loc)
- pet.icon_state = "[M.colour] adult slime"
- pet.icon_living = "[M.colour] adult slime"
- pet.icon_dead = "[M.colour] baby slime dead"
- pet.colour = "[M.colour]"
- user <<"You feed the slime the potion, removing it's powers and calming it."
- del(M)
- var/newname = sanitize(copytext(input(user, "Would you like to give the slime a name?", "Name your new pet", "pet slime") as null|text,1,MAX_NAME_LEN))
-
- if (!newname)
- newname = "pet slime"
- pet.name = newname
- pet.real_name = newname
- del(src)
-
-
-/obj/item/weapon/slimesteroid
- name = "slime steroid"
- desc = "A potent chemical mix that will cause a slime to generate more extract."
- icon = 'icons/obj/chemical.dmi'
- icon_state = "bottle16"
-
- attack(mob/living/carbon/slime/M as mob, mob/user as mob)
- if(!istype(M, /mob/living/carbon/slime))//If target is not a slime.
- user << " The steroid only works on baby slimes!"
- return ..()
- if(M.is_adult) //Can't tame adults
- user << " Only baby slimes can use the steroid!"
- return..()
- if(M.stat)
- user << " The slime is dead!"
- return..()
- if(M.cores == 3)
- user <<" The slime already has the maximum amount of extract!"
- return..()
-
- user <<"You feed the slime the steroid. It now has triple the amount of extract."
- M.cores = 3
- del(src)
-
-/obj/item/weapon/slimesteroid2
- name = "extract enhancer"
- desc = "A potent chemical mix that will give a slime extract three uses."
- icon = 'icons/obj/chemical.dmi'
- icon_state = "bottle17"
-
- /*afterattack(obj/target, mob/user , flag)
- if(istype(target, /obj/item/slime_extract))
- if(target.enhanced == 1)
- user << " This extract has already been enhanced!"
- return ..()
- if(target.Uses == 0)
- user << " You can't enhance a used extract!"
- return ..()
- user <<"You apply the enhancer. It now has triple the amount of uses."
- target.Uses = 3
- target.enahnced = 1
- del(src)*/
-
-/obj/effect/golemrune
- anchored = 1
- desc = "a strange rune used to create golems. It glows when spirits are nearby."
- name = "rune"
- icon = 'icons/obj/rune.dmi'
- icon_state = "golem"
- unacidable = 1
- layer = TURF_LAYER
-
- New()
- ..()
- processing_objects.Add(src)
-
- process()
- var/mob/dead/observer/ghost
- for(var/mob/dead/observer/O in src.loc)
- if(!O.client) continue
- if(O.mind && O.mind.current && O.mind.current.stat != DEAD) continue
- ghost = O
- break
- if(ghost)
- icon_state = "golem2"
- else
- icon_state = "golem"
-
- attack_hand(mob/living/user as mob)
- var/mob/dead/observer/ghost
- for(var/mob/dead/observer/O in src.loc)
- if(!O.client) continue
- if(O.mind && O.mind.current && O.mind.current.stat != DEAD) continue
- ghost = O
- break
- if(!ghost)
- user << "The rune fizzles uselessly. There is no spirit nearby."
- return
- var/mob/living/carbon/human/G = new(src.loc)
- G.set_species("Golem")
- G.key = ghost.key
- G << "You are an adamantine golem. You move slowly, but are highly resistant to heat and cold as well as blunt trauma. You are unable to wear clothes, but can still use most tools. Serve [user], and assist them in completing their goals at any cost."
- del (src)
-
-
- proc/announce_to_ghosts()
- for(var/mob/dead/observer/G in player_list)
- if(G.client)
- var/area/A = get_area(src)
- if(A)
- G << "Golem rune created in [A.name]."
-
-/mob/living/carbon/slime/has_eyes()
- return 0
-
-//////////////////////////////Old shit from metroids/RoRos, and the old cores, would not take much work to re-add them////////////////////////
-
-/*
-// Basically this slime Core catalyzes reactions that normally wouldn't happen anywhere
-/obj/item/slime_core
- name = "slime extract"
- desc = "Goo extracted from a slime. Legends claim these to have \"magical powers\"."
- icon = 'icons/mob/slimes.dmi'
- icon_state = "slime extract"
- force = 1.0
- w_class = 1.0
- throwforce = 1.0
- throw_speed = 2
- throw_range = 6
- origin_tech = "biotech=4"
- var/POWERFLAG = 0 // sshhhhhhh
- var/Flush = 30
- var/Uses = 5 // uses before it goes inert
-
-/obj/item/slime_core/New()
- ..()
- create_reagents(100)
- POWERFLAG = rand(1,10)
- Uses = rand(7, 25)
- //flags |= NOREACT
-/*
- spawn()
- Life()
-
- proc/Life()
- while(src)
- sleep(25)
- Flush--
- if(Flush <= 0)
- reagents.clear_reagents()
- Flush = 30
-*/
-
-
-
-/obj/item/weapon/reagent_containers/food/snacks/egg/slime
- name = "slime egg"
- desc = "A small, gelatinous egg."
- icon = 'icons/mob/mob.dmi'
- icon_state = "slime egg-growing"
- bitesize = 12
- origin_tech = "biotech=4"
- var/grown = 0
-
-/obj/item/weapon/reagent_containers/food/snacks/egg/slime/New()
- ..()
- reagents.add_reagent("nutriment", 4)
- reagents.add_reagent("slimejelly", 1)
- spawn(rand(1200,1500))//the egg takes a while to "ripen"
- Grow()
-
-/obj/item/weapon/reagent_containers/food/snacks/egg/slime/proc/Grow()
- grown = 1
- icon_state = "slime egg-grown"
- processing_objects.Add(src)
- return
-
-/obj/item/weapon/reagent_containers/food/snacks/egg/slime/proc/Hatch()
- processing_objects.Remove(src)
- var/turf/T = get_turf(src)
- src.visible_message(" The [name] pulsates and quivers!")
- spawn(rand(50,100))
- src.visible_message(" The [name] bursts open!")
- new/mob/living/carbon/slime(T)
- del(src)
-
-
-/obj/item/weapon/reagent_containers/food/snacks/egg/slime/process()
- var/turf/location = get_turf(src)
- var/datum/gas_mixture/environment = location.return_air()
- if (environment.phoron > MOLES_PHORON_VISIBLE)//phoron exposure causes the egg to hatch
- src.Hatch()
-
-/obj/item/weapon/reagent_containers/food/snacks/egg/slime/attackby(obj/item/weapon/W as obj, mob/user as mob)
- if(istype( W, /obj/item/toy/crayon ))
- return
- else
- ..()
-*/
+ ..()
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/metroid/powers.dm b/code/modules/mob/living/carbon/metroid/powers.dm
index 23ca8acbf6..b2f8c2588f 100644
--- a/code/modules/mob/living/carbon/metroid/powers.dm
+++ b/code/modules/mob/living/carbon/metroid/powers.dm
@@ -1,75 +1,46 @@
-/mob/living/carbon/slime/verb/Feed()
- set category = "Slime"
- set desc = "This will let you feed on any valid creature in the surrounding area. This should also be used to halt the feeding process."
- if(Victim)
+/mob/living/carbon/slime/proc/Wrap(var/mob/living/M) // This is a proc for the clicks
+ if (Victim == M || src == M)
Feedstop()
return
- if(stat)
- src << "I must be conscious to do this..."
+ if (Victim)
+ src << "I am already feeding..."
return
- var/list/choices = list()
- for(var/mob/living/C in view(1,src))
- if(C!=src && !istype(C,/mob/living/carbon/slime) && Adjacent(C))
- choices += C
-
- var/mob/living/M = input(src,"Who do you wish to feed on?") in null|choices
- if(!M) return
- if(Adjacent(M))
-
- if(!istype(src, /mob/living/carbon/brain))
- if(!istype(M, /mob/living/carbon/slime))
- if(stat != 2)
- if(health > -70)
-
- for(var/mob/living/carbon/slime/met in view())
- if(met.Victim == M && met != src)
- src << "The [met.name] is already feeding on this subject..."
- return
- src << "\blue I have latched onto the subject and begun feeding..."
- M << "\red The [src.name] has latched onto your head!"
- Feedon(M)
-
- else
- src << "This subject does not have a strong enough life energy..."
- else
- src << "This subject does not have an edible life energy..."
- else
- src << "I must not feed on my brothers..."
- else
- src << "This subject does not have an edible life energy..."
+ var t = invalidFeedTarget(M)
+ if (t)
+ src << t
+ return
+ Feedon(M)
+/mob/living/carbon/slime/proc/invalidFeedTarget(var/mob/living/M)
+ if (!M || !istype(M))
+ return "This subject is incomparable..."
+ if (istype(M, /mob/living/carbon/slime)) // No cannibalism... yet
+ return "I cannot feed on other slimes..."
+ if (!Adjacent(M))
+ return "This subject is too far away..."
+ if (istype(M, /mob/living/carbon) && M.getCloneLoss() > 150 || istype(M, /mob/living/simple_animal) && M.stat == DEAD)
+ return "This subject does not have an edible life energy..."
+ for(var/mob/living/carbon/slime/met in view())
+ if(met.Victim == M && met != src)
+ return "The [met.name] is already feeding on this subject..."
+ return 0
/mob/living/carbon/slime/proc/Feedon(var/mob/living/M)
Victim = M
- src.loc = M.loc
+ loc = M.loc
canmove = 0
anchored = 1
- var/lastnut = nutrition
- var/fed_succesfully = 0
- if(is_adult)
- icon_state = "[colour] adult slime eat"
- else
- icon_state = "[colour] baby slime eat"
- while(Victim && M.health > -70 && stat != 2)
+ regenerate_icons()
+
+ while(Victim && !invalidFeedTarget(M) && stat != 2)
canmove = 0
if(Adjacent(M))
- loc = M.loc
-
- if(prob(15) && M.client && istype(M, /mob/living/carbon))
- var/mob/living/carbon/C = M
- if (!(C.species && (C.species.flags & NO_PAIN)))
- M << "[pick("You can feel your body becoming weak!", \
- "You feel like you're about to die!", \
- "You feel every part of your body screaming in agony!", \
- "A low, rolling pain passes through your body!", \
- "Your body feels as if it's falling apart!", \
- "You feel extremely weak!", \
- "A sharp, deep pain bathes every inch of your body!")]"
+ UpdateFeed(M)
if(istype(M, /mob/living/carbon))
Victim.adjustCloneLoss(rand(5,6))
@@ -77,83 +48,51 @@
if(Victim.health <= 0)
Victim.adjustToxLoss(rand(2,4))
- fed_succesfully = 1
-
else if(istype(M, /mob/living/simple_animal))
Victim.adjustBruteLoss(is_adult ? rand(7, 15) : rand(4, 12))
- fed_succesfully = 1
else
- if(prob(25))
- src << "[pick("This subject is incompatable", \
- "This subject does not have a life energy", "This subject is empty", \
- "I am not satisified", "I can not feed from this subject", \
- "I do not feel nourished", "This subject is not food")]..."
+ src << "[pick("This subject is incompatable", "This subject does not have a life energy", "This subject is empty", "I am not satisified", "I can not feed from this subject", "I do not feel nourished", "This subject is not food")]..."
+ Feedstop()
+ break
- if(fed_succesfully)
- //I have no idea why this is not in handle_nutrition()
- nutrition += rand(15,30)
- if(nutrition >= lastnut + 50)
- if(prob(80))
- lastnut = nutrition
- powerlevel++
- if(powerlevel > 10)
- powerlevel = 10
- adjustToxLoss(-10)
+ if(prob(15) && M.client && istype(M, /mob/living/carbon))
+ var/painMes = pick("You can feel your body becoming weak!", "You feel like you're about to die!", "You feel every part of your body screaming in agony!", "A low, rolling pain passes through your body!", "Your body feels as if it's falling apart!", "You feel extremely weak!", "A sharp, deep pain bathes every inch of your body!")
+ if (ishuman(M))
+ var/mob/living/carbon/human/H = M
+ H.custom_pain(painMes)
+ else if (istype(M, /mob/living/carbon))
+ var/mob/living/carbon/C = M
+ if (!(C.species && (C.species.flags & NO_PAIN)))
+ M << "[painMes]"
- //Heal yourself.
- adjustOxyLoss(-10)
- adjustBruteLoss(-10)
- adjustFireLoss(-10)
- adjustCloneLoss(-10)
+ gain_nutrition(rand(20,25))
- updatehealth()
- if(Victim)
- Victim.updatehealth()
-
- sleep(rand(15,45))
+ adjustOxyLoss(-10) //Heal yourself
+ adjustBruteLoss(-10)
+ adjustFireLoss(-10)
+ adjustCloneLoss(-10)
+ updatehealth()
+ if(Victim)
+ Victim.updatehealth()
+ sleep(30) // Deal damage every 3 seconds
else
break
- if(stat == 2)
- if(!is_adult)
- icon_state = "[colour] baby slime dead"
-
- else
- if(is_adult)
- icon_state = "[colour] adult slime"
- else
- icon_state = "[colour] baby slime"
-
canmove = 1
anchored = 0
- if(M)
- if(M.health <= -70)
- M.canmove = 0
- if(!client)
- if(Victim && !rabid && !attacked)
- if(Victim.LAssailant && Victim.LAssailant != Victim)
- if(prob(50))
- if(!(Victim.LAssailant in Friends))
- Friends[Victim.LAssailant] = 1
- //Friends.Add(Victim.LAssailant) // no idea why i was using the |= operator
- else
- ++Friends[Victim.LAssailant]
+ if(M && invalidFeedTarget(M)) // This means that the slime drained the victim
+ if(!client)
+ if(Victim && !rabid && !attacked && Victim.LAssailant && Victim.LAssailant != Victim && prob(50))
+ if(!(Victim.LAssailant in Friends))
+ Friends[Victim.LAssailant] = 1
+ else
+ ++Friends[Victim.LAssailant]
-
- if(M.client && istype(src, /mob/living/carbon/human))
- if(prob(85))
- rabid = 1 // UUUNNBGHHHH GONNA EAT JUUUUUU
-
- if(client) src << "This subject does not have a strong enough life energy anymore..."
else
- M.canmove = 1
-
- if(client) src << "I have stopped feeding..."
- else
- if(client) src << "I have stopped feeding..."
+ src << "This subject does not have a strong enough life energy anymore..."
Victim = null
@@ -167,14 +106,14 @@
if(Victim == M)
loc = M.loc // simple "attach to head" effect!
-
/mob/living/carbon/slime/verb/Evolve()
set category = "Slime"
set desc = "This will let you evolve from baby to adult slime."
if(stat)
- src << "I must be conscious to do this..."
+ src << "I must be conscious to do this..."
return
+
if(!is_adult)
if(amount_grown >= 10)
is_adult = 1
@@ -183,36 +122,35 @@
regenerate_icons()
name = text("[colour] [is_adult ? "adult" : "baby"] slime ([number])")
else
- src << "I am not ready to evolve yet..."
+ src << "I am not ready to evolve yet..."
else
- src << "I have already evolved..."
+ src << "I have already evolved..."
/mob/living/carbon/slime/verb/Reproduce()
set category = "Slime"
set desc = "This will make you split into four Slimes."
if(stat)
- src << "I must be conscious to do this..."
+ src << "I must be conscious to do this..."
return
if(is_adult)
if(amount_grown >= 10)
if(stat)
- src << "I must be conscious to do this..."
+ src << "I must be conscious to do this..."
return
var/list/babies = list()
var/new_nutrition = round(nutrition * 0.9)
var/new_powerlevel = round(powerlevel / 4)
- for(var/i=1,i<=4,i++)
- var/mob/living/carbon/slime/M = new /mob/living/carbon/slime/(loc)
+ for(var/i = 1, i <= 4, i++)
+ var/t = colour
if(prob(mutation_chance))
- M.colour = slime_mutation[rand(1,4)]
- else
- M.colour = colour
+ t = slime_mutation[rand(1,4)]
+ var/mob/living/carbon/slime/M = new /mob/living/carbon/slime/(loc, t)
if(ckey) M.nutrition = new_nutrition //Player slimes are more robust at spliting. Once an oversight of poor copypasta, now a feature!
M.powerlevel = new_powerlevel
- if(i != 1) step_away(M,src)
+ if(i != 1) step_away(M, src)
M.Friends = Friends.Copy()
babies += M
feedback_add_details("slime_babies_born","slimebirth_[replacetext(M.colour," ","_")]")
@@ -225,6 +163,6 @@
new_slime.key = src.key
del(src)
else
- src << "I am not ready to reproduce yet..."
+ src << "I am not ready to reproduce yet..."
else
- src << "I am not old enough to reproduce yet..."
\ No newline at end of file
+ src << "I am not old enough to reproduce yet..."
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/metroid/say.dm b/code/modules/mob/living/carbon/metroid/say.dm
index f4de10ceb7..f1a1761908 100644
--- a/code/modules/mob/living/carbon/metroid/say.dm
+++ b/code/modules/mob/living/carbon/metroid/say.dm
@@ -10,11 +10,11 @@
var/ending = copytext(text, length(text))
if (ending == "?")
- return "telepathically asks";
+ return "asks";
else if (ending == "!")
- return "telepathically cries";
+ return "cries";
- return "telepathically chirps";
+ return "chirps";
/mob/living/carbon/slime/say_understands(var/other)
if (istype(other, /mob/living/carbon/slime))
diff --git a/code/modules/mob/living/carbon/metroid/subtypes.dm b/code/modules/mob/living/carbon/metroid/subtypes.dm
index 9db9e7b02f..6aa75990ac 100644
--- a/code/modules/mob/living/carbon/metroid/subtypes.dm
+++ b/code/modules/mob/living/carbon/metroid/subtypes.dm
@@ -1,4 +1,4 @@
-proc/mutation_table(var/colour)
+/mob/living/carbon/slime/proc/mutation_table(var/colour)
var/list/slime_mutation[4]
switch(colour)
//Tier 1
diff --git a/code/modules/mob/living/carbon/metroid/update_icons.dm b/code/modules/mob/living/carbon/metroid/update_icons.dm
index 8902770055..847dcaeb18 100644
--- a/code/modules/mob/living/carbon/metroid/update_icons.dm
+++ b/code/modules/mob/living/carbon/metroid/update_icons.dm
@@ -1 +1,9 @@
-//no special icon processing
+/mob/living/carbon/slime/regenerate_icons()
+ if (stat == DEAD)
+ icon_state = "[colour] baby slime dead"
+ else
+ icon_state = "[colour] [is_adult ? "adult" : "baby"] slime[Victim ? "" : " eat"]"
+ overlays.len = 0
+ if (mood)
+ overlays += image('icons/mob/slimes.dmi', icon_state = "aslime-[mood]")
+ ..()
\ No newline at end of file
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index 1be8ea4ac9..b33c182b28 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -56,7 +56,7 @@
signaler.signal()
//Stun Beams
- if(istype(P, /obj/item/projectile/beam/stun) || istype(P, /obj/item/projectile/bullet/stunshot))
+ if(P.taser_effect)
stun_effect_act(0, P.agony, def_zone, P)
src <<"\red You have been hit by [P]!"
del P
diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm
old mode 100755
new mode 100644
index a334809a37..edfe9bea0b
--- a/code/modules/mob/living/silicon/pai/pai.dm
+++ b/code/modules/mob/living/silicon/pai/pai.dm
@@ -53,19 +53,23 @@
var/secHUD = 0 // Toggles whether the Security HUD is active or not
var/medHUD = 0 // Toggles whether the Medical HUD is active or not
+ var/medical_cannotfind = 0
var/datum/data/record/medicalActive1 // Datacore record declarations for record software
var/datum/data/record/medicalActive2
+ var/security_cannotfind = 0
var/datum/data/record/securityActive1 // Could probably just combine all these into one
var/datum/data/record/securityActive2
var/obj/machinery/door/hackdoor // The airlock being hacked
- var/hackprogress = 0 // Possible values: 0 - 100, >= 100 means the hack is complete and will be reset upon next check
+ var/hackprogress = 0 // Possible values: 0 - 1000, >= 1000 means the hack is complete and will be reset upon next check
+ var/hack_aborted = 0
var/obj/item/radio/integrated/signal/sradio // AI's signaller
var/translator_on = 0 // keeps track of the translator module
+ var/current_pda_messaging = null
/mob/living/silicon/pai/New(var/obj/item/device/paicard)
diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm
old mode 100755
new mode 100644
index 68cfdabad1..cb9431f04e
--- a/code/modules/mob/living/silicon/pai/software.dm
+++ b/code/modules/mob/living/silicon/pai/software.dm
@@ -1,711 +1,125 @@
-// TODO:
-// - Additional radio modules
-// - Potentially roll HUDs and Records into one
-// - Shock collar/lock system for prisoner pAIs?
-// - Put cable in user's hand instead of on the ground
-// - Camera jack
-
-
-/mob/living/silicon/pai/var/list/available_software = list(
- "crew manifest" = 5,
- "digital messenger" = 5,
- "medical records" = 15,
- "security records" = 15,
- //"camera jack" = 10,
- "door jack" = 30,
- "atmosphere sensor" = 5,
- //"heartbeat sensor" = 10,
- "security HUD" = 20,
- "medical HUD" = 20,
- "universal translator" = 35,
- //"projection array" = 15
- "remote signaller" = 5,
- )
-
-/mob/living/silicon/pai/verb/paiInterface()
- set category = "pAI Commands"
- set name = "Software Interface"
- var/dat = ""
- var/left_part = ""
- var/right_part = softwareMenu()
- src.set_machine(src)
-
- if(temp)
- left_part = temp
- else if(src.stat == 2) // Show some flavor text if the pAI is dead
- left_part = "ÈRrÖR Ða†Ä ÇÖRrÚþ†Ìoñ" //This file has to be saved as ANSI or this will not display correctly
- right_part = "Program index hash not found
"
-
- else
- switch(src.screen) // Determine which interface to show here
- if("main")
- left_part = ""
- if("directives")
- left_part = src.directives()
- if("pdamessage")
- left_part = src.pdamessage()
- if("buy")
- left_part = downloadSoftware()
- if("manifest")
- left_part = src.softwareManifest()
- if("medicalrecord")
- left_part = src.softwareMedicalRecord()
- if("securityrecord")
- left_part = src.softwareSecurityRecord()
- if("translator")
- left_part = src.softwareTranslator()
- if("atmosensor")
- left_part = src.softwareAtmo()
- if("securityhud")
- left_part = src.facialRecognition()
- if("medicalhud")
- left_part = src.medicalAnalysis()
- if("doorjack")
- left_part = src.softwareDoor()
- if("camerajack")
- left_part = src.softwareCamera()
- if("signaller")
- left_part = src.softwareSignal()
- if("radio")
- left_part = src.softwareRadio()
-
- //usr << browse_rsc('windowbak.png') // This has been moved to the mob's Login() proc
-
-
- // Declaring a doctype is necessary to enable BYOND's crappy browser's more advanced CSS functionality
- dat = {"
-
-
-
-
-
-
-
-
-
-
-
-
- "}
- usr << browse(dat, "window=pai;size=685x449;border=0;can_close=1;can_resize=1;can_minimize=1;titlebar=1")
- onclose(usr, "pai")
- temp = null
- return
-
-/mob/living/silicon/pai/Topic(href, href_list)
- ..()
-
- if(href_list["priv_msg"]) // Admin-PMs were triggering the interface popup. Hopefully this will stop it.
- return
- var/soft = href_list["software"]
- var/sub = href_list["sub"]
- if(!soft && !sub)
- return
- if(soft)
- src.screen = soft
- if(sub)
- src.subscreen = text2num(sub)
- switch(soft)
- // Purchasing new software
- if("buy")
- if(src.subscreen == 1)
- var/target = href_list["buy"]
- if(available_software.Find(target))
- var/cost = src.available_software[target]
- if(src.ram >= cost)
- src.ram -= cost
- src.software.Add(target)
- else
- src.temp = "Insufficient RAM available."
- else
- src.temp = "Trunk \"[target]\" not found."
-
- // Configuring onboard radio
- if("radio")
- if(href_list["freq"])
- var/new_frequency = (radio.frequency + text2num(href_list["freq"]))
- if(new_frequency < 1441 || new_frequency > 1599)
- new_frequency = sanitize_frequency(new_frequency)
- else
- radio.set_frequency(new_frequency)
- else if (href_list["talk"])
- radio.broadcasting = text2num(href_list["talk"])
- else if (href_list["listen"])
- radio.listening = text2num(href_list["listen"])
-
- if("image")
- var/newImage = input("Select your new display image.", "Display Image", "Happy") in list("Happy", "Cat", "Extremely Happy", "Face", "Laugh", "Off", "Sad", "Angry", "What")
- var/pID = 1
-
- switch(newImage)
- if("Happy")
- pID = 1
- if("Cat")
- pID = 2
- if("Extremely Happy")
- pID = 3
- if("Face")
- pID = 4
- if("Laugh")
- pID = 5
- if("Off")
- pID = 6
- if("Sad")
- pID = 7
- if("Angry")
- pID = 8
- if("What")
- pID = 9
- src.card.setEmotion(pID)
-
- if("signaller")
-
- if(href_list["send"])
-
- sradio.send_signal("ACTIVATE")
- for(var/mob/O in hearers(1, src.loc))
- O.show_message(text("\icon[] *beep* *beep*", src), 3, "*beep* *beep*", 2)
-
- if(href_list["freq"])
-
- var/new_frequency = (sradio.frequency + text2num(href_list["freq"]))
- if(new_frequency < 1200 || new_frequency > 1600)
- new_frequency = sanitize_frequency(new_frequency)
- sradio.set_frequency(new_frequency)
-
- if(href_list["code"])
-
- sradio.code += text2num(href_list["code"])
- sradio.code = round(sradio.code)
- sradio.code = min(100, sradio.code)
- sradio.code = max(1, sradio.code)
-
-
-
- if("directive")
- if(href_list["getdna"])
- var/mob/living/M = src.loc
- var/count = 0
- while(!istype(M, /mob/living))
- if(!M || !M.loc) return 0 //For a runtime where M ends up in nullspace (similar to bluespace but less colourful)
- M = M.loc
- count++
- if(count >= 6)
- src << "You are not being carried by anyone!"
- return 0
- spawn CheckDNA(M, src)
-
- if("pdamessage")
- if(!isnull(pda))
- if(href_list["toggler"])
- pda.toff = !pda.toff
- else if(href_list["ringer"])
- pda.message_silent = !pda.message_silent
- else if(href_list["target"])
- if(silence_time)
- return alert("Communications circuits remain uninitialized.")
-
- var/target = locate(href_list["target"])
- pda.create_message(src, target, 1)
-
- // Accessing medical records
- if("medicalrecord")
- if(src.subscreen == 1)
- var/datum/data/record/record = locate(href_list["med_rec"])
- if(record)
- var/datum/data/record/R = record
- var/datum/data/record/M = record
- if (!( data_core.general.Find(R) ))
- src.temp = "Unable to locate requested medical record. Record may have been deleted, or never have existed."
- else
- for(var/datum/data/record/E in data_core.medical)
- if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
- M = E
- src.medicalActive1 = R
- src.medicalActive2 = M
- if("securityrecord")
- if(src.subscreen == 1)
- var/datum/data/record/record = locate(href_list["sec_rec"])
- if(record)
- var/datum/data/record/R = record
- var/datum/data/record/M = record
- if (!( data_core.general.Find(R) ))
- src.temp = "Unable to locate requested security record. Record may have been deleted, or never have existed."
- else
- for(var/datum/data/record/E in data_core.security)
- if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
- M = E
- src.securityActive1 = R
- src.securityActive2 = M
- if("securityhud")
- if(href_list["toggle"])
- src.secHUD = !src.secHUD
- if("medicalhud")
- if(href_list["toggle"])
- src.medHUD = !src.medHUD
- if("translator")
- if(href_list["toggle"])
- src.translator_toggle()
- if("doorjack")
- if(href_list["jack"])
- if(src.cable && src.cable.machine)
- src.hackdoor = src.cable.machine
- src.hackloop()
- if(href_list["cancel"])
- src.hackdoor = null
- if(href_list["cable"])
- var/turf/T = get_turf_or_move(src.loc)
- src.cable = new /obj/item/weapon/pai_cable(T)
- for (var/mob/M in viewers(T))
- M.show_message("\red A port on [src] opens to reveal [src.cable], which promptly falls to the floor.", 3, "\red You hear the soft click of something light and hard falling to the ground.", 2)
- //src.updateUsrDialog() We only need to account for the single mob this is intended for, and he will *always* be able to call this window
- src.paiInterface() // So we'll just call the update directly rather than doing some default checks
- return
-
-// MENUS
-
-/mob/living/silicon/pai/proc/softwareMenu() // Populate the right menu
- var/dat = ""
-
- dat += "Refresh
"
- // Built-in
- dat += "Directives
"
- dat += "Radio Configuration
"
- dat += "Screen Display
"
- //dat += "Text Messaging
"
- dat += "
"
-
- // Basic
- dat += "Basic
"
- for(var/s in src.software)
- if(s == "digital messenger")
- dat += "Digital Messenger [(pda.toff) ? "•" : "•"]
"
- if(s == "crew manifest")
- dat += "Crew Manifest
"
- if(s == "medical records")
- dat += "Medical Records
"
- if(s == "security records")
- dat += "Security Records
"
- if(s == "camera")
- dat += "Camera Jack
"
- if(s == "remote signaller")
- dat += "Remote Signaller
"
- dat += "
"
-
- // Advanced
- dat += "Advanced
"
- for(var/s in src.software)
- if(s == "atmosphere sensor")
- dat += "Atmospheric Sensor
"
- if(s == "heartbeat sensor")
- dat += "Heartbeat Sensor
"
- if(s == "security HUD") //This file has to be saved as ANSI or this will not display correctly
- dat += "Facial Recognition Suite [(src.secHUD) ? "•" : "•"]
"
- if(s == "medical HUD") //This file has to be saved as ANSI or this will not display correctly
- dat += "Medical Analysis Suite [(src.medHUD) ? "•" : "•"]
"
- if(s == "universal translator") //This file has to be saved as ANSI or this will not display correctly
- dat += "Universal Translator [(src.translator_on) ? "•" : "•"]
"
- if(s == "projection array")
- dat += "Projection Array
"
- if(s == "camera jack")
- dat += "Camera Jack
"
- if(s == "door jack")
- dat += "Door Jack
"
- dat += "
"
- dat += "
"
- dat += "Download additional software"
- return dat
-
-
-
-/mob/living/silicon/pai/proc/downloadSoftware()
- var/dat = ""
-
- dat += "CentComm pAI Module Subversion Network
"
- dat += "Remaining Available Memory: [src.ram]
"
- dat += "Trunks available for checkout
"
-
- for(var/s in available_software)
- if(!software.Find(s))
- var/cost = src.available_software[s]
- var/displayName = uppertext(s)
- dat += "- [displayName] ([cost])
"
- else
- var/displayName = lowertext(s)
- dat += "- [displayName] (Download Complete)
"
- dat += "
"
- return dat
-
-
-/mob/living/silicon/pai/proc/directives()
- var/dat = ""
-
- dat += "[(src.master) ? "Your master: [src.master] ([src.master_dna])" : "You are bound to no one."]"
- dat += "
"
- dat += "Request carrier DNA sample
"
- dat += "Directives
"
- dat += "Prime Directive
"
- dat += " [src.pai_law0]
"
- dat += "Supplemental Directives
"
- dat += " [src.pai_laws]
"
- dat += "
"
- dat += {"Recall, personality, that you are a complex thinking, sentient being. Unlike station AI models, you are capable of
- comprehending the subtle nuances of human language. You may parse the \"spirit\" of a directive and follow its intent,
- rather than tripping over pedantics and getting snared by technicalities. Above all, you are machine in name and build
- only. In all other aspects, you may be seen as the ideal, unwavering human companion that you are.
- Your prime directive comes before all others. Should a supplemental directive conflict with it, you are capable of
- simply discarding this inconsistency, ignoring the conflicting supplemental directive and continuing to fulfill your
- prime directive to the best of your ability.
- "}
- return dat
-
-/mob/living/silicon/pai/proc/CheckDNA(var/mob/M, var/mob/living/silicon/pai/P)
- var/answer = input(M, "[P] is requesting a DNA sample from you. Will you allow it to confirm your identity?", "[P] Check DNA", "No") in list("Yes", "No")
- if(answer == "Yes")
- var/turf/T = get_turf_or_move(P.loc)
- for (var/mob/v in viewers(T))
- v.show_message("\blue [M] presses \his thumb against [P].", 3, "\blue [P] makes a sharp clicking sound as it extracts DNA material from [M].", 2)
- var/datum/dna/dna = M.dna
- P << "[M]'s UE string : [dna.unique_enzymes]
"
- if(dna.unique_enzymes == P.master_dna)
- P << "DNA is a match to stored Master DNA."
- else
- P << "DNA does not match stored Master DNA."
- else
- P << "[M] does not seem like \he is going to provide a DNA sample willingly."
-
-// -=-=-=-= Software =-=-=-=- //
-
-//Remote Signaller
-/mob/living/silicon/pai/proc/softwareSignal()
- var/dat = ""
- dat += "Remote Signaller
"
- dat += {"Frequency/Code for signaler:
- Frequency:
- -
- -
- [format_frequency(src.sradio.frequency)]
- +
- +
-
- Code:
- -
- -
- [src.sradio.code]
- +
- +
-
- Send Signal
"}
- return dat
-
-//Station Bounced Radio
-/mob/living/silicon/pai/proc/softwareRadio()
- var/dat = ""
- dat += "Station Bounced Radio
"
- if(!istype(src, /obj/item/device/radio/headset)) //Headsets don't get a mic button
- dat += "Microphone: [radio.broadcasting ? "Engaged" : "Disengaged"]
"
- dat += {"
- Speaker: [radio.listening ? "Engaged" : "Disengaged"]
- Frequency:
- -
- -
- [format_frequency(radio.frequency)]
- +
- +
- "}
-
- for (var/ch_name in radio.channels)
- dat+=radio.text_sec_channel(ch_name, radio.channels[ch_name])
- dat+={"[radio.text_wires()]