diff --git a/ByondPOST.dll b/ByondPOST.dll
index 93dff79d7f6..f94ea657653 100644
Binary files a/ByondPOST.dll and b/ByondPOST.dll differ
diff --git a/baystation12.dme b/baystation12.dme
index 18adf991bb3..91a9b169831 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -53,6 +53,7 @@
#include "code\_helpers\matrices.dm"
#include "code\_helpers\mobs.dm"
#include "code\_helpers\names.dm"
+#include "code\_helpers\overlay.dm"
#include "code\_helpers\sanitize_values.dm"
#include "code\_helpers\spawn_sync.dm"
#include "code\_helpers\text.dm"
@@ -172,6 +173,7 @@
#include "code\datums\mind.dm"
#include "code\datums\mixed.dm"
#include "code\datums\modules.dm"
+#include "code\datums\scheduled_task.dm"
#include "code\datums\server_greeting.dm"
#include "code\datums\sun.dm"
#include "code\datums\supplypacks.dm"
@@ -336,6 +338,7 @@
#include "code\game\gamemodes\setupgame.dm"
#include "code\game\gamemodes\calamity\calamity.dm"
#include "code\game\gamemodes\changeling\changeling.dm"
+#include "code\game\gamemodes\changeling\changeling_items.dm"
#include "code\game\gamemodes\changeling\changeling_powers.dm"
#include "code\game\gamemodes\changeling\modularchangling.dm"
#include "code\game\gamemodes\cult\cult.dm"
@@ -467,6 +470,8 @@
#include "code\game\machinery\wall_frames.dm"
#include "code\game\machinery\washing_machine.dm"
#include "code\game\machinery\wishgranter.dm"
+#include "code\game\machinery\abstract\abstract.dm"
+#include "code\game\machinery\abstract\intercom_listener.dm"
#include "code\game\machinery\atmoalter\area_atmos_computer.dm"
#include "code\game\machinery\atmoalter\canister.dm"
#include "code\game\machinery\atmoalter\meter.dm"
@@ -999,10 +1004,7 @@
#include "code\modules\alarm\fire_alarm.dm"
#include "code\modules\alarm\motion_alarm.dm"
#include "code\modules\alarm\power_alarm.dm"
-#include "code\modules\antag_contest\contest_defines.dm"
-#include "code\modules\antag_contest\contest_helpers.dm"
-#include "code\modules\antag_contest\contest_objective.dm"
-#include "code\modules\antag_contest\contest_verbs.dm"
+#include "code\modules\antag_contest\sol_items.dm"
#include "code\modules\assembly\assembly.dm"
#include "code\modules\assembly\bomb.dm"
#include "code\modules\assembly\helpers.dm"
diff --git a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm
index a032b747d96..05488c719af 100644
--- a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm
@@ -250,7 +250,7 @@
return 1
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user << "You begin to unfasten \the [src]..."
- if (do_after(user, 40))
+ if (do_after(user, 40, act_target = src))
user.visible_message( \
"\The [user] unfastens \the [src].", \
"You have unfastened \the [src].", \
diff --git a/code/ATMOSPHERICS/components/binary_devices/pump.dm b/code/ATMOSPHERICS/components/binary_devices/pump.dm
index 1832ea8784e..c6ef3e201da 100644
--- a/code/ATMOSPHERICS/components/binary_devices/pump.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/pump.dm
@@ -229,7 +229,7 @@ Thus, the two variables affect pump operation are set in New():
return 1
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user << "You begin to unfasten \the [src]..."
- if (do_after(user, 40))
+ if (do_after(user, 40, act_target = src))
user.visible_message( \
"\The [user] unfastens \the [src].", \
"You have unfastened \the [src].", \
diff --git a/code/ATMOSPHERICS/components/omni_devices/omni_base.dm b/code/ATMOSPHERICS/components/omni_devices/omni_base.dm
index ac7d88301af..b62a63da903 100644
--- a/code/ATMOSPHERICS/components/omni_devices/omni_base.dm
+++ b/code/ATMOSPHERICS/components/omni_devices/omni_base.dm
@@ -92,7 +92,7 @@
return 1
user << "You begin to unfasten \the [src]..."
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
- if(do_after(user, 40))
+ if(do_after(user, 40, act_target = src))
user.visible_message( \
"\The [user] unfastens \the [src].", \
"You have unfastened \the [src].", \
diff --git a/code/ATMOSPHERICS/components/portables_connector.dm b/code/ATMOSPHERICS/components/portables_connector.dm
index 4f6473fccf3..72eedd3d7f1 100644
--- a/code/ATMOSPHERICS/components/portables_connector.dm
+++ b/code/ATMOSPHERICS/components/portables_connector.dm
@@ -146,7 +146,7 @@
return 1
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user << "You begin to unfasten \the [src]..."
- if (do_after(user, 40))
+ if (do_after(user, 40, act_target = src))
user.visible_message( \
"\The [user] unfastens \the [src].", \
"You have unfastened \the [src].", \
diff --git a/code/ATMOSPHERICS/components/trinary_devices/filter.dm b/code/ATMOSPHERICS/components/trinary_devices/filter.dm
index e78d777cabc..3506c3a2a75 100755
--- a/code/ATMOSPHERICS/components/trinary_devices/filter.dm
+++ b/code/ATMOSPHERICS/components/trinary_devices/filter.dm
@@ -139,7 +139,7 @@
return 1
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user << "You begin to unfasten \the [src]..."
- if (do_after(user, 40))
+ if (do_after(user, 40, act_target = src))
user.visible_message( \
"\The [user] unfastens \the [src].", \
"You have unfastened \the [src].", \
diff --git a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm
index a163c122f01..48accdd6dbd 100644
--- a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm
+++ b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm
@@ -114,7 +114,7 @@
return 1
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user << "You begin to unfasten \the [src]..."
- if (do_after(user, 40))
+ if (do_after(user, 40, act_target = src))
user.visible_message( \
"\The [user] unfastens \the [src].", \
"You have unfastened \the [src].", \
diff --git a/code/ATMOSPHERICS/components/tvalve.dm b/code/ATMOSPHERICS/components/tvalve.dm
index f93970a93fd..c3592deb365 100644
--- a/code/ATMOSPHERICS/components/tvalve.dm
+++ b/code/ATMOSPHERICS/components/tvalve.dm
@@ -358,7 +358,7 @@
return 1
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user << "You begin to unfasten \the [src]..."
- if (do_after(user, 40))
+ if (do_after(user, 40, act_target = src))
user.visible_message( \
"\The [user] unfastens \the [src].", \
"You have unfastened \the [src].", \
diff --git a/code/ATMOSPHERICS/components/unary/heat_exchanger.dm b/code/ATMOSPHERICS/components/unary/heat_exchanger.dm
index 79e43a8e1c3..b6014ff34f5 100644
--- a/code/ATMOSPHERICS/components/unary/heat_exchanger.dm
+++ b/code/ATMOSPHERICS/components/unary/heat_exchanger.dm
@@ -80,7 +80,7 @@
return 1
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user << "You begin to unfasten \the [src]..."
- if (do_after(user, 40))
+ if (do_after(user, 40, act_target = src))
user.visible_message( \
"\The [user] unfastens \the [src].", \
"You have unfastened \the [src].", \
diff --git a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm
index 6e445bed48a..3cb91710571 100644
--- a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm
+++ b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm
@@ -275,7 +275,7 @@
return 1
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user << "You begin to unfasten \the [src]..."
- if (do_after(user, 40))
+ if (do_after(user, 40, act_target = src))
user.visible_message( \
"\The [user] unfastens \the [src].", \
"You have unfastened \the [src].", \
@@ -290,7 +290,7 @@
user << "\The [WT] must be turned on!"
else if (WT.remove_fuel(0,user))
user << "Now welding \the [src]."
- if(do_after(user, 20))
+ if(do_after(user, 20, act_target = src))
if(!src || !WT.isOn()) return
playsound(src.loc, 'sound/items/Welder2.ogg', 50, 1)
if(!welded)
diff --git a/code/ATMOSPHERICS/components/valve.dm b/code/ATMOSPHERICS/components/valve.dm
index 94d583c721c..121d58e186e 100644
--- a/code/ATMOSPHERICS/components/valve.dm
+++ b/code/ATMOSPHERICS/components/valve.dm
@@ -315,7 +315,7 @@
return 1
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user << "You begin to unfasten \the [src]..."
- if (do_after(user, 40))
+ if (do_after(user, 40, act_target = src))
user.visible_message( \
"\The [user] unfastens \the [src].", \
"You have unfastened \the [src].", \
diff --git a/code/ATMOSPHERICS/pipes.dm b/code/ATMOSPHERICS/pipes.dm
index d5656f75fc0..ee9d9ee0afb 100644
--- a/code/ATMOSPHERICS/pipes.dm
+++ b/code/ATMOSPHERICS/pipes.dm
@@ -93,7 +93,7 @@
return 1
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user << "You begin to unfasten \the [src]..."
- if (do_after(user, 40))
+ if (do_after(user, 40, act_target = src))
user.visible_message( \
"\The [user] unfastens \the [src].", \
"You have unfastened \the [src].", \
diff --git a/code/__defines/lighting.dm b/code/__defines/lighting.dm
index 815f4dc2d82..6b057fce8ba 100644
--- a/code/__defines/lighting.dm
+++ b/code/__defines/lighting.dm
@@ -73,15 +73,20 @@
#define LIGHT_NARROW 45
// Night lighting controller times
-// The time (in ticks based on worldtime2ticks()) that various actions trigger
-#define MORNING_LIGHT_RESET 252000 // 7am or 07:00 - lighting restores to normal in morning
-#define NIGHT_LIGHT_ACTIVE 648000 // 6pm or 18:00 - night lighting mode activates
+// The time (in hours based on worldtime2hours()) that various actions trigger
+#define MORNING_LIGHT_RESET 7 // 7am or 07:00 - lighting restores to normal in morning
+#define NIGHT_LIGHT_ACTIVE 18 // 6pm or 18:00 - night lighting mode activates
// Some brightness/range defines for objects.
#define L_WALLMOUNT_POWER 0.4
#define L_WALLMOUNT_RANGE 2
-#define L_WALLMOUNT_HI_POWER 2 // For red/delta alert on fire alarms.
+#define L_WALLMOUNT_HI_POWER 1 // For red/delta alert on fire alarms.
#define L_WALLMOUNT_HI_RANGE 4
+// This controls by how much console sprites are dimmed before being overlayed.
+#define HOLOSCREEN_ADDITION_FACTOR 1
+#define HOLOSCREEN_MULTIPLICATION_FACTOR 0.5
+#define HOLOSCREEN_ADDITION_OPACITY 0.8
+#define HOLOSCREEN_MULTIPLICATION_OPACITY 1
// Just so we can avoid unneeded proc calls when profiling is disabled.
#define L_PROF(O,T) if (lighting_profiling) {lprof_write(O,T);}
diff --git a/code/__defines/machinery.dm b/code/__defines/machinery.dm
index ab74ab7ddfe..9758cfdef84 100644
--- a/code/__defines/machinery.dm
+++ b/code/__defines/machinery.dm
@@ -105,3 +105,8 @@ var/list/restricted_camera_networks = list(NETWORK_ERT,NETWORK_MERCENARY,"Secret
// If this is returned from a machine's process() proc, the machine will stop processing but
// will continue to have power calculations done.
#define M_NO_PROCESS 27
+
+// This controls how much power the AME generates per unit of fuel.
+// Assuming 100% efficency, use this equation to figure out power output.
+// power_generated = (fuel**2) * AM_POWER_FACTOR
+#define AM_POWER_FACTOR 50000
diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm
index d20cbfd7eb1..075bdd366fa 100644
--- a/code/__defines/misc.dm
+++ b/code/__defines/misc.dm
@@ -49,7 +49,8 @@
#define CHAT_NOICONS 0x8000
#define PARALLAX_SPACE 0x1
-#define PARALLAX_DUST 0x2
+#define PARALLAX_DUST 0x2
+#define PROGRESS_BARS 0x4
#define TOGGLES_DEFAULT (SOUND_ADMINHELP|SOUND_MIDI|SOUND_AMBIENCE|SOUND_LOBBY|CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_ATTACKLOGS|CHAT_LOOC)
@@ -286,6 +287,9 @@
#define get_turf(A) (get_step(A, 0))
#define QDELETED(TARGET) (!TARGET || TARGET.gcDestroyed)
+#define QDEL_NULL(item) qdel(item); item = null
+// Shim until addtimer is merged or I figure out if it is safe to use scheduler for this.
+#define QDEL_IN(OBJ, TIME) spawn(TIME) qdel(OBJ)
//Recipe type defines. Used to determine what machine makes them
#define MICROWAVE 0x1
diff --git a/code/__defines/process_scheduler.dm b/code/__defines/process_scheduler.dm
index 3db5980b7c1..d2dfe2505d6 100644
--- a/code/__defines/process_scheduler.dm
+++ b/code/__defines/process_scheduler.dm
@@ -30,3 +30,5 @@
last_slept = TimeOfHour; \
tick_start = world.tick_usage; \
}
+
+#define PSCHED_CHECK_TICK (world.tick_usage > 100 || (world.tick_usage - tick_start) > tick_allowance)
diff --git a/code/_helpers/overlay.dm b/code/_helpers/overlay.dm
new file mode 100644
index 00000000000..3ee93ccaf52
--- /dev/null
+++ b/code/_helpers/overlay.dm
@@ -0,0 +1,33 @@
+// Factor/Opacity values are defined in __defines\lighting.dm
+
+/proc/holographic_overlay(obj/target, icon, icon_state)
+ var/image/multiply = make_screen_overlay(icon, icon_state)
+ multiply.blend_mode = BLEND_MULTIPLY
+ multiply.color = list(
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ HOLOSCREEN_MULTIPLICATION_FACTOR, HOLOSCREEN_MULTIPLICATION_FACTOR, HOLOSCREEN_MULTIPLICATION_FACTOR, HOLOSCREEN_MULTIPLICATION_OPACITY
+ )
+ target.overlays += multiply
+ var/image/overlay = make_screen_overlay(icon, icon_state)
+ overlay.blend_mode = BLEND_ADD
+ overlay.color = list(
+ HOLOSCREEN_ADDITION_FACTOR, 0, 0, 0,
+ 0, HOLOSCREEN_ADDITION_FACTOR, 0, 0,
+ 0, 0, HOLOSCREEN_ADDITION_FACTOR, 0,
+ 0, 0, 0, HOLOSCREEN_ADDITION_OPACITY
+ )
+ target.overlays += overlay
+
+/proc/make_screen_overlay(icon, icon_state, brightness_factor = null)
+ var/image/overlay = image(icon, icon_state)
+ overlay.layer = LIGHTING_LAYER + 0.1
+ if (brightness_factor)
+ overlay.color = list(
+ brightness_factor, 0, 0, 0,
+ 0, brightness_factor, 0, 0,
+ 0, 0, brightness_factor, 0,
+ 0, 0, 0, 1
+ )
+ return overlay
diff --git a/code/_helpers/time.dm b/code/_helpers/time.dm
index 689e191fb57..ef732ebd0f4 100644
--- a/code/_helpers/time.dm
+++ b/code/_helpers/time.dm
@@ -10,10 +10,12 @@ proc/worldtime2text(time = world.time, timeshift = 1)
if(!roundstart_hour) roundstart_hour = rand(0, 23)
return timeshift ? time2text(time+(36000*roundstart_hour), "hh:mm") : time2text(time, "hh:mm")
-proc/worldtime2ticks(time = world.time)
- if(!roundstart_hour)
+/proc/worldtime2hours()
+ if (!roundstart_hour)
worldtime2text()
- return ((roundstart_hour * 60 MINUTES) + time) % TICKS_IN_DAY
+ . = (world.timeofday / (60 MINUTES)) + roundstart_hour
+ if (. > 24)
+ . -= 24
proc/worlddate2text()
return num2text(game_year) + "-" + time2text(world.timeofday, "MM-DD")
diff --git a/code/_helpers/type2type.dm b/code/_helpers/type2type.dm
index 232f696a719..39c33cadfce 100644
--- a/code/_helpers/type2type.dm
+++ b/code/_helpers/type2type.dm
@@ -222,7 +222,7 @@ proc/tg_list2text(list/list, glue=",")
// Converts an angle (degrees) into an ss13 direction
/proc/angle2dir(var/degree)
- degree = (degree + 22.5) % 365 // 22.5 = 45 / 2
+ degree = (degree + 22.5) % 360 // 22.5 = 45 / 2
if (degree < 45) return NORTH
if (degree < 90) return NORTHEAST
if (degree < 135) return EAST
diff --git a/code/_helpers/unsorted.dm b/code/_helpers/unsorted.dm
index c91a9b0a031..294ad172268 100644
--- a/code/_helpers/unsorted.dm
+++ b/code/_helpers/unsorted.dm
@@ -646,45 +646,109 @@ proc/GaussRandRound(var/sigma,var/roundto)
else return get_step(ref, base_dir)
-/proc/do_mob(var/mob/user, var/mob/target, var/delay = 30, var/numticks = 5, var/needhand = 1) //This is quite an ugly solution but i refuse to use the old request system.
- if(!user || !target) return 0
- if(numticks == 0) return 0
-
- var/delayfraction = round(delay/numticks)
- var/original_user_loc = user.loc
- var/original_target_loc = target.loc
+/proc/do_mob(mob/user , mob/target, delay = 30, numticks = 10, needhand = TRUE, display_progress = TRUE) //This is quite an ugly solution but i refuse to use the old request system.
+ if(!user || !target)
+ return 0
+ var/user_loc = user.loc
+ var/target_loc = target.loc
var/holding = user.get_active_hand()
-
- for(var/i = 0, i= config.nl_start)
+ activate()
+ else
+ deactivate()
/datum/controller/process/night_lighting/doWork()
if (manual_override) // don't automatically change lighting if it was manually changed in-game
return
- switch (worldtime2ticks())
- if (0 to config.nl_finish)
- if (isactive)
- command_announcement.Announce("Good morning. The time is [worldtime2text()]. \n\nThe automated systems aboard the [station_name()] will now return the public hallway lighting levels to normal.", "Automated Lighting System", new_sound = 'sound/misc/bosuns_whistle.ogg')
- deactivate()
-
- if (config.nl_start to TICKS_IN_DAY)
- if (!isactive)
- command_announcement.Announce("Good evening. The time is [worldtime2text()]. \n\nThe automated systems aboard the [station_name()] will now dim lighting in the public hallways in order to accommodate the circadian rhythm of some species.", "Automated Lighting System", new_sound = 'sound/misc/bosuns_whistle.ogg')
- activate()
-
- else
- if (isactive)
- deactivate()
+ var/time = worldtime2hours()
+ if (time <= config.nl_finish || time >= config.nl_start)
+ if (!isactive)
+ command_announcement.Announce("Good evening. The time is [worldtime2text()]. \n\nThe automated systems aboard the [station_name()] will now dim lighting in the public hallways in order to accommodate the circadian rhythm of some species.", "Automated Lighting System", new_sound = 'sound/misc/bosuns_whistle.ogg')
+ activate()
+ else
+ if (isactive)
+ command_announcement.Announce("Good morning. The time is [worldtime2text()]. \n\nThe automated systems aboard the [station_name()] will now return the public hallway lighting levels to normal.", "Automated Lighting System", new_sound = 'sound/misc/bosuns_whistle.ogg')
+ deactivate()
// 'whitelisted' areas are areas that have nightmode explicitly enabled
diff --git a/code/controllers/Processes/scheduler.dm b/code/controllers/Processes/scheduler.dm
index f2729d5d3aa..35146686fcc 100644
--- a/code/controllers/Processes/scheduler.dm
+++ b/code/controllers/Processes/scheduler.dm
@@ -4,54 +4,141 @@
* Scheduler *
************/
/datum/controller/process/scheduler
- var/list/scheduled_tasks
- var/tick_completed = TRUE
- var/list/queued_tasks
+ var/list/datum/scheduled_task/tasks = list()
+ var/datum/scheduled_task/head
/datum/controller/process/scheduler/setup()
name = "scheduler"
- schedule_interval = 2 SECONDS
- scheduled_tasks = list()
+ schedule_interval = 2
scheduler = src
/datum/controller/process/scheduler/doWork()
- if (tick_completed)
- queued_tasks = scheduled_tasks.Copy()
- tick_completed = FALSE
+ while (head && !PSCHED_CHECK_TICK)
+ if (head.destroyed)
+ head.kill()
+ head = head.next
+ tasks -= head
+ continue
+ if (head.trigger_time >= world.time)
+ return // Nothing after this will be ready to fire.
- while (queued_tasks.len)
- var/datum/scheduled_task/task = queued_tasks[queued_tasks.len]
- queued_tasks.len--
+ // This one's ready to fire, process it.
+ var/datum/scheduled_task/task = head
+ head = task.next
+ task.pre_process()
+ task.process()
+ task.post_process()
+ if (task.destroyed) // post_process probably destroyed it.
+ tasks -= task
+ task.kill()
+/datum/controller/process/scheduler/proc/queue(datum/scheduled_task/task)
+ if (!task || !task.trigger_time)
+ warning("scheduler: Invalid task queued! Ignoring.")
+ return
+ // Reset this in-case we're doing a rebuild.
+ task.next = null
+ if (!head && !tasks.len)
+ head = task
+ tasks += task
+ return
+
+ if (!head) // Head's missing but we still have tasks, rebuild.
+ tasks += task
+ rebuild_queue()
+ return
+
+ var/datum/scheduled_task/curr = head
+ while (curr.next && curr.trigger_time < task.trigger_time)
+ curr = curr.next
+
+ if (!curr.next)
+ // We're at the end of the queue, just append.
+ curr.next = task
+ tasks += task
+ return
+
+ // Inserting midway into the list.
+ var/old_next = curr.next
+ curr.next = task
+ task.next = old_next
+ tasks += task
+
+// Rebuilds the queue linked-list, removing invalid or destroyed entries.
+/datum/controller/process/scheduler/proc/rebuild_queue()
+ log_debug("scheduler: Rebuilding queue.")
+ var/list/old_tasks = tasks
+ tasks = list()
+ if (!old_tasks.len)
+ log_debug("scheduler: rebuild was called on empty queue! Aborting.")
+ return
+
+ // Find the head.
+ for (var/thing in old_tasks)
+ var/datum/scheduled_task/task = thing
if (QDELETED(task))
- scheduled_tasks -= task
+ old_tasks -= task
continue
- if (world.time > task.trigger_time)
- unschedule(task)
- task.pre_process()
- task.process()
- task.post_process()
- F_SCHECK
+ if (task.destroyed)
+ old_tasks -= task
+ task.kill()
+ continue
- tick_completed = TRUE
+ if (!head || task.trigger_time < head.trigger_time)
+ head = task
+
+ if (!head)
+ log_debug("scheduler: unable to find head! Purging task queue.")
+ for (var/thing in old_tasks)
+ var/datum/scheduled_task/task = thing
+ if (QDELETED(task))
+ continue
+
+ task.kill()
+
+ head = null
+ return
+
+ // Don't queue the head.
+ tasks += head
+ old_tasks -= head
+
+ // Now rebuild the queue.
+ for (var/thing in old_tasks)
+ var/datum/scheduled_task/task = thing
+
+ queue(task)
+
+ log_debug("scheduler: Queue diff is [old_tasks.len - tasks.len].")
/datum/controller/process/scheduler/statProcess()
..()
- stat(null, "[scheduled_tasks.len] tasks, [queued_tasks.len] queued")
+ stat(null, "[tasks.len] task\s")
/datum/controller/process/scheduler/proc/schedule(var/datum/scheduled_task/st)
- scheduled_tasks += st
- destroyed_event.register(st, src, /datum/controller/process/scheduler/proc/unschedule)
+ queue(st)
/datum/controller/process/scheduler/proc/unschedule(var/datum/scheduled_task/st)
- if(st in scheduled_tasks)
- scheduled_tasks -= st
- destroyed_event.unregister(st, src)
+ st.destroyed = TRUE
/**********
* Helpers *
**********/
+/proc/schedule(source, the_proc, time, ...)
+ if (time < 0)
+ return
+ time += world.time
+ var/list/the_args
+ if (length(args) > 3)
+ the_args = args.Copy(4)
+ else
+ the_args = list()
+ if (source)
+ return schedule_task_with_source(time, the_proc, the_args)
+ else
+ return schedule_task(time, the_proc, the_args)
+
/proc/schedule_task_in(var/in_time, var/procedure, var/list/arguments = list())
return schedule_task(world.time + in_time, procedure, arguments)
@@ -77,68 +164,3 @@
var/datum/scheduled_task/st = new/datum/scheduled_task/source(trigger_time, source, procedure, arguments, /proc/repeat_scheduled_task, list(repeat_interval))
scheduler.schedule(st)
return st
-
-/*************
-* Task Datum *
-*************/
-/datum/scheduled_task
- var/trigger_time
- var/procedure
- var/list/arguments
- var/task_after_process
- var/list/task_after_process_args
-
-/datum/scheduled_task/New(var/trigger_time, var/procedure, var/list/arguments, var/proc/task_after_process, var/list/task_after_process_args)
- ..()
- src.trigger_time = trigger_time
- src.procedure = procedure
- src.arguments = arguments ? arguments : list()
- src.task_after_process = task_after_process ? task_after_process : /proc/destroy_scheduled_task
- src.task_after_process_args = istype(task_after_process_args) ? task_after_process_args : list()
- task_after_process_args += src
-
-/datum/scheduled_task/Destroy()
- procedure = null
- arguments.Cut()
- task_after_process = null
- task_after_process_args.Cut()
- return ..()
-
-/datum/scheduled_task/proc/pre_process()
- task_triggered_event.raise_event(list(src))
-
-/datum/scheduled_task/proc/process()
- if(procedure)
- call(procedure)(arglist(arguments))
-
-/datum/scheduled_task/proc/post_process()
- call(task_after_process)(arglist(task_after_process_args))
-
-// Resets the trigger time, has no effect if the task has already triggered
-/datum/scheduled_task/proc/trigger_task_in(var/trigger_in)
- src.trigger_time = world.time + trigger_in
-
-/datum/scheduled_task/source
- var/datum/source
-
-/datum/scheduled_task/source/New(var/trigger_time, var/datum/source, var/procedure, var/list/arguments, var/proc/task_after_process, var/list/task_after_process_args)
- src.source = source
- destroyed_event.register(src.source, src, /datum/scheduled_task/source/proc/source_destroyed)
- ..(trigger_time, procedure, arguments, task_after_process, task_after_process_args)
-
-/datum/scheduled_task/source/Destroy()
- source = null
- return ..()
-
-/datum/scheduled_task/source/process()
- call(source, procedure)(arglist(arguments))
-
-/datum/scheduled_task/source/proc/source_destroyed()
- qdel(src)
-
-/proc/destroy_scheduled_task(var/datum/scheduled_task/st)
- qdel(st)
-
-/proc/repeat_scheduled_task(var/trigger_delay, var/datum/scheduled_task/st)
- st.trigger_time = world.time + trigger_delay
- scheduler.schedule(st)
diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm
index 2e22c1d9b12..8cfb79a34ab 100644
--- a/code/controllers/configuration.dm
+++ b/code/controllers/configuration.dm
@@ -177,8 +177,8 @@ var/list/gamemode_cache = list()
var/ghost_interaction = 0
var/night_lighting = 0
- var/nl_start = 19 * TICKS_IN_HOUR
- var/nl_finish = 8 * TICKS_IN_HOUR
+ var/nl_start = 19
+ var/nl_finish = 8
var/comms_password = ""
@@ -187,6 +187,7 @@ var/list/gamemode_cache = list()
var/use_discord_bot = 0
var/discord_bot_host = "localhost"
var/discord_bot_port = 0
+ var/use_discord_pins = 0
var/python_path = "python" //Path to the python executable. Defaults to "python" on windows and "/usr/bin/env python2" on unix
var/use_lib_nudge = 0 //Use the C library nudge instead of the python nudge.
var/use_overmap = 0
@@ -629,10 +630,10 @@ var/list/gamemode_cache = list()
config.night_lighting = 1
if("nl_start_hour")
- config.nl_start = text2num(value) * TICKS_IN_HOUR
+ config.nl_start = text2num(value)
if("nl_finish_hour")
- config.nl_finish = text2num(value) * TICKS_IN_HOUR
+ config.nl_finish = text2num(value)
if("disable_player_mice")
config.disable_player_mice = 1
@@ -652,6 +653,9 @@ var/list/gamemode_cache = list()
if("discord_bot_port")
config.discord_bot_port = value
+ if("use_discord_pins")
+ config.use_discord_pins = 1
+
if("python_path")
if(value)
config.python_path = value
@@ -878,6 +882,8 @@ var/list/gamemode_cache = list()
discord_bot.active = 1
if ("robust_debug")
discord_bot.robust_debug = 1
+ if ("subscriber")
+ discord_bot.subscriber_role = value
else
log_misc("Unknown setting in discord configuration: '[name]'")
diff --git a/code/controllers/voting.dm b/code/controllers/voting.dm
index 694f64e0f21..2b8c10ac6e1 100644
--- a/code/controllers/voting.dm
+++ b/code/controllers/voting.dm
@@ -194,8 +194,16 @@ datum/controller/vote
proc/submit_vote(var/ckey, var/vote)
if(mode)
- if(config.vote_no_dead && usr.stat == DEAD && !usr.client.holder)
- return 0
+ if (mode == "crew_transfer")
+ if(config.vote_no_dead && usr && !usr.client.holder)
+ if (isnewplayer(usr))
+ usr << "You must be playing or have been playing to start a vote."
+ return 0
+ else if (isobserver(usr))
+ var/mob/dead/observer/O = usr
+ if (O.started_as_observer)
+ usr << "You must be playing or have been playing to start a vote."
+ return 0
if(vote && vote >= 1 && vote <= choices.len)
if(current_votes[ckey])
choices[choices[current_votes[ckey]]]--
@@ -211,6 +219,16 @@ datum/controller/vote
// Transfer votes are their own little special snowflake
var/next_allowed_time = 0
if (vote_type == "crew_transfer")
+ if (config.vote_no_dead && !usr.client.holder)
+ if (isnewplayer(usr))
+ usr << "You must be playing or have been playing to start a vote."
+ return 0
+ else if (isobserver(usr))
+ var/mob/dead/observer/O = usr
+ if (O.started_as_observer)
+ usr << "You must be playing or have been playing to start a vote."
+ return 0
+
if (last_transfer_vote)
next_allowed_time = (last_transfer_vote + config.vote_delay)
else
@@ -275,16 +293,16 @@ datum/controller/vote
log_vote(text)
world << "[text]\nType vote or click here to place your votes.\nYou have [config.vote_period/10] seconds to vote."
- for(var/client/C in clients)
+ for(var/cc in clients)
+ var/client/C = cc
if(C.prefs.asfx_togs & ASFX_VOTE) //Personal mute
- C << sound('sound/effects/vote.ogg')
- switch(vote_type)
- if("crew_transfer")
- world << sound('sound/ambience/alarm4.ogg', repeat = 0, wait = 0, volume = 50, channel = 3)
- if("gamemode")
- world << sound('sound/ambience/alarm4.ogg', repeat = 0, wait = 0, volume = 50, channel = 3)
- if("custom")
- world << sound('sound/ambience/alarm4.ogg', repeat = 0, wait = 0, volume = 50, channel = 3)
+ switch(vote_type)
+ if("crew_transfer")
+ C << sound('sound/effects/vote.ogg', repeat = 0, wait = 0, volume = 50, channel = 3)
+ if("gamemode")
+ C << sound('sound/ambience/alarm4.ogg', repeat = 0, wait = 0, volume = 50, channel = 3)
+ if("custom")
+ C << sound('sound/ambience/alarm4.ogg', repeat = 0, wait = 0, volume = 50, channel = 3)
if(mode == "gamemode" && round_progressing)
round_progressing = 0
world << "Round start has been delayed."
diff --git a/code/datums/discord_bot.dm b/code/datums/discord_bot.dm
index 1238e3e93e4..1f74fee83b6 100644
--- a/code/datums/discord_bot.dm
+++ b/code/datums/discord_bot.dm
@@ -1,6 +1,13 @@
#define CHAN_ADMIN "channel_admin"
#define CHAN_CCIAA "channel_cciaa"
#define CHAN_ANNOUNCE "channel_announce"
+#define CHAN_INVITE "channel_invite"
+
+#define SEND_OK 0
+#define SEND_TIMEOUT 1
+#define ERROR_PROC 2
+#define ERROR_CURL 3
+#define ERROR_HTTP 4
var/datum/discord_bot/discord_bot = null
@@ -15,21 +22,34 @@ var/datum/discord_bot/discord_bot = null
discord_bot.update_channels()
+ if (config.use_discord_pins && server_greeting)
+ server_greeting.update_pins()
+
return 1
/datum/discord_bot
- var/list/channels = list()
+ var/list/channels_to_group = list() // Group flag -> list of channel datums map.
+ var/list/channels = list() // Channel ID -> channel datum map. Will ensure that only one datum per channel ID exists.
+
+ var/datum/discord_channel/invite = null // The channel datum where the ingame Join Channel button will link to.
var/active = 0
var/auth_token = ""
+ var/subscriber_role = ""
var/robust_debug = 0
// Lazy man's rate limiting vars
- var/rate_limited_since = 0
- var/queue_being_pushed = 0
+ var/datum/scheduled_task/push_task
var/list/queue = list()
+/*
+ * Proc update_channels
+ * Used to load channels from the database and construct them with the discord API.
+ * Wipes all current channels and channel maps.
+ *
+ * @return num - Error code. 0 upon success.
+ */
/datum/discord_bot/proc/update_channels()
if (!active)
return 1
@@ -38,27 +58,56 @@ var/datum/discord_bot/discord_bot = null
log_debug("BOREALIS: Failed to update channels due to missing database.")
return 2
- channels = list()
+ // Reset the channel lists.
+ channels_to_group.Cut()
+ channels.Cut()
- var/DBQuery/channel_query = dbcon.NewQuery("SELECT channel_group, channel_id FROM discord_channels")
+ var/DBQuery/channel_query = dbcon.NewQuery("SELECT channel_group, channel_id, pin_flag, server_id FROM discord_channels")
channel_query.Execute()
- var/list/A
while (channel_query.NextRow())
- if (isnull(channels[channel_query.item[1]]))
- channels[channel_query.item[1]] = list()
+ // Create the channel map.
+ if (isnull(channels_to_group[channel_query.item[1]]))
+ channels_to_group[channel_query.item[1]] = list()
- A = channels[channel_query.item[1]]
- A += channel_query.item[2]
+ var/datum/discord_channel/B = channels[channel_query.item[2]]
+
+ // We don't have this channel datum yet.
+ if (isnull(B))
+ B = new(channel_query.item[2], channel_query.item[4], text2num(channel_query.item[3]))
+
+ if (!B)
+ log_debug("BOREALIS: Bad channel data during update channels. [jointext(channel_query.item, ", ")].")
+ continue
+
+ channels[channel_query.item[2]] = B
+
+ if (text2num(channel_query.item[3]))
+ B.pin_flag |= text2num(channel_query.item[3])
+
+ // Add the channel to the required lists.
+ channels_to_group[channel_query.item[1]] += B
+
+ if (!isnull(channels_to_group[CHAN_INVITE]))
+ invite = channels_to_group[CHAN_INVITE][1]
+ else if (robust_debug)
+ log_debug("BOREALIS: No invite channel designated.")
log_debug("BOREALIS: Channels updated successfully.")
return 0
+/*
+ * Proc send_message
+ * Used to send a message to a specific channel group.
+ *
+ * @param text channel_group - The name of the channel group which to target.
+ * @param text message - The message to send.
+ */
/datum/discord_bot/proc/send_message(var/channel_group, var/message)
if (!active || !auth_token)
return
- if (!channel_group || !channels.len || isnull(channels[channel_group]))
+ if (!channel_group || !channels.len || isnull(channels_to_group[channel_group]))
return
if (!message)
@@ -70,18 +119,18 @@ var/datum/discord_bot/discord_bot = null
// Let's run it through the proper JSON encoder, just in case of special characters.
message = json_encode(list("content" = message))
- var/list/A = channels[channel_group]
+ var/list/A = channels_to_group[channel_group]
var/list/sent = list()
- for (var/channel in A)
- if (send_post_request("https://discordapp.com/api/channels/[channel]/messages", message, "Authorization: Bot [auth_token]", "Content-Type: application/json") == 429)
+ for (var/B in A)
+ var/datum/discord_channel/channel = B
+ if (channel.send_message_to(auth_token, message) == SEND_TIMEOUT)
// Whoopsies, rate limited.
// Set up the queue.
- rate_limited_since = world.time
- queue.Add(list(message, A - sent))
+ queue.Add(list(list(message, A - sent)))
// Schedule a push.
- spawn (100)
- push_queue()
+ if (!push_task)
+ push_task = schedule_task_with_source_in(10 SECONDS, src, /datum/discord_bot/proc/push_queue)
// And exit.
return
@@ -89,43 +138,87 @@ var/datum/discord_bot/discord_bot = null
sent += channel
if (robust_debug)
- log_debug("BOEALIS: Message sent to [channel_group]. JSON body: '[message]'")
+ log_debug("BOREALIS: Message sent to [channel_group]. JSON body: '[message]'")
+/*
+ * Proc retreive_pins
+ * Used to fetch a list of all pins from the designated channels.
+ *
+ * @return list - A multilayered list of flags associated with pins. Structure looks like this:
+ * list("pin_flag" = list(list("author" = author name, "content" = content),
+ * list("author" = author name, "content" = content)))
+ */
+/datum/discord_bot/proc/retreive_pins()
+ if (!active || !auth_token)
+ return list()
+
+ if (!channels.len || isnull(channels_to_group["channel_pins"]))
+ testing("No group.")
+ return list()
+
+ var/list/output = list()
+
+ for (var/A in channels_to_group["channel_pins"])
+ var/datum/discord_channel/channel = A
+ if (isnull(output["[channel.pin_flag]"]))
+ output["[channel.pin_flag]"] = list()
+
+ output["[channel.pin_flag]"] += channel.get_pins(auth_token)
+
+ return output
+
+/*
+ * Proc retreive_invite
+ * Used to retreive the invite to the invite channel.
+ * One will be created if none exist.
+ *
+ * @return text - The invite URL to the designated invite channel.
+ */
+/datum/discord_bot/proc/retreive_invite()
+ if (!active || !auth_token)
+ return ""
+
+ if (!invite)
+ return ""
+
+ var/res = invite.get_invite(auth_token)
+ return isnum(res) ? "" : res
+
+/*
+ * Proc send_to_admin
+ * Forwards a message to the admin channels.
+ */
/datum/discord_bot/proc/send_to_admins(message)
send_message(CHAN_ADMIN, message)
+/*
+ * Proc send_to_cciaa
+ * Forwards a message to the CCIAA channels.
+ */
/datum/discord_bot/proc/send_to_cciaa(message)
send_message(CHAN_CCIAA, message)
-/datum/discord_bot/proc/send_to_announce(message)
+/*
+ * Proc send_to_announce
+ * Forwards a message to the announcements channels.
+ */
+/datum/discord_bot/proc/send_to_announce(message, prepend_role = 0)
+ if (prepend_role && subscriber_role)
+ message = "<@&[subscriber_role]> " + message
send_message(CHAN_ANNOUNCE, message)
+/*
+ * Proc push_queue
+ * Handles the queue pushing for the bot. If there is no need to reschedule (all messages get successfully
+ * pushed), then it deletes push_task and sets it back to null. Otherwise, it simply reschedules it.
+ */
/datum/discord_bot/proc/push_queue()
// What facking queue.
- if (!queue.len)
+ if (!queue || !queue.len)
if (robust_debug)
log_debug("BOREALIS: Attempted to push a null length queue.")
- if (queue_being_pushed)
- queue_being_pushed = 0
return
- if (queue_being_pushed)
- if (robust_debug)
- log_debug("BOREALIS: Attempted to initialize a second queue driver.")
- return
-
- if ((world.time - rate_limited_since) < 100)
- // Something broke the limit again. Ideally, this wouldn't happen. But sure.
- // Use a longer timeout, just in case.
- spawn (200)
- push_queue()
-
- queue_being_pushed = 0
- return
-
- // Async process lock var. No touchy.
- queue_being_pushed = 1
-
// A[1] - message body.
// A[2] - list of channels to send to.
var/message
@@ -134,22 +227,216 @@ var/datum/discord_bot/discord_bot = null
message = A[1]
destinations = A[2]
- for (var/channel in destinations)
- if (send_post_request("https://discordapp.com/api/channels/[channel]/messages", message, "Authorization: Bot [auth_token]", "Content-Type: application/json") == 429)
- // Limited again. Reschedule.
- rate_limited_since = world.time
- spawn (100)
- push_queue()
+ for (var/B in destinations)
+ var/datum/discord_channel/channel = B
+ if (channel.send_message_to(auth_token, message) == SEND_TIMEOUT)
+ // Tasks nuke themselves after use. So just make a new one! What could possibly go wrong!
+ push_task = schedule_task_with_source_in(10 SECONDS, src, /datum/discord_bot/proc/push_queue)
- queue_being_pushed = 0
return
else
destinations.Remove(channel)
queue.Remove(A)
- queue_being_pushed = 0
+// A holder class for channels.
+/datum/discord_channel
+ var/id = ""
+ var/server_id = ""
+ var/pin_flag = 0
+ var/invite_url = ""
+
+/*
+ * Constructor
+ *
+ * @param text _id - the discord API id of the channel, as a string.
+ * @param text _sid - the discord API server id for the channel, as a string.
+ * @param num _pin - the bitflags of admin permissions which have access to the pins from this channel.
+ */
+/datum/discord_channel/New(var/_id, var/_sid, var/_pin)
+ id = _id
+ server_id = _sid
+
+ if (_pin)
+ pin_flag = _pin
+
+/*
+ * Proc send_message_to
+ * Sends a message to the channel.
+ *
+ * @param text token - the authorization token to be used for the requests.
+ * @param text message - the sanitized message content to be sent.
+ * @return num - a specific return code for the discord_bot to handle.
+ */
+/datum/discord_channel/proc/send_message_to(var/token, var/message)
+ if (!token || !message)
+ return ERROR_PROC
+
+ var/res = send_post_request("https://discordapp.com/api/channels/[id]/messages", message, "Authorization: Bot [token]", "Content-Type: application/json")
+
+ switch (res)
+ if (-1)
+ return ERROR_PROC
+
+ if (200)
+ return SEND_OK
+
+ if (429)
+ return SEND_TIMEOUT
+
+ if (0 to 90)
+ log_debug("BOREALIS: cURL error while forwarding message to Discord API: [res]. Message body: [message].")
+ return ERROR_CURL
+
+ else
+ log_debug("BOREALIS: HTTP error while forwarding message to Discord API: [res]. Channel: [id]. Message body: [message].")
+ return ERROR_HTTP
+
+/*
+ * Proc get_pins
+ * Retreives a list of pinned messages from the channel.
+ *
+ * @param text token - the authorization token to be used for the requests.
+ * @return mixed - 2d array of content upon success, in format: list(list("author" = text, "content" = text)).
+ * Num upon failure.
+ */
+/datum/discord_channel/proc/get_pins(var/token)
+ var/res = send_get_request("https://discordapp.com/api/channels/[id]/pins", "Authorization: Bot [token]")
+
+ // Is a number, so an error code.
+ if (isnum(res))
+ switch (res)
+ if (-1)
+ return ERROR_PROC
+
+ if (0 to 90)
+ log_debug("BOREALIS: cURL error while fetching pins from the Discord API: [res].")
+ return ERROR_CURL
+
+ if (100 to 600)
+ log_debug("BOREALIS: HTTP error while fetching pins from the Discord API: [res].")
+ return ERROR_HTTP
+
+ else
+ log_debug("BOREALIS: Unknown response code while fetching pins from the Discord API: [res].")
+ return ERROR_PROC
+ else
+ var/list/A = res
+ var/list/pinned_messages = list()
+
+ // Begin processing the list structure delivered back to us from send_get_request.
+ for (var/list/B in A)
+ var/content = B["content"]
+
+ // We have mentions to take care of.
+ if (!isnull(B["mentions"]))
+ var/list/mentions = B["mentions"]
+
+ for (var/list/C in mentions)
+ content = replacetextEx(content, "<@[C["id"]]>", C["username"])
+
+ // Role mentions are up next.
+ if (!isnull(B["mention_roles"]))
+ var/list/mentions = B["mention_roles"]
+
+ for (var/C in mentions)
+ content = replacetextEx(content, "<@&[C]>", "@SomeRole")
+
+ pinned_messages += list(list("author" = B["author"]["username"], "content" = content))
+
+ return pinned_messages
+
+/*
+ * Proc get_invite
+ * Retreives (or creates if none found) an invite URL to the specific channel.
+ *
+ * @param text token - the authorization token to be used for the requests.
+ * @return mixed - text upon success, the link to the invite; num upon failure.
+ */
+/datum/discord_channel/proc/get_invite(var/token)
+ if (invite_url)
+ return invite_url
+
+ var/res = send_get_request("https://discordapp.com/api/channels/[id]/invites", "Authorization: Bot [token]")
+
+ // Is a number, so an error code.
+ if (isnum(res))
+ switch (res)
+ if (-1)
+ return ERROR_PROC
+
+ if (0 to 90)
+ log_debug("BOREALIS: cURL error while fetching pins from the Discord API: [res].")
+ return ERROR_CURL
+
+ if (100 to 600)
+ log_debug("BOREALIS: HTTP error while fetching pins from the Discord API: [res].")
+ return ERROR_HTTP
+
+ else
+ log_debug("BOREALIS: Unknown response code while fetching pins from the Discord API: [res].")
+ return ERROR_PROC
+ else
+ var/list/A = res
+
+ // No length to return data, but a valid 200 return header.
+ // So we simply have no invites active. Make one!
+ if (!A || !A.len)
+ return create_invite(token)
+
+ var/best_age = A[1]["max_age"]
+ var/code = A[1]["code"]
+
+ // Find the best invite.
+ // Why? Because round time expires are lame, I guess.
+ if (best_age != 0)
+ for (var/i = 2, i < A.len, i++)
+ if (A[i]["max_age"] == 0)
+ code = A[i]["code"]
+ break
+
+ if (best_age < A[i]["max_age"])
+ best_age = A[i]["max_age"]
+ code = A[i]["code"]
+
+ // Sanity check for debug I guess.
+ if (!code)
+ log_debug("BOREALIS: Retreived an empty invite. This should not happen. Response object: [json_encode(A)]")
+
+ // Save the URL for later retreival.
+ invite_url = "https://discord.gg/[code]"
+ return invite_url
+
+/*
+ * Proc create_invite
+ * Creates a permanent invite to a channel and returns it, under the assumption that
+ * there are no other invites for this channel.
+ *
+ * @param text token - the authorization token to be used for the requests.
+ * @return mixed - String upon success - the URL of the newly generated invite.
+ * Num upon failure.
+ */
+/datum/discord_channel/proc/create_invite(var/token)
+ var/data = list("max_age" = 0, "max_uses" = 0)
+ var/res = send_post_request("https://discordapp.com/api/channels/[id]/invites", json_encode(data), "Authorization: Bot [token]", "Content-Type: application/json")
+
+ if (res == 200)
+ var/list/get_req = send_get_request("https://discordapp.com/api/channels/[id]/invites", "Authorization: Bot [token]")
+
+ if (!istype(get_req) || !get_req.len)
+ return ERROR_PROC
+
+ // The first index should now exist. So we just use that!
+ invite_url = "https://discord.gg/[get_req[1]["code"]]"
+ return invite_url
#undef CHAN_ADMIN
#undef CHAN_CCIAA
#undef CHAN_ANNOUNCE
+#undef CHAN_INVITE
+
+#undef SEND_OK
+#undef SEND_TIMEOUT
+#undef ERROR_PROC
+#undef ERROR_CURL
+#undef ERROR_HTTP
diff --git a/code/datums/scheduled_task.dm b/code/datums/scheduled_task.dm
new file mode 100644
index 00000000000..f7ffb042325
--- /dev/null
+++ b/code/datums/scheduled_task.dm
@@ -0,0 +1,79 @@
+/*************
+* Task Datum *
+*************/
+/datum/scheduled_task
+ var/trigger_time
+ var/procedure
+ var/list/arguments
+ var/task_after_process
+ var/list/task_after_process_args
+ var/datum/scheduled_task/next
+ var/destroyed = FALSE
+
+/datum/scheduled_task/New(var/trigger_time, var/procedure, var/list/arguments, var/proc/task_after_process, var/list/task_after_process_args)
+ ..()
+ src.trigger_time = trigger_time
+ src.procedure = procedure
+ src.arguments = arguments ? arguments : list()
+ src.task_after_process = task_after_process ? task_after_process : /proc/destroy_scheduled_task
+ src.task_after_process_args = istype(task_after_process_args) ? task_after_process_args : list()
+ task_after_process_args += src
+
+/datum/scheduled_task/Destroy()
+ if (!destroyed)
+ kill(no_del = TRUE)
+ procedure = null
+ arguments.Cut()
+ task_after_process = null
+ task_after_process_args.Cut()
+ return ..()
+
+/datum/scheduled_task/proc/pre_process()
+ return
+
+/datum/scheduled_task/proc/process()
+ if(procedure)
+ call(procedure)(arglist(arguments))
+
+/datum/scheduled_task/proc/post_process()
+ call(task_after_process)(arglist(task_after_process_args))
+
+// Resets the trigger time, has no effect if the task has already triggered
+/datum/scheduled_task/proc/trigger_task_in(var/trigger_in)
+ src.trigger_time = world.time + trigger_in
+
+/datum/scheduled_task/proc/kill(no_del = FALSE)
+ if (!destroyed)
+ warning("scheduler: Non-destroyed task was killed!")
+ destroyed = TRUE
+
+ if (src in scheduler.tasks)
+ warning("scheduler: Task was not cleaned up correctly, rebuilding scheduler queue!")
+ scheduler.rebuild_queue()
+
+ if (!no_del)
+ qdel(src)
+
+/datum/scheduled_task/source
+ var/datum/source
+
+/datum/scheduled_task/source/New(var/trigger_time, var/datum/source, var/procedure, var/list/arguments, var/proc/task_after_process, var/list/task_after_process_args)
+ src.source = source
+ ..(trigger_time, procedure, arguments, task_after_process, task_after_process_args)
+
+/datum/scheduled_task/source/Destroy()
+ source = null
+ return ..()
+
+/datum/scheduled_task/source/process()
+ call(source, procedure)(arglist(arguments))
+
+/datum/scheduled_task/source/proc/source_destroyed()
+ destroyed = TRUE
+
+/proc/destroy_scheduled_task(var/datum/scheduled_task/st)
+ st.destroyed = TRUE
+
+/proc/repeat_scheduled_task(var/trigger_delay, var/datum/scheduled_task/st)
+ st.trigger_time = world.time + trigger_delay
+ scheduler.schedule(st)
diff --git a/code/datums/server_greeting.dm b/code/datums/server_greeting.dm
index be8bfcee59f..5b7868b07b6 100644
--- a/code/datums/server_greeting.dm
+++ b/code/datums/server_greeting.dm
@@ -46,8 +46,9 @@
if (F["motd"])
F["motd"] >> motd
- if (F["memo"])
- F["memo"] >> memo_list
+ if (!config.use_discord_pins)
+ if (F["memo"])
+ F["memo"] >> memo_list
update_data()
@@ -63,18 +64,32 @@
motd = initial(motd)
motd_hash = ""
- if (memo_list.len)
- memo = ""
- for (var/ckey in memo_list)
- var/data = {"
[ckey] wrote on [memo_list[ckey]["date"]]:
- [memo_list[ckey]["content"]]
"}
+ if (!config.use_discord_pins)
+ // The initialization of memos in case use_discord_pins == 1 is done in discord_bot.dm
+ // Primary reason is to avoid null references when the bot isn't created yet.
+ if (memo_list.len)
+ memo = ""
+ for (var/ckey in memo_list)
+ var/data = {"
[ckey] wrote on [memo_list[ckey]["date"]]:
+ [memo_list[ckey]["content"]]
"}
- memo += data
+ memo += data
- memo_hash = md5(memo)
- else
- memo = initial(memo)
- memo_hash = ""
+ memo_hash = md5(memo)
+ else
+ memo = initial(memo)
+ memo_hash = ""
+
+/datum/server_greeting/proc/update_pins()
+ var/list/temp_list = discord_bot.retreive_pins()
+
+ // A is a number in a string form
+ // temp_list[A] is a list of lists.
+ for (var/A in temp_list)
+ var/list/memos = temp_list[A]
+ var/flag = text2num(A)
+
+ memo_list += new /datum/memo_datum(memos, flag)
/*
* Helper to update the MoTD or memo contents.
@@ -94,9 +109,15 @@
motd = new_value
if ("memo_write")
+ if (config.use_discord_pins)
+ return 0
+
memo_list[new_value[1]] = list("date" = time2text(world.realtime, "DD-MMM-YYYY"), "content" = new_value[2])
if ("memo_delete")
+ if (config.use_discord_pins)
+ return 0
+
if (memo_list[new_value])
memo_list -= new_value
else
@@ -132,7 +153,7 @@
if (motd_hash && user.prefs.motd_hash != motd_hash)
outdated_info |= OUTDATED_MOTD
- if (user.holder && memo_hash && user.prefs.memo_hash != memo_hash)
+ if (user.holder && user.prefs.memo_hash != get_memo_hash(user))
outdated_info |= OUTDATED_MEMO
if (user.prefs.notifications.len)
@@ -185,13 +206,13 @@
else
if (outdated_info & OUTDATED_MEMO)
data["update"] = 1
- data["changeHash"] = memo_hash
+ data["changeHash"] = get_memo_hash(user)
else
data["update"] = 0
data["changeHash"] = null
data["div"] = "#memo"
- data["content"] = memo
+ data["content"] = get_memo_content(user)
user << output(JS_SANITIZE(data), "greeting.browser:AddContent")
if (outdated_info & OUTDATED_MOTD)
@@ -216,6 +237,81 @@
if ("request_data")
send_to_javascript(C)
+/*
+ * Gets the appropriate memo hash for the memo system in use.
+ * Args:
+ * - var/C client
+ * Returns:
+ * - string
+ */
+/datum/server_greeting/proc/get_memo_hash(var/client/C)
+ if (!C || !C.holder)
+ return ""
+
+ if (!config.use_discord_pins)
+ return memo_hash
+
+ var/joint_checksum = ""
+ for (var/A in memo_list)
+ var/datum/memo_datum/memo = A
+ if (C.holder.rights & memo.flag)
+ joint_checksum += memo.hash
+
+ return md5(joint_checksum)
+
+/*
+ * Gets the appropriate memo content for the memo system in use.
+ * Args:
+ * - var/C client
+ * Returns:
+ * - string if old memo system is used (config.use_discord_pins = 0)
+ * - list of strings if new memo system is used
+ */
+/datum/server_greeting/proc/get_memo_content(var/client/C)
+ if (!C || !C.holder)
+ return ""
+
+ if (!config.use_discord_pins)
+ return memo
+
+ var/list/content = list()
+ for (var/A in memo_list)
+ var/datum/memo_datum/memo = A
+ if (C.holder.rights & memo.flag)
+ content += memo.contents
+
+ return content
+
+/datum/memo_datum
+ var/contents
+ var/hash
+ var/flag
+
+/datum/memo_datum/New(var/list/input = list(), var/_flag)
+ flag = _flag
+
+ // Yes. This is an unfortunately acceptable way of doing it.
+ // Why? Because you cannot use numbers as indexes in an assoc list without fucking DM.
+ var/static/list/flags_to_divs = list("[R_ADMIN]" = "danger",
+ "[R_MOD]" = "warning",
+ "[(R_MOD|R_ADMIN)]" = "warning",
+ "[R_CCIAA]" = "info",
+ "[R_DEV]" = "info")
+
+ if (input.len)
+ contents = "
"
+ for (var/i = 1, i <= input.len, i++)
+ contents += "[input[i]["author"]] wrote: [nl2br(input[i]["content"])]"
+
+ if (i < input.len)
+ contents += ""
+
+ contents += "
"
+ else
+ contents = ""
+
+ hash = md5(contents)
+
#undef OUTDATED_NOTE
#undef OUTDATED_MEMO
#undef OUTDATED_MOTD
diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm
index c2caf09c07e..5b17e18198f 100644
--- a/code/datums/supplypacks.dm
+++ b/code/datums/supplypacks.dm
@@ -1733,3 +1733,44 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
containertype = /obj/structure/closet/crate
containername = "IPC/Shell tag implanters"
group = "Security"
+
+/datum/supply_packs/ame_ctrl
+ name = "Antimatter Reactor Control Unit"
+ contains = list(
+ /obj/machinery/power/am_control_unit
+ )
+ cost = 40
+ containertype = /obj/structure/closet/crate/secure/large
+ containername = "antimatter reactor control unit kit"
+ group = "Engineering"
+ access = access_ce
+
+/datum/supply_packs/ame_section
+ name = "Antimatter Reactor Shielding Kit"
+ contains = list(
+ /obj/item/device/am_shielding_container,
+ /obj/item/device/am_shielding_container,
+ /obj/item/device/am_shielding_container,
+ /obj/item/device/am_shielding_container,
+ /obj/item/device/am_shielding_container,
+ /obj/item/device/am_shielding_container,
+ /obj/item/device/am_shielding_container,
+ /obj/item/device/am_shielding_container,
+ /obj/item/device/am_shielding_container
+ )
+ cost = 20
+ containertype = /obj/structure/closet/crate/secure/phoron
+ containername = "antimatter reactor shielding (9x) crate"
+ group = "Engineering"
+ access = access_ce
+
+/datum/supply_packs/ame_fuel
+ name = "Antimatter Reactor Fuel"
+ contains = list(
+ /obj/item/weapon/am_containment
+ )
+ cost = 20
+ containertype = /obj/structure/closet/crate/secure/bin
+ containername = "antimatter fuel container"
+ group = "Engineering"
+ access = access_engine
diff --git a/code/game/antagonist/antagonist_add.dm b/code/game/antagonist/antagonist_add.dm
index 6eb6a230083..9f9c828b59a 100644
--- a/code/game/antagonist/antagonist_add.dm
+++ b/code/game/antagonist/antagonist_add.dm
@@ -45,7 +45,7 @@
update_icons_added(player)
return 1
-/datum/antagonist/proc/remove_antagonist(var/datum/mind/player, var/show_message, var/implanted)
+/datum/antagonist/proc/remove_antagonist(var/datum/mind/player, var/show_message = TRUE, var/implanted)
if(!istype(player))
return 0
@@ -53,14 +53,15 @@
player.current.verbs -= faction_verb
if(player in current_antagonists)
- player.current << "You are no longer a [role_text]!"
+ if (show_message)
+ player.current << "You are no longer a [role_text]!"
current_antagonists -= player
faction_members -= player
player.special_role = null
update_icons_removed(player)
BITSET(player.current.hud_updateflag, SPECIALROLE_HUD)
- if (!is_special_character(player))
+ if (!is_special_character(player) && !player.current.client.holder)
player.current.client.verbs -= /client/proc/aooc
return 1
diff --git a/code/game/antagonist/station/cultist.dm b/code/game/antagonist/station/cultist.dm
index 1ff619546e0..df159aeb16d 100644
--- a/code/game/antagonist/station/cultist.dm
+++ b/code/game/antagonist/station/cultist.dm
@@ -6,6 +6,12 @@ var/datum/antagonist/cultist/cult
if(player.mind in cult.current_antagonists)
return 1
+/proc/iscult(var/mob/test)
+ if (test.faction == "cult")
+ return 1
+
+ else return iscultist(test)
+
/datum/antagonist/cultist
id = MODE_CULTIST
role_text = "Cultist"
@@ -113,7 +119,7 @@ var/datum/antagonist/cultist/cult
player << "You catch a glimpse of the Realm of Nar-Sie, the Geometer of Blood. You now see how flimsy the world is, you see that it should be open to the knowledge of That Which Waits. Assist your new compatriots in their dark dealings. Their goals are yours, and yours are theirs. You serve the Dark One above all else. Bring It back."
if(player.current && !istype(player.current, /mob/living/simple_animal/construct))
player.current.add_language(LANGUAGE_CULT)
-
+
/datum/antagonist/cultist/can_become_antag(var/datum/mind/player, ignore_role = 1)
if(!..())
return 0
diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm
index cb0665ea768..1a4e3a52734 100755
--- a/code/game/area/Space Station 13 areas.dm
+++ b/code/game/area/Space Station 13 areas.dm
@@ -611,6 +611,13 @@ area/space/atmosalert()
flags = RAD_SHIELDED
sound_env = TUNNEL_ENCLOSED
turf_initializer = new /datum/turf_initializer/maintenance()
+ ambience = list(
+ 'sound/ambience/ambimaint1.ogg',
+ 'sound/ambience/ambimaint2.ogg',
+ 'sound/ambience/ambimaint3.ogg',
+ 'sound/ambience/ambimaint4.ogg',
+ 'sound/ambience/ambimaint5.ogg'
+ )
station_area = 1
/area/maintenance/civ
@@ -1130,14 +1137,20 @@ area/space/atmosalert()
/area/engineering
name = "\improper Engineering"
icon_state = "engineering"
- ambience = list('sound/ambience/ambisin1.ogg','sound/ambience/ambisin2.ogg','sound/ambience/ambisin3.ogg','sound/ambience/ambisin4.ogg')
+ ambience = list(
+ 'sound/ambience/ambisin1.ogg',
+ 'sound/ambience/ambisin2.ogg',
+ 'sound/ambience/ambisin3.ogg',
+ 'sound/ambience/ambisin4.ogg'
+ )
station_area = 1
/area/engineering/atmos
- name = "\improper Atmospherics"
- icon_state = "atmos"
- sound_env = LARGE_ENCLOSED
- no_light_control = 1
+ name = "\improper Atmospherics"
+ icon_state = "atmos"
+ sound_env = LARGE_ENCLOSED
+ no_light_control = 1
+ ambience = list('sound/ambience/ambiatm1.ogg')
/area/engineering/atmos/monitoring
name = "\improper Atmospherics Monitoring Room"
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index 1c2d6d0382f..214caef4a92 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -9,7 +9,7 @@
blend_mode = BLEND_MULTIPLY
/area/New()
- icon_state = ""
+ icon_state = "white"
layer = 10
uid = ++global_uid
all_areas += src
@@ -154,21 +154,40 @@
D.open()
return
+#define DO_PARTY(COLOR) animate(color = COLOR, time = 0.5 SECONDS, easing = QUAD_EASING)
+
/area/proc/updateicon()
if ((fire || eject || party) && (!requires_power||power_environ) && !istype(src, /area/space))//If it doesn't require power, can still activate this proc.
- if(fire && !eject && !party)
- icon_state = "blue"
- /*else if(atmosalm && !fire && !eject && !party)
- icon_state = "bluenew"*/
- else if(!fire && eject && !party)
- icon_state = "red"
- else if(party && !fire && !eject)
- icon_state = "party"
+ if(fire && !eject && !party) // FIRE
+ color = "#ff9292"
+ animate(src) // stop any current animations.
+ animate(src, color = "#ffa5b2", time = 1 SECOND, loop = -1, easing = SINE_EASING)
+ animate(color = "#ff9292", time = 1 SECOND, easing = SINE_EASING)
+ else if(!fire && eject && !party) // EJECT
+ color = "#ff9292"
+ animate(src)
+ animate(src, color = "#bc8a81", time = 1 SECOND, loop = -1, easing = EASE_IN|CUBIC_EASING)
+ animate(color = "#ff9292", time = 0.5 SECOND, easing = EASE_OUT|CUBIC_EASING)
+ else if(party && !fire && !eject) // PARTY
+ color = "#ff728e"
+ animate(src)
+ animate(src, color = "#7272ff", time = 0.5 SECONDS, loop = -1, easing = QUAD_EASING)
+ DO_PARTY("#72aaff")
+ DO_PARTY("#ffc68e")
+ DO_PARTY("#72c6ff")
+ DO_PARTY("#ff72e2")
+ DO_PARTY("#72ff8e")
+ DO_PARTY("#ffff8e")
+ DO_PARTY("#ff728e")
else
- icon_state = "blue-red"
+ color = "#ffb2b2"
+ animate(src)
+ animate(src, color = "#B3DFFF", time = 0.5 SECOND, loop = -1, easing = SINE_EASING)
+ animate(color = "#ffb2b2", time = 0.5 SECOND, loop = -1, easing = SINE_EASING)
else
- // new lighting behaviour with obj lights
- icon_state = null
+ animate(src, color = "#FFFFFF", time = 0.5 SECONDS, easing = QUAD_EASING) // Stop the animation.
+
+#undef DO_PARTY
/*
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 0fa8af01ad0..132587422cb 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -223,15 +223,6 @@ its easier to just keep the beam vertical.
/atom/proc/set_dir(new_dir)
. = new_dir != dir
dir = new_dir
- /*for(var/datum/light_source/L in light_sources)
- if (L.source_atom.offset_light)
- L.force_update = 1
- if (world.tick_usage < 80)
- L.instant_update()//Instant update skips the normal controller process and updates the light now.
- //This makes things more responsive, but probably has a performance cost for people spinning rapidly
- //Ergo, it checks tick usage first
- else
- L.source_atom.update_light()*/
/atom/proc/ex_act()
return
@@ -510,4 +501,4 @@ its easier to just keep the beam vertical.
change_area_name(oldarea.name, newarea.name)
/atom/proc/change_area_name(var/oldname, var/newname)
- name = replacetext(name,oldname,newname)
\ No newline at end of file
+ name = replacetext(name,oldname,newname)
diff --git a/code/game/gamemodes/changeling/changeling_items.dm b/code/game/gamemodes/changeling/changeling_items.dm
new file mode 100644
index 00000000000..cf27d5301ba
--- /dev/null
+++ b/code/game/gamemodes/changeling/changeling_items.dm
@@ -0,0 +1,91 @@
+/obj/item/weapon/melee/arm_blade
+ name = "arm blade"
+ desc = "A grotesque blade made out of bone and flesh that cleaves through people as a hot knife through butter."
+ icon = 'icons/obj/changeling.dmi'
+ icon_state = "arm_blade"
+ item_state = "arm_blade"
+ contained_sprite = 1
+ w_class = 4
+ force = 30
+ sharp = 1
+ edge = 1
+ anchored = 1
+ throwforce = 0 //Just to be on the safe side
+ throw_range = 0
+ throw_speed = 0
+ can_embed = 0
+ attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
+ var/mob/living/creator
+
+/obj/item/weapon/melee/arm_blade/New()
+ processing_objects |= src
+
+/obj/item/weapon/melee/arm_blade/Destroy()
+ processing_objects -= src
+ ..()
+
+/obj/item/weapon/melee/arm_blade/dropped()
+ visible_message("With a sickening crunch, [user] reforms their arm blade into an arm!",
+ "We assimilate the weapon back into our body.",
+ "You hear organic matter ripping and tearing!")
+ playsound(loc, 'sound/effects/blobattack.ogg', 30, 1)
+ spawn(1) if(src) qdel(src)
+
+/obj/item/weapon/melee/arm_blade/process()
+ if(!creator || loc != creator || (creator.l_hand != src && creator.r_hand != src))
+ // Tidy up a bit.
+ if(istype(loc,/mob/living))
+ var/mob/living/carbon/human/host = loc
+ if(istype(host))
+ for(var/obj/item/organ/external/organ in host.organs)
+ for(var/obj/item/O in organ.implants)
+ if(O == src)
+ organ.implants -= src
+ host.pinned -= src
+ host.embedded -= src
+ host.drop_from_inventory(src)
+ spawn(1) if(src) qdel(src)
+
+/obj/item/weapon/shield/riot/changeling
+ name = "shield-like mass"
+ desc = "A mass of tough, boney tissue. You can still see the fingers as a twisted pattern in the shield."
+ icon = 'icons/obj/changeling.dmi'
+ icon_state = "ling_shield"
+ item_state = "ling_shield"
+ contained_sprite = 1
+ slot_flags = null
+ anchored = 1
+ throwforce = 0 //Just to be on the safe side
+ throw_range = 0
+ throw_speed = 0
+ can_embed = 0
+ var/mob/living/creator
+
+/obj/item/weapon/shield/riot/changeling/New()
+ processing_objects |= src
+
+/obj/item/weapon/shield/riot/changeling/Destroy()
+ processing_objects -= src
+ ..()
+
+/obj/item/weapon/shield/riot/changeling/dropped()
+ visible_message("With a sickening crunch, [user] reforms their arm blade into an arm!",
+ "We assimilate the weapon back into our body.",
+ "You hear organic matter ripping and tearing!")
+ playsound(loc, 'sound/effects/blobattack.ogg', 30, 1)
+ spawn(1) if(src) qdel(src)
+
+/obj/item/weapon/shield/riot/changeling/process()
+ if(!creator || loc != creator || (creator.l_hand != src && creator.r_hand != src))
+ // Tidy up a bit.
+ if(istype(loc,/mob/living))
+ var/mob/living/carbon/human/host = loc
+ if(istype(host))
+ for(var/obj/item/organ/external/organ in host.organs)
+ for(var/obj/item/O in organ.implants)
+ if(O == src)
+ organ.implants -= src
+ host.pinned -= src
+ host.embedded -= src
+ host.drop_from_inventory(src)
+ spawn(1) if(src) qdel(src)
\ No newline at end of file
diff --git a/code/game/gamemodes/changeling/changeling_powers.dm b/code/game/gamemodes/changeling/changeling_powers.dm
index eb3a092a03c..f57322c47a1 100644
--- a/code/game/gamemodes/changeling/changeling_powers.dm
+++ b/code/game/gamemodes/changeling/changeling_powers.dm
@@ -1,8 +1,7 @@
var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon","Zeta","Eta","Theta","Iota","Kappa","Lambda","Mu","Nu","Xi","Omicron","Pi","Rho","Sigma","Tau","Upsilon","Phi","Chi","Psi","Omega")
/datum/changeling //stores changeling powers, changeling recharge thingie, changeling absorbed DNA and changeling ID (for changeling hivemind)
- var/list/absorbed_dna = list()
- var/list/absorbed_species = list()
+ var/list/datum/absorbed_dna/absorbed_dna = list()
var/list/absorbed_languages = list()
var/absorbedcount = 0
var/chem_charges = 20
@@ -31,12 +30,24 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
geneticdamage = max(0, geneticdamage-1)
/datum/changeling/proc/GetDNA(var/dna_owner)
- var/datum/dna/chosen_dna
- for(var/datum/dna/DNA in absorbed_dna)
- if(dna_owner == DNA.real_name)
- chosen_dna = DNA
- break
- return chosen_dna
+ for(var/datum/absorbed_dna/DNA in absorbed_dna)
+ if(dna_owner == DNA.name)
+ return DNA
+
+/mob/proc/absorbDNA(var/datum/absorbed_dna/newDNA)
+ var/datum/changeling/changeling = null
+ if(src.mind && src.mind.changeling)
+ changeling = src.mind.changeling
+ if(!changeling)
+ return
+
+ for(var/language in newDNA.languages)
+ changeling.absorbed_languages |= language
+
+ changeling_update_languages(changeling.absorbed_languages)
+
+ if(!changeling.GetDNA(newDNA.name)) // Don't duplicate - I wonder if it's possible for it to still be a different DNA? DNA code could use a rewrite
+ changeling.absorbed_dna += newDNA
//Restores our verbs. It will only restore verbs allowed during lesser (monkey) form if we are not human
/mob/proc/make_changeling()
@@ -65,14 +76,13 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
if(!(P in src.verbs))
src.verbs += P.verbpath
- mind.changeling.absorbed_dna |= dna
+ for(var/language in languages)
+ mind.changeling.absorbed_languages |= language
var/mob/living/carbon/human/H = src
if(istype(H))
- mind.changeling.absorbed_species += H.species.name
-
- for(var/language in languages)
- mind.changeling.absorbed_languages |= language
+ var/datum/absorbed_dna/newDNA = new(H.real_name, H.dna, H.species.name, H.languages)
+ absorbDNA(newDNA)
return 1
@@ -83,13 +93,6 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
if(P.isVerb)
verbs -= P.verbpath
-//removes changeling powers but keeps those with allowduringlesserform
-/mob/proc/remove_changeling_powers_monkey()
- if(!mind || !mind.changeling) return
- for(var/datum/power/changeling/P in mind.changeling.purchasedpowers)
- if(P.isVerb && (P.allowduringlesserform == 0))
- verbs -= P.verbpath
-
//Helper proc. Does all the checks and stuff for us to avoid copypasta
/mob/proc/changeling_power(var/required_chems=0, var/required_dna=0, var/max_genetic_damage=100, var/max_stat=0)
@@ -133,46 +136,6 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
return
-//Used to switch species based on the changeling datum.
-/mob/proc/changeling_change_species()
-
- set category = "Changeling"
- set name = "Change Species (5)"
-
- var/mob/living/carbon/human/H = src
- if(!istype(H))
- src << "We may only use this power while in humanoid form."
- return
-
- var/datum/changeling/changeling = changeling_power(5,1,0)
- if(!changeling) return
-
- if(changeling.absorbed_species.len < 2)
- src << "We do not know of any other species genomes to use."
- return
-
- var/S = input("Select the target species: ", "Target Species", null) as null|anything in changeling.absorbed_species
- if(!S) return
-
- domutcheck(src, null)
-
- changeling.chem_charges -= 5
- changeling.geneticdamage = 30
-
- src.visible_message("[src] transforms!")
-
- src.verbs -= /mob/proc/changeling_change_species
- H.set_species(S,1) //Until someone moves body colour into DNA, they're going to have to use the default.
-
- spawn(10)
- src.verbs += /mob/proc/changeling_change_species
- src.regenerate_icons()
-
- changeling_update_languages(changeling.absorbed_languages)
- feedback_add_details("changeling_powers","TR")
-
- return 1
-
//Absorbs the victim's DNA making them uncloneable. Requires a strong grip on the victim.
//Doesn't cost anything as it's the most basic ability.
/mob/proc/changeling_absorb_dna()
@@ -196,6 +159,10 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
src << "We do not know how to parse this creature's DNA!"
return
+ if(islesserform(T))
+ src << "This creature DNA is not compatible with our form!"
+ return
+
if(HUSK in T.mutations)
src << "This creature's DNA is ruined beyond useability!"
return
@@ -213,6 +180,7 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
switch(stage)
if(1)
src << "This creature is compatible. We must hold still..."
+ src.visible_message("[src]'s skin begins to shift and squirm!")
if(2)
src << "We extend a proboscis."
src.visible_message("[src] extends a proboscis!")
@@ -234,9 +202,6 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
src.visible_message("[src] sucks the fluids from [T]!")
T << "You have been absorbed by the changeling!"
- T.dna.real_name = T.real_name //Set this again, just to be sure that it's properly set.
- changeling.absorbed_dna |= T.dna
- if(src.nutrition < max_nutrition) src.nutrition = min((nutrition + T.nutrition), max_nutrition)
changeling.chem_charges += 10
changeling.geneticpoints += 2
@@ -247,16 +212,15 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
changeling_update_languages(changeling.absorbed_languages)
- //Steal their species!
- if(T.species && !(T.species.name in changeling.absorbed_species))
- changeling.absorbed_species += T.species.name
+ var/datum/absorbed_dna/newDNA = new(T.real_name, T.dna, T.species.name, T.languages)
+ absorbDNA(newDNA)
if(T.mind && T.mind.changeling)
if(T.mind.changeling.absorbed_dna)
- for(var/dna_data in T.mind.changeling.absorbed_dna) //steal all their loot
- if(dna_data in changeling.absorbed_dna)
+ for(var/datum/absorbed_dna/dna_data in T.mind.changeling.absorbed_dna) //steal all their loot
+ if(changeling.GetDNA(dna_data.name))
continue
- changeling.absorbed_dna += dna_data
+ absorbDNA(dna_data)
changeling.absorbedcount++
T.mind.changeling.absorbed_dna.len = 1
@@ -295,31 +259,44 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
if(!changeling) return
var/list/names = list()
- for(var/datum/dna/DNA in changeling.absorbed_dna)
- names += "[DNA.real_name]"
+ for(var/datum/absorbed_dna/DNA in changeling.absorbed_dna)
+ names += "[DNA.name]"
var/S = input("Select the target DNA: ", "Target DNA", null) as null|anything in names
if(!S) return
- var/datum/dna/chosen_dna = changeling.GetDNA(S)
+ var/datum/absorbed_dna/chosen_dna = changeling.GetDNA(S)
if(!chosen_dna)
return
changeling.chem_charges -= 5
- src.visible_message("[src] transforms!")
changeling.geneticdamage = 30
- src.dna = chosen_dna.Clone()
- src.real_name = chosen_dna.real_name
- src.flavor_text = ""
- src.UpdateAppearance()
- domutcheck(src, null)
+
+ handle_changeling_transform(chosen_dna)
src.verbs -= /mob/proc/changeling_transform
- spawn(10) src.verbs += /mob/proc/changeling_transform
+ spawn(10)
+ src.verbs += /mob/proc/changeling_transform
+
+ changeling_update_languages(changeling.absorbed_languages)
feedback_add_details("changeling_powers","TR")
return 1
+/mob/proc/handle_changeling_transform(var/datum/absorbed_dna/chosen_dna)
+ src.visible_message("[src] transforms!")
+
+ if(ishuman(src))
+ var/mob/living/carbon/human/H = src
+ var/newSpecies = chosen_dna.speciesName
+ H.set_species(newSpecies,1)
+
+ src.dna = chosen_dna.dna
+ src.real_name = chosen_dna.name
+ src.flavor_text = ""
+ domutcheck(src, null)
+ src.UpdateAppearance()
+
//Transform into a monkey.
/mob/proc/changeling_lesser_form()
@@ -340,15 +317,10 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
return
changeling.chem_charges--
- H.remove_changeling_powers_monkey() //we weren't making us of allowduringlesserform before for some reason? -Ryan784
H.visible_message("[H] transforms!")
changeling.geneticdamage = 30
H << "Our genes cry out!"
- var/list/implants = list() //Try to preserve implants.
- for(var/obj/item/weapon/implant/W in H)
- implants += W
- H.monkeyize()
- verbs += /mob/proc/changeling_lesser_transform //allow us to actually transform BACK into a human - Ryan784
+ H = H.monkeyize()
feedback_add_details("changeling_powers","LF")
return 1
@@ -457,25 +429,29 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
// charge the changeling chemical cost for stasis
changeling.chem_charges -= 20
- // restore us to health
- C.revive()
-
- // remove our fake death flag
- C.status_flags &= ~(FAKEDEATH)
-
- // let us move again
- C.update_canmove()
-
- // re-add out changeling powers
- C.make_changeling()
-
- // sending display messages
- C << "We have regenerated."
-
+ C << "We are ready to rise. Use the Revive verb when you are ready."
+ C.verbs += /mob/proc/changeling_revive
feedback_add_details("changeling_powers","FD")
return 1
+/mob/proc/changeling_revive()
+ set category = "Changeling"
+ set name = "Revive"
+
+ var/mob/living/carbon/C = src
+ // restore us to health
+ C.revive()
+ // remove our fake death flag
+ C.status_flags &= ~(FAKEDEATH)
+ // let us move again
+ C.update_canmove()
+ // re-add out changeling powers
+ C.make_changeling()
+ // sending display messages
+ C << "We have regenerated."
+ C.verbs -= /mob/proc/changeling_revive
+
//Boosts the range of your next sting attack by 1
/mob/proc/changeling_boost_range()
@@ -581,7 +557,7 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
// HIVE MIND UPLOAD/DOWNLOAD DNA
-var/list/datum/dna/hivemind_bank = list()
+var/list/datum/absorbed_dna/hivemind_bank = list()
/mob/proc/changeling_hiveupload()
set category = "Changeling"
@@ -592,9 +568,14 @@ var/list/datum/dna/hivemind_bank = list()
if(!changeling) return
var/list/names = list()
- for(var/datum/dna/DNA in changeling.absorbed_dna)
- if(!(DNA in hivemind_bank))
- names += DNA.real_name
+ for(var/datum/absorbed_dna/DNA in changeling.absorbed_dna)
+ var/valid = 1
+ for(var/datum/absorbed_dna/DNB in hivemind_bank)
+ if(DNA.name == DNB.name)
+ valid = 0
+ break
+ if(valid)
+ names += DNA.name
if(names.len <= 0)
src << "The airwaves already have all of our DNA."
@@ -603,7 +584,7 @@ var/list/datum/dna/hivemind_bank = list()
var/S = input("Select a DNA to channel: ", "Channel DNA", null) as null|anything in names
if(!S) return
- var/datum/dna/chosen_dna = changeling.GetDNA(S)
+ var/datum/absorbed_dna/chosen_dna = changeling.GetDNA(S)
if(!chosen_dna)
return
@@ -622,9 +603,9 @@ var/list/datum/dna/hivemind_bank = list()
if(!changeling) return
var/list/names = list()
- for(var/datum/dna/DNA in hivemind_bank)
- if(!(DNA in changeling.absorbed_dna))
- names[DNA.real_name] = DNA
+ for(var/datum/absorbed_dna/DNA in hivemind_bank)
+ if(!(changeling.GetDNA(DNA.name)))
+ names[DNA.name] = DNA
if(names.len <= 0)
src << "There's no new DNA to absorb from the air."
@@ -637,7 +618,7 @@ var/list/datum/dna/hivemind_bank = list()
return
changeling.chem_charges -= 20
- changeling.absorbed_dna += chosen_dna
+ absorbDNA(chosen_dna)
src << "We absorb the DNA of [S] from the air."
feedback_add_details("changeling_powers","HD")
return 1
@@ -692,7 +673,7 @@ var/list/datum/dna/hivemind_bank = list()
return 1
//Handles the general sting code to reduce on copypasta (seeming as somebody decided to make SO MANY dumb abilities)
-/mob/proc/changeling_sting(var/required_chems=0, var/verb_path)
+/mob/proc/changeling_sting(var/required_chems=0, var/verb_path, var/stealthy = 0)
var/datum/changeling/changeling = changeling_power(required_chems)
if(!changeling) return
@@ -711,9 +692,20 @@ var/list/datum/dna/hivemind_bank = list()
src.verbs -= verb_path
spawn(10) src.verbs += verb_path
- src << "We stealthily sting [T]."
+ if(stealthy == 1)
+ src << "We stealthily sting [T]."
+ T << "You feel a tiny prick."
+ else
+ src.visible_message(pick("[src]'s eyes balloon and burst out in a welter of blood, burrowing into [T]!",
+ "[src]'s arm rapidly shifts into a giant scorpion-stinger and stabs into [T]!",
+ "[src]'s throat lengthens and twists before vomitting a chunky red spew all over [T]!",
+ "[src]'s tongue stretches an impossible length and stabs into [T]!",
+ "[src] sneezes a cloud of shrieking spiders at [T]!",
+ "[src] erupts a grotesque tail and impales [T]!",
+ "[src]'s chin skin bulges and tears, launching a bone-dart at [T]!"))
+
if(!T.mind || !T.mind.changeling) return T //T will be affected by the sting
- T << "You feel a tiny prick."
+
return
@@ -722,7 +714,7 @@ var/list/datum/dna/hivemind_bank = list()
set name = "Hallucination Sting (15)"
set desc = "Causes terror in the target."
- var/mob/living/carbon/T = changeling_sting(15,/mob/proc/changeling_lsdsting)
+ var/mob/living/carbon/T = changeling_sting(15,/mob/proc/changeling_lsdsting,stealthy = 1)
if(!T) return 0
spawn(rand(300,600))
if(T) T.hallucination += 400
@@ -734,7 +726,7 @@ var/list/datum/dna/hivemind_bank = list()
set name = "Silence sting (10)"
set desc="Sting target"
- var/mob/living/carbon/T = changeling_sting(10,/mob/proc/changeling_silence_sting)
+ var/mob/living/carbon/T = changeling_sting(10,/mob/proc/changeling_silence_sting,stealthy = 1)
if(!T) return 0
T.silent += 30
feedback_add_details("changeling_powers","SS")
@@ -745,7 +737,7 @@ var/list/datum/dna/hivemind_bank = list()
set name = "Blind sting (20)"
set desc="Sting target"
- var/mob/living/carbon/T = changeling_sting(20,/mob/proc/changeling_blind_sting)
+ var/mob/living/carbon/T = changeling_sting(20,/mob/proc/changeling_blind_sting,stealthy = 0)
if(!T) return 0
T << "Your eyes burn horrificly!"
T.disabilities |= NEARSIGHTED
@@ -760,7 +752,7 @@ var/list/datum/dna/hivemind_bank = list()
set name = "Deaf sting (5)"
set desc="Sting target:"
- var/mob/living/carbon/T = changeling_sting(5,/mob/proc/changeling_deaf_sting)
+ var/mob/living/carbon/T = changeling_sting(5,/mob/proc/changeling_deaf_sting,stealthy = 0)
if(!T) return 0
T << "Your ears pop and begin ringing loudly!"
T.sdisabilities |= DEAF
@@ -773,7 +765,7 @@ var/list/datum/dna/hivemind_bank = list()
set name = "Paralysis sting (30)"
set desc="Sting target"
- var/mob/living/carbon/T = changeling_sting(30,/mob/proc/changeling_paralysis_sting)
+ var/mob/living/carbon/T = changeling_sting(30,/mob/proc/changeling_paralysis_sting,stealthy = 0)
if(!T) return 0
T << "Your muscles begin to painfully tighten."
T.Weaken(20)
@@ -788,29 +780,25 @@ var/list/datum/dna/hivemind_bank = list()
var/datum/changeling/changeling = changeling_power(40)
if(!changeling) return 0
-
-
var/list/names = list()
- for(var/datum/dna/DNA in changeling.absorbed_dna)
- names += "[DNA.real_name]"
+ for(var/datum/absorbed_dna/DNA in changeling.absorbed_dna)
+ names += "[DNA.name]"
var/S = input("Select the target DNA: ", "Target DNA", null) as null|anything in names
if(!S) return
- var/datum/dna/chosen_dna = changeling.GetDNA(S)
+ var/datum/absorbed_dna/chosen_dna = changeling.GetDNA(S)
if(!chosen_dna)
return
- var/mob/living/carbon/T = changeling_sting(40,/mob/proc/changeling_transformation_sting)
+ var/mob/living/carbon/T = changeling_sting(40,/mob/proc/changeling_transformation_sting,stealthy = 1)
if(!T) return 0
if((HUSK in T.mutations) || (!ishuman(T) && !issmall(T)))
src << "Our sting appears ineffective against its DNA."
return 0
- T.visible_message("[T] transforms!")
- T.dna = chosen_dna.Clone()
- T.real_name = chosen_dna.real_name
- T.UpdateAppearance()
- domutcheck(T, null)
+
+ T.handle_changeling_transform(chosen_dna)
+
feedback_add_details("changeling_powers","TS")
return 1
@@ -819,10 +807,9 @@ var/list/datum/dna/hivemind_bank = list()
set name = "Unfat sting (5)"
set desc = "Sting target"
- var/mob/living/carbon/T = changeling_sting(5,/mob/proc/changeling_unfat_sting)
+ var/mob/living/carbon/T = changeling_sting(5,/mob/proc/changeling_unfat_sting,stealthy = 1)
if(!T) return 0
T << "you feel a small prick as stomach churns violently and you become to feel skinnier."
- T.overeatduration = 0
T.nutrition -= 100
feedback_add_details("changeling_powers","US")
return 1
@@ -832,13 +819,13 @@ var/list/datum/dna/hivemind_bank = list()
set name = "Death Sting (40)"
set desc = "Causes spasms onto death."
- var/mob/living/carbon/T = changeling_sting(40,/mob/proc/changeling_DEATHsting)
+ var/mob/living/carbon/T = changeling_sting(40,/mob/proc/changeling_DEATHsting,stealthy = 0)
if(!T) return 0
T << "You feel a small prick and your chest becomes tight."
T.silent = 10
T.Paralyse(10)
T.make_jittery(1000)
- if(T.reagents) T.reagents.add_reagent("lexorin", 40)
+ if(T.reagents) T.reagents.add_reagent("cyanide", 5)
feedback_add_details("changeling_powers","DTHS")
return 1
@@ -853,13 +840,66 @@ var/list/datum/dna/hivemind_bank = list()
if(!changeling)
return 0
- var/mob/living/carbon/human/T = changeling_sting(40, /mob/proc/changeling_extract_dna_sting)
+ var/mob/living/carbon/human/T = changeling_sting(40, /mob/proc/changeling_extract_dna_sting,stealthy = 1)
if(!T) return 0
- T.dna.real_name = T.real_name
- changeling.absorbed_dna |= T.dna
- if(T.species && !(T.species.name in changeling.absorbed_species))
- changeling.absorbed_species += T.species.name
+ var/datum/absorbed_dna/newDNA = new(T.real_name, T.dna, T.species.name, T.languages)
+ absorbDNA(newDNA)
feedback_add_details("changeling_powers","ED")
return 1
+
+/mob/proc/armblades()
+ set category = "Changeling"
+ set name = "Form Blades"
+ set desc="Rupture the flesh and mend the bone of your hand into a deadly blade."
+
+ var/mob/living/M = src
+
+ if(M.l_hand && M.r_hand)
+ M << "Your hands are full."
+ return
+
+ var/obj/item/weapon/melee/arm_blade/blade = new(M)
+ blade.creator = M
+ M.put_in_hands(blade)
+ playsound(loc, 'sound/effects/blobattack.ogg', 30, 1)
+ src.visible_message("A grotesque blade forms around [M]\'s arm!",
+ "Our arm twists and mutates, transforming it into a deadly blade.",
+ "You hear organic matter ripping and tearing!")
+ gibs(src.loc)
+
+/mob/proc/changeling_shield()
+ set category = "Changeling"
+ set name = "Form Shield"
+ set desc="Bend the flesh and bone of your hand into a grotesque shield."
+
+ var/mob/living/M = src
+
+ if(M.l_hand && M.r_hand)
+ M << "Your hands are full."
+ return
+
+ var/obj/item/weapon/shield/riot/changeling/shield = new(M)
+ shield.creator = M
+ M.put_in_hands(shield)
+ playsound(loc, 'sound/effects/blobattack.ogg', 30, 1)
+ src.visible_message("The end of [M]\'s hand inflates rapidly, forming a huge shield-like mass!",
+ "We inflate our hand into a robust shield.",
+ "You hear organic matter ripping and tearing!")
+ gibs(src.loc)
+
+//dna related datum
+
+/datum/absorbed_dna
+ var/name
+ var/datum/dna/dna
+ var/speciesName
+ var/list/languages
+
+/datum/absorbed_dna/New(var/newName, var/newDNA, var/newSpecies, var/newLanguages)
+ ..()
+ name = newName
+ dna = newDNA
+ speciesName = newSpecies
+ languages = newLanguages
diff --git a/code/game/gamemodes/changeling/modularchangling.dm b/code/game/gamemodes/changeling/modularchangling.dm
index 7ba0052b816..303016281a2 100644
--- a/code/game/gamemodes/changeling/modularchangling.dm
+++ b/code/game/gamemodes/changeling/modularchangling.dm
@@ -26,12 +26,6 @@ var/list/datum/power/changeling/powerinstances = list()
genomecost = 0
verbpath = /mob/proc/changeling_transform
-/datum/power/changeling/change_species
- name = "Change Species"
- desc = "We take on the apperance of a species that we have absorbed."
- genomecost = 0
- verbpath = /mob/proc/changeling_change_species
-
/datum/power/changeling/fakedeath
name = "Regenerative Stasis"
desc = "We become weakened to a death-like state, where we will rise again from death."
@@ -64,14 +58,14 @@ var/list/datum/power/changeling/powerinstances = list()
/datum/power/changeling/deaf_sting
name = "Deaf Sting"
- desc = "We silently sting a human, completely deafening them for a short time."
+ desc = "We sting a human, completely deafening them for a short time."
genomecost = 1
allowduringlesserform = 1
verbpath = /mob/proc/changeling_deaf_sting
/datum/power/changeling/blind_sting
name = "Blind Sting"
- desc = "We silently sting a human, completely blinding them for a short time."
+ desc = "We sting a human, completely blinding them for a short time."
genomecost = 2
allowduringlesserform = 1
verbpath = /mob/proc/changeling_blind_sting
@@ -108,7 +102,7 @@ var/list/datum/power/changeling/powerinstances = list()
/datum/power/changeling/paralysis_sting
name = "Paralysis Sting"
- desc = "We silently sting a human, paralyzing them for a short time."
+ desc = "We sting a human, paralyzing them for a short time."
genomecost = 8
verbpath = /mob/proc/changeling_paralysis_sting
@@ -121,7 +115,7 @@ var/list/datum/power/changeling/powerinstances = list()
/datum/power/changeling/DeathSting
name = "Death Sting"
- desc = "We silently sting a human, filling them with potent chemicals. Their rapid death is all but assured."
+ desc = "We sting a human, filling them with potent chemicals. Their rapid death is all but assured."
genomecost = 10
verbpath = /mob/proc/changeling_DEATHsting
@@ -184,7 +178,19 @@ var/list/datum/power/changeling/powerinstances = list()
genomecost = 7
verbpath = /mob/proc/changeling_rapidregen
+//weapon and armor like powers
+/datum/power/changeling/armblades
+ name = "Mutate Armblades"
+ desc = "Permits us to reshape our arms into a deadly blade."
+ genomecost = 2
+ verbpath = /mob/proc/armblades
+
+/datum/power/changeling/shield
+ name = "Mutate Shield"
+ desc = "Permits us to bloat our hands into a robust shield."
+ genomecost = 3
+ verbpath = /mob/proc/changeling_shield
// Modularchangling, totally stolen from the new player panel. YAYY
/datum/changeling/proc/EvolutionMenu()//The new one
diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm
index 59cf8f8856b..80f4d996dcb 100644
--- a/code/game/gamemodes/cult/cult_structures.dm
+++ b/code/game/gamemodes/cult/cult_structures.dm
@@ -17,59 +17,565 @@
desc = "A forge used in crafting the unholy weapons used by the armies of Nar-Sie"
icon_state = "forge"
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*
+ Cult pylons can be used as arcane defensive turrets.
+
+ First of all they must be empowered with a sacrifice. Any small organic creature that can be picked up is valid
+ Hit the pylon with the creature - while still alive - to present it as a sacrifice, and then end its life to complete the process.
+
+ Once empowered, pylons will fire rapid, weak magical beams at non cult mobs.
+
+ As crystals, pylons are immune to energy weaponry. More than immune, they will absorb lasers and become
+ supercharged for some time, boosting their damage. Pylons can only be harmed by ballistics and physical weapons
+ Building reinforced windows around them is highly recommended.
+
+ Pylons are fairly fragile and will quickly break under direct hits.
+ A damaged pylon will self repair, if it contains a soul.
+
+
+ Pylons are largely intended as a stalling, early warning, fire support and area denial system. They are unlikely to actually
+ kill anyone alone but they can keep pesky civilians away for long enough to learn runes and prepare rituals.
+
+ If you can get ahold of a laser rifle to supercharge them, they can even give security some pause
+
+ Recommended tools for combatting pylons:
+ Heavy melee (fireaxe, baseball bat, etc)
+ Sniper rifles
+ Exosuits
+ Explosives
+ Ablative armour
+*/
/obj/structure/cult/pylon
name = "Pylon"
desc = "A floating crystal that hums with an unearthly energy"
- icon_state = "pylon"
+ description_antag = "A pylon can be upgraded into a magical defensive turret that shoots anyone opposing the cult\
+ Upgrading a pylon requires a sacrifice. Bring it a small organic creature, like a monkey or mouse. Use the creature on the pylon, or drag and drop to present it.\
+ Once the sacrifice is accepted, kill it to complete the process. This will gib its body and make a very visible mess. After this point the pylon is fixed to the floor and cant be moved\
+ The pylon will fire weak beams that are harmless to the cult. In addition it can be upgraded even more by shooting it with a laser, which will give it a limited number of extra-power shots."
+
+ icon_state = "pylonbase"
var/isbroken = 0
light_range = 5
light_color = "#3e0000"
- var/obj/item/wepon = null
+ var/pylonmode = 0
+ //Pylon has three states:
+ //0 = Idle, the pylon is an inert crystal
+ //1 = Awaiting sacrifice. The pylon is actively tracking a creature to be sacrificed to it
+ //2 = Turret. The pylon has been empowered by a sacrifice and is now a turret permanantly
+
+ var/damagetaken = 0
+ var/empowered = 0 //Number of empowered, higher-damage shots remaining
+ var/processing = 0
+ var/mob/living/sacrifice //Holds a reference to a mob that is a pending sacrifice
+ var/mob/living/sacrificer //A reference to the last mob that attempted to sacrifice something. So we can message them
+ //Sacrifier is also used in target handling. the pylon will not bite the hand that feeds it. Noncultist colleagues are fair game though
+
+ var/next_shot = 0 //Absolute world time when we're allowed to fire again
+ var/shot_delay = 5 //Minimum delay between shots, in deciseconds
+ var/mob/living/target
+
+ var/notarget //Number of times handle_firing has been called without finding anything to shoot at
+ //This is used for switching to lower-intensity processing
+
+ var/datum/language/cultcommon/lang
+ //An instance of the cult language datum. Used to scramble speech when speaking to noncultists
+
+ var/turf/last_target_loc
+
+ var/process_interval = 1
+ var/ticks
+ anchored = 0
+
+
+//Just a subtype that starts off in turret mode. For adminbus and debugging. Maybe a future wizard spell
+//Spawn them next to ERPers
+/obj/structure/cult/pylon/turret
+ pylonmode = 2
+
+/obj/structure/cult/pylon/turret/New()
+ ..()
+ start_process()
+
+
+//Another subtype which starts with infinite empower shots. For empowered adminbus
+/obj/structure/cult/pylon/turret/empowered
+ empowered = 99999999
+
+
+/obj/structure/cult/pylon/New()
+ ..()
+ lang = new /datum/language/cultcommon()
+ update_icon()
+
+/obj/structure/cult/pylon/examine(var/mob/user)
+ ..()
+ if (damagetaken)
+ switch (damagetaken)
+ if (1 to 8)
+ user << "It has very faint hairline fractures."
+ if (8 to 20)
+ user << "It has several cracks across its surface."
+ if (20 to 30)
+ user << "It is chipped and deeply cracked, it may shatter with much more pressure."
+ if (30 to INFINITY)
+ user << "It is almost cleaved in two, the pylon looks like it will fall to shards under its own weight."
+
+
+/obj/structure/cult/pylon/Move()
+ ..()
+ last_target_loc = null
+
+/obj/structure/cult/pylon/proc/start_process()
+ process_interval = 1
+ if (!processing)
+ processing_objects += src
+ processing = 1
+
+
+//If the pylon goes a long time without shooting anything, it will consider slowing down processing
+/obj/structure/cult/pylon/proc/reconsider_interval()
+ var/mindist = INFINITY
+ for (var/m in player_list)
+ var/mob/living/L = m
+ if (L.z != z)
+ continue
+
+ if (L.stat == DEAD)
+ continue
+
+ if (iscult(L))
+ continue
+
+ if (L == sacrificer)
+ continue
+
+ var/d = get_dist(src, L)
+ if (d < mindist)
+ mindist = d
+
+ mindist = min(150, mindist)
+ process_interval = Ceiling(mindist*0.1)
+ process_interval = max(1, process_interval)
+
+
+//Run each process loop, this function checks if we can stop processing yet.
+//Returns 0 if its time to stop. Returns 1 if we should keep going.
+/obj/structure/cult/pylon/proc/check_process()
+ if (isbroken)
+ return 0
+
+ if (pylonmode == 2)
+ return 1
+
+ if (pylonmode == 1)
+ if (sacrifice)
+ return 1
+
+ if (empowered > 0)
+ return 1
+
+ return 0
+
+/obj/structure/cult/pylon/process()
+ ticks++
+ if(!check_process())
+ processing_objects.Remove(src)
+ processing = 0
+ return
+
+ switch (pylonmode)
+ if (1)
+ handle_sacrifice()
+ if (2)
+ if ((ticks % process_interval) == 0)
+ handle_firing()
+ if (damagetaken && prob(50))
+ damagetaken = max(0, damagetaken-1) //An empowered pylon slowly self repairs
+ if (prob(10))
+ visible_message("Cracks in the [src] gradually seal as new crystalline matter grows to fill them.")
+
+ if (empowered && prob(2))
+ empowered = max(0, empowered - 1) //Overcharging gradually wears off over time
+ if (empowered <= 0)
+ update_icon()
+
+
+//If user is a cultist, speaks message to them with a prefix
+//If user is not cultist, then speaks cult-y gibberish
+/obj/structure/cult/pylon/proc/speak_to(var/mob/user, var/message)
+ if (iscult(user) || (/datum/language/cultcommon in user.languages))
+ user << "A voice speaks into your mind, [span("cult","\"[message]\"")]"
+ else
+ user << "A voice speaks into your mind, [span("cult","\"[lang.scramble(message)]\"")]"
+
+
+//Todo: Replace the messages here with better ones. Should display a proper message to cultists
+//And nonsensical arcane gibberish to non cultists
+/obj/structure/cult/pylon/proc/present_sacrifice(var/mob/living/user, var/mob/living/victim)
+ if (!user || !victim)
+ return 0
+
+ if (isbroken)
+ user << "The pylon lies silent."
+ return 0
+
+ if (pylonmode != 0)
+ return 0
+
+ if (!(victim.mob_size) || victim.mob_size > 6)
+ //toolarge sacrifice, display a message and return
+ speak_to(user, "This creature is too large, we only require a lesser sacrifice. A small morsel of life...")
+ return
+
+ if (victim.stat == DEAD)
+ speak_to(user, "You are too late, the spark of life is already gone from this one. It is naught but an empty husk...")
+ return
+
+ var/types = victim.find_type()
+ if ((!(types & TYPE_ORGANIC)) || ((types & TYPE_WIERD)))
+ //Invalid sacrifice. Display a message and return
+ speak_to(user, "This soulless automaton cannot satisfy our hunger. We yearn for life essence, it must have a soul.")
+ return
+
+ sacrifice = victim
+ sacrificer = user
+ //Sacrifice accepted, display message here
+ speak_to(user, "Your sacrifice has been deemed worthy, and accepted. End its life now, and liberate its soul, to seal our contract...")
+ sacrifice << span("danger", "You feel an invisible force grip your soul, as you're drawn inexorably towards the pylon. Every part of you screams to flee from here!")
+
+ if (istype(sacrifice.loc,/obj/item/weapon/holder))
+ var/obj/item/weapon/holder/H = sacrifice.loc
+ H.release_to_floor()
+ else
+ sacrifice.forceMove(get_turf(sacrifice))
+ pylonmode = 1
+ update_icon()
+ start_process()
+
+
+
+//Runs every proc while there's a pending sacrifice. This checks whether the sacrifice was killed or escaped
+/obj/structure/cult/pylon/proc/handle_sacrifice()
+ .=0 //Return value has 3 states.
+ //0 = waiting, the sacrifice is still alive
+ //1 = Finished, the sacrifice was killed, finalize the process and become a turret
+ //-1 = Escape: The sacrifice left the vicinity of the pylon, return to inert mode.
+
+ if (!sacrifice)
+ //If the sacrifice was deleted somehow, we cant know exactly what happened. We'll assume it escaped
+ .=-1
+
+ else if(get_dist(src, sacrifice) > 5)
+ //If the sacrifice gets more than 5 tiles away, it has escaped
+ .=-1
+ else if (sacrifice.stat == DEAD)
+ .=1
+
+ switch(.)
+ if (1)
+ finalize_sacrifice()
+ if (-1)
+ speak_to(sacrificer, "Fool! Your offering has escaped. Bring it back, or find us another...")
+ sacrifice = null
+ pylonmode = 0
+ update_icon()
+ if (sacrifice)
+ walk_to(sacrifice,0)
+ else
+ walk_towards(sacrifice,src, 10)
+
+/obj/structure/cult/pylon/proc/finalize_sacrifice()
+ sacrifice.visible_message(span("danger","\The [sacrifice]'s physical form unwinds as its soul is extracted from the remains, and drawn into the pylon!"))
+ if (istype(sacrifice.loc,/obj/item/weapon/holder))
+ var/obj/item/weapon/holder/H = sacrifice.loc
+ H.release_to_floor()
+ else
+ sacrifice.forceMove(get_turf(sacrifice)) //Make sure its on the floor before we gib it
+ pylonmode = 2
+ sacrifice.gib()
+
+ update_icon()
+
+
+//Called every process in turret mode, and also by chaining spawns
+/obj/structure/cult/pylon/proc/handle_firing()
+
+ if ((world.time < next_shot) || isbroken)
+ return
+ //Not ready to fire yet
+
+
+ var/list/stuffcache
+ //Stuffcache holds a list of things found by a dview call, so we only need to do it once per proc.
+
+
+ if (target && (target.stat != DEAD))
+ if (target.loc == last_target_loc)
+ //To minimise expensive DVIEW calls, if the target hasnt moved since the last shot we'll assume they're still in sight
+ //This could cause problems in some edge cases (like lowering firelocks or shutters without moving)
+ //But it has a major performance gain that makes it worth it
+ fire_at(target)
+ return
+ else
+ stuffcache = mobs_in_view(10, src)
+ //for (var/turf/T in stuffcache)
+ //new /obj/effect/testtrans(T)
+ if ((target in stuffcache) && isInSight(src, target))
+ for (var/mob/m in stuffcache)
+ fire_at(target)
+ return
+ else
+ target = null
+
+ //We may have already populated stuffcache this run, dont repeat work
+ if (!stuffcache)
+ stuffcache = mobs_in_view(10, src)
+
+ target = null //Either we lost a target or lack one
+ //for (var/turf/T in stuffcache)
+ //new /obj/effect/testtrans(T)
+
+ for (var/mob/living/L in stuffcache)
+ if (L == sacrificer)
+ continue
+ //A pylon won't shoot the person who created it, regardless of cult status.
+ //This is mainly for xenoarch antags
+
+ if (L.stat == DEAD)
+ continue
+ //No point shooting at corpses
+
+ if (iscult(L))
+ continue
+ //Pylon wont shoot at cultists or constructs
+
+ if (!isInSight(src, L))
+ continue
+
+ target = L
+
+
+ break
+
+ if (target)
+ fire_at(target)
+ else
+ notarget++
+ if (notarget > 60 || process_interval > 1)
+ notarget = 0
+ reconsider_interval()
+
+
+/obj/structure/cult/pylon/proc/fire_at(var/atom/target)
+ //Only store loc if target is on a turf. Otherwise this bugs out with people in exosuits
+ if (istype(target.loc, /turf))
+ last_target_loc = target.loc
+
+ process_interval = 1 //Instantly wake up if we found a target
+ var/obj/item/projectile/beam/cult/A
+ if (empowered > 0)
+ A = new /obj/item/projectile/beam/cult/heavy(loc)
+ empowered = max(0, empowered-1)
+ playsound(loc, 'sound/weapons/laserdeep.ogg', 100, 1)
+ if (empowered <= 0)
+ update_icon()
+ else
+ A = new /obj/item/projectile/beam/cult(loc)
+ playsound(loc, 'sound/weapons/laserdeep.ogg', 65, 1)
+ A.ignore = sacrificer
+ A.launch(target)
+ next_shot = world.time + shot_delay
+ spawn(shot_delay+1)
+ handle_firing()
+
+
/obj/structure/cult/pylon/attack_hand(mob/M as mob)
- attackpylon(M, 5)
+ if (M.a_intent == "help")
+ M << "The pylon feels warm to the touch...."
+ else
+ attackpylon(M, 4, M)
/obj/structure/cult/pylon/attack_generic(var/mob/user, var/damage)
- attackpylon(user, damage)
+ user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
+
+ //Artificiers maintain pylons
+ if(istype(user, /mob/living/simple_animal/construct))
+ var/mob/living/simple_animal/construct/C = user
+ if (C.can_repair)
+ repair(user)
+ return
+ attackpylon(user, damage, user)
/obj/structure/cult/pylon/attackby(obj/item/W as obj, mob/user as mob)
- attackpylon(user, W.force)
+ if (istype(W, /obj/item/weapon/holder))
+ var/obj/item/weapon/holder/H = W
+ if (H.contained)
+ present_sacrifice(user, H.contained)
+ return
-/obj/structure/cult/pylon/proc/attackpylon(mob/user as mob, var/damage)
- user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
- if(!isbroken)
- if(prob(1+ damage * 5))
- user.visible_message(
- "[user] smashed the pylon!",
- "You hit the pylon, and its crystal breaks apart!",
- "You hear a tinkle of crystal shards"
+ attackpylon(user, W.force, W)
+
+
+//Mousedrop so that constructs can drag mice out of maintenance to make turrets
+/obj/structure/cult/pylon/MouseDrop_T(var/atom/movable/C, mob/user)
+ if (istype(C, /mob/living))
+ present_sacrifice(user, C)
+ return
+ return ..()
+
+/obj/structure/cult/pylon/bullet_act(var/obj/item/projectile/Proj)
+ attackpylon(user, Proj.damage, Proj)
+
+//Explosions will usually cause instant shattering, or heavy damage
+//Class 3 or lower blast is sometimes survivable. 2 or higher will always shatter
+/obj/structure/cult/pylon/ex_act(var/severity)
+ if (severity > 0)
+ attackpylon(null, (rand(200,400)/severity), null)
+
+/obj/structure/cult/pylon/proc/attackpylon(mob/user as mob, var/damage, var/source)
+ var/ranged = 0
+ if (user)
+ user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
+ if (istype(source, /obj/item))
+ var/obj/item/I = source
+ if (I.damtype != BRUTE)
+ user << "You swing at the pylon to no effect."
+ return
+
+ if (istype(source, /obj/item/projectile))
+ if (istype(source, /obj/item/projectile/beam/cult))
+ return //No feedback loops
+ var/obj/item/projectile/proj = source
+ if (proj.damage_type == BURN)
+ if (empowered <= 0)
+ visible_message(
+ "The beam refracts inside the pylon, splitting into an indistinct violet glow. The crystal takes on a new, more ominous aura!"
)
+ empowered += damage*0.3
+ //When shot with a laser, the pylon absorbs the beam, becoming empowered for a while, glowing brighter
+ // and firing more powerful blasts which have some armor penetration
+ // Using lasers to empower a defensive pylon yields more total damage than directly shooting your enemies
+
+ start_process()
+ update_icon()
+ return
+ else if (proj.damage_type != BRUTE)
+ return
+ ranged = 1
+
+ if (!damage)
+ return
+
+ damagetaken += damage
+
+ if(!isbroken)
+ if (user)
user.do_attack_animation(src)
- playsound(get_turf(src), 'sound/effects/Glassbr3.ogg', 75, 1)
- isbroken = 1
- density = 0
- icon_state = "pylon-broken"
- set_light(0)
+ if(prob(damagetaken*0.5))
+ shatter()
else
- user << "You hit the pylon!"
+ if (user && !ranged)
+ user << "You hit the pylon!"
playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1)
else
- if(prob(damage * 2))
- user << "You pulverize what was left of the pylon!"
+ if(prob(damagetaken))
+ if (user)
+ user << "You pulverize what was left of the pylon!"
qdel(src)
- else
+ else if (user && !ranged)
user << "You hit the pylon!"
playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1)
+ start_process()
+
+/obj/structure/cult/pylon/proc/shatter()
+ visible_message(
+ "The pylon shatters into shards of crystal!",
+ "You hear a tinkle of crystal shards"
+ )
+ playsound(get_turf(src), 'sound/effects/Glassbr3.ogg', 75, 1)
+ isbroken = 1
+ if (pylonmode == 2)
+ //If the pylon had a soul in it then it plays a creepy evil sound as the soul is released
+ var/possibles = list('sound/hallucinations/far_noise.ogg',
+ 'sound/hallucinations/growl3.ogg',
+ 'sound/hallucinations/veryfar_noise.ogg',
+ 'sound/hallucinations/wail.ogg',
+ 'sound/voice/hiss5.ogg')
+ playsound(get_turf(src), pick(possibles), 50, 1)
+
+ pylonmode = 0 //A broken pylon loses its soul. Even if repaired it will need a new sacrifice to re-empower it
+
+ //Make sure we stop it from firing
+ target = null
+ sacrificer = null
+ notarget = 0
+ last_target_loc = null
+ process_interval = 1
+ //It will stop processing after the next check, start of the next process
+
+ empowered = 0
+ density = 0
+ update_icon()
+
+
/obj/structure/cult/pylon/proc/repair(mob/user as mob)
if(isbroken)
- user << "You repair the pylon."
+ if(user)
+ user << span("notice","You weave forgotten magic, summoning the shards of the crystal and knitting them anew, until it hovers flawless once more.")
isbroken = 0
density = 1
- icon_state = "pylon"
- set_light(5)
+ else if (damagetaken > 0)
+ user << span("notice","You meld the crystal lattice back into integrity, sealing over the cracks until they never were.")
+ else
+ user << span("notice","The crystal lights up at your touch.")
+
+ process_interval = 1 //Wake up the crystal
+ notarget = 0
+ damagetaken = 0
+ update_icon()
+
+
+/obj/structure/cult/pylon/update_icon()
+ overlays.Cut()
+ if (pylonmode == 2)
+ anchored = 1
+ if (empowered > 0)
+ overlays += "crystal_overcharge"
+ set_light(7, 3, l_color = "#a160bf")
+ else
+ set_light(6, 3, l_color = "#3e0000")
+ overlays += "crystal_turret"
+ else if (!isbroken)
+ set_light(5, 2, l_color = "#3e0000")
+ overlays += "crystal_idle"
+ if (pylonmode == 1)
+ anchored = 1
+ else
+ anchored = 0
+ else
+ anchored = 0
+ set_light(0)
+
+
+
+//============================================
/obj/structure/cult/tome
name = "Desk"
desc = "A desk covered in arcane manuscripts and tomes in unknown languages. Looking at the text makes your skin crawl"
@@ -144,7 +650,7 @@
if(M.has_brain_worms())
return //Borer stuff - RR
- if(iscultist(M)) return
+ if(iscult(M)) return
if(!ishuman(M) && !isrobot(M)) return
M.transforming = 1
@@ -174,3 +680,12 @@
new_mob.key = M.key
new_mob << "Your form morphs into that of a corgi." //Because we don't have cluwnes
+
+/obj/effect/testtrans
+ icon = 'icons/obj/cult.dmi'
+ icon_state = "tt"
+
+/obj/effect/testtrans/New()
+ ..()
+ spawn(10)
+ qdel(src)
\ No newline at end of file
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index 71de8a75d2e..c093642416d 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -283,7 +283,7 @@ var/global/list/additional_antag_types = list()
/datum/game_mode/proc/declare_completion()
var/is_antag_mode = (antag_templates && antag_templates.len)
- var/discord_text = "@subscribers A round of **[name]** has ended! \[Game ID: [game_id]\]\n\n"
+ var/discord_text = "A round of **[name]** has ended! \[Game ID: [game_id]\]\n\n"
check_victory()
if(is_antag_mode)
sleep(10)
@@ -298,7 +298,7 @@ var/global/list/additional_antag_types = list()
sleep(10)
print_ownerless_uplinks()
- discord_bot.send_to_announce(discord_text)
+ discord_bot.send_to_announce(discord_text, 1)
discord_text = ""
var/clients = 0
diff --git a/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_networking.dm b/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_networking.dm
index 3bf6ab01108..046da249b1d 100644
--- a/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_networking.dm
+++ b/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_networking.dm
@@ -111,6 +111,13 @@
return
log_ability_use(user, "elite encryption hack (SUCCESS - title: [title])")
command_announcement.Announce(text, title)
+ for (var/obj/machinery/computer/communications/C in machines)
+ if(! (C.stat & (BROKEN|NOPOWER) ) )
+ var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( C.loc )
+ P.name = "[command_name()] Update"
+ P.info = replacetext(text, "\n", " ")
+ P.update_space(P.info)
+ P.update_icon()
/datum/game_mode/malfunction/verb/elite_encryption_hack()
set category = "Software"
diff --git a/code/game/gamemodes/vampire/vampire_powers.dm b/code/game/gamemodes/vampire/vampire_powers.dm
index e483bb0c30a..341d2ba8e1d 100644
--- a/code/game/gamemodes/vampire/vampire_powers.dm
+++ b/code/game/gamemodes/vampire/vampire_powers.dm
@@ -850,6 +850,10 @@
if (alert(src, choice_text, "Choices", "Yes", "No") == "No")
src << "[denial_response]"
return
+
+ vampire_thrall.remove_antagonist(T.mind, 0, 0)
+ qdel(draining_vamp)
+ draining_vamp = null
else
src << "You feel corruption running in [T.name]'s blood. Much like yourself, \he[T] is already a spawn of the Veil, and cannot be Embraced."
return
diff --git a/code/game/jobs/job/captain.dm b/code/game/jobs/job/captain.dm
index 82858a19d42..02e8eba06a5 100644
--- a/code/game/jobs/job/captain.dm
+++ b/code/game/jobs/job/captain.dm
@@ -29,13 +29,12 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1)
if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_cap(H), slot_back)
if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back)
if(5) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/duffel/cap(H), slot_back)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/captain(H), slot_w_uniform)
+ H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/captain(H), slot_w_uniform)
if(H.age>49)
- // Since we can have something other than the default uniform at this
+ // Since we can have something other than the default uniform at this
// point, check if we can actually attach the medal
var/obj/item/clothing/uniform = H.w_uniform
var/obj/item/clothing/accessory/medal/gold/captain/medal = new()
-
if(uniform && uniform.can_attach_accessory(medal))
uniform.attach_accessory(null, medal)
else
diff --git a/code/game/jobs/job/civilian.dm b/code/game/jobs/job/civilian.dm
index a1be098d394..36634a74d08 100644
--- a/code/game/jobs/job/civilian.dm
+++ b/code/game/jobs/job/civilian.dm
@@ -80,7 +80,12 @@
H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_service(H), slot_l_ear)
H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/hydroponics(H), slot_w_uniform)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/clothing/gloves/botanic_leather(H), slot_gloves)
+ if(istajara(H))
+ H.equip_to_slot_or_del(new /obj/item/clothing/gloves/botanic_leather/tajara(H), slot_gloves)
+ if(isunathi(H))
+ H.equip_to_slot_or_del(new /obj/item/clothing/gloves/botanic_leather/unathi(H), slot_gloves)
+ else
+ H.equip_to_slot_or_del(new /obj/item/clothing/gloves/botanic_leather(H), slot_gloves)
H.equip_to_slot_or_del(new /obj/item/clothing/suit/apron(H), slot_wear_suit)
H.equip_to_slot_or_del(new /obj/item/device/analyzer/plant_analyzer(H), slot_s_store)
H.equip_to_slot_or_del(new /obj/item/device/pda/botanist(H), slot_belt)
@@ -285,6 +290,8 @@
if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_norm(H), slot_back)
if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back)
if(5) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/duffel(H), slot_back)
+
+ H.implant_loyalty(H)
H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/internalaffairs(H), slot_w_uniform)
H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/toggle/internalaffairs(H), slot_wear_suit)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(H), slot_shoes)
@@ -292,7 +299,5 @@
H.equip_to_slot_or_del(new /obj/item/device/pda/lawyer(H), slot_belt)
H.equip_to_slot_or_del(new /obj/item/weapon/storage/briefcase(H), slot_l_hand)
- H.implant_loyalty(H)
-
return 1
diff --git a/code/game/jobs/job/security.dm b/code/game/jobs/job/security.dm
index abb3a6c68f0..77c6dc7ec8d 100644
--- a/code/game/jobs/job/security.dm
+++ b/code/game/jobs/job/security.dm
@@ -33,15 +33,13 @@
H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/head_of_security(H), slot_w_uniform)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/jackboots(H), slot_shoes)
H.equip_to_slot_or_del(new /obj/item/device/pda/heads/hos(H), slot_belt)
- if(H.species.name == "Tajara")
+ if(istajara(H))
H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black/tajara(H), slot_gloves)
- if(H.species.name == "Unathi")
+ if(isunathi(H))
H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black/unathi(H), slot_gloves)
else
H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(H), slot_gloves)
-// H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas(H), slot_wear_mask) //Grab one from the armory you donk
H.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/sechud(H), slot_glasses)
- H.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/gun(H), slot_s_store)
if(H.backbag == 1)
H.equip_to_slot_or_del(new /obj/item/weapon/handcuffs(H), slot_l_store)
else
@@ -77,9 +75,9 @@
H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/warden(H), slot_w_uniform)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/jackboots(H), slot_shoes)
H.equip_to_slot_or_del(new /obj/item/device/pda/warden(H), slot_belt)
- if(H.species.name == "Tajara")
+ if(istajara(H))
H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black/tajara(H), slot_gloves)
- if(H.species.name == "Unathi")
+ if(isunathi(H))
H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black/unathi(H), slot_gloves)
else
H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(H), slot_gloves)
@@ -120,9 +118,9 @@
H.equip_to_slot_or_del(new /obj/item/clothing/under/det(H), slot_w_uniform)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/laceup(H), slot_shoes)
H.equip_to_slot_or_del(new /obj/item/device/pda/detective(H), slot_belt)
- if(H.species.name == "Tajara")
+ if(istajara(H))
H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black/tajara(H), slot_gloves)
- if(H.species.name == "Unathi")
+ if(isunathi(H))
H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black/unathi(H), slot_gloves)
else
H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(H), slot_gloves)
diff --git a/code/game/machinery/abstract/abstract.dm b/code/game/machinery/abstract/abstract.dm
new file mode 100644
index 00000000000..675113713d3
--- /dev/null
+++ b/code/game/machinery/abstract/abstract.dm
@@ -0,0 +1,47 @@
+/*
+ - Abstract machinery -
+
+ Pretty much designed for whenever you want something that is not a machine to interact with the power grid.
+ Better to use one of these to be notified of power changes than poll with process().
+
+*/
+
+/obj/machinery/abstract
+ name = "impossible device"
+ desc = "No matter how hard you look at it, you have no idea what it is. (please inform coders if you see this)"
+ simulated = FALSE
+ anchored = 1
+ var/should_process = FALSE
+ mouse_opacity = 0
+
+/obj/machinery/abstract/attack_ai(mob/user as mob)
+ return
+
+/obj/machinery/abstract/attack_hand(mob/user as mob)
+ return
+
+/obj/machinery/abstract/emp_act(severity)
+ return // No EMPing these.
+
+/obj/machinery/abstract/ex_act(severity)
+ return
+
+/obj/machinery/abstract/tesla_act()
+ return
+
+/obj/machinery/abstract/singularity_act()
+ return
+
+/obj/machinery/abstract/singularity_pull()
+ return
+
+/obj/machinery/abstract/singuloCanEat()
+ return FALSE
+
+/obj/machinery/abstract/operable(additional_flags = 0)
+ return TRUE
+
+/obj/machinery/abstract/get_process_type()
+ . = ..()
+ if (!should_process)
+ . &= ~M_PROCESSES
diff --git a/code/game/machinery/abstract/intercom_listener.dm b/code/game/machinery/abstract/intercom_listener.dm
new file mode 100644
index 00000000000..a344eeeb9ae
--- /dev/null
+++ b/code/game/machinery/abstract/intercom_listener.dm
@@ -0,0 +1,25 @@
+/obj/machinery/abstract/intercom_listener
+ name = "intercom power interface"
+ desc = "You shouldn't see this."
+ power_channel = EQUIP
+
+ var/obj/item/device/radio/intercom/master
+
+/obj/machinery/abstract/intercom_listener/New(atom/loc, obj/item/device/radio/intercom/owner)
+ if (QDELETED(owner))
+ warning("intercom_listener created with QDELETED intercom!")
+ qdel(src)
+ else
+ master = owner
+
+/obj/machinery/abstract/intercom_listener/Destroy()
+ master = null
+ return ..()
+
+/obj/machinery/abstract/intercom_listener/power_change()
+ if (master)
+ var/state = powered(power_channel)
+ master.power_change(state)
+ else
+ warning("intercom_listener got power_change but has no master!")
+ qdel(src)
diff --git a/code/game/machinery/computer/RCON_Console.dm b/code/game/machinery/computer/RCON_Console.dm
index ec0d0f3c7d5..3d45813923d 100644
--- a/code/game/machinery/computer/RCON_Console.dm
+++ b/code/game/machinery/computer/RCON_Console.dm
@@ -40,4 +40,4 @@
/obj/machinery/computer/rcon/update_icon()
..()
if(is_operable())
- overlays += image('icons/obj/computer.dmi', "ai-fixer-empty", overlay_layer)
+ holographic_overlay(src, src.icon, "ai-fixer-empty")
diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm
index cc3fb188f9b..30684a17c4b 100644
--- a/code/game/machinery/computer/camera.dm
+++ b/code/game/machinery/computer/camera.dm
@@ -215,6 +215,7 @@
network = list(NETWORK_THUNDER)
density = 0
circuit = null
+ is_holographic = FALSE
/obj/machinery/computer/security/telescreen/entertainment
name = "entertainment monitor"
@@ -260,6 +261,7 @@
icon_screen = "syndicam"
network = list(NETWORK_MERCENARY)
circuit = null
+ is_holographic = FALSE // I mean, it is, but the holo effect looks terrible with the current merc shuttle floor.
/obj/machinery/computer/security/nuclear/New()
..()
diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm
index 66ed07fb01f..775b3aa937f 100644
--- a/code/game/machinery/computer/computer.dm
+++ b/code/game/machinery/computer/computer.dm
@@ -14,6 +14,7 @@
var/light_range_on = 2
var/light_power_on = 1
var/overlay_layer
+ var/is_holographic = TRUE
/obj/machinery/computer/New()
overlay_layer = layer
@@ -64,8 +65,10 @@
if(stat & BROKEN)
overlays += image(icon,"[icon_state]_broken", overlay_layer)
+ else if (is_holographic)
+ holographic_overlay(src, src.icon, icon_screen)
else
- overlays += image(icon,icon_screen, overlay_layer)
+ overlays += image(icon, icon_screen, overlay_layer)
/obj/machinery/computer/power_change()
..()
diff --git a/code/game/machinery/computer/guestpass.dm b/code/game/machinery/computer/guestpass.dm
index f9c7be55df0..c63134fe0c2 100644
--- a/code/game/machinery/computer/guestpass.dm
+++ b/code/game/machinery/computer/guestpass.dm
@@ -47,6 +47,7 @@
light_color = LIGHT_COLOR_BLUE
icon_screen = "pass"
+ is_holographic = FALSE
density = 0
var/obj/item/weapon/card/id/giver
diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm
index 57c19f9a318..af4983258ee 100644
--- a/code/game/machinery/computer/medical.dm
+++ b/code/game/machinery/computer/medical.dm
@@ -16,7 +16,6 @@
var/datum/data/record/active2 = null
var/a_id = null
var/temp = null
- //var/printing = null
/obj/machinery/computer/med_data/AltClick(var/mob/user)
eject_id()
@@ -562,3 +561,4 @@
icon_state = "medlaptop0"
icon_screen = "medlaptop"
+ is_holographic = FALSE
diff --git a/code/game/machinery/computer/message.dm b/code/game/machinery/computer/message.dm
index c8ddad2a140..b8f1638c4bd 100644
--- a/code/game/machinery/computer/message.dm
+++ b/code/game/machinery/computer/message.dm
@@ -33,6 +33,12 @@
..()
spark_system = bind_spark(src, 5)
+/obj/machinery/computer/message_monitor/Destroy()
+ QDEL_NULL(spark_system)
+ linkedServer = null
+ customrecepient = null
+ return ..()
+
/obj/machinery/computer/message_monitor/attackby(obj/item/weapon/O as obj, mob/living/user as mob)
if(stat & (NOPOWER|BROKEN))
..()
diff --git a/code/game/machinery/computer/shuttle.dm b/code/game/machinery/computer/shuttle.dm
index 735f61947a2..7f6152bdd6d 100644
--- a/code/game/machinery/computer/shuttle.dm
+++ b/code/game/machinery/computer/shuttle.dm
@@ -2,6 +2,7 @@
name = "Shuttle"
desc = "For shuttle control."
+ is_holographic = FALSE
icon_screen = "shuttle"
light_color = "#00ffff"
var/auth_need = 3.0
diff --git a/code/game/machinery/computer/skills.dm b/code/game/machinery/computer/skills.dm
index 4e20655ec88..f60ab34fcb0 100644
--- a/code/game/machinery/computer/skills.dm
+++ b/code/game/machinery/computer/skills.dm
@@ -16,7 +16,7 @@
var/datum/data/record/active1 = null
var/a_id = null
var/temp = null
- //var/printing = null
+ is_holographic = FALSE
var/can_change_id = 0
var/list/Perp
var/tempname = null
diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm
index 36dd5e90b43..275ebce38d2 100644
--- a/code/game/machinery/deployable.dm
+++ b/code/game/machinery/deployable.dm
@@ -261,6 +261,6 @@ for reference:
else if (src.emagged == 1)
src.emagged = 2
user << "You short out the anchoring mechanism on \the [src]."
- spark(src, 2, 1)
+ spark(src, 2, alldirs)
visible_message("BZZzZZzZZzZT")
return 1
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index 391d885fccb..b4118abd48a 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -30,8 +30,7 @@
var/obj/item/stack/material/steel/repairing
var/block_air_zones = 1 //If set, air zones cannot merge across the door even when it is opened.
var/open_duration = 150//How long it stays open
- var/datum/scheduled_task/close_task
- var/datum/scheduled_task/hatch_task
+
var/hashatch = 0//If 1, this door has hatches, and certain small creatures can move through them without opening the door
var/hatchstate = 0//0: closed, 1: open
@@ -229,7 +228,7 @@
switch (Proj.damage_type)
if(BRUTE)
new /obj/item/stack/material/steel(src.loc, 2)
- getFromPool(/obj/item/stack/rods, list(src.loc, 3))
+ getFromPool(/obj/item/stack/rods, src.loc, 3)
if(BURN)
new /obj/effect/decal/cleanable/ash(src.loc) // Turn it to ashes!
qdel(src)
diff --git a/code/game/machinery/floodlight.dm b/code/game/machinery/floodlight.dm
index db1e0ff71f5..abb2cc6f8be 100644
--- a/code/game/machinery/floodlight.dm
+++ b/code/game/machinery/floodlight.dm
@@ -33,10 +33,10 @@
// If the cell is almost empty rarely "flicker" the light. Aesthetic only.
if((cell.percent() < 10) && prob(5))
- set_light(brightness_on/2, brightness_on/4)
+ set_light(brightness_on/2, 0.5)
spawn(20)
if(on)
- set_light(brightness_on, brightness_on/2)
+ set_light(brightness_on, 1)
cell.use(use*CELLRATE)
@@ -49,7 +49,7 @@
return 0
on = 1
- set_light(brightness_on, brightness_on / 2)
+ set_light(brightness_on, 1)
update_icon()
if(loud)
visible_message("\The [src] turns on.")
@@ -57,7 +57,7 @@
/obj/machinery/floodlight/proc/turn_off(var/loud = 0)
on = 0
- set_light(0, 0)
+ set_light(0)
update_icon()
if(loud)
visible_message("\The [src] shuts down.")
diff --git a/code/game/machinery/igniter.dm b/code/game/machinery/igniter.dm
index c4169470fde..4c4c40ec7c7 100755
--- a/code/game/machinery/igniter.dm
+++ b/code/game/machinery/igniter.dm
@@ -126,7 +126,7 @@
flick("migniter-spark", src)
- spark(src, 2, 1)
+ spark(src, 2, alldirs)
src.last_spark = world.time
use_power(1000)
var/turf/location = src.loc
diff --git a/code/game/machinery/kitchen/cooking_machines/_appliance.dm b/code/game/machinery/kitchen/cooking_machines/_appliance.dm
index fab66c20872..29d727f1d19 100644
--- a/code/game/machinery/kitchen/cooking_machines/_appliance.dm
+++ b/code/game/machinery/kitchen/cooking_machines/_appliance.dm
@@ -389,14 +389,15 @@
CI.result_type = 4//Recipe type, a specific recipe will transform the ingredients into a new food
var/list/results = recipe.make_food(C)
- var/atom/temp = new /atom //To prevent infinite loops, all results will be moved into a temporary location so they're not considered as inputs for other recipes
+ var/obj/temp = new /obj(src) //To prevent infinite loops, all results will be moved into a temporary location so they're not considered as inputs for other recipes
for (var/atom/movable/AM in results)
AM.loc = temp
//making multiple copies of a recipe from one container. For example, tons of fries
while (select_recipe(available_recipes,C) == recipe)
- var/list/TR = recipe.make_food(C)
+ var/list/TR = list()
+ TR.Add(recipe.make_food(C))
for (var/atom/movable/AM in TR) //Move results to buffer
AM.loc = temp
results.Add(TR)
@@ -636,7 +637,7 @@
//var/obj/object
var/max_cookwork
var/cookwork
- var/overcook_mult = 2
+ var/overcook_mult = 3
var/result_type = 0
var/obj/item/weapon/reagent_containers/cooking_container/container = null
var/combine_target = null
diff --git a/code/game/machinery/kitchen/cooking_machines/_cooker.dm b/code/game/machinery/kitchen/cooking_machines/_cooker.dm
index d8bfd43dabe..18089e06572 100644
--- a/code/game/machinery/kitchen/cooking_machines/_cooker.dm
+++ b/code/game/machinery/kitchen/cooking_machines/_cooker.dm
@@ -16,7 +16,7 @@
if (.)//no need to duplicate adjacency check
if (!stat)
if (temperature < min_temp)
- user << span("warning", "It is heating up.")
+ user << span("warning", "The [src] is still heating up and is too cold to cook anything yet.")
else
user << span("notice", "It is running at [round(get_efficiency(), 0.1)]% efficiency!")
user << "Temperature: [round(temperature - T0C, 0.1)]C / [round(optimal_temp - T0C, 0.1)]C"
@@ -121,9 +121,10 @@
//Cookers do differently, they use containers
/obj/machinery/appliance/cooker/has_space(var/obj/item/I)
- if (istype(I, /obj/item/weapon/reagent_containers/cooking_container) && cooking_objs.len < max_contents)
+ if (istype(I, /obj/item/weapon/reagent_containers/cooking_container))
//Containers can go into an empty slot
- return 1
+ if (cooking_objs.len < max_contents)
+ return 1
else
@@ -137,6 +138,6 @@
/obj/machinery/appliance/cooker/add_content(var/obj/item/I, var/mob/user)
var/datum/cooking_item/CI = ..()
- if (CI.combine_target)
+ if (CI && CI.combine_target)
user << "The [I] will be used to make a [selected_option]. Output selection is returned to default for future items."
selected_option = null
\ No newline at end of file
diff --git a/code/game/machinery/kitchen/cooking_machines/container.dm b/code/game/machinery/kitchen/cooking_machines/container.dm
index f9be08952ae..f1decf8c811 100644
--- a/code/game/machinery/kitchen/cooking_machines/container.dm
+++ b/code/game/machinery/kitchen/cooking_machines/container.dm
@@ -8,6 +8,10 @@
var/max_space = 20//Maximum sum of w-classes of foods in this container at once
var/max_reagents = 80//Maximum units of reagents
+ var/list/insertable = list(/obj/item/weapon/reagent_containers/food/snacks,
+ /obj/item/weapon/holder,
+ /obj/item/weapon/paper)
+
/obj/item/weapon/reagent_containers/cooking_container/New()
..()
create_reagents(max_reagents)
@@ -26,15 +30,17 @@
/obj/item/weapon/reagent_containers/cooking_container/attackby(var/obj/item/I as obj, var/mob/user as mob)
- if (istype(I, /obj/item/weapon/reagent_containers/food/snacks))
- if (!can_fit(I))
- user << span("warning","There's no more space in the [src] for that!")
- return 0
+ for (var/possible_type in insertable)
+ if (istype(I, possible_type))
+ if (!can_fit(I))
+ user << span("warning","There's no more space in the [src] for that!")
+ return 0
- if(!user.unEquip(I))
+ if(!user.unEquip(I))
+ return
+ I.forceMove(src)
+ user << span("notice", "You put the [I] into the [src]")
return
- I.forceMove(src)
- user << span("notice", "You put the [I] into the [src]")
/obj/item/weapon/reagent_containers/cooking_container/verb/empty()
set src in view()
diff --git a/code/game/machinery/kitchen/cooking_machines/oven.dm b/code/game/machinery/kitchen/cooking_machines/oven.dm
index 48e3364c7ee..c741535df3b 100644
--- a/code/game/machinery/kitchen/cooking_machines/oven.dm
+++ b/code/game/machinery/kitchen/cooking_machines/oven.dm
@@ -67,7 +67,7 @@
loss = (active_power_usage / resistance)*0.5
else
open = 1
- loss = (active_power_usage / resistance)*10
+ loss = (active_power_usage / resistance)*6
//When the oven door is opened, heat is lost MUCH faster
playsound(src, 'sound/machines/hatch_open.ogg', 20, 1)
diff --git a/code/game/machinery/kitchen/microwave.dm b/code/game/machinery/kitchen/microwave.dm
index 05a1f0f3bba..c9763016618 100644
--- a/code/game/machinery/kitchen/microwave.dm
+++ b/code/game/machinery/kitchen/microwave.dm
@@ -16,7 +16,7 @@
var/global/list/datum/recipe/available_recipes // List of the recipes you can use
var/global/list/acceptable_items // List of the items you can put in
var/global/list/acceptable_reagents // List of the reagents you can put in
- var/global/max_n_of_items = 0
+ var/global/max_n_of_items = 20
var/appliancetype = MICROWAVE
// see code/modules/food/recipes_microwave.dm for recipes
@@ -44,8 +44,6 @@
acceptable_items |= item
for (var/reagent in recipe.reagents)
acceptable_reagents |= reagent
- if (recipe.items)
- max_n_of_items = max(max_n_of_items,recipe.items.len)
// This will do until I can think of a fun recipe to use dionaea in -
// will also allow anything using the holder item to be microwaved into
// impure carbon. ~Z
@@ -295,13 +293,28 @@
var/result = recipe.result
var/valid = 1
var/list/cooked_items = list()
+ var/obj/temp = new /obj(src) //To prevent infinite loops, all results will be moved into a temporary location so they're not considered as inputs for other recipes
while(valid)
- cooked_items += recipe.make_food(src)
+ var/list/things = list()
+ things.Add(recipe.make_food(src))
+ cooked_items += things
+ //Move cooked things to the buffer so they're not considered as ingredients
+ for (var/atom/movable/AM in things)
+ AM.loc = temp
+
valid = 0
recipe = select_recipe(available_recipes,src)
if (recipe && recipe.result == result)
+ sleep(2)
valid = 1
+ for (var/r in cooked_items)
+ var/atom/movable/R = r
+ R.loc = src //Move everything from the buffer back to the container
+
+ qdel(temp)//Delete buffer object
+ temp = null
+
//Any leftover reagents are divided amongst the foods
var/total = reagents.total_volume
for (var/obj/item/weapon/reagent_containers/food/snacks/S in cooked_items)
@@ -312,6 +325,7 @@
dispose(0) //clear out anything left
stop()
+
return
/obj/machinery/microwave/proc/wzhzhzh(var/seconds as num) // Whoever named this proc is fucking literally Satan. ~ Z
diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm
index 640e5cfa2f8..e83fba6d060 100644
--- a/code/game/machinery/teleporter.dm
+++ b/code/game/machinery/teleporter.dm
@@ -179,6 +179,11 @@
underlays += image('icons/obj/stationobjs.dmi', icon_state = "tele-wires")
spark_system = bind_spark(src, 5, alldirs)
+/obj/machinery/teleport/hub/Destroy()
+ QDEL_NULL(spark_system)
+ com = null
+ return ..()
+
/obj/machinery/teleport/hub/Bumped(M as mob|obj)
spawn()
if (src.icon_state == "tele1")
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index bc658b7faf8..ee25385e2a8 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -237,7 +237,7 @@
anchored = !anchored
return
- else
+ else if (!is_borg_item(W))
for(var/datum/data/vending_product/R in product_records)
if(istype(W, R.product_path))
@@ -245,6 +245,8 @@
qdel(W)
return
..()
+ else
+ ..()
/**
* Receive payment with cashmoney.
@@ -722,7 +724,7 @@
vend_power_usage = 85000 //85 kJ to heat a 250 mL cup of coffee
products = list(/obj/item/weapon/reagent_containers/food/drinks/coffee = 25,/obj/item/weapon/reagent_containers/food/drinks/tea = 25,/obj/item/weapon/reagent_containers/food/drinks/h_chocolate = 25)
contraband = list(/obj/item/weapon/reagent_containers/food/drinks/ice = 10)
- prices = list(/obj/item/weapon/reagent_containers/food/drinks/coffee = 30, /obj/item/weapon/reagent_containers/food/drinks/tea = 30, /obj/item/weapon/reagent_containers/food/drinks/h_chocolate = 32)
+ prices = list(/obj/item/weapon/reagent_containers/food/drinks/coffee = 20, /obj/item/weapon/reagent_containers/food/drinks/tea = 20, /obj/item/weapon/reagent_containers/food/drinks/h_chocolate = 22)
@@ -738,10 +740,10 @@
/obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers = 6, /obj/item/weapon/reagent_containers/food/snacks/tastybread = 6, /obj/item/weapon/reagent_containers/food/snacks/skrellsnacks = 3,
/obj/item/weapon/reagent_containers/food/snacks/meatsnack = 2, /obj/item/weapon/reagent_containers/food/snacks/maps = 2, /obj/item/weapon/reagent_containers/food/snacks/nathisnack = 2)
contraband = list(/obj/item/weapon/reagent_containers/food/snacks/syndicake = 6)
- prices = list(/obj/item/weapon/reagent_containers/food/snacks/candy = 25,/obj/item/weapon/reagent_containers/food/drinks/dry_ramen = 30,/obj/item/weapon/reagent_containers/food/snacks/chips = 27,
- /obj/item/weapon/reagent_containers/food/snacks/sosjerky = 30,/obj/item/weapon/reagent_containers/food/snacks/no_raisin = 22,/obj/item/weapon/reagent_containers/food/snacks/spacetwinkie = 25,
- /obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers = 25, /obj/item/weapon/reagent_containers/food/snacks/tastybread = 28, /obj/item/weapon/reagent_containers/food/snacks/skrellsnacks = 50,
- /obj/item/weapon/reagent_containers/food/snacks/meatsnack = 32, /obj/item/weapon/reagent_containers/food/snacks/maps = 33, /obj/item/weapon/reagent_containers/food/snacks/nathisnack = 34)
+ prices = list(/obj/item/weapon/reagent_containers/food/snacks/candy = 15,/obj/item/weapon/reagent_containers/food/drinks/dry_ramen = 20,/obj/item/weapon/reagent_containers/food/snacks/chips = 17,
+ /obj/item/weapon/reagent_containers/food/snacks/sosjerky = 20,/obj/item/weapon/reagent_containers/food/snacks/no_raisin = 12,/obj/item/weapon/reagent_containers/food/snacks/spacetwinkie = 15,
+ /obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers = 15, /obj/item/weapon/reagent_containers/food/snacks/tastybread = 18, /obj/item/weapon/reagent_containers/food/snacks/skrellsnacks = 40,
+ /obj/item/weapon/reagent_containers/food/snacks/meatsnack = 22, /obj/item/weapon/reagent_containers/food/snacks/maps = 23, /obj/item/weapon/reagent_containers/food/snacks/nathisnack = 24)
/obj/machinery/vending/cola
@@ -755,10 +757,10 @@
/obj/item/weapon/reagent_containers/food/drinks/cans/waterbottle = 10,/obj/item/weapon/reagent_containers/food/drinks/cans/space_up = 10,
/obj/item/weapon/reagent_containers/food/drinks/cans/iced_tea = 10, /obj/item/weapon/reagent_containers/food/drinks/cans/grape_juice = 10)
contraband = list(/obj/item/weapon/reagent_containers/food/drinks/cans/thirteenloko = 5, /obj/item/weapon/reagent_containers/food/snacks/liquidfood = 6)
- prices = list(/obj/item/weapon/reagent_containers/food/drinks/cans/cola = 25,/obj/item/weapon/reagent_containers/food/drinks/cans/space_mountain_wind = 21,
- /obj/item/weapon/reagent_containers/food/drinks/cans/dr_gibb = 26,/obj/item/weapon/reagent_containers/food/drinks/cans/starkist = 25,
- /obj/item/weapon/reagent_containers/food/drinks/cans/waterbottle = 22,/obj/item/weapon/reagent_containers/food/drinks/cans/space_up = 25,
- /obj/item/weapon/reagent_containers/food/drinks/cans/iced_tea = 23,/obj/item/weapon/reagent_containers/food/drinks/cans/grape_juice = 26)
+ prices = list(/obj/item/weapon/reagent_containers/food/drinks/cans/cola = 15,/obj/item/weapon/reagent_containers/food/drinks/cans/space_mountain_wind = 11,
+ /obj/item/weapon/reagent_containers/food/drinks/cans/dr_gibb = 16,/obj/item/weapon/reagent_containers/food/drinks/cans/starkist = 15,
+ /obj/item/weapon/reagent_containers/food/drinks/cans/waterbottle = 12,/obj/item/weapon/reagent_containers/food/drinks/cans/space_up = 15,
+ /obj/item/weapon/reagent_containers/food/drinks/cans/iced_tea = 13,/obj/item/weapon/reagent_containers/food/drinks/cans/grape_juice = 16)
idle_power_usage = 211 //refrigerator - believe it or not, this is actually the average power consumption of a refrigerated vending machine according to NRCan.
//This one's from bay12
@@ -783,7 +785,7 @@
products = list(/obj/item/weapon/storage/fancy/cigarettes = 10,/obj/item/weapon/storage/box/matches = 10,/obj/item/weapon/flame/lighter/random = 4)
contraband = list(/obj/item/weapon/flame/lighter/zippo = 4)
premium = list(/obj/item/weapon/storage/fancy/cigar = 5,/obj/item/weapon/storage/fancy/cigarettes/killthroat = 5 )
- prices = list(/obj/item/weapon/storage/fancy/cigarettes = 520,/obj/item/weapon/storage/box/matches = 22,/obj/item/weapon/flame/lighter/random = 22)
+ prices = list(/obj/item/weapon/storage/fancy/cigarettes = 510,/obj/item/weapon/storage/box/matches = 12,/obj/item/weapon/flame/lighter/random = 12)
/obj/machinery/vending/medical
diff --git a/code/game/mecha/equipment/tracking_beacon.dm b/code/game/mecha/equipment/tracking_beacon.dm
index 92787c3873d..d45b7d7aab5 100644
--- a/code/game/mecha/equipment/tracking_beacon.dm
+++ b/code/game/mecha/equipment/tracking_beacon.dm
@@ -12,6 +12,10 @@
if (in_mecha())
exo_beacons.Add(src)//For the sake of exosuits which spawn with a preinstalled tracking beacon
+/obj/item/mecha_parts/mecha_tracking/Destroy()
+ exo_beacons.Remove(src)
+ return ..()
+
/obj/item/mecha_parts/mecha_tracking/proc/get_mecha_info()
if(!in_mecha())
return 0
diff --git a/code/game/objects/effects/chem/chemsmoke.dm b/code/game/objects/effects/chem/chemsmoke.dm
index 1e06328564c..d95d9966b29 100644
--- a/code/game/objects/effects/chem/chemsmoke.dm
+++ b/code/game/objects/effects/chem/chemsmoke.dm
@@ -250,7 +250,7 @@
if(passed_smoke)
smoke = passed_smoke
else
- smoke = getFromPool(/obj/effect/effect/smoke/chem, list(location, smoke_duration + rand(smoke_duration*-0.25, smoke_duration*0.25), T, I))
+ smoke = getFromPool(/obj/effect/effect/smoke/chem, location, smoke_duration + rand(smoke_duration*-0.25, smoke_duration*0.25), T, I)
if(chemholder.reagents.reagent_list.len)
chemholder.reagents.trans_to_obj(smoke, chemholder.reagents.total_volume / dist, copy = 1) //copy reagents to the smoke so mob/breathe() can handle inhaling the reagents
diff --git a/code/game/objects/effects/chem/foam.dm b/code/game/objects/effects/chem/foam.dm
index 73ea7cf3c67..b7d2acc5411 100644
--- a/code/game/objects/effects/chem/foam.dm
+++ b/code/game/objects/effects/chem/foam.dm
@@ -108,7 +108,7 @@
F.amount += amount
return
- F = getFromPool(/obj/effect/effect/foam, list(location, metal))
+ F = getFromPool(/obj/effect/effect/foam, location, metal)
F.amount = amount
if(!metal) // don't carry other chemicals if a metal foam
@@ -180,4 +180,4 @@
/obj/structure/foamedmetal/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0)
if(air_group)
return 0
- return !density
\ No newline at end of file
+ return !density
diff --git a/code/game/objects/effects/spiders.dm b/code/game/objects/effects/spiders.dm
index 5265e05531a..02d66ed114d 100644
--- a/code/game/objects/effects/spiders.dm
+++ b/code/game/objects/effects/spiders.dm
@@ -101,7 +101,7 @@
O = loc
for(var/i=0, i 30) || ((world.timeofday - last_tick) < 0))
- last_tick = world.timeofday
+/obj/item/device/radio/intercom/proc/power_change(has_power)
+ if (!src.loc)
+ on = 0
+ else
+ on = has_power
- if(!src.loc)
- on = 0
- else
- var/area/A = get_area(src)
- if(!A)
- on = 0
- else
- on = A.powered(EQUIP) // set "on" to the power status
+ update_icon()
- if(!on)
- icon_state = "intercom-p"
- else
- icon_state = "intercom"
+/obj/item/device/radio/intercom/forceMove(atom/dest)
+ power_interface.forceMove(dest)
+ ..(dest)
+
+/obj/item/device/radio/intercom/update_icon()
+ if (on)
+ icon_state = "intercom"
+ else
+ icon_state = "intercom-p"
/obj/item/device/radio/intercom/broadcasting
broadcasting = 1
diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm
index bd40f42b4c4..60663c8596c 100644
--- a/code/game/objects/items/weapons/cards_ids.dm
+++ b/code/game/objects/items/weapons/cards_ids.dm
@@ -121,6 +121,10 @@ var/const/NO_EMAG_ACT = -50
var/rank = null //actual job
var/dorm = 0 // determines if this ID has claimed a dorm already
+/obj/item/weapon/card/id/Destroy()
+ mob = null
+ return ..()
+
/obj/item/weapon/card/id/examine(mob/user)
set src in oview(1)
if(in_range(usr, src))
diff --git a/code/game/objects/items/weapons/cigs_lighters.dm b/code/game/objects/items/weapons/cigs_lighters.dm
index 76b7043f01e..48998682eab 100644
--- a/code/game/objects/items/weapons/cigs_lighters.dm
+++ b/code/game/objects/items/weapons/cigs_lighters.dm
@@ -266,7 +266,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
ignitermes = "USER fiddles with FLAME, and manages to light their NAME with the power of science."
/obj/item/clothing/mask/smokable/cigarette/cigar/cohiba
- name = "\improper Cohiba Robusto cigar"
+ name = "\improper Cohiba robusto cigar"
desc = "There's little more you could want from a cigar."
icon_state = "cigar2off"
icon_on = "cigar2on"
diff --git a/code/game/objects/items/weapons/circuitboards/computer/holodeckcontrol.dm b/code/game/objects/items/weapons/circuitboards/computer/holodeckcontrol.dm
index db11c4de502..e36b147d113 100644
--- a/code/game/objects/items/weapons/circuitboards/computer/holodeckcontrol.dm
+++ b/code/game/objects/items/weapons/circuitboards/computer/holodeckcontrol.dm
@@ -5,7 +5,7 @@
/obj/item/weapon/circuitboard/holodeckcontrol
name = T_BOARD("holodeck control console")
build_path = /obj/machinery/computer/HolodeckControl
- origin_tech = "programming=2;bluespace=2"
+ origin_tech = list(TECH_DATA = 2, TECH_BLUESPACE = 2)
var/last_to_emag
var/linkedholodeck_area
var/list/supported_programs
diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm
index a7c8f69e32d..54a774b176c 100644
--- a/code/game/objects/items/weapons/implants/implant.dm
+++ b/code/game/objects/items/weapons/implants/implant.dm
@@ -367,6 +367,17 @@ the implant may become unstable and either pre-maturely inject the subject or si
processing_objects.Add(src)
return 1
+/obj/item/weapon/implant/loyalty/ipc
+ name = "loyalty chip"
+ desc = "A device that sets directives programmed for loyalty to NanoTrasen on the synthetic subject. Will not work on organics."
+
+/obj/item/weapon/implant/loyalty/ipc/implanted(mob/M)
+
+ if (!isipc(M))
+ return
+
+ ..()
+
/obj/item/weapon/implant/adrenalin
name = "adrenalin"
desc = "Removes all stuns and knockdowns."
diff --git a/code/game/objects/items/weapons/material/knives.dm b/code/game/objects/items/weapons/material/knives.dm
index f78b563917f..f5bc195ead9 100644
--- a/code/game/objects/items/weapons/material/knives.dm
+++ b/code/game/objects/items/weapons/material/knives.dm
@@ -58,7 +58,7 @@
edge = 1
force_divisor = 0.15 // 9 when wielded with hardness 60 (steel)
matter = list(DEFAULT_WALL_MATERIAL = 12000)
- origin_tech = "materials=1"
+ origin_tech = list(TECH_MATERIAL = 1)
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
unbreakable = 1
diff --git a/code/game/objects/items/weapons/material/misc.dm b/code/game/objects/items/weapons/material/misc.dm
index 8cae5642073..ae28d217466 100644
--- a/code/game/objects/items/weapons/material/misc.dm
+++ b/code/game/objects/items/weapons/material/misc.dm
@@ -18,7 +18,7 @@
w_class = 2
sharp = 1
edge = 1
- origin_tech = "materials=2;combat=1"
+ origin_tech = list(TECH_MATERIAL = 2, TECH_COMBAT = 1)
attack_verb = list("chopped", "torn", "cut")
applies_material_colour = 0
@@ -61,5 +61,5 @@
throw_range = 3
w_class = 4
slot_flags = SLOT_BACK
- origin_tech = "materials=2;combat=2"
+ origin_tech = list(TECH_MATERIAL = 2, TECH_COMBAT = 2)
attack_verb = list("chopped", "sliced", "cut", "reaped")
diff --git a/code/game/objects/items/weapons/material/twohanded.dm b/code/game/objects/items/weapons/material/twohanded.dm
index c0c5ceb1b4a..7f24f9919a8 100644
--- a/code/game/objects/items/weapons/material/twohanded.dm
+++ b/code/game/objects/items/weapons/material/twohanded.dm
@@ -107,6 +107,7 @@
var/obj/item/weapon/material/twohanded/offhand/O = user.get_inactive_hand()
if(O && istype(O))
+ user.u_equip(O)
O.unwield()
else //Trying to wield it
@@ -149,9 +150,17 @@
default_material = "placeholder"
/obj/item/weapon/material/twohanded/offhand/unwield()
+ if (ismob(loc))
+ var/mob/living/our_mob = loc
+ our_mob.remove_from_mob(src)
+
qdel(src)
/obj/item/weapon/material/twohanded/offhand/wield()
+ if (ismob(loc))
+ var/mob/living/our_mob = loc
+ our_mob.remove_from_mob(src)
+
qdel(src)
/obj/item/weapon/material/twohanded/offhand/update_icon()
diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm
index 4b7db053bd8..45d9aef2c6c 100644
--- a/code/game/objects/items/weapons/melee/energy.dm
+++ b/code/game/objects/items/weapons/melee/energy.dm
@@ -5,15 +5,23 @@
var/active_w_class
sharp = 0
edge = 0
- armor_penetration = 50
+ armor_penetration = 10
flags = NOBLOODY
can_embed = 0//No embedding pls
+ var/base_reflectchance = 40
+ var/base_block_chance = 25
+ var/shield_power = 100
+ var/can_block_bullets = 0
var/datum/effect_system/sparks/spark_system
/obj/item/weapon/melee/energy/New()
spark_system = bind_spark(src, 5)
..()
+/obj/item/weapon/melee/energy/Destroy()
+ QDEL_NULL(spark_system)
+ return ..()
+
/obj/item/weapon/melee/energy/proc/activate(mob/living/user)
anchored = 1
if(active)
@@ -56,6 +64,66 @@
add_fingerprint(user)
return
+/obj/item/weapon/melee/energy/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
+ if(active && default_parry_check(user, attacker, damage_source) && prob(50))
+ user.visible_message("\The [user] parries [attack_text] with \the [src]!")
+
+ spark_system.queue()
+ playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1)
+ return 1
+ else
+
+ if(!active)
+ return 0 //turn it on first!
+
+ if(user.incapacitated())
+ return 0
+
+ //block as long as they are not directly behind us
+ var/bad_arc = reverse_direction(user.dir) //arc of directions from which we cannot block
+ if(check_shield_arc(user, bad_arc, damage_source, attacker))
+
+ if(prob(base_block_chance))
+ spark_system.queue()
+ playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1)
+ shield_power -= round(damage/4)
+
+ if(shield_power <= 0)
+ visible_message("\The [user]'s [src.name] overloads!")
+ deactivate()
+ shield_power = initial(shield_power)
+ return 0
+
+ if(istype(damage_source, /obj/item/projectile/energy) || istype(damage_source, /obj/item/projectile/beam))
+ var/obj/item/projectile/P = damage_source
+
+ var/reflectchance = base_reflectchance - round(damage/3)
+ if(!(def_zone in list("chest", "groin","head")))
+ reflectchance /= 2
+ if(P.starting && prob(reflectchance))
+ visible_message("\The [user]'s [src.name] reflects [attack_text]!")
+
+ // Find a turf near or on the original location to bounce to
+ var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
+ var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
+ var/turf/curloc = get_turf(user)
+
+ // redirect the projectile
+ P.redirect(new_x, new_y, curloc, user)
+
+ return PROJECTILE_CONTINUE // complete projectile permutation
+ else
+ user.visible_message("\The [user] blocks [attack_text] with \the [src]!")
+ return 1
+
+ else if(istype(damage_source, /obj/item/projectile/bullet) && can_block_bullets)
+ var/reflectchance = (base_reflectchance) - round(damage/3)
+ if(!(def_zone in list("chest", "groin","head")))
+ reflectchance /= 2
+ if(prob(reflectchance))
+ user.visible_message("\The [user] blocks [attack_text] with \the [src]!")
+ return 1
+
/obj/item/weapon/melee/energy/glaive
name = "energy glaive"
desc = "An energized glaive."
@@ -74,6 +142,11 @@
sharp = 1
edge = 1
slot_flags = SLOT_BACK
+ base_reflectchance = 0
+ base_block_chance = 0 //cannot be used to block guns
+ shield_power = 0
+ can_block_bullets = 0
+ armor_penetration = 20
/obj/item/weapon/melee/energy/glaive/activate(mob/living/user)
..()
@@ -108,6 +181,11 @@
attack_verb = list("attacked", "chopped", "cleaved", "torn", "cut")
sharp = 1
edge = 1
+ base_reflectchance = 0
+ base_block_chance = 0 //cannot be used to block guns
+ shield_power = 0
+ can_block_bullets = 0
+ armor_penetration = 35
/obj/item/weapon/melee/energy/axe/activate(mob/living/user)
..()
@@ -140,6 +218,7 @@
sharp = 1
edge = 1
var/blade_color
+ shield_power = 75
/obj/item/weapon/melee/energy/sword/dropped(var/mob/user)
..()
@@ -175,19 +254,12 @@
attack_verb = list()
icon_state = initial(icon_state)
-/obj/item/weapon/melee/energy/sword/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
- if(active && default_parry_check(user, attacker, damage_source) && prob(50))
- user.visible_message("\The [user] parries [attack_text] with \the [src]!")
-
- spark_system.queue()
- playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1)
- return 1
- return 0
-
/obj/item/weapon/melee/energy/sword/pirate
name = "energy cutlass"
desc = "Arrrr matey."
icon_state = "cutlass0"
+ base_reflectchance = 60
+ base_block_chance = 60
/obj/item/weapon/melee/energy/sword/pirate/activate(mob/living/user)
..()
@@ -196,13 +268,12 @@
/*
*Energy Blade
*/
-
-//Can't be activated or deactivated, so no reason to be a subtype of energy
/obj/item/weapon/melee/energy/blade
name = "energy blade"
desc = "A concentrated beam of energy in the shape of a blade. Very stylish... and lethal."
icon_state = "blade"
- force = 40 //Normal attacks deal very high damage - about the same as wielded fire axe
+ force = 40
+ active_force = 40 //Normal attacks deal very high damage - about the same as wielded fire axe
armor_penetration = 100
sharp = 1
edge = 1
@@ -214,6 +285,12 @@
flags = NOBLOODY
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
var/mob/living/creator
+ base_reflectchance = 140
+ base_block_chance = 75
+ shield_power = 150
+ can_block_bullets = 1
+ active = 1
+ armor_penetration = 20
/obj/item/weapon/melee/energy/blade/New()
processing_objects |= src
@@ -223,10 +300,14 @@
processing_objects -= src
..()
-/obj/item/weapon/melee/energy/blade/attack_self(mob/user as mob)
+/obj/item/weapon/melee/energy/blade/deactivate(mob/living/user)
+ if(!active)
+ return
+ playsound(user, 'sound/weapons/saberoff.ogg', 50, 1)
user.drop_from_inventory(src)
spawn(1) if(src) qdel(src)
+
/obj/item/weapon/melee/energy/blade/dropped()
spawn(1) if(src) qdel(src)
diff --git a/code/game/objects/items/weapons/mop.dm b/code/game/objects/items/weapons/mop.dm
index e50ce867967..e60df528ed1 100644
--- a/code/game/objects/items/weapons/mop.dm
+++ b/code/game/objects/items/weapons/mop.dm
@@ -12,9 +12,14 @@
var/mopping = 0
var/mopcount = 0
-
/obj/item/weapon/mop/New()
+ ..()
create_reagents(30)
+ janitorial_supplies |= src
+
+/obj/item/weapon/mop/Destroy()
+ janitorial_supplies -= src
+ return ..()
/obj/item/weapon/mop/afterattack(atom/A, mob/user, proximity)
if(!proximity) return
diff --git a/code/game/objects/items/weapons/shields.dm b/code/game/objects/items/weapons/shields.dm
index d57d312ab15..45483b8c8f0 100644
--- a/code/game/objects/items/weapons/shields.dm
+++ b/code/game/objects/items/weapons/shields.dm
@@ -103,17 +103,62 @@
w_class = 2
origin_tech = list(TECH_MATERIAL = 4, TECH_MAGNET = 3, TECH_ILLEGAL = 4)
attack_verb = list("shoved", "bashed")
+ var/shield_power = 150
var/active = 0
-/obj/item/weapon/shield/energy/handle_shield(mob/user)
+/obj/item/weapon/shield/energy/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
if(!active)
return 0 //turn it on first!
- . = ..()
+ if(user.incapacitated())
+ return 0
+
if(.)
spark(user.loc, 5)
playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1)
+ //block as long as they are not directly behind us
+ var/bad_arc = reverse_direction(user.dir) //arc of directions from which we cannot block
+ if(check_shield_arc(user, bad_arc, damage_source, attacker))
+
+ if(prob(get_block_chance(user, damage, damage_source, attacker)))
+ spark(user.loc, 5)
+ playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1)
+ shield_power -= round(damage/4)
+
+ if(shield_power <= 0)
+ visible_message("\The [user]'s [src.name] overloads!")
+ active = 0
+ force = 3
+ update_icon()
+ w_class = 1
+ playsound(user, 'sound/weapons/saberoff.ogg', 50, 1)
+ shield_power = initial(shield_power)
+ return 0
+
+ if(istype(damage_source, /obj/item/projectile/energy) || istype(damage_source, /obj/item/projectile/beam))
+ var/obj/item/projectile/P = damage_source
+
+ var/reflectchance = 80 - round(damage/3)
+ if(P.starting && prob(reflectchance))
+ visible_message("\The [user]'s [src.name] reflects [attack_text]!")
+
+ // Find a turf near or on the original location to bounce to
+ var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
+ var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
+ var/turf/curloc = get_turf(user)
+
+ // redirect the projectile
+ P.redirect(new_x, new_y, curloc, user)
+
+ return PROJECTILE_CONTINUE // complete projectile permutation
+ else
+ user.visible_message("\The [user] blocks [attack_text] with \the [src]!")
+ return 1
+ else
+ user.visible_message("\The [user] blocks [attack_text] with \the [src]!")
+ return 1
+
/obj/item/weapon/shield/energy/get_block_chance(mob/user, var/damage, atom/damage_source = null, mob/attacker = null)
if(istype(damage_source, /obj/item/projectile))
var/obj/item/projectile/P = damage_source
diff --git a/code/game/objects/items/weapons/storage/backpack.dm b/code/game/objects/items/weapons/storage/backpack.dm
index 3ca7ce50aa0..633f8285947 100644
--- a/code/game/objects/items/weapons/storage/backpack.dm
+++ b/code/game/objects/items/weapons/storage/backpack.dm
@@ -329,11 +329,19 @@
name = "duffel bag"
desc = "A spacious duffel bag."
icon_state = "duffel-norm"
+ item_state_slots = list(
+ slot_l_hand_str = "duffle",
+ slot_r_hand_str = "duffle"
+ )
/obj/item/weapon/storage/backpack/duffel/cap
name = "captain's duffel bag"
desc = "A rare and special duffel bag for only the most air-headed of Nanotrasen personnel."
icon_state = "duffel-captain"
+ item_state_slots = list(
+ slot_l_hand_str = "duffle_captain",
+ slot_r_hand_str = "duffle_captain"
+ )
/obj/item/weapon/storage/backpack/duffel/hyd
name = "botanist's duffel bag"
@@ -344,16 +352,28 @@
name = "virology duffel bag"
desc = "A sterilized duffel bag suited to those about to unleash pathogenic havoc upon the world."
icon_state = "duffel-virology"
+ item_state_slots = list(
+ slot_l_hand_str = "duffle_med",
+ slot_r_hand_str = "duffle_med"
+ )
/obj/item/weapon/storage/backpack/duffel/med
name = "medical duffel bag"
desc = "A sterilized duffel bag for the young, upcoming lesbayan."
icon_state = "duffel-medical"
+ item_state_slots = list(
+ slot_l_hand_str = "duffle_med",
+ slot_r_hand_str = "duffle_med"
+ )
/obj/item/weapon/storage/backpack/duffel/eng
name = "industrial duffel bag"
desc = "A rough and tumble duffel bag for the hard working wrench-monkey of tomorrow."
icon_state = "duffel-engineering"
+ item_state_slots = list(
+ slot_l_hand_str = "duffle_eng",
+ slot_r_hand_str = "duffle_eng"
+ )
/obj/item/weapon/storage/backpack/duffel/tox
name = "scientist's duffel bag"
@@ -374,11 +394,19 @@
name = "chemistry duffel bag"
desc = "Spice up the love life a little."
icon_state = "duffel-chemistry"
+ item_state_slots = list(
+ slot_l_hand_str = "duffle_med",
+ slot_r_hand_str = "duffle_med"
+ )
/obj/item/weapon/storage/backpack/duffel/syndie
name = "syndicate duffel bag"
desc = "A snazzy black and red duffel bag, perfect for smuggling C4 and Parapens."
icon_state = "duffel-syndie"
+ item_state_slots = list(
+ slot_l_hand_str = "duffle_syndie",
+ slot_r_hand_str = "duffle_syndie"
+ )
/obj/item/weapon/storage/backpack/duffel/wizard
name = "wizardly duffel bag"
diff --git a/code/game/objects/items/weapons/storage/fancy.dm b/code/game/objects/items/weapons/storage/fancy.dm
index 9865e60e2cc..649cd666a0f 100644
--- a/code/game/objects/items/weapons/storage/fancy.dm
+++ b/code/game/objects/items/weapons/storage/fancy.dm
@@ -71,7 +71,7 @@
item_state = "candlebox5"
throwforce = 2
slot_flags = SLOT_BELT
-
+ max_storage_space = 5
/obj/item/weapon/storage/fancy/candle_box/New()
..()
diff --git a/code/game/objects/items/weapons/storage/lockbox.dm b/code/game/objects/items/weapons/storage/lockbox.dm
index e5409eef9c2..f215deb0cf6 100644
--- a/code/game/objects/items/weapons/storage/lockbox.dm
+++ b/code/game/objects/items/weapons/storage/lockbox.dm
@@ -114,21 +114,15 @@
/obj/item/weapon/storage/lockbox/medal/New()
..()
- new /obj/item/clothing/accessory/medal
- new /obj/item/clothing/accessory/medal
- new /obj/item/clothing/accessory/medal/conduct
- new /obj/item/clothing/accessory/medal/conduct
- new /obj/item/clothing/accessory/medal/conduct
- new /obj/item/clothing/accessory/medal/conduct
- new /obj/item/clothing/accessory/medal/bronze_heart
- new /obj/item/clothing/accessory/medal/bronze_heart
- new /obj/item/clothing/accessory/medal/nobel_science
- new /obj/item/clothing/accessory/medal/nobel_science
- new /obj/item/clothing/accessory/medal/silver
- new /obj/item/clothing/accessory/medal/iron/merit
- new /obj/item/clothing/accessory/medal/silver/valor
- new /obj/item/clothing/accessory/medal/silver/security
- new /obj/item/clothing/accessory/medal/silver/security
- new /obj/item/clothing/accessory/medal/gold
-
-
+ new /obj/item/clothing/accessory/medal/conduct(src)
+ new /obj/item/clothing/accessory/medal/conduct(src)
+ new /obj/item/clothing/accessory/medal/conduct(src)
+ new /obj/item/clothing/accessory/medal/bronze_heart(src)
+ new /obj/item/clothing/accessory/medal/bronze_heart(src)
+ new /obj/item/clothing/accessory/medal/nobel_science(src)
+ new /obj/item/clothing/accessory/medal/nobel_science(src)
+ new /obj/item/clothing/accessory/medal/iron/merit(src)
+ new /obj/item/clothing/accessory/medal/iron/merit(src)
+ new /obj/item/clothing/accessory/medal/silver/valor(src)
+ new /obj/item/clothing/accessory/medal/silver/security(src)
+ new /obj/item/clothing/accessory/medal/silver/security(src)
diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm
index e1c2f9796d4..c09aef55f4f 100644
--- a/code/game/objects/items/weapons/storage/storage.dm
+++ b/code/game/objects/items/weapons/storage/storage.dm
@@ -413,7 +413,16 @@
update_icon()
return 1
+
//This proc is called when you want to place an item into the storage item.
+//Its a safe proc for adding things to the storage that does the necessary checks. Object will not be moved if it fails
+/obj/item/weapon/storage/proc/insert_into_storage(obj/item/W as obj, var/prevent_messages = 1)
+ if(!can_be_inserted(W, prevent_messages))
+ return
+
+ return handle_item_insertion(W, prevent_messages)
+
+
/obj/item/weapon/storage/attackby(obj/item/W as obj, mob/user as mob)
..()
diff --git a/code/game/objects/items/weapons/storage/wallets.dm b/code/game/objects/items/weapons/storage/wallets.dm
index 724b6c31ac1..faf8a11c76c 100644
--- a/code/game/objects/items/weapons/storage/wallets.dm
+++ b/code/game/objects/items/weapons/storage/wallets.dm
@@ -4,11 +4,13 @@
storage_slots = 10
icon_state = "wallet"
w_class = 2
+ max_w_class = 2
can_hold = list(
/obj/item/weapon/spacecash,
/obj/item/weapon/card,
- /obj/item/clothing/mask/smokable/cigarette/,
+ /obj/item/clothing/mask/smokable,
/obj/item/clothing/accessory/badge,
+ /obj/item/clothing/accessory/locket,
/obj/item/device/flashlight/pen,
/obj/item/seeds,
/obj/item/stack/medical,
@@ -19,11 +21,16 @@
/obj/item/weapon/flame/lighter,
/obj/item/weapon/flame/match,
/obj/item/weapon/paper,
+ /obj/item/weapon/paper_bundle,
/obj/item/weapon/pen,
/obj/item/weapon/photo,
/obj/item/weapon/reagent_containers/dropper,
+ /obj/item/weapon/reagent_containers/syringe,
+ /obj/item/weapon/reagent_containers/pill,
+ /obj/item/weapon/reagent_containers/hypospray/autoinjector,
/obj/item/weapon/screwdriver,
- /obj/item/weapon/stamp)
+ /obj/item/weapon/stamp,
+ /obj/item/device/paicard)
slot_flags = SLOT_ID
var/obj/item/weapon/card/id/front_id = null
diff --git a/code/game/objects/items/weapons/stunbaton.dm b/code/game/objects/items/weapons/stunbaton.dm
index 51c60982e46..64a44c1af54 100644
--- a/code/game/objects/items/weapons/stunbaton.dm
+++ b/code/game/objects/items/weapons/stunbaton.dm
@@ -208,7 +208,7 @@
item_state = "stunrod"
force = 20
baton_color = "#75ACFF"
- origin_tech = "combat=4,illegal=2"
+ origin_tech = list(TECH_COMBAT = 4, TECH_ILLEGAL = 2)
contained_sprite = 1
/obj/item/weapon/melee/baton/stunrod/New()
diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm
index 77de8acdb59..8c5ddf22f50 100644
--- a/code/game/objects/items/weapons/tools.dm
+++ b/code/game/objects/items/weapons/tools.dm
@@ -166,8 +166,8 @@
desc = "A welding tool with an extended-capacity built-in fuel tank, standard issue for engineers."
max_fuel = 40
matter = list(DEFAULT_WALL_MATERIAL = 100, "glass" = 60)
- origin_tech = "engineering=2"
base_iconstate = "ind_welder_off"
+ origin_tech = list(TECH_ENGINEERING = 2)
/obj/item/weapon/weldingtool/hugetank
@@ -176,8 +176,8 @@
max_fuel = 80
w_class = 2.0
matter = list(DEFAULT_WALL_MATERIAL = 200, "glass" = 120)
- origin_tech = "engineering=3"
base_iconstate = "adv_welder_off"
+ origin_tech = list(TECH_ENGINEERING = 3)
//The Experimental Welding Tool!
@@ -187,8 +187,8 @@
max_fuel = 40
w_class = 2.0
matter = list(DEFAULT_WALL_MATERIAL = 100, "glass" = 120)
- origin_tech = "engineering=4;biotech=4"
base_iconstate = "exp_welder_off"
+ origin_tech = list(TECH_ENGINEERING = 4, TECH_BIO = 4)
base_itemstate = "exp_welder"
var/last_gen = 0
diff --git a/code/game/objects/items/weapons/traps.dm b/code/game/objects/items/weapons/traps.dm
index 31bcd4a6e72..b2e58cdad5b 100644
--- a/code/game/objects/items/weapons/traps.dm
+++ b/code/game/objects/items/weapons/traps.dm
@@ -8,7 +8,7 @@
desc = "A mechanically activated leg trap. Low-tech, but reliable. Looks like it could really hurt if you set it off."
throwforce = 0
w_class = 3
- origin_tech = "materials=1"
+ origin_tech = list(TECH_MATERIAL = 1)
matter = list(DEFAULT_WALL_MATERIAL = 18750)
var/deployed = 0
diff --git a/code/game/objects/items/weapons/vaurca_items.dm b/code/game/objects/items/weapons/vaurca_items.dm
index 7a13b765692..0bcdb2eedaf 100644
--- a/code/game/objects/items/weapons/vaurca_items.dm
+++ b/code/game/objects/items/weapons/vaurca_items.dm
@@ -157,7 +157,7 @@
desc = "A lightweight Zo'rane designed Vaurcae softsuit, for extremely extended EVA operations."
slowdown = 0
- species_restricted = list("Vaurca Worker", "Vaurca Warrior")
+ species_restricted = list("Vaurca")
boots = /obj/item/clothing/shoes/magboots/vox/vaurca
helmet = /obj/item/clothing/head/helmet/space/void/vaurca
@@ -170,7 +170,7 @@
icon_state = "helm_void"
item_state = "helm_void"
- species_restricted = list("Vaurca Worker", "Vaurca Warrior")
+ species_restricted = list("Vaurca")
light_overlay = "helmet_light"
@@ -183,7 +183,7 @@
contained_sprite = 1
icon = 'icons/obj/vaurca_items.dmi'
- species_restricted = list("Vaurca Worker", "Vaurca Warrior")
+ species_restricted = list("Vaurca")
action_button_name = "Toggle the magclaws"
diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm
index bd9a9876bae..46cda524cb7 100644
--- a/code/game/objects/structures/grille.dm
+++ b/code/game/objects/structures/grille.dm
@@ -96,7 +96,7 @@
if(iswirecutter(W))
if(!shock(user, 100))
playsound(loc, 'sound/items/Wirecutter.ogg', 100, 1)
- getFromPool(/obj/item/stack/rods, list(get_turf(src), destroyed ? 1 : 2))
+ getFromPool(/obj/item/stack/rods, get_turf(src), destroyed ? 1 : 2)
qdel(src)
else if((isscrewdriver(W)) && (istype(loc, /turf/simulated) || anchored))
if(!shock(user, 90))
diff --git a/code/game/objects/structures/janicart.dm b/code/game/objects/structures/janicart.dm
index b35e3ac59e6..f8052a2b022 100644
--- a/code/game/objects/structures/janicart.dm
+++ b/code/game/objects/structures/janicart.dm
@@ -22,8 +22,21 @@
var/has_items = 0//This is set true whenever the cart has anything loaded/mounted on it
var/dismantled = 0//This is set true after the object has been dismantled to avoid an infintie loop
-///obj/structure/janitorialcart/New()
+/obj/structure/janitorialcart/New()
+ ..()
+ janitorial_supplies |= src
+/obj/structure/janitorialcart/Destroy()
+ janitorial_supplies -= src
+ QDEL_NULL(mybag)
+ QDEL_NULL(mymop)
+ QDEL_NULL(myspray)
+ QDEL_NULL(myreplacer)
+ QDEL_NULL(mybucket)
+ return ..()
+
+/obj/structure/janitorialcart/proc/get_short_status()
+ return "Contents: [english_list(contents)]"
/obj/structure/janitorialcart/examine(mob/user)
if(..(user, 1))
diff --git a/code/game/objects/structures/mop_bucket.dm b/code/game/objects/structures/mop_bucket.dm
index 6e3807c30cf..00bb35a041a 100644
--- a/code/game/objects/structures/mop_bucket.dm
+++ b/code/game/objects/structures/mop_bucket.dm
@@ -10,12 +10,17 @@
/obj/structure/mopbucket/New()
- create_reagents(100)
..()
+ create_reagents(100)
+ janitorial_supplies |= src
+
+/obj/structure/mobbucket/Destroy()
+ janitorial_supplies -= src
+ return ..()
/obj/structure/mopbucket/examine(mob/user)
if(..(user, 1))
- user << "[src] \icon[src] contains [reagents.total_volume] unit\s of water!"
+ user << "Contains [reagents.total_volume] unit\s of water."
/obj/structure/mopbucket/attackby(obj/item/I, mob/user)
if(istype(I, /obj/item/weapon/mop))
diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm
index 1742cd09b0f..c7bc593fcad 100644
--- a/code/game/objects/structures/watercloset.dm
+++ b/code/game/objects/structures/watercloset.dm
@@ -18,6 +18,7 @@
/obj/structure/toilet/attack_hand(mob/living/user as mob)
if(swirlie)
+ usr.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
usr.visible_message("[user] slams the toilet seat onto [swirlie.name]'s head!", "You slam the toilet seat onto [swirlie.name]'s head!", "You hear reverberating porcelain.")
swirlie.adjustBruteLoss(8)
return
@@ -53,6 +54,7 @@
return
if(istype(I, /obj/item/weapon/grab))
+ usr.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
var/obj/item/weapon/grab/G = I
if(isliving(G.affecting))
@@ -117,7 +119,7 @@
/obj/machinery/shower
name = "shower"
- desc = "The HS-451. Installed in the 2550s by the Hygiene Division."
+ desc = "The HS-451. Installed in the 2450s by the Hygiene Division."
icon = 'icons/obj/watercloset.dmi'
icon_state = "shower"
density = 0
@@ -453,9 +455,7 @@
R.cell.charge -= 20
else
B.deductcharge(B.hitcost)
- user.visible_message( \
- "[user] was stunned by \his wet [O]!", \
- "[user] was stunned by \his wet [O]!")
+ user.visible_message("[user] was stunned by \the [O]!")
return 1
// Short of a rewrite, this is necessary to stop monkeycubes being washed.
else if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/monkeycube))
diff --git a/code/game/objects/structures/windoor_assembly.dm b/code/game/objects/structures/windoor_assembly.dm
index dbf92c1b11c..0b278903a74 100644
--- a/code/game/objects/structures/windoor_assembly.dm
+++ b/code/game/objects/structures/windoor_assembly.dm
@@ -17,6 +17,7 @@ obj/structure/windoor_assembly
density = 0
dir = NORTH
w_class = 3
+ flags = ON_BORDER
var/obj/item/weapon/airlock_electronics/electronics = null
@@ -79,7 +80,7 @@ obj/structure/windoor_assembly/Destroy()
user << "You dissasembled the windoor assembly!"
new /obj/item/stack/material/glass/reinforced(get_turf(src), 5)
if(secure)
- getFromPool(/obj/item/stack/rods, list(get_turf(src), 4))
+ getFromPool(/obj/item/stack/rods, get_turf(src), 4)
qdel(src)
else
user << "You need more welding fuel to dissassemble the windoor assembly."
@@ -261,18 +262,60 @@ obj/structure/windoor_assembly/Destroy()
//Rotates the windoor assembly clockwise
-/obj/structure/windoor_assembly/verb/revrotate()
- set name = "Rotate Windoor Assembly"
+//These directions are fucked up, apparently dm rotates anticlockwise by default
+/obj/structure/windoor_assembly/verb/rotate()
+ set name = "Rotate Windoor Clockwise"
set category = "Object"
set src in oview(1)
+ var/targetdir = turn(src.dir, 270)
+
+ for(var/obj/obstacle in get_turf(src))
+ if (obstacle == src)
+ continue
+
+ if((obstacle.flags & ON_BORDER) && obstacle.dir == targetdir)
+ usr << span("danger", "You can't turn the windoor assembly that way, there's already something there!")
+ return
+
if (src.anchored)
usr << "It is fastened to the floor; therefore, you can't rotate it!"
return 0
if(src.state != "01")
update_nearby_tiles(need_rebuild=1) //Compel updates before
- src.set_dir(turn(src.dir, 270))
+ src.set_dir(targetdir)
+
+ if(src.state != "01")
+ update_nearby_tiles(need_rebuild=1)
+
+ update_icon()
+ return
+
+
+//Rotates the windoor assembly anticlockwise
+/obj/structure/windoor_assembly/verb/revrotate()
+ set name = "Rotate Windoor Anticlockwise"
+ set category = "Object"
+ set src in oview(1)
+
+ var/targetdir = turn(src.dir, 90)
+
+ for(var/obj/obstacle in get_turf(src))
+ if (obstacle == src)
+ continue
+
+ if((obstacle.flags & ON_BORDER) && obstacle.dir == targetdir)
+ usr << span("danger", "You can't turn the windoor assembly that way, there's already something there!")
+ return
+
+ if (src.anchored)
+ usr << "It is fastened to the floor; therefore, you can't rotate it!"
+ return 0
+ if(src.state != "01")
+ update_nearby_tiles(need_rebuild=1) //Compel updates before
+
+ src.set_dir(targetdir)
if(src.state != "01")
update_nearby_tiles(need_rebuild=1)
diff --git a/code/game/objects/structures/window_spawner.dm b/code/game/objects/structures/window_spawner.dm
index a1cec9eb55c..966d6e8e0e1 100644
--- a/code/game/objects/structures/window_spawner.dm
+++ b/code/game/objects/structures/window_spawner.dm
@@ -35,7 +35,7 @@
/obj/effect/wingrille_spawn/proc/activate()
if(activated) return
if (!locate(/obj/structure/grille) in get_turf(src))
- var/obj/structure/grille/G = getFromPool(/obj/structure/grille, src.loc)
+ var/obj/structure/grille/G = new /obj/structure/grille(src.loc)
handle_grille_spawn(G)
var/list/neighbours = list()
for (var/dir in cardinal)
@@ -49,7 +49,7 @@
found_connection = 1
qdel(W)
if(!found_connection)
- var/obj/structure/window/new_win = getFromPool(win_path, src.loc)
+ var/obj/structure/window/new_win = new win_path(src.loc)
new_win.set_dir(dir)
handle_window_spawn(new_win)
else
diff --git a/code/game/turfs/initialization/maintenance.dm b/code/game/turfs/initialization/maintenance.dm
index 833c0cd68dc..558f6385882 100644
--- a/code/game/turfs/initialization/maintenance.dm
+++ b/code/game/turfs/initialization/maintenance.dm
@@ -15,9 +15,10 @@
T.update_dirt()
if(prob(2))
- getFromPool(junk(), T)
+ var/type = junk()
+ new type(T)
if(prob(2))
- getFromPool(/obj/effect/decal/cleanable/blood/oil, T)
+ new /obj/effect/decal/cleanable/blood/oil(T)
if(prob(25)) // Keep in mind that only "corners" get any sort of web
attempt_web(T, cardinal_turfs)
@@ -54,7 +55,7 @@ var/global/list/random_junk
var/turf/neighbour = get_step(T, dir)
if(neighbour && neighbour.density)
if(dir == WEST)
- getFromPool(/obj/effect/decal/cleanable/cobweb, T)
+ new /obj/effect/decal/cleanable/cobweb(T)
if(dir == EAST)
- getFromPool(/obj/effect/decal/cleanable/cobweb2, T)
+ new /obj/effect/decal/cleanable/cobweb2(T)
return
diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm
index 11022e2f469..977d25059b5 100644
--- a/code/game/turfs/simulated.dm
+++ b/code/game/turfs/simulated.dm
@@ -14,8 +14,6 @@
var/max_fire_temperature_sustained = 0 //The max temperature of the fire which it was subjected to
var/dirt = 0
- var/datum/scheduled_task/unwet_task
-
// This is not great.
/turf/simulated/proc/wet_floor(var/wet_val = 1)
if(wet_val < wet)
@@ -26,22 +24,17 @@
wet_overlay = image('icons/effects/water.dmi',src,"wet_floor")
overlays += wet_overlay
- if(unwet_task)
- unwet_task.trigger_task_in(180 SECONDS)
- else
- unwet_task = schedule_task_in(180 SECONDS)
- task_triggered_event.register(unwet_task, src, /turf/simulated/proc/task_unwet_floor)
-
-/turf/simulated/proc/task_unwet_floor(var/triggered_task)
- if(triggered_task == unwet_task)
- unwet_task = null
- unwet_floor()
+ schedule_task_with_source_in(180 SECONDS, src, .proc/unwet_floor)
/turf/simulated/proc/unwet_floor()
- wet = 0
- if(wet_overlay)
- overlays -= wet_overlay
- wet_overlay = null
+ --wet
+ if (wet < 1)
+ wet = 0
+ if(wet_overlay)
+ overlays -= wet_overlay
+ wet_overlay = null
+ else
+ schedule_task_with_source_in(180 SECONDS, src, .proc/unwet_floor)
/turf/simulated/clean_blood()
for(var/obj/effect/decal/cleanable/blood/B in contents)
@@ -54,11 +47,6 @@
holy = 1
levelupdate()
-/turf/simulated/Destroy()
- qdel(unwet_task)
- unwet_task = null
- return ..()
-
/turf/simulated/proc/initialize()
return
diff --git a/code/game/turfs/simulated/wall_attacks.dm b/code/game/turfs/simulated/wall_attacks.dm
index 1db04cfef6c..104fc1802e9 100644
--- a/code/game/turfs/simulated/wall_attacks.dm
+++ b/code/game/turfs/simulated/wall_attacks.dm
@@ -24,15 +24,19 @@
can_open = WALL_CAN_OPEN
update_icon()
-/turf/simulated/wall/proc/fail_smash(var/mob/user)
+/turf/simulated/wall/proc/fail_smash(var/mob/user, var/multiplier = 1)
+ user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN*2.5)
user << "You smash against the wall!"
- take_damage(rand(25,75))
+ user.do_attack_animation(src)
+ take_damage(rand(60,135)*multiplier)
+ return 1
/turf/simulated/wall/proc/success_smash(var/mob/user)
user << "You smash through the wall!"
user.do_attack_animation(src)
spawn(1)
dismantle_wall(1)
+ return 1
/turf/simulated/wall/proc/try_touch(var/mob/user, var/rotting)
@@ -64,7 +68,7 @@
if (rotting || !prob(material.hardness))
success_smash(user)
else
- fail_smash(user)
+ fail_smash(user, 2)
return 1
try_touch(user, rotting)
@@ -72,21 +76,21 @@
/turf/simulated/wall/attack_generic(var/mob/user, var/damage, var/attack_message, var/wallbreaker)
radiate()
- user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
var/rotting = (locate(/obj/effect/overlay/wallrot) in src)
if(!damage || !wallbreaker)
try_touch(user, rotting)
return
+
if(rotting)
return success_smash(user)
if(reinf_material)
- if((wallbreaker == 2) || (damage >= max(material.hardness,reinf_material.hardness)))
+ if((wallbreaker == 2) && (damage >= max(material.hardness,reinf_material.hardness)))
return success_smash(user)
else if(damage >= material.hardness)
return success_smash(user)
- return fail_smash(user)
+ return fail_smash(user, wallbreaker)
/turf/simulated/wall/attackby(obj/item/weapon/W as obj, mob/user as mob)
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index 67d55d583dc..2775ca50cbd 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -143,7 +143,7 @@ var/const/enterloopsanity = 100
M.make_floating(0)
..()
var/objects = 0
- if(A && (A.flags & PROXMOVE))
+ if(A && (A.flags & PROXMOVE) && A.simulated)
for(var/atom/movable/thing in range(1))
if(objects > enterloopsanity) break
objects++
diff --git a/code/game/turfs/turf_changing.dm b/code/game/turfs/turf_changing.dm
index 8797e040811..331d10b3e5e 100644
--- a/code/game/turfs/turf_changing.dm
+++ b/code/game/turfs/turf_changing.dm
@@ -69,6 +69,7 @@
W.post_change()
. = W
+ recalc_atom_opacity()
lighting_overlay = old_lighting_overlay
affecting_lights = old_affecting_lights
corners = old_corners
diff --git a/code/global.dm b/code/global.dm
index d4adf226408..700bdc2717b 100644
--- a/code/global.dm
+++ b/code/global.dm
@@ -15,6 +15,7 @@ var/global/list/active_diseases = list()
var/global/list/med_hud_users = list() // List of all entities using a medical HUD.
var/global/list/sec_hud_users = list() // List of all entities using a security HUD.
var/global/list/hud_icon_reference = list()
+var/global/list/janitorial_supplies = list() // List of all the janitorial supplies on the map that the PDA cart may be tracking.
var/global/list/global_mutations = list() // List of hidden mutation things.
diff --git a/code/modules/admin/verbs/bluespacetech.dm b/code/modules/admin/verbs/bluespacetech.dm
index 2e35869ee97..f25a668b327 100644
--- a/code/modules/admin/verbs/bluespacetech.dm
+++ b/code/modules/admin/verbs/bluespacetech.dm
@@ -349,7 +349,7 @@
//Headset
/obj/item/device/radio/headset/ert/bst
- name = "\improper Bluespace Technician's headset"
+ name = "bluespace technician's headset"
desc = "A Bluespace Technician's headset. The letters 'BST' are stamped on the side."
translate_binary = 1
translate_hive = 1
@@ -375,7 +375,7 @@
//Clothes
/obj/item/clothing/under/rank/centcom_officer/bst
- name = "\improper Bluespace Technician's Uniform"
+ name = "bluespace technician's uniform"
desc = "A Bluespace Technician's Uniform. There is a logo on the sleeve that reads 'BST'."
has_sensor = 0
sensor_mode = 0
@@ -395,7 +395,7 @@
//Gloves
/obj/item/clothing/gloves/swat/bst
- name = "\improper Bluespace Technician's gloves"
+ name = "bluespace technician's gloves"
desc = "A pair of modified gloves. The letters 'BST' are stamped on the side."
siemens_coefficient = 0
permeability_coefficient = 0
@@ -412,7 +412,7 @@
//Sunglasses
/obj/item/clothing/glasses/sunglasses/bst
- name = "\improper Bluespace Technician's Glasses"
+ name = "bluespace technician's glasses"
desc = "A pair of modified sunglasses. The word 'BST' is stamped on the side."
// var/list/obj/item/clothing/glasses/hud/health/hud = null
vision_flags = (SEE_TURFS|SEE_OBJS|SEE_MOBS)
@@ -435,7 +435,7 @@
//Shoes
/obj/item/clothing/shoes/black/bst
- name = "\improper Bluespace Technician's shoes"
+ name = "bluespace technician's shoes"
desc = "A pair of black shoes with extra grip. The letters 'BST' are stamped on the side."
icon_state = "black"
flags = NOSLIP
diff --git a/code/modules/antag_contest/contest_helpers.dm b/code/modules/antag_contest/contest_helpers.dm
index 53235d77b50..3bef7a99c5d 100644
--- a/code/modules/antag_contest/contest_helpers.dm
+++ b/code/modules/antag_contest/contest_helpers.dm
@@ -42,3 +42,14 @@
antag_contest_side = ANTI_SYNTH
else
antag_contest_side = 0
+
+
+/mob/living/carbon/human/proc/implant_loyalty_sol(mob/living/carbon/human/M, override = FALSE) // Won't override by default.
+
+ var/obj/item/weapon/implant/loyalty/sol/L = new/obj/item/weapon/implant/loyalty/sol(M)
+ L.imp_in = M
+ L.implanted = 1
+ var/obj/item/organ/external/affected = M.organs_by_name["head"]
+ affected.implants += L
+ L.part = affected
+ L.implanted(src)
\ No newline at end of file
diff --git a/code/modules/antag_contest/sol_items.dm b/code/modules/antag_contest/sol_items.dm
new file mode 100644
index 00000000000..e5b164d3fb7
--- /dev/null
+++ b/code/modules/antag_contest/sol_items.dm
@@ -0,0 +1,299 @@
+/*
+ * Sol Alliance military related items
+ */
+
+
+/obj/item/weapon/implant/loyalty/sol
+ name = "loyalty implant"
+ desc = "Makes you loyal to the Sol Alliance, or to a certain individual."
+
+/obj/item/weapon/implant/loyalty/sol/implanted(mob/M)
+ if(!istype(M, /mob/living/carbon/human)) return 0
+ var/mob/living/carbon/human/H = M
+ var/datum/antagonist/antag_data = get_antag_data(H.mind.special_role)
+ if(antag_data && (antag_data.flags & ANTAG_IMPLANT_IMMUNE))
+ H.visible_message("[H] seems to resist the implant!", "You feel the tendrils of the Sol Alliance try to invade your mind!")
+ return 0
+ else
+ clear_antag_roles(H.mind, 1)
+ H << "You feel a surge of loyalty towards Admiral Michael Frost."
+ return 1
+
+
+//sol uniforms
+
+/obj/item/clothing/under/rank/fatigues //regular sol navy combat fatigues
+ name = "sol navy fatigues"
+ desc = "Military looking uniform issued to Sol Alliance navy, to be used while in the field."
+ icon = 'icons/obj/sol_uniform.dmi'
+ icon_state = "sol_uniform"
+ item_state = "sol_uniform"
+ contained_sprite = 1
+ armor = list(melee = 10, bullet = 10, laser = 10,energy = 0, bomb = 0, bio = 0, rad = 0)
+
+/obj/item/clothing/under/rank/fatigues/marine //regular sol navy marine fatigues
+ name = "sol marine fatigues"
+ desc = "Military looking uniform issued to Sol Alliance marines, to be used while in the field."
+ icon = 'icons/obj/sol_uniform.dmi'
+ icon_state = "marine_fatigue"
+ item_state = "marine_fatigue"
+ contained_sprite = 1
+
+/obj/item/clothing/under/rank/service //navy personnel service unniform
+ name = "sol navy service uniform"
+ desc = "Military looking service uniform issued to Sol Alliance navy members."
+ icon = 'icons/obj/sol_uniform.dmi'
+ icon_state = "whiteservice"
+ item_state = "whiteservice"
+ contained_sprite = 1
+
+/obj/item/clothing/under/rank/service/marine //sol marine service unniform
+ name = "sol marine service uniform"
+ desc = "Military looking service uniform issued to Sol Alliance marines."
+ icon = 'icons/obj/sol_uniform.dmi'
+ icon_state = "tanutility"
+ item_state = "tanutility"
+ contained_sprite = 1
+
+/obj/item/clothing/under/rank/dress //navy personnel dress unniform
+ name = "sol navy dress uniform"
+ desc = "A fancy military looking dress uniform issued to Sol Alliance navy members."
+ icon = 'icons/obj/sol_uniform.dmi'
+ icon_state = "sailor"
+ item_state = "sailor"
+ contained_sprite = 1
+
+/obj/item/clothing/under/rank/dress/marine //sol marine dress unniform
+ name = "sol marine dress uniform"
+ desc = "A fancy military looking dress uniform issued to Sol Alliance marine."
+ icon = 'icons/obj/sol_uniform.dmi'
+ icon_state = "mahreendress"
+ item_state = "mahreendress"
+ contained_sprite = 1
+
+/obj/item/clothing/under/rank/dress/officer //sol marine officer dress unniform
+ name = "sol navy commander dress uniform"
+ desc = "A fancy military looking dress uniform issued to high ranking Sol Alliance navy officers. This one wears the rank of Commander"
+ icon = 'icons/obj/sol_uniform.dmi'
+ icon_state = "dress"
+ item_state = "dress"
+ contained_sprite = 1
+
+/obj/item/clothing/under/rank/dress/subofficer //sol marine officer dress unniform
+ name = "sol navy lieutenant dress uniform"
+ desc = "A fancy military looking dress uniform issued to lower ranking Sol Alliance navy officers. This one wears the rank of Lieutenant"
+ icon = 'icons/obj/sol_uniform.dmi'
+ icon_state = "subdress"
+ item_state = "subdress"
+ contained_sprite = 1
+
+/obj/item/clothing/under/rank/dress/admiral //admiral uniform
+ name = "sol navy admiral uniform"
+ desc = "A fancy military dress uniform issued to a higher member of the Sol Alliance navy."
+ icon = 'icons/obj/sol_uniform.dmi'
+ icon_state = "admiral_uniform"
+ item_state = "admiral_uniform"
+ contained_sprite = 1
+
+//hats
+
+/obj/item/clothing/head/navy
+ name = "sol navy utility cover"
+ desc = "An eight pointed cover issued to Sol Alliance navy members as part of their field uniform."
+ icon = 'icons/obj/sol_uniform.dmi'
+ icon_state = "greyutility"
+ item_state = "greyutility"
+ contained_sprite = 1
+ armor = list(melee = 10, bullet = 10, laser = 10,energy = 0, bomb = 0, bio = 0, rad = 0)
+
+/obj/item/clothing/head/navy/marine
+ name = "sol marine utility cover"
+ desc = "An eight pointed cover issued to Sol Alliance marines as part of their field uniform."
+ icon = 'icons/obj/sol_uniform.dmi'
+ icon_state = "greenutility"
+ item_state = "greenutility"
+ contained_sprite = 1
+
+/obj/item/clothing/head/navy/garrison
+ name = "sol marine garrison cap"
+ desc = "A green garrison cap issued to Sol Alliance marines."
+ icon = 'icons/obj/sol_uniform.dmi'
+ icon_state = "greengarrisoncap"
+ item_state = "greengarrisoncap"
+ contained_sprite = 1
+
+/obj/item/clothing/head/dress
+ name = "sol navy dress cap"
+ desc = "A white cap issued as part of the Sol Alliance navy dress uniform."
+ icon = 'icons/obj/sol_uniform.dmi'
+ icon_state = "whitepeakcap"
+ item_state = "whitepeakcap"
+ contained_sprite = 1
+
+/obj/item/clothing/head/dress/marine
+ name = "sol marine dress cap"
+ desc = "A green cap issued as part of the Sol Alliance marine dress uniform."
+ icon = 'icons/obj/sol_uniform.dmi'
+ icon_state = "whitepeakcap"
+ item_state = "whitepeakcap"
+ contained_sprite = 1
+
+/obj/item/clothing/head/dress/officer
+ name = "sol navy officer dress cap"
+ desc = "A white cap issued as part of the Sol Alliance navy officers dress uniform."
+ icon = 'icons/obj/sol_uniform.dmi'
+ icon_state = "whitewheelcap"
+ item_state = "whitewheelcap"
+ contained_sprite = 1
+
+/obj/item/clothing/head/dress/admiral
+ name = "sol navy admiral dress cap"
+ desc = "A fancy looking cap issued to a higher member of the Sol Alliance navy."
+ icon = 'icons/obj/sol_uniform.dmi'
+ icon_state = "admiral_cap"
+ item_state = "admiral_cap"
+ contained_sprite = 1
+
+//ceremonial swords
+
+/obj/item/weapon/melee/ceremonial_sword
+ name = "sol officer ceremonial sword"
+ desc = "A ceremonial sword issued to Sol navy officers as part of their dress uniform."
+ icon = 'icons/obj/sol_uniform.dmi'
+ icon_state = "officersword"
+ item_state = "officersword"
+ contained_sprite = 1
+ flags = CONDUCT
+ slot_flags = SLOT_BELT
+ force = 15
+ throwforce = 5
+ w_class = 4
+ sharp = 1
+ edge = 1
+ can_embed = 0
+ origin_tech = list(TECH_COMBAT = 4)
+ attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
+ hitsound = 'sound/weapons/bladeslice.ogg'
+
+/obj/item/weapon/melee/ceremonial_sword/marine
+ name = "sol marine ceremonial sword"
+ desc = "A ceremonial sword issued to Sol marine officers as part of their dress uniform."
+ icon = 'icons/obj/sol_uniform.dmi'
+ icon_state = "marineofficersword"
+ item_state = "marineofficersword"
+ contained_sprite = 1
+
+//closet uniform
+
+/obj/structure/closet/sol
+ name = "sol navy uniform closet"
+ desc = "It's a storage unit for Sol Alliance navy uniforms."
+ icon_state = "syndicate1"
+ icon_closed = "syndicate1"
+ icon_opened = "syndicate1open"
+
+/obj/structure/closet/sol/navy/New()
+ ..()
+ new /obj/item/clothing/under/rank/fatigues(src)
+ new /obj/item/clothing/under/rank/fatigues(src)
+ new /obj/item/clothing/under/rank/fatigues(src)
+ new /obj/item/clothing/under/rank/service(src)
+ new /obj/item/clothing/under/rank/service(src)
+ new /obj/item/clothing/under/rank/service(src)
+ new /obj/item/clothing/head/navy(src)
+ new /obj/item/clothing/head/navy(src)
+ new /obj/item/clothing/head/navy(src)
+ new /obj/item/clothing/shoes/jackboots(src)
+ new /obj/item/clothing/shoes/jackboots(src)
+ new /obj/item/clothing/shoes/jackboots(src)
+
+/obj/structure/closet/sol/marine
+ name = "sol marines uniform closet"
+ desc = "It's a storage unit for Sol Alliance marine uniforms."
+
+/obj/structure/closet/sol/marine/New()
+ ..()
+ new /obj/item/clothing/under/rank/fatigues/marine(src)
+ new /obj/item/clothing/under/rank/fatigues/marine(src)
+ new /obj/item/clothing/under/rank/fatigues/marine(src)
+ new /obj/item/clothing/under/rank/service/marine(src)
+ new /obj/item/clothing/under/rank/service/marine(src)
+ new /obj/item/clothing/under/rank/service/marine(src)
+ new /obj/item/clothing/head/navy/marine(src)
+ new /obj/item/clothing/head/navy/marine(src)
+ new /obj/item/clothing/head/navy/garrison(src)
+ new /obj/item/clothing/shoes/jackboots(src)
+ new /obj/item/clothing/shoes/jackboots(src)
+ new /obj/item/clothing/shoes/jackboots(src)
+
+/obj/structure/closet/sol/navy_dress
+ name = "sol navy dress uniform closet"
+ desc = "It's a storage unit for Sol Alliance navy dress uniforms."
+
+/obj/structure/closet/sol/navy_dress/New()
+ ..()
+ new /obj/item/clothing/under/rank/dress(src)
+ new /obj/item/clothing/under/rank/dress(src)
+ new /obj/item/clothing/under/rank/dress(src)
+ new /obj/item/clothing/head/dress(src)
+ new /obj/item/clothing/head/dress(src)
+ new /obj/item/clothing/head/dress(src)
+ new /obj/item/clothing/shoes/laceup(src)
+ new /obj/item/clothing/shoes/laceup(src)
+ new /obj/item/clothing/shoes/laceup(src)
+ new /obj/item/clothing/gloves/white(src)
+ new /obj/item/clothing/gloves/white(src)
+ new /obj/item/clothing/gloves/white(src)
+
+/obj/structure/closet/sol/marine_dress
+ name = "sol marine dress uniform closet"
+ desc = "It's a storage unit for Sol Alliance marine dress uniforms."
+
+/obj/structure/closet/sol/marine_dress/New()
+ ..()
+ new /obj/item/clothing/under/rank/dress/marine(src)
+ new /obj/item/clothing/under/rank/dress/marine(src)
+ new /obj/item/clothing/under/rank/dress/marine(src)
+ new /obj/item/clothing/head/dress/marine(src)
+ new /obj/item/clothing/head/dress/marine(src)
+ new /obj/item/clothing/head/dress/marine(src)
+ new /obj/item/clothing/shoes/laceup(src)
+ new /obj/item/clothing/shoes/laceup(src)
+ new /obj/item/clothing/shoes/laceup(src)
+ new /obj/item/clothing/gloves/white(src)
+ new /obj/item/clothing/gloves/white(src)
+ new /obj/item/clothing/gloves/white(src)
+
+/obj/structure/closet/secure_closet/soll_officer
+ name = "sol alliance officer locker"
+ req_access = list(access_captain)
+ icon_state = "capsecure1"
+ icon_closed = "capsecure"
+ icon_locked = "capsecure1"
+ icon_opened = "capsecureopen"
+ icon_broken = "capsecurebroken"
+ icon_off = "capsecureoff"
+
+/obj/structure/closet/secure_closet/soll_officer/New()
+ ..()
+ if(prob(50))
+ new /obj/item/weapon/storage/backpack/captain(src)
+ else
+ new /obj/item/weapon/storage/backpack/satchel_cap(src)
+ new /obj/item/clothing/under/rank/dress/officer(src)
+ new /obj/item/clothing/head/dress/officer(src)
+ new /obj/item/clothing/suit/storage/vest(src)
+ new /obj/item/weapon/cartridge/captain(src)
+ new /obj/item/clothing/head/helmet(src)
+ new /obj/item/clothing/shoes/laceup(src)
+ new /obj/item/device/radio/headset/heads/captain(src)
+ new /obj/item/clothing/gloves/white(src)
+ new /obj/item/weapon/gun/energy/pistol(src)
+ new /obj/item/device/flash(src)
+ new /obj/item/weapon/melee/telebaton(src)
+ new /obj/item/weapon/melee/ceremonial_sword(src)
+ new /obj/item/clothing/under/rank/fatigues(src)
+ new /obj/item/clothing/under/rank/service(src)
+ new /obj/item/clothing/shoes/jackboots(src)
+ new /obj/item/clothing/accessory/holster/armpit(src)
+ return
diff --git a/code/modules/cargo/randomstock.dm b/code/modules/cargo/randomstock.dm
index cfa4149685d..1efaea7d4f3 100644
--- a/code/modules/cargo/randomstock.dm
+++ b/code/modules/cargo/randomstock.dm
@@ -134,6 +134,7 @@ var/list/global/random_stock_common = list(
"paicard" = 2,
"phoronsheets" = 2,
"hide" = 1,
+ "paint" = 0.5,
"nothing" = 0)
var/list/global/random_stock_uncommon = list(
@@ -177,7 +178,6 @@ var/list/global/random_stock_uncommon = list(
"crimekit" = 1,
"carpet" = 2,
"gift" = 4,
- "linenbin" = 1,
"coatrack" = 1,
"riotshield" = 2,
"fireaxe" = 1,
@@ -203,6 +203,7 @@ var/list/global/random_stock_uncommon = list(
"lizardhide" = 0.5,
"wintercoat" = 0.5,
"cookingoil" = 1,
+ "coin" = 1.3,
"nothing" = 0)
var/list/global/random_stock_rare = list(
@@ -214,7 +215,6 @@ var/list/global/random_stock_rare = list(
"combatmeds" = 3,
"batterer" = 0.75,
"posibrain" = 3,
- "thermals" = 0.75,
"bsbeaker" = 3,
"energyshield" = 2,
"hardsuit" = 0.75,
@@ -227,6 +227,7 @@ var/list/global/random_stock_rare = list(
"voice" = 1.5,
"xenohide" = 0.5,
"humanhide" = 0.5,
+ "modkit" = 1,
"nothing" = 0)
var/list/global/random_stock_large = list(
@@ -236,7 +237,7 @@ var/list/global/random_stock_large = list(
"tacticool" = 0.2,
"radsuit" = 3,
"exosuit" = 1.2,//A randomly generated exosuit in a very variable condition.
- "EOD" = 1.5,
+ "EOD" = 1.5,
"biosuit" = 3,
"hydrotray" = 3,
"oxycanister" = 6,//Cargo should almost always have an oxycanister
@@ -261,6 +262,7 @@ var/list/global/random_stock_large = list(
"jukebox" = 1.2,
"pipemachine" = 1.7,
"bike" = 0.3,
+ "sol" = 0.2,
"nothing" = 0)
@@ -987,13 +989,18 @@ var/list/global/random_stock_large = list(
if ("hide")
new /obj/item/stack/material/animalhide(L, rand(5,50))
-
-
-
-
-
-
-
+ if ("paint")
+ var/list/paints = list(
+ /obj/item/weapon/reagent_containers/glass/paint/red,
+ /obj/item/weapon/reagent_containers/glass/paint/yellow,
+ /obj/item/weapon/reagent_containers/glass/paint/green,
+ /obj/item/weapon/reagent_containers/glass/paint/blue,
+ /obj/item/weapon/reagent_containers/glass/paint/purple,
+ /obj/item/weapon/reagent_containers/glass/paint/black,
+ /obj/item/weapon/reagent_containers/glass/paint/white
+ )
+ var/type = pick(paints)
+ new type(L)
@@ -1067,7 +1074,8 @@ var/list/global/random_stock_large = list(
if ("flare")
new /obj/item/device/flashlight/flare(L)
new /obj/item/device/flashlight/flare(L)
- new /obj/item/device/flashlight/flare(L)
+ if (prob(50))
+ new /obj/random/glowstick(L)
if("deathalarm")
new /obj/item/weapon/storage/box/cdeathalarm_kit(L)
if("trackimp")
@@ -1232,8 +1240,6 @@ var/list/global/random_stock_large = list(
new /obj/item/stack/tile/carpet(L, 50)
if ("gift")
new /obj/item/weapon/a_gift(L)
- if ("linenbin")
- new /obj/structure/bedsheetbin(get_turf(L))
if ("coatrack")
var/turf/T = get_turf(L)
if (!turf_clear(T))
@@ -1432,7 +1438,8 @@ var/list/global/random_stock_large = list(
break
new /obj/structure/reagent_dispensers/cookingoil(T)
-
+ if("coin")
+ new /obj/random/coin(L)
@@ -1502,8 +1509,6 @@ var/list/global/random_stock_large = list(
new /obj/item/device/batterer(L)
if("posibrain")
new /obj/item/device/mmi/digital/posibrain(L)
- if("thermals")
- new /obj/item/clothing/glasses/thermal(L)
if("bsbeaker")
new /obj/item/weapon/reagent_containers/glass/beaker/bluespace(L)
if (prob(50))
@@ -1521,7 +1526,8 @@ var/list/global/random_stock_large = list(
/obj/item/weapon/material/sword/rapier,
/obj/item/weapon/material/sword/longsword,
/obj/item/weapon/material/sword/trench,
- /obj/item/weapon/material/sword/sabre
+ /obj/item/weapon/material/sword/sabre,
+ /obj/item/weapon/material/sword/axe
)
var/type = pick(swords)
@@ -1542,8 +1548,8 @@ var/list/global/random_stock_large = list(
/obj/item/weapon/rig/ert/assetprotection = 0.05,
/obj/item/weapon/rig/light = 0.5,
/obj/item/weapon/rig/light/hacker = 0.8,
- /obj/item/weapon/rig/light/stealth = 1.5,
- /obj/item/weapon/rig/merc = 0.5,
+ /obj/item/weapon/rig/light/stealth = 0.5,
+ /obj/item/weapon/rig/merc/empty = 0.5,
/obj/item/weapon/rig/industrial = 3,
/obj/item/weapon/rig/eva = 3,
/obj/item/weapon/rig/ce = 2,
@@ -1606,10 +1612,24 @@ var/list/global/random_stock_large = list(
if("humanhide")
new /obj/item/stack/material/animalhide/human(L, rand(2,15))
+ if("modkit")
+ var/list/modkits = list(
+ /obj/item/device/kit/paint/ripley,
+ /obj/item/device/kit/paint/ripley/death,
+ /obj/item/device/kit/paint/ripley/flames_red,
+ /obj/item/device/kit/paint/ripley/flames_blue,
+ /obj/item/device/kit/paint/ripley/titan,
+ /obj/item/device/kit/paint/ripley/earth,
+ /obj/item/device/kit/paint/durand,
+ /obj/item/device/kit/paint/durand/seraph,
+ /obj/item/device/kit/paint/durand/phazon,
+ /obj/item/device/kit/paint/gygax,
+ /obj/item/device/kit/paint/gygax/darkgygax,
+ /obj/item/device/kit/paint/gygax/recitence
+ )
-
-
-
+ var/type = pick(modkits)
+ new type(L)
@@ -1799,6 +1819,12 @@ var/list/global/random_stock_large = list(
if ("bike")
new /obj/vehicle/bike(L)
+
+ if ("sol")
+ if (prob(50))
+ new /obj/structure/closet/sol/navy(L)
+ else
+ new /obj/structure/closet/sol/marine(L)
//This will be complex
//Spawns a random exosuit, Probably not in good condition
diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm
index 72cad917ada..5c67ae30d10 100644
--- a/code/modules/client/client procs.dm
+++ b/code/modules/client/client procs.dm
@@ -194,11 +194,6 @@
return
- // Antag contest shit
- if (href_list["contest_action"] && config.antag_contest_enabled)
- src.process_contest_topic(href_list)
- return
-
..() //redirect to hsrc.()
/client/proc/handle_spam_prevention(var/message, var/mute_type)
diff --git a/code/modules/client/preference_setup/general/01_basic.dm b/code/modules/client/preference_setup/general/01_basic.dm
index 71037aade69..0d2d0e7262c 100644
--- a/code/modules/client/preference_setup/general/01_basic.dm
+++ b/code/modules/client/preference_setup/general/01_basic.dm
@@ -105,12 +105,12 @@
return TOPIC_NOACTION
else if(href_list["namehelp"])
- alert(user, "Due to game mechanics, you are no longer able to edit the name for this character. The grace period offered is 5 days since the character's initial save.
If you have a need to change the character's name, or further questions regarding this policy, please contact an administrator.")
+ alert(user, "Due to game mechanics, you are no longer able to edit the name for this character. The grace period offered is 5 days since the character's initial save.\n\nIf you have a need to change the character's name, or further questions regarding this policy, please contact an administrator.")
return TOPIC_NOACTION
else if(href_list["random_name"])
if (!pref.can_edit_name)
- alert(user, "You can no longer edit the name of your character.
"
if(!R.total_volume)
diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm
index d66a6a96c6d..032c7470ee6 100644
--- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm
+++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm
@@ -117,7 +117,9 @@
if(alien == IS_DIONA)
return //Diona can gain nutrients, but don't get drunk or suffer other effects
-
+
+ if(isunathi(M))//unathi are poisoned by alcohol as well
+ M.adjustToxLoss(2.5 * removed * (strength / 100))
var/quantity = (strength / 100) * removed
M.intoxication += quantity
diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm
index 36eb5e15b18..02328b537b9 100644
--- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm
+++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm
@@ -543,7 +543,7 @@
else
if(world.time > data + ANTIDEPRESSANT_MESSAGE_DELAY)
data = world.time
- if(prob(90))
+ if(prob(96))
M << "Your mind feels much more stable."
else
M << "Your mind breaks apart..."
diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm
index 8f7d494e6b0..69495a4bd43 100644
--- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm
+++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm
@@ -176,6 +176,13 @@
strength = 0.5 // It's not THAT poisonous.
color = "#664330"
+/datum/reagent/toxin/fertilizer/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
+ if(alien == IS_DIONA)
+ M.nutrition += removed*3
+ //Fertilizer is good for plants
+ else
+ ..()
+
/datum/reagent/toxin/fertilizer/eznutrient
name = "EZ Nutrient"
id = "eznutrient"
@@ -195,7 +202,7 @@
reagent_state = LIQUID
color = "#49002E"
strength = 4
- metabolism = REM * 0.35
+ metabolism = REM*1.5
/datum/reagent/toxin/plantbgone/touch_turf(var/turf/T)
if(istype(T, /turf/simulated/wall))
@@ -212,12 +219,12 @@
/datum/reagent/toxin/plantbgone/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
..()
if(alien == IS_DIONA)
- M.adjustToxLoss(50 * removed)
+ M.adjustToxLoss(8 * removed)
+//Affect touch automatically transfers to affect_blood, so we'll apply the damage there, after accounting for permeability
/datum/reagent/toxin/plantbgone/affect_touch(var/mob/living/carbon/M, var/alien, var/removed)
- ..()
- if(alien == IS_DIONA)
- M.adjustToxLoss(50 * removed)
+ removed *= M.reagent_permeability()
+ affect_blood(M, alien, removed*0.5)
/datum/reagent/acid/polyacid
name = "Polytrinic acid"
diff --git a/code/modules/reagents/dispenser/cartridge.dm b/code/modules/reagents/dispenser/cartridge.dm
index 2f7369cba0d..570fb0b0742 100644
--- a/code/modules/reagents/dispenser/cartridge.dm
+++ b/code/modules/reagents/dispenser/cartridge.dm
@@ -36,6 +36,13 @@
set category = "Object"
set src in view(usr, 1)
+ if (!ishuman(usr))
+ return
+
+ if (usr.stat)
+ usr << "You cannot do that in your current state."
+ return
+
setLabel(L, usr)
/obj/item/weapon/reagent_containers/chem_disp_cartridge/proc/setLabel(L, mob/user = null)
diff --git a/code/modules/reagents/reagent_containers/food/cans.dm b/code/modules/reagents/reagent_containers/food/cans.dm
index 7d72b8bf51f..5b19b671409 100644
--- a/code/modules/reagents/reagent_containers/food/cans.dm
+++ b/code/modules/reagents/reagent_containers/food/cans.dm
@@ -6,7 +6,7 @@
//DRINKS
/obj/item/weapon/reagent_containers/food/drinks/cans/cola
- name = "\improper Space Cola"
+ name = "space cola"
desc = "Cola. in space."
icon_state = "cola"
center_of_mass = list("x"=16, "y"=10)
@@ -33,7 +33,7 @@
reagents.add_reagent("spacemountainwind", 30)
/obj/item/weapon/reagent_containers/food/drinks/cans/thirteenloko
- name = "\improper Thirteen Loko"
+ name = "thirteen loko"
desc = "The CMO has advised crew members that consumption of Thirteen Loko may result in seizures, blindness, drunkeness, or even death. Please Drink Responsibly."
icon_state = "thirteen_loko"
center_of_mass = list("x"=16, "y"=8)
@@ -78,7 +78,7 @@
reagents.add_reagent("lemon_lime", 30)
/obj/item/weapon/reagent_containers/food/drinks/cans/iced_tea
- name = "\improper Vrisk Serket Iced Tea"
+ name = "\improper Vrisk Serket iced tea"
desc = "That sweet, refreshing southern earthy flavor. That's where it's from, right? South Earth?"
icon_state = "ice_tea_can"
center_of_mass = list("x"=16, "y"=10)
@@ -87,7 +87,7 @@
reagents.add_reagent("icetea", 30)
/obj/item/weapon/reagent_containers/food/drinks/cans/grape_juice
- name = "\improper Grapel Juice"
+ name = "\improper Grapel juice"
desc = "500 pages of rules of how to appropriately enter into a combat with this juice!"
icon_state = "purple_can"
center_of_mass = list("x"=16, "y"=10)
@@ -96,7 +96,7 @@
reagents.add_reagent("grapejuice", 30)
/obj/item/weapon/reagent_containers/food/drinks/cans/tonic
- name = "\improper T-Borg's Tonic Water"
+ name = "\improper T-Borg's tonic water"
desc = "Quinine tastes funny, but at least it'll keep that Space Malaria away."
icon_state = "tonic"
center_of_mass = list("x"=16, "y"=10)
diff --git a/code/modules/reagents/reagent_containers/food/condiment.dm b/code/modules/reagents/reagent_containers/food/condiment.dm
index c6300a15628..e320c66b52a 100644
--- a/code/modules/reagents/reagent_containers/food/condiment.dm
+++ b/code/modules/reagents/reagent_containers/food/condiment.dm
@@ -6,7 +6,7 @@
//Food items that aren't eaten normally and leave an empty container behind.
/obj/item/weapon/reagent_containers/food/condiment
- name = "Condiment Container"
+ name = "condiment container"
desc = "Just your average condiment container."
icon = 'icons/obj/food.dmi'
icon_state = "emptycondiment"
@@ -58,51 +58,51 @@
if(reagents.reagent_list.len > 0)
switch(reagents.get_master_reagent_id())
if("ketchup")
- name = "Ketchup"
+ name = "ketchup"
desc = "You feel more American already."
icon_state = "ketchup"
center_of_mass = list("x"=16, "y"=6)
if("capsaicin")
- name = "Hotsauce"
+ name = "hotsauce"
desc = "You can almost TASTE the stomach ulcers now!"
icon_state = "hotsauce"
center_of_mass = list("x"=16, "y"=6)
if("enzyme")
- name = "Universal Enzyme"
+ name = "universal enzyme"
desc = "Used in cooking various dishes."
icon_state = "enzyme"
center_of_mass = list("x"=16, "y"=6)
if("soysauce")
- name = "Soy Sauce"
+ name = "soy sauce"
desc = "A salty soy-based flavoring."
icon_state = "soysauce"
center_of_mass = list("x"=16, "y"=6)
if("frostoil")
- name = "Coldsauce"
+ name = "coldsauce"
desc = "Leaves the tongue numb in its passage."
icon_state = "coldsauce"
center_of_mass = list("x"=16, "y"=6)
if("sodiumchloride")
- name = "Salt Shaker"
+ name = "salt shaker"
desc = "Salt. From space oceans, presumably."
icon_state = "saltshaker"
center_of_mass = list("x"=16, "y"=10)
if("blackpepper")
- name = "Pepper Mill"
+ name = "pepper mill"
desc = "Often used to flavor food or make people sneeze."
icon_state = "peppermillsmall"
center_of_mass = list("x"=16, "y"=10)
if("cornoil")
- name = "Corn Oil"
+ name = "corn oil"
desc = "A delicious oil used in cooking. Made from corn."
icon_state = "oliveoil"
center_of_mass = list("x"=16, "y"=6)
if("sugar")
- name = "Sugar"
+ name = "sugar"
desc = "Tastey space sugar!"
center_of_mass = list("x"=16, "y"=6)
else
- name = "Misc Condiment Bottle"
+ name = "misc condiment bottle"
if (reagents.reagent_list.len==1)
desc = "Looks like it is [reagents.get_master_reagent_name()], but you are not sure."
else
@@ -111,13 +111,13 @@
center_of_mass = list("x"=16, "y"=6)
else
icon_state = "emptycondiment"
- name = "Condiment Bottle"
+ name = "condiment bottle"
desc = "An empty condiment bottle."
center_of_mass = list("x"=16, "y"=6)
return
/obj/item/weapon/reagent_containers/food/condiment/enzyme
- name = "Universal Enzyme"
+ name = "universal enzyme"
desc = "Used in cooking various dishes."
icon_state = "enzyme"
New()
@@ -130,7 +130,7 @@
reagents.add_reagent("sugar", 50)
/obj/item/weapon/reagent_containers/food/condiment/saltshaker //Seperate from above since it's a small shaker rather then
- name = "Salt Shaker" // a large one.
+ name = "salt shaker" // a large one.
desc = "Salt. From space oceans, presumably."
icon_state = "saltshakersmall"
possible_transfer_amounts = list(1,20) //for clown turning the lid off
@@ -141,7 +141,7 @@
reagents.add_reagent("sodiumchloride", 20)
/obj/item/weapon/reagent_containers/food/condiment/peppermill
- name = "Pepper Mill"
+ name = "pepper mill"
desc = "Often used to flavor food or make people sneeze."
icon_state = "peppermillsmall"
possible_transfer_amounts = list(1,20) //for clown turning the lid off
diff --git a/code/modules/reagents/reagent_containers/food/drinks.dm b/code/modules/reagents/reagent_containers/food/drinks.dm
index 0820f4445d1..f92818a48e7 100644
--- a/code/modules/reagents/reagent_containers/food/drinks.dm
+++ b/code/modules/reagents/reagent_containers/food/drinks.dm
@@ -102,7 +102,7 @@
// Formatting is the same as food.
/obj/item/weapon/reagent_containers/food/drinks/milk
- name = "Space Milk"
+ name = "space milk"
desc = "It's milk. White and nutritious goodness!"
icon_state = "milk"
item_state = "carton"
@@ -112,7 +112,7 @@
reagents.add_reagent("milk", 50)
/obj/item/weapon/reagent_containers/food/drinks/soymilk
- name = "SoyMilk"
+ name = "soymilk"
desc = "It's soy milk. White and nutritious goodness!"
icon_state = "soymilk"
item_state = "carton"
@@ -122,7 +122,7 @@
reagents.add_reagent("soymilk", 50)
/obj/item/weapon/reagent_containers/food/drinks/coffee
- name = "Robust Coffee"
+ name = "Robust coffee"
desc = "Careful, the beverage you're about to enjoy is extremely hot."
icon_state = "coffee"
center_of_mass = list("x"=15, "y"=10)
@@ -131,7 +131,7 @@
reagents.add_reagent("coffee", 30)
/obj/item/weapon/reagent_containers/food/drinks/tea
- name = "Duke Purple Tea"
+ name = "Duke purple tea"
desc = "An insult to Duke Purple is an insult to the Space Queen! Any proper gentleman will fight you, if you sully this tea."
icon_state = "teacup"
item_state = "coffee"
@@ -141,7 +141,7 @@
reagents.add_reagent("tea", 30)
/obj/item/weapon/reagent_containers/food/drinks/ice
- name = "Ice Cup"
+ name = "ice cup"
desc = "Careful, cold ice, do not chew."
icon_state = "coffee"
center_of_mass = list("x"=15, "y"=10)
@@ -150,7 +150,7 @@
reagents.add_reagent("ice", 30)
/obj/item/weapon/reagent_containers/food/drinks/h_chocolate
- name = "Dutch Hot Coco"
+ name = "dutch hot coco"
desc = "Made in Space South America."
icon_state = "hot_coco"
item_state = "coffee"
@@ -160,7 +160,7 @@
reagents.add_reagent("hot_coco", 30)
/obj/item/weapon/reagent_containers/food/drinks/dry_ramen
- name = "Cup Ramen"
+ name = "cup ramen"
desc = "Just add 10ml water, self heats! A taste that reminds you of your school years."
icon_state = "ramen"
center_of_mass = list("x"=16, "y"=11)
@@ -170,7 +170,7 @@
/obj/item/weapon/reagent_containers/food/drinks/sillycup
- name = "Paper Cup"
+ name = "paper cup"
desc = "A paper water cup."
icon_state = "water_cup_e"
possible_transfer_amounts = null
@@ -191,7 +191,7 @@
// icon states.
/obj/item/weapon/reagent_containers/food/drinks/shaker
- name = "Shaker"
+ name = "shaker"
desc = "A metal shaker to mix drinks in."
icon_state = "shaker"
amount_per_transfer_from_this = 10
@@ -208,7 +208,7 @@
center_of_mass = list("x"=17, "y"=7)
/obj/item/weapon/reagent_containers/food/drinks/flask
- name = "Captain's Flask"
+ name = "captain's flask"
desc = "A metal flask belonging to the captain"
icon_state = "flask"
volume = 60
@@ -225,7 +225,7 @@
icon_state = "lithiumflask"
/obj/item/weapon/reagent_containers/food/drinks/flask/detflask
- name = "Detective's Flask"
+ name = "detective's flask"
desc = "A metal flask with a leather band and golden badge belonging to the detective."
icon_state = "detflask"
volume = 60
diff --git a/code/modules/reagents/reagent_containers/food/drinks/bottle.dm b/code/modules/reagents/reagent_containers/food/drinks/bottle.dm
index 87f88c8e8e1..b3a44f0a5e9 100644
--- a/code/modules/reagents/reagent_containers/food/drinks/bottle.dm
+++ b/code/modules/reagents/reagent_containers/food/drinks/bottle.dm
@@ -151,7 +151,7 @@
//Keeping this here for now, I'll ask if I should keep it here.
/obj/item/weapon/broken_bottle
- name = "Broken Bottle"
+ name = "broken bottle"
desc = "A bottle with a sharp broken bottom."
icon = 'icons/obj/drinks.dmi'
icon_state = "broken_bottle"
@@ -171,7 +171,7 @@
/obj/item/weapon/reagent_containers/food/drinks/bottle/gin
- name = "Griffeater Gin"
+ name = "Griffeater gin"
desc = "A bottle of high quality gin, produced in the New London Space Station."
icon_state = "ginbottle"
center_of_mass = list("x"=16, "y"=4)
@@ -198,7 +198,7 @@
reagents.add_reagent("vodka", 100)
/obj/item/weapon/reagent_containers/food/drinks/bottle/tequilla
- name = "Caccavo Guaranteed Quality Tequilla"
+ name = "Caccavo Guaranteed Quality tequilla"
desc = "Made from premium petroleum distillates, pure thalidomide and other fine quality ingredients!"
icon_state = "tequillabottle"
center_of_mass = list("x"=16, "y"=3)
@@ -207,7 +207,7 @@
reagents.add_reagent("tequilla", 100)
/obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing
- name = "Bottle of Nothing"
+ name = "bottle of nothing"
desc = "A bottle filled with nothing"
icon_state = "bottleofnothing"
center_of_mass = list("x"=17, "y"=5)
@@ -216,7 +216,7 @@
reagents.add_reagent("nothing", 100)
/obj/item/weapon/reagent_containers/food/drinks/bottle/patron
- name = "Wrapp Artiste Patron"
+ name = "Wrapp Artiste patron"
desc = "Silver laced tequilla, served in space night clubs across the galaxy."
icon_state = "patronbottle"
center_of_mass = list("x"=16, "y"=6)
@@ -225,7 +225,7 @@
reagents.add_reagent("patron", 100)
/obj/item/weapon/reagent_containers/food/drinks/bottle/rum
- name = "Captain Pete's Cuban Spiced Rum"
+ name = "Captain Pete's Cuban Spiced rum"
desc = "This isn't just rum, oh no. It's practically GRIFF in a bottle."
icon_state = "rumbottle"
center_of_mass = list("x"=16, "y"=8)
@@ -234,7 +234,7 @@
reagents.add_reagent("rum", 100)
/obj/item/weapon/reagent_containers/food/drinks/bottle/holywater
- name = "Flask of Holy Water"
+ name = "flask of holy water"
desc = "A flask of the chaplain's holy water."
icon_state = "holyflask"
center_of_mass = list("x"=17, "y"=10)
@@ -243,7 +243,7 @@
reagents.add_reagent("holywater", 100)
/obj/item/weapon/reagent_containers/food/drinks/bottle/vermouth
- name = "Goldeneye Vermouth"
+ name = "Goldeneye vermouth"
desc = "Sweet, sweet dryness~"
icon_state = "vermouthbottle"
center_of_mass = list("x"=17, "y"=3)
@@ -252,7 +252,7 @@
reagents.add_reagent("vermouth", 100)
/obj/item/weapon/reagent_containers/food/drinks/bottle/kahlua
- name = "Robert Robust's Coffee Liqueur"
+ name = "Robert Robust's coffee liqueur"
desc = "A widely known, Mexican coffee-flavoured liqueur. In production since 1936, HONK"
icon_state = "kahluabottle"
center_of_mass = list("x"=17, "y"=3)
@@ -261,7 +261,7 @@
reagents.add_reagent("kahlua", 100)
/obj/item/weapon/reagent_containers/food/drinks/bottle/goldschlager
- name = "College Girl Goldschlager"
+ name = "College Girl goldschlager"
desc = "Because they are the only ones who will drink 100 proof cinnamon schnapps."
icon_state = "goldschlagerbottle"
center_of_mass = list("x"=15, "y"=3)
@@ -270,7 +270,7 @@
reagents.add_reagent("goldschlager", 100)
/obj/item/weapon/reagent_containers/food/drinks/bottle/cognac
- name = "Chateau De Baton Premium Cognac"
+ name = "Chateau De Baton Premium cognac"
desc = "A sweet and strongly alchoholic drink, made after numerous distillations and years of maturing. You might as well not scream 'SHITCURITY' this time."
icon_state = "cognacbottle"
center_of_mass = list("x"=16, "y"=6)
@@ -279,7 +279,7 @@
reagents.add_reagent("cognac", 100)
/obj/item/weapon/reagent_containers/food/drinks/bottle/wine
- name = "Doublebeard Bearded Special Wine"
+ name = "Doublebeard Bearded Special wine"
desc = "A faint aura of unease and asspainery surrounds the bottle."
icon_state = "winebottle"
center_of_mass = list("x"=16, "y"=4)
@@ -297,7 +297,7 @@
reagents.add_reagent("absinthe", 100)
/obj/item/weapon/reagent_containers/food/drinks/bottle/melonliquor
- name = "Emeraldine Melon Liquor"
+ name = "Emeraldine melon liquor"
desc = "A bottle of 46 proof Emeraldine Melon Liquor. Sweet and light."
icon_state = "alco-green" //Placeholder.
center_of_mass = list("x"=16, "y"=6)
@@ -306,7 +306,7 @@
reagents.add_reagent("melonliquor", 100)
/obj/item/weapon/reagent_containers/food/drinks/bottle/bluecuracao
- name = "Miss Blue Curacao"
+ name = "Miss blue curacao"
desc = "A fruity, exceptionally azure drink. Does not allow the imbiber to use the fifth magic."
icon_state = "alco-blue" //Placeholder.
center_of_mass = list("x"=16, "y"=6)
@@ -315,7 +315,7 @@
reagents.add_reagent("bluecuracao", 100)
/obj/item/weapon/reagent_containers/food/drinks/bottle/grenadine
- name = "Briar Rose Grenadine Syrup"
+ name = "Briar Rose grenadine syrup"
desc = "Sweet and tangy, a bar syrup used to add color or flavor to drinks."
icon_state = "grenadinebottle"
center_of_mass = list("x"=16, "y"=6)
@@ -324,7 +324,7 @@
reagents.add_reagent("grenadine", 100)
/obj/item/weapon/reagent_containers/food/drinks/bottle/cola
- name = "\improper Space Cola"
+ name = "space cola"
desc = "Cola. in space"
icon_state = "colabottle"
center_of_mass = list("x"=16, "y"=6)
@@ -362,7 +362,7 @@
//////////////////////////JUICES AND STUFF ///////////////////////
/obj/item/weapon/reagent_containers/food/drinks/bottle/orangejuice
- name = "Orange Juice"
+ name = "orange juice"
desc = "Full of vitamins and deliciousness!"
icon_state = "orangejuice"
item_state = "carton"
@@ -373,7 +373,7 @@
reagents.add_reagent("orangejuice", 100)
/obj/item/weapon/reagent_containers/food/drinks/bottle/cream
- name = "Milk Cream"
+ name = "milk cream"
desc = "It's cream. Made from milk. What else did you think you'd find in there?"
icon_state = "cream"
item_state = "carton"
@@ -384,7 +384,7 @@
reagents.add_reagent("cream", 100)
/obj/item/weapon/reagent_containers/food/drinks/bottle/tomatojuice
- name = "Tomato Juice"
+ name = "tomato juice"
desc = "Well, at least it LOOKS like tomato juice. You can't tell with all that redness."
icon_state = "tomatojuice"
item_state = "carton"
@@ -395,7 +395,7 @@
reagents.add_reagent("tomatojuice", 100)
/obj/item/weapon/reagent_containers/food/drinks/bottle/limejuice
- name = "Lime Juice"
+ name = "lime juice"
desc = "Sweet-sour goodness."
icon_state = "limejuice"
item_state = "carton"
@@ -425,7 +425,7 @@
reagents.add_reagent("beer", 30)
/obj/item/weapon/reagent_containers/food/drinks/bottle/small/ale
- name = "\improper Magm-Ale"
+ name = "\improper Magm-ale"
desc = "A true dorf's drink of choice."
icon_state = "alebottle"
item_state = "beer"
@@ -437,7 +437,7 @@
//aurora's drinks
/obj/item/weapon/reagent_containers/food/drinks/bottle/chartreusegreen
- name = "Green Chartreuse"
+ name = "green chartreuse"
desc = "A green, strong liqueur."
icon_state = "chartreusegreenbottle"
New()
@@ -445,7 +445,7 @@
reagents.add_reagent("chartreusegreen", 100)
/obj/item/weapon/reagent_containers/food/drinks/bottle/chartreuseyellow
- name = "Yellow Chartreuse"
+ name = "yellow chartreuse"
desc = "A yellow, strong liqueur."
icon_state = "chartreuseyellowbottle"
New()
@@ -453,7 +453,7 @@
reagents.add_reagent("chartreuseyellow", 100)
/obj/item/weapon/reagent_containers/food/drinks/bottle/cremewhite
- name = "White Creme de Menthe"
+ name = "white creme de menthe"
desc = "Mint-flavoured alcohol, in a bottle."
icon_state = "whitecremebottle"
New()
@@ -469,7 +469,7 @@
reagents.add_reagent("cremeyvette", 100)
/obj/item/weapon/reagent_containers/food/drinks/bottle/brandy
- name = "Brandy"
+ name = "brandy"
desc = "Cheap knock off for cognac."
icon_state = "brandybottle"
New()
@@ -493,7 +493,7 @@
reagents.add_reagent("drambuie", 100)
/obj/item/weapon/reagent_containers/food/drinks/bottle/sbiten
- name = "Sbiten"
+ name = "sbiten"
desc = "A bottle full of sweet sbiten."
icon_state = "sbitenbottle"
New()
diff --git a/code/modules/reagents/reagent_containers/food/drinks/drinkingglass.dm b/code/modules/reagents/reagent_containers/food/drinks/drinkingglass.dm
index c7f0f0a9fee..e722e791a8b 100644
--- a/code/modules/reagents/reagent_containers/food/drinks/drinkingglass.dm
+++ b/code/modules/reagents/reagent_containers/food/drinks/drinkingglass.dm
@@ -28,7 +28,7 @@
if(R.glass_name)
name = R.glass_name
else
- name = "Glass of.. what?"
+ name = "glass of.. what?"
if(R.glass_desc)
desc = R.glass_desc
diff --git a/code/modules/reagents/reagent_containers/food/lunch.dm b/code/modules/reagents/reagent_containers/food/lunch.dm
index 6392213adae..8c9a7ded478 100644
--- a/code/modules/reagents/reagent_containers/food/lunch.dm
+++ b/code/modules/reagents/reagent_containers/food/lunch.dm
@@ -10,7 +10,9 @@ var/list/lunchables_lunches_ = list(/obj/item/weapon/reagent_containers/food/sna
/obj/item/weapon/reagent_containers/food/snacks/liquidfood,
/obj/item/weapon/reagent_containers/food/snacks/jellysandwich/cherry,
/obj/item/weapon/reagent_containers/food/snacks/tossedsalad,
- /obj/item/weapon/reagent_containers/food/snacks/koiswaffles)
+ /obj/item/weapon/reagent_containers/food/snacks/koiswaffles,
+ /obj/item/weapon/reagent_containers/food/snacks/funnelcake,
+ /obj/item/weapon/reagent_containers/food/snacks/hotdog)
var/list/lunchables_snacks_ = list(/obj/item/weapon/reagent_containers/food/snacks/donut/jelly,
/obj/item/weapon/reagent_containers/food/snacks/donut/cherryjelly,
diff --git a/code/modules/reagents/reagent_containers/food/snacks.dm b/code/modules/reagents/reagent_containers/food/snacks.dm
index 46ea5d35e91..c0b2e1d23f9 100644
--- a/code/modules/reagents/reagent_containers/food/snacks.dm
+++ b/code/modules/reagents/reagent_containers/food/snacks.dm
@@ -401,7 +401,7 @@
//Here is an example of the new formatting for anyone who wants to add more food items.
///obj/item/weapon/reagent_containers/food/snacks/xenoburger //Identification path for the object.
-// name = "Xenoburger" //Name that displays in the UI.
+// name = "xenoburger" //Name that displays in the UI.
// desc = "Smells caustic. Tastes like heresy." //Duh
// icon_state = "xburger" //Refers to an icon in food.dmi
// New() //Don't mess with this.
@@ -413,7 +413,7 @@
/obj/item/weapon/reagent_containers/food/snacks/koisbar
- name = "K'ois Bar"
+ name = "k'ois bar"
desc = "Bland NanoTrasen produced K'ois bars, rich in syrup."
icon_state = "koisbar"
trash = /obj/item/trash/koisbar
@@ -425,7 +425,7 @@
bitesize = 5
/obj/item/weapon/reagent_containers/food/snacks/aesirsalad
- name = "Aesir salad"
+ name = "aesir salad"
desc = "Probably too incredible for mortal men to fully enjoy."
icon_state = "aesirsalad"
trash = /obj/item/trash/snack_bowl
@@ -454,7 +454,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/candy/donor
- name = "Donor Candy"
+ name = "donor candy"
desc = "A little treat for blood donors."
trash = /obj/item/trash/candy
@@ -503,7 +503,7 @@
bitesize = 1
/obj/item/weapon/reagent_containers/food/snacks/chocolatebar
- name = "Chocolate Bar"
+ name = "chocolate bar"
desc = "Such sweet, fattening food."
icon_state = "chocolatebar"
filling_color = "#7D5F46"
@@ -517,7 +517,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/chocolateegg
- name = "Chocolate Egg"
+ name = "chocolate egg"
desc = "Such sweet, fattening food."
icon_state = "chocolateegg"
filling_color = "#7D5F46"
@@ -555,7 +555,7 @@
center_of_mass = list("x"=19, "y"=16)
/obj/item/weapon/reagent_containers/food/snacks/donut/chaos
- name = "Chaos Donut"
+ name = "chaos donut"
desc = "Like life, it never quite tastes the same."
icon_state = "donut1"
filling_color = "#ED11E6"
@@ -595,7 +595,7 @@
/obj/item/weapon/reagent_containers/food/snacks/donut/jelly
- name = "Jelly Donut"
+ name = "jelly donut"
desc = "You jelly?"
icon_state = "jdonut1"
filling_color = "#ED1169"
@@ -614,7 +614,7 @@
reagents.add_reagent("sprinkles", 2)
/obj/item/weapon/reagent_containers/food/snacks/donut/slimejelly
- name = "Jelly Donut"
+ name = "jelly donut"
desc = "You jelly?"
icon_state = "jdonut1"
filling_color = "#ED1169"
@@ -633,7 +633,7 @@
reagents.add_reagent("sprinkles", 2)
/obj/item/weapon/reagent_containers/food/snacks/donut/cherryjelly
- name = "Jelly Donut"
+ name = "jelly donut"
desc = "You jelly?"
icon_state = "jdonut1"
filling_color = "#ED1169"
@@ -652,7 +652,7 @@
reagents.add_reagent("sprinkles", 2)
/obj/item/weapon/reagent_containers/food/snacks/funnelcake
- name = "Funnel cake"
+ name = "funnel cake"
desc = "Funnel cakes rule!"
icon_state = "funnelcake"
filling_color = "#Ef1479"
@@ -733,7 +733,7 @@
icon_state = "egg-yellow"
/obj/item/weapon/reagent_containers/food/snacks/friedegg
- name = "Fried egg"
+ name = "fried egg"
desc = "A fried egg, with a touch of salt and pepper."
icon_state = "friedegg"
filling_color = "#FFDF78"
@@ -747,7 +747,7 @@
bitesize = 1
/obj/item/weapon/reagent_containers/food/snacks/boiledegg
- name = "Boiled egg"
+ name = "boiled egg"
desc = "A hard boiled egg."
icon_state = "egg"
filling_color = "#FFFFFF"
@@ -771,7 +771,7 @@
src.bitesize = 3
/obj/item/weapon/reagent_containers/food/snacks/tofu
- name = "Tofu"
+ name = "tofu"
icon_state = "tofu"
desc = "We all love tofu."
filling_color = "#FFFEE0"
@@ -783,7 +783,7 @@
src.bitesize = 3
/obj/item/weapon/reagent_containers/food/snacks/tofurkey
- name = "Tofurkey"
+ name = "tofurkey"
desc = "A fake turkey made from tofu."
icon_state = "tofurkey"
filling_color = "#FFFEE0"
@@ -796,7 +796,7 @@
bitesize = 3
/obj/item/weapon/reagent_containers/food/snacks/stuffing
- name = "Stuffing"
+ name = "stuffing"
desc = "Moist, peppery breadcrumbs for filling the body cavities of dead birds. Dig in!"
icon_state = "stuffing"
filling_color = "#C9AC83"
@@ -821,7 +821,7 @@
src.bitesize = 6
/obj/item/weapon/reagent_containers/food/snacks/fishfingers
- name = "Fish Fingers"
+ name = "fish Fingers"
desc = "A finger of fish."
icon_state = "fishfingers"
filling_color = "#FFDEFE"
@@ -897,7 +897,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/sausage
- name = "Sausage"
+ name = "sausage"
desc = "A piece of mixed, long meat."
icon_state = "sausage"
filling_color = "#DB0000"
@@ -909,7 +909,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/sausage/battered
- name = "Battered Sausage"
+ name = "battered sausage"
desc = "A piece of mixed, long meat, battered and then deepfried"
icon_state = "batteredsausage"
filling_color = "#DB0000"
@@ -923,7 +923,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/jalapeno_poppers
- name = "Jalapeno Popper"
+ name = "jalapeno popper"
desc = "A battered, deep-fried chilli pepper"
icon_state = "popper"
filling_color = "#00AA00"
@@ -979,12 +979,18 @@
proc/cooltime()
if (src.warm)
spawn(4200)
- src.warm = 0
- for(var/reagent in heated_reagents)
- src.reagents.del_reagent(reagent)
- src.name = initial(name)
+ if(src)
+ src.warm = 0
+ for(var/reagent in heated_reagents)
+ src.reagents.del_reagent(reagent)
+ src.name = initial(name)
return
+/obj/item/weapon/reagent_containers/food/snacks/donkpocket/cook()
+ ..()
+ if (!warm)
+ heat()
+
/obj/item/weapon/reagent_containers/food/snacks/brainburger
name = "brainburger"
desc = "A strange looking burger. It looks almost sentient."
@@ -999,7 +1005,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/ghostburger
- name = "Ghost Burger"
+ name = "ghost burger"
desc = "Spooky! It doesn't look very filling."
icon_state = "ghostburger"
filling_color = "#FFF2FF"
@@ -1051,7 +1057,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/fishburger
- name = "Fillet -o- Carp Sandwich"
+ name = "fillet -o- carp sandwich"
desc = "Almost like a carp is yelling somewhere... Give me back that fillet -o- carp, give me that carp."
icon_state = "fishburger"
filling_color = "#FFDEFE"
@@ -1064,7 +1070,7 @@
bitesize = 3
/obj/item/weapon/reagent_containers/food/snacks/tofuburger
- name = "Tofu Burger"
+ name = "tofu burger"
desc = "What.. is that meat?"
icon_state = "tofuburger"
filling_color = "#FFFEE0"
@@ -1115,7 +1121,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/clownburger
- name = "Clown Burger"
+ name = "clown burger"
desc = "This tastes funny..."
icon_state = "clownburger"
filling_color = "#FF00FF"
@@ -1127,7 +1133,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/mimeburger
- name = "Mime Burger"
+ name = "mime burger"
desc = "Its taste defies language."
icon_state = "mimeburger"
filling_color = "#FFFFFF"
@@ -1139,7 +1145,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/mouseburger
- name = "Mouse Burger"
+ name = "mouse burger"
desc = "Squeaky and a little furry."
icon_state = "ratburger"
center_of_mass = list("x"=16, "y"=11)
@@ -1150,7 +1156,7 @@
/obj/item/weapon/reagent_containers/food/snacks/omelette
- name = "Omelette Du Fromage"
+ name = "omelette du fromage"
desc = "That's all you can say!"
icon_state = "omelette"
trash = /obj/item/trash/plate
@@ -1176,7 +1182,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/pie
- name = "Banana Cream Pie"
+ name = "banana cream pie"
desc = "Just like back home, on clown planet! HONK!"
icon_state = "pie"
trash = /obj/item/trash/plate
@@ -1196,7 +1202,7 @@
qdel(src)
/obj/item/weapon/reagent_containers/food/snacks/berryclafoutis
- name = "Berry Clafoutis"
+ name = "berry clafoutis"
desc = "No black birds, this is a good sign."
icon_state = "berryclafoutis"
trash = /obj/item/trash/plate
@@ -1222,7 +1228,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/eggplantparm
- name = "Eggplant Parmigiana"
+ name = "eggplant parmigiana"
desc = "The only good recipe for eggplant."
icon_state = "eggplantparm"
trash = /obj/item/trash/plate
@@ -1235,7 +1241,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/soylentgreen
- name = "Soylent Green"
+ name = "soylent green"
desc = "Not made of people. Honest." //Totally people.
icon_state = "soylent_green"
trash = /obj/item/trash/waffles
@@ -1248,7 +1254,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/soylenviridians
- name = "Soylen Virdians"
+ name = "soylen virdians"
desc = "Not made of people. Honest." //Actually honest for once.
icon_state = "soylent_yellow"
trash = /obj/item/trash/waffles
@@ -1262,7 +1268,7 @@
/obj/item/weapon/reagent_containers/food/snacks/meatpie
- name = "Meat-pie"
+ name = "meat-pie"
icon_state = "meatpie"
desc = "An old barber recipe, very delicious!"
trash = /obj/item/trash/plate
@@ -1275,7 +1281,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/tofupie
- name = "Tofu-pie"
+ name = "tofu-pie"
icon_state = "meatpie"
desc = "A delicious tofu pie."
trash = /obj/item/trash/plate
@@ -1321,7 +1327,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/xemeatpie
- name = "Xeno-pie"
+ name = "xeno-pie"
icon_state = "xenomeatpie"
desc = "A delicious meatpie. Probably heretical."
trash = /obj/item/trash/plate
@@ -1334,7 +1340,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/wingfangchu
- name = "Wing Fang Chu"
+ name = "wing fang chu"
desc = "A savory dish of alien wing wang in soy."
icon_state = "wingfangchu"
trash = /obj/item/trash/snack_bowl
@@ -1361,7 +1367,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/monkeykabob
- name = "Meat-kabob"
+ name = "meat-kabob"
icon_state = "kabob"
desc = "Delicious meat, on a stick."
trash = /obj/item/stack/rods
@@ -1374,7 +1380,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/tofukabob
- name = "Tofu-kabob"
+ name = "tofu-kabob"
icon_state = "kabob"
desc = "Vegan meat, on a stick."
trash = /obj/item/stack/rods
@@ -1387,7 +1393,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/cubancarp
- name = "Cuban Carp"
+ name = "cuban carp"
desc = "A sandwich that burns your tongue and then leaves it numb!"
icon_state = "cubancarp"
trash = /obj/item/trash/plate
@@ -1402,7 +1408,7 @@
bitesize = 3
/obj/item/weapon/reagent_containers/food/snacks/chickenkatsu
- name = "Chicken Katsu"
+ name = "chicken katsu"
desc = "A terran delicacy consisting of chicken fried in a light beer batter"
icon_state = "katsu"
trash = /obj/item/trash/plate
@@ -1417,7 +1423,7 @@
bitesize = 1.5
/obj/item/weapon/reagent_containers/food/snacks/popcorn
- name = "Popcorn"
+ name = "popcorn"
desc = "Now let's find some cinema."
icon_state = "popcorn"
trash = /obj/item/trash/popcorn
@@ -1438,7 +1444,7 @@
/obj/item/weapon/reagent_containers/food/snacks/sosjerky
- name = "Scaredy's Private Reserve Beef Jerky"
+ name = "Scaredy's Private Reserve beef jerky"
icon_state = "sosjerky"
desc = "Beef jerky made from the finest space cows."
trash = /obj/item/trash/sosjerky
@@ -1463,7 +1469,7 @@
reagents.add_reagent("nutriment", 6)
/obj/item/weapon/reagent_containers/food/snacks/spacetwinkie
- name = "Space Twinkie"
+ name = "space twinkie"
icon_state = "space_twinkie"
desc = "Guaranteed to survive longer then you will."
filling_color = "#FFE591"
@@ -1502,7 +1508,7 @@
bitesize = 3
/obj/item/weapon/reagent_containers/food/snacks/loadedbakedpotato
- name = "Loaded Baked Potato"
+ name = "loaded baked potato"
desc = "Totally baked."
icon_state = "loadedbakedpotato"
filling_color = "#9C7A68"
@@ -1515,7 +1521,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/fries
- name = "Space Fries"
+ name = "space fries"
desc = "AKA: French Fries, Freedom Fries, etc."
icon_state = "fries"
trash = /obj/item/trash/plate
@@ -1529,7 +1535,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/microchips
- name = "Micro Chips"
+ name = "micro chips"
desc = "Soft and rubbery. should have fried them"
icon_state = "microchips"
trash = /obj/item/trash/plate
@@ -1542,7 +1548,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/ovenchips
- name = "Ovem Chips"
+ name = "ovem chips"
desc = "Dark and crispy, but a bit dry"
icon_state = "ovenchips"
trash = /obj/item/trash/plate
@@ -1555,7 +1561,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/soydope
- name = "Soy Dope"
+ name = "soy dope"
desc = "Dope from a soy."
icon_state = "soydope"
trash = /obj/item/trash/plate
@@ -1568,7 +1574,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/spagetti
- name = "Spaghetti"
+ name = "spaghetti"
desc = "A bundle of raw spaghetti."
icon_state = "spagetti"
filling_color = "#EDDD00"
@@ -1580,7 +1586,7 @@
bitesize = 1
/obj/item/weapon/reagent_containers/food/snacks/cheesyfries
- name = "Cheesy Fries"
+ name = "cheesy fries"
desc = "Fries. Covered in cheese. Duh."
icon_state = "cheesyfries"
trash = /obj/item/trash/plate
@@ -1594,7 +1600,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/fortunecookie
- name = "Fortune cookie"
+ name = "fortune cookie"
desc = "A true prophecy in each cookie!"
icon_state = "fortune_cookie"
filling_color = "#E8E79E"
@@ -1606,7 +1612,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/badrecipe
- name = "Burned mess"
+ name = "burned mess"
desc = "Someone should be demoted from chef for this."
icon_state = "badrecipe"
filling_color = "#211F02"
@@ -1619,7 +1625,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/meatsteak
- name = "Meat steak"
+ name = "meat steak"
desc = "A piece of hot spicy meat."
icon_state = "meatstake"
trash = /obj/item/trash/plate
@@ -1635,7 +1641,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/spacylibertyduff
- name = "Spacy Liberty Duff"
+ name = "spacy liberty duff"
desc = "Jello gelatin, from Alfred Hubbard's cookbook"
icon_state = "spacylibertyduff"
trash = /obj/item/trash/snack_bowl
@@ -1649,7 +1655,7 @@
bitesize = 3
/obj/item/weapon/reagent_containers/food/snacks/amanitajelly
- name = "Amanita Jelly"
+ name = "amanita jelly"
desc = "Looks curiously toxic"
icon_state = "amanitajelly"
trash = /obj/item/trash/snack_bowl
@@ -1664,7 +1670,7 @@
bitesize = 3
/obj/item/weapon/reagent_containers/food/snacks/poppypretzel
- name = "Poppy pretzel"
+ name = "poppy pretzel"
desc = "It's all twisted up!"
icon_state = "poppypretzel"
bitesize = 2
@@ -1678,7 +1684,7 @@
/obj/item/weapon/reagent_containers/food/snacks/meatballsoup
- name = "Meatball soup"
+ name = "meatball soup"
desc = "You've got balls kid, BALLS!"
icon_state = "meatballsoup"
trash = /obj/item/trash/snack_bowl
@@ -1704,7 +1710,7 @@
bitesize = 5
/obj/item/weapon/reagent_containers/food/snacks/bloodsoup
- name = "Tomato soup"
+ name = "tomato soup"
desc = "Smells like copper."
icon_state = "tomatosoup"
filling_color = "#FF0000"
@@ -1718,7 +1724,7 @@
bitesize = 5
/obj/item/weapon/reagent_containers/food/snacks/clownstears
- name = "Clown's Tears"
+ name = "clown's tears"
desc = "Not very funny."
icon_state = "clownstears"
filling_color = "#C4FBFF"
@@ -1732,7 +1738,7 @@
bitesize = 5
/obj/item/weapon/reagent_containers/food/snacks/vegetablesoup
- name = "Vegetable soup"
+ name = "vegetable soup"
desc = "A true vegan meal" //TODO
icon_state = "vegetablesoup"
trash = /obj/item/trash/snack_bowl
@@ -1746,7 +1752,7 @@
bitesize = 5
/obj/item/weapon/reagent_containers/food/snacks/nettlesoup
- name = "Nettle soup"
+ name = "nettle soup"
desc = "To think, the botanist would've beat you to death with one of these."
icon_state = "nettlesoup"
trash = /obj/item/trash/snack_bowl
@@ -1761,7 +1767,7 @@
bitesize = 5
/obj/item/weapon/reagent_containers/food/snacks/mysterysoup
- name = "Mystery soup"
+ name = "mystery soup"
desc = "The mystery is, why aren't you eating it?"
icon_state = "mysterysoup"
trash = /obj/item/trash/snack_bowl
@@ -1809,7 +1815,7 @@
bitesize = 5
/obj/item/weapon/reagent_containers/food/snacks/wishsoup
- name = "Wish Soup"
+ name = "wish soup"
desc = "I wish this was soup."
icon_state = "wishsoup"
trash = /obj/item/trash/snack_bowl
@@ -1825,7 +1831,7 @@
reagents.add_reagent("nutriment", 8)
/obj/item/weapon/reagent_containers/food/snacks/hotchili
- name = "Hot Chili"
+ name = "hot chili"
desc = "A five alarm Texan Chili!"
icon_state = "hotchili"
trash = /obj/item/trash/snack_bowl
@@ -1842,7 +1848,7 @@
/obj/item/weapon/reagent_containers/food/snacks/coldchili
- name = "Cold Chili"
+ name = "cold chili"
desc = "This slush is barely a liquid!"
icon_state = "coldchili"
filling_color = "#2B00FF"
@@ -1859,7 +1865,7 @@
/* No more of this
/obj/item/weapon/reagent_containers/food/snacks/telebacon
- name = "Tele Bacon"
+ name = "tele bacon"
desc = "It tastes a little odd but it is still delicious."
icon_state = "bacon"
var/obj/item/device/radio/beacon/bacon/baconbeacon
@@ -1991,7 +1997,7 @@
/obj/item/weapon/reagent_containers/food/snacks/spellburger
- name = "Spell Burger"
+ name = "spell burger"
desc = "This is absolutely Ei Nath."
icon_state = "spellburger"
filling_color = "#D505FF"
@@ -2002,7 +2008,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/bigbiteburger
- name = "Big Bite Burger"
+ name = "big bite burger"
desc = "Forget the Big Mac. THIS is the future!"
icon_state = "bigbiteburger"
filling_color = "#E3D681"
@@ -2015,7 +2021,7 @@
bitesize = 3
/obj/item/weapon/reagent_containers/food/snacks/enchiladas
- name = "Enchiladas"
+ name = "enchiladas"
desc = "Viva La Mexico!"
icon_state = "enchiladas"
trash = /obj/item/trash/tray
@@ -2030,7 +2036,7 @@
bitesize = 4
/obj/item/weapon/reagent_containers/food/snacks/monkeysdelight
- name = "monkey's Delight"
+ name = "monkey's delight"
desc = "Eeee Eee!"
icon_state = "monkeysdelight"
trash = /obj/item/trash/tray
@@ -2046,7 +2052,7 @@
bitesize = 6
/obj/item/weapon/reagent_containers/food/snacks/baguette
- name = "Baguette"
+ name = "baguette"
desc = "Bon appetit!"
icon_state = "baguette"
filling_color = "#E3D796"
@@ -2060,7 +2066,7 @@
bitesize = 3
/obj/item/weapon/reagent_containers/food/snacks/fishandchips
- name = "Fish and Chips"
+ name = "fish and chips"
desc = "I do say so myself chap."
icon_state = "fishandchips"
filling_color = "#E3D796"
@@ -2074,7 +2080,7 @@
bitesize = 3
/obj/item/weapon/reagent_containers/food/snacks/sandwich
- name = "Sandwich"
+ name = "sandwich"
desc = "A grand creation of meat, cheese, bread, and several leaves of lettuce! Arthur Dent would be proud."
icon_state = "sandwich"
trash = /obj/item/trash/plate
@@ -2088,7 +2094,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/toastedsandwich
- name = "Toasted Sandwich"
+ name = "toasted sandwich"
desc = "Now if you only had a pepper bar."
icon_state = "toastedsandwich"
trash = /obj/item/trash/plate
@@ -2103,7 +2109,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/grilledcheese
- name = "Grilled Cheese Sandwich"
+ name = "grilled cheese sandwich"
desc = "Goes great with Tomato soup!"
icon_state = "toastedsandwich"
trash = /obj/item/trash/plate
@@ -2116,7 +2122,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/tomatosoup
- name = "Tomato Soup"
+ name = "tomato soup"
desc = "Drinking this feels like being a vampire! A tomato vampire..."
icon_state = "tomatosoup"
trash = /obj/item/trash/snack_bowl
@@ -2130,7 +2136,7 @@
bitesize = 3
/obj/item/weapon/reagent_containers/food/snacks/rofflewaffles
- name = "Roffle Waffles"
+ name = "roffle waffles"
desc = "Waffles from Roffle. Co."
icon_state = "rofflewaffles"
trash = /obj/item/trash/waffles
@@ -2160,7 +2166,7 @@
bitesize = 10
/obj/item/weapon/reagent_containers/food/snacks/jelliedtoast
- name = "Jellied Toast"
+ name = "jellied toast"
desc = "A slice of bread covered with delicious jam."
icon_state = "jellytoast"
trash = /obj/item/trash/plate
@@ -2183,7 +2189,7 @@
reagents.add_reagent("slimejelly", 5)
/obj/item/weapon/reagent_containers/food/snacks/jellyburger
- name = "Jelly Burger"
+ name = "jelly burger"
desc = "Culinary delight..?"
icon_state = "jellyburger"
filling_color = "#B572AB"
@@ -2205,7 +2211,7 @@
reagents.add_reagent("cherryjelly", 5)
/obj/item/weapon/reagent_containers/food/snacks/milosoup
- name = "Milosoup"
+ name = "milosoup"
desc = "The universes best soup! Yum!!!"
icon_state = "milosoup"
trash = /obj/item/trash/snack_bowl
@@ -2218,7 +2224,7 @@
bitesize = 4
/obj/item/weapon/reagent_containers/food/snacks/stewedsoymeat
- name = "Stewed Soy Meat"
+ name = "stewed soy meat"
desc = "Even non-vegetarians will LOVE this!"
icon_state = "stewedsoymeat"
trash = /obj/item/trash/plate
@@ -2230,7 +2236,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/boiledspagetti
- name = "Boiled Spaghetti"
+ name = "boiled spaghetti"
desc = "A plain dish of noodles, this sucks."
icon_state = "spagettiboiled"
trash = /obj/item/trash/plate
@@ -2243,7 +2249,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/boiledrice
- name = "Boiled Rice"
+ name = "boiled rice"
desc = "A boring dish of boring rice."
icon_state = "boiledrice"
trash = /obj/item/trash/snack_bowl
@@ -2256,7 +2262,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/ricepudding
- name = "Rice Pudding"
+ name = "rice pudding"
desc = "Where's the jam?"
icon_state = "rpudding"
trash = /obj/item/trash/snack_bowl
@@ -2269,7 +2275,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/pudding
- name = "Figgy pudding"
+ name = "figgy pudding"
icon_state = "pudding"
desc = "Bring it to me."
trash = /obj/item/trash/plate
@@ -2281,7 +2287,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/pastatomato
- name = "Spaghetti"
+ name = "spaghetti"
desc = "Spaghetti and crushed tomatoes. Just like your abusive father used to make!"
icon_state = "pastatomato"
trash = /obj/item/trash/plate
@@ -2295,7 +2301,7 @@
bitesize = 4
/obj/item/weapon/reagent_containers/food/snacks/meatballspagetti
- name = "Spaghetti & Meatballs"
+ name = "spaghetti & meatballs"
desc = "Now thats a nic'e meatball!"
icon_state = "meatballspagetti"
trash = /obj/item/trash/plate
@@ -2309,7 +2315,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/spesslaw
- name = "Spesslaw"
+ name = "spesslaw"
desc = "A lawyers favourite"
icon_state = "spesslaw"
filling_color = "#DE4545"
@@ -2336,7 +2342,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/superbiteburger
- name = "Super Bite Burger"
+ name = "super bite burger"
desc = "This is a mountain of a burger. FOOD!"
icon_state = "superbiteburger"
filling_color = "#CCA26A"
@@ -2349,7 +2355,7 @@
bitesize = 10
/obj/item/weapon/reagent_containers/food/snacks/candiedapple
- name = "Candied Apple"
+ name = "candied apple"
desc = "An apple coated in sugary sweetness."
icon_state = "candiedapple"
filling_color = "#F21873"
@@ -2361,7 +2367,7 @@
bitesize = 3
/obj/item/weapon/reagent_containers/food/snacks/applepie
- name = "Apple Pie"
+ name = "apple pie"
desc = "A pie containing sweet sweet love... or apple."
icon_state = "applepie"
filling_color = "#E0EDC5"
@@ -2374,7 +2380,7 @@
/obj/item/weapon/reagent_containers/food/snacks/cherrypie
- name = "Cherry Pie"
+ name = "cherry pie"
desc = "Taste so good, make a grown man cry."
icon_state = "cherrypie"
filling_color = "#FF525A"
@@ -2386,7 +2392,7 @@
bitesize = 3
/obj/item/weapon/reagent_containers/food/snacks/twobread
- name = "Two Bread"
+ name = "two bread"
desc = "It is very bitter and winy."
icon_state = "twobread"
filling_color = "#DBCC9A"
@@ -2398,7 +2404,7 @@
bitesize = 3
/obj/item/weapon/reagent_containers/food/snacks/jellysandwich
- name = "Jelly Sandwich"
+ name = "jelly sandwich"
desc = "You wish you had some peanut butter to go with this..."
icon_state = "jellysandwich"
trash = /obj/item/trash/plate
@@ -2421,7 +2427,7 @@
reagents.add_reagent("cherryjelly", 5)
/obj/item/weapon/reagent_containers/food/snacks/boiledslimecore
- name = "Boiled slime Core"
+ name = "boiled slime core"
desc = "A boiled red thing."
icon_state = "boiledslimecore" //nonexistant?
New()
@@ -2597,7 +2603,7 @@
center_of_mass = list("x"=16, "y"=13)
/obj/item/weapon/reagent_containers/food/snacks/sliceable/bananabread
- name = "Banana-nut bread"
+ name = "banana-nut bread"
desc = "A heavenly and filling treat."
icon_state = "bananabread"
slice_path = /obj/item/weapon/reagent_containers/food/snacks/bananabreadslice
@@ -2612,7 +2618,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/bananabreadslice
- name = "Banana-nut bread slice"
+ name = "banana-nut bread slice"
desc = "A slice of delicious banana bread."
icon_state = "bananabreadslice"
trash = /obj/item/trash/plate
@@ -2621,7 +2627,7 @@
center_of_mass = list("x"=16, "y"=8)
/obj/item/weapon/reagent_containers/food/snacks/sliceable/tofubread
- name = "Tofubread"
+ name = "tofubread"
icon_state = "Like meatbread but for vegetarians. Not guaranteed to give superpowers."
icon_state = "tofubread"
slice_path = /obj/item/weapon/reagent_containers/food/snacks/tofubreadslice
@@ -2635,7 +2641,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/tofubreadslice
- name = "Tofubread slice"
+ name = "tofubread slice"
desc = "A slice of delicious tofubread."
icon_state = "tofubreadslice"
trash = /obj/item/trash/plate
@@ -2645,7 +2651,7 @@
/obj/item/weapon/reagent_containers/food/snacks/sliceable/carrotcake
- name = "Carrot Cake"
+ name = "carrot cake"
desc = "A favorite desert of a certain wascally wabbit. Not a lie."
icon_state = "carrotcake"
slice_path = /obj/item/weapon/reagent_containers/food/snacks/carrotcakeslice
@@ -2660,7 +2666,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/carrotcakeslice
- name = "Carrot Cake slice"
+ name = "carrot cake slice"
desc = "Carrotty slice of Carrot Cake, carrots are good for your eyes! Also not a lie."
icon_state = "carrotcake_slice"
trash = /obj/item/trash/plate
@@ -2669,7 +2675,7 @@
center_of_mass = list("x"=16, "y"=14)
/obj/item/weapon/reagent_containers/food/snacks/sliceable/braincake
- name = "Brain Cake"
+ name = "brain cake"
desc = "A squishy cake-thing."
icon_state = "braincake"
slice_path = /obj/item/weapon/reagent_containers/food/snacks/braincakeslice
@@ -2685,7 +2691,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/braincakeslice
- name = "Brain Cake slice"
+ name = "brain cake slice"
desc = "Lemme tell you something about prions. THEY'RE DELICIOUS."
icon_state = "braincakeslice"
trash = /obj/item/trash/plate
@@ -2694,7 +2700,7 @@
center_of_mass = list("x"=16, "y"=12)
/obj/item/weapon/reagent_containers/food/snacks/sliceable/cheesecake
- name = "Cheese Cake"
+ name = "cheese cake"
desc = "DANGEROUSLY cheesy."
icon_state = "cheesecake"
slice_path = /obj/item/weapon/reagent_containers/food/snacks/cheesecakeslice
@@ -2709,7 +2715,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/cheesecakeslice
- name = "Cheese Cake slice"
+ name = "cheese cake slice"
desc = "Slice of pure cheestisfaction"
icon_state = "cheesecake_slice"
trash = /obj/item/trash/plate
@@ -2718,7 +2724,7 @@
center_of_mass = list("x"=16, "y"=14)
/obj/item/weapon/reagent_containers/food/snacks/sliceable/plaincake
- name = "Vanilla Cake"
+ name = "vanilla cake"
desc = "A plain cake, not a lie."
icon_state = "plaincake"
slice_path = /obj/item/weapon/reagent_containers/food/snacks/plaincakeslice
@@ -2731,7 +2737,7 @@
reagents.add_reagent("nutriment", 20)
/obj/item/weapon/reagent_containers/food/snacks/plaincakeslice
- name = "Vanilla Cake slice"
+ name = "vanilla cake slice"
desc = "Just a slice of cake, it is enough for everyone."
icon_state = "plaincake_slice"
trash = /obj/item/trash/plate
@@ -2740,7 +2746,7 @@
center_of_mass = list("x"=16, "y"=14)
/obj/item/weapon/reagent_containers/food/snacks/sliceable/orangecake
- name = "Orange Cake"
+ name = "orange cake"
desc = "A cake with added orange."
icon_state = "orangecake"
slice_path = /obj/item/weapon/reagent_containers/food/snacks/orangecakeslice
@@ -2753,7 +2759,7 @@
reagents.add_reagent("nutriment", 20)
/obj/item/weapon/reagent_containers/food/snacks/orangecakeslice
- name = "Orange Cake slice"
+ name = "orange cake slice"
desc = "Just a slice of cake, it is enough for everyone."
icon_state = "orangecake_slice"
trash = /obj/item/trash/plate
@@ -2762,7 +2768,7 @@
center_of_mass = list("x"=16, "y"=14)
/obj/item/weapon/reagent_containers/food/snacks/sliceable/limecake
- name = "Lime Cake"
+ name = "lime cake"
desc = "A cake with added lime."
icon_state = "limecake"
slice_path = /obj/item/weapon/reagent_containers/food/snacks/limecakeslice
@@ -2775,7 +2781,7 @@
reagents.add_reagent("nutriment", 20)
/obj/item/weapon/reagent_containers/food/snacks/limecakeslice
- name = "Lime Cake slice"
+ name = "lime cake slice"
desc = "Just a slice of cake, it is enough for everyone."
icon_state = "limecake_slice"
trash = /obj/item/trash/plate
@@ -2784,7 +2790,7 @@
center_of_mass = list("x"=16, "y"=14)
/obj/item/weapon/reagent_containers/food/snacks/sliceable/lemoncake
- name = "Lemon Cake"
+ name = "lemon cake"
desc = "A cake with added lemon."
icon_state = "lemoncake"
slice_path = /obj/item/weapon/reagent_containers/food/snacks/lemoncakeslice
@@ -2797,7 +2803,7 @@
reagents.add_reagent("nutriment", 20)
/obj/item/weapon/reagent_containers/food/snacks/lemoncakeslice
- name = "Lemon Cake slice"
+ name = "lemon cake slice"
desc = "Just a slice of cake, it is enough for everyone."
icon_state = "lemoncake_slice"
trash = /obj/item/trash/plate
@@ -2806,7 +2812,7 @@
center_of_mass = list("x"=16, "y"=14)
/obj/item/weapon/reagent_containers/food/snacks/sliceable/chocolatecake
- name = "Chocolate Cake"
+ name = "chocolate cake"
desc = "A cake with added chocolate"
icon_state = "chocolatecake"
slice_path = /obj/item/weapon/reagent_containers/food/snacks/chocolatecakeslice
@@ -2819,7 +2825,7 @@
reagents.add_reagent("nutriment", 20)
/obj/item/weapon/reagent_containers/food/snacks/chocolatecakeslice
- name = "Chocolate Cake slice"
+ name = "chocolate cake slice"
desc = "Just a slice of cake, it is enough for everyone."
icon_state = "chocolatecake_slice"
trash = /obj/item/trash/plate
@@ -2828,7 +2834,7 @@
center_of_mass = list("x"=16, "y"=14)
/obj/item/weapon/reagent_containers/food/snacks/sliceable/cheesewheel
- name = "Cheese wheel"
+ name = "cheese wheel"
desc = "A big wheel of delcious Cheddar."
icon_state = "cheesewheel"
slice_path = /obj/item/weapon/reagent_containers/food/snacks/cheesewedge
@@ -2842,7 +2848,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/cheesewedge
- name = "Cheese wedge"
+ name = "cheese wedge"
desc = "A wedge of delicious Cheddar. The cheese wheel it was cut from can't have gone far."
icon_state = "cheesewedge"
filling_color = "#FFF700"
@@ -2850,7 +2856,7 @@
center_of_mass = list("x"=16, "y"=10)
/obj/item/weapon/reagent_containers/food/snacks/sliceable/birthdaycake
- name = "Birthday Cake"
+ name = "birthday cake"
desc = "Happy Birthday..."
icon_state = "birthdaycake"
slice_path = /obj/item/weapon/reagent_containers/food/snacks/birthdaycakeslice
@@ -2865,7 +2871,7 @@
bitesize = 3
/obj/item/weapon/reagent_containers/food/snacks/birthdaycakeslice
- name = "Birthday Cake slice"
+ name = "birthday cake slice"
desc = "A slice of your birthday."
icon_state = "birthdaycakeslice"
trash = /obj/item/trash/plate
@@ -2874,7 +2880,7 @@
center_of_mass = list("x"=16, "y"=14)
/obj/item/weapon/reagent_containers/food/snacks/sliceable/bread
- name = "Bread"
+ name = "bread"
icon_state = "Some plain old Earthen bread."
icon_state = "bread"
slice_path = /obj/item/weapon/reagent_containers/food/snacks/breadslice
@@ -2888,7 +2894,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/breadslice
- name = "Bread slice"
+ name = "bread slice"
desc = "A slice of home."
icon_state = "breadslice"
trash = /obj/item/trash/plate
@@ -2898,7 +2904,7 @@
/obj/item/weapon/reagent_containers/food/snacks/sliceable/creamcheesebread
- name = "Cream Cheese Bread"
+ name = "cream cheese bread"
desc = "Yum yum yum!"
icon_state = "creamcheesebread"
slice_path = /obj/item/weapon/reagent_containers/food/snacks/creamcheesebreadslice
@@ -2913,7 +2919,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/creamcheesebreadslice
- name = "Cream Cheese Bread slice"
+ name = "cream cheese bread slice"
desc = "A slice of yum!"
icon_state = "creamcheesebreadslice"
trash = /obj/item/trash/plate
@@ -2923,7 +2929,7 @@
/obj/item/weapon/reagent_containers/food/snacks/watermelonslice
- name = "Watermelon Slice"
+ name = "watermelon slice"
desc = "A slice of watery goodness."
icon_state = "watermelonslice"
filling_color = "#FF3867"
@@ -2932,7 +2938,7 @@
/obj/item/weapon/reagent_containers/food/snacks/sliceable/applecake
- name = "Apple Cake"
+ name = "apple cake"
desc = "A cake centred with Apple"
icon_state = "applecake"
slice_path = /obj/item/weapon/reagent_containers/food/snacks/applecakeslice
@@ -2945,7 +2951,7 @@
reagents.add_reagent("nutriment", 15)
/obj/item/weapon/reagent_containers/food/snacks/applecakeslice
- name = "Apple Cake slice"
+ name = "apple cake slice"
desc = "A slice of heavenly cake."
icon_state = "applecakeslice"
trash = /obj/item/trash/plate
@@ -2954,7 +2960,7 @@
center_of_mass = list("x"=16, "y"=14)
/obj/item/weapon/reagent_containers/food/snacks/sliceable/pumpkinpie
- name = "Pumpkin Pie"
+ name = "pumpkin pie"
desc = "A delicious treat for the autumn months."
icon_state = "pumpkinpie"
slice_path = /obj/item/weapon/reagent_containers/food/snacks/pumpkinpieslice
@@ -2967,7 +2973,7 @@
reagents.add_reagent("nutriment", 15)
/obj/item/weapon/reagent_containers/food/snacks/pumpkinpieslice
- name = "Pumpkin Pie slice"
+ name = "pumpkin pie slice"
desc = "A slice of pumpkin pie, with whipped cream on top. Perfection."
icon_state = "pumpkinpieslice"
trash = /obj/item/trash/plate
@@ -2976,7 +2982,7 @@
center_of_mass = list("x"=16, "y"=12)
/obj/item/weapon/reagent_containers/food/snacks/cracker
- name = "Cracker"
+ name = "cracker"
desc = "It's a salted cracker."
icon_state = "cracker"
filling_color = "#F5DEB8"
@@ -2995,7 +3001,7 @@
filling_color = "#BAA14C"
/obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/margherita
- name = "Margherita"
+ name = "margherita"
desc = "The golden standard of pizzas."
icon_state = "pizzamargherita"
slice_path = /obj/item/weapon/reagent_containers/food/snacks/margheritaslice
@@ -3010,7 +3016,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/margheritaslice
- name = "Margherita slice"
+ name = "margherita slice"
desc = "A slice of the classic pizza."
icon_state = "pizzamargheritaslice"
filling_color = "#BAA14C"
@@ -3018,7 +3024,7 @@
center_of_mass = list("x"=18, "y"=13)
/obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/meatpizza
- name = "Meatpizza"
+ name = "meatpizza"
desc = "A pizza with meat topping."
icon_state = "meatpizza"
slice_path = /obj/item/weapon/reagent_containers/food/snacks/meatpizzaslice
@@ -3032,7 +3038,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/meatpizzaslice
- name = "Meatpizza slice"
+ name = "meatpizza slice"
desc = "A slice of a meaty pizza."
icon_state = "meatpizzaslice"
filling_color = "#BAA14C"
@@ -3040,7 +3046,7 @@
center_of_mass = list("x"=18, "y"=13)
/obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/mushroompizza
- name = "Mushroompizza"
+ name = "mushroompizza"
desc = "Very special pizza"
icon_state = "mushroompizza"
slice_path = /obj/item/weapon/reagent_containers/food/snacks/mushroompizzaslice
@@ -3054,7 +3060,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/mushroompizzaslice
- name = "Mushroompizza slice"
+ name = "mushroompizza slice"
desc = "Maybe it is the last slice of pizza in your life."
icon_state = "mushroompizzaslice"
filling_color = "#BAA14C"
@@ -3062,7 +3068,7 @@
center_of_mass = list("x"=18, "y"=13)
/obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/vegetablepizza
- name = "Vegetable pizza"
+ name = "vegetable pizza"
desc = "No one of Tomato Sapiens were harmed during making this pizza"
icon_state = "vegetablepizza"
slice_path = /obj/item/weapon/reagent_containers/food/snacks/vegetablepizzaslice
@@ -3078,7 +3084,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/vegetablepizzaslice
- name = "Vegetable pizza slice"
+ name = "vegetable pizza slice"
desc = "A slice of the most green pizza of all pizzas not containing green ingredients "
icon_state = "vegetablepizzaslice"
filling_color = "#BAA14C"
@@ -3087,7 +3093,7 @@
/obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/crunch
- name = "Pizza Crunch"
+ name = "pizza crunch"
desc = "This was once a normal pizza, but it has been coated in batter and deep-fried. Whatever toppings it once had are a mystery, but they're still under there, somewhere..."
icon_state = "pizzacrunch"
slice_path = /obj/item/weapon/reagent_containers/food/snacks/pizzacrunchslice
@@ -3103,7 +3109,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/pizzacrunchslice
- name = "Pizza Crunch"
+ name = "pizza crunch"
desc = "A little piece of a heart attack. It's toppings are a mystery, hidden under batter"
icon_state = "pizzacrunchslice"
filling_color = "#BAA14C"
@@ -3524,7 +3530,7 @@
reagents.add_reagent("nutriment", 3)
/obj/item/weapon/reagent_containers/food/snacks/liquidfood
- name = "\improper LiquidFood Ration"
+ name = "\improper LiquidFood ration"
desc = "A prepackaged grey slurry of all the essential nutrients for a spacefarer on the go. Should this be crunchy?"
icon_state = "liquidfood"
trash = /obj/item/trash/liquidfood
@@ -3564,7 +3570,7 @@
bitesize = 3
/obj/item/weapon/reagent_containers/food/snacks/friedkois
- name = "Fried K'ois"
+ name = "fried k'ois"
desc = "K'ois, freshly bathed in the radiation of a microwave."
icon_state = "friedkois"
filling_color = "#E6E600"
@@ -3587,7 +3593,7 @@
qdel(src)
/obj/item/weapon/reagent_containers/food/snacks/koiskebab1
- name = "K'ois on a Stick"
+ name = "k'ois on a stick"
desc = "It's K'ois. On a stick. It looks like you could fit more."
icon_state = "koisbab1"
trash = /obj/item/stack/rods
@@ -3608,7 +3614,7 @@
/obj/item/weapon/reagent_containers/food/snacks/koiskebab2
- name = "K'ois on a Stick"
+ name = "k'ois on a stick"
desc = "It's K'ois. On a stick. It looks like you could fit more."
icon_state = "koisbab2"
trash = /obj/item/stack/rods
@@ -3628,7 +3634,7 @@
qdel(W)
/obj/item/weapon/reagent_containers/food/snacks/koiskebab3
- name = "K'ois on a Stick"
+ name = "k'ois on a stick"
desc = "It's K'ois. On a stick. It doesn't look like you can fit anymore."
icon_state = "koisbab3"
trash = /obj/item/stack/rods
@@ -3641,7 +3647,7 @@
bitesize = 9
/obj/item/weapon/reagent_containers/food/snacks/koissoup
- name = "K'ois Paste"
+ name = "k'ois paste"
desc = "A thick K'ois goop, piled into a bowl."
icon_state = "koissoup"
trash = /obj/item/trash/snack_bowl
@@ -3654,7 +3660,7 @@
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/koiswaffles
- name = "K'ois Waffles"
+ name = "k'ois waffles"
desc = "Rock-hard 'waffles' composed entirely of microwaved K'ois goop."
icon_state = "koiswaffles"
trash = /obj/item/trash/waffles
@@ -3667,7 +3673,7 @@
bitesize = 5
/obj/item/weapon/reagent_containers/food/snacks/koisjelly
- name = "K'ois Jelly"
+ name = "k'ois jelly"
desc = "Enriched K'ois paste, filled to the brim with the good stuff."
icon_state = "koisjelly"
filling_color = "#E6E600"
diff --git a/code/modules/reagents/reagent_containers/food/snacks/meat.dm b/code/modules/reagents/reagent_containers/food/snacks/meat.dm
index 58e773b0e0c..832070fb934 100644
--- a/code/modules/reagents/reagent_containers/food/snacks/meat.dm
+++ b/code/modules/reagents/reagent_containers/food/snacks/meat.dm
@@ -26,6 +26,7 @@
if (!isnull(cooked_icon))
icon_state = cooked_icon
+ flat_icon = null //Force regenating the flat icon for coatings, since we've changed the icon of the thing being coated
..()
if (name == initial(name))
@@ -50,7 +51,7 @@
//same as plain meat
/obj/item/weapon/reagent_containers/food/snacks/meat/corgi
- name = "Corgi meat"
+ name = "corgi meat"
desc = "Tastes like... well, you know."
@@ -62,4 +63,4 @@
New()
..()
reagents.remove_reagent("triglyceride", INFINITY)
- //Chicken is low fat. Less total calories than other meats
\ No newline at end of file
+ //Chicken is low fat. Less total calories than other meats
diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm
index ebb346dc6e8..06c6bd648ac 100644
--- a/code/modules/reagents/reagent_containers/spray.dm
+++ b/code/modules/reagents/reagent_containers/spray.dm
@@ -33,6 +33,11 @@
if(istype(A, /obj/item/weapon/storage) || istype(A, /obj/structure/table) || istype(A, /obj/structure/closet) || istype(A, /obj/item/weapon/reagent_containers) || istype(A, /obj/structure/sink) || istype(A, /obj/structure/janitorialcart))
return
+ if(istype(A, /mob))
+ user.setClickCooldown(25)
+ else
+ user.setClickCooldown(4)
+
if(istype(A, /spell))
return
@@ -53,7 +58,7 @@
playsound(src.loc, 'sound/effects/spray2.ogg', 50, 1, -6)
- user.setClickCooldown(4)
+
if(reagents.has_reagent("sacid"))
message_admins("[key_name_admin(user)] fired sulphuric acid from \a [src].")
diff --git a/code/modules/research/designs.dm b/code/modules/research/designs.dm
index 501d168ab62..f867ef6077f 100644
--- a/code/modules/research/designs.dm
+++ b/code/modules/research/designs.dm
@@ -766,7 +766,7 @@ datum/design/item/experimental_welder
name = "Experimental Welding Tool"
desc = "A scientifically-enhanced welding tool that uses fuel-producing microbes to gradually replenish its fuel supply"
id = "experimental_welder"
- req_tech = list(ENGINEERING = 4, TECH_MATERIAL = 4)
+ req_tech = list(TECH_ENGINEERING = 4, TECH_MATERIAL = 4)
materials = list(DEFAULT_WALL_MATERIAL = 500)
build_path =/obj/item/weapon/weldingtool/experimental
sort_string = "VABAJ"
diff --git a/code/modules/research/xenoarchaeology/tools/anomaly_suit.dm b/code/modules/research/xenoarchaeology/tools/anomaly_suit.dm
index 67ac1bd867f..232213c7ee6 100644
--- a/code/modules/research/xenoarchaeology/tools/anomaly_suit.dm
+++ b/code/modules/research/xenoarchaeology/tools/anomaly_suit.dm
@@ -1,21 +1,21 @@
//changes: rad protection up to 100 from 20/50 respectively
/obj/item/clothing/suit/bio_suit/anomaly
- name = "Anomaly suit"
+ name = "anomaly suit"
desc = "A sealed bio suit capable of insulating against exotic alien energies."
icon_state = "engspace_suit"
item_state = "engspace_suit"
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 100)
/obj/item/clothing/head/bio_hood/anomaly
- name = "Anomaly hood"
+ name = "anomaly hood"
desc = "A sealed bio hood capable of insulating against exotic alien energies."
icon_state = "engspace_helmet"
item_state = "engspace_helmet"
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 100)
/obj/item/clothing/suit/space/anomaly
- name = "Excavation suit"
+ name = "excavation suit"
desc = "A pressure resistant excavation suit partially capable of insulating against exotic alien energies."
icon_state = "cespace_suit"
item_state = "cespace_suit"
@@ -23,7 +23,7 @@
allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit)
/obj/item/clothing/head/helmet/space/anomaly
- name = "Excavation hood"
+ name = "excavation hood"
desc = "A pressure resistant excavation hood partially capable of insulating against exotic alien energies."
icon_state = "cespace_helmet"
item_state = "cespace_helmet"
diff --git a/code/modules/spells/artifacts.dm b/code/modules/spells/artifacts.dm
index 6ef000cbe03..b2a59d86517 100644
--- a/code/modules/spells/artifacts.dm
+++ b/code/modules/spells/artifacts.dm
@@ -54,13 +54,16 @@
throw_speed = 5
throw_range = 10
w_class = 5
- flags = NOBLOODY
+ slot_flags = SLOT_BELT
origin_tech = list(TECH_COMBAT = 8, TECH_MATERIAL = 8)
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
hitsound = 'sound/weapons/bladeslice.ogg'
sharp = 1
edge = 1
- slot_flags = SLOT_BELT
+ base_reflectchance = 60
+ base_block_chance = 60
+ can_block_bullets = 1
+ shield_power = 150
/obj/item/weapon/melee/energy/wizard/activate(mob/living/user)
..()
@@ -90,23 +93,9 @@
return 1
-/* //commented until issues with sparks and sword blocking updates are merged
-/obj/item/weapon/melee/energy/wizard/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
- if(active && default_parry_check(user, attacker, damage_source) && prob(50))
- user.visible_message("\The [user] parries [attack_text] with \the [src]!")
-
- var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
- spark_system.set_up(5, 0, user.loc)
- spark_system.start()
- playsound(user.loc, 'sound/weapons/punchmiss.ogg', 50, 1)
- return 1
-
- return 0
- */
-
//skeleton weapons and armor
-/obj/item/clothing/suit/bone
+/obj/item/clothing/suit/armor/bone
name = "bone armor"
desc = "A rudimentary armor made of bones of several creatures."
icon = 'icons/obj/necromancer.dmi'
diff --git a/code/modules/spells/monster_manual.dm b/code/modules/spells/monster_manual.dm
index 9d21d6c3fd6..59c53d1d6b1 100644
--- a/code/modules/spells/monster_manual.dm
+++ b/code/modules/spells/monster_manual.dm
@@ -9,17 +9,17 @@
var/uses = 1
var/temp = null
var/list/monster = list(/mob/living/simple_animal/familiar/pet/cat,
- /mob/living/simple_animal/familiar/pet/mouse,
+ /mob/living/simple_animal/mouse/familiar,
/mob/living/simple_animal/familiar/carcinus,
/mob/living/simple_animal/familiar/horror,
/mob/living/simple_animal/familiar/goat,
/mob/living/simple_animal/familiar/pike
)
var/list/monster_info = list( "It is well known that the blackest of cats make good familiars.",
- "Mice are full of mischief and magic. A simple animal, yes, but one of the wizard's finest.",
+ "Mice are small but fragile creatures. This one is gifted with unending life, and the ability to renew others.",
"A mortal decendant of the original Carcinus, it is said their shells are near impenetrable and their claws as sharp as knives.",
"A creature from other plane, its very own presence is enough to shatter the sanity of men.",
- "A magical goat known for its healing powers and nearly-pacifist ways.",
+ "A stubborn and mischievous creature, this goat delights in stirring trouble.",
"The more carnivorous and knowledge hungry cousin of the space carp. Keep away from books."
)
diff --git a/code/modules/spells/targeted/necromancer_spells.dm b/code/modules/spells/targeted/necromancer_spells.dm
index 54940aabb18..ab807ed024c 100644
--- a/code/modules/spells/targeted/necromancer_spells.dm
+++ b/code/modules/spells/targeted/necromancer_spells.dm
@@ -111,14 +111,14 @@
F.faction = usr.faction
if(C.mob && C.mob.mind)
C.mob.mind.transfer_to(F)
- F << "You are skeleton minion to [usr], he is your master. Aid your master don't matter what, you have no free will."
+ F << "You are a skeleton minion to [usr], they are your master. Obey and protect your master at all costs, you have no free will."
//equips the skeleton war gear
F.equip_to_slot_or_del(new /obj/item/clothing/under/gladiator(F), slot_w_uniform)
F.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(F), slot_shoes)
F.equip_to_slot_or_del(new /obj/item/weapon/material/twohanded/spear/bone(F), slot_back)
F.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/bone(F), slot_head)
- F.equip_to_slot_or_del(new /obj/item/clothing/suit/bone(F), slot_wear_suit)
+ F.equip_to_slot_or_del(new /obj/item/clothing/suit/armor/bone(F), slot_wear_suit)
/spell/targeted/raise_dead/proc/get_player()
for(var/mob/O in dead_mob_list)
diff --git a/code/modules/supermatter/supermatter.dm b/code/modules/supermatter/supermatter.dm
index 131cca980ef..bf08fa1d8c3 100644
--- a/code/modules/supermatter/supermatter.dm
+++ b/code/modules/supermatter/supermatter.dm
@@ -98,7 +98,7 @@
/obj/machinery/power/supermatter/Destroy()
- qdel(radio)
+ QDEL_NULL(radio)
. = ..()
/obj/machinery/power/supermatter/proc/explode()
diff --git a/code/modules/surgery/bones.dm b/code/modules/surgery/bones.dm
index 25addbd40a4..1ba5179fd88 100644
--- a/code/modules/surgery/bones.dm
+++ b/code/modules/surgery/bones.dm
@@ -6,7 +6,7 @@
/datum/surgery_step/glue_bone
allowed_tools = list(
/obj/item/weapon/bonegel = 100, \
- /obj/item/weapon/screwdriver = 75
+ /obj/item/weapon/tape_roll = 60
)
can_infect = 1
blood_level = 1
@@ -18,7 +18,7 @@
if (!hasorgans(target))
return 0
var/obj/item/organ/external/affected = target.get_organ(target_zone)
- return affected && !(affected.status & ORGAN_ROBOT) && affected.open >= 2 && affected.stage == 0
+ return affected && !(affected.status & ORGAN_ROBOT) && affected.open >= 2 && affected.open < 3 && affected.stage == 0
begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
var/obj/item/organ/external/affected = target.get_organ(target_zone)
@@ -115,7 +115,7 @@
/datum/surgery_step/finish_bone
allowed_tools = list(
/obj/item/weapon/bonegel = 100, \
- /obj/item/weapon/screwdriver = 75
+ /obj/item/weapon/tape_roll = 60
)
can_infect = 1
blood_level = 1
@@ -127,7 +127,7 @@
if (!hasorgans(target))
return 0
var/obj/item/organ/external/affected = target.get_organ(target_zone)
- return affected && affected.open >= 2 && !(affected.status & ORGAN_ROBOT) && affected.stage == 2
+ return affected && affected.open >= 2 && affected.open < 3 && !(affected.status & ORGAN_ROBOT) && affected.stage == 2
begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
var/obj/item/organ/external/affected = target.get_organ(target_zone)
diff --git a/code/modules/surgery/encased.dm b/code/modules/surgery/encased.dm
index 762c2b71c46..fbd1e8b8d89 100644
--- a/code/modules/surgery/encased.dm
+++ b/code/modules/surgery/encased.dm
@@ -17,7 +17,9 @@
/datum/surgery_step/open_encased/saw
allowed_tools = list(
- /obj/item/weapon/circular_saw = 100, \
+ /obj/item/weapon/circular_saw = 100,
+ /obj/item/weapon/melee/energy = 100,
+ /obj/item/weapon/melee/chainsword = 70,
/obj/item/weapon/material/hatchet = 75
)
@@ -172,7 +174,7 @@
affected.createwound(BRUISE, 20)
affected.fracture()
-
+
if(affected.internal_organs && affected.internal_organs.len)
if(prob(40))
var/obj/item/organ/O = pick(affected.internal_organs) //TODO weight by organ size
@@ -182,7 +184,7 @@
/datum/surgery_step/open_encased/mend
allowed_tools = list(
/obj/item/weapon/bonegel = 100, \
- /obj/item/weapon/screwdriver = 75
+ /obj/item/weapon/tape_roll = 60
)
min_duration = 20
diff --git a/code/modules/surgery/robotics.dm b/code/modules/surgery/robotics.dm
index 70c40a002bc..31caab1822e 100644
--- a/code/modules/surgery/robotics.dm
+++ b/code/modules/surgery/robotics.dm
@@ -78,7 +78,7 @@
var/obj/item/organ/external/affected = target.get_organ(target_zone)
user.visible_message("[user] opens the maintenance hatch on [target]'s [affected.name] with \the [tool].", \
"You open the maintenance hatch on [target]'s [affected.name] with \the [tool].")
- affected.open = 2
+ affected.open = 3
fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
var/obj/item/organ/external/affected = target.get_organ(target_zone)
@@ -134,7 +134,7 @@
var/obj/item/weapon/weldingtool/welder = tool
if(!welder.isOn() || !welder.remove_fuel(1,user))
return 0
- return affected && affected.open == 2 && affected.brute_dam > 0 && target_zone != "mouth"
+ return affected && affected.open == 3 && affected.brute_dam > 0 && target_zone != "mouth"
begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
var/obj/item/organ/external/affected = target.get_organ(target_zone)
@@ -166,7 +166,7 @@
if(..())
var/obj/item/stack/cable_coil/C = tool
var/obj/item/organ/external/affected = target.get_organ(target_zone)
- var/limb_can_operate = (affected && affected.open == 2 && affected.burn_dam > 0 && target_zone != "mouth")
+ var/limb_can_operate = (affected && affected.open == 3 && affected.burn_dam > 0 && target_zone != "mouth")
if(limb_can_operate)
if(istype(C))
if(!C.get_amount() >= 3)
@@ -205,17 +205,17 @@
max_duration = 90
can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
-
if (!hasorgans(target))
return
var/obj/item/organ/external/affected = target.get_organ(target_zone)
- if(!affected) return
+ if(!affected)
+ return
var/is_organ_damaged = 0
for(var/obj/item/organ/I in affected.internal_organs)
if(I.damage > 0 && I.robotic >= 2)
is_organ_damaged = 1
break
- return affected.open == 2 && is_organ_damaged
+ return affected.open == 3 && is_organ_damaged
begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
@@ -375,7 +375,7 @@
var/obj/item/device/mmi/M = tool
var/obj/item/organ/external/affected = target.get_organ(target_zone)
- if(!(affected && affected.open == 2))
+ if(!(affected && affected.open == 3))
return 0
if(!istype(M))
diff --git a/code/modules/surgery/surgery.dm b/code/modules/surgery/surgery.dm
index e582d1222f7..30d9e86f8a1 100644
--- a/code/modules/surgery/surgery.dm
+++ b/code/modules/surgery/surgery.dm
@@ -110,6 +110,7 @@ proc/do_surgery(mob/living/carbon/M, mob/living/user, obj/item/tool)
if (user.a_intent == I_HELP)
user << "You can't see any useful way to use [tool] on [M]."
+ return 1 //Prevents attacking your patient on help intent
return 0
proc/sort_surgeries()
diff --git a/code/modules/telesci/bscrystal.dm b/code/modules/telesci/bscrystal.dm
index 2f06ac3c1bc..e9de80093c6 100644
--- a/code/modules/telesci/bscrystal.dm
+++ b/code/modules/telesci/bscrystal.dm
@@ -6,7 +6,7 @@
icon = 'icons/obj/telescience.dmi'
icon_state = "bluespace_crystal"
w_class = 1
- origin_tech = "bluespace=4;materials=3"
+ origin_tech = list(TECH_BLUESPACE = 4, TECH_MATERIAL = 3)
var/blink_range = 8 // The teleport range when crushed/thrown at someone.
@@ -42,5 +42,5 @@
/obj/item/bluespace_crystal/artificial
name = "artificial bluespace crystal"
desc = "An artificially made bluespace crystal, it looks delicate."
- origin_tech = "bluespace=2"
+ origin_tech = list(TECH_BLUESPACE = 2)
blink_range = 4 // Not as good as the organic stuff!
diff --git a/code/modules/telesci/gps.dm b/code/modules/telesci/gps.dm
index 6271a79a6dd..3ea12461f42 100644
--- a/code/modules/telesci/gps.dm
+++ b/code/modules/telesci/gps.dm
@@ -6,7 +6,7 @@ var/list/GPS_list = list()
icon_state = "gps-c"
w_class = 2
slot_flags = SLOT_BELT
- origin_tech = "programming=2;engineering=2"
+ origin_tech = list(TECH_DATA = 2, TECH_ENGINEERING = 2)
var/gpstag = "COM0"
var/emped = 0
var/turf/locked_location
diff --git a/code/modules/telesci/telepad.dm b/code/modules/telesci/telepad.dm
index 2317c4775b9..565a67f6f4b 100644
--- a/code/modules/telesci/telepad.dm
+++ b/code/modules/telesci/telepad.dm
@@ -94,7 +94,7 @@
icon = 'icons/obj/radio.dmi'
icon_state = "beacon"
item_state = "signaler"
- origin_tech = "bluespace=3"
+ origin_tech = list(TECH_BLUESPACE = 3)
/obj/item/device/telepad_beacon/attack_self(mob/user)
if(user)
diff --git a/config/example/config.txt b/config/example/config.txt
index 7f730bef569..6082e8703e9 100644
--- a/config/example/config.txt
+++ b/config/example/config.txt
@@ -162,7 +162,8 @@ VOTE_AUTOGAMEMODE_TIMELEFT 100
## min delay (deciseconds) before a transfer vote can be called (default 120 minutes)
TRANSFER_TIMEOUT 72000
-## prevents dead players from voting or starting votes
+## Prevets lobby-sitters and ghosts who went straight from the lobby to observing from voting.
+## Ghosts who died will still be able to vote.
#NO_DEAD_VOTE
## players' votes default to "No vote" (otherwise, default to "No change")
diff --git a/config/example/discord.txt b/config/example/discord.txt
index c7725c4f755..ea66b2cc9ab 100644
--- a/config/example/discord.txt
+++ b/config/example/discord.txt
@@ -7,3 +7,6 @@
## Uncomment this to enable robust debugging.
## This results in more messages being sent via log_debug() during bot operations.
# ROBUST_DEBUG
+
+## The subscriber role ID goes here.
+# SUBSCRIBER
diff --git a/config/example/tips.txt b/config/example/tips.txt
index 1291e1d4240..5683ad344bc 100644
--- a/config/example/tips.txt
+++ b/config/example/tips.txt
@@ -12,11 +12,11 @@ You can grab someone by clicking on them with the grab intent, then upgrade the
Holding alt and left clicking a tile will allow you to see its contents in the top right window pane, which is much faster than right clicking.
The resist button will allow you to resist out of handcuffs, being buckled to a chair or bed, out of locked lockers and more. Whenever you're stuck, try resisting!
You can move an item out of the way by dragging it and then clicking on an adjacent tile with an empty hand.
-Maintenance is full of equipment that is randomized every round. Look around and see if anything is worth using.There are many places around the station to hide contraband. A few for starters: linen boxes, toilet cisterns, body bags. Experiment to find more!
+Maintenance is full of equipment that is randomized every round. Look around and see if anything is worth using. There are many places around the station to hide contraband. A few for starters: linen boxes, toilet cisterns, body bags. Experiment to find more!
As the Captain, you are one of the highest priority targets on the station. Everything from revolutions, to nuclear operatives, to traitors that need to rob you of your unique lasgun or your life are things to worry about.
As the Captain, you have absolute access and control over the station, but this does not mean that being a horrible person won't result in mutiny and a ban.
As the Chief Medical Officer, your hypospray is like an instant injection syringe that can hold 30 units as opposed to the standard 15.
-As the Chief Medical Officer, coordinate and communicate with your doctors, chemists, and EMTs during a nuclear emergency, blob infestation, or some other crisis to keep people alive and fighting.
+As the Chief Medical Officer, coordinate and communicate with your doctors, chemists, and EMTs during a pirate raid, blob infestation, or some other crisis to keep people alive and fighting.
As a Medical Doctor, you can attempt to drain blood from a husk with a syringe to determine the cause. If you can extract blood, it was caused by extreme temperatures or lasers, if there is no blood to extract, it was caused by something unnatural.
As a Medical Doctor, you can surgically implant or extract things from people's chests. This can range from putting in a bomb to pulling out an alien larva.
As a Medical Doctor, you must target the correct limb and be on help intent when trying to perform surgery on someone.
@@ -24,8 +24,8 @@ As a Chemist, there are dozens of chemicals that can heal, and even more that ca
As the Virologist, you only require small amounts of vaccine to heal a sick patient. Work with the Chemist to distribute your cures more efficiently.
As the Research Director, you can take AIs out of their cores by loading them into an intelliCard, and then from there into an AI system integrity restorer computer to revive and/or repair them.
As the Research Director, you can lock down cyborgs instead of blowing them up. Then you can have their laws reset or if that doesn't work, safely dismantled.
-As a Xenoscientist, you can inject yourself with the mutation toxin extracted from green slimes to become a slime person, who will never be attacked by slimes!
-As a Xenoscientist, you can maximize the number of uses you get out of a slime by feeding it slime steroid, created from purple slimes, while alive. You can then apply extract enhancer, created from cerulean slimes, on each extract.
+As a Xenobiologist, you can inject yourself with the mutation toxin extracted from green slimes to become a slime person, who will never be attacked by slimes!
+As a Xenobiologist, you can maximize the number of uses you get out of a slime by feeding it slime steroid, created from purple slimes, while alive. You can then apply extract enhancer, created from cerulean slimes, on each extract.
As a Scientist, researchable machine parts can seriously improve the efficiency and speed of machines around the station. In some cases, it can even unlock new functions.
As a Scientist, the teleporter in Misc research can be set-up to teleport across the whole station! All you need to do is crack the formula.
As a Roboticist, you can repair your cyborgs with a welding tool. If they have taken burn damage from lasers, you can remove their battery, expose the wiring with a screwdriver and replace their wires with a cable coil.
@@ -40,8 +40,6 @@ As the Chief Engineer, you can rename areas or create entirely new ones using yo
As the Research Director, you can spy on and even forge PDA communications with the message monitor console! The key is in your office.
As an Engineer, the supermatter shard is an extremely dangerous piece of equipment: touching it will disintegrate you.
As an Engineer, you can electrify grilles by placing wire "nodes" beneath them: the big seemingly unconnected bulges from a half completed wiring job.
-As an Engineer, you can power the station solely with the solar arrays. While uninteresting, it is a much safer alternative to most other engines.
-As an Engineer, you can repair windows by using a welding tool on them while on any intent other than harm.
As an Engineer, you can lock emitters using your ID card to prevent others from disabling them.
As an Atmospheric Technician, you can't unwrench a pipe if the pressure within is too high.
As the Head of Security, you are expected to coordinate your security force to handle any threat that comes to the station. Sometimes it means making use of the armory to handle a blob, sometimes it means being ruthless during a revolution or cult.
@@ -80,11 +78,11 @@ As a Traitor, the Captain and the Head of Security are two of the most difficult
As a Traitor, you can manufacture and recycle revolver bullets at a hacked autolathe, making the revolver an extremely powerful tool.
As a Traitor, you may sometimes hunt other traitors, and in turn be hunted by them.
As a Traitor, the syndicate encryption key is very useful for coordinating plans with your fellow traitors -- or, of course, betraying them.
-As a Nuclear Operative, communication is key! Use your radio to speak to your fellow operatives and coordinate an attack plan.
-As a Nuclear Operative, you should look into purchasing a syndicate cyborg, as they can provide heavy fire support, are immune to conventional stuns, and can easily take down the AI.
-As a Nuclear Operative, stick together! While your equipment is robust, your fellow operatives are much better at saving your life: they can drag you away from danger while stunned and provide cover fire.
-As a Nuclear Operative, you might end up in a situation where the AI has bolted you into a room. Having some spare C4 in your pocket can save your life.
-As a Monkey, you can crawl through air or scrubber vents by alt+left clicking them. You must drop everything you are wearing and holding to do this, however.
+As a Mercenary, communication is key! Use your radio to speak to your fellow operatives and coordinate an attack plan.
+As a Mercenary, you should look into purchasing a syndicate cyborg, as they can provide heavy fire support, are immune to conventional stuns, and can easily take down the AI.
+As a Mercenary, stick together! While your equipment is robust, your fellow operatives are much better at saving your life: they can drag you away from danger while stunned and provide cover fire.
+As a Mercenary, you might end up in a situation where the AI has bolted you into a room. Having some spare C4 in your pocket can save your life.
+As a Monkey, you can crawl through air or scrubber vents by alt+left clicking them. You must drop everything you are wearing and holding to do this, however.
As a Monkey, you can still wear a few human items, such as backpacks, gas masks and hats, and still have two free hands.
As the Malfunctioning AI, you should either order your cyborgs to dismantle the robotics console or blow it up yourself in order to protect them. Make sure to hunt down all those laptops too!
As an Alien, your melee prowess is unmatched, but your ranged abilities are sorely lacking. Make use of corners to force a melee confrontation!
@@ -134,38 +132,44 @@ Remember the cheesy line!
Toolboxes do more damage if they are full of things, but their contents will spill when you use them as a weapon.
Heads of Staff will be more willing to help you if you bring paperwork that's already filled out.
See no evil, hear no evil, speak no evil.
-Auto-Hiss, despite the name, can be used for Unathi, Tajara, and Vaurca.
+Despite the name, Auto-Hiss can be used for Unathi, Tajara, and Vaurca.
Service borgs can use the special maidborg sprite if they pray hard enough.
-Chainswords and energy weapons can slice walls and people.
+Chainswords and energy weapons can slice both walls and people.
If you see this message something has gone seriously wrong.
If you're having trouble as an antagonist, consider a Dionaea whitelist.
As a Medical Doctor, you can attach limbs from one species to the torso of another species. You too can make your own Frankenstein monster!
The second antag contest is still running, you know.
Killing mice on sight is not and never will be gank, no matter how much people complain.
-As an Unathi, you are the only species capable of wearing the rare Breacher hardsuits.
+Unathi are the only species capable of wearing the rare Breacher hardsuits.
As an Unathi, you can devour small mobs after some time.
-As a Tajaran, you move pretty fast. Zoom zoom, kitty.
-As a Tajaran, your resistance to cold probably doesn't actually help you in space. Feel free to try, though.
-As a Skrell you can look pretty and...uhh...not slip?
-As a Skrell you have free reign to validhunt synthetics. (Not really, please don't do this oh God what have I done).
-As a Human you are the best. Why do you care about your mechanics?
-As a Human you are really very great.
-As an IPC you are immune to most chemicals and gasses.
-As an IPC you can survive longer than most species in space, despite your supposed "weakness".
-As a Dionaea you can survive pretty much anything except a tiny little bottle of weedkiller.
-As a Dionaea you will die in darkness. Find the light at the end of the tunnel, and quick.
-As a Vaurca you can remotely speak to any other Vaurca on board. Not that there are any.
-As a Vaurca you can wade freely through phoron gas. Avoid phoron fires though. Somehow a species that breathes phoron gas is really weak to fire.
+As a Tajara, you move pretty fast. Zoom zoom, kitty.
+As a Tajara, your resistance to cold probably doesn't actually help you in space. Feel free to try, though.
+As a Skrell, you can look pretty and...uhh...not slip?
+As a Skrell, you have free reign to validhunt synthetics. (Not really, please don't do this oh God what have I done).
+As a Human, you are the best. Why do you care about your mechanics?
+As a Human, you are really very great.
+Due to IPCs' synthetic nature, they're immune to most chemicals and gasses.
+IPCs can survive longer than most species in space, despite their supposed "weakness".
+As a Dionaea, you can survive pretty much anything except a tiny little bottle of weedkiller.
+Dionae die in darkness. Find the light at the end of the tunnel, and quick.
+All Vaurca can remotely speak to any other Vaurca on board. Not that there are any.
+Vaurca can wade freely through phoron gas. Avoid phoron fires though. Somehow a species that breathes phoron gas is really weak to fire.
As an ERT trooper, your most powerful weapons are your team mates. Your second most powerful weapon is your bigass gun.
-As an ERT trooper you're still expected to roleplay and progress the round.
+ERT troopers are still expected to roleplay and progress the round. Try not to wordlessly gun down everyone you see.
As a Ninja, you should learn the difference between invisibility and invulnerability.
As a Ninja, you have a pretty badass sword. Use it.
-As a Cortical Borer, you a limp feather can kill you if you're outside of a host.
-As a NanoTrasen Actor you can't do anything. Thank Bay.
+A Ninja's sword can cut through many objects. Experiment!
+As a Cortical Borer, a limp feather can kill you if you're outside of a host.
+NanoTrasen Actors can't do anything. Thank Bay.
As a Syndicate Commando you are a Nuke Operative with bigger and better guns. Use them.
As a Death Commando you have only one course of action: RIP AND TEAR.
As a Highlander, there can be only one.
As a Loyalist, remember that you are an antagonist too!
As a Renegade, consider playing a better gamemode.
As a Vampire, you can create new vampires out of willing and less than willing crew. Mind that new vampires may decide to turn their powers against you.
-As a Vampire, if you start going hungry for blood don't expect to stay hidden for long.
\ No newline at end of file
+As a Vampire, if you start going hungry for blood don't expect to stay hidden for long.
+You can use . (period) instead of : to speak into a radio.
+The radio key .i will allow you to speak into a nearby intercom, .r will speak into a radio in your right hand, and .l will speak into your left. The microphone does not need to be enabled for this to work.
+Your ID card's access determines what departmental channels you can set intercoms to.
+You can fax papers between request consoles by attacking the console with a paper. Make sure the paper tray is closed first!
+No wall or window is 100% impervious to heat.
diff --git a/html/changelog.html b/html/changelog.html
index 7fff4929a01..b3abe25e263 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -1,7 +1,7 @@
-
+
- Baystation 12 Changelog
+ Aurorastation Changelog