diff --git a/code/__DEFINES/clothing.dm b/code/__DEFINES/clothing.dm
index 76818446795..fabe22f95c4 100644
--- a/code/__DEFINES/clothing.dm
+++ b/code/__DEFINES/clothing.dm
@@ -47,6 +47,8 @@
#define slot_legcuffed 19
#define slot_drone_storage 20
+#define slots_amt 20 // Keep this up to date!
+
//Cant seem to find a mob bitflags area other than the powers one
// bitflags for clothing parts - also used for limbs
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index 83849c86068..b5c2e9e0cdb 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -315,6 +315,7 @@ var/list/bloody_footprints_cache = list()
#define SENTIENCE_ORGANIC 1
#define SENTIENCE_ARTIFICIAL 2
#define SENTIENCE_OTHER 3
+#define SENTIENCE_MINEBOT 4
//Fire stuff, for burn_state
#define LAVA_PROOF -2
diff --git a/code/__DEFINES/sight.dm b/code/__DEFINES/sight.dm
index 1bbb24cf4cf..097ac213004 100644
--- a/code/__DEFINES/sight.dm
+++ b/code/__DEFINES/sight.dm
@@ -21,3 +21,4 @@
#define BORGMESON 1
#define BORGTHERM 2
#define BORGXRAY 4
+#define BORGMATERIAL 8
diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm
index ff88b0a70e0..371ba01bb99 100644
--- a/code/__HELPERS/game.dm
+++ b/code/__HELPERS/game.dm
@@ -332,13 +332,19 @@
for(var/client/C in show_to)
C.images -= I
-/proc/get_active_player_count()
+/proc/get_active_player_count(var/alive_check = 0, var/afk_check = 0, var/human_check = 0)
// Get active players who are playing in the round
var/active_players = 0
for(var/i = 1; i <= player_list.len; i++)
var/mob/M = player_list[i]
if(M && M.client)
- if(istype(M, /mob/new_player)) // exclude people in the lobby
+ if(alive_check && M.stat)
+ continue
+ else if(afk_check && M.client.is_afk())
+ continue
+ else if(human_check && !istype(M, /mob/living/carbon/human))
+ continue
+ else if(istype(M, /mob/new_player)) // exclude people in the lobby
continue
else if(isobserver(M)) // Ghosts are fine if they were playing once (didn't start as observers)
var/mob/dead/observer/O = M
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index e509e5bb806..c1dd0f89a46 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -901,8 +901,8 @@ var/list/WALLITEMS_INVERSE = list(
for(var/id in cached_gases)
var/gas_concentration = cached_gases[id][MOLES]/total_moles
- if(id in hardcoded_gases || gas_concentration > 0.01) //ensures the four primary gases are always shown.
- user << "[cached_gases[id][GAS_META][META_GAS_NAME]]: [round(gas_concentration*100)] %"
+ if(id in hardcoded_gases || gas_concentration > 0.001) //ensures the four primary gases are always shown.
+ user << "[cached_gases[id][GAS_META][META_GAS_NAME]]: [round(gas_concentration*100, 0.01)] %"
user << "Temperature: [round(air_contents.temperature-T0C)] °C"
else
diff --git a/code/_globalvars/lists/names.dm b/code/_globalvars/lists/names.dm
index 834f4aa8dd6..9aa8b5e07e2 100644
--- a/code/_globalvars/lists/names.dm
+++ b/code/_globalvars/lists/names.dm
@@ -11,9 +11,10 @@ var/list/lizard_names_male = file2list("config/names/lizard_male.txt")
var/list/lizard_names_female = file2list("config/names/lizard_female.txt")
var/list/clown_names = file2list("config/names/clown.txt")
var/list/mime_names = file2list("config/names/mime.txt")
+var/list/golem_names = file2list("config/names/golem.txt")
var/list/verbs = file2list("config/names/verbs.txt")
var/list/adjectives = file2list("config/names/adjectives.txt")
//loaded on startup because of "
-//would include in rsc if ' was used
\ No newline at end of file
+//would include in rsc if ' was used
diff --git a/code/_onclick/hud/alien.dm b/code/_onclick/hud/alien.dm
index 7b11372bac4..7313091df06 100644
--- a/code/_onclick/hud/alien.dm
+++ b/code/_onclick/hud/alien.dm
@@ -37,50 +37,34 @@
//equippable shit
//hands
- inv_box = new /obj/screen/inventory()
- inv_box.name = "r_hand"
+ inv_box = new /obj/screen/inventory/hand()
+ inv_box.name = "right hand"
inv_box.icon = 'icons/mob/screen_alien.dmi'
- inv_box.icon_state = "hand_r_inactive"
- if(mymob && !mymob.hand) //This being 0 or null means the right hand is in use
- inv_box.icon_state = "hand_r_active"
+ inv_box.icon_state = "hand_r"
inv_box.screen_loc = ui_rhand
- inv_box.layer = 19
inv_box.slot_id = slot_r_hand
- r_hand_hud_object = inv_box
- if(owner.handcuffed)
- inv_box.overlays += image("icon"='icons/mob/screen_gen.dmi', "icon_state"="markus")
static_inventory += inv_box
- inv_box = new /obj/screen/inventory()
- inv_box.name = "l_hand"
+ inv_box = new /obj/screen/inventory/hand()
+ inv_box.name = "left hand"
inv_box.icon = 'icons/mob/screen_alien.dmi'
- inv_box.icon_state = "hand_l_inactive"
- if(mymob && mymob.hand) //This being 1 means the left hand is in use
- inv_box.icon_state = "hand_l_active"
+ inv_box.icon_state = "hand_l"
inv_box.screen_loc = ui_lhand
- inv_box.layer = 19
inv_box.slot_id = slot_l_hand
- l_hand_hud_object = inv_box
- if(owner.handcuffed)
- inv_box.overlays += image("icon"='icons/mob/screen_gen.dmi', "icon_state"="gabrielle")
static_inventory += inv_box
//begin buttons
- using = new /obj/screen/inventory()
- using.name = "hand"
+ using = new /obj/screen/swap_hand()
using.icon = 'icons/mob/screen_alien.dmi'
using.icon_state = "swap_1"
using.screen_loc = ui_swaphand1
- using.layer = 19
static_inventory += using
- using = new /obj/screen/inventory()
- using.name = "hand"
+ using = new /obj/screen/swap_hand()
using.icon = 'icons/mob/screen_alien.dmi'
using.icon_state = "swap_2"
using.screen_loc = ui_swaphand2
- using.layer = 19
static_inventory += using
using = new /obj/screen/act_intent/alien()
@@ -130,6 +114,12 @@
zone_select.update_icon(mymob)
static_inventory += zone_select
+ for(var/obj/screen/inventory/inv in (static_inventory + toggleable_inventory))
+ if(inv.slot_id)
+ inv.hud = src
+ inv_slots[inv.slot_id] = inv
+ inv.update_icon()
+
/datum/hud/alien/persistant_inventory_update()
if(!mymob)
return
diff --git a/code/_onclick/hud/drones.dm b/code/_onclick/hud/drones.dm
index 7e2d478c2ab..de79a28c5a2 100644
--- a/code/_onclick/hud/drones.dm
+++ b/code/_onclick/hud/drones.dm
@@ -14,68 +14,62 @@
pull_icon.screen_loc = ui_drone_pull
static_inventory += pull_icon
- inv_box = new /obj/screen/inventory()
- inv_box.name = "r_hand"
+ inv_box = new /obj/screen/inventory/hand()
+ inv_box.name = "right hand"
inv_box.icon = ui_style
- inv_box.icon_state = "hand_r_inactive"
- if(mymob && !mymob.hand) //Hand being true means the LEFT hand is active
- inv_box.icon_state = "hand_r_active"
+ inv_box.icon_state = "hand_r"
inv_box.screen_loc = ui_rhand
inv_box.slot_id = slot_r_hand
- inv_box.layer = 19
- r_hand_hud_object = inv_box
static_inventory += inv_box
- inv_box = new /obj/screen/inventory()
- inv_box.name = "l_hand"
+ inv_box = new /obj/screen/inventory/hand()
+ inv_box.name = "left hand"
inv_box.icon = ui_style
- inv_box.icon_state = "hand_l_inactive"
- if(mymob && mymob.hand) //Hand being true means the LEFT hand is active
- inv_box.icon_state = "hand_l_active"
+ inv_box.icon_state = "hand_l"
inv_box.screen_loc = ui_lhand
inv_box.slot_id = slot_l_hand
- inv_box.layer = 19
- l_hand_hud_object = inv_box
static_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "internal storage"
inv_box.icon = ui_style
inv_box.icon_state = "suit_storage"
+// inv_box.icon_full = "template"
inv_box.screen_loc = ui_drone_storage
inv_box.slot_id = slot_drone_storage
- inv_box.layer = 19
static_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "head/mask"
inv_box.icon = ui_style
inv_box.icon_state = "mask"
+// inv_box.icon_full = "template"
inv_box.screen_loc = ui_drone_head
inv_box.slot_id = slot_head
- inv_box.layer = 19
static_inventory += inv_box
- using = new /obj/screen/inventory()
- using.name = "hand"
+ using = new /obj/screen/swap_hand()
using.icon = ui_style
using.icon_state = "swap_1_m"
using.screen_loc = ui_swaphand1
- using.layer = 19
static_inventory += using
- using = new /obj/screen/inventory()
- using.name = "hand"
+ using = new /obj/screen/swap_hand()
using.icon = ui_style
using.icon_state = "swap_2"
using.screen_loc = ui_swaphand2
- using.layer = 19
static_inventory += using
zone_select = new /obj/screen/zone_sel()
zone_select.icon = ui_style
zone_select.update_icon(mymob)
+ for(var/obj/screen/inventory/inv in (static_inventory + toggleable_inventory))
+ if(inv.slot_id)
+ inv.hud = src
+ inv_slots[inv.slot_id] = inv
+ inv.update_icon()
+
/datum/hud/drone/persistant_inventory_update()
if(!mymob)
diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm
index d794ff09c7c..ff86c8ce2c5 100644
--- a/code/_onclick/hud/hud.dm
+++ b/code/_onclick/hud/hud.dm
@@ -24,8 +24,6 @@
var/obj/screen/deity_follower_display
var/obj/screen/nightvisionicon
- var/obj/screen/r_hand_hud_object
- var/obj/screen/l_hand_hud_object
var/obj/screen/action_intent
var/obj/screen/zone_select
var/obj/screen/pull_icon
@@ -37,6 +35,7 @@
var/list/obj/screen/hotkeybuttons = list() //the buttons that can be used via hotkeys
var/list/infodisplay = list() //the screen objects that display mob info (health, alien plasma, etc...)
var/list/screenoverlays = list() //the screen objects used as whole screen overlays (flash, damageoverlay, etc...)
+ var/list/inv_slots[slots_amt] // /obj/screen/inventory objects, ordered by their slot ID.
var/obj/screen/movable/action_button/hide_toggle/hide_actions_toggle
var/action_buttons_hidden = 0
@@ -65,8 +64,7 @@
qdel(thing)
static_inventory.Cut()
- r_hand_hud_object = null
- l_hand_hud_object = null
+ inv_slots.Cut()
action_intent = null
zone_select = null
pull_icon = null
@@ -154,10 +152,10 @@
mymob.client.screen += infodisplay
//These ones are a part of 'static_inventory', 'toggleable_inventory' or 'hotkeybuttons' but we want them to stay
- if(l_hand_hud_object)
- mymob.client.screen += l_hand_hud_object //we want the hands to be visible
- if(r_hand_hud_object)
- mymob.client.screen += r_hand_hud_object //we want the hands to be visible
+ if(inv_slots[slot_l_hand])
+ mymob.client.screen += inv_slots[slot_l_hand] //we want the hands to be visible
+ if(inv_slots[slot_r_hand])
+ mymob.client.screen += inv_slots[slot_r_hand] //we want the hands to be visible
if(action_intent)
mymob.client.screen += action_intent //we want the intent switcher visible
action_intent.screen_loc = ui_acti_alt //move this to the alternative position, where zone_select usually is.
diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm
index 8991dd28480..40bb0c2d7d0 100644
--- a/code/_onclick/hud/human.dm
+++ b/code/_onclick/hud/human.dm
@@ -76,8 +76,8 @@
inv_box.icon = ui_style
inv_box.slot_id = slot_w_uniform
inv_box.icon_state = "uniform"
+// inv_box.icon_full = "template"
inv_box.screen_loc = ui_iclothing
- inv_box.layer = 19
toggleable_inventory += inv_box
inv_box = new /obj/screen/inventory()
@@ -85,106 +85,90 @@
inv_box.icon = ui_style
inv_box.slot_id = slot_wear_suit
inv_box.icon_state = "suit"
+// inv_box.icon_full = "template"
inv_box.screen_loc = ui_oclothing
- inv_box.layer = 19
toggleable_inventory += inv_box
- inv_box = new /obj/screen/inventory()
- inv_box.name = "r_hand"
+ inv_box = new /obj/screen/inventory/hand()
+ inv_box.name = "right hand"
inv_box.icon = ui_style
- inv_box.icon_state = "hand_r_inactive"
- if(mymob && !mymob.hand) //This being 0 or null means the right hand is in use
- inv_box.icon_state = "hand_r_active"
+ inv_box.icon_state = "hand_r"
inv_box.screen_loc = ui_rhand
inv_box.slot_id = slot_r_hand
- inv_box.layer = 19
- r_hand_hud_object = inv_box
- if(owner.handcuffed)
- inv_box.overlays += image("icon"='icons/mob/screen_gen.dmi', "icon_state"="markus")
static_inventory += inv_box
- inv_box = new /obj/screen/inventory()
- inv_box.name = "l_hand"
+ inv_box = new /obj/screen/inventory/hand()
+ inv_box.name = "left hand"
inv_box.icon = ui_style
- inv_box.icon_state = "hand_l_inactive"
- if(mymob && mymob.hand) //This being 1 means the left hand is in use
- inv_box.icon_state = "hand_l_active"
+ inv_box.icon_state = "hand_l"
inv_box.screen_loc = ui_lhand
inv_box.slot_id = slot_l_hand
- inv_box.layer = 19
- l_hand_hud_object = inv_box
- if(owner.handcuffed)
- inv_box.overlays += image("icon"='icons/mob/screen_gen.dmi', "icon_state"="gabrielle")
static_inventory += inv_box
- using = new /obj/screen/inventory()
- using.name = "hand"
+ using = new /obj/screen/swap_hand()
using.icon = ui_style
using.icon_state = "swap_1"
using.screen_loc = ui_swaphand1
- using.layer = 19
static_inventory += using
- using = new /obj/screen/inventory()
- using.name = "hand"
+ using = new /obj/screen/swap_hand()
using.icon = ui_style
using.icon_state = "swap_2"
using.screen_loc = ui_swaphand2
- using.layer = 19
static_inventory += using
inv_box = new /obj/screen/inventory()
inv_box.name = "id"
inv_box.icon = ui_style
inv_box.icon_state = "id"
+// inv_box.icon_full = "template_small"
inv_box.screen_loc = ui_id
inv_box.slot_id = slot_wear_id
- inv_box.layer = 19
static_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "mask"
inv_box.icon = ui_style
inv_box.icon_state = "mask"
+// inv_box.icon_full = "template"
inv_box.screen_loc = ui_mask
inv_box.slot_id = slot_wear_mask
- inv_box.layer = 19
toggleable_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "back"
inv_box.icon = ui_style
inv_box.icon_state = "back"
+// inv_box.icon_full = "template_small"
inv_box.screen_loc = ui_back
inv_box.slot_id = slot_back
- inv_box.layer = 19
static_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "storage1"
inv_box.icon = ui_style
inv_box.icon_state = "pocket"
+// inv_box.icon_full = "template_small"
inv_box.screen_loc = ui_storage1
inv_box.slot_id = slot_l_store
- inv_box.layer = 19
static_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "storage2"
inv_box.icon = ui_style
inv_box.icon_state = "pocket"
+// inv_box.icon_full = "template_small"
inv_box.screen_loc = ui_storage2
inv_box.slot_id = slot_r_store
- inv_box.layer = 19
static_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "suit storage"
inv_box.icon = ui_style
inv_box.icon_state = "suit_storage"
+// inv_box.icon_full = "template"
inv_box.screen_loc = ui_sstore1
inv_box.slot_id = slot_s_store
- inv_box.layer = 19
static_inventory += inv_box
using = new /obj/screen/resist()
@@ -206,54 +190,54 @@
inv_box.name = "gloves"
inv_box.icon = ui_style
inv_box.icon_state = "gloves"
+// inv_box.icon_full = "template"
inv_box.screen_loc = ui_gloves
inv_box.slot_id = slot_gloves
- inv_box.layer = 19
toggleable_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "eyes"
inv_box.icon = ui_style
inv_box.icon_state = "glasses"
+// inv_box.icon_full = "template"
inv_box.screen_loc = ui_glasses
inv_box.slot_id = slot_glasses
- inv_box.layer = 19
toggleable_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "ears"
inv_box.icon = ui_style
inv_box.icon_state = "ears"
+// inv_box.icon_full = "template"
inv_box.screen_loc = ui_ears
inv_box.slot_id = slot_ears
- inv_box.layer = 19
toggleable_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "head"
inv_box.icon = ui_style
inv_box.icon_state = "head"
+// inv_box.icon_full = "template"
inv_box.screen_loc = ui_head
inv_box.slot_id = slot_head
- inv_box.layer = 19
toggleable_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "shoes"
inv_box.icon = ui_style
inv_box.icon_state = "shoes"
+// inv_box.icon_full = "template"
inv_box.screen_loc = ui_shoes
inv_box.slot_id = slot_shoes
- inv_box.layer = 19
toggleable_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "belt"
inv_box.icon = ui_style
inv_box.icon_state = "belt"
+// inv_box.icon_full = "template_small"
inv_box.screen_loc = ui_belt
inv_box.slot_id = slot_belt
- inv_box.layer = 19
static_inventory += inv_box
throw_icon = new /obj/screen/throw_catch()
@@ -290,6 +274,12 @@
inventory_shown = 0
+ for(var/obj/screen/inventory/inv in (static_inventory + toggleable_inventory))
+ if(inv.slot_id)
+ inv.hud = src
+ inv_slots[inv.slot_id] = inv
+ inv.update_icon()
+
/datum/hud/human/hidden_inventory_update()
if(!mymob)
return
diff --git a/code/_onclick/hud/monkey.dm b/code/_onclick/hud/monkey.dm
index 021310f06e1..b7d8437e02a 100644
--- a/code/_onclick/hud/monkey.dm
+++ b/code/_onclick/hud/monkey.dm
@@ -21,75 +21,59 @@
using.screen_loc = ui_drop_throw
static_inventory += using
- inv_box = new /obj/screen/inventory()
- inv_box.name = "r_hand"
+ inv_box = new /obj/screen/inventory/hand()
+ inv_box.name = "right hand"
inv_box.icon = ui_style
- inv_box.icon_state = "hand_r_inactive"
- if(mymob && !mymob.hand) //This being 0 or null means the right hand is in use
- inv_box.icon_state = "hand_r_active"
+ inv_box.icon_state = "hand_r"
inv_box.screen_loc = ui_rhand
inv_box.slot_id = slot_r_hand
- inv_box.layer = 19
- r_hand_hud_object = inv_box
- if(owner.handcuffed)
- inv_box.overlays += image("icon"='icons/mob/screen_gen.dmi', "icon_state"="markus")
static_inventory += inv_box
- inv_box = new /obj/screen/inventory()
- inv_box.name = "l_hand"
+ inv_box = new /obj/screen/inventory/hand()
+ inv_box.name = "left hand"
inv_box.icon = ui_style
- inv_box.icon_state = "hand_l_inactive"
- if(mymob && mymob.hand) //This being 1 means the left hand is in use
- inv_box.icon_state = "hand_l_active"
+ inv_box.icon_state = "hand_l"
inv_box.screen_loc = ui_lhand
inv_box.slot_id = slot_l_hand
- inv_box.layer = 19
- l_hand_hud_object = inv_box
- if(owner.handcuffed)
- inv_box.overlays += image("icon"='icons/mob/screen_gen.dmi', "icon_state"="gabrielle")
static_inventory += inv_box
- using = new /obj/screen/inventory()
- using.name = "hand"
+ using = new /obj/screen/swap_hand()
using.icon = ui_style
using.icon_state = "swap_1_m" //extra wide!
using.screen_loc = ui_swaphand1
- using.layer = 19
static_inventory += using
- using = new /obj/screen/inventory()
- using.name = "hand"
+ using = new /obj/screen/swap_hand()
using.icon = ui_style
using.icon_state = "swap_2"
using.screen_loc = ui_swaphand2
- using.layer = 19
static_inventory += using
inv_box = new /obj/screen/inventory()
inv_box.name = "mask"
inv_box.icon = ui_style
inv_box.icon_state = "mask"
+// inv_box.icon_full = "template"
inv_box.screen_loc = ui_monkey_mask
inv_box.slot_id = slot_wear_mask
- inv_box.layer = 19
static_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "head"
inv_box.icon = ui_style
inv_box.icon_state = "head"
+// inv_box.icon_full = "template"
inv_box.screen_loc = ui_monkey_head
inv_box.slot_id = slot_head
- inv_box.layer = 19
static_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "back"
inv_box.icon = ui_style
inv_box.icon_state = "back"
+ inv_box.icon_full = "template_small"
inv_box.screen_loc = ui_back
inv_box.slot_id = slot_back
- inv_box.layer = 19
static_inventory += inv_box
throw_icon = new /obj/screen/throw_catch()
@@ -128,6 +112,12 @@
using.screen_loc = ui_pull_resist
hotkeybuttons += using
+ for(var/obj/screen/inventory/inv in (static_inventory + toggleable_inventory))
+ if(inv.slot_id)
+ inv.hud = src
+ inv_slots[inv.slot_id] = inv
+ inv.update_icon()
+
/datum/hud/monkey/persistant_inventory_update()
if(!mymob)
return
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index 13a6f9a00a2..2fc47ab95be 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -13,6 +13,7 @@
unacidable = 1
appearance_flags = APPEARANCE_UI
var/obj/master = null //A reference to the object in the slot. Grabs or items, generally.
+ var/datum/hud/hud = null // A reference to the owner HUD, if any.
/obj/screen/Destroy()
master = null
@@ -27,19 +28,107 @@
maptext_height = 480
maptext_width = 480
+/obj/screen/swap_hand
+ layer = 19
+ name = "swap hand"
+
+/obj/screen/swap_hand/Click()
+ // At this point in client Click() code we have passed the 1/10 sec check and little else
+ // We don't even know if it's a middle click
+ if(world.time <= usr.next_move)
+ return 1
+
+ if(usr.incapacitated())
+ return 1
+
+ if(ismob(usr))
+ var/mob/M = usr
+ M.swap_hand()
+ return 1
+
/obj/screen/inventory
- var/slot_id //The indentifier for the slot. It has nothing to do with ID cards.
+ var/slot_id // The indentifier for the slot. It has nothing to do with ID cards.
+ var/icon_empty // Icon when empty. For now used only by humans.
+ var/icon_full // Icon when contains an item. For now used only by humans.
+ layer = 19
+/obj/screen/inventory/Click()
+ // At this point in client Click() code we have passed the 1/10 sec check and little else
+ // We don't even know if it's a middle click
+ if(world.time <= usr.next_move)
+ return 1
+
+ if(usr.incapacitated())
+ return 1
+ if (istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech
+ return 1
+ if(usr.attack_ui(slot_id))
+ usr.update_inv_l_hand(0)
+ usr.update_inv_r_hand(0)
+ return 1
+
+/obj/screen/inventory/update_icon()
+ if(!icon_empty)
+ icon_empty = icon_state
+
+ if(hud && hud.mymob && slot_id && icon_full)
+ if(hud.mymob.get_item_by_slot(slot_id))
+ icon_state = icon_full
+ else
+ icon_state = icon_empty
+
+/obj/screen/inventory/hand
+ var/image/active_overlay
+ var/image/handcuff_overlay
+
+/obj/screen/inventory/hand/update_icon()
+ ..()
+ if(!active_overlay)
+ active_overlay = image("icon"=icon, "icon_state"="hand_active")
+ if(!handcuff_overlay)
+ var/state = (slot_id == slot_r_hand) ? "markus" : "gabrielle"
+ handcuff_overlay = image("icon"='icons/mob/screen_gen.dmi', "icon_state"=state)
+
+ overlays.Cut()
+
+ if(hud && hud.mymob)
+ if(iscarbon(hud.mymob))
+ var/mob/living/carbon/C = hud.mymob
+ if(C.handcuffed)
+ overlays += handcuff_overlay
+
+ if(slot_id == slot_l_hand && hud.mymob.hand)
+ overlays += active_overlay
+ else if(slot_id == slot_r_hand && !hud.mymob.hand)
+ overlays += active_overlay
+
+/obj/screen/inventory/hand/Click()
+ // At this point in client Click() code we have passed the 1/10 sec check and little else
+ // We don't even know if it's a middle click
+ if(world.time <= usr.next_move)
+ return 1
+ if(usr.incapacitated())
+ return 1
+ if (istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech
+ return 1
+
+ if(ismob(usr))
+ var/mob/M = usr
+ switch(name)
+ if("right hand", "r_hand")
+ M.activate_hand("r")
+ if("left hand", "l_hand")
+ M.activate_hand("l")
+ return 1
/obj/screen/close
name = "close"
/obj/screen/close/Click()
- if(master)
- if(istype(master, /obj/item/weapon/storage))
- var/obj/item/weapon/storage/S = master
- S.close(usr)
+ if(istype(master, /obj/item/weapon/storage))
+ var/obj/item/weapon/storage/S = master
+ S.close(usr)
return 1
@@ -304,38 +393,6 @@
/obj/screen/zone_sel/robot
icon = 'icons/mob/screen_cyborg.dmi'
-/obj/screen/inventory/Click()
- // At this point in client Click() code we have passed the 1/10 sec check and little else
- // We don't even know if it's a middle click
- if(world.time <= usr.next_move)
- return 1
-
- if(usr.incapacitated())
- return 1
- if (istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech
- return 1
- switch(name)
- if("r_hand")
- if(ismob(usr))
- var/mob/Mr = usr
- Mr.activate_hand("r")
- if("l_hand")
- if(ismob(usr))
- var/mob/Ml = usr
- Ml.activate_hand("l")
- if("swap")
- if(ismob(usr))
- var/mob/Ms = usr
- Ms.swap_hand()
- if("hand")
- if(ismob(usr))
- var/mob/Mh = usr
- Mh.swap_hand()
- else
- if(usr.attack_ui(slot_id))
- usr.update_inv_l_hand(0)
- usr.update_inv_r_hand(0)
- return 1
/obj/screen/flash
name = "flash"
diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm
index 55679b7138c..03a72667267 100644
--- a/code/controllers/configuration.dm
+++ b/code/controllers/configuration.dm
@@ -90,7 +90,6 @@
var/list/probabilities = list() // relative probability of each mode
var/humans_need_surnames = 0
- var/allow_random_events = 0 // enables random events mid-round when set to 1
var/allow_ai = 0 // allow ai job
var/forbid_secborg = 0 // disallow secborg module to be chosen.
var/panic_bunker = 0 // prevents new people it hasn't seen before from connecting
@@ -187,6 +186,13 @@
var/maprotation = 1
var/maprotatechancedelta = 0.75
+ // Enables random events mid-round when set to 1
+ var/allow_random_events = 0
+
+ // Multipliers for random events minimal starting time and minimal players amounts
+ var/events_min_time_mul = 1
+ var/events_min_players_mul = 1
+
// The object used for the clickable stat() button.
var/obj/effect/statclick/statclick
@@ -510,6 +516,12 @@
config.allow_latejoin_antagonists = 1
if("allow_random_events")
config.allow_random_events = 1
+
+ if("events_min_time_mul")
+ config.events_min_time_mul = text2num(value)
+ if("events_min_players_mul")
+ config.events_min_players_mul = text2num(value)
+
if("minimal_access_threshold")
config.minimal_access_threshold = text2num(value)
if("jobs_have_minimal_access")
diff --git a/code/controllers/master.dm b/code/controllers/master.dm
index 33b493a1c4b..7a0da4235a4 100644
--- a/code/controllers/master.dm
+++ b/code/controllers/master.dm
@@ -148,7 +148,7 @@ var/global/datum/controller/master/Master = new()
//this is a queue for any SS skipped or paused for tick reasons, to be ran first next tick
if (priority_queue.len)
priorityrunning = priority_queue.len
- subsystemstorun = priority_queue | subsystems
+ subsystemstorun = priority_queue | subsystemstorun
#endif
var/ran_subsystems = 0
while(subsystemstorun.len)
diff --git a/code/controllers/subsystem/air.dm b/code/controllers/subsystem/air.dm
index 04fcce75dcf..3ce50737474 100644
--- a/code/controllers/subsystem/air.dm
+++ b/code/controllers/subsystem/air.dm
@@ -26,7 +26,7 @@ var/datum/subsystem/air/SSair
//Special functions lists
var/list/turf/active_super_conductivity = list()
- var/list/turf/high_pressure_delta = list()
+ var/list/turf/open/high_pressure_delta = list()
/datum/subsystem/air/New()
@@ -179,7 +179,8 @@ var/datum/subsystem/air/SSair
z_start = z_level
z_finish = z_level
- var/list/turfs_to_init = block(locate(1, 1, z_start), locate(world.maxx, world.maxy, z_finish))
+ var/turf/open/space/S = /turf/open/space
+ var/list/turfs_to_init = block(locate(1, 1, z_start), locate(world.maxx, world.maxy, z_finish)) - S.space_turfs
for(var/thing in turfs_to_init)
var/turf/t = thing
@@ -189,9 +190,6 @@ var/datum/subsystem/air/SSair
if(t.blocks_air)
continue
- if(istype(t, /turf/open/space))
- continue //don't need to initialize these; just slows down roundstart without any real benefit
-
var/turf/open/T = t
T.excited = 0
diff --git a/code/controllers/subsystem/events.dm b/code/controllers/subsystem/events.dm
index 198c6d18300..c4fcf0ab933 100644
--- a/code/controllers/subsystem/events.dm
+++ b/code/controllers/subsystem/events.dm
@@ -70,19 +70,14 @@ var/datum/subsystem/events/SSevent
// if(E) E.runEvent()
return
+ var/gamemode = ticker.mode.config_tag
+ var/players_amt = get_active_player_count(alive_check = 1, afk_check = 1, human_check = 1)
+ // Only alive, non-AFK human players count towards this.
+
var/sum_of_weights = 0
for(var/datum/round_event_control/E in control)
- if(E.occurrences >= E.max_occurrences)
+ if(!E.canSpawnEvent(players_amt, gamemode))
continue
- if(E.earliest_start >= world.time)
- continue
- if(E.gamemode_blacklist.len && (ticker.mode.config_tag in E.gamemode_blacklist))
- continue
- if(E.gamemode_whitelist.len && !(ticker.mode.config_tag in E.gamemode_whitelist))
- continue
- if(E.holidayID)
- if(!holidays || !holidays[E.holidayID])
- continue
if(E.weight < 0) //for round-start events etc.
if(E.runEvent() == PROCESS_KILL)
E.max_occurrences = 0
@@ -96,17 +91,8 @@ var/datum/subsystem/events/SSevent
sum_of_weights = rand(0,sum_of_weights) //reusing this variable. It now represents the 'weight' we want to select
for(var/datum/round_event_control/E in control)
- if(E.occurrences >= E.max_occurrences)
+ if(!E.canSpawnEvent(players_amt, gamemode))
continue
- if(E.earliest_start >= world.time)
- continue
- if(E.gamemode_blacklist.len && (ticker.mode.config_tag in E.gamemode_blacklist))
- continue
- if(E.gamemode_whitelist.len && !(ticker.mode.config_tag in E.gamemode_whitelist))
- continue
- if(E.holidayID)
- if(!holidays || !holidays[E.holidayID])
- continue
sum_of_weights -= E.weight
if(sum_of_weights <= 0) //we've hit our goal
diff --git a/code/controllers/subsystem/lighting.dm b/code/controllers/subsystem/lighting.dm
index e9452869a02..dc6dee36d1a 100644
--- a/code/controllers/subsystem/lighting.dm
+++ b/code/controllers/subsystem/lighting.dm
@@ -5,7 +5,12 @@ var/datum/subsystem/lighting/SSlighting
/datum/subsystem/lighting
name = "Lighting"
priority = 1
- wait = 6
+ wait = 1
+ dynamic_wait = 1
+ dwait_delta = 4
+ dwait_buffer = 0.1
+ dwait_lower = 1
+ dwait_upper = 5
display = 5
var/list/changed_lights = list() //list of all datum/light_source that need updating
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 1a8e401399b..933d8ff2db8 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -62,7 +62,7 @@
src.key = key
-/datum/mind/proc/transfer_to(mob/new_character)
+/datum/mind/proc/transfer_to(mob/new_character, var/force_key_move = 0)
if(current) // remove ourself from our old body's mind variable
current.mind = null
SStgui.on_transfer(current, new_character)
@@ -83,7 +83,7 @@
transfer_antag_huds(hud_to_transfer) //inherit the antag HUD
transfer_actions(new_character)
- if(active)
+ if(active || force_key_move)
new_character.key = key //now transfer the key to link the client to our new body
/datum/mind/proc/store_memory(new_text)
diff --git a/code/game/gamemodes/miniantags/revenant/revenant.dm b/code/game/gamemodes/miniantags/revenant/revenant.dm
index 190864b65fc..a3254bae5b9 100644
--- a/code/game/gamemodes/miniantags/revenant/revenant.dm
+++ b/code/game/gamemodes/miniantags/revenant/revenant.dm
@@ -112,6 +112,7 @@
src << "You can move again!"
if(essence_regenerating && !inhibited && essence < essence_regen_cap) //While inhibited, essence will not regenerate
essence = min(essence_regen_cap, essence+essence_regen_amount)
+ update_action_buttons_icon() //because we update something required by our spells in life, we need to update our buttons
update_spooky_icon()
update_health_hud()
..()
@@ -283,6 +284,7 @@
if(essence + essence_amt <= 0)
return
essence = max(0, essence+essence_amt)
+ update_action_buttons_icon()
update_health_hud()
if(essence_amt > 0)
essence_accumulated = max(0, essence_accumulated+essence_amt)
diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm
index c6cd0c9117e..33d894008f3 100644
--- a/code/game/machinery/deployable.dm
+++ b/code/game/machinery/deployable.dm
@@ -80,7 +80,9 @@
/obj/structure/barricade/CanPass(atom/movable/mover, turf/target, height=0)//So bullets will fly over and stuff.
if(height==0)
return 1
- if(istype(mover, /obj/item/projectile))
+ if(locate(/obj/structure/barricade) in get_turf(mover))
+ return 1
+ else if(istype(mover, /obj/item/projectile))
if(!anchored)
return 1
var/obj/item/projectile/proj = mover
@@ -90,9 +92,7 @@
return 1
return 0
else
- return 0
-
-
+ return !density
@@ -106,6 +106,21 @@
material = WOOD
+/obj/structure/barricade/sandbags
+ name = "sandbags"
+ desc = "Bags of sand. Self explanatory."
+ icon = 'icons/obj/smooth_structures/sandbags.dmi'
+ icon_state = "sandbags"
+ health = 280
+ maxhealth = 280
+ proj_pass_rate = 20
+ pass_flags = LETPASSTHROW
+ material = null
+ climbable = TRUE
+ smooth = SMOOTH_TRUE
+ canSmoothWith = list(/obj/structure/barricade/sandbags, /turf/simulated/wall, /turf/simulated/wall/r_wall, /obj/structure/falsewall, /obj/structure/falsewall/reinforced, /turf/simulated/wall/rust, /turf/simulated/wall/r_wall/rust, /obj/structure/barricade/security)
+
+
/obj/structure/barricade/security
name = "security barrier"
desc = "A deployable barrier. Provides good cover in fire fights."
diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm
index ca12ad9a4a5..4bd343989b6 100644
--- a/code/game/machinery/suit_storage_unit.dm
+++ b/code/game/machinery/suit_storage_unit.dm
@@ -60,6 +60,10 @@
storage_type = /obj/item/weapon/watertank/atmos
/obj/machinery/suit_storage_unit/mining
+ suit_type = /obj/item/clothing/suit/hooded/explorer
+ mask_type = /obj/item/clothing/mask/gas
+
+/obj/machinery/suit_storage_unit/mining/eva
suit_type = /obj/item/clothing/suit/space/hardsuit/mining
mask_type = /obj/item/clothing/mask/breath
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index 145b97cc6fb..82bbe0c8c6f 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -789,7 +789,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
icon_state = "nutri"
icon_deny = "nutri-deny"
products = list(/obj/item/weapon/reagent_containers/glass/bottle/nutrient/ez = 30,/obj/item/weapon/reagent_containers/glass/bottle/nutrient/l4z = 20,/obj/item/weapon/reagent_containers/glass/bottle/nutrient/rh = 10,/obj/item/weapon/reagent_containers/spray/pestspray = 20,
- /obj/item/weapon/reagent_containers/syringe = 5,/obj/item/weapon/storage/bag/plants = 5,/obj/item/weapon/cultivator = 3,/obj/item/weapon/shovel/spade = 3,/obj/item/device/analyzer/plant_analyzer = 2)
+ /obj/item/weapon/reagent_containers/syringe = 5,/obj/item/weapon/storage/bag/plants = 5,/obj/item/weapon/cultivator = 3,/obj/item/weapon/shovel/spade = 3,/obj/item/device/analyzer/plant_analyzer = 4)
contraband = list(/obj/item/weapon/reagent_containers/glass/bottle/ammonia = 10,/obj/item/weapon/reagent_containers/glass/bottle/diethylamine = 5)
/obj/machinery/vending/hydroseeds
diff --git a/code/game/objects/explosion.dm b/code/game/objects/explosion.dm
index 2fc09eff02a..6ca8e7598e8 100644
--- a/code/game/objects/explosion.dm
+++ b/code/game/objects/explosion.dm
@@ -34,7 +34,7 @@
var/list/cached_exp_block = list()
if(adminlog)
- message_admins("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z])")
+ message_admins("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z] - JMP)")
log_game("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z])")
// Play sounds; we want sounds to be different depending on distance so we will manually do it ourselves.
diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm
index ee2caeae9bf..33760586938 100644
--- a/code/game/objects/items/devices/PDA/PDA.dm
+++ b/code/game/objects/items/devices/PDA/PDA.dm
@@ -268,8 +268,8 @@ var/global/list/obj/item/device/pda/PDAs = list()
if (total_moles)
for(var/id in env_gases)
var/gas_level = env_gases[id][MOLES]/total_moles
- if(id in hardcoded_gases || gas_level > 0.01)
- dat += "[env_gases[id][GAS_META][META_GAS_NAME]]: [round(gas_level*100)]%
"
+ if(id in hardcoded_gases || gas_level > 0.001)
+ dat += "[env_gases[id][GAS_META][META_GAS_NAME]]: [round(gas_level*100, 0.01)]%
"
dat += "Temperature: [round(environment.temperature-T0C)]°C
"
dat += "
"
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index 68052b14958..7099ecfa557 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -281,28 +281,30 @@ MASS SPECTROMETER
environment.garbage_collect()
if(abs(n2_concentration - N2STANDARD) < 20)
- user << "Nitrogen: [round(n2_concentration*100)] %"
+ user << "Nitrogen: [round(n2_concentration*100, 0.01)] %"
else
- user << "Nitrogen: [round(n2_concentration*100)] %"
+ user << "Nitrogen: [round(n2_concentration*100, 0.01)] %"
if(abs(o2_concentration - O2STANDARD) < 2)
- user << "Oxygen: [round(o2_concentration*100)] %"
+ user << "Oxygen: [round(o2_concentration*100, 0.01)] %"
else
- user << "Oxygen: [round(o2_concentration*100)] %"
+ user << "Oxygen: [round(o2_concentration*100, 0.01)] %"
if(co2_concentration > 0.01)
- user << "CO2: [round(co2_concentration*100)] %"
+ user << "CO2: [round(co2_concentration*100, 0.01)] %"
else
- user << "CO2: [round(co2_concentration*100)] %"
+ user << "CO2: [round(co2_concentration*100, 0.01)] %"
- if(plasma_concentration > 0.01)
- user << "Plasma: [round(plasma_concentration*100)] %"
+ if(plasma_concentration > 0.005)
+ user << "Plasma: [round(plasma_concentration*100, 0.01)] %"
+ else
+ user << "Plasma: [round(plasma_concentration*100, 0.01)] %"
for(var/id in env_gases)
if(id in hardcoded_gases)
continue
var/gas_concentration = env_gases[id][MOLES]/total_moles
- user << "[env_gases[id][GAS_META][META_GAS_NAME]]: [round(gas_concentration*100)] %"
+ user << "[env_gases[id][GAS_META][META_GAS_NAME]]: [round(gas_concentration*100, 0.01)] %"
user << "Temperature: [round(environment.temperature-T0C)] °C"
diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm
index 9c50d02b0f7..a674ccb0d69 100644
--- a/code/game/objects/items/robot/robot_items.dm
+++ b/code/game/objects/items/robot/robot_items.dm
@@ -174,6 +174,10 @@
sight_mode = BORGMESON
icon_state = "meson"
+/obj/item/borg/sight/material
+ name = "\proper material vision"
+ sight_mode = BORGMATERIAL
+ icon_state = "material"
/obj/item/borg/sight/hud
name = "hud"
diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm
index 79b45ba163f..9633c4562f6 100644
--- a/code/game/objects/items/stacks/sheets/mineral.dm
+++ b/code/game/objects/items/stacks/sheets/mineral.dm
@@ -2,6 +2,7 @@
Mineral Sheets
Contains:
- Sandstone
+ - Sandbags
- Diamond
- Snow
- Uranium
@@ -50,6 +51,32 @@ var/global/list/datum/stack_recipe/sandstone_recipes = list ( \
/obj/item/stack/sheet/mineral/sandstone/thirty
amount = 30
+/*
+ * Sandbags(
+ */
+
+/obj/item/stack/sheet/mineral/sandbags
+ name = "sandbags"
+ icon = 'icons/obj/items.dmi'
+ icon_state = "sandbag"
+ singular_name = "sandbag"
+ force = 5
+ throwforce = 5
+ w_class = 3
+ throw_speed = 1
+ throw_range = 3
+ origin_tech = "materials=2"
+
+var/global/list/datum/stack_recipe/sandbag_recipes = list ( \
+ new/datum/stack_recipe("sandbags", /obj/structure/barricade/sandbags, 1, time = 25, one_per_turf = 1, on_floor = 1), \
+ )
+
+/obj/item/stack/sheet/mineral/sandbags/New(var/loc, var/amount=null)
+ recipes = sandbag_recipes
+ pixel_x = rand(0,4)-4
+ pixel_y = rand(0,4)-4
+ ..()
+
/*
* Diamond
*/
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index d228525bb8a..7b965b354a7 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -57,6 +57,11 @@ var/global/list/datum/stack_recipe/metal_recipes = list ( \
flags = CONDUCT
origin_tech = "materials=1"
+/obj/item/stack/sheet/metal/narsie_act()
+ if(prob(20))
+ new /obj/item/stack/sheet/runed_metal(loc, amount)
+ qdel(src)
+
/obj/item/stack/sheet/metal/fifty
amount = 50
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index a79e334d6e8..f9285e22cc4 100755
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -864,17 +864,17 @@
M.put_in_hands(src)
usr << "You pick up the deck."
- else if(istype(over_object, /obj/screen))
- switch(over_object.name)
- if("l_hand")
- if(!remove_item_from_storage(M))
- M.unEquip(src)
- M.put_in_l_hand(src)
- else if("r_hand")
- if(!remove_item_from_storage(M))
- M.unEquip(src)
+ else if(istype(over_object, /obj/screen/inventory/hand))
+ var/obj/screen/inventory/hand/H = over_object
+ if(!remove_item_from_storage(M))
+ M.unEquip(src)
+ switch(H.slot_id)
+ if(slot_r_hand)
M.put_in_r_hand(src)
- usr << "You pick up the deck."
+ if(slot_l_hand)
+ M.put_in_l_hand(src)
+ usr << "You pick up the deck."
+
else
usr << "You can't reach it from here!"
diff --git a/code/game/objects/items/weapons/RPD.dm b/code/game/objects/items/weapons/RPD.dm
index b05d7795924..65cb7d6984b 100644
--- a/code/game/objects/items/weapons/RPD.dm
+++ b/code/game/objects/items/weapons/RPD.dm
@@ -125,9 +125,6 @@ var/global/list/RPD_recipes=list(
desc = "A device used to rapidly pipe things."
icon = 'icons/obj/items.dmi'
icon_state = "rpd"
- opacity = 0
- density = 0
- anchored = 0
flags = CONDUCT
force = 10
throwforce = 10
diff --git a/code/game/objects/items/weapons/defib.dm b/code/game/objects/items/weapons/defib.dm
index 082f1c4671e..41aba0f01c7 100644
--- a/code/game/objects/items/weapons/defib.dm
+++ b/code/game/objects/items/weapons/defib.dm
@@ -91,19 +91,22 @@
/obj/item/weapon/defibrillator/MouseDrop(obj/over_object)
if(ismob(src.loc))
var/mob/M = src.loc
- switch(over_object.name)
- if("r_hand")
- if(M.r_hand)
- return
- if(!M.unEquip(src))
- return
- M.put_in_r_hand(src)
- if("l_hand")
- if(M.l_hand)
- return
- if(!M.unEquip(src))
- return
- M.put_in_l_hand(src)
+ if(istype(over_object, /obj/screen/inventory/hand))
+ var/obj/screen/inventory/hand/H = over_object
+
+ switch(H.slot_id)
+ if(slot_r_hand)
+ if(M.r_hand)
+ return
+ if(!M.unEquip(src))
+ return
+ M.put_in_r_hand(src)
+ if(slot_l_hand)
+ if(M.l_hand)
+ return
+ if(!M.unEquip(src))
+ return
+ M.put_in_l_hand(src)
/obj/item/weapon/defibrillator/attackby(obj/item/weapon/W, mob/user, params)
if(W == paddles)
diff --git a/code/game/objects/items/weapons/handcuffs.dm b/code/game/objects/items/weapons/handcuffs.dm
index a526ea5644c..e3f44bc86ef 100644
--- a/code/game/objects/items/weapons/handcuffs.dm
+++ b/code/game/objects/items/weapons/handcuffs.dm
@@ -72,6 +72,7 @@
desc = "Looks like some cables tied together. Could be used to tie something up."
icon_state = "cuff_red"
item_state = "coil_red"
+ materials = list(MAT_METAL=150, MAT_GLASS=75)
breakouttime = 300 //Deciseconds = 30s
cuffsound = 'sound/weapons/cablecuff.ogg'
var/datum/robot_energy_storage/wirestorage = null
@@ -179,6 +180,7 @@
name = "zipties"
desc = "Plastic, disposable zipties that can be used to restrain temporarily but are destroyed after use."
icon_state = "cuff_white"
+ materials = list()
breakouttime = 450 //Deciseconds = 45s
trashtype = /obj/item/weapon/restraints/handcuffs/cable/zipties/used
diff --git a/code/game/objects/items/weapons/kitchen.dm b/code/game/objects/items/weapons/kitchen.dm
index 640a14dec73..942df998fa9 100644
--- a/code/game/objects/items/weapons/kitchen.dm
+++ b/code/game/objects/items/weapons/kitchen.dm
@@ -98,6 +98,12 @@
origin_tech = "materials=2;combat=4"
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "cut")
+
+/obj/item/weapon/kitchen/knife/combat/survival
+ name = "survival knife"
+ force = 15
+ throwforce = 15
+
/obj/item/weapon/kitchen/knife/combat/cyborg
name = "cyborg knife"
icon = 'icons/obj/items_cyborg.dmi'
diff --git a/code/game/objects/items/weapons/miscellaneous.dm b/code/game/objects/items/weapons/miscellaneous.dm
index dc9c0c9540c..1f8800565e2 100644
--- a/code/game/objects/items/weapons/miscellaneous.dm
+++ b/code/game/objects/items/weapons/miscellaneous.dm
@@ -17,4 +17,11 @@
icon = 'icons/obj/items.dmi'
icon_state = "skub"
w_class = 4
- attack_verb = list("skubbed")
\ No newline at end of file
+ attack_verb = list("skubbed")
+
+/obj/item/weapon/emptysandbag
+ name = "empty sandbag"
+ desc = "A bag to be filled with sand."
+ icon = 'icons/obj/items.dmi'
+ icon_state = "sandbag"
+ w_class = 1
diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm
index 302de997c59..13797e8d551 100644
--- a/code/game/objects/items/weapons/storage/boxes.dm
+++ b/code/game/objects/items/weapons/storage/boxes.dm
@@ -664,3 +664,123 @@
#undef SYNDI
#undef HEART
#undef SMILE
+
+/obj/item/weapon/storage/box/ingredients //This box is for the randomely chosen version the chef spawns with, it shouldn't actually exist.
+ name = "ingredients box"
+ icon_state = "donk_kit"
+ item_state = null
+
+/obj/item/weapon/storage/box/ingredients/wildcard
+ item_state = "wildcard"
+
+/obj/item/weapon/storage/box/ingredients/wildcard/New()
+ ..()
+ for(var/i in 1 to 6)
+ //Pick common ingredients
+ var/randomFood = pick(/obj/item/weapon/reagent_containers/food/snacks/grown/chili,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/tomato,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/carrot,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/potato,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/apple,
+ /obj/item/weapon/reagent_containers/food/snacks/chocolatebar,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/cherries,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/banana,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/cabbage,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/soybeans,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/ambrosia/vulgaris,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/corn)
+ new randomFood(src)
+ //Pick one random rare ingredient
+ var/randomRareFood = pick(/obj/item/weapon/reagent_containers/food/snacks/grown/ambrosia/deus,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/apple/gold,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/icepepper,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/ghost_chili,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/plumphelmet,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/chanterelle)
+ new randomRareFood(src)
+
+/obj/item/weapon/storage/box/ingredients/fiesta
+ item_state = "fiesta"
+
+/obj/item/weapon/storage/box/ingredients/fiesta/New()
+ ..()
+ for(var/i in 1 to 3)
+ new /obj/item/weapon/reagent_containers/food/snacks/tortilla(src)
+ for(var/i in 1 to 2)
+ new /obj/item/weapon/reagent_containers/food/snacks/grown/soybeans(src)
+ new /obj/item/weapon/reagent_containers/food/snacks/grown/chili(src)
+
+/obj/item/weapon/storage/box/ingredients/italian
+ item_state = "italian"
+
+/obj/item/weapon/storage/box/ingredients/italian/New()
+ ..()
+ for(var/i in 1 to 3)
+ new /obj/item/weapon/reagent_containers/food/snacks/grown/tomato(src)
+ new /obj/item/weapon/reagent_containers/food/snacks/grown/ambrosia/vulgaris(src)
+ new /obj/item/weapon/reagent_containers/food/snacks/faggot(src)
+
+/obj/item/weapon/storage/box/ingredients/vegetarian
+ item_state = "vegetarian"
+
+/obj/item/weapon/storage/box/ingredients/vegetarian/New()
+ ..()
+ for(var/i in 1 to 3)
+ new /obj/item/weapon/reagent_containers/food/snacks/grown/ambrosia/vulgaris(src)
+ new /obj/item/weapon/reagent_containers/food/snacks/grown/carrot(src)
+ new /obj/item/weapon/reagent_containers/food/snacks/grown/eggplant(src)
+ new /obj/item/weapon/reagent_containers/food/snacks/grown/potato(src)
+ new /obj/item/weapon/reagent_containers/food/snacks/grown/apple(src)
+
+/obj/item/weapon/storage/box/ingredients/sweets
+ item_state = "sweets"
+
+/obj/item/weapon/storage/box/ingredients/sweets/New()
+ ..()
+ for(var/i in 1 to 3)
+ new /obj/item/weapon/reagent_containers/food/snacks/chocolatebar(src)
+ new /obj/item/weapon/reagent_containers/food/condiment/sugar(src)
+ new /obj/item/weapon/reagent_containers/food/snacks/grown/cherries(src)
+ new /obj/item/weapon/reagent_containers/food/snacks/grown/banana(src)
+ new /obj/item/weapon/reagent_containers/food/snacks/icecream(src)
+
+/obj/item/weapon/storage/box/ingredients/carnivore
+ item_state = "carnivore"
+
+/obj/item/weapon/storage/box/ingredients/carnivore/New()
+ ..()
+ new /obj/item/weapon/reagent_containers/food/snacks/meat/slab/bear(src)
+ new /obj/item/weapon/reagent_containers/food/snacks/meat/slab/spider(src)
+ new /obj/item/weapon/reagent_containers/food/snacks/carpmeat(src)
+ new /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/slime(src)
+ new /obj/item/weapon/reagent_containers/food/snacks/faggot(src)
+ new /obj/item/weapon/reagent_containers/food/snacks/meat/slab/corgi(src)
+ new /obj/item/weapon/reagent_containers/food/snacks/meat/slab/monkey(src)
+
+/obj/item/weapon/storage/box/ingredients/exotic
+ item_state = "exotic"
+
+/obj/item/weapon/storage/box/ingredients/exotic/New()
+ ..()
+ new /obj/item/weapon/reagent_containers/food/condiment/soysauce(src)
+ for(var/i in 1 to 2)
+ new /obj/item/weapon/reagent_containers/food/snacks/grown/cabbage(src)
+ new /obj/item/weapon/reagent_containers/food/snacks/soydope(src)
+ new /obj/item/weapon/reagent_containers/food/snacks/carpmeat(src)
+
+/obj/item/weapon/storage/box/ingredients/New()
+ ..()
+ if(item_state)
+ desc = "A box containing supplementary ingredients for the aspiring chef. This box's theme is '[item_state]'."
+/obj/item/weapon/storage/box/emptysandbags
+ name = "box of empty sandbags"
+
+/obj/item/weapon/storage/box/emptysandbags/New()
+ ..()
+ new /obj/item/weapon/emptysandbag(src)
+ new /obj/item/weapon/emptysandbag(src)
+ new /obj/item/weapon/emptysandbag(src)
+ new /obj/item/weapon/emptysandbag(src)
+ new /obj/item/weapon/emptysandbag(src)
+ new /obj/item/weapon/emptysandbag(src)
+ new /obj/item/weapon/emptysandbag(src)
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/storage/firstaid.dm b/code/game/objects/items/weapons/storage/firstaid.dm
index 9183ffc92e5..054b4e426cc 100644
--- a/code/game/objects/items/weapons/storage/firstaid.dm
+++ b/code/game/objects/items/weapons/storage/firstaid.dm
@@ -138,13 +138,14 @@
var/mob/M = usr
if(!istype(over_object, /obj/screen) || !Adjacent(M))
return ..()
- if((!( M.restrained() ) && !( M.stat ) /*&& M.pocket == src*/))
- switch(over_object.name)
- if("r_hand")
- M.unEquip(src)
+ if(!M.restrained() && !M.stat && istype(over_object, /obj/screen/inventory/hand))
+ var/obj/screen/inventory/hand/H = over_object
+ if(!M.unEquip(src))
+ return
+ switch(H.slot_id)
+ if(slot_r_hand)
M.put_in_r_hand(src)
- if("l_hand")
- M.unEquip(src)
+ if(slot_l_hand)
M.put_in_l_hand(src)
src.add_fingerprint(usr)
return
@@ -163,7 +164,7 @@
..()
for(var/i in 1 to 7)
new /obj/item/weapon/reagent_containers/pill/patch/silver_sulf(src)
-
+
/obj/item/weapon/storage/pill_bottle/charcoal
name = "bottle of charcoal pills"
desc = "Contains pills used to counter toxins."
@@ -172,7 +173,7 @@
..()
for(var/i in 1 to 7)
new /obj/item/weapon/reagent_containers/pill/charcoal(src)
-
+
/obj/item/weapon/storage/pill_bottle/epinephrine
name = "bottle of epinephrine pills"
desc = "Contains pills used to stabilize patients."
@@ -181,7 +182,7 @@
..()
for(var/i in 1 to 7)
new /obj/item/weapon/reagent_containers/pill/epinephrine(src)
-
+
/obj/item/weapon/storage/pill_bottle/mutadone
name = "bottle of mutadone pills"
desc = "Contains pills used to treat genetic abnormalities."
@@ -190,7 +191,7 @@
..()
for(var/i in 1 to 7)
new /obj/item/weapon/reagent_containers/pill/mutadone(src)
-
+
/obj/item/weapon/storage/pill_bottle/mannitol
name = "bottle of mannitol pills"
desc = "Contains pills used to treat brain damage."
@@ -199,7 +200,7 @@
..()
for(var/i in 1 to 7)
new /obj/item/weapon/reagent_containers/pill/mannitol(src)
-
+
/obj/item/weapon/storage/pill_bottle/stimulant
name = "bottle of stimulant pills"
desc = "Guaranteed to give you that extra burst of energy during a long shift!"
diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm
index a031e2ad2de..9764781e8fc 100644
--- a/code/game/objects/items/weapons/storage/storage.dm
+++ b/code/game/objects/items/weapons/storage/storage.dm
@@ -51,15 +51,18 @@
return
playsound(loc, "rustle", 50, 1, -5)
- switch(over_object.name)
- if("r_hand")
- if(!M.unEquip(src))
- return
- M.put_in_r_hand(src)
- if("l_hand")
- if(!M.unEquip(src))
- return
- M.put_in_l_hand(src)
+
+
+ if(istype(over_object, /obj/screen/inventory/hand))
+ var/obj/screen/inventory/hand/H = over_object
+ if(!M.unEquip(src))
+ return
+ switch(H.slot_id)
+ if(slot_r_hand)
+ M.put_in_r_hand(src)
+ if(slot_l_hand)
+ M.put_in_l_hand(src)
+
add_fingerprint(usr)
//Check if this storage can dump the items
diff --git a/code/game/objects/items/weapons/tanks/watertank.dm b/code/game/objects/items/weapons/tanks/watertank.dm
index 7a6f50308d8..7652493137c 100644
--- a/code/game/objects/items/weapons/tanks/watertank.dm
+++ b/code/game/objects/items/weapons/tanks/watertank.dm
@@ -81,15 +81,16 @@
/obj/item/weapon/watertank/MouseDrop(obj/over_object)
var/mob/M = src.loc
- if(istype(M))
- switch(over_object.name)
- if("r_hand")
+ if(istype(M) && istype(over_object, /obj/screen/inventory/hand))
+ var/obj/screen/inventory/hand/H = over_object
+ switch(H.slot_id)
+ if(slot_r_hand)
if(M.r_hand)
return
if(!M.unEquip(src))
return
M.put_in_r_hand(src)
- if("l_hand")
+ if(slot_l_hand)
if(M.l_hand)
return
if(!M.unEquip(src))
diff --git a/code/game/objects/items/weapons/twohanded.dm b/code/game/objects/items/weapons/twohanded.dm
index 0e74735a4ee..acfe1e6cd77 100644
--- a/code/game/objects/items/weapons/twohanded.dm
+++ b/code/game/objects/items/weapons/twohanded.dm
@@ -307,6 +307,7 @@
throw_speed = 4
embedded_impact_pain_multiplier = 3
armour_penetration = 10
+ materials = list(MAT_METAL=1150, MAT_GLASS=2075)
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("attacked", "poked", "jabbed", "torn", "gored")
sharpness = IS_SHARP
diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm
index 483f1fc85fd..3d6a7c72441 100644
--- a/code/game/objects/items/weapons/weaponry.dm
+++ b/code/game/objects/items/weapons/weaponry.dm
@@ -85,7 +85,7 @@
force = 9
throwforce = 10
w_class = 3
- materials = list(MAT_METAL=1000)
+ materials = list(MAT_METAL=1150, MAT_GLASS=75)
attack_verb = list("hit", "bludgeoned", "whacked", "bonked")
/obj/item/weapon/wirerod/attackby(obj/item/I, mob/user, params)
diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm
index b50ae5e49a5..90b3cb2be9d 100644
--- a/code/game/objects/structures.dm
+++ b/code/game/objects/structures.dm
@@ -1,6 +1,9 @@
/obj/structure
icon = 'icons/obj/structures.dmi'
pressure_resistance = 8
+ var/climb_time = 20
+ var/climbable = FALSE
+ var/mob/structureclimber
/obj/structure/New()
..()
@@ -46,3 +49,66 @@
/obj/structure/proc/deconstruct(forced = FALSE)
qdel(src)
+
+
+/obj/structure/MouseDrop_T(atom/movable/O, mob/user)
+ . = ..()
+ if(!climbable)
+ return
+ if(ismob(O) && user == O && ishuman(user))
+ if(user.canmove)
+ climb_structure(user)
+ return
+ if ((!( istype(O, /obj/item/weapon) ) || user.get_active_hand() != O))
+ return
+ if(isrobot(user))
+ return
+ if(!user.drop_item())
+ return
+ if (O.loc != src.loc)
+ step(O, get_dir(O, src))
+ return
+
+/obj/structure/proc/climb_structure(mob/user)
+ src.add_fingerprint(user)
+ user.visible_message("[user] starts climbing onto [src].", \
+ "You start climbing onto [src]...")
+ var/climb_time = 20
+ if(user.restrained()) //climbing takes twice as long when restrained.
+ climb_time *= 2
+ structureclimber = user
+ if(do_mob(user, user, climb_time))
+ if(src.loc) //Checking if structure has been destroyed
+ density = 0
+ if(step(user,get_dir(user,src.loc)))
+ user.visible_message("[user] climbs onto [src].", \
+ "You climb onto [src].")
+ add_logs(user, src, "climbed onto")
+ user.Stun(2)
+ else
+ user << "You fail to climb onto [src]."
+ density = 1
+ structureclimber = null
+ return 1
+ structureclimber = null
+ return ..()
+
+
+/obj/structure/table/attack_hand(mob/living/user)
+ . = ..()
+
+ if(structureclimber && structureclimber != user)
+ user.changeNext_move(CLICK_CD_MELEE)
+ structureclimber.Weaken(2)
+ structureclimber.visible_message("[structureclimber.name] has been knocked off the [src]", "You're knocked off the [src]!", "You see [structureclimber.name] get knocked off the [src]")
+
+
+/obj/structure/CanPass(atom/movable/mover, turf/target, height=0)
+ if(height==0)
+ return 1
+ else
+ return !density
+
+
+obj/structure/CanAStarPass(ID,dir,caller)
+ . = !density
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm b/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm
index ef988ea7c35..49d82149ea1 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm
@@ -11,10 +11,8 @@
new /obj/item/device/radio/headset/headset_cargo(src)
new /obj/item/clothing/suit/fire/firefighter(src)
new /obj/item/clothing/gloves/fingerless(src)
- new /obj/item/weapon/mining_voucher(src)
new /obj/item/device/megaphone/cargo(src)
new /obj/item/weapon/tank/internals/emergency_oxygen(src)
new /obj/item/clothing/mask/gas(src)
- new /obj/item/clothing/glasses/meson(src)
new /obj/item/clothing/head/soft(src)
new /obj/item/weapon/door_remote/quartermaster(src)
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/misc.dm b/code/game/objects/structures/crates_lockers/closets/secure/misc.dm
index f75526e5790..0864e8a875f 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/misc.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/misc.dm
@@ -60,7 +60,8 @@
new /obj/item/stack/sheet/plasteel(src, 50)
new /obj/item/stack/sheet/metal(src, 50)
new /obj/item/stack/sheet/glass(src, 50)
+ new /obj/item/stack/sheet/mineral/sandbags(src, 30)
new /obj/item/clothing/shoes/magboots(src)
new /obj/item/weapon/storage/box/metalfoam(src)
- for(var/i in 1 to 3)
+ for(var/i in 1 to 3)
new /obj/item/weapon/rcd_ammo/large(src)
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
index 41d071db1ab..502024a7c7b 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
@@ -46,7 +46,6 @@
new /obj/item/clothing/suit/armor/vest(src)
new /obj/item/device/assembly/flash/handheld(src)
new /obj/item/clothing/glasses/sunglasses(src)
- new /obj/item/weapon/mining_voucher(src)
new /obj/item/weapon/restraints/handcuffs/cable/zipties(src)
new /obj/item/weapon/gun/energy/gun(src)
new /obj/item/clothing/tie/petcollar(src)
diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm
index e4ab72ab8ed..bc08d60b217 100644
--- a/code/game/objects/structures/girders.dm
+++ b/code/game/objects/structures/girders.dm
@@ -280,6 +280,11 @@
new remains(loc)
qdel(src)
+/obj/structure/girder/narsie_act()
+ if(prob(25))
+ new /obj/structure/girder/cult(loc)
+ qdel(src)
+
/obj/structure/girder/displaced
name = "displaced girder"
icon_state = "displaced"
@@ -376,9 +381,8 @@
else
..()
-/obj/structure/girder/cult/blob_act()
- if(prob(40))
- qdel(src)
+/obj/structure/girder/cult/narsie_act()
+ return
/obj/structure/girder/cult/ex_act(severity, target)
switch(severity)
diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm
index 205c6c34e34..59bc6451075 100644
--- a/code/game/objects/structures/grille.dm
+++ b/code/game/objects/structures/grille.dm
@@ -268,8 +268,15 @@
if(ismob(AM))
tforce = 5
else if(isobj(AM))
- var/obj/item/I = AM
- tforce = max(0, I.throwforce * 0.5)
+ if(prob(50))
+ var/obj/item/I = AM
+ tforce = max(0, I.throwforce * 0.5)
+ else if(anchored && !destroyed)
+ var/turf/T = get_turf(src)
+ var/obj/structure/cable/C = T.get_cable_node()
+ if(C)
+ playsound(src.loc, 'sound/magic/LightningShock.ogg', 100, 1, extrarange = 5)
+ tesla_zap(src, 3, C.powernet.avail * 0.08) //ZAP for 1/5000 of the amount of power, which is from 15-25 with 200000W
playsound(loc, 'sound/effects/grillehit.ogg', 80, 1)
health = max(0, health - tforce)
healthcheck()
diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm
index 42d016a54d7..6420894e4de 100644
--- a/code/game/objects/structures/tables_racks.dm
+++ b/code/game/objects/structures/tables_racks.dm
@@ -20,6 +20,7 @@
density = 1
anchored = 1
layer = 2.8
+ climbable = TRUE
pass_flags = LETPASSTHROW //You can throw objects over this, despite it's density.")
var/frame = /obj/structure/table_frame
var/framestack = /obj/item/stack/rods
@@ -27,7 +28,6 @@
var/busy = 0
var/buildstackamount = 1
var/framestackamount = 2
- var/mob/tableclimber
var/deconstructable = 1
smooth = SMOOTH_TRUE
canSmoothWith = list(/obj/structure/table, /obj/structure/table/reinforced)
@@ -94,20 +94,12 @@
table_destroy(1)
return 1
-/obj/structure/table/attack_hand(mob/living/user)
- . = ..()
- user.changeNext_move(CLICK_CD_MELEE)
- if(tableclimber && tableclimber != user)
- tableclimber.Weaken(2)
- tableclimber.visible_message("[tableclimber.name] has been knocked off the table", "You're knocked off the table!", "You see [tableclimber.name] get knocked off the table")
-
/obj/structure/table/attack_tk() // no telehulk sorry
return
/obj/structure/table/CanPass(atom/movable/mover, turf/target, height=0)
if(height==0)
return 1
-
if(istype(mover) && mover.checkpass(PASSTABLE))
return 1
if(locate(/obj/structure/table) in get_turf(mover))
@@ -121,22 +113,6 @@
var/atom/movable/mover = caller
. = . || mover.checkpass(PASSTABLE)
-/obj/structure/table/MouseDrop_T(atom/movable/O, mob/user)
- ..()
- if(ismob(O) && user == O && ishuman(user))
- if(user.canmove)
- climb_table(user)
- return
- if ((!( istype(O, /obj/item/weapon) ) || user.get_active_hand() != O))
- return
- if(isrobot(user))
- return
- if(!user.drop_item())
- return
- if (O.loc != src.loc)
- step(O, get_dir(O, src))
- return
-
/obj/structure/table/proc/tablepush(obj/item/I, mob/user)
if(get_dist(src, user) < 2)
var/obj/item/weapon/grab/G = I
@@ -261,36 +237,6 @@
qdel(src)
return
-/*
- * TABLE CLIMBING
- */
-
-
-/obj/structure/table/proc/climb_table(mob/user)
- src.add_fingerprint(user)
- user.visible_message("[user] starts climbing onto [src].", \
- "You start climbing onto [src]...")
- var/climb_time = 20
- if(user.restrained()) //Table climbing takes twice as long when restrained.
- climb_time *= 2
- tableclimber = user
- if(do_mob(user, user, climb_time))
- if(src.loc) //Checking if table has been destroyed
- density = 0
- if(step(user,get_dir(user,src.loc)))
- user.visible_message("[user] climbs onto [src].", \
- "You climb onto [src].")
- add_logs(user, src, "climbed onto")
- user.Stun(2)
- else
- user << "You fail to climb onto [src]."
- density = 1
- tableclimber = null
- return 1
- tableclimber = null
- return 0
-
-
/*
* Glass tables
*/
@@ -311,7 +257,7 @@
qdel(src)
-/obj/structure/table/glass/climb_table(mob/user)
+/obj/structure/table/glass/climb_structure(mob/user)
if(..())
visible_message("[src] breaks!")
playsound(src.loc, "shatter", 50, 1)
@@ -592,3 +538,4 @@
R.add_fingerprint(user)
qdel(src)
return
+
diff --git a/code/game/turfs/open.dm b/code/game/turfs/open.dm
index 89375d9e0e1..52f56e0cd52 100644
--- a/code/game/turfs/open.dm
+++ b/code/game/turfs/open.dm
@@ -19,7 +19,6 @@
/turf/open/handle_slip(mob/living/carbon/C, s_amount, w_amount, obj/O, lube)
if(has_gravity(src))
var/obj/buckled_obj
- var/oldlying = C.lying
if(C.buckled)
buckled_obj = C.buckled
if(!(lube&GALOSHES_DONT_HELP)) //can't slip while buckled unless it's lube.
@@ -50,9 +49,6 @@
spawn (i)
step(C, olddir)
C.spin(1,1)
- if(C.lying != oldlying && lube) //did we actually fall?
- var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg")
- C.apply_damage(5, BRUTE, dam_zone)
return 1
/turf/open/proc/MakeSlippery(wet_setting = TURF_WET_WATER) // 1 = Water, 2 = Lube, 3 = Ice
diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm
index c9d30731192..d145fa1b915 100644
--- a/code/game/turfs/space/space.dm
+++ b/code/game/turfs/space/space.dm
@@ -12,14 +12,21 @@
var/destination_y
var/global/datum/gas_mixture/space/space_gas = new
+ var/global/list/turf/open/space/space_turfs = list()
/turf/open/space/New()
update_icon()
air = space_gas
+ space_turfs += src
/turf/open/space/Destroy()
return QDEL_HINT_LETMELIVE
+/turf/open/space/ChangeTurf(path)
+ . = ..()
+ if(!istype(., /turf/open/space))
+ space_turfs -= src
+
/turf/open/space/proc/update_starlight()
if(config.starlight)
for(var/t in RANGE_TURFS(1,src)) //RANGE_TURFS is in code\__HELPERS\game.dm
diff --git a/code/modules/admin/verbs/modifyvariables.dm b/code/modules/admin/verbs/modifyvariables.dm
index b602d141ddc..308489beabe 100644
--- a/code/modules/admin/verbs/modifyvariables.dm
+++ b/code/modules/admin/verbs/modifyvariables.dm
@@ -33,10 +33,10 @@ var/list/VVckey_edit = list("key", "ckey")
var/class = "text"
if(src.holder && src.holder.marked_datum)
class = input("What kind of variable?","Variable Type") as null|anything in list("text",
- "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default","marked datum ([holder.marked_datum.type])")
+ "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default", "new atom", "new datum", "marked datum ([holder.marked_datum.type])")
else
class = input("What kind of variable?","Variable Type") as null|anything in list("text",
- "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default")
+ "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default", "new atom", "new datum")
if(!class)
return
@@ -72,6 +72,14 @@ var/list/VVckey_edit = list("key", "ckey")
if("marked datum")
var_value = holder.marked_datum
+ if("new atom")
+ var/type = input("Enter type:","Type") as null|anything in typesof(/obj,/mob,/area,/turf)
+ var_value = new type()
+
+ if("new datum")
+ var/type = input("Enter type:","Type") as null|anything in (typesof(/datum)-typesof(/obj,/mob,/area,/turf))
+ var_value = new type()
+
if(!var_value) return
if(istext(var_value))
@@ -90,10 +98,10 @@ var/list/VVckey_edit = list("key", "ckey")
var/class = "text"
if(src.holder && src.holder.marked_datum)
class = input("What kind of variable?","Variable Type") as null|anything in list("text",
- "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default","marked datum ([holder.marked_datum.type])")
+ "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default", "new atom", "new datum","marked datum ([holder.marked_datum.type])")
else
class = input("What kind of variable?","Variable Type") as null|anything in list("text",
- "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default")
+ "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default", "new atom", "new datum")
if(!class)
return
@@ -129,6 +137,14 @@ var/list/VVckey_edit = list("key", "ckey")
if("marked datum")
var_value = holder.marked_datum
+ if("new atom")
+ var/type = input("Enter type:","Type") as null|anything in typesof(/obj,/mob,/area,/turf)
+ var_value = new type()
+
+ if("new datum")
+ var/type = input("Enter type:","Type") as null|anything in (typesof(/datum)-typesof(/obj,/mob,/area,/turf))
+ var_value = new type()
+
if(!var_value) return
if(istext(var_value))
@@ -267,10 +283,10 @@ var/list/VVckey_edit = list("key", "ckey")
var/class = "text"
if(src.holder && src.holder.marked_datum)
class = input("What kind of variable?","Variable Type",default) as null|anything in list("text",
- "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default","marked datum ([holder.marked_datum.type])", "DELETE FROM LIST")
+ "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default", "new atom", "new datum","marked datum ([holder.marked_datum.type])", "DELETE FROM LIST")
else
class = input("What kind of variable?","Variable Type",default) as null|anything in list("text",
- "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default", "DELETE FROM LIST")
+ "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default", "new atom", "new datum", "DELETE FROM LIST")
if(!class)
return
@@ -372,6 +388,22 @@ var/list/VVckey_edit = list("key", "ckey")
else
L[L.Find(variable)] = new_var
+ if("new atom")
+ var/type = input("Enter type:","Type") as null|anything in typesof(/obj,/mob,/area,/turf)
+ new_var = new type()
+ if(assoc)
+ L[assoc_key] = new_var
+ else
+ L[L.Find(variable)] = new_var
+
+ if("new datum")
+ var/type = input("Enter type:","Type") as null|anything in (typesof(/datum)-typesof(/obj,/mob,/area,/turf))
+ new_var = new type()
+ if(assoc)
+ L[assoc_key] = new_var
+ else
+ L[L.Find(variable)] = new_var
+
O.on_varedit(objectvar)
world.log << "### ListVarEdit by [src]: [O.type] [objectvar]: [original_var]=[new_var]"
log_admin("[key_name(src)] modified [original_name]'s [objectvar]: [original_var]=[new_var]")
@@ -541,10 +573,10 @@ var/list/VVckey_edit = list("key", "ckey")
if(src.holder && src.holder.marked_datum)
class = input("What kind of variable?","Variable Type",default) as null|anything in list("text",
- "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default","marked datum ([holder.marked_datum.type])")
+ "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default", "new atom", "new datum", "marked datum ([holder.marked_datum.type])")
else
class = input("What kind of variable?","Variable Type",default) as null|anything in list("text",
- "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default")
+ "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default", "new atom", "new datum")
if(!class)
return
@@ -638,6 +670,18 @@ var/list/VVckey_edit = list("key", "ckey")
if("marked datum")
O.vars[variable] = holder.marked_datum
+ if("new atom")
+ var/type = input("Enter type:","Type") as null|anything in typesof(/obj,/mob,/area,/turf)
+ var/var_new = new type()
+ if(var_new==null) return
+ O.vars[variable] = var_new
+
+ if("new datum")
+ var/type = input("Enter type:","Type") as null|anything in (typesof(/datum)-typesof(/obj,/mob,/area,/turf))
+ var/var_new = new type()
+ if(var_new==null) return
+ O.vars[variable] = var_new
+
O.on_varedit(variable)
world.log << "### VarEdit by [src]: [O.type] [variable]=[html_encode("[O.vars[variable]]")]"
log_admin("[key_name(src)] modified [original_name]'s [variable] to [O.vars[variable]]")
diff --git a/code/modules/admin/verbs/playsound.dm b/code/modules/admin/verbs/playsound.dm
index 167f1bd4861..f2166945d65 100644
--- a/code/modules/admin/verbs/playsound.dm
+++ b/code/modules/admin/verbs/playsound.dm
@@ -7,8 +7,13 @@ var/sound/admin_sound
if(!check_rights(R_SOUNDS))
return
- admin_sound = sound(S, repeat = 0, wait = 1, channel = SOUND_CHANNEL_ADMIN)
+
+ var/sound/admin_sound = new()
+ admin_sound.file = S
admin_sound.priority = 250
+ admin_sound.channel = SOUND_CHANNEL_ADMIN
+ admin_sound.wait = 1
+ admin_sound.repeat = 0
admin_sound.status = SOUND_UPDATE|SOUND_STREAM
log_admin("[key_name(src)] played sound [S]")
@@ -20,7 +25,8 @@ var/sound/admin_sound
for(var/mob/M in player_list)
if(M.client.prefs.toggles & SOUND_MIDI)
- M << admin_sound
+ var/vol = M.client.prefs.adminmusicvolume
+ M << sound(admin_sound,channel = SOUND_CHANNEL_ADMIN,volume=vol)
admin_sound.frequency = 1 //Remove this line when the AFD stuff above is gone
admin_sound.wait = 0
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 52fece2c3e8..7ffb0c72eb0 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -62,7 +62,7 @@ var/list/preferences_datums = list()
var/list/features = list("mcolor" = "FFF", "tail_lizard" = "Smooth", "tail_human" = "None", "snout" = "Round", "horns" = "None", "ears" = "None", "frills" = "None", "spines" = "None", "body_markings" = "None")
var/list/custom_names = list("clown", "mime", "ai", "cyborg", "religion", "deity")
-
+ var/adminmusicvolume = 50
//Mob preview
var/icon/preview_icon = null
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index 1ebfd9ecf5b..b988dd25e1e 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -223,6 +223,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["preferred_map"] >> preferred_map
S["ignoring"] >> ignoring
S["ghost_hud"] >> ghost_hud
+ S["adminmusicvolume"] >> adminmusicvolume
S["inquisitive_ghost"] >> inquisitive_ghost
//try to fix any outdated data if necessary
@@ -274,6 +275,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["preferred_map"] << preferred_map
S["ignoring"] << ignoring
S["ghost_hud"] << ghost_hud
+ S["adminmusicvolume"] << adminmusicvolume
S["inquisitive_ghost"] << inquisitive_ghost
return 1
diff --git a/code/modules/client/preferences_toggles.dm b/code/modules/client/preferences_toggles.dm
index ddc8dda4dda..8e8e856b4ae 100644
--- a/code/modules/client/preferences_toggles.dm
+++ b/code/modules/client/preferences_toggles.dm
@@ -333,3 +333,12 @@ var/global/list/ghost_orbits = list(GHOST_ORBIT_CIRCLE,GHOST_ORBIT_TRIANGLE,GHOS
src << "You will now [(prefs.toggles & SOUND_ANNOUNCEMENTS) ? "no longer hear announcements" : "hear announcement sounds"]."
prefs.save_preferences()
feedback_add_details("admin_verb","TAS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+
+/client/verb/set_admin_volume()
+ set name = "Set Admin Music Volume"
+ set category = "Preferences"
+ set desc = "Set the volume you hear admin music at."
+ var/musinput = input("Range of 0 to 100.","Admin Music Volume", prefs.adminmusicvolume) as num
+ prefs.adminmusicvolume = max(0,min(musinput,100))
+ prefs.save_preferences()
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index 2315d1e53f8..d808eef5e0f 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -178,7 +178,7 @@ BLIND // can't see anything
var/list/bloody_shoes = list(BLOOD_STATE_HUMAN = 0,BLOOD_STATE_XENO = 0, BLOOD_STATE_OIL = 0, BLOOD_STATE_NOT_BLOODY = 0)
var/can_hold_items = 0//if set to 1, the shoe can hold knives and edaggers
var/obj/held_item
- var/list/valid_held_items = list(/obj/item/weapon/kitchen/knife, /obj/item/weapon/pen, /obj/item/weapon/switchblade)//can hold both regular pens and energy daggers. made for your every-day tactical librarians/murderers.
+ var/list/valid_held_items = list(/obj/item/weapon/kitchen/knife, /obj/item/weapon/pen, /obj/item/weapon/switchblade, /obj/item/weapon/scalpel, /obj/item/weapon/reagent_containers/syringe, /obj/item/weapon/dnainjector)//can hold both regular pens and energy daggers. made for your every-day tactical librarians/murderers.
/obj/item/clothing/shoes/worn_overlays(var/isinhands = FALSE)
diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm
index df0f18f5405..b9f54abd510 100644
--- a/code/modules/clothing/glasses/glasses.dm
+++ b/code/modules/clothing/glasses/glasses.dm
@@ -84,7 +84,26 @@
item_state = "glasses"
origin_tech = "magnets=3;engineering=3"
vision_flags = SEE_OBJS
- invis_view = SEE_INVISIBLE_MINIMUM
+
+/obj/item/clothing/glasses/material/mining
+ name = "Optical Material Scanner"
+ desc = "Used by miners to detect ores deep within the rock."
+ icon_state = "material"
+ item_state = "glasses"
+ origin_tech = "magnets=3;engineering=3"
+ darkness_view = 0
+
+/obj/item/clothing/glasses/material/mining/gar
+ name = "gar material scanner"
+ icon_state = "garm"
+ item_state = "garm"
+ desc = "Do the impossible, see the invisible!"
+ force = 10
+ throwforce = 20
+ throw_speed = 4
+ attack_verb = list("sliced")
+ hitsound = 'sound/weapons/bladeslice.ogg'
+ sharpness = IS_SHARP
/obj/item/clothing/glasses/regular
name = "Prescription Glasses"
diff --git a/code/modules/clothing/suits/cloaks.dm b/code/modules/clothing/suits/cloaks.dm
index 0b9756b5bf5..f74ff4feb36 100644
--- a/code/modules/clothing/suits/cloaks.dm
+++ b/code/modules/clothing/suits/cloaks.dm
@@ -17,6 +17,7 @@
name = "head of security's cloak"
desc = "Worn by Securistan, ruling the station with an iron fist. It's slightly armored."
icon_state = "hoscloak"
+ allowed = list(/obj/item/weapon/gun/energy/gun/hos)
armor = list(melee = 30, bullet = 30, laser = 10, energy = 10, bomb = 25, bio = 0, rad = 0)
/obj/item/clothing/suit/cloak/qm
@@ -27,24 +28,28 @@
name = "chief medical officer's cloak"
desc = "Worn by Meditopia, the valiant men and women keeping pestilence at bay. It's slightly shielded from contaminants."
icon_state = "cmocloak"
+ allowed = list(/obj/item/weapon/reagent_containers/hypospray/CMO)
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 25, rad = 0)
/obj/item/clothing/suit/cloak/ce
name = "chief engineer's cloak"
desc = "Worn by Engitopia, wielders of an unlimited power. It's slightly shielded against radiation."
icon_state = "cecloak"
+ allowed = list(/obj/item/weapon/rcd, /obj/item/weapon/pipe_dispenser)
armor = list(melee = 10, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 10)
/obj/item/clothing/suit/cloak/rd
name = "research director's cloak."
desc = "Worn by Sciencia, thaumaturges and researchers of the universe. It's slightly shielded from contaminants."
icon_state = "rdcloak"
+ allowed = list(/obj/item/weapon/hand_tele, /obj/item/weapon/storage/part_replacer)
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 10, bio = 10, rad = 0)
/obj/item/clothing/suit/cloak/cap
name = "captain's cloak"
desc = "Worn by the commander of Space Station 13."
icon_state = "capcloak"
+ allowed = list(/obj/item/weapon/gun/energy/laser/captain)
armor = list(melee = 30, bullet = 30, laser = 30, energy = 10, bomb = 25, bio = 10, rad = 10)
/* //wip
diff --git a/code/modules/clothing/under/jobs/civilian.dm b/code/modules/clothing/under/jobs/civilian.dm
index 25a2027e4c7..2e360b3f31c 100644
--- a/code/modules/clothing/under/jobs/civilian.dm
+++ b/code/modules/clothing/under/jobs/civilian.dm
@@ -171,4 +171,12 @@
name = "shaft miner's jumpsuit"
icon_state = "miner"
item_state = "miner"
- item_color = "miner"
\ No newline at end of file
+ item_color = "miner"
+
+
+/obj/item/clothing/under/rank/miner/lavaland
+ desc = "A black jumpsuit for operating in hazardous environments."
+ name = "shaft miner's jumpsuit"
+ icon_state = "syndicate"
+ item_state = "bl_suit"
+ item_color = "syndicate"
diff --git a/code/modules/crafting/recipes.dm b/code/modules/crafting/recipes.dm
index 07caf9ce90c..cccf994d590 100644
--- a/code/modules/crafting/recipes.dm
+++ b/code/modules/crafting/recipes.dm
@@ -172,6 +172,14 @@
time = 10
category = CAT_WEAPON
+/datum/table_recipe/sandbags
+ name = "Sandbags"
+ result = /obj/item/stack/sheet/mineral/sandbags
+ reqs = list(/obj/item/weapon/ore/glass = 5,
+ /obj/item/weapon/emptysandbag = 1)
+ time = 10
+ category = CAT_WEAPON
+
/datum/table_recipe/meteorshot
name = "Meteorshot Shell"
result = /obj/item/ammo_casing/shotgun/meteorshot
diff --git a/code/modules/events/event.dm b/code/modules/events/_event.dm
similarity index 76%
rename from code/modules/events/event.dm
rename to code/modules/events/_event.dm
index 722f6556868..2a10c13bfbf 100644
--- a/code/modules/events/event.dm
+++ b/code/modules/events/_event.dm
@@ -1,127 +1,153 @@
-//this datum is used by the events controller to dictate how it selects events
-/datum/round_event_control
- var/name //The name human-readable name of the event
- var/typepath //The typepath of the event datum /datum/round_event
-
- var/weight = 10 //The weight this event has in the random-selection process.
- //Higher weights are more likely to be picked.
- //10 is the default weight. 20 is twice more likely; 5 is half as likely as this default.
-
- var/earliest_start = 12000 //The earliest world.time that an event can start (round-duration in deciseconds) default: 20 mins
-
- var/occurrences = 0 //How many times this event has occured
- var/max_occurrences = 20 //The maximum number of times this event can occur (naturally), it can still be forced.
- //By setting this to 0 you can effectively disable an event.
-
- var/holidayID = "" //string which should be in the SSevents.holidays list if you wish this event to be holiday-specific
- //anything with a (non-null) holidayID which does not match holiday, cannot run.
- var/wizardevent = 0
-
- var/alertadmins = 1 //should we let the admins know this event is firing
- //should be disabled on events that fire a lot
-
- var/list/gamemode_blacklist = list() // Event won't happen in these gamemodes
- var/list/gamemode_whitelist = list() // Event will happen ONLY in these gamemodes if not empty
-
-/datum/round_event_control/wizard
- wizardevent = 1
-
-/datum/round_event_control/proc/runEvent()
- if(!ispath(typepath,/datum/round_event))
- return PROCESS_KILL
- var/datum/round_event/E = new typepath()
- E.control = src
- feedback_add_details("event_ran","[E]")
- occurrences++
-
- testing("[time2text(world.time, "hh:mm:ss")] [E.type]")
-
- return E
-
-/datum/round_event //NOTE: Times are measured in master controller ticks!
- var/processing = 1
- var/datum/round_event_control/control
-
- var/startWhen = 0 //When in the lifetime to call start().
- var/announceWhen = 0 //When in the lifetime to call announce(). Set an event's announceWhen to >0 if there is an announcement.
- var/endWhen = 0 //When in the lifetime the event should end.
-
- var/activeFor = 0 //How long the event has existed. You don't need to change this.
-
-//Called first before processing.
-//Allows you to setup your event, such as randomly
-//setting the startWhen and or announceWhen variables.
-//Only called once.
-//EDIT: if there's anything you want to override within the new() call, it will not be overridden by the time this proc is called.
-//It will only have been overridden by the time we get to announce() start() tick() or end() (anything but setup basically).
-//This is really only for setting defaults which can be overridden later when New() finishes.
-/datum/round_event/proc/setup()
- return
-
-//Called when the tick is equal to the startWhen variable.
-//Allows you to start before announcing or vice versa.
-//Only called once.
-/datum/round_event/proc/start()
- return
-
-//Called when the tick is equal to the announceWhen variable.
-//Allows you to announce before starting or vice versa.
-//Only called once.
-/datum/round_event/proc/announce()
- return
-
-//Called on or after the tick counter is equal to startWhen.
-//You can include code related to your event or add your own
-//time stamped events.
-//Called more than once.
-/datum/round_event/proc/tick()
- return
-
-//Called on or after the tick is equal or more than endWhen
-//You can include code related to the event ending.
-//Do not place spawn() in here, instead use tick() to check for
-//the activeFor variable.
-//For example: if(activeFor == myOwnVariable + 30) doStuff()
-//Only called once.
-/datum/round_event/proc/end()
- return
-
-
-
-//Do not override this proc, instead use the appropiate procs.
-//This proc will handle the calls to the appropiate procs.
-/datum/round_event/process()
- if(!processing)
- return
-
- if(activeFor == startWhen)
- start()
-
- if(activeFor == announceWhen)
- announce()
-
- if(startWhen < activeFor && activeFor < endWhen)
- tick()
-
- if(activeFor == endWhen)
- end()
-
- // Everything is done, let's clean up.
- if(activeFor >= endWhen && activeFor >= announceWhen && activeFor >= startWhen)
- kill()
-
- activeFor++
-
-
-//Garbage collects the event by removing it from the global events list,
-//which should be the only place it's referenced.
-//Called when start(), announce() and end() has all been called.
-/datum/round_event/proc/kill()
- SSevent.running -= src
-
-
-//Sets up the event then adds the event to the the list of running events
-/datum/round_event/New()
- setup()
- SSevent.running += src
+//this datum is used by the events controller to dictate how it selects events
+/datum/round_event_control
+ var/name //The human-readable name of the event
+ var/typepath //The typepath of the event datum /datum/round_event
+
+ var/weight = 10 //The weight this event has in the random-selection process.
+ //Higher weights are more likely to be picked.
+ //10 is the default weight. 20 is twice more likely; 5 is half as likely as this default.
+
+ var/earliest_start = 12000 //The earliest world.time that an event can start (round-duration in deciseconds) default: 20 mins
+ var/min_players = 0 //The minimum amount of alive, non-AFK human players on server required to start the event.
+
+ var/occurrences = 0 //How many times this event has occured
+ var/max_occurrences = 20 //The maximum number of times this event can occur (naturally), it can still be forced.
+ //By setting this to 0 you can effectively disable an event.
+
+ var/holidayID = "" //string which should be in the SSevents.holidays list if you wish this event to be holiday-specific
+ //anything with a (non-null) holidayID which does not match holiday, cannot run.
+ var/wizardevent = 0
+
+ var/alertadmins = 1 //should we let the admins know this event is firing
+ //should be disabled on events that fire a lot
+
+ var/list/gamemode_blacklist = list() // Event won't happen in these gamemodes
+ var/list/gamemode_whitelist = list() // Event will happen ONLY in these gamemodes if not empty
+
+/datum/round_event_control/New()
+ ..()
+ if(config && !wizardevent) // Magic is unaffected by configs
+ earliest_start = Ceiling(earliest_start * config.events_min_time_mul)
+ min_players = Ceiling(min_players * config.events_min_players_mul)
+
+/datum/round_event_control/wizard
+ wizardevent = 1
+
+// Checks if the event can be spawned. Used by event controller and "false alarm" event.
+// Admin-created events override this.
+/datum/round_event_control/proc/canSpawnEvent(var/players_amt, var/gamemode)
+ if(occurrences >= max_occurrences)
+ return FALSE
+ if(earliest_start >= world.time)
+ return FALSE
+ if(players_amt < min_players)
+ return FALSE
+ if(gamemode_blacklist.len && (gamemode in gamemode_blacklist))
+ return FALSE
+ if(gamemode_whitelist.len && !(gamemode in gamemode_whitelist))
+ return FALSE
+ if(holidayID && (!SSevent.holidays || !SSevent.holidays[holidayID]))
+ return FALSE
+ return TRUE
+
+/datum/round_event_control/proc/runEvent()
+ if(!ispath(typepath,/datum/round_event))
+ return PROCESS_KILL
+ var/datum/round_event/E = new typepath()
+ E.current_players = get_active_player_count(alive_check = 1, afk_check = 1, human_check = 1)
+ E.control = src
+ feedback_add_details("event_ran","[E]")
+ occurrences++
+
+ testing("[time2text(world.time, "hh:mm:ss")] [E.type]")
+
+ return E
+
+/datum/round_event //NOTE: Times are measured in master controller ticks!
+ var/processing = 1
+ var/datum/round_event_control/control
+
+ var/startWhen = 0 //When in the lifetime to call start().
+ var/announceWhen = 0 //When in the lifetime to call announce(). Set an event's announceWhen to >0 if there is an announcement.
+ var/endWhen = 0 //When in the lifetime the event should end.
+
+ var/activeFor = 0 //How long the event has existed. You don't need to change this.
+ var/current_players = 0 //Amount of of alive, non-AFK human players on server at the time of event start
+
+//Called first before processing.
+//Allows you to setup your event, such as randomly
+//setting the startWhen and or announceWhen variables.
+//Only called once.
+//EDIT: if there's anything you want to override within the new() call, it will not be overridden by the time this proc is called.
+//It will only have been overridden by the time we get to announce() start() tick() or end() (anything but setup basically).
+//This is really only for setting defaults which can be overridden later when New() finishes.
+/datum/round_event/proc/setup()
+ return
+
+//Called when the tick is equal to the startWhen variable.
+//Allows you to start before announcing or vice versa.
+//Only called once.
+/datum/round_event/proc/start()
+ return
+
+//Called when the tick is equal to the announceWhen variable.
+//Allows you to announce before starting or vice versa.
+//Only called once.
+/datum/round_event/proc/announce()
+ return
+
+//Called on or after the tick counter is equal to startWhen.
+//You can include code related to your event or add your own
+//time stamped events.
+//Called more than once.
+/datum/round_event/proc/tick()
+ return
+
+//Called on or after the tick is equal or more than endWhen
+//You can include code related to the event ending.
+//Do not place spawn() in here, instead use tick() to check for
+//the activeFor variable.
+//For example: if(activeFor == myOwnVariable + 30) doStuff()
+//Only called once.
+/datum/round_event/proc/end()
+ return
+
+
+
+//Do not override this proc, instead use the appropiate procs.
+//This proc will handle the calls to the appropiate procs.
+/datum/round_event/process()
+ if(!processing)
+ return
+
+ if(activeFor == startWhen)
+ start()
+
+ if(activeFor == announceWhen)
+ announce()
+
+ if(startWhen < activeFor && activeFor < endWhen)
+ tick()
+
+ if(activeFor == endWhen)
+ end()
+
+ // Everything is done, let's clean up.
+ if(activeFor >= endWhen && activeFor >= announceWhen && activeFor >= startWhen)
+ kill()
+
+ activeFor++
+
+
+//Garbage collects the event by removing it from the global events list,
+//which should be the only place it's referenced.
+//Called when start(), announce() and end() has all been called.
+/datum/round_event/proc/kill()
+ SSevent.running -= src
+
+
+//Sets up the event then adds the event to the the list of running events
+/datum/round_event/New()
+ setup()
+ SSevent.running += src
return ..()
\ No newline at end of file
diff --git a/code/modules/events/abductor.dm b/code/modules/events/abductor.dm
index 3eaf7e3c0c7..65ec0a7aae2 100644
--- a/code/modules/events/abductor.dm
+++ b/code/modules/events/abductor.dm
@@ -4,6 +4,7 @@
weight = 5
max_occurrences = 1
+ min_players = 5
earliest_start = 18000 // 30 min
gamemode_blacklist = list("nuclear","wizard","revolution","abduction")
diff --git a/code/modules/events/alien_infestation.dm b/code/modules/events/alien_infestation.dm
index b57118957f1..0082e3d62fa 100644
--- a/code/modules/events/alien_infestation.dm
+++ b/code/modules/events/alien_infestation.dm
@@ -2,6 +2,8 @@
name = "Alien Infestation"
typepath = /datum/round_event/alien_infestation
weight = 5
+
+ min_players = 10
max_occurrences = 1
/datum/round_event/alien_infestation
diff --git a/code/modules/events/anomaly.dm b/code/modules/events/anomaly.dm
index 547618e63de..0b98ee4ec7f 100644
--- a/code/modules/events/anomaly.dm
+++ b/code/modules/events/anomaly.dm
@@ -1,6 +1,8 @@
/datum/round_event_control/anomaly
name = "Anomaly: Energetic Flux"
typepath = /datum/round_event/anomaly
+
+ min_players = 1
max_occurrences = 0 //This one probably shouldn't occur! It'd work, but it wouldn't be very fun.
weight = 15
diff --git a/code/modules/events/anomaly_flux.dm b/code/modules/events/anomaly_flux.dm
index 7d8da5021df..10fdb119ff2 100644
--- a/code/modules/events/anomaly_flux.dm
+++ b/code/modules/events/anomaly_flux.dm
@@ -1,6 +1,8 @@
/datum/round_event_control/anomaly/anomaly_flux
name = "Anomaly: Hyper-Energetic Flux"
typepath = /datum/round_event/anomaly/anomaly_flux
+
+ min_players = 10
max_occurrences = 5
weight = 20
diff --git a/code/modules/events/anomaly_vortex.dm b/code/modules/events/anomaly_vortex.dm
index 72684b1a8bd..9d7b40cf6e1 100644
--- a/code/modules/events/anomaly_vortex.dm
+++ b/code/modules/events/anomaly_vortex.dm
@@ -1,6 +1,8 @@
/datum/round_event_control/anomaly/anomaly_vortex
name = "Anomaly: Vortex"
typepath = /datum/round_event/anomaly/anomaly_vortex
+
+ min_players = 20
max_occurrences = 2
weight = 5
diff --git a/code/modules/events/blob.dm b/code/modules/events/blob.dm
index 343c4bd5758..ab361a56b39 100644
--- a/code/modules/events/blob.dm
+++ b/code/modules/events/blob.dm
@@ -4,6 +4,7 @@
weight = 5
max_occurrences = 1
+ min_players = 20
earliest_start = 18000 //30 minutes
gamemode_blacklist = list("blob") //Just in case a blob survives that long
diff --git a/code/modules/events/brand_intelligence.dm b/code/modules/events/brand_intelligence.dm
index 7edf5a9f482..5a4fbcd9c5d 100644
--- a/code/modules/events/brand_intelligence.dm
+++ b/code/modules/events/brand_intelligence.dm
@@ -2,6 +2,8 @@
name = "Brand Intelligence"
typepath = /datum/round_event/brand_intelligence
weight = 5
+
+ min_players = 15
max_occurrences = 1
/datum/round_event/brand_intelligence
diff --git a/code/modules/events/carp_migration.dm b/code/modules/events/carp_migration.dm
index 0b65480c830..a7af3fe9a31 100644
--- a/code/modules/events/carp_migration.dm
+++ b/code/modules/events/carp_migration.dm
@@ -2,6 +2,7 @@
name = "Carp Migration"
typepath = /datum/round_event/carp_migration
weight = 15
+ min_players = 2
earliest_start = 6000
max_occurrences = 6
diff --git a/code/modules/events/disease_outbreak.dm b/code/modules/events/disease_outbreak.dm
index bf704135455..d19c54d5080 100644
--- a/code/modules/events/disease_outbreak.dm
+++ b/code/modules/events/disease_outbreak.dm
@@ -2,6 +2,7 @@
name = "Disease Outbreak"
typepath = /datum/round_event/disease_outbreak
max_occurrences = 1
+ min_players = 10
weight = 5
/datum/round_event/disease_outbreak
diff --git a/code/modules/events/electrical_storm.dm b/code/modules/events/electrical_storm.dm
index 302586925c5..1568e409207 100644
--- a/code/modules/events/electrical_storm.dm
+++ b/code/modules/events/electrical_storm.dm
@@ -2,6 +2,7 @@
name = "Electrical Storm"
typepath = /datum/round_event/electrical_storm
earliest_start = 6000
+ min_players = 5
weight = 40
alertadmins = 0
diff --git a/code/modules/events/false_alarm.dm b/code/modules/events/false_alarm.dm
index 1379d44d3e9..e34c532dad0 100644
--- a/code/modules/events/false_alarm.dm
+++ b/code/modules/events/false_alarm.dm
@@ -10,11 +10,14 @@
/datum/round_event/falsealarm/announce()
var/list/events_list = list()
+
+ var/players_amt = get_active_player_count(alive_check = 1, afk_check = 1, human_check = 1)
+ var/gamemode = ticker.mode.config_tag
+
for(var/datum/round_event_control/E in SSevent.control)
- if(E.holidayID || E.wizardevent)
- continue
- if(E.earliest_start >= world.time)
+ if(!E.canSpawnEvent(players_amt, gamemode))
continue
+
var/datum/round_event/event = E.typepath
if(initial(event.announceWhen) <= 0)
continue
diff --git a/code/modules/events/immovable_rod.dm b/code/modules/events/immovable_rod.dm
index 4ff5bd2519b..79199bc33a0 100644
--- a/code/modules/events/immovable_rod.dm
+++ b/code/modules/events/immovable_rod.dm
@@ -10,6 +10,7 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
/datum/round_event_control/immovable_rod
name = "Immovable Rod"
typepath = /datum/round_event/immovable_rod
+ min_players = 15
max_occurrences = 5
/datum/round_event/immovable_rod
diff --git a/code/modules/events/ion_storm.dm b/code/modules/events/ion_storm.dm
index 177ee3dece6..b2e140ac548 100644
--- a/code/modules/events/ion_storm.dm
+++ b/code/modules/events/ion_storm.dm
@@ -5,6 +5,7 @@
name = "Ion Storm"
typepath = /datum/round_event/ion_storm
weight = 15
+ min_players = 2
/datum/round_event/ion_storm
var/botEmagChance = 10
diff --git a/code/modules/events/mass_hallucination.dm b/code/modules/events/mass_hallucination.dm
index 17888250c20..1705598c36e 100644
--- a/code/modules/events/mass_hallucination.dm
+++ b/code/modules/events/mass_hallucination.dm
@@ -3,6 +3,7 @@
typepath = /datum/round_event/mass_hallucination
weight = 7
max_occurrences = 2
+ min_players = 1
/datum/round_event/mass_hallucination/start()
for(var/mob/living/carbon/C in living_mob_list)
diff --git a/code/modules/events/meteor_wave.dm b/code/modules/events/meteor_wave.dm
index 9a48f2ccca6..b670df5bdf2 100644
--- a/code/modules/events/meteor_wave.dm
+++ b/code/modules/events/meteor_wave.dm
@@ -2,6 +2,7 @@
name = "Meteor Wave"
typepath = /datum/round_event/meteor_wave
weight = 5
+ min_players = 5
max_occurrences = 3
/datum/round_event/meteor_wave
diff --git a/code/modules/events/portal_storm.dm b/code/modules/events/portal_storm.dm
index e9152f15168..fb4f68e7fba 100644
--- a/code/modules/events/portal_storm.dm
+++ b/code/modules/events/portal_storm.dm
@@ -2,6 +2,7 @@
name = "Portal Storm: Syndicate Shocktroops"
typepath = /datum/round_event/portal_storm/syndicate_shocktroop
weight = 2
+ min_players = 15
earliest_start = 18000
/datum/round_event/portal_storm/syndicate_shocktroop
diff --git a/code/modules/events/prison_break.dm b/code/modules/events/prison_break.dm
index f81e7f47cc4..f4d1ae65437 100644
--- a/code/modules/events/prison_break.dm
+++ b/code/modules/events/prison_break.dm
@@ -2,6 +2,7 @@
name = "Prison Break"
typepath = /datum/round_event/prison_break
max_occurrences = 2
+ min_players = 5
/datum/round_event/prison_break
announceWhen = 50
diff --git a/code/modules/events/spacevine.dm b/code/modules/events/spacevine.dm
index a2382d717f3..3b34c7a89dc 100644
--- a/code/modules/events/spacevine.dm
+++ b/code/modules/events/spacevine.dm
@@ -3,6 +3,7 @@
typepath = /datum/round_event/spacevine
weight = 15
max_occurrences = 3
+ min_players = 10
/datum/round_event/spacevine/start()
var/list/turfs = list() //list of all the empty floor turfs in the hallway areas
diff --git a/code/modules/events/spider_infestation.dm b/code/modules/events/spider_infestation.dm
index 32641e5125d..a25f60366ee 100644
--- a/code/modules/events/spider_infestation.dm
+++ b/code/modules/events/spider_infestation.dm
@@ -3,6 +3,7 @@
typepath = /datum/round_event/spider_infestation
weight = 5
max_occurrences = 1
+ min_players = 15
/datum/round_event/spider_infestation
announceWhen = 400
diff --git a/code/modules/events/spontaneous_appendicitis.dm b/code/modules/events/spontaneous_appendicitis.dm
index 11e8d74923e..491da24ba6c 100644
--- a/code/modules/events/spontaneous_appendicitis.dm
+++ b/code/modules/events/spontaneous_appendicitis.dm
@@ -4,6 +4,7 @@
weight = 20
max_occurrences = 4
earliest_start = 6000
+ min_players = 5 // To make your chance of getting help a bit higher.
/datum/round_event/spontaneous_appendicitis/start()
for(var/mob/living/carbon/human/H in shuffle(living_mob_list))
diff --git a/code/modules/events/wormholes.dm b/code/modules/events/wormholes.dm
index fedc0d34bb0..d141c308775 100644
--- a/code/modules/events/wormholes.dm
+++ b/code/modules/events/wormholes.dm
@@ -3,6 +3,7 @@
typepath = /datum/round_event/wormholes
max_occurrences = 3
weight = 2
+ min_players = 2
/datum/round_event/wormholes
diff --git a/code/modules/food&drinks/drinks/drinks/bottle.dm b/code/modules/food&drinks/drinks/drinks/bottle.dm
index 89bb14f42ab..9ea0b9d7bb1 100644
--- a/code/modules/food&drinks/drinks/drinks/bottle.dm
+++ b/code/modules/food&drinks/drinks/drinks/bottle.dm
@@ -241,6 +241,11 @@
icon_state = "absinthebottle"
list_reagents = list("absinthe" = 100)
+/obj/item/weapon/reagent_containers/food/drinks/bottle/absinthe/premium
+ name = "Gwyn's Premium Absinthe"
+ desc = "A potent alcoholic beverage, almost makes you forget the ash in your lungs."
+ icon_state = "absinthepremium"
+
//////////////////////////JUICES AND STUFF ///////////////////////
/obj/item/weapon/reagent_containers/food/drinks/bottle/orangejuice
diff --git a/code/modules/food&drinks/food/condiment.dm b/code/modules/food&drinks/food/condiment.dm
index cb4ead55dca..d08c6f4a536 100644
--- a/code/modules/food&drinks/food/condiment.dm
+++ b/code/modules/food&drinks/food/condiment.dm
@@ -165,6 +165,13 @@
list_reagents = list("rice" = 30)
possible_states = list()
+/obj/item/weapon/reagent_containers/food/condiment/soysauce
+ name = "soy sauce"
+ desc = "A salty soy-based flavoring."
+ icon_state = "soysauce"
+ list_reagents = list("soysauce" = 50)
+ possible_states = list()
+
//Food packs. To easily apply deadly toxi... delicious sauces to your food!
diff --git a/code/modules/food&drinks/food/snacks/meat.dm b/code/modules/food&drinks/food/snacks/meat.dm
index cbabea0adb0..476f84383fa 100644
--- a/code/modules/food&drinks/food/snacks/meat.dm
+++ b/code/modules/food&drinks/food/snacks/meat.dm
@@ -170,7 +170,16 @@
slice_path = /obj/item/weapon/reagent_containers/food/snacks/meat/rawcutlet/spider
+/obj/item/weapon/reagent_containers/food/snacks/meat/slab/goliath
+ name = "goliath meat"
+ desc = "A slab of goliath meat. It's not very edible now, but it cooks great in lava."
+ list_reagents = list("nutriment" = 3, "toxin" = 5)
+/obj/item/weapon/reagent_containers/food/snacks/meat/slab/goliath/burn()
+ visible_message("\The [src] finishes cooking!")
+ new/obj/item/weapon/reagent_containers/food/snacks/meat/steak/goliath/(src.loc)
+ SSobj.burning -= src
+ qdel(src)
////////////////////////////////////// MEAT STEAKS ///////////////////////////////////////////////////////////
@@ -200,6 +209,10 @@
/obj/item/weapon/reagent_containers/food/snacks/meat/steak/spider
name = "spider steak"
+/obj/item/weapon/reagent_containers/food/snacks/meat/steak/goliath
+ name = "goliath steak"
+ desc = "A delicious, lava cooked steak."
+ burn_state = LAVA_PROOF
//////////////////////////////// MEAT CUTLETS ///////////////////////////////////////////////////////
diff --git a/code/modules/hydroponics/biogenerator.dm b/code/modules/hydroponics/biogenerator.dm
index 334cc5f671c..b67fff7abda 100644
--- a/code/modules/hydroponics/biogenerator.dm
+++ b/code/modules/hydroponics/biogenerator.dm
@@ -141,8 +141,10 @@
dat += "