Please don't break

This commit is contained in:
Qwertytoforty
2021-06-28 19:12:39 -04:00
427 changed files with 13498 additions and 19756 deletions
+4 -3
View File
@@ -2,13 +2,13 @@
<!-- You can view Contributing.MD for a detailed description of the pull request process. -->
## What Does This PR Do
<!-- Include a small to medium description of what your PR changes. Document every changes or this may delay review or even discourage maintainers from merging your PR! -->
<!-- Include a small to medium description of what your PR changes. Document all changes, as not doing this may delay reviews or even discourage maintainers from merging your PR! -->
## Why It's Good For The Game
<!-- Please add a short description of why you think these changes would benefit the game. If you can't justify it in words, it might not be worth adding. -->
<!-- Add a short description of why you think these changes would benefit the game. If you can't justify it in words, it might not be worth adding. -->
## Images of changes
<!-- If you did not make a map or sprite edit, you may delete this section. You may include a gif of your feature if you want -->
<!-- If you did not make a map or sprite edit, you may delete this section. You may include a gif or mp4 of your feature if you want. -->
## Changelog
:cl:
@@ -27,3 +27,4 @@ experiment: Added an experimental thingy
<!-- Both :cl:'s are required for the changelog to work! You can put your name to the right of the first :cl: if you want to overwrite your GitHub username as author ingame. -->
<!-- You can use multiple of the same prefix (they're only used for the icon ingame) and delete the unneeded ones. Despite some of the tags, changelogs should generally represent how a player might be affected by the changes rather than a summary of the PR's contents. -->
<!-- If a PR has no impact on players (i.e. a code refactor that does not change functionality) then the entire Changelog heading and contents can be removed. -->
+1 -1
View File
@@ -50,7 +50,7 @@ jobs:
tools/ci/install_byond.sh
source $HOME/BYOND/byond/bin/byondsetup
tools/ci/generate_maplist.sh
tools/ci/dm.sh -Mci_map_testing paradise.dme
tools/ci/dm.sh -DCIMAP paradise.dme
unit_tests_and_sql:
name: Unit Tests + SQL Validation
+4 -7
View File
@@ -1,8 +1,5 @@
{
"workbench.editorAssociations": [
{
"filenamePattern": "*.dmi",
"viewType": "imagePreview.previewEditor"
}
]
}
"workbench.editorAssociations": {
"*.dmi": "imagePreview.previewEditor"
}
}
+14
View File
@@ -277,6 +277,7 @@ CREATE TABLE `player` (
`fupdate` smallint(4) DEFAULT '0',
`parallax` tinyint(1) DEFAULT '8',
`byond_date` DATE DEFAULT NULL,
`2fa_status` ENUM('DISABLED','ENABLED_IP','ENABLED_ALWAYS') NOT NULL DEFAULT 'DISABLED' COLLATE 'utf8mb4_general_ci',
PRIMARY KEY (`id`),
UNIQUE KEY `ckey` (`ckey`),
KEY `lastseen` (`lastseen`),
@@ -585,3 +586,16 @@ CREATE TABLE `round` (
`station_name` VARCHAR(80) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
--
-- Table structure for table `2fa_secrets`
--
CREATE TABLE `2fa_secrets` (
`ckey` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_general_ci',
`secret` VARCHAR(64) NOT NULL COLLATE 'utf8mb4_general_ci',
`date_setup` DATETIME NOT NULL DEFAULT current_timestamp(),
`last_time` DATETIME NULL DEFAULT NULL,
PRIMARY KEY (`ckey`) USING BTREE
)
COLLATE='utf8mb4_general_ci' ENGINE=InnoDB;
+13
View File
@@ -276,6 +276,7 @@ CREATE TABLE `SS13_player` (
`fupdate` smallint(4) DEFAULT '0',
`parallax` tinyint(1) DEFAULT '8',
`byond_date` DATE DEFAULT NULL,
`2fa_status` ENUM('DISABLED','ENABLED_IP','ENABLED_ALWAYS') NOT NULL DEFAULT 'DISABLED' COLLATE 'utf8mb4_general_ci',
PRIMARY KEY (`id`),
UNIQUE KEY `ckey` (`ckey`),
KEY `lastseen` (`lastseen`),
@@ -582,3 +583,15 @@ CREATE TABLE `SS13_round` (
`station_name` VARCHAR(80) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
--
-- Table structure for table `2fa_secrets`
--
CREATE TABLE `SS13_2fa_secrets` (
`ckey` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_general_ci',
`secret` VARCHAR(64) NOT NULL COLLATE 'utf8mb4_general_ci',
`date_setup` DATETIME NOT NULL DEFAULT current_timestamp(),
`last_time` DATETIME NULL DEFAULT NULL,
PRIMARY KEY (`ckey`) USING BTREE
)
COLLATE='utf8mb4_general_ci' ENGINE=InnoDB;
+13
View File
@@ -0,0 +1,13 @@
# Updates DB from 23 to 24 -AffectedArc07
# Add new column to player table for 2FA status
ALTER TABLE `player` ADD COLUMN `2fa_status` ENUM('DISABLED','ENABLED_IP','ENABLED_ALWAYS') NOT NULL DEFAULT 'DISABLED' AFTER `byond_date`;
# Create new table for 2FA tokens
CREATE TABLE `2fa_secrets` (
`ckey` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_general_ci',
`secret` VARCHAR(64) NOT NULL COLLATE 'utf8mb4_general_ci',
`date_setup` DATETIME NOT NULL DEFAULT current_timestamp(),
`last_time` DATETIME NULL DEFAULT NULL,
PRIMARY KEY (`ckey`) USING BTREE
)
COLLATE='utf8mb4_general_ci' ENGINE=InnoDB;
+5
View File
@@ -0,0 +1,5 @@
#include "map_files\generic\centcomm.dmm"
#define CC_TRANSITION_CONFIG DECLARE_LEVEL(CENTCOMM, SELFLOOPING, list(ADMIN_LEVEL, BLOCK_TELEPORT, IMPEDES_MAGIC))
#ifdef CIMAP
#include "ci_map_testing.dm"
#endif
-27
View File
@@ -1,27 +0,0 @@
/*
All z-levels should be identical in size. Their numbers should not matter.
The order of z-levels should not matter as long as their attributes are properly defined at MAP_TRANSITION_CONFIG.
Old code checked for the number of the z-level (for example whether there are any revheads on Z1),
currently it should check for the define (for example whether there are any revheads on any z-levels defined as STATION_LEVEL).
z1 = centcomm
z2 = station
z3 = lavaland
*/
#if !defined(USING_MAP_DATUM)
#include "map_files\generic\centcomm.dmm"
#include "map_files\cyberiad\cyberiad.dmm"
#include "map_files\generic\Lavaland.dmm"
#define MAP_TRANSITION_CONFIG list(\
DECLARE_LEVEL(CENTCOMM, SELFLOOPING, list(ADMIN_LEVEL, BLOCK_TELEPORT, IMPEDES_MAGIC)),\
DECLARE_LEVEL(MAIN_STATION, CROSSLINKED, list(STATION_LEVEL, STATION_CONTACT, REACHABLE, AI_OK)),\
DECLARE_LEVEL(MINING, SELFLOOPING, list(ORE_LEVEL, REACHABLE, STATION_CONTACT, HAS_WEATHER, AI_OK)))
#define USING_MAP_DATUM /datum/map/cyberiad
#elif !defined(MAP_OVERRIDE)
#warn a map has already been included, ignoring Cyberiad.
#endif
-30
View File
@@ -1,30 +0,0 @@
/*
All z-levels should be identical in size. Their numbers should not matter.
The order of z-levels should not matter as long as their attributes are properly defined at MAP_TRANSITION_CONFIG.
Old code checked for the number of the z-level (for example whether there are any revheads on Z1),
currently it should check for the define (for example whether there are any revheads on any z-levels defined as STATION_LEVEL).
z1 = centcomm
z2 = station
z3 = lavaland
Original design by Okand37 of TG Station
Lovingly ported by Purpose2 to Paradise
*/
#if !defined(USING_MAP_DATUM)
#include "map_files\generic\centcomm.dmm"
#include "map_files\delta\delta.dmm"
#include "map_files\generic\Lavaland.dmm"
#define MAP_TRANSITION_CONFIG list(\
DECLARE_LEVEL(CENTCOMM, SELFLOOPING, list(ADMIN_LEVEL, BLOCK_TELEPORT, IMPEDES_MAGIC)),\
DECLARE_LEVEL(MAIN_STATION, CROSSLINKED, list(STATION_LEVEL, STATION_CONTACT, REACHABLE, AI_OK)),\
DECLARE_LEVEL(MINING, SELFLOOPING, list(ORE_LEVEL, REACHABLE, STATION_CONTACT, HAS_WEATHER, AI_OK)))
#define USING_MAP_DATUM /datum/map/delta
#elif !defined(MAP_OVERRIDE)
#warn a map has already been included, ignoring Delta.
#endif
+1
View File
@@ -0,0 +1 @@
// See code/modules/mapping for map datums
File diff suppressed because it is too large Load Diff
@@ -2388,7 +2388,7 @@
},
/area/ruin/unpowered/syndicate_space_base/main)
"yf" = (
/obj/machinery/computer/monitor{
/obj/machinery/computer/monitor/secret{
name = "Engine Grid Power Monitoring Computer"
},
/obj/structure/cable/yellow,
@@ -4114,7 +4114,7 @@
icon_state = "0-2";
pixel_y = 1
},
/obj/machinery/computer/monitor{
/obj/machinery/computer/monitor/secret{
name = "Output Grid Power Monitoring Computer"
},
/turf/simulated/floor/plating,
@@ -133,7 +133,7 @@
},
/area/derelict/bridge)
"av" = (
/obj/machinery/computer/monitor,
/obj/machinery/computer/monitor/secret,
/turf/simulated/floor/plasteel{
dir = 1;
icon_state = "darkblue"
@@ -3697,7 +3697,7 @@
name = "Derelict Annex"
})
"hD" = (
/obj/machinery/computer/monitor,
/obj/machinery/computer/monitor/secret,
/turf/simulated/floor/plasteel{
icon_state = "caution";
dir = 5
@@ -2536,7 +2536,7 @@
icon_state = "0-4";
d2 = 4
},
/obj/machinery/computer/monitor,
/obj/machinery/computer/monitor/secret,
/obj/effect/decal/warning_stripes/west,
/turf/simulated/floor/plasteel,
/area/awaymission/BMPship/Aft)
@@ -2785,7 +2785,7 @@
d2 = 8;
icon_state = "0-8"
},
/obj/machinery/computer/monitor,
/obj/machinery/computer/monitor/secret,
/turf/simulated/floor/plasteel{
icon_state = "yellow"
},
@@ -1308,7 +1308,7 @@
icon_state = "0-4";
d2 = 4
},
/obj/machinery/computer/monitor,
/obj/machinery/computer/monitor/secret,
/obj/structure/cable{
d1 = 4;
d2 = 8;
@@ -5160,7 +5160,7 @@
/turf/simulated/floor/plating,
/area/awaycontent/a7)
"hm" = (
/obj/machinery/computer/monitor,
/obj/machinery/computer/monitor/secret,
/obj/structure/cable,
/turf/simulated/floor/plating,
/area/awaycontent/a7)
@@ -7975,7 +7975,7 @@
icon_state = "0-4";
d2 = 4
},
/obj/machinery/computer/monitor{
/obj/machinery/computer/monitor/secret{
name = "primary power monitoring console"
},
/obj/structure/sign/nosmoking_2{
@@ -10652,7 +10652,7 @@
/turf/simulated/floor/plating/asteroid/airless,
/area/awaymission/UO71/outside)
"vV" = (
/obj/machinery/computer/monitor,
/obj/machinery/computer/monitor/secret,
/turf/simulated/floor/plasteel,
/area/awaymission/UO71/bridge)
"vW" = (
@@ -11805,7 +11805,7 @@
},
/area/awaymission/UO71/eng)
"yc" = (
/obj/machinery/computer/monitor{
/obj/machinery/computer/monitor/secret{
name = "primary power monitoring console"
},
/obj/structure/cable,
@@ -11078,7 +11078,7 @@
icon_state = "0-4";
d2 = 4
},
/obj/machinery/computer/monitor{
/obj/machinery/computer/monitor/secret{
name = "primary power monitoring console"
},
/obj/structure/sign/nosmoking_2{
@@ -15909,7 +15909,7 @@
name = "UO45 Engineering"
})
"xg" = (
/obj/machinery/computer/monitor{
/obj/machinery/computer/monitor/secret{
name = "primary power monitoring console"
},
/obj/structure/cable,
+3
View File
@@ -11168,6 +11168,9 @@
icon_state = "tube1";
tag = "icon-tube1 (WEST)"
},
/obj/structure/chair/comfy/shuttle{
dir = 4
},
/turf/simulated/floor/mineral/plastitanium/red,
/area/shuttle/specops)
"QL" = (
-27
View File
@@ -1,27 +0,0 @@
/*
All z-levels should be identical in size. Their numbers should not matter.
The order of z-levels should not matter as long as their attributes are properly defined at MAP_TRANSITION_CONFIG.
Old code checked for the number of the z-level (for example whether there are any revheads on Z1),
currently it should check for the define (for example whether there are any revheads on any z-levels defined as STATION_LEVEL).
z1 = centcomm
z2 = station
z3 = lavaland
*/
#if !defined(USING_MAP_DATUM)
#include "map_files\generic\centcomm.dmm"
#include "map_files\MetaStation\MetaStation.dmm"
#include "map_files\generic\Lavaland.dmm"
#define MAP_TRANSITION_CONFIG list(\
DECLARE_LEVEL(CENTCOMM, SELFLOOPING, list(ADMIN_LEVEL, BLOCK_TELEPORT, IMPEDES_MAGIC)),\
DECLARE_LEVEL(MAIN_STATION, CROSSLINKED, list(STATION_LEVEL, STATION_CONTACT, REACHABLE, AI_OK)),\
DECLARE_LEVEL(MINING, SELFLOOPING, list(ORE_LEVEL, REACHABLE, STATION_CONTACT, HAS_WEATHER, AI_OK)))
#define USING_MAP_DATUM /datum/map/metastation
#elif !defined(MAP_OVERRIDE)
#warn a map has already been included, ignoring MetaStation.
#endif
+1 -1
View File
@@ -363,7 +363,7 @@
#define INVESTIGATE_BOMB "bombs"
// The SQL version required by this version of the code
#define SQL_VERSION 23
#define SQL_VERSION 24
// Vending machine stuff
#define CAT_NORMAL 1
+11 -1
View File
@@ -55,8 +55,9 @@
// Yes I know this being an "enable to disable" is misleading, but it avoids having to tweak all existing pref entries
#define PREFTOGGLE_2_REVERB_DISABLE 512
#define PREFTOGGLE_2_FORCE_WHITE_RUNECHAT 1024
#define PREFTOGGLE_2_SIMPLE_STAT_PANEL 2048
#define TOGGLES_2_TOTAL 2047 // If you add or remove a preference toggle above, make sure you update this define with the total value of the toggles combined.
#define TOGGLES_2_TOTAL 4095 // If you add or remove a preference toggle above, make sure you update this define with the total value of the toggles combined.
#define TOGGLES_2_DEFAULT (PREFTOGGLE_2_FANCYUI|PREFTOGGLE_2_ITEMATTACK|PREFTOGGLE_2_WINDOWFLASHING|PREFTOGGLE_2_RUNECHAT|PREFTOGGLE_2_DEATHMESSAGE|PREFTOGGLE_2_EMOTE_BUBBLE)
@@ -104,3 +105,12 @@
#define PARALLAX_MED 4
#define PARALLAX_HIGH 8
#define PARALLAX_INSANE 16
// 2FA Defines. These are the same as the schema DB enums //
/// Client has 2FA disabled
#define _2FA_DISABLED "DISABLED"
/// Client will be prompted for 2FA on IP changes
#define _2FA_ENABLED_IP "ENABLED_IP"
/// Client will be prompted for 2FA always
#define _2FA_ENABLED_ALWAYS "ENABLED_ALWAYS"
+3 -3
View File
@@ -134,9 +134,6 @@ GLOBAL_PROTECT(log_end)
/proc/log_href(text)
rustg_log_write(GLOB.world_href_log, "HREF: [html_decode(text)][GLOB.log_end]")
/proc/log_asset(text)
rustg_log_write(GLOB.world_asset_log, "ASSET: [text][GLOB.log_end]")
/proc/log_runtime_summary(text)
rustg_log_write(GLOB.runtime_summary_log, "[text][GLOB.log_end]")
@@ -147,6 +144,9 @@ GLOBAL_PROTECT(log_end)
rustg_log_write(GLOB.sql_log, "[text][GLOB.log_end]")
SEND_TEXT(world.log, text) // Redirect it to DD too
/proc/log_chat_debug(text)
rustg_log_write(GLOB.chat_debug_log, "[text][GLOB.log_end]")
// A logging proc that only outputs after setup is done, to
// help devs test initialization stuff that happens a lot
/proc/log_after_setup(message)
+3 -6
View File
@@ -15,9 +15,9 @@ GLOBAL_VAR(church_name)
return name
GLOBAL_VAR(command_name)
// TODO: Remove this. Its always gonna be NAS Trurl
/proc/command_name()
return GLOB.using_map.dock_name
return "NAS Trurl"
GLOBAL_VAR(religion_name)
/proc/religion_name()
@@ -31,11 +31,8 @@ GLOBAL_VAR(religion_name)
return capitalize(name)
/proc/system_name()
return GLOB.using_map.starsys_name
/proc/station_name()
return GLOB.using_map.station_name
return SSmapping.map_datum.fluff_name
/proc/new_station_name()
var/random = rand(1,5)
+58
View File
@@ -514,6 +514,7 @@
text = replacetext(text, "\[logo\]", "&ZeroWidthSpace;<img src = ntlogo.png>")
text = replacetext(text, "\[time\]", "[station_time_timestamp()]") // TO DO
text = replacetext(text, "\[date\]", "[GLOB.current_date_string]")
text = replacetext(text, "\[station\]", "[SSmapping.map_datum.fluff_name]")
if(!no_font)
if(P)
text = "<font face=\"[deffont]\" color=[P ? P.colour : "black"]>[text]</font>"
@@ -653,6 +654,62 @@
// return the split html object to the caller
return s
//Used for applying byonds text macros to strings that are loaded at runtime
/proc/apply_text_macros(string)
var/next_backslash = findtext(string, "\\")
if(!next_backslash)
return string
var/leng = length(string)
var/next_space = findtext(string, " ", next_backslash + length(string[next_backslash]))
if(!next_space)
next_space = leng - next_backslash
if(!next_space) //trailing bs
return string
var/base = next_backslash == 1 ? "" : copytext(string, 1, next_backslash)
var/macro = lowertext(copytext(string, next_backslash + length(string[next_backslash]), next_space))
var/rest = next_backslash > leng ? "" : copytext(string, next_space + length(string[next_space]))
//See https://secure.byond.com/docs/ref/info.html#/DM/text/macros
switch(macro)
//prefixes/agnostic
if("the")
rest = text("\the []", rest)
if("a")
rest = text("\a []", rest)
if("an")
rest = text("\an []", rest)
if("proper")
rest = text("\proper []", rest)
if("improper")
rest = text("\improper []", rest)
if("roman")
rest = text("\roman []", rest)
//postfixes
if("th")
base = text("[]\th", rest)
if("s")
base = text("[]\s", rest)
if("he")
base = text("[]\he", rest)
if("she")
base = text("[]\she", rest)
if("his")
base = text("[]\his", rest)
if("himself")
base = text("[]\himself", rest)
if("herself")
base = text("[]\herself", rest)
if("hers")
base = text("[]\hers", rest)
. = base
if(rest)
. += .(rest)
/**
* Proc to generate a "rank colour" from a client
*
@@ -671,3 +728,4 @@
if(C.donator_level)
return "#e67e22" // Patreon orange
return null
+4 -3
View File
@@ -99,7 +99,7 @@
Remember to update _globalvars/traits.dm if you're adding/removing/renaming traits.
*/
//mob traits
//***** MOB TRAITS *****//
#define TRAIT_BLIND "blind"
#define TRAIT_MUTE "mute"
#define TRAIT_DEAF "deaf"
@@ -152,8 +152,9 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_NOEXAMINE "no_examine"
#define TRAIT_NOPAIN "no_pain"
/// Blowing kisses actually does damage to the victim
#define TRAIT_KISS_OF_DEATH "kiss_of_death"
//***** ITEM TRAITS *****//
/// Show what machine/door wires do when held.
#define TRAIT_SHOW_WIRE_INFO "show_wire_info"
//
// common trait sources
+1 -1
View File
@@ -2072,7 +2072,7 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
return _list
/// Waits at a line of code until X is true
#define UNTIL(X) while(!(X)) stoplag()
#define UNTIL(X) while(!(X)) sleep(world.tick_lag)
// Check if the source atom contains another atom
/atom/proc/contains(atom/location)
+1
View File
@@ -18,6 +18,7 @@ GLOBAL_LIST_INIT(cell_logs, list())
GLOBAL_LIST_INIT(navigation_computers, list())
GLOBAL_LIST_INIT(all_areas, list())
GLOBAL_LIST_INIT(all_unique_areas, list()) // List of all unique areas. AKA areas with there_can_be_many = FALSE
GLOBAL_LIST_INIT(machines, list())
GLOBAL_LIST_INIT(rcd_list, list()) //list of Rapid Construction Devices.
+2 -2
View File
@@ -11,8 +11,6 @@ GLOBAL_VAR(world_qdel_log)
GLOBAL_PROTECT(world_qdel_log)
GLOBAL_VAR(world_href_log)
GLOBAL_PROTECT(world_href_log)
GLOBAL_VAR(world_asset_log)
GLOBAL_PROTECT(world_asset_log)
GLOBAL_VAR(runtime_summary_log)
GLOBAL_PROTECT(runtime_summary_log)
GLOBAL_VAR(tgui_log)
@@ -21,6 +19,8 @@ GLOBAL_VAR(http_log)
GLOBAL_PROTECT(http_log)
GLOBAL_VAR(sql_log)
GLOBAL_PROTECT(sql_log)
GLOBAL_VAR(chat_debug_log)
GLOBAL_PROTECT(chat_debug_log)
GLOBAL_VAR(round_id)
GLOBAL_PROTECT(round_id)
-3
View File
@@ -8,9 +8,6 @@ GLOBAL_LIST_INIT(alldirs, list(NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, S
GLOBAL_LIST_INIT(alldirs2, list(NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST, NORTH, SOUTH, EAST, WEST))
GLOBAL_LIST_INIT(diagonals, list(NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST))
// This must exist early on or shit breaks bad
GLOBAL_DATUM_INIT(using_map, /datum/map, new USING_MAP_DATUM)
GLOBAL_LIST(global_map) // This is the array of zlevels | list(list(1,5),list(4,3)) | becomes a 2D array of zlevels
//Resulting sector map looks like
//|_1_|_4_|
-3
View File
@@ -86,9 +86,6 @@ GLOBAL_VAR_INIT(copier_items_printed, 0)
GLOBAL_VAR_INIT(copier_max_items, 300)
GLOBAL_VAR_INIT(copier_items_printed_logged, FALSE)
GLOBAL_VAR(map_name) // Self explanatory
GLOBAL_DATUM_INIT(data_core, /datum/datacore, new) // Station datacore, manifest, etc
GLOBAL_VAR_INIT(panic_bunker_enabled, FALSE) // Is the panic bunker enabled
+6 -2
View File
@@ -45,7 +45,6 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_DWARF" = TRAIT_DWARF,
"TRAIT_SILENT_FOOTSTEPS" = TRAIT_SILENT_FOOTSTEPS,
"TRAIT_ALCOHOL_TOLERANCE" = TRAIT_ALCOHOL_TOLERANCE,
"TRAIT_KISS_OF_DEATH" = TRAIT_KISS_OF_DEATH,
"TRAIT_COMIC_SANS" = TRAIT_COMIC_SANS,
"TRAIT_NOFINGERPRINTS" = TRAIT_NOFINGERPRINTS,
@@ -57,7 +56,12 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_NOGERMS" = TRAIT_NOGERMS,
"TRAIT_NODECAY" = TRAIT_NODECAY,
"TRAIT_NOEXAMINE" = TRAIT_NOEXAMINE,
"TRAIT_NOPAIN" = TRAIT_NOPAIN)))
"TRAIT_NOPAIN" = TRAIT_NOPAIN
),
/obj/item = list(
"TRAIT_SHOW_WIRE_INFO" = TRAIT_SHOW_WIRE_INFO
)
))
/// value -> trait name, generated on use from trait_by_type global
GLOBAL_LIST(trait_name_map)
+2 -2
View File
@@ -27,10 +27,10 @@
/obj/item/badminBook/attack_self(mob/living/user as mob)
if(user.middleClickOverride)
to_chat(user, "<span class='warning'>You try to draw power from the [src], but you cannot hold the power at this time!</span>")
to_chat(user, "<span class='warning'>You try to draw power from [src], but you cannot hold the power at this time!</span>")
return
user.middleClickOverride = clickBehavior
to_chat(user, "<span class='notice'>You draw a bit of power from the [src], you can use <b>middle click</b> or <b>alt click</b> to release the power!</span>")
to_chat(user, "<span class='notice'>You draw a bit of power from [src], you can use <b>middle click</b> or <b>alt click</b> to release the power!</span>")
/datum/middleClickOverride/badminClicker
var/summon_path = /obj/item/reagent_containers/food/snacks/cookie
+2 -2
View File
@@ -122,12 +122,12 @@
icon_state = "too_much_oxy"
/obj/screen/alert/not_enough_nitro
name = "Choking (No N)"
name = "Choking (No N2)"
desc = "You're not getting enough nitrogen. Find some good air before you pass out!"
icon_state = "not_enough_nitro"
/obj/screen/alert/too_much_nitro
name = "Choking (N)"
name = "Choking (N2)"
desc = "There's too much nitrogen in the air, and you're breathing it in! Find some good air before you pass out!"
icon_state = "too_much_nitro"
-19
View File
@@ -78,15 +78,6 @@
var/mob/living/silicon/robot/R = usr
R.toggle_ionpulse()
/obj/screen/robot/panel
name = "installed modules"
icon_state = "panel"
/obj/screen/robot/panel/Click()
if(issilicon(usr))
var/mob/living/silicon/robot/R = usr
R.installed_modules()
/obj/screen/robot/mov_intent
name = "fast/slow toggle"
icon_state = "running"
@@ -224,16 +215,6 @@
var/x = -4 //Start at CENTER-4,SOUTH+1
var/y = 1
//Unfortunately adding the emag module to the list of modules has to be here. This is because a borg can
//be emagged before they actually select a module. - or some situation can cause them to get a new module
// - or some situation might cause them to get de-emagged or something.
if(R.emagged || R.weapons_unlock)
if(!(R.module.emag in R.module.modules))
R.module.modules.Add(R.module.emag)
else
if(R.module.emag in R.module.modules)
R.module.modules.Remove(R.module.emag)
for(var/atom/movable/A in R.module.modules)
if( (A != R.module_state_1) && (A != R.module_state_2) && (A != R.module_state_3) )
//Module is not currently active
+10
View File
@@ -275,6 +275,12 @@
/// Enable auto profiler of rounds
var/auto_profile = FALSE
// Enable map voting
var/map_voting_enabled = FALSE
// 2FA auth host
var/_2fa_auth_host = null
/datum/configuration/New()
for(var/T in subtypesof(/datum/game_mode))
var/datum/game_mode/M = T
@@ -770,6 +776,10 @@
max_client_cid_history = text2num(value)
if("enable_auto_profiler")
auto_profile = TRUE
if("enable_map_voting")
map_voting_enabled = TRUE
if("2fa_host")
_2fa_auth_host = value
else
log_config("Unknown setting in configuration: '[name]'")
+1 -1
View File
@@ -193,7 +193,7 @@ SUBSYSTEM_DEF(dbcore)
if(!IsConnected())
return
var/datum/db_query/query_round_end = SSdbcore.NewQuery(
"UPDATE [format_table_name("round")] SET end_datetime = Now(), game_mode_result = :game_mode_result, station_name = :station_name WHERE id = :round_id",
"UPDATE [format_table_name("round")] SET end_datetime = Now(), game_mode_result = :game_mode_result WHERE id = :round_id",
list("game_mode_result" = SSticker.mode_result, "station_name" = station_name(), "round_id" = GLOB.round_id)
)
query_round_end.Execute()
+4 -1
View File
@@ -12,8 +12,11 @@ SUBSYSTEM_DEF(http)
/// Total requests the SS has processed in a round
var/total_requests
/datum/controller/subsystem/http/Initialize(start_timeofday)
/datum/controller/subsystem/http/PreInit()
. = ..()
rustg_create_async_http_client() // Open the door
/datum/controller/subsystem/http/Initialize(start_timeofday)
active_async_requests = list()
return ..()
+88 -24
View File
@@ -1,31 +1,51 @@
SUBSYSTEM_DEF(mapping)
name = "Mapping"
init_order = INIT_ORDER_MAPPING // 9
flags = SS_NO_FIRE
name = "Mapping"
init_order = INIT_ORDER_MAPPING // 9
flags = SS_NO_FIRE
/// What map datum are we using
var/datum/map/map_datum
/// What map will be used next round
var/datum/map/next_map
// This has to be here because world/New() uses [station_name()], which looks this datum up
/datum/controller/subsystem/mapping/PreInit()
. = ..()
if(map_datum) // Dont do this again if we are recovering
return
if(fexists("data/next_map.txt"))
var/list/lines = file2list("data/next_map.txt")
// Check its valid
try
map_datum = text2path(lines[1])
map_datum = new map_datum
catch
map_datum = new /datum/map/cyberiad // Assume cyberiad if non-existent
fdel("data/next_map.txt") // Remove to avoid the same map existing forever
else
map_datum = new /datum/map/cyberiad // Assume cyberiad if non-existent
/datum/controller/subsystem/mapping/Shutdown()
if(next_map) // Save map for next round
var/F = file("data/next_map.txt")
F << next_map.type
/datum/controller/subsystem/mapping/Initialize(timeofday)
// Load all Z level templates
preloadTemplates()
// Load the station
loadStation()
// Load lavaland
loadLavaland()
// Pick a random away mission.
if(!config.disable_away_missions)
load_away_mission()
// Seed space ruins
if(!config.disable_space_ruins)
// load in extra levels of space ruins
var/load_zlevels_timer = start_watch()
log_startup_progress("Creating random space levels...")
var/num_extra_space = rand(config.extra_space_ruin_levels_min, config.extra_space_ruin_levels_max)
for(var/i = 1, i <= num_extra_space, i++)
GLOB.space_manager.add_new_zlevel("Ruin Area #[i]", linkage = CROSSLINKED, traits = list(REACHABLE, SPAWN_RUINS))
log_startup_progress("Loaded random space levels in [stop_watch(load_zlevels_timer)]s.")
// Now spawn ruins, random budget between 20 and 30 for all zlevels combined.
// While this may seem like a high number, the amount of ruin Z levels can be anywhere between 3 and 7.
// Note that this budget is not split evenly accross all zlevels
log_startup_progress("Seeding ruins...")
var/seed_ruins_timer = start_watch()
seedRuins(levels_by_trait(SPAWN_RUINS), rand(20, 30), /area/space, GLOB.space_ruins_templates)
log_startup_progress("Successfully seeded ruins in [stop_watch(seed_ruins_timer)]s.")
handleRuins()
// Makes a blank space level for the sake of randomness
GLOB.space_manager.add_new_zlevel("Empty Area", linkage = CROSSLINKED, traits = list(REACHABLE))
@@ -63,12 +83,6 @@ SUBSYSTEM_DEF(mapping)
GLOB.ghostteleportlocs = sortAssoc(GLOB.ghostteleportlocs)
// Map name. Break these down into SSmapping controller vars instaed of GLOBs at some point
if(GLOB.using_map && GLOB.using_map.name)
GLOB.map_name = "[GLOB.using_map.name]"
else
GLOB.map_name = "Unknown"
// World name
if(config && config.server_name)
world.name = "[config.server_name]: [station_name()]"
@@ -77,6 +91,56 @@ SUBSYSTEM_DEF(mapping)
return ..()
// Do not confuse with seedRuins()
/datum/controller/subsystem/mapping/proc/handleRuins()
// load in extra levels of space ruins
var/load_zlevels_timer = start_watch()
log_startup_progress("Creating random space levels...")
var/num_extra_space = rand(config.extra_space_ruin_levels_min, config.extra_space_ruin_levels_max)
for(var/i in 1 to num_extra_space)
GLOB.space_manager.add_new_zlevel("Ruin Area #[i]", linkage = CROSSLINKED, traits = list(REACHABLE, SPAWN_RUINS))
log_startup_progress("Loaded random space levels in [stop_watch(load_zlevels_timer)]s.")
// Now spawn ruins, random budget between 20 and 30 for all zlevels combined.
// While this may seem like a high number, the amount of ruin Z levels can be anywhere between 3 and 7.
// Note that this budget is not split evenly accross all zlevels
log_startup_progress("Seeding ruins...")
var/seed_ruins_timer = start_watch()
seedRuins(levels_by_trait(SPAWN_RUINS), rand(20, 30), /area/space, GLOB.space_ruins_templates)
log_startup_progress("Successfully seeded ruins in [stop_watch(seed_ruins_timer)]s.")
// Loads in the station
/datum/controller/subsystem/mapping/proc/loadStation()
ASSERT(map_datum.map_path)
if(!fexists(map_datum.map_path))
// Make a VERY OBVIOUS error
to_chat(world, "<span class='narsie'>ERROR: The path specified for the map to load is invalid. No station has been loaded!</span>")
return
var/watch = start_watch()
log_startup_progress("Loading [map_datum.fluff_name]...")
// This should always be Z2, but you never know
var/map_z_level = GLOB.space_manager.add_new_zlevel(MAIN_STATION, linkage = CROSSLINKED, traits = list(STATION_LEVEL, STATION_CONTACT, REACHABLE, AI_OK))
GLOB.maploader.load_map(file(map_datum.map_path), z_offset = map_z_level)
log_startup_progress("Loaded [map_datum.fluff_name] in [stop_watch(watch)]s")
// Save station name in the DB
if(!SSdbcore.IsConnected())
return
var/datum/db_query/query_set_map = SSdbcore.NewQuery(
"UPDATE [format_table_name("round")] SET start_datetime=NOW(), map_name=:mapname, station_name=:stationname WHERE id=:round_id",
list("mapname" = map_datum.technical_name, "stationname" = map_datum.fluff_name, "round_id" = GLOB.round_id)
)
query_set_map.Execute(async = FALSE) // This happens during a time of intense server lag, so should be non-async
qdel(query_set_map)
// Loads in lavaland
/datum/controller/subsystem/mapping/proc/loadLavaland()
var/watch = start_watch()
log_startup_progress("Loading Lavaland...")
var/lavaland_z_level = GLOB.space_manager.add_new_zlevel(MINING, linkage = SELFLOOPING, traits = list(ORE_LEVEL, REACHABLE, STATION_CONTACT, HAS_WEATHER, AI_OK))
GLOB.maploader.load_map(file("_maps/map_files/generic/Lavaland.dmm"), z_offset = lavaland_z_level)
log_startup_progress("Loaded Lavaland in [stop_watch(watch)]s")
/datum/controller/subsystem/mapping/proc/seedRuins(list/z_levels = null, budget = 0, whitelist = /area/space, list/potentialRuins)
if(!z_levels || !z_levels.len)
-2
View File
@@ -135,8 +135,6 @@ SUBSYSTEM_DEF(shuttle)
to_chat(user, "The emergency shuttle has been disabled by Centcom.")
return
call_reason = trim(html_encode(call_reason))
if(length(call_reason) < CALL_SHUTTLE_REASON_LENGTH)
to_chat(user, "Reason is too short. [CALL_SHUTTLE_REASON_LENGTH] character minimum.")
return
@@ -16,8 +16,6 @@ SUBSYSTEM_DEF(title)
else if(L.len > 1)
if(use_rare_screens && lowertext(L[1]) == "rare")
title_screens += S
else if(GLOB.using_map && (lowertext(L[1]) == lowertext(GLOB.using_map.name)))
title_screens += S
if(!isemptylist(title_screens))
if(length(title_screens) > 1)
+29 -6
View File
@@ -177,6 +177,16 @@ SUBSYSTEM_DEF(vote)
if("crew_transfer")
if(. == "Initiate Crew Transfer")
init_shift_change(null, 1)
if("map")
// Find target map.
var/datum/map/top_voted_map
for(var/x in subtypesof(/datum/map))
var/datum/map/M = x
// Set top voted map
if(. == "[initial(M.fluff_name)] ([initial(M.technical_name)])")
top_voted_map = M
to_chat(world, "<font color='purple'>Map for next round: [initial(top_voted_map.fluff_name)] ([initial(top_voted_map.technical_name)])</font>")
SSmapping.next_map = new top_voted_map
if(restart)
@@ -197,7 +207,7 @@ SUBSYSTEM_DEF(vote)
return vote
return 0
/datum/controller/subsystem/vote/proc/initiate_vote(vote_type, initiator_key)
/datum/controller/subsystem/vote/proc/initiate_vote(vote_type, initiator_key, code_invoked = FALSE)
if(!mode)
if(started_time != null && !check_rights(R_ADMIN))
var/next_allowed_time = (started_time + config.vote_delay)
@@ -223,6 +233,14 @@ SUBSYSTEM_DEF(vote)
return 0
question = "End the shift?"
choices.Add("Initiate Crew Transfer", "Continue The Round")
if("map")
if(!(check_rights(R_SERVER) || code_invoked))
return FALSE
question = "Map for next round"
for(var/x in subtypesof(/datum/map))
var/datum/map/M = x
choices.Add("[initial(M.fluff_name)] ([initial(M.technical_name)])")
if("custom")
question = html_encode(input(usr,"What is the vote for?") as text|null)
if(!question) return 0
@@ -248,11 +266,7 @@ SUBSYSTEM_DEF(vote)
<a href='?src=[UID()];vote=open'>Click here or type vote to place your vote.</a>
You have [config.vote_period/10] seconds to vote.</font>"})
switch(vote_type)
if("crew_transfer")
SEND_SOUND(world, sound('sound/ambience/alarm4.ogg'))
if("gamemode")
SEND_SOUND(world, sound('sound/ambience/alarm4.ogg'))
if("custom")
if("crew_transfer", "gamemode", "custom", "map")
SEND_SOUND(world, sound('sound/ambience/alarm4.ogg'))
if(mode == "gamemode" && SSticker.ticker_going)
SSticker.ticker_going = FALSE
@@ -321,6 +335,12 @@ SUBSYSTEM_DEF(vote)
if(admin)
dat += "\t(<a href='?src=[UID()];vote=toggle_gamemode'>[config.allow_vote_mode?"Allowed":"Disallowed"]</a>)"
dat += "</li><li>"
if(admin)
dat += "<a href='?src=[UID()];vote=map'>Map</a>"
else
dat += "<font color='grey'>Map (Disallowed)</font>"
dat += "</li>"
//custom
if(admin)
@@ -381,6 +401,9 @@ SUBSYSTEM_DEF(vote)
if("gamemode")
if(config.allow_vote_mode || admin)
initiate_vote("gamemode",usr.key)
if("map")
if(admin)
initiate_vote("map", usr.key)
if("crew_transfer")
if(config.allow_vote_restart || admin)
initiate_vote("crew_transfer",usr.key)
+1
View File
@@ -429,6 +429,7 @@
desc = "Activates the jump boot's internal propulsion system, allowing the user to dash over 4-wide gaps."
icon_icon = 'icons/mob/actions/actions.dmi'
button_icon_state = "jetboot"
use_itemicon = FALSE
///prset for organ actions
/datum/action/item_action/organ_action
+3 -3
View File
@@ -130,13 +130,13 @@
/datum/component/material_container/proc/insert_stack(obj/item/stack/S, amt, multiplier = 1)
if(isnull(amt))
amt = S.amount
amt = S.get_amount()
if(amt <= 0)
return FALSE
if(amt > S.amount)
amt = S.amount
if(amt > S.get_amount())
amt = S.get_amount()
var/material_amt = get_item_material_amount(S)
if(!material_amt)
-123
View File
@@ -5,129 +5,6 @@
//This list tracks characters spawned in the world and cannot be modified in-game. Currently referenced by respawn_character().
var/list/locked = list()
/datum/datacore/proc/get_manifest(monochrome, OOC)
var/list/heads = new()
var/list/sec = new()
var/list/eng = new()
var/list/med = new()
var/list/sci = new()
var/list/ser = new()
var/list/sup = new()
var/list/bot = new()
var/list/misc = new()
var/list/isactive = new()
var/dat = {"
<head><style>
.manifest {border-collapse:collapse;}
.manifest td, th {border:1px solid [monochrome?"black":"#DEF; background-color:white; color:black"]; padding:.25em}
.manifest th {height: 2em; [monochrome?"border-top-width: 3px":"background-color: #48C; color:white"]}
.manifest tr.head th { [monochrome?"border-top-width: 1px":"background-color: #488;"] }
.manifest td:first-child {text-align:right}
.manifest tr.alt td {[monochrome?"border-top-width: 2px":"background-color: #DEF"]}
</style></head>
<table class="manifest" width='350px'>
<tr class='head'><th>Name</th><th>Rank</th><th>Activity</th></tr>
"}
var/even = 0
// sort mobs
for(var/datum/data/record/t in GLOB.data_core.general)
var/name = t.fields["name"]
var/rank = t.fields["rank"]
var/real_rank = t.fields["real_rank"]
if(OOC)
var/activetext = "Inactive"
for(var/thing in GLOB.human_list)
var/mob/living/carbon/human/H = thing
if(H.real_name != name)
continue
if(H.client && H.client.inactivity <= 6000)
activetext = "Active"
break
if(isLivingSSD(H))
activetext = "SSD"
break
isactive[name] = activetext
else
isactive[name] = t.fields["p_stat"]
var/department = 0
if(real_rank in GLOB.command_positions)
heads[name] = rank
department = 1
if(real_rank in GLOB.security_positions)
sec[name] = rank
department = 1
if(real_rank in GLOB.engineering_positions)
eng[name] = rank
department = 1
if(real_rank in GLOB.medical_positions)
med[name] = rank
department = 1
if(real_rank in GLOB.science_positions)
sci[name] = rank
department = 1
if(real_rank in GLOB.service_positions)
ser[name] = rank
department = 1
if(real_rank in GLOB.supply_positions)
sup[name] = rank
department = 1
if(real_rank in GLOB.nonhuman_positions)
bot[name] = rank
department = 1
if(!department && !(name in heads))
misc[name] = rank
if(heads.len > 0)
dat += "<tr><th colspan=3>Heads</th></tr>"
for(var/name in heads)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[heads[name]]</td><td>[isactive[name]]</td></tr>"
even = !even
if(sec.len > 0)
dat += "<tr><th colspan=3>Security</th></tr>"
for(var/name in sec)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[sec[name]]</td><td>[isactive[name]]</td></tr>"
even = !even
if(eng.len > 0)
dat += "<tr><th colspan=3>Engineering</th></tr>"
for(var/name in eng)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[eng[name]]</td><td>[isactive[name]]</td></tr>"
even = !even
if(med.len > 0)
dat += "<tr><th colspan=3>Medical</th></tr>"
for(var/name in med)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[med[name]]</td><td>[isactive[name]]</td></tr>"
even = !even
if(sci.len > 0)
dat += "<tr><th colspan=3>Science</th></tr>"
for(var/name in sci)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[sci[name]]</td><td>[isactive[name]]</td></tr>"
even = !even
if(ser.len > 0)
dat += "<tr><th colspan=3>Service</th></tr>"
for(var/name in ser)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[ser[name]]</td><td>[isactive[name]]</td></tr>"
even = !even
if(sup.len > 0)
dat += "<tr><th colspan=3>Supply</th></tr>"
for(var/name in sup)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[sup[name]]</td><td>[isactive[name]]</td></tr>"
even = !even
if(bot.len > 0)
dat += "<tr><th colspan=3>Silicon</th></tr>"
for(var/name in bot)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[bot[name]]</td><td>[isactive[name]]</td></tr>"
even = !even
if(misc.len > 0)
dat += "<tr><th colspan=3>Miscellaneous</th></tr>"
for(var/name in misc)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[misc[name]]</td><td>[isactive[name]]</td></tr>"
even = !even
dat += "</table>"
dat = replacetext(dat, "\n", "") // so it can be placed on paper correctly
dat = replacetext(dat, "\t", "")
return dat
/*
We can't just insert in HTML into the TGUI so we need the raw data to play with.
Instead of creating this list over and over when someone leaves their PDA open to the page
@@ -47,7 +47,7 @@
/datum/construction/proc/custom_action(step, used_atom, user)
if(istype(used_atom, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C = used_atom
if(C.amount<4)
if(C.get_amount() < 4)
to_chat(user, ("<span class='warning'>There's not enough cable to finish the task.</span>"))
return 0
else
@@ -55,7 +55,7 @@
playsound(holder, C.usesound, 50, 1)
else if(istype(used_atom, /obj/item/stack))
var/obj/item/stack/S = used_atom
if(S.amount < 5)
if(S.get_amount() < 5)
to_chat(user, ("<span class='warning'>There's not enough material in this stack.</span>"))
return 0
else
@@ -113,7 +113,7 @@
// STACKS
if(istype(used_atom,/obj/item/stack))
var/obj/item/stack/stack=used_atom
if(stack.amount < amount)
if(stack.get_amount() < amount)
to_chat(user, "<span class='warning'>You don't have enough [stack]! You need at least [amount].</span>")
return 0
stack.use(amount)
+12 -38
View File
@@ -1375,46 +1375,20 @@
switch(href_list["silicon"])
if("unemag")
var/mob/living/silicon/robot/R = current
if(istype(R))
R.emagged = 0
if(R.module)
if(R.activated(R.module.emag))
R.module_active = null
if(R.module_state_1 == R.module.emag)
R.module_state_1 = null
R.contents -= R.module.emag
else if(R.module_state_2 == R.module.emag)
R.module_state_2 = null
R.contents -= R.module.emag
else if(R.module_state_3 == R.module.emag)
R.module_state_3 = null
R.contents -= R.module.emag
R.clear_supplied_laws()
R.laws = new /datum/ai_laws/crewsimov
log_admin("[key_name(usr)] has un-emagged [key_name(current)]")
message_admins("[key_name_admin(usr)] has un-emagged [key_name_admin(current)]")
if(!istype(R))
return
R.unemag()
log_admin("[key_name(usr)] has un-emagged [key_name(current)]")
message_admins("[key_name_admin(usr)] has un-emagged [key_name_admin(current)]")
if("unemagcyborgs")
if(isAI(current))
var/mob/living/silicon/ai/ai = current
for(var/mob/living/silicon/robot/R in ai.connected_robots)
R.emagged = 0
if(R.module)
if(R.activated(R.module.emag))
R.module_active = null
if(R.module_state_1 == R.module.emag)
R.module_state_1 = null
R.contents -= R.module.emag
else if(R.module_state_2 == R.module.emag)
R.module_state_2 = null
R.contents -= R.module.emag
else if(R.module_state_3 == R.module.emag)
R.module_state_3 = null
R.contents -= R.module.emag
R.clear_supplied_laws()
R.laws = new /datum/ai_laws/crewsimov
log_admin("[key_name(usr)] has unemagged [key_name(ai)]'s cyborgs")
message_admins("[key_name_admin(usr)] has unemagged [key_name_admin(ai)]'s cyborgs")
if(!isAI(current))
return
var/mob/living/silicon/ai/ai = current
for(var/mob/living/silicon/robot/R in ai.connected_robots)
R.unemag()
log_admin("[key_name(usr)] has unemagged [key_name(ai)]'s cyborgs")
message_admins("[key_name_admin(usr)] has unemagged [key_name_admin(ai)]'s cyborgs")
else if(href_list["common"])
switch(href_list["common"])
+2
View File
@@ -640,6 +640,7 @@
if(istype(I))
apply_to_card(I, H, get_all_centcom_access(), name, "lifetimeid")
I.assignment = "Solar Federation Representative"
H.sec_hud_set_ID()
/datum/outfit/admin/solgov
@@ -783,6 +784,7 @@
var/obj/item/card/id/I = H.wear_id
if(istype(I))
apply_to_card(I, H, list(ACCESS_TRADE_SOL, ACCESS_MAINT_TUNNELS, ACCESS_EXTERNAL_AIRLOCKS), name)
H.sec_hud_set_ID()
/datum/outfit/admin/chrono
name = "Chrono Legionnaire"
+2 -2
View File
@@ -95,7 +95,7 @@
if((ABSTRACT in item.flags) || (NODROP in item.flags))
continue
marked_item = item
to_chat(M, "<span class='warning'>You begin to focus your very being into the [item.name]...</span>")
to_chat(M, "<span class='warning'>You begin to focus your very being into [item]...</span>")
break
if(!marked_item)
@@ -104,7 +104,7 @@
spawn(50)
if(marked_item.loc != M) //I changed my mind I don't want to put my soul in a cheeseburger!
to_chat(M, "<span class='warning'>Your soul snaps back to your body as you drop the [marked_item.name]!</span>")
to_chat(M, "<span class='warning'>Your soul snaps back to your body as you drop [marked_item]!</span>")
marked_item = null
return
name = "RISE!"
+2 -2
View File
@@ -21,7 +21,7 @@
if(!usr.mind.miming)
to_chat(usr, "<span class='notice'>You must dedicate yourself to silence first.</span>")
return
invocation = "<B>[usr.real_name]</B> looks as if a wall is in front of [usr.p_them()]."
invocation = "<B>[usr.name]</B> looks as if a wall is in front of [usr.p_them()]."
else
invocation_type ="none"
..()
@@ -86,7 +86,7 @@
if(!usr.mind.miming)
to_chat(usr, "<span class='notice'>You must dedicate yourself to silence first.</span>")
return
invocation = "<B>[usr.real_name]</B> looks as if a blockade is in front of [usr.p_them()]."
invocation = "<B>[usr.name]</B> looks as if a blockade is in front of [usr.p_them()]."
else
invocation_type ="none"
..()
+4 -4
View File
@@ -80,7 +80,7 @@
var/obj/item/organ/external/part = X
if(item_to_retrieve in part.embedded_objects)
part.embedded_objects -= item_to_retrieve
to_chat(C, "<span class='warning'>The [item_to_retrieve] that was embedded in your [part] has mysteriously vanished. How fortunate!</span>")
to_chat(C, "<span class='warning'>\The [item_to_retrieve] that was embedded in your [part] has mysteriously vanished. How fortunate!</span>")
if(!C.has_embedded_objects())
C.clear_alert("embeddedobject")
break
@@ -99,7 +99,7 @@
if(!item_to_retrieve)
return
item_to_retrieve.loc.visible_message("<span class='warning'>The [item_to_retrieve.name] suddenly disappears!</span>")
item_to_retrieve.loc.visible_message("<span class='warning'>\The [item_to_retrieve] suddenly disappears!</span>")
if(target.hand) //left active hand
@@ -112,10 +112,10 @@
butterfingers = 1
if(butterfingers)
item_to_retrieve.loc = target.loc
item_to_retrieve.loc.visible_message("<span class='caution'>The [item_to_retrieve.name] suddenly appears!</span>")
item_to_retrieve.loc.visible_message("<span class='caution'>\The [item_to_retrieve] suddenly appears!</span>")
playsound(get_turf(target),'sound/magic/summonitems_generic.ogg',50,1)
else
item_to_retrieve.loc.visible_message("<span class='caution'>The [item_to_retrieve.name] suddenly appears in [target]'s hand!</span>")
item_to_retrieve.loc.visible_message("<span class='caution'>\The [item_to_retrieve] suddenly appears in [target]'s hand!</span>")
playsound(get_turf(target),'sound/magic/summonitems_generic.ogg',50,1)
if(message)
+8
View File
@@ -935,6 +935,14 @@ GLOBAL_LIST_INIT(all_supply_groups, list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY
containername = "surgery crate"
access = ACCESS_MEDICAL
/datum/supply_packs/medical/gloves
name = "Nitrile Glove Crate"
contains = list(/obj/item/clothing/gloves/color/latex/nitrile,
/obj/item/clothing/gloves/color/latex/nitrile,
/obj/item/clothing/gloves/color/latex/nitrile,
/obj/item/clothing/gloves/color/latex/nitrile)
cost = 50
containername = "nitrile glove crate"
//////////////////////////////////////////////////////////////////////////////
//////////////////////////// Science /////////////////////////////////////////
+2 -1
View File
@@ -864,6 +864,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
reference = "CQC"
item = /obj/item/CQC_manual
cost = 13
cant_discount = TRUE
/datum/uplink_item/stealthy_weapons/cameraflash
name = "Camera Flash"
@@ -1425,7 +1426,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
name = "Power Sink"
desc = "When screwed to wiring attached to an electric grid, then activated, this large device places excessive load on the grid, causing a stationwide blackout. The sink cannot be carried because of its excessive size. Ordering this sends you a small beacon that will teleport the power sink to your location on activation."
reference = "PS"
item = /obj/item/powersink
item = /obj/item/radio/beacon/syndicate/power_sink
cost = 10
/datum/uplink_item/device_tools/singularity_beacon
+4 -5
View File
@@ -209,7 +209,7 @@
/**
* Proc called to determine if the user can see wire define information, such as "Contraband", "Door Bolts", etc.
*
* If the user is an admin, or has a multitool which reveals wire information in their active hand, the proc returns TRUE.
* If the user is an admin, or has an item which reveals wire information in their active hand, the proc returns TRUE.
*
* Arguments:
* * user - the mob who is interacting with the wires.
@@ -217,10 +217,9 @@
/datum/wires/proc/can_see_wire_info(mob/user)
if(user.can_admin_interact())
return TRUE
else if(istype(user.get_active_hand(), /obj/item/multitool))
var/obj/item/multitool/M = user.get_active_hand()
if(M.shows_wire_information)
return TRUE
var/obj/item/held_item = user.get_active_hand()
if(istype(held_item) && HAS_TRAIT(held_item, TRAIT_SHOW_WIRE_INFO))
return TRUE
return FALSE
/**
+6
View File
@@ -75,6 +75,12 @@
///Used to decide what the maximum time between ambience is
var/max_ambience_cooldown = 90 SECONDS
/area/New(loc, ...)
if(!there_can_be_many) // Has to be done in New else the maploader will fuck up and find subtypes for the parent
GLOB.all_unique_areas[type] = src
..()
/area/Initialize(mapload)
GLOB.all_areas += src
icon_state = ""
+52 -95
View File
@@ -607,53 +607,75 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
icon_state = "fpmaint"
/area/maintenance/fpmaint
name = "EVA Maintenance"
name = "Fore-Port Maintenance"
icon_state = "fpmaint"
/area/maintenance/fpmaint2
name = "Arrivals North Maintenance"
name = "Fore-Port Secondary Maintenance"
icon_state = "fpmaint"
/area/maintenance/fsmaint
name = "Dormitory Maintenance"
name = "Fore-Starboard Maintenance"
icon_state = "fsmaint"
/area/maintenance/fsmaint2
name = "Bar Maintenance"
name = "Fore-Starboard Secondary Maintenance"
icon_state = "fsmaint"
/area/maintenance/asmaint
name = "Medbay Maintenance"
name = "Aft-Starboard Maintenance"
icon_state = "asmaint"
/area/maintenance/asmaint2
name = "Science Maintenance"
name = "Aft-Starboard Secondary Maintenance"
icon_state = "asmaint"
/area/maintenance/apmaint
name = "Cargo Maintenance"
name = "Aft-Port Maintenance"
icon_state = "apmaint"
/area/maintenance/apmaint2
name = "Aft-Port Secondary Maintenance"
icon_state = "apmaint"
/area/maintenance/maintcentral
name = "Bridge Maintenance"
name = "Central Maintenance"
icon_state = "maintcentral"
/area/maintenance/maintcentral2
name = "Central Secondary Maintenance"
icon_state = "maintcentral"
/area/maintenance/fore
name = "Fore Maintenance"
icon_state = "fmaint"
/area/maintenance/fore2
name = "Fore Secondary Maintenance"
icon_state = "fmaint"
/area/maintenance/aft
name = "Aft Maintenance"
icon_state = "amaint"
/area/maintenance/aft2
name = "Aft Secondary Maintenance"
icon_state = "amaint"
/area/maintenance/starboard
name = "Starboard Maintenance"
icon_state = "smaint"
/area/maintenance/starboard2
name = "Starboard Secondary Maintenance"
icon_state = "smaint"
/area/maintenance/port
name = "Locker Room Maintenance"
name = "Port Maintenance"
icon_state = "pmaint"
/area/maintenance/aft
name = "Engineering Maintenance"
icon_state = "amaint"
/area/maintenance/port2
name = "Port Secondary Maintenance"
icon_state = "pmaint"
/area/maintenance/storage
name = "Atmospherics Maintenance"
icon_state = "green"
@@ -677,18 +699,18 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/maintenance/electrical
name = "Electrical Maintenance"
icon_state = "yellow"
icon_state = "elec"
/area/maintenance/abandonedbar
name = "Maintenance Bar"
icon_state = "yellow"
icon_state = "oldbar"
power_equip = 0
power_light = 0
power_environ = 0
/area/maintenance/electrical_shop
name ="Electronics Den"
icon_state = "yellow"
icon_state = "elec"
/area/maintenance/gambling_den
name = "Gambling Den"
@@ -696,7 +718,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/maintenance/consarea
name = "Alternate Construction Area"
icon_state = "yellow"
icon_state = "construction"
//Hallway
@@ -836,7 +858,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/comms
name = "\improper Communications Relay"
icon_state = "tcomsatcham"
icon_state = "tcomms"
sound_environment = SOUND_AREA_STANDARD_STATION
/area/server
@@ -846,11 +868,11 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/ntrep
name = "\improper Nanotrasen Representative's Office"
icon_state = "bluenew"
icon_state = "ntrep"
/area/blueshield
name = "\improper Blueshield's Office"
icon_state = "blueold"
icon_state = "blueshield"
/area/centcomdocks
name = "\improper Central Command Docks"
@@ -919,7 +941,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/crew_quarters/bar
name = "\improper Bar"
icon_state = "bar"
icon_state = "barstation"
sound_environment = SOUND_AREA_WOODFLOOR
/area/crew_quarters/bar/atrium
@@ -1048,45 +1070,6 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/holodeck/source_knightarena
name = "\improper Holodeck - Knight Arena"
//Embassies
/area/embassy/
name = "\improper Embassy Hallway"
/area/embassy/tajaran
name = "\improper Tajaran Embassy"
icon_state = "tajaran"
/area/embassy/skrell
name = "\improper Skrell Embassy"
icon_state = "skrell"
/area/embassy/unathi
name = "\improper Unathi Embassy"
icon_state = "unathi"
/area/embassy/kidan
name = "\improper Kidan Embassy"
icon_state = "kidan"
/area/embassy/diona
name = "\improper Diona Embassy"
icon_state = "diona"
/area/embassy/slime
name = "\improper Slime Person Embassy"
icon_state = "slime"
/area/embassy/grey
name = "\improper Grey Embassy"
icon_state = "grey"
/area/embassy/vox
name = "\improper Vox Embassy"
icon_state = "vox"
//Engineering
/area/engine
ambientsounds = ENGINEERING_SOUNDS
@@ -1310,15 +1293,11 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/medical/robotics
name = "Robotics"
icon_state = "medresearch"
icon_state = "research"
/area/medical/research
name = "Medical Research"
icon_state = "medresearch"
/area/medical/research_shuttle_dock
name = "\improper Research Shuttle Dock"
icon_state = "medresearch"
name = "Research Division"
icon_state = "research"
/area/medical/virology
name = "Virology"
@@ -1459,10 +1438,6 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "Security Equipment Storage"
icon_state = "securityequipmentstorage"
/area/security/interrogationhallway
name = "\improper Interrogation Hallway"
icon_state = "interrogationhall"
/area/security/courtroomdandp
name = "\improper Courtroom Defense and Prosecution"
icon_state = "seccourt"
@@ -1505,7 +1480,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
icon_state = "secarmory"
/area/security/securehallway
name = "\improper Security Secure Hallway"
name = "\improper Brig Secure Hallway"
icon_state = "securehall"
/area/security/hos
@@ -2061,45 +2036,27 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/tcommsat/chamber
name = "\improper Telecoms Central Compartment"
icon_state = "tcomsatcham"
icon_state = "tcomms"
// These areas are needed for MetaStation's AI sat
/area/turret_protected/tcomsat
name = "\improper Telecoms Satellite"
icon_state = "tcomsatlob"
ambientsounds = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg')
/area/turret_protected/tcomfoyer
name = "\improper Telecoms Foyer"
icon_state = "tcomsatentrance"
ambientsounds = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg')
/area/turret_protected/tcomwest
name = "\improper Telecoms West Wing"
icon_state = "tcomsatwest"
icon_state = "tcomms"
ambientsounds = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg')
/area/turret_protected/tcomeast
name = "\improper Telecoms East Wing"
icon_state = "tcomsateast"
icon_state = "tcomms"
ambientsounds = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg')
/area/tcommsat/computer
name = "\improper Telecoms Control Room"
icon_state = "tcomsatcomp"
icon_state = "tcomms"
sound_environment = SOUND_AREA_MEDIUM_SOFTFLOOR
/area/tcommsat/server
name = "\improper Telecoms Server Room"
icon_state = "tcomsatcham"
/area/tcommsat/lounge
name = "\improper Telecoms Lounge"
icon_state = "tcomsatlounge"
/area/tcommsat/powercontrol
name = "\improper Telecoms Power Control"
icon_state = "tcomsatwest"
icon_state = "tcomms"
// Away Missions
/area/awaymission
+4 -4
View File
@@ -413,6 +413,9 @@
/atom/proc/emag_act()
return
/atom/proc/unemag()
return
/**
* Respond to a radioactive wave hitting this atom
*
@@ -941,9 +944,6 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
/atom/proc/narsie_act()
return
/atom/proc/ratvar_act()
return
/**
* Respond to an electric bolt action on our item
*
@@ -1072,7 +1072,7 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
Returning TRUE here will override the above proc's result.
*/
/atom/proc/CanAStarPassTo(ID, dir, obj/destination)
return TRUE
return FALSE
/** Call this when you want to present a renaming prompt to the user.
+2 -4
View File
@@ -178,12 +178,10 @@
/mob/living/carbon/med_hud_set_status()
var/image/holder = hud_list[STATUS_HUD]
var/mob/living/simple_animal/borer/B = has_brain_worms()
var/dead = stat == DEAD || HAS_TRAIT(src, TRAIT_FAKEDEATH)
// To the right of health bar
if(dead)
var/mob/dead/observer/ghost = get_ghost(TRUE)
if(stat == DEAD || HAS_TRAIT(src, TRAIT_FAKEDEATH))
var/revivable
if(ghost && !ghost.can_reenter_corpse) // DNR or AntagHUD
if(!ghost_can_reenter()) // DNR or AntagHUD
revivable = FALSE
else if(timeofdeath && (round(world.time - timeofdeath) < DEFIB_TIME_LIMIT))
revivable = TRUE
+7 -7
View File
@@ -150,16 +150,16 @@
if(usr.incapacitated() || usr.buckled) //are you cuffed, dying, lying, stunned or other
return
if(!ishuman(usr)) //Make sure they're a mob that has dna
to_chat(usr, "<span class='notice'>Try as you might, you can not climb up into the [src].</span>")
to_chat(usr, "<span class='notice'>Try as you might, you can not climb up into [src].</span>")
return
if(occupant)
to_chat(usr, "<span class='boldnotice'>The [src] is already occupied!</span>")
to_chat(usr, "<span class='boldnotice'>[src] is already occupied!</span>")
return
if(usr.abiotic())
to_chat(usr, "<span class='boldnotice'>Subject cannot have abiotic items on.</span>")
return
if(usr.has_buckled_mobs()) //mob attached to us
to_chat(usr, "<span class='warning'>[usr] will not fit into the [src] because [usr.p_they()] [usr.p_have()] a slime latched onto [usr.p_their()] head.</span>")
to_chat(usr, "<span class='warning'>[usr] will not fit into [src] because [usr.p_they()] [usr.p_have()] a slime latched onto [usr.p_their()] head.</span>")
return
usr.stop_pulling()
usr.forceMove(src)
@@ -188,7 +188,7 @@
if(!istype(user.loc, /turf) || !istype(O.loc, /turf)) // are you in a container/closet/pod/etc?
return
if(occupant)
to_chat(user, "<span class='boldnotice'>The [src] is already occupied!</span>")
to_chat(user, "<span class='boldnotice'>[src] is already occupied!</span>")
return
var/mob/living/L = O
if(!istype(L) || L.buckled)
@@ -200,9 +200,9 @@
to_chat(user, "<span class='warning'>[L] will not fit into [src] because [L.p_they()] [L.p_have()] a slime latched onto [L.p_their()] head.</span>")
return
if(L == user)
visible_message("[user] climbs into the [src].")
visible_message("<span class='notice'>[user] climbs into [src].</span>")
else
visible_message("[user] puts [L.name] into the [src].")
visible_message("<span class='notice'>[user] puts [L.name] into [src].</span>")
put_in(L)
if(user.pulling == L)
user.stop_pulling()
@@ -235,7 +235,7 @@
to_chat(user, "<span class='boldnotice'>Subject cannot have abiotic items on.</span>")
return
if(G.affecting.has_buckled_mobs()) //mob attached to us
to_chat(user, "<span class='warning'>will not fit into the [src] because [G.affecting.p_they()] [G.affecting.p_have()] a slime latched onto [G.affecting.p_their()] head.</span>")
to_chat(user, "<span class='warning'>[G] will not fit into [src] because [G.affecting.p_they()] [G.affecting.p_have()] a slime latched onto [G.affecting.p_their()] head.</span>")
return
if(panel_open)
to_chat(usr, "<span class='boldnotice'>Close the maintenance panel first.</span>")
+2 -2
View File
@@ -80,7 +80,7 @@
/datum/mutation/noprints
name = "No Prints"
activation_messages = list("Your fingers feel numb.")
deactivation_messages = list("your fingers no longer feel numb.")
deactivation_messages = list("Your fingers no longer feel numb.")
instability = GENE_INSTABILITY_MINOR
traits_to_add = list(TRAIT_NOFINGERPRINTS)
@@ -161,7 +161,7 @@
/datum/mutation/xray
name = "X-Ray Vision"
activation_messages = list("The walls suddenly disappear.")
deactivation_messages = list("the walls around you re-appear.")
deactivation_messages = list("The walls around you re-appear.")
instability = GENE_INSTABILITY_MAJOR
traits_to_add = list(TRAIT_XRAY_VISION)
activation_prob = 15
+6 -20
View File
@@ -15,7 +15,6 @@ GLOBAL_LIST_EMPTY(blob_nodes)
recommended_enemies = 1
restricted_jobs = list("Cyborg", "AI")
var/declared = 0
var/burst = 0
var/cores_to_spawn = 1
@@ -75,8 +74,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
log_game("[key_name(blob)] has been selected as a Blob")
greet_blob(blobmind)
to_chat(blob, "<span class='userdanger'>You feel very tired and bloated! You don't have long before you burst!</span>")
spawn(600)
burst_blob(blobmind)
addtimer(CALLBACK(src, .proc/burst_blob, blobmind), 60 SECONDS)
return 1
/datum/game_mode/blob/proc/make_blobs(count)
@@ -128,8 +126,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
if(!warned)
to_chat(C, "<span class='userdanger'>You feel ready to burst, but this isn't an appropriate place! You must return to the station!</span>")
message_admins("[key_name_admin(C)] was in space when the blobs burst, and will die if [C.p_they()] [C.p_do()] not return to the station.")
spawn(300)
burst_blob(blob, 1)
addtimer(CALLBACK(src, .proc/burst_blob, blob, 1), 30 SECONDS)
else
burst++
log_admin("[key_name(C)] was in space when attempting to burst as a blob.")
@@ -173,33 +170,22 @@ GLOBAL_LIST_EMPTY(blob_nodes)
show_message("<span class='userdanger'>You feel like you are about to burst.</span>")
sleep(wait_time / 2)
burst_blobs()
// Stage 0
sleep(wait_time)
stage(0)
addtimer(CALLBACK(src, .proc/burst_blobs), (wait_time / 2))
// Stage 1
sleep(wait_time)
stage(1)
addtimer(CALLBACK(src, .proc/stage, 1), (wait_time * 2 + wait_time / 2))
// Stage 2
sleep(30000)
stage(2)
addtimer(CALLBACK(src, .proc/stage, 2), 50 MINUTES)
return ..()
/datum/game_mode/blob/proc/stage(stage)
switch(stage)
if(0)
send_intercept(1)
declared = 1
if(1)
GLOB.event_announcement.Announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/AI/outbreak5.ogg')
if(2)
send_intercept(2)
send_intercept(1)
/datum/game_mode/proc/update_blob_icons_added(datum/mind/mob_mind)
var/datum/atom_hud/antag/antaghud = GLOB.huds[ANTAG_HUD_BLOB]
-1
View File
@@ -26,7 +26,6 @@
to_chat(world, "<FONT size = 3><B>The staff has won!</B></FONT>")
to_chat(world, "<B>The alien organism has been eradicated from the station</B>")
log_game("Blob mode completed with a crew victory.")
to_chat(world, "<span class='notice'>Rebooting in 30s</span>")
..()
return 1
-13
View File
@@ -5,19 +5,6 @@
if(0)
return
if(1)
interceptname = "Level 5-6 Biohazard Response Procedures"
intercepttext += "<FONT size = 3><B>Nanotrasen Update</B>: Biohazard Alert.</FONT><HR>"
intercepttext += "Reports indicate the probable transfer of a biohazardous agent onto [station_name()] during the last crew deployment cycle.<BR>"
intercepttext += "Preliminary analysis of the organism classifies it as a level 5 biohazard. Its origin is unknown.<BR>"
intercepttext += "Nanotrasen has issued a directive 7-10 for [station_name()]. The station is to be considered quarantined.<BR>"
intercepttext += "Orders for all [station_name()] personnel follows:<BR>"
intercepttext += " 1. Do not leave the quarantine area.<BR>"
intercepttext += " 2. Locate any outbreaks of the organism on the station.<BR>"
intercepttext += " 3. If found, use any neccesary means to contain the organism.<BR>"
intercepttext += " 4. Avoid damage to the capital infrastructure of the station.<BR>"
intercepttext += "<BR>Note in the event of a quarantine breach or uncontrolled spread of the biohazard, the directive 7-10 may be upgraded to a directive 7-12.<BR>"
intercepttext += "Message ends."
if(2)
var/nukecode = rand(10000, 99999)
for(var/obj/machinery/nuclearbomb/bomb in GLOB.machines)
if(bomb && bomb.r_code)
@@ -49,7 +49,7 @@
to_chat(user, "<span class='notice'>We stealthily stab [target] with a minor proboscis...</span>")
to_chat(target, "<span class='userdanger'>You experience a stabbing sensation and your ears begin to ring...</span>")
if(3)
to_chat(user, "<span class='notice'>You mold the [target]'s mind like clay, [target.p_they()] can now speak in the hivemind!</span>")
to_chat(user, "<span class='notice'>You mold [target]'s mind like clay, [target.p_they()] can now speak in the hivemind!</span>")
to_chat(target, "<span class='userdanger'>A migraine throbs behind your eyes, you hear yourself screaming - but your mouth has not opened!</span>")
for(var/mob/M in GLOB.mob_list)
if(GLOB.all_languages["Changeling"] in M.languages)
@@ -38,7 +38,7 @@
/datum/action/changeling/weapon/sting_action(mob/user)
if(!user.drop_item())
to_chat(user, "The [user.get_active_hand()] is stuck to your hand, you cannot grow a [weapon_name_simple] over it!")
to_chat(user, "[user.get_active_hand()] is stuck to your hand, you cannot grow a [weapon_name_simple] over it!")
return
var/obj/item/W = new weapon_type(user, silent)
user.put_in_hands(W)
@@ -173,8 +173,11 @@
name = "Tentacle"
desc = "We ready a tentacle to grab items or victims with. Costs 10 chemicals."
helptext = "We can use it once to retrieve a distant item. If used on living creatures, the effect depends on the intent: \
Help will simply drag them closer, Disarm will grab whatever they are holding instead of them, Grab will put the victim in our hold after catching it, \
and Harm will stun it, and stab it if we are also holding a sharp weapon. Cannot be used while in lesser form."
Help will drag the target closer. \
Disarm will grab whatever the target is holding. \
Grab will put the target in our grip after we catch it. \
Harm will drag the target closer and stab it if we are holding a sharp weapon in our other hand. \
Cannot be used while in our lesser form."
button_icon_state = "tentacle"
chemical_cost = 10
dna_cost = 2
@@ -209,7 +212,7 @@
to_chat(loc, "<span class='notice'>You prepare to extend a tentacle.</span>")
/obj/item/gun/magic/tentacle/shoot_with_empty_chamber(mob/living/user as mob|obj)
to_chat(user, "<span class='warning'>The [name] is not ready yet.</span>")
to_chat(user, "<span class='warning'>[src] is not ready yet.</span>")
/obj/item/gun/magic/tentacle/suicide_act(mob/user)
user.visible_message("<span class='suicide'>[user] coils [src] tightly around [user.p_their()] neck! It looks like [user.p_theyre()] trying to commit suicide.</span>")
@@ -195,6 +195,7 @@
GLOBAL_LIST_INIT(blacklisted_pylon_turfs, typecacheof(list(
/turf/simulated/floor/engine/cult,
/turf/space,
/turf/simulated/wall/indestructible,
/turf/simulated/floor/plating/lava,
/turf/simulated/floor/chasm,
/turf/simulated/wall/cult,
+8 -3
View File
@@ -366,6 +366,7 @@ structure_check() searches for nearby cultist structures required for the invoca
return
var/sacrifice_fulfilled
var/worthless = FALSE
var/datum/game_mode/gamemode = SSticker.mode
if(offering.mind)
GLOB.sacrificed += offering.mind
@@ -379,13 +380,16 @@ structure_check() searches for nearby cultist structures required for the invoca
if(sacrifice_fulfilled)
to_chat(M, "<span class='cultlarge'>\"Yes! This is the one I desire! You have done well.\"</span>")
else
if(ishuman(offering) || isrobot(offering))
if(ishuman(offering) && offering.mind.offstation_role && offering.mind.special_role != SPECIAL_ROLE_ERT) //If you try it on a ghost role, you get nothing
to_chat(M, "<span class='cultlarge'>\"This soul is of no use to either of us.\"</span>")
worthless = TRUE
else if(ishuman(offering) || isrobot(offering))
to_chat(M, "<span class='cultlarge'>\"I accept this sacrifice.\"</span>")
else
to_chat(M, "<span class='cultlarge'>\"I accept this meager sacrifice.\"</span>")
playsound(offering, 'sound/misc/demon_consume.ogg', 100, TRUE)
if((ishuman(offering) || isrobot(offering) || isbrain(offering)) && offering.mind)
if(((ishuman(offering) || isrobot(offering) || isbrain(offering)) && offering.mind) && !worthless)
var/obj/item/soulstone/stone = new /obj/item/soulstone(get_turf(src))
stone.invisibility = INVISIBILITY_MAXIMUM // So it's not picked up during transfer_soul()
stone.transfer_soul("FORCE", offering, user) // If it cannot be added
@@ -591,7 +595,8 @@ structure_check() searches for nearby cultist structures required for the invoca
return
sacrifices_used += SOULS_TO_REVIVE
mob_to_revive.revive()
mob_to_revive.grab_ghost()
if(mob_to_revive.ghost_can_reenter())
mob_to_revive.grab_ghost()
if(!mob_to_revive.client || mob_to_revive.client.is_afk())
set waitfor = FALSE
@@ -30,7 +30,7 @@
if(target.has_buckled_mobs()) //mob attached to us
to_chat(user, "<span class='warning'>[target] will not fit into [src] because [target.p_they()] [target.p_have()] a slime latched onto [target.p_their()] head.</span>")
return
visible_message("[user] puts [target] into the [src].")
visible_message("<span class='notice'>[user] puts [target] into [src].</span>")
target.forceMove(src)
occupant = target
@@ -187,12 +187,12 @@
if(isabductor(grabbed.affecting))
return
if(occupant)
to_chat(user, "<span class='notice'>The [src] is already occupied!</span>")
to_chat(user, "<span class='notice'>[src] is already occupied!</span>")
return
if(grabbed.affecting.has_buckled_mobs()) //mob attached to us
to_chat(user, "<span class='warning'>[grabbed.affecting] will not fit into [src] because [grabbed.affecting.p_they()] [grabbed.affecting.p_have()] a slime latched onto [grabbed.affecting.p_their()] head.</span>")
return
visible_message("[user] puts [grabbed.affecting] into the [src].")
visible_message("<span class='notice'>[user] puts [grabbed.affecting] into [src].</span>")
var/mob/living/carbon/human/H = grabbed.affecting
H.forceMove(src)
occupant = H
@@ -332,6 +332,14 @@
to_chat(S, "<span class='warning'>An inhospitable area may be created as a result of destroying this object. Aborting.</span>")
return FALSE
/obj/structure/fans/tiny/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>An inhospitable area may be created as a result of destroying this object. Aborting.</span>")
return FALSE
/obj/structure/holosign/barrier/atmos/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>An inhospitable area may be created as a result of destroying this object. Aborting.</span>")
return FALSE
/obj/machinery/tcomms/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>This communications relay should be preserved, it will be a useful resource to our masters in the future. Aborting.</span>")
return FALSE
@@ -63,7 +63,7 @@
/obj/item/guardian_bomb/proc/detonate(mob/living/user)
if(!istype(user))
return
to_chat(user, "<span class='danger'>The [src] was boobytrapped!</span>")
to_chat(user, "<span class='danger'>[src] was boobytrapped!</span>")
if(istype(spawner, /mob/living/simple_animal/hostile/guardian))
var/mob/living/simple_animal/hostile/guardian/G = spawner
if(user == G.summoner)
@@ -94,7 +94,7 @@
F.icon = 'icons/turf/floors.dmi'
F.name = "bluespace recieving pad"
F.desc = "A recieving zone for bluespace teleportations. Building a wall over it should disable it."
F.icon_state = "light_on-w"
F.icon_state = "light_on"
to_chat(src, "<span class='danger'>Beacon placed! You may now warp targets to it, including your user, via Alt+Click. </span>")
if(beacon)
beacon.ChangeTurf(/turf/simulated/floor/plating)
+18 -13
View File
@@ -108,18 +108,23 @@
var/agent_number = 1
var/spawnpos = 1
var/obj/machinery/nuclearbomb/syndicate/the_bomb
if(nuke_spawn && length(synd_spawn))
the_bomb = new /obj/machinery/nuclearbomb/syndicate(nuke_spawn.loc)
the_bomb.r_code = nuke_code
for(var/datum/mind/synd_mind in syndicates)
if(spawnpos > synd_spawn.len)
spawnpos = 2
synd_mind.current.loc = synd_spawn[spawnpos]
synd_mind.offstation_role = TRUE
forge_syndicate_objectives(synd_mind)
create_syndicate(synd_mind)
create_syndicate(synd_mind, the_bomb)
greet_syndicate(synd_mind)
equip_syndicate(synd_mind.current)
if(!leader_selected)
prepare_syndicate_leader(synd_mind, nuke_code)
prepare_syndicate_leader(synd_mind, the_bomb)
leader_selected = 1
else
synd_mind.current.real_name = "[syndicate_name()] Operative #[agent_number]"
@@ -131,9 +136,6 @@
scale_telecrystals()
share_telecrystals()
if(nuke_spawn && synd_spawn.len > 0)
var/obj/machinery/nuclearbomb/syndicate/the_bomb = new /obj/machinery/nuclearbomb/syndicate(nuke_spawn.loc)
the_bomb.r_code = nuke_code
return ..()
@@ -160,7 +162,7 @@
U.hidden_uplink.uses++
remainder--
/datum/game_mode/proc/create_syndicate(datum/mind/synd_mind) // So we don't have inferior species as ops - randomize a human
/datum/game_mode/proc/create_syndicate(datum/mind/synd_mind, obj/machinery/nuclearbomb/syndicate/the_bomb) // So we don't have inferior species as ops - randomize a human
var/mob/living/carbon/human/M = synd_mind.current
M.set_species(/datum/species/human, TRUE)
@@ -186,7 +188,14 @@
M.regenerate_icons()
M.update_body()
/datum/game_mode/proc/prepare_syndicate_leader(datum/mind/synd_mind, nuke_code)
if(!the_bomb)
the_bomb = locate(/obj/machinery/nuclearbomb/syndicate) in GLOB.poi_list
if(the_bomb)
synd_mind.store_memory("<B>Syndicate [the_bomb.name] Code</B>: [the_bomb.r_code]")
to_chat(synd_mind.current, "The code for \the [the_bomb.name] is: <B>[the_bomb.r_code]</B>")
/datum/game_mode/proc/prepare_syndicate_leader(datum/mind/synd_mind, obj/machinery/nuclearbomb/syndicate/the_bomb)
var/leader_title = pick("Czar", "Boss", "Commander", "Chief", "Kingpin", "Director", "Overlord")
synd_mind.current.real_name = "[syndicate_name()] Team [leader_title]"
to_chat(synd_mind.current, "<B>You are the Syndicate leader for this mission. You are responsible for the distribution of telecrystals and your ID is the only one who can open the launch bay doors.</B>")
@@ -198,11 +207,9 @@
update_syndicate_id(synd_mind, leader_title, TRUE)
if(nuke_code)
synd_mind.store_memory("<B>Syndicate Nuclear Bomb Code</B>: [nuke_code]", 0, 0)
to_chat(synd_mind.current, "The nuclear authorization code is: <B>[nuke_code]</B>")
if(the_bomb)
var/obj/item/paper/P = new
P.info = "The nuclear authorization code is: <b>[nuke_code]</b>"
P.info = "The code for \the [the_bomb.name] is: <B>[the_bomb.r_code]</B>"
P.name = "nuclear bomb code"
var/obj/item/stamp/syndicate/stamp = new
P.stamp(stamp)
@@ -216,8 +223,6 @@
H.equip_to_slot_or_del(P, slot_r_store, 0)
H.update_icons()
else
nuke_code = "code will be provided later"
/datum/game_mode/proc/update_syndicate_id(datum/mind/synd_mind, is_leader = FALSE)
var/list/found_ids = synd_mind.current.search_contents_for(/obj/item/card/id)
@@ -55,6 +55,7 @@
for(var/obj/machinery/computer/shuttle/syndicate/S in GLOB.machines)
S.challenge = TRUE
S.challenge_time = world.time
// No. of player - Min. Player to dec, divided by player per bonus, then multipled by TC per bonus. Rounded.
total_tc = CHALLENGE_TELECRYSTALS + round((((GLOB.player_list.len - CHALLENGE_MIN_PLAYERS)/CHALLENGE_SCALE_PLAYER) * CHALLENGE_SCALE_BONUS))
+3 -3
View File
@@ -465,7 +465,7 @@ GLOBAL_VAR(bomb_set)
else if(off_station == 2)
to_chat(world, "<b>A nuclear device was set off, but the device was not on the station!</b>")
else
to_chat(world, "<b>The station was destoyed by the nuclear blast!</b>")
to_chat(world, "<b>The station was destroyed by the nuclear blast!</b>")
SSticker.mode.station_was_nuked = (off_station < 2) //offstation==1 is a draw. the station becomes irradiated and needs to be evacuated.
//kinda shit but I couldn't get permission to do what I wanted to do.
@@ -483,12 +483,12 @@ GLOBAL_VAR(bomb_set)
if(safety == 1)
if(!is_syndicate)
set_security_level(previous_level)
visible_message("<span class='notice'>The [src] quiets down.</span>")
visible_message("<span class='notice'>[src] quiets down.</span>")
if(!lighthack)
if(icon_state == "nuclearbomb2")
icon_state = "nuclearbomb1"
else
visible_message("<span class='notice'>The [src] emits a quiet whirling noise!</span>")
visible_message("<span class='notice'>[src] emits a quiet whirling noise!</span>")
//==========DAT FUKKEN DISK===============
/obj/item/disk/nuclear
@@ -513,7 +513,7 @@
target_apc.operating = 0
target_apc.update()
target_apc.update_icon()
target_apc.visible_message("<span class='warning'>The [target_apc] flickers and begins to grow dark.</span>")
target_apc.visible_message("<span class='warning'>[target_apc] flickers and begins to grow dark.</span>")
to_chat(user, "<span class='shadowling'>You dim the APC's screen and carefully begin siphoning its power into the void.</span>")
if(!do_after(user, 200, target=target_apc))
@@ -522,7 +522,7 @@
target_apc.operating = 1
target_apc.update()
target_apc.update_icon()
target_apc.visible_message("<span class='warning'>The [target_apc] begins glowing brightly!</span>")
target_apc.visible_message("<span class='warning'>[target_apc] begins glowing brightly!</span>")
else
//We did it!
to_chat(user, "<span class='shadowling'>You sent the APC's power to the void while overloading all it's lights!</span>")
+1 -1
View File
@@ -290,7 +290,7 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha
draining = null
return
add_attack_logs(owner, H, "vampirebit & is draining their blood.", ATKLOG_ALMOSTALL)
owner.visible_message("<span class='danger'>[owner] grabs [H]'s neck harshly and sinks in [owner.p_their()] fangs!</span>", "<span class='danger'>You sink your fangs into [H] and begin to drain [owner.p_their()] blood.</span>", "<span class='notice'>You hear a soft puncture and a wet sucking noise.</span>")
owner.visible_message("<span class='danger'>[owner] grabs [H]'s neck harshly and sinks in [owner.p_their()] fangs!</span>", "<span class='danger'>You sink your fangs into [H] and begin to drain [H.p_their()] blood.</span>", "<span class='notice'>You hear a soft puncture and a wet sucking noise.</span>")
if(!iscarbon(owner))
H.LAssailant = null
else
@@ -9,6 +9,7 @@
action_background_icon_state = "bg_vampire"
var/required_blood = 0
var/gain_desc = null
var/deduct_blood_on_cast = TRUE //Do we want to take the blood when this is cast, or at a later point?
/obj/effect/proc_holder/spell/vampire/New()
..()
@@ -99,6 +100,8 @@
var/datum/vampire/vampire = usr.mind.vampire
if(required_blood <= vampire.bloodusable)
if(!deduct_blood_on_cast) //don't take the blood yet if this is false!
return
vampire.bloodusable -= required_blood
else
// stop!!
@@ -288,8 +291,10 @@
gain_desc = "You have gained the Enthrall ability which at a heavy blood cost allows you to enslave a human that is not loyal to any other for a random period of time."
action_icon_state = "vampire_enthrall"
required_blood = 300
deduct_blood_on_cast = FALSE
/obj/effect/proc_holder/spell/vampire/targetted/enthrall/cast(list/targets, mob/user = usr)
var/datum/vampire/vampire = user.mind.vampire
for(var/mob/living/target in targets)
user.visible_message("<span class='warning'>[user] bites [target]'s neck!</span>", "<span class='warning'>You bite [target]'s neck and begin the flow of power.</span>")
to_chat(target, "<span class='warning'>You feel the tendrils of evil invade your mind.</span>")
@@ -299,6 +304,7 @@
if(do_mob(user, target, 50))
if(can_enthrall(user, target))
handle_enthrall(user, target)
vampire.bloodusable -= required_blood //we take the blood after enthralling, not before
else
revert_cast(user)
to_chat(user, "<span class='warning'>You or your target either moved or you dont have enough usable blood.</span>")
+3 -3
View File
@@ -57,7 +57,7 @@
new /obj/effect/particle_effect/smoke(H.loc)
var/mob/living/carbon/human/M = new/mob/living/carbon/human(H.loc)
M.key = C.key
to_chat(M, "<B>You are the [H.real_name]'s apprentice! You are bound by magic contract to follow [H.p_their()] orders and help [H.p_them()] in accomplishing their goals.")
to_chat(M, "<B>You are [H.real_name]'s apprentice! You are bound by magic contract to follow [H.p_their()] orders and help [H.p_them()] in accomplishing their goals.")
switch(href_list["school"])
if("destruction")
M.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/projectile/magic_missile(null))
@@ -293,7 +293,7 @@ GLOBAL_LIST_EMPTY(multiverse)
/obj/item/multisword/attack(mob/living/M as mob, mob/living/user as mob) //to prevent accidental friendly fire or out and out grief.
if(M.real_name == user.real_name)
to_chat(user, "<span class='warning'>The [src] detects benevolent energies in your target and redirects your attack!</span>")
to_chat(user, "<span class='warning'>[src] detects benevolent energies in your target and redirects your attack!</span>")
return
..()
@@ -856,7 +856,7 @@ GLOBAL_LIST_EMPTY(multiverse)
if(link)
target = null
link.loc = get_turf(src)
to_chat(user, "<span class='notice'>You remove the [link] from the doll.</span>")
to_chat(user, "<span class='notice'>You remove [link] from the doll.</span>")
link = null
update_targets()
return
+19 -13
View File
@@ -95,6 +95,10 @@
to_chat(user, "<span class='cultlarge'>\"Come now, do not capture your fellow's soul.\"</span>")
return ..()
if(M.mind.offstation_role && M.mind.special_role != SPECIAL_ROLE_ERT)
to_chat(user, "<span class='warning'>This being's soul seems worthless. Not even the stone will absorb it.</span>")
return ..()
if(optional)
if(!M.ckey)
to_chat(user, "<span class='warning'>They have no soul!</span>")
@@ -253,17 +257,18 @@
return ..()
////////////////////////////Proc for moving soul in and out off stone//////////////////////////////////////
// this whole proc is pain
/obj/item/soulstone/proc/transfer_soul(choice, target, mob/user)
switch(choice)
if("FORCE")
var/mob/living/T = target
if(T.client != null)
T.grab_ghost(FALSE) // If they haven't DC'd or ahudded, put them back in their body
if(T.client) // If there's someone in the body
init_shade(T, user)
else
else // Poll ghosts
to_chat(user, "<span class='userdanger'>Capture failed!</span> The soul has already fled its mortal frame. You attempt to bring it back...")
T.Paralyse(20)
if(!get_cult_ghost(T, user))
if(!get_cult_ghost(T, user, TRUE))
T.dust() //If we can't get a ghost, kill the sacrifice anyway.
if("VICTIM")
@@ -276,7 +281,7 @@
else
if(T.client == null)
to_chat(user, "<span class='userdanger'>Capture failed!</span> The soul has already fled its mortal frame. You attempt to bring it back...")
get_cult_ghost(T, user)
get_cult_ghost(T, user, get_new_player = !T.ghost_can_reenter())
else
if(length(contents))
to_chat(user, "<span class='danger'>Capture failed!</span> The soul stone is full! Use or free an existing soul to make room.")
@@ -312,9 +317,9 @@
"Wraith" = /mob/living/simple_animal/hostile/construct/wraith,
"Artificer" = /mob/living/simple_animal/hostile/construct/builder)
/// Custom construct icons for different cults
var/list/construct_icons = list("Juggernaut" = image(icon = 'icons/mob/mob.dmi', icon_state = SSticker.cultdat.get_icon("juggernaut")),
"Wraith" = image(icon = 'icons/mob/mob.dmi', icon_state = SSticker.cultdat.get_icon("wraith")),
"Artificer" = image(icon = 'icons/mob/mob.dmi', icon_state = SSticker.cultdat.get_icon("builder")))
var/list/construct_icons = list("Juggernaut" = image(icon = 'icons/mob/cult.dmi', icon_state = SSticker.cultdat.get_icon("juggernaut")),
"Wraith" = image(icon = 'icons/mob/cult.dmi', icon_state = SSticker.cultdat.get_icon("wraith")),
"Artificer" = image(icon = 'icons/mob/cult.dmi', icon_state = SSticker.cultdat.get_icon("builder")))
if(shade)
var/construct_choice = show_radial_menu(user, shell, construct_icons, custom_check = CALLBACK(src, .proc/radial_check, user), require_near = TRUE)
@@ -413,13 +418,14 @@
return /mob/living/simple_animal/shade/holy
return /mob/living/simple_animal/shade/cult
/obj/item/soulstone/proc/get_cult_ghost(mob/living/M, mob/user)
/obj/item/soulstone/proc/get_cult_ghost(mob/living/M, mob/user, get_new_player = FALSE)
var/mob/dead/observer/chosen_ghost
for(var/mob/dead/observer/ghost in GLOB.player_list) // We put them back in their body
if(ghost.mind && ghost.mind.current == M && ghost.client)
chosen_ghost = ghost
break
if(!get_new_player)
for(var/mob/dead/observer/ghost in GLOB.player_list) // We put them back in their body
if(ghost.mind && ghost.mind.current == M && ghost.client)
chosen_ghost = ghost
break
if(!chosen_ghost) // Failing that, we grab a ghost
var/list/consenting_candidates
+1 -1
View File
@@ -783,7 +783,7 @@
owner = user
return
if(user != owner)
to_chat(user, "<span class='warning'>The [name] does not recognize you as it's owner and refuses to open!</span>")
to_chat(user, "<span class='warning'>[src] does not recognize you as it's owner and refuses to open!</span>")
return
user.set_machine(src)
var/dat = ""
+2 -2
View File
@@ -104,7 +104,7 @@
storedpda.desc = colorlist[P]
else
to_chat(user, "<span class='notice'>The [src] is empty.</span>")
to_chat(user, "<span class='notice'>[src] is empty.</span>")
/obj/machinery/pdapainter/verb/ejectpda()
@@ -120,7 +120,7 @@
storedpda = null
update_icon()
else
to_chat(usr, "<span class='notice'>The [src] is empty.</span>")
to_chat(usr, "<span class='notice'>[src] is empty.</span>")
/obj/machinery/pdapainter/power_change()
+1 -1
View File
@@ -481,7 +481,7 @@
if(unknown_body || e.hidden)
imp += "Unknown body present:"
if(!AN && !open && !infected & !imp)
if(!AN && !open && !infected && !imp)
AN = "None:"
dat += "<td>[e.name]</td><td>[e.burn_dam]</td><td>[e.brute_dam]</td><td>[robot][bled][AN][splint][open][infected][imp][internal_bleeding][lung_ruptured][dead]</td>"
dat += "</tr>"
+1 -1
View File
@@ -54,7 +54,7 @@
return FALSE
if(status)
SSalarm.triggerAlarm("Motion", get_area(src), list(UID()), src)
visible_message("<span class='warning'>A red light flashes on the [src]!</span>")
visible_message("<span class='warning'>A red light flashes on [src]!</span>")
detectTime = -1
return TRUE
@@ -234,7 +234,7 @@
if(!silent)
var/obj/oldobj = obj
visible_message("The [oldobj.name] fades away!")
visible_message("[oldobj] fades away!")
qdel(obj)
/obj/machinery/computer/HolodeckControl/proc/checkInteg(area/A)
@@ -505,12 +505,12 @@
return
G.affecting.loc = src.loc
G.affecting.Weaken(5)
visible_message("<span class='warning'>[G.assailant] dunks [G.affecting] into the [src]!</span>")
visible_message("<span class='warning'>[G.assailant] dunks [G.affecting] into [src]!</span>")
qdel(W)
return
else if(istype(W, /obj/item) && get_dist(src,user)<2)
user.drop_item(src)
visible_message("<span class='notice'>[user] dunks [W] into the [src]!</span>")
visible_message("<span class='notice'>[user] dunks [W] into [src]!</span>")
return
/obj/structure/holohoop/CanPass(atom/movable/mover, turf/target, height=0)
@@ -59,10 +59,7 @@
return TRUE
if("toggle_bolts" in href_list)
bolts = !bolts
if(bolts)
visible_message("You hear a quite click as the [src] bolts to the floor", "You hear a quite click")
else
visible_message("You hear a quite click as the [src]'s floor bolts raise", "You hear a quite click")
visible_message("<span class='notice'>You hear a quiet click as [src][bolts ? " bolts to the floor" : "'s bolts raise"].</span>", "<span class='notice>You hear a quiet click.</span>")
return TRUE
/obj/machinery/air_sensor/attackby(obj/item/W as obj, mob/user as mob)
@@ -71,7 +68,7 @@
return 1
if(istype(W, /obj/item/wrench))
if(bolts)
to_chat(usr, "The [src] is bolted to the floor! You can't detach it like this.")
to_chat(usr, "[src] is bolted to the floor! You can't detach it like this.")
return 1
playsound(loc, W.usesound, 50, 1)
to_chat(user, "<span class='notice'>You begin to unfasten \the [src]...</span>")
@@ -392,7 +392,7 @@
/obj/item/circuitboard/rdconsole/attackby(obj/item/I as obj, mob/user as mob, params)
if(istype(I,/obj/item/card/id)||istype(I, /obj/item/pda))
if(allowed(user))
user.visible_message("<span class='notice'>\the [user] waves [user.p_their()] ID past the [src]'s access protocol scanner.</span>", "<span class='notice'>You swipe your ID past the [src]'s access protocol scanner.</span>")
user.visible_message("<span class='notice'>[user] waves [user.p_their()] ID past [src]'s access protocol scanner.</span>", "<span class='notice'>You swipe your ID past [src]'s access protocol scanner.</span>")
var/console_choice = input(user, "What do you want to configure the access to?", "Access Modification", "R&D Core") as null|anything in access_types
if(console_choice == null)
return
@@ -477,11 +477,11 @@
return
if(istype(P, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C = P
if(C.amount >= 5)
if(C.get_amount() >= 5)
playsound(loc, C.usesound, 50, 1)
to_chat(user, "<span class='notice'>You start to add cables to the frame.</span>")
if(do_after(user, 20 * C.toolspeed, target = src))
if(state == 2 && C.amount >= 5 && C.use(5))
if(state == 2 && C.get_amount() >= 5 && C.use(5))
to_chat(user, "<span class='notice'>You add cables to the frame.</span>")
state = 3
icon_state = "3"
@@ -502,11 +502,11 @@
return
if(istype(P, /obj/item/stack/sheet/glass))
var/obj/item/stack/sheet/glass/G = P
if(G.amount >= 2)
if(G.get_amount() >= 2)
playsound(loc, G.usesound, 50, 1)
to_chat(user, "<span class='notice'>You start to add the glass panel to the frame.</span>")
if(do_after(user, 20 * G.toolspeed, target = src))
if(state == 3 && G.amount >= 2 && G.use(2))
if(state == 3 && G.get_amount() >= 2 && G.use(2))
to_chat(user, "<span class='notice'>You put in the glass panel.</span>")
state = 4
icon_state = "4"
@@ -608,11 +608,11 @@
icon_state = "1"
if(istype(P, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C = P
if(C.amount >= 5)
if(C.get_amount() >= 5)
playsound(loc, C.usesound, 50, 1)
to_chat(user, "<span class='notice'>You start to add cables to the frame.</span>")
if(do_after(user, 20 * C.toolspeed, target = src))
if(state == 2 && C.amount >= 5 && C.use(5))
if(state == 2 && C.get_amount() >= 5 && C.use(5))
to_chat(user, "<span class='notice'>You add cables to the frame.</span>")
state = 3
icon_state = "3"
@@ -633,11 +633,11 @@
if(istype(P, /obj/item/stack/sheet/glass))
var/obj/item/stack/sheet/glass/G = P
if(G.amount >= 2)
if(G.get_amount() >= 2)
playsound(loc, G.usesound, 50, 1)
to_chat(user, "<span class='notice'>You start to add the glass panel to the frame.</span>")
if(do_after(user, 20 * G.toolspeed, target = src))
if(state == 3 && G.amount >= 2 && G.use(2))
if(state == 3 && G.get_amount() >= 2 && G.use(2))
to_chat(user, "<span class='notice'>You put in the glass panel.</span>")
state = 4
icon_state = "4"
@@ -147,7 +147,7 @@
message_cooldown = world.time + 600 //One minute
if("callshuttle")
var/input = clean_input("Please enter the reason for calling the shuttle.", "Shuttle Call Reason.","")
var/input = input("Please enter the reason for calling the shuttle.", "Shuttle Call Reason.") as null|message
if(!input || ..() || !is_authenticated(usr))
return
call_shuttle_proc(usr, input)
@@ -410,7 +410,7 @@
else
menu_state=value
/proc/call_shuttle_proc(mob/user, reason)
/proc/call_shuttle_proc(mob/user, reason, sanitized = FALSE)
if(GLOB.sent_strike_team == 1)
to_chat(user, "<span class='warning'>Central Command will not allow the shuttle to be called. Consider all contracts terminated.</span>")
return
@@ -427,6 +427,9 @@
to_chat(user, "<span class='warning'>Under directive 7-10, [station_name()] is quarantined until further notice.</span>")
return
if(!sanitized)
reason = trim_strip_html_properly(reason, allow_lines = TRUE)
SSshuttle.requestEvac(user, reason)
log_game("[key_name(user)] has called the shuttle.")
message_admins("[key_name_admin(user)] has called the shuttle.", 1)
+1
View File
@@ -225,5 +225,6 @@
log_game("[key_name(usr)] emagged [key_name(R)] using robotic console!")
message_admins("<span class='notice'>[key_name_admin(usr)] emagged [key_name_admin(R)] using robotic console!</span>")
R.emagged = TRUE
R.module.rebuild_modules()
to_chat(R, "<span class='notice'>Failsafe protocols overriden. New tools available.</span>")
. = TRUE
+4 -4
View File
@@ -75,11 +75,11 @@
if(1)
if(istype(P, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C = P
if(C.amount >= 5)
if(C.get_amount() >= 5)
playsound(src.loc, C.usesound, 50, 1)
to_chat(user, "<span class='notice'>You start to add cables to the frame.</span>")
if(do_after(user, 20 * C.toolspeed, target = src))
if(state == 1 && C.amount >= 5 && C.use(5))
if(state == 1 && C.get_amount() >= 5 && C.use(5))
to_chat(user, "<span class='notice'>You add cables to the frame.</span>")
state = 2
icon_state = "box_1"
@@ -193,8 +193,8 @@
playsound(src.loc, P.usesound, 50, 1)
if(istype(P, /obj/item/stack))
var/obj/item/stack/S = P
var/camt = min(S.amount, req_components[I])
var/obj/item/stack/NS = new P.type(src)
var/camt = min(S.get_amount(), req_components[I])
var/obj/item/stack/NS = new S.merge_type(src)
NS.amount = camt
NS.update_icon()
S.use(camt)
+2 -2
View File
@@ -52,7 +52,7 @@
else
. += "<span class='notice'>Its locking clamps can be [clamps_locked ? "dis" : ""]engaged by swiping an ID with access.</span>"
else
. += "<span class='notice'>There are a pair of <b>bolts</b> in the defib unit housing securing the [src] to the wall.<span>"
. += "<span class='notice'>There are a pair of <b>bolts</b> in the defibrillator unit housing, securing [src] to the wall.<span>"
/obj/machinery/defibrillator_mount/process()
if(defib && defib.cell && defib.cell.charge < defib.cell.maxcharge && is_operational())
@@ -117,7 +117,7 @@
/obj/machinery/defibrillator_mount/wrench_act(mob/user, obj/item/I)
. = TRUE
if(defib)
to_chat(user, "<span class='warning'>The [defib] is blocking access to the bolts!</span>")
to_chat(user, "<span class='warning'>[defib] is blocking access to the bolts!</span>")
return
if(!I.use_tool(src, user, 0, volume = I.tool_volume))
return
-8
View File
@@ -195,11 +195,6 @@
/obj/machinery/door/window/narsie_act()
color = NARSIE_WINDOW_COLOUR
/obj/machinery/door/window/ratvar_act()
var/obj/machinery/door/window/clockwork/C = new(loc, dir)
C.name = name
qdel(src)
/obj/machinery/door/window/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
..()
if(exposed_temperature > T0C + (reinf ? 1600 : 800))
@@ -358,9 +353,6 @@
if(prob(80/severity))
open()
/obj/machinery/door/window/clockwork/ratvar_act()
obj_integrity = max_integrity
/obj/machinery/door/window/clockwork/hasPower()
return TRUE //yup that's power all right
+2 -2
View File
@@ -43,7 +43,7 @@
if(istype(I, /obj/item/hair_dye_bottle))
var/obj/item/hair_dye_bottle/HD = I
user.visible_message("<span class='notice'>[user] fills the [HD] up with some dye.</span>","<span class='notice'>You fill the [HD] up with some hair dye.</span>")
user.visible_message("<span class='notice'>[user] fills [HD] up with some dye.</span>","<span class='notice'>You fill [HD] up with some hair dye.</span>")
HD.dye_color = dye_color
HD.update_dye_overlay()
return
@@ -52,7 +52,7 @@
//Hair Dye Bottle
/obj/item/hair_dye_bottle
name = "Hair Dye Bottle"
name = "hair dye bottle"
desc = "A refillable bottle used for holding hair dyes of all sorts of colors."
icon = 'icons/obj/items.dmi'
icon_state = "hairdyebottle"
+1 -1
View File
@@ -69,7 +69,7 @@ FIRE ALARM
if(!emagged)
emagged = TRUE
if(user)
user.visible_message("<span class='warning'>Sparks fly out of the [src]!</span>",
user.visible_message("<span class='warning'>Sparks fly out of [src]!</span>",
"<span class='notice'>You emag [src], disabling its thermal sensors.</span>")
playsound(loc, 'sound/effects/sparks4.ogg', 50, 1)
+3 -3
View File
@@ -21,7 +21,7 @@
return 1
if(istype(W, /obj/item/screwdriver))
to_chat(user, "You begin to unscrew the bolts off the [src]...")
to_chat(user, "<span class='notice'>You begin to unscrew the bolts off [src]...</span>")
playsound(get_turf(src), W.usesound, 50, 1)
if(do_after(user, 30 * W.toolspeed, target = src))
var/obj/machinery/mass_driver_frame/F = new(get_turf(src))
@@ -126,7 +126,7 @@
var/obj/item/stack/cable_coil/C = W
to_chat(user, "You start adding cables to \the [src]...")
playsound(get_turf(src), C.usesound, 50, 1)
if(do_after(user, 20 * C.toolspeed, target = src) && (C.amount >= 2) && (build == 2))
if(do_after(user, 20 * C.toolspeed, target = src) && (C.get_amount() >= 2) && (build == 2))
C.use(2)
to_chat(user, "<span class='notice'>You've added cables to \the [src].</span>")
build++
@@ -146,7 +146,7 @@
var/obj/item/stack/rods/R = W
to_chat(user, "You begin to complete \the [src]...")
playsound(get_turf(src), R.usesound, 50, 1)
if(do_after(user, 20 * R.toolspeed, target = src) && (R.amount >= 2) && (build == 3))
if(do_after(user, 20 * R.toolspeed, target = src) && (R.get_amount() >= 2) && (build == 3))
R.use(2)
to_chat(user, "<span class='notice'>You've added the grille to \the [src].</span>")
build++
+5 -5
View File
@@ -145,6 +145,8 @@
else if(our_rpd.mode == RPD_FLIP_MODE)
flip()
else if(our_rpd.mode == RPD_DELETE_MODE)
if(pipe_type == PIPE_CIRCULATOR) //Skip TEG heat circulators, they aren't really pipes
return ..()
our_rpd.delete_single_pipe(user, src)
else
return ..()
@@ -499,13 +501,11 @@
P.on_construction(dir, pipe_dir, color)
user.visible_message( \
"[user] fastens the [src].", \
"<span class='notice'>You have fastened the [src].</span>", \
"You hear ratchet.")
"<span class='notice'>[user] fastens [src].</span>",
"<span class='notice'>You fasten [src].</span>",
"<span class='notice'>You hear a ratchet.</span>")
qdel(src) // remove the pipe item
return
/obj/item/pipe_meter
name = "meter"
desc = "A meter that can be laid on pipes"
+1 -1
View File
@@ -63,7 +63,7 @@
M.set_multitool_buffer(user, src)
else
linked_pad = M.buffer
to_chat(user, "<span class='notice'>You link the [src] to the one in the [I.name]'s buffer.</span>")
to_chat(user, "<span class='notice'>You link [src] to the one in [I]'s buffer.</span>")
/obj/machinery/quantumpad/screwdriver_act(mob/user, obj/item/I)
. = TRUE
+26 -83
View File
@@ -7,11 +7,18 @@
use_power = IDLE_POWER_USE
idle_power_usage = 5
active_power_usage = 1000
/// A reference to the occupant currently sitting inside the recharger.
var/mob/occupant = null
/// What type of circuit board is required to build this machine.
var/circuitboard = /obj/item/circuitboard/cyborgrecharger
/// How fast the recharger can give charge to the occupants energy cell. Based on capacitors and the cell the recharger has.
var/recharge_speed
/// How much nutrition is given to the occupant. Based on capacitors and the cell the recharger has. Only relevent for IPCs.
var/recharge_speed_nutrition
/// How much the occupant is repaired every cycle. Based on what manipulator the recharger has.
var/repairs
/// How efficiently the recharger is able to recharge consumable items such as metal, glass, chemicals in sprays, welding tool fuel, etc.
var/consumable_recharge_coeff
/obj/machinery/recharge_station/Destroy()
go_out()
@@ -42,6 +49,7 @@
recharge_speed = 0
recharge_speed_nutrition = 0
repairs = 0
// The recharge_speed can be anywhere from 200 to 3200, depending on the capacitors and the cell.
for(var/obj/item/stock_parts/capacitor/C in component_parts)
recharge_speed += C.rating * 100
recharge_speed_nutrition += C.rating * 10
@@ -52,11 +60,14 @@
recharge_speed *= multiplier
recharge_speed_nutrition *= multiplier
// This coefficient can be anywhere from 1, to 16.
consumable_recharge_coeff = max(1, recharge_speed / 200)
/obj/machinery/recharge_station/process()
if(!(NOPOWER|BROKEN))
return
if(src.occupant)
if(occupant)
process_occupant()
for(var/mob/M as mob in src) // makes sure that simple mobs don't get stuck inside a sleeper when they resist out of occupant's grasp
@@ -133,20 +144,20 @@
return TRUE
/obj/machinery/recharge_station/proc/process_occupant()
if(src.occupant)
if(istype(occupant, /mob/living/silicon/robot))
var/mob/living/silicon/robot/R = occupant
restock_modules()
if(repairs)
R.heal_overall_damage(repairs, repairs)
if(R.cell)
R.cell.charge = min(R.cell.charge + recharge_speed, R.cell.maxcharge)
else if(istype(occupant, /mob/living/carbon/human))
var/mob/living/carbon/human/H = occupant
if(H.get_int_organ(/obj/item/organ/internal/cell) && H.nutrition < 450)
H.set_nutrition(min(H.nutrition + recharge_speed_nutrition, 450))
if(repairs)
H.heal_overall_damage(repairs, repairs, TRUE, 0, 1)
if(isrobot(occupant))
var/mob/living/silicon/robot/R = occupant
if(R.module)
R.module.recharge_consumables(R, consumable_recharge_coeff) // This will handle all of a cyborg's items.
if(repairs)
R.heal_overall_damage(repairs, repairs)
if(R.cell)
R.cell.charge = min(R.cell.charge + recharge_speed, R.cell.maxcharge)
else if(ishuman(occupant))
var/mob/living/carbon/human/H = occupant
if(H.get_int_organ(/obj/item/organ/internal/cell) && H.nutrition < 450)
H.set_nutrition(min(H.nutrition + recharge_speed_nutrition, 450))
if(repairs)
H.heal_overall_damage(repairs, repairs, TRUE, 0, 1)
/obj/machinery/recharge_station/proc/go_out()
if(!occupant)
@@ -157,74 +168,6 @@
use_power = IDLE_POWER_USE
return
/obj/machinery/recharge_station/proc/restock_modules()
if(src.occupant)
if(istype(occupant, /mob/living/silicon/robot))
var/mob/living/silicon/robot/R = occupant
var/coeff = recharge_speed / 200
if(R.module && R.module.modules)
var/list/um = R.contents|R.module.modules
// ^ makes sinle list of active (R.contents) and inactive modules (R.module.modules)
for(var/obj/O in um)
// Engineering
if(istype(O,/obj/item/stack/sheet))
var/obj/item/stack/sheet/S = O
if(S.amount < S.max_amount)
S.amount += round(min(1 * coeff, S.max_amount - S.amount))
// Security
if(istype(O,/obj/item/flash))
var/obj/item/flash/F = O
if(F.broken)
F.broken = 0
F.times_used = 0
F.icon_state = "flash"
if(istype(O,/obj/item/gun/energy))
var/obj/item/gun/energy/D = O
if(D.cell.charge < D.cell.maxcharge)
var/obj/item/ammo_casing/energy/E = D.ammo_type[D.select]
D.cell.give(E.e_cost)
D.on_recharge()
D.update_icon()
else
D.charge_tick = 0
if(istype(O,/obj/item/melee/baton))
var/obj/item/melee/baton/B = O
if(B.cell)
B.cell.charge = B.cell.maxcharge
//Service
if(istype(O,/obj/item/reagent_containers/food/condiment/enzyme))
if(O.reagents.get_reagent_amount("enzyme") < 50)
O.reagents.add_reagent("enzyme", 2 * coeff)
//Janitor
if(istype(O, /obj/item/lightreplacer))
var/obj/item/lightreplacer/LR = O
var/i = 1
for(1, i <= coeff, i++)
LR.Charge(occupant)
//Fire extinguisher
if(istype(O, /obj/item/extinguisher))
var/obj/item/extinguisher/ext = O
ext.reagents.check_and_add("water", ext.max_water, 5 * coeff)
//Welding tools
if(istype(O, /obj/item/weldingtool))
var/obj/item/weldingtool/weld = O
weld.reagents.check_and_add("fuel", weld.maximum_fuel, 2 * coeff)
if(R)
if(R.module)
R.module.respawn_consumable(R)
//Emagged items for janitor and medical borg
if(R.module.emag)
if(istype(R.module.emag, /obj/item/reagent_containers/spray))
var/obj/item/reagent_containers/spray/S = R.module.emag
if(S.name == "polyacid spray")
S.reagents.add_reagent("facid", 2 * coeff)
if(S.name == "lube spray")
S.reagents.add_reagent("lube", 2 * coeff)
else if(S.name == "acid synthesizer")
S.reagents.add_reagent("facid", 2 * coeff)
S.reagents.add_reagent("sacid", 2 * coeff)
/obj/machinery/recharge_station/verb/move_eject()
set category = "Object"
set src in oview(1)
+1 -1
View File
@@ -77,7 +77,7 @@
emergency_mode = FALSE
update_icon()
playsound(src, "sparks", 75, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
to_chat(user, "<span class='notice'>You use the cryptographic sequencer on the [name].</span>")
to_chat(user, "<span class='notice'>You use the cryptographic sequencer on [src].</span>")
/obj/machinery/recycler/update_icon()
..()
+12 -10
View File
@@ -126,7 +126,7 @@
return visible
/obj/machinery/shieldgen
name = "Emergency shield projector"
name = "emergency shield projector"
desc = "Used to seal minor hull breaches."
icon = 'icons/obj/objects.dmi'
icon_state = "shieldoff"
@@ -160,7 +160,12 @@
for(var/turf/target_tile in range(2, src))
if(istype(target_tile,/turf/space) && !(locate(/obj/machinery/shield) in target_tile))
if(malfunction && prob(33) || !malfunction)
deployed_shields += new /obj/machinery/shield(target_tile)
var/obj/machinery/shield/new_shield = new(target_tile)
RegisterSignal(new_shield, COMSIG_PARENT_QDELETING, .proc/remove_shield) // Ensures they properly GC
deployed_shields += new_shield
/obj/machinery/shieldgen/proc/remove_shield(obj/machinery/shield/S)
deployed_shields -= S
/obj/machinery/shieldgen/proc/shields_down()
if(!active)
@@ -169,15 +174,12 @@
active = 0
update_icon()
for(var/obj/machinery/shield/shield_tile in deployed_shields)
qdel(shield_tile)
QDEL_LIST(deployed_shields)
/obj/machinery/shieldgen/process()
if(malfunction && active)
if(deployed_shields.len && prob(5))
qdel(pick(deployed_shields))
return
if(length(deployed_shields) && prob(5))
qdel(pick_n_take(deployed_shields))
/obj/machinery/shieldgen/proc/checkhp()
if(health <= 30)
@@ -251,7 +253,7 @@
health = max_health
malfunction = TRUE
playsound(loc, coil.usesound, 50, 1)
to_chat(user, "<span class='notice'>You repair the [src]!</span>")
to_chat(user, "<span class='notice'>You repair [src]!</span>")
update_icon()
else if(istype(I, /obj/item/card/id) || istype(I, /obj/item/pda))
@@ -407,7 +409,7 @@
active = 2
if(active >= 1)
if(power == 0)
visible_message("<span class='warning'>The [name] shuts down due to lack of power!</span>", \
visible_message("<span class='warning'>[name] shuts down due to lack of power!</span>", \
"You hear heavy droning fade out")
icon_state = "Shield_Gen"
active = 0
+3 -3
View File
@@ -315,7 +315,7 @@
if(store_item(I, user))
update_icon()
SStgui.update_uis(src)
to_chat(user, "<span class='notice'>You load the [I] into the storage compartment.</span>")
to_chat(user, "<span class='notice'>You load [I] into the storage compartment.</span>")
else
to_chat(user, "<span class='warning'>You can't fit [I] into [src]!</span>")
return
@@ -382,10 +382,10 @@
return
var/mob/living/target = A
if(!state_open)
to_chat(user, "<span class='warning'>The [src]'s doors are shut!</span>")
to_chat(user, "<span class='warning'>[src]'s doors are shut!</span>")
return
if(!is_operational())
to_chat(user, "<span class='warning'>The [src] is not operational!</span>")
to_chat(user, "<span class='warning'>[src] is not operational!</span>")
return
if(occupant || helmet || suit || storage)
to_chat(user, "<span class='warning'>It's too cluttered inside to fit in!</span>")

Some files were not shown because too many files have changed in this diff Show More