mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-23 12:07:27 +01:00
Merge remote-tracking branch 'ParadiseSS13/master' into toml-config
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
+10494
-17177
File diff suppressed because it is too large
Load Diff
@@ -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" = (
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -104,3 +104,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"
|
||||
|
||||
@@ -136,9 +136,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]")
|
||||
|
||||
|
||||
@@ -514,6 +514,7 @@
|
||||
text = replacetext(text, "\[logo\]", "​<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>"
|
||||
|
||||
@@ -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"
|
||||
@@ -155,6 +155,10 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
|
||||
/// 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
|
||||
#define TRAIT_GENERIC "generic"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -57,7 +57,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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ..()
|
||||
|
||||
|
||||
@@ -136,8 +136,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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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"])
|
||||
|
||||
@@ -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"
|
||||
..()
|
||||
|
||||
@@ -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 /////////////////////////////////////////
|
||||
|
||||
@@ -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
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 = ""
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -413,6 +413,9 @@
|
||||
/atom/proc/emag_act()
|
||||
return
|
||||
|
||||
/atom/proc/unemag()
|
||||
return
|
||||
|
||||
/**
|
||||
* Respond to a radioactive wave hitting this atom
|
||||
*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -382,7 +382,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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>")
|
||||
@@ -312,9 +316,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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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++
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -699,7 +699,7 @@
|
||||
else if(istype(W, /obj/item/stack/cable_coil))
|
||||
if(state == 3 && hasInternalDamage(MECHA_INT_SHORT_CIRCUIT))
|
||||
var/obj/item/stack/cable_coil/CC = W
|
||||
if(CC.amount > 1)
|
||||
if(CC.get_amount() > 1)
|
||||
CC.use(2)
|
||||
clearInternalDamage(MECHA_INT_SHORT_CIRCUIT)
|
||||
to_chat(user, "You replace the fused wires.")
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
return 0
|
||||
else if(istype(used_atom, /obj/item/stack))
|
||||
var/obj/item/stack/S = used_atom
|
||||
if(S.amount < STANDARD_STACK_AMOUNT)
|
||||
if(S.get_amount() < STANDARD_STACK_AMOUNT)
|
||||
to_chat(user, ("There's not enough material in this stack."))
|
||||
return 0
|
||||
else
|
||||
@@ -35,7 +35,7 @@
|
||||
return 0
|
||||
else if(istype(used_atom, /obj/item/stack))
|
||||
var/obj/item/stack/S = used_atom
|
||||
if(S.amount < STANDARD_STACK_AMOUNT)
|
||||
if(S.get_amount() < STANDARD_STACK_AMOUNT)
|
||||
to_chat(user, ("There's not enough material in this stack."))
|
||||
return 0
|
||||
else
|
||||
|
||||
@@ -258,7 +258,7 @@
|
||||
/obj/item/assembly/signaler/anomaly/random = 50, // anomaly core
|
||||
/obj/item/mecha_parts/mecha_equipment/weapon/energy/xray = 25, // mecha x-ray laser
|
||||
/obj/item/mecha_parts/mecha_equipment/teleporter/precise = 25, // upgraded mecha teleporter
|
||||
/obj/item/autosurgeon = 50,
|
||||
/obj/item/autosurgeon/organ = 50,
|
||||
|
||||
// Research / Experimentor
|
||||
/obj/item/paper/researchnotes = 150, // papers that give random R&D levels
|
||||
|
||||
@@ -728,3 +728,6 @@ GLOBAL_DATUM_INIT(fire_overlay, /image, image("icon" = 'icons/goonstation/effect
|
||||
if(flags & SLOT_PDA)
|
||||
owner.update_inv_wear_pda()
|
||||
|
||||
/// Called on cyborg items that need special charging behavior. Override as needed for specific items.
|
||||
/obj/item/proc/cyborg_recharge(coeff = 1, emagged = FALSE)
|
||||
return
|
||||
|
||||
@@ -176,6 +176,12 @@
|
||||
..()
|
||||
new /obj/effect/temp_visual/borgflash(get_turf(src))
|
||||
|
||||
/obj/item/flash/cyborg/cyborg_recharge(coeff, emagged)
|
||||
if(broken)
|
||||
broken = FALSE
|
||||
times_used = 0
|
||||
icon_state = "flash"
|
||||
|
||||
/obj/item/flash/cameraflash
|
||||
name = "camera"
|
||||
icon = 'icons/obj/items.dmi'
|
||||
|
||||
@@ -262,6 +262,10 @@
|
||||
/obj/item/lightreplacer/cyborg/janicart_insert(mob/user, obj/structure/janitorialcart/J)
|
||||
return
|
||||
|
||||
/obj/item/lightreplacer/cyborg/cyborg_recharge(coeff, emagged)
|
||||
for(var/I in 1 to coeff)
|
||||
Charge()
|
||||
|
||||
#undef LIGHT_OK
|
||||
#undef LIGHT_EMPTY
|
||||
#undef LIGHT_BROKEN
|
||||
|
||||
@@ -132,7 +132,7 @@
|
||||
return
|
||||
else if(iscoil(W) && buildstage == 1)
|
||||
var/obj/item/stack/cable_coil/coil = W
|
||||
if(coil.amount < 5)
|
||||
if(coil.get_amount() < 5)
|
||||
to_chat(user, "<span class='warning'>You need more cable for this!</span>")
|
||||
return
|
||||
if(do_after(user, 10 * coil.toolspeed, target = src) && buildstage == 1)
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
return 1
|
||||
if(istype(I, /obj/item/stack))
|
||||
var/obj/item/stack/S = I
|
||||
if(S.amount > 1)
|
||||
if(S.get_amount() > 1)
|
||||
var/obj/item/stack/to_add = S.split(user, 1)
|
||||
to_add.forceMove(src)
|
||||
user.visible_message("<span class='notice'>[user] adds one of [S] to [src].</span>", "<span class='notice'>You add one of [S] to [src].</span>")
|
||||
|
||||
@@ -7,19 +7,72 @@
|
||||
icon = 'icons/obj/module.dmi'
|
||||
icon_state = "cyborg_upgrade"
|
||||
origin_tech = "programming=2"
|
||||
var/locked = 0
|
||||
var/installed = 0
|
||||
/// Whether or not the cyborg needs to have a chosen module before they can recieve this upgrade.
|
||||
var/require_module = FALSE
|
||||
/// The type of module this upgrade is compatible with: Engineering, Medical, etc.
|
||||
var/module_type = null
|
||||
/// A list of items, and their replacements that this upgrade should replace on installation, in the format of `item_type_to_replace = replacement_item_type`.
|
||||
var/list/items_to_replace = list()
|
||||
/// A list of replacement items will need to be placed into a cyborg module's `special_rechargable` list after this upgrade is installed.
|
||||
var/list/special_rechargables = list()
|
||||
|
||||
/**
|
||||
* Called when someone clicks on a borg with an upgrade in their hand.
|
||||
*
|
||||
* Arguments:
|
||||
* * R - the cyborg that was clicked on with an upgrade.
|
||||
*/
|
||||
/obj/item/borg/upgrade/proc/action(mob/living/silicon/robot/R)
|
||||
if(!pre_install_checks(R))
|
||||
return
|
||||
if(!do_install(R))
|
||||
return
|
||||
after_install(R)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Checks if the upgrade is able to be applied to the cyborg, before actually applying it.
|
||||
*
|
||||
* Arguments:
|
||||
* * R - the cyborg that was clicked on with an upgrade.
|
||||
*/
|
||||
/obj/item/borg/upgrade/proc/pre_install_checks(mob/living/silicon/robot/R)
|
||||
if(R.stat == DEAD)
|
||||
to_chat(usr, "<span class='notice'>[src] will not function on a deceased cyborg.</span>")
|
||||
return TRUE
|
||||
to_chat(usr, "<span class='warning'>[src] will not function on a deceased cyborg.</span>")
|
||||
return FALSE
|
||||
if(module_type && !istype(R.module, module_type))
|
||||
to_chat(R, "Upgrade mounting error! No suitable hardpoint detected!")
|
||||
to_chat(usr, "There's no mounting point for the module!")
|
||||
return TRUE
|
||||
to_chat(R, "<span class='warning'>Upgrade mounting error! No suitable hardpoint detected!</span>")
|
||||
to_chat(usr, "<span class='warning'>There's no mounting point for the module!</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Executes code that will modify the cyborg or its module.
|
||||
*
|
||||
* Arguments:
|
||||
* * R - the cyborg we're applying the upgrade to.
|
||||
*/
|
||||
/obj/item/borg/upgrade/proc/do_install(mob/living/silicon/robot/R)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Executes code after the module has been installed and the cyborg has been modified in some way.
|
||||
*
|
||||
* Arguments:
|
||||
* * R - the cyborg that we've applied the upgrade to.
|
||||
*/
|
||||
/obj/item/borg/upgrade/proc/after_install(mob/living/silicon/robot/R)
|
||||
for(var/item in items_to_replace)
|
||||
var/replacement_type = items_to_replace[item]
|
||||
var/obj/item/replacement = new replacement_type(R.module)
|
||||
R.module.remove_item_from_lists(item)
|
||||
R.module.basic_modules += replacement
|
||||
|
||||
if(replacement_type in special_rechargables)
|
||||
R.module.special_rechargables += replacement
|
||||
|
||||
R.module.rebuild_modules()
|
||||
return TRUE
|
||||
|
||||
/obj/item/borg/upgrade/reset
|
||||
name = "cyborg module reset board"
|
||||
@@ -27,14 +80,13 @@
|
||||
icon_state = "cyborg_upgrade1"
|
||||
require_module = TRUE
|
||||
|
||||
/obj/item/borg/upgrade/reset/action(mob/living/silicon/robot/R)
|
||||
if(..())
|
||||
return
|
||||
|
||||
/obj/item/borg/upgrade/reset/do_install(mob/living/silicon/robot/R)
|
||||
R.reset_module()
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/item/borg/upgrade/reset/after_install(mob/living/silicon/robot/R)
|
||||
return // We don't need to give them replacement items, or rebuild their module list. It's going to be a blank borg.
|
||||
|
||||
/obj/item/borg/upgrade/rename
|
||||
name = "cyborg reclassification board"
|
||||
desc = "Used to rename a cyborg."
|
||||
@@ -44,9 +96,7 @@
|
||||
/obj/item/borg/upgrade/rename/attack_self(mob/user)
|
||||
heldname = stripped_input(user, "Enter new robot name", "Cyborg Reclassification", heldname, MAX_NAME_LEN)
|
||||
|
||||
/obj/item/borg/upgrade/rename/action(mob/living/silicon/robot/R)
|
||||
if(..())
|
||||
return
|
||||
/obj/item/borg/upgrade/rename/do_install(mob/living/silicon/robot/R)
|
||||
if(!R.allow_rename)
|
||||
to_chat(R, "<span class='warning'>Internal diagnostic error: incompatible upgrade module detected.</span>")
|
||||
return 0
|
||||
@@ -63,7 +113,7 @@
|
||||
desc = "Used to force a reboot of a disabled-but-repaired cyborg, bringing it back online."
|
||||
icon_state = "cyborg_upgrade1"
|
||||
|
||||
/obj/item/borg/upgrade/restart/action(mob/living/silicon/robot/R)
|
||||
/obj/item/borg/upgrade/restart/do_install(mob/living/silicon/robot/R)
|
||||
if(R.health < 0)
|
||||
to_chat(usr, "<span class='warning'>You have to repair the cyborg before using this module!</span>")
|
||||
return 0
|
||||
@@ -88,9 +138,7 @@
|
||||
require_module = TRUE
|
||||
origin_tech = "engineering=4;materials=5;programming=4"
|
||||
|
||||
/obj/item/borg/upgrade/vtec/action(mob/living/silicon/robot/R)
|
||||
if(..())
|
||||
return
|
||||
/obj/item/borg/upgrade/vtec/do_install(mob/living/silicon/robot/R)
|
||||
if(R.speed < 0)
|
||||
to_chat(R, "<span class='notice'>A VTEC unit is already installed!</span>")
|
||||
to_chat(usr, "<span class='notice'>There's no room for another VTEC unit!</span>")
|
||||
@@ -108,10 +156,7 @@
|
||||
require_module = TRUE
|
||||
module_type = /obj/item/robot_module/security
|
||||
|
||||
/obj/item/borg/upgrade/disablercooler/action(mob/living/silicon/robot/R)
|
||||
if(..())
|
||||
return
|
||||
|
||||
/obj/item/borg/upgrade/disablercooler/do_install(mob/living/silicon/robot/R)
|
||||
var/obj/item/gun/energy/disabler/cyborg/T = locate() in R.module.modules
|
||||
if(!T)
|
||||
to_chat(usr, "<span class='notice'>There's no disabler in this unit!</span>")
|
||||
@@ -131,10 +176,7 @@
|
||||
icon_state = "cyborg_upgrade3"
|
||||
origin_tech = "engineering=4;powerstorage=4"
|
||||
|
||||
/obj/item/borg/upgrade/thrusters/action(mob/living/silicon/robot/R)
|
||||
if(..())
|
||||
return
|
||||
|
||||
/obj/item/borg/upgrade/thrusters/do_install(mob/living/silicon/robot/R)
|
||||
if(R.ionpulse)
|
||||
to_chat(usr, "<span class='notice'>This unit already has ion thrusters installed!</span>")
|
||||
return
|
||||
@@ -149,20 +191,9 @@
|
||||
origin_tech = "engineering=4;materials=5"
|
||||
require_module = TRUE
|
||||
module_type = /obj/item/robot_module/miner
|
||||
|
||||
/obj/item/borg/upgrade/ddrill/action(mob/living/silicon/robot/R)
|
||||
if(..())
|
||||
return
|
||||
|
||||
for(var/obj/item/pickaxe/drill/cyborg/D in R.module.modules)
|
||||
qdel(D)
|
||||
for(var/obj/item/shovel/S in R.module.modules)
|
||||
qdel(S)
|
||||
|
||||
R.module.modules += new /obj/item/pickaxe/drill/cyborg/diamond(R.module)
|
||||
R.module.rebuild()
|
||||
|
||||
return TRUE
|
||||
items_to_replace = list(
|
||||
/obj/item/pickaxe/drill/cyborg = /obj/item/pickaxe/drill/cyborg/diamond
|
||||
)
|
||||
|
||||
/obj/item/borg/upgrade/soh
|
||||
name = "mining cyborg satchel of holding"
|
||||
@@ -171,18 +202,9 @@
|
||||
origin_tech = "engineering=4;materials=4;bluespace=4"
|
||||
require_module = TRUE
|
||||
module_type = /obj/item/robot_module/miner
|
||||
|
||||
/obj/item/borg/upgrade/soh/action(mob/living/silicon/robot/R)
|
||||
if(..())
|
||||
return
|
||||
|
||||
for(var/obj/item/storage/bag/ore/cyborg/S in R.module.modules)
|
||||
qdel(S)
|
||||
|
||||
R.module.modules += new /obj/item/storage/bag/ore/holding(R.module)
|
||||
R.module.rebuild()
|
||||
|
||||
return TRUE
|
||||
items_to_replace = list(
|
||||
/obj/item/storage/bag/ore/cyborg = /obj/item/storage/bag/ore/holding
|
||||
)
|
||||
|
||||
/obj/item/borg/upgrade/abductor_engi
|
||||
name = "engineering cyborg abductor upgrade"
|
||||
@@ -191,33 +213,17 @@
|
||||
origin_tech = "engineering=6;materials=6;abductor=3"
|
||||
require_module = TRUE
|
||||
module_type = /obj/item/robot_module/engineering
|
||||
|
||||
/obj/item/borg/upgrade/abductor_engi/action(mob/living/silicon/robot/R)
|
||||
if(..())
|
||||
return
|
||||
|
||||
for(var/obj/item/weldingtool/largetank/cyborg/W in R.module.modules)
|
||||
qdel(W)
|
||||
for(var/obj/item/screwdriver/cyborg/S in R.module.modules)
|
||||
qdel(S)
|
||||
for(var/obj/item/wrench/cyborg/E in R.module.modules)
|
||||
qdel(E)
|
||||
for(var/obj/item/crowbar/cyborg/C in R.module.modules)
|
||||
qdel(C)
|
||||
for(var/obj/item/wirecutters/cyborg/I in R.module.modules)
|
||||
qdel(I)
|
||||
for(var/obj/item/multitool/cyborg/M in R.module.modules)
|
||||
qdel(M)
|
||||
|
||||
R.module.modules += new /obj/item/weldingtool/abductor(R.module)
|
||||
R.module.modules += new /obj/item/wrench/abductor(R.module)
|
||||
R.module.modules += new /obj/item/screwdriver/abductor(R.module)
|
||||
R.module.modules += new /obj/item/crowbar/abductor(R.module)
|
||||
R.module.modules += new /obj/item/wirecutters/abductor(R.module)
|
||||
R.module.modules += new /obj/item/multitool/abductor(R.module)
|
||||
R.module.rebuild()
|
||||
|
||||
return TRUE
|
||||
items_to_replace = list(
|
||||
/obj/item/weldingtool = /obj/item/weldingtool/abductor,
|
||||
/obj/item/wrench = /obj/item/wrench/abductor,
|
||||
/obj/item/screwdriver = /obj/item/screwdriver/abductor,
|
||||
/obj/item/crowbar = /obj/item/crowbar/abductor,
|
||||
/obj/item/wirecutters = /obj/item/wirecutters/abductor,
|
||||
/obj/item/multitool = /obj/item/multitool/abductor
|
||||
)
|
||||
special_rechargables = list(
|
||||
/obj/item/weldingtool/abductor
|
||||
)
|
||||
|
||||
/obj/item/borg/upgrade/abductor_medi
|
||||
name = "medical cyborg abductor upgrade"
|
||||
@@ -226,39 +232,16 @@
|
||||
origin_tech = "biotech=6;materials=6;abductor=3"
|
||||
require_module = TRUE
|
||||
module_type = /obj/item/robot_module/medical
|
||||
|
||||
/obj/item/borg/upgrade/abductor_medi/action(mob/living/silicon/robot/R)
|
||||
if(..())
|
||||
return
|
||||
|
||||
for(var/obj/item/scalpel/laser/laser1/L in R.module.modules)
|
||||
qdel(L)
|
||||
for(var/obj/item/hemostat/H in R.module.modules)
|
||||
qdel(H)
|
||||
for(var/obj/item/retractor/E in R.module.modules)
|
||||
qdel(E)
|
||||
for(var/obj/item/bonegel/B in R.module.modules)
|
||||
qdel(B)
|
||||
for(var/obj/item/FixOVein/F in R.module.modules)
|
||||
qdel(F)
|
||||
for(var/obj/item/bonesetter/S in R.module.modules)
|
||||
qdel(S)
|
||||
for(var/obj/item/circular_saw/C in R.module.modules)
|
||||
qdel(C)
|
||||
for(var/obj/item/surgicaldrill/D in R.module.modules)
|
||||
qdel(D)
|
||||
|
||||
R.module.modules += new /obj/item/scalpel/laser/laser3(R.module) //no abductor laser scalpel, so next best thing.
|
||||
R.module.modules += new /obj/item/hemostat/alien(R.module)
|
||||
R.module.modules += new /obj/item/retractor/alien(R.module)
|
||||
R.module.modules += new /obj/item/bonegel/alien(R.module)
|
||||
R.module.modules += new /obj/item/FixOVein/alien(R.module)
|
||||
R.module.modules += new /obj/item/bonesetter/alien(R.module)
|
||||
R.module.modules += new /obj/item/circular_saw/alien(R.module)
|
||||
R.module.modules += new /obj/item/surgicaldrill/alien(R.module)
|
||||
R.module.rebuild()
|
||||
|
||||
return TRUE
|
||||
items_to_replace = list(
|
||||
/obj/item/scalpel/laser/laser1 = /obj/item/scalpel/laser/laser3, // No abductor laser scalpel, so next best thing.
|
||||
/obj/item/hemostat = /obj/item/hemostat/alien,
|
||||
/obj/item/retractor = /obj/item/retractor/alien,
|
||||
/obj/item/bonegel = /obj/item/bonegel/alien,
|
||||
/obj/item/FixOVein = /obj/item/FixOVein/alien,
|
||||
/obj/item/bonesetter = /obj/item/bonesetter/alien,
|
||||
/obj/item/circular_saw = /obj/item/circular_saw/alien,
|
||||
/obj/item/surgicaldrill = /obj/item/surgicaldrill/alien
|
||||
)
|
||||
|
||||
/obj/item/borg/upgrade/syndicate
|
||||
name = "safety override module"
|
||||
@@ -267,13 +250,11 @@
|
||||
origin_tech = "combat=6;materials=6"
|
||||
require_module = TRUE
|
||||
|
||||
/obj/item/borg/upgrade/syndicate/action(mob/living/silicon/robot/R)
|
||||
if(..())
|
||||
return
|
||||
/obj/item/borg/upgrade/syndicate/do_install(mob/living/silicon/robot/R)
|
||||
if(R.weapons_unlock)
|
||||
to_chat(R, "<span class='warning'>Warning: Safety Overide Protocols have be disabled.</span>")
|
||||
return
|
||||
R.weapons_unlock = 1
|
||||
return // They already had the safety override upgrade, or they're a cyborg type which has this by default.
|
||||
R.weapons_unlock = TRUE
|
||||
to_chat(R, "<span class='warning'>Warning: Safety Overide Protocols have be disabled.</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/item/borg/upgrade/lavaproof
|
||||
@@ -284,9 +265,7 @@
|
||||
require_module = TRUE
|
||||
module_type = /obj/item/robot_module/miner
|
||||
|
||||
/obj/item/borg/upgrade/lavaproof/action(mob/living/silicon/robot/R)
|
||||
if(..())
|
||||
return
|
||||
/obj/item/borg/upgrade/lavaproof/do_install(mob/living/silicon/robot/R)
|
||||
if(istype(R))
|
||||
R.weather_immunities += "lava"
|
||||
return TRUE
|
||||
@@ -303,10 +282,7 @@
|
||||
var/powercost = 10
|
||||
var/mob/living/silicon/robot/cyborg
|
||||
|
||||
/obj/item/borg/upgrade/selfrepair/action(mob/living/silicon/robot/R)
|
||||
if(..())
|
||||
return
|
||||
|
||||
/obj/item/borg/upgrade/selfrepair/do_install(mob/living/silicon/robot/R)
|
||||
var/obj/item/borg/upgrade/selfrepair/U = locate() in R
|
||||
if(U)
|
||||
to_chat(usr, "<span class='warning'>This unit is already equipped with a self-repair module.</span>")
|
||||
|
||||
@@ -17,13 +17,18 @@
|
||||
var/healverb = "bandage"
|
||||
|
||||
/obj/item/stack/medical/attack(mob/living/M, mob/user)
|
||||
if(get_amount() <= 0)
|
||||
if(is_cyborg)
|
||||
to_chat(user, "<span class='warning'>You don't have enough energy to dispense more [singular_name]\s!</span>")
|
||||
return TRUE
|
||||
|
||||
if(!iscarbon(M) && !isanimal(M))
|
||||
to_chat(user, "<span class='danger'>[src] cannot be applied to [M]!</span>")
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
if(!user.IsAdvancedToolUser())
|
||||
to_chat(user, "<span class='danger'>You don't have the dexterity to do this!</span>")
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
|
||||
if(ishuman(M))
|
||||
@@ -167,7 +172,12 @@
|
||||
heal_brute = 25
|
||||
stop_bleeding = 0
|
||||
|
||||
/obj/item/stack/medical/bruise_pack/advanced/cyborg
|
||||
energy_type = /datum/robot_energy_storage/medical/adv_brute_kit
|
||||
is_cyborg = TRUE
|
||||
|
||||
/obj/item/stack/medical/bruise_pack/advanced/cyborg/syndicate
|
||||
energy_type = /datum/robot_energy_storage/medical/adv_brute_kit/syndicate
|
||||
|
||||
//Ointment//
|
||||
|
||||
@@ -208,6 +218,13 @@
|
||||
icon_state = "burnkit"
|
||||
heal_burn = 25
|
||||
|
||||
/obj/item/stack/medical/ointment/advanced/cyborg
|
||||
energy_type = /datum/robot_energy_storage/medical/adv_burn_kit
|
||||
is_cyborg = TRUE
|
||||
|
||||
/obj/item/stack/medical/ointment/advanced/cyborg/syndicate
|
||||
energy_type = /datum/robot_energy_storage/medical/adv_burn_kit/syndicate
|
||||
|
||||
//Medical Herbs//
|
||||
/obj/item/stack/medical/bruise_pack/comfrey
|
||||
name = "\improper Comfrey leaf"
|
||||
@@ -283,6 +300,13 @@
|
||||
H.handle_splints()
|
||||
use(1)
|
||||
|
||||
/obj/item/stack/medical/splint/cyborg
|
||||
energy_type = /datum/robot_energy_storage/medical/splint
|
||||
is_cyborg = TRUE
|
||||
|
||||
/obj/item/stack/medical/splint/cyborg/syndicate
|
||||
energy_type = /datum/robot_energy_storage/medical/splint/syndicate
|
||||
|
||||
/obj/item/stack/medical/splint/tribal
|
||||
name = "tribal splints"
|
||||
icon_state = "tribal_splint"
|
||||
|
||||
@@ -63,3 +63,16 @@
|
||||
to_chat(user, "<span class='notice'>Nothing to fix here.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>[src] won't work on that.</span>")
|
||||
|
||||
/obj/item/stack/nanopaste/cyborg
|
||||
energy_type = /datum/robot_energy_storage/medical/nanopaste
|
||||
is_cyborg = TRUE
|
||||
|
||||
/obj/item/stack/nanopaste/cyborg/attack(mob/living/M, mob/user)
|
||||
if(get_amount() <= 0)
|
||||
to_chat(user, "<span class='warning'>You don't have enough energy to dispense more [name]!</span>")
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/stack/nanopaste/cyborg/syndicate
|
||||
energy_type = /datum/robot_energy_storage/medical/nanopaste/syndicate
|
||||
|
||||
@@ -21,10 +21,16 @@ GLOBAL_LIST_INIT(rod_recipes, list ( \
|
||||
hitsound = 'sound/weapons/grenadelaunch.ogg'
|
||||
toolspeed = 1
|
||||
usesound = 'sound/items/deconstruct.ogg'
|
||||
merge_type = /obj/item/stack/rods
|
||||
|
||||
/obj/item/stack/rods/cyborg
|
||||
energy_type = /datum/robot_energy_storage/rods
|
||||
is_cyborg = TRUE
|
||||
materials = list()
|
||||
|
||||
/obj/item/stack/rods/cyborg/update_icon()
|
||||
return // icon_state should always be a full stack of rods.
|
||||
|
||||
/obj/item/stack/rods/ten
|
||||
amount = 10
|
||||
|
||||
|
||||
@@ -40,6 +40,8 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \
|
||||
amount = 50
|
||||
|
||||
/obj/item/stack/sheet/glass/cyborg
|
||||
energy_type = /datum/robot_energy_storage/glass
|
||||
is_cyborg = TRUE
|
||||
materials = list()
|
||||
|
||||
/obj/item/stack/sheet/glass/New(loc, amount)
|
||||
@@ -48,15 +50,15 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \
|
||||
|
||||
/obj/item/stack/sheet/glass/attackby(obj/item/W, mob/user, params)
|
||||
..()
|
||||
if(istype(W,/obj/item/stack/cable_coil))
|
||||
if(istype(W, /obj/item/stack/cable_coil))
|
||||
var/obj/item/stack/cable_coil/CC = W
|
||||
if(CC.amount < 5)
|
||||
if(CC.get_amount() < 5)
|
||||
to_chat(user, "<b>There is not enough wire in this coil. You need 5 lengths.</b>")
|
||||
return
|
||||
CC.use(5)
|
||||
to_chat(user, "<span class='notice'>You attach wire to the [name].</span>")
|
||||
new /obj/item/stack/light_w(user.loc)
|
||||
src.use(1)
|
||||
use(1)
|
||||
else if( istype(W, /obj/item/stack/rods) )
|
||||
var/obj/item/stack/rods/V = W
|
||||
var/obj/item/stack/sheet/rglass/RG = new (user.loc)
|
||||
@@ -97,9 +99,6 @@ GLOBAL_LIST_INIT(reinforced_glass_recipes, list ( \
|
||||
merge_type = /obj/item/stack/sheet/rglass
|
||||
point_value = 4
|
||||
|
||||
/obj/item/stack/sheet/rglass/cyborg
|
||||
materials = list()
|
||||
|
||||
/obj/item/stack/sheet/rglass/New(loc, amount)
|
||||
recipes = GLOB.reinforced_glass_recipes
|
||||
..()
|
||||
@@ -109,6 +108,11 @@ GLOBAL_LIST_INIT(pglass_recipes, list ( \
|
||||
new/datum/stack_recipe/window("fulltile window", /obj/structure/window/full/plasmabasic, 2, time = 0, on_floor = TRUE, window_checks = TRUE) \
|
||||
))
|
||||
|
||||
/obj/item/stack/sheet/rglass/cyborg
|
||||
energy_type = /datum/robot_energy_storage/rglass
|
||||
is_cyborg = TRUE
|
||||
materials = list()
|
||||
|
||||
/obj/item/stack/sheet/plasmaglass
|
||||
name = "plasma glass"
|
||||
desc = "A very strong and very resistant sheet of a plasma-glass alloy."
|
||||
|
||||
@@ -13,25 +13,16 @@
|
||||
flags = CONDUCT
|
||||
max_amount = 60
|
||||
|
||||
/obj/item/stack/light_w/attackby(obj/item/O as obj, mob/user as mob, params)
|
||||
/obj/item/stack/light_w/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(istype(O,/obj/item/wirecutters))
|
||||
var/obj/item/stack/cable_coil/CC = new/obj/item/stack/cable_coil(user.loc)
|
||||
if(istype(I, /obj/item/wirecutters))
|
||||
var/obj/item/stack/cable_coil/CC = new(user.loc)
|
||||
CC.amount = 5
|
||||
amount--
|
||||
new/obj/item/stack/sheet/glass(user.loc)
|
||||
if(amount <= 0)
|
||||
user.unEquip(src, 1)
|
||||
qdel(src)
|
||||
use(1)
|
||||
|
||||
if(istype(O,/obj/item/stack/sheet/metal))
|
||||
var/obj/item/stack/sheet/metal/M = O
|
||||
M.amount--
|
||||
if(M.amount <= 0)
|
||||
user.unEquip(src, 1)
|
||||
qdel(M)
|
||||
amount--
|
||||
new/obj/item/stack/tile/light(user.loc)
|
||||
if(amount <= 0)
|
||||
user.unEquip(src, 1)
|
||||
qdel(src)
|
||||
if(istype(I, /obj/item/stack/sheet/metal))
|
||||
var/obj/item/stack/sheet/metal/M = I
|
||||
M.use(1)
|
||||
new /obj/item/stack/tile/light(user.loc)
|
||||
use(1)
|
||||
|
||||
@@ -110,6 +110,8 @@ GLOBAL_LIST_INIT(metal_recipes, list(
|
||||
point_value = 2
|
||||
|
||||
/obj/item/stack/sheet/metal/cyborg
|
||||
energy_type = /datum/robot_energy_storage/metal
|
||||
is_cyborg = TRUE
|
||||
materials = list()
|
||||
|
||||
/obj/item/stack/sheet/metal/fifty
|
||||
@@ -162,6 +164,10 @@ GLOBAL_LIST_INIT(plasteel_recipes, list(
|
||||
recipes = GLOB.plasteel_recipes
|
||||
return ..()
|
||||
|
||||
/obj/item/stack/sheet/wood/cyborg
|
||||
energy_type = /datum/robot_energy_storage/wood
|
||||
is_cyborg = TRUE
|
||||
|
||||
/*
|
||||
* Wood
|
||||
*/
|
||||
|
||||
@@ -10,7 +10,16 @@
|
||||
*/
|
||||
/obj/item/stack
|
||||
origin_tech = "materials=1"
|
||||
var/list/recipes = list() // /datum/stack_recipe
|
||||
/// Whether this stack is a `/cyborg` subtype or not.
|
||||
var/is_cyborg = FALSE
|
||||
/// The energy storage datum that will be used with this stack. Used only with `/cyborg` type stacks.
|
||||
var/datum/robot_energy_storage/source
|
||||
/// Which `robot_energy_storage` to choose when this stack is created in cyborgs. Used only with `/cyborg` type stacks.
|
||||
var/energy_type
|
||||
/// How much energy using 1 sheet from the stack costs. Used only with `/cyborg` type stacks.
|
||||
var/cost = 1
|
||||
/// A list of recipes buildable with this stack.
|
||||
var/list/recipes = list()
|
||||
var/singular_name
|
||||
var/amount = 1
|
||||
var/to_transfer = 0
|
||||
@@ -52,15 +61,27 @@
|
||||
|
||||
/obj/item/stack/examine(mob/user)
|
||||
. = ..()
|
||||
if(in_range(user, src))
|
||||
if(!in_range(user, src))
|
||||
return
|
||||
|
||||
if(is_cyborg)
|
||||
if(singular_name)
|
||||
. += "There are [amount] [singular_name]\s in the stack."
|
||||
. += "There is enough energy for [get_amount()] [singular_name]\s."
|
||||
else
|
||||
. += "There are [amount] [name]\s in the stack."
|
||||
. +="<span class='notice'>Alt-click to take a custom amount.</span>"
|
||||
. += "There is enough energy for [get_amount()]."
|
||||
return
|
||||
|
||||
if(singular_name)
|
||||
. += "There are [amount] [singular_name]\s in the stack."
|
||||
else
|
||||
. += "There are [amount] [name]\s in the stack."
|
||||
. +="<span class='notice'>Alt-click to take a custom amount.</span>"
|
||||
|
||||
/obj/item/stack/proc/add(newamount)
|
||||
amount += newamount
|
||||
if(is_cyborg)
|
||||
source.add_charge(newamount * cost)
|
||||
else
|
||||
amount += newamount
|
||||
update_icon()
|
||||
|
||||
/obj/item/stack/attack_self(mob/user)
|
||||
@@ -87,8 +108,10 @@
|
||||
if(!recipes)
|
||||
return
|
||||
|
||||
if(amount <= 0)
|
||||
if(get_amount() <= 0)
|
||||
user << browse(null, "window=stack")
|
||||
if(is_cyborg)
|
||||
to_chat(user, "<span class='warning'>You don't have enough energy to dispense more [name]!</span>")
|
||||
return
|
||||
|
||||
user.set_machine(src) //for correct work of onclose
|
||||
@@ -98,7 +121,7 @@
|
||||
var/datum/stack_recipe_list/srl = recipe_list[recipes_sublist]
|
||||
recipe_list = srl.recipes
|
||||
|
||||
var/t1 = "Amount Left: [amount]<br>"
|
||||
var/t1 = "Amount Left: [get_amount()]<br>"
|
||||
for(var/i in 1 to recipe_list.len)
|
||||
var/E = recipe_list[i]
|
||||
if(isnull(E))
|
||||
@@ -114,7 +137,7 @@
|
||||
|
||||
if(istype(E, /datum/stack_recipe))
|
||||
var/datum/stack_recipe/R = E
|
||||
var/max_multiplier = round(amount / R.req_amount)
|
||||
var/max_multiplier = round(get_amount() / R.req_amount)
|
||||
var/title
|
||||
var/can_build = 1
|
||||
can_build = can_build && (max_multiplier > 0)
|
||||
@@ -154,7 +177,7 @@
|
||||
list_recipes(usr, text2num(href_list["sublist"]))
|
||||
|
||||
if(href_list["make"])
|
||||
if(amount < 1)
|
||||
if(amount < 0 && !is_cyborg)
|
||||
qdel(src) //Never should happen
|
||||
|
||||
var/list/recipes_list = recipes
|
||||
@@ -167,8 +190,8 @@
|
||||
if(!multiplier || multiplier <= 0 || multiplier > 50) // Href exploit checks
|
||||
multiplier = 1
|
||||
|
||||
if(amount < R.req_amount * multiplier)
|
||||
if(R.req_amount * multiplier>1)
|
||||
if(get_amount() < R.req_amount * multiplier)
|
||||
if(R.req_amount * multiplier > 1)
|
||||
to_chat(usr, "<span class='warning'>You haven't got enough [src] to build \the [R.req_amount * multiplier] [R.title]\s!</span>")
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>You haven't got enough [src] to build \the [R.title]!</span>")
|
||||
@@ -195,7 +218,7 @@
|
||||
if(!do_after(usr, R.time, target = usr))
|
||||
return 0
|
||||
|
||||
if(amount < R.req_amount * multiplier)
|
||||
if(get_amount() < R.req_amount * multiplier)
|
||||
return
|
||||
|
||||
var/atom/O
|
||||
@@ -205,6 +228,7 @@
|
||||
O = new R.result_type(usr.drop_location())
|
||||
O.setDir(usr.dir)
|
||||
use(R.req_amount * multiplier)
|
||||
updateUsrDialog()
|
||||
|
||||
R.post_build(src, O)
|
||||
|
||||
@@ -231,6 +255,8 @@
|
||||
/obj/item/stack/use(used, check = TRUE)
|
||||
if(check && zero_amount())
|
||||
return FALSE
|
||||
if(is_cyborg)
|
||||
return source.use_charge(used * cost)
|
||||
if(amount < used)
|
||||
return FALSE
|
||||
amount -= used
|
||||
@@ -240,6 +266,8 @@
|
||||
return TRUE
|
||||
|
||||
/obj/item/stack/proc/get_amount()
|
||||
if(is_cyborg)
|
||||
return round(source.energy / cost)
|
||||
return amount
|
||||
|
||||
/obj/item/stack/proc/get_max_amount()
|
||||
@@ -258,7 +286,7 @@
|
||||
return F
|
||||
|
||||
/obj/item/stack/attack_hand(mob/user)
|
||||
if(user.is_in_inactive_hand(src) && amount > 1)
|
||||
if(user.is_in_inactive_hand(src) && get_amount() > 1)
|
||||
change_stack(user, 1)
|
||||
if(src && usr.machine == src)
|
||||
spawn(0)
|
||||
@@ -272,6 +300,8 @@
|
||||
return
|
||||
if(!in_range(src, user))
|
||||
return
|
||||
if(is_cyborg)
|
||||
return
|
||||
if(!ishuman(usr))
|
||||
return
|
||||
if(amount < 1)
|
||||
@@ -305,11 +335,9 @@
|
||||
// Returns TRUE if the stack amount is zero.
|
||||
// Also qdels the stack gracefully if it is.
|
||||
/obj/item/stack/proc/zero_amount()
|
||||
if(is_cyborg)
|
||||
return source.energy < cost
|
||||
if(amount < 1)
|
||||
if(isrobot(loc))
|
||||
var/mob/living/silicon/robot/R = loc
|
||||
if(locate(src) in R.module.modules)
|
||||
R.module.modules -= src
|
||||
if(ismob(loc))
|
||||
var/mob/living/L = loc // At this stage, stack code is so horrible and atrocious, I wouldn't be all surprised ghosts can somehow have stacks. If this happens, then the world deserves to burn.
|
||||
L.unEquip(src, TRUE)
|
||||
@@ -325,7 +353,10 @@
|
||||
if(QDELETED(S) || QDELETED(src) || S == src) //amusingly this can cause a stack to consume itself, let's not allow that.
|
||||
return FALSE
|
||||
var/transfer = get_amount()
|
||||
transfer = min(transfer, S.max_amount - S.amount)
|
||||
if(S.is_cyborg)
|
||||
transfer = min(transfer, round((S.source.max_energy - S.source.energy) / S.cost))
|
||||
else
|
||||
transfer = min(transfer, S.max_amount - S.amount)
|
||||
if(transfer <= 0)
|
||||
return
|
||||
if(pulledby)
|
||||
@@ -333,6 +364,7 @@
|
||||
S.copy_evidences(src)
|
||||
S.add(transfer)
|
||||
use(transfer)
|
||||
return transfer
|
||||
|
||||
/obj/item/stack/proc/copy_evidences(obj/item/stack/from)
|
||||
blood_DNA = from.blood_DNA
|
||||
|
||||
@@ -61,8 +61,13 @@
|
||||
icon_state = "tile-wood"
|
||||
origin_tech = "biotech=1"
|
||||
turf_type = /turf/simulated/floor/wood
|
||||
merge_type = /obj/item/stack/tile/wood
|
||||
resistance_flags = FLAMMABLE
|
||||
|
||||
/obj/item/stack/tile/wood/cyborg
|
||||
energy_type = /datum/robot_energy_storage/wood_tile
|
||||
is_cyborg = TRUE
|
||||
|
||||
//Carpets
|
||||
/obj/item/stack/tile/carpet
|
||||
name = "carpet"
|
||||
@@ -101,6 +106,10 @@
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 70)
|
||||
resistance_flags = FIRE_PROOF
|
||||
|
||||
/obj/item/stack/tile/plasteel/cyborg
|
||||
energy_type = /datum/robot_energy_storage/metal_tile
|
||||
is_cyborg = TRUE
|
||||
|
||||
//Light
|
||||
/obj/item/stack/tile/light
|
||||
name = "light tiles"
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
toolspeed = 1
|
||||
tool_behaviour = TOOL_MULTITOOL
|
||||
hitsound = 'sound/weapons/tap.ogg'
|
||||
var/shows_wire_information = FALSE // shows what a wire does if set to TRUE
|
||||
var/obj/machinery/buffer // simple machine buffer for device linkage
|
||||
|
||||
/obj/item/multitool/proc/IsBufferA(typepath)
|
||||
@@ -95,7 +94,10 @@
|
||||
/obj/item/multitool/ai_detect/admin
|
||||
desc = "Used for pulsing wires to test which to cut. Not recommended by doctors. Has a strange tag that says 'Grief in Safety'" //What else should I say for a meme item?
|
||||
track_delay = 5
|
||||
shows_wire_information = TRUE
|
||||
|
||||
/obj/item/multitool/ai_detect/admin/Initialize(mapload)
|
||||
. = ..()
|
||||
ADD_TRAIT(src, TRAIT_SHOW_WIRE_INFO, ROUNDSTART_TRAIT)
|
||||
|
||||
/obj/item/multitool/ai_detect/admin/multitool_detect()
|
||||
var/turf/our_turf = get_turf(src)
|
||||
@@ -112,6 +114,12 @@
|
||||
desc = "Optimised and stripped-down version of a regular multitool."
|
||||
toolspeed = 0.5
|
||||
|
||||
/obj/item/multitool/cyborg/drone
|
||||
|
||||
/obj/item/multitool/cyborg/drone/Initialize(mapload)
|
||||
. = ..()
|
||||
ADD_TRAIT(src, TRAIT_SHOW_WIRE_INFO, ROUNDSTART_TRAIT) // Drones are linked to the station
|
||||
|
||||
/obj/item/multitool/abductor
|
||||
name = "alien multitool"
|
||||
desc = "An omni-technological interface."
|
||||
@@ -119,4 +127,7 @@
|
||||
icon_state = "multitool"
|
||||
toolspeed = 0.1
|
||||
origin_tech = "magnets=5;engineering=5;abductor=3"
|
||||
shows_wire_information = TRUE
|
||||
|
||||
/obj/item/multitool/abductor/Initialize(mapload)
|
||||
. = ..()
|
||||
ADD_TRAIT(src, TRAIT_SHOW_WIRE_INFO, ROUNDSTART_TRAIT)
|
||||
|
||||
@@ -177,6 +177,9 @@
|
||||
update_torch()
|
||||
..()
|
||||
|
||||
/obj/item/weldingtool/cyborg_recharge(coeff, emagged)
|
||||
if(reagents.check_and_add("fuel", maximum_fuel, 2 * coeff))
|
||||
update_icon()
|
||||
|
||||
/obj/item/weldingtool/largetank
|
||||
name = "industrial welding tool"
|
||||
|
||||
@@ -62,11 +62,21 @@
|
||||
origin_tech = "materials=5;engineering=4;abductor=3"
|
||||
random_color = FALSE
|
||||
|
||||
/obj/item/wirecutters/abductor/Initialize(mapload)
|
||||
. = ..()
|
||||
ADD_TRAIT(src, TRAIT_SHOW_WIRE_INFO, ROUNDSTART_TRAIT)
|
||||
|
||||
/obj/item/wirecutters/cyborg
|
||||
name = "wirecutters"
|
||||
desc = "This cuts wires."
|
||||
toolspeed = 0.5
|
||||
|
||||
/obj/item/wirecutters/cyborg/drone
|
||||
|
||||
/obj/item/wirecutters/cyborg/drone/Initialize(mapload)
|
||||
. = ..()
|
||||
ADD_TRAIT(src, TRAIT_SHOW_WIRE_INFO, ROUNDSTART_TRAIT) // Drones are linked to the station
|
||||
|
||||
/obj/item/wirecutters/power
|
||||
name = "jaws of life"
|
||||
desc = "A set of jaws of life, the magic of science has managed to fit it down into a device small enough to fit in a tool belt. It's fitted with a cutting head."
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
return
|
||||
else
|
||||
if(loaded.amount < max_amount)
|
||||
var/amount = min(loaded.amount + C.amount, max_amount)
|
||||
var/amount = min(loaded.amount + C.get_amount(), max_amount)
|
||||
C.use(amount - loaded.amount)
|
||||
loaded.amount = amount
|
||||
else
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
desc = "squirts smokey liquids."
|
||||
icon = 'icons/mob/alien.dmi'
|
||||
icon_state = "borg-spray-smoke"
|
||||
list_reagents = list("water" = 50)
|
||||
|
||||
/obj/item/reagent_containers/spray/alien/smoke/afterattack(atom/A as mob|obj, mob/user as mob)
|
||||
if(istype(A, /obj/structure/reagent_dispensers) && get_dist(src,A) <= 1)
|
||||
@@ -45,17 +46,29 @@
|
||||
smoke.start()
|
||||
playsound(user.loc, 'sound/effects/bamf.ogg', 50, 2)
|
||||
|
||||
/obj/item/reagent_containers/spray/alien/smoke/cyborg_recharge(coeff, emagged)
|
||||
reagents.check_and_add("water", volume, 2 * coeff)
|
||||
|
||||
/obj/item/reagent_containers/spray/alien/acid
|
||||
name = "acid synthesizer"
|
||||
desc = "squirts burny liquids."
|
||||
icon = 'icons/mob/alien.dmi'
|
||||
icon_state = "borg-spray-acid"
|
||||
list_reagents = list("facid" = 125, "sacid" = 125)
|
||||
|
||||
/obj/item/reagent_containers/spray/alien/acid/cyborg_recharge(coeff, emagged)
|
||||
reagents.check_and_add("facid", volume / 2, 2 * coeff) // Volume / 2 here becuase there should be an even amount of both chems.
|
||||
reagents.check_and_add("sacid", volume / 2, 2 * coeff)
|
||||
|
||||
/obj/item/reagent_containers/spray/alien/stun
|
||||
name = "paralytic toxin synthesizer"
|
||||
desc = "squirts viagra."
|
||||
icon = 'icons/mob/alien.dmi'
|
||||
icon_state = "borg-spray-stun"
|
||||
list_reagents = list("ether" = 250)
|
||||
|
||||
/obj/item/reagent_containers/spray/alien/stun/cyborg_recharge(coeff, emagged)
|
||||
reagents.check_and_add("ether", volume, 2 * coeff)
|
||||
|
||||
//SKREEEEEEEEEEEE tool
|
||||
|
||||
|
||||
@@ -180,3 +180,6 @@
|
||||
sleep(2)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/extinguisher/cyborg_recharge(coeff, emagged)
|
||||
reagents.check_and_add("water", max_water, 5 * coeff)
|
||||
|
||||
@@ -314,7 +314,7 @@
|
||||
//Therefore, make a new stack internally that has the remainder.
|
||||
// -Sayu
|
||||
|
||||
if(S.amount > S.max_amount)
|
||||
if(S.get_amount() > S.max_amount)
|
||||
var/obj/item/stack/sheet/temp = new S.type(src)
|
||||
temp.amount = S.amount - S.max_amount
|
||||
S.amount = S.max_amount
|
||||
|
||||
@@ -206,6 +206,11 @@
|
||||
return TRUE
|
||||
..()
|
||||
|
||||
/obj/item/melee/baton/cyborg_recharge(coeff, emagged)
|
||||
if(cell)
|
||||
cell.charge = cell.maxcharge
|
||||
update_icon()
|
||||
|
||||
//Makeshift stun baton. Replacement for stun gloves.
|
||||
/obj/item/melee/baton/cattleprod
|
||||
name = "stunprod"
|
||||
|
||||
@@ -69,7 +69,6 @@
|
||||
togglelock(user)
|
||||
|
||||
/obj/structure/closet/secure_closet/AltClick(mob/user)
|
||||
..()
|
||||
if(Adjacent(user))
|
||||
togglelock(user)
|
||||
|
||||
|
||||
@@ -35,10 +35,19 @@
|
||||
QDEL_NULL(showpiece)
|
||||
return ..()
|
||||
|
||||
/obj/structure/displaycase/emag_act(mob/user)
|
||||
if(!emagged)
|
||||
to_chat(user, "<span class='warning'>You override the ID lock on [src].</span>")
|
||||
trigger_alarm()
|
||||
|
||||
emagged = TRUE
|
||||
|
||||
/obj/structure/displaycase/examine(mob/user)
|
||||
. = ..()
|
||||
if(alert)
|
||||
. += "<span class='notice'>Hooked up with an anti-theft system.</span>"
|
||||
if(emagged)
|
||||
. += "<span class='warning'>The ID lock has been shorted out.</span>"
|
||||
if(showpiece)
|
||||
. += "<span class='notice'>There's [showpiece] inside.</span>"
|
||||
if(trophy_message)
|
||||
@@ -100,7 +109,7 @@
|
||||
|
||||
/obj/structure/displaycase/attackby(obj/item/I, mob/user, params)
|
||||
if(I.GetID() && !broken && openable)
|
||||
if(allowed(user))
|
||||
if(allowed(user) || emagged)
|
||||
to_chat(user, "<span class='notice'>You [open ? "close":"open"] [src].</span>")
|
||||
toggle_lock(user)
|
||||
else
|
||||
|
||||
@@ -243,6 +243,7 @@
|
||||
if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = CALLBACK(src, .proc/check_state_and_anchored, state, anchored)))
|
||||
return
|
||||
anchored = !anchored
|
||||
air_update_turf(TRUE)
|
||||
update_nearby_icons()
|
||||
to_chat(user, "<span class='notice'>You [anchored ? "fasten the frame to":"unfasten the frame from"] the floor.</span>")
|
||||
|
||||
@@ -397,7 +398,8 @@
|
||||
return TRUE
|
||||
|
||||
/obj/structure/window/AltClick(mob/user)
|
||||
|
||||
if(fulltile) // Can't rotate these.
|
||||
return ..()
|
||||
if(user.incapacitated())
|
||||
to_chat(user, "<span class='warning'>You can't do that right now!</span>")
|
||||
return
|
||||
|
||||
@@ -237,7 +237,6 @@ GLOBAL_LIST_EMPTY(world_topic_handlers)
|
||||
GLOB.world_href_log = "[GLOB.log_directory]/hrefs.log"
|
||||
GLOB.world_runtime_log = "[GLOB.log_directory]/runtime.log"
|
||||
GLOB.world_qdel_log = "[GLOB.log_directory]/qdel.log"
|
||||
GLOB.world_asset_log = "[GLOB.log_directory]/asset.log"
|
||||
GLOB.tgui_log = "[GLOB.log_directory]/tgui.log"
|
||||
GLOB.http_log = "[GLOB.log_directory]/http.log"
|
||||
GLOB.sql_log = "[GLOB.log_directory]/sql.log"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//Blocks an attempt to connect before even creating our client datum thing.
|
||||
/world/IsBanned(key, address, computer_id, type, check_ipintel = TRUE)
|
||||
/world/IsBanned(key, address, computer_id, type, check_ipintel = TRUE, check_2fa = TRUE)
|
||||
|
||||
if(!key || !address || !computer_id)
|
||||
log_adminwarn("Failed Login (invalid data): [key] [address]-[computer_id]")
|
||||
@@ -44,6 +44,49 @@
|
||||
return list("reason"="using proxy or vpn", "desc"="\nReason: Proxies/VPNs are not allowed here. [mistakemessage]")
|
||||
|
||||
|
||||
// If 2FA is enabled, makes sure they were authed within the last minute
|
||||
if(check_2fa && config._2fa_auth_host)
|
||||
// First see if they exist at all
|
||||
var/datum/db_query/check_query = SSdbcore.NewQuery("SELECT 2fa_status, ip FROM [format_table_name("player")] WHERE ckey=:ckey", list("ckey" = ckey(key)))
|
||||
|
||||
if(!check_query.warn_execute())
|
||||
message_admins("Failed to do a DB 2FA check for [key]. You have been warned.")
|
||||
qdel(check_query)
|
||||
return
|
||||
|
||||
|
||||
// If a row is returned, the player exists
|
||||
var/_2fa_enabled = FALSE
|
||||
var/always_check = FALSE
|
||||
var/last_ip
|
||||
if(check_query.NextRow())
|
||||
if(check_query.item[1] != _2FA_DISABLED)
|
||||
_2fa_enabled = TRUE
|
||||
if(check_query.item[1] == _2FA_ENABLED_ALWAYS)
|
||||
always_check = TRUE
|
||||
last_ip = check_query.item[2]
|
||||
qdel(check_query)
|
||||
|
||||
// If client has 2FA enabled, and they either:
|
||||
// Have it set to always check, or their IP is different
|
||||
if(_2fa_enabled && (always_check || (address != last_ip)))
|
||||
// They have 2FA enabled, lets make sure they have authed within the last minute
|
||||
var/datum/db_query/verify_query = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("2fa_secrets")] WHERE (last_time BETWEEN NOW() - INTERVAL 1 MINUTE AND NOW()) AND ckey=:ckey LIMIT 1", list(
|
||||
"ckey" = ckey(key)
|
||||
))
|
||||
|
||||
if(!verify_query.warn_execute())
|
||||
message_admins("Failed to do a DB 2FA check for [key]. You have been warned.")
|
||||
qdel(verify_query)
|
||||
return
|
||||
|
||||
if(!verify_query.NextRow())
|
||||
// If no row was returned, fail 2FA
|
||||
qdel(verify_query)
|
||||
return list("reason"="2fa check failed", "desc"="You have 2FA enabled but did not properly authenticate.")
|
||||
|
||||
qdel(verify_query)
|
||||
|
||||
if(!GLOB.configuration.general.use_database_bans)
|
||||
//Ban Checking
|
||||
. = CheckBan(ckey(key), computer_id, address)
|
||||
|
||||
@@ -263,6 +263,8 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
|
||||
verbs += GLOB.admin_verbs_proccall
|
||||
if(holder.rights & R_VIEWRUNTIMES)
|
||||
verbs += /client/proc/view_runtimes
|
||||
verbs += /client/proc/cmd_display_del_log
|
||||
verbs += /client/proc/cmd_display_del_log_simple
|
||||
spawn(1) // This setting exposes the profiler for people with R_VIEWRUNTIMES. They must still have it set in cfg/admin.txt
|
||||
control_freak = 0
|
||||
|
||||
|
||||
@@ -2810,7 +2810,7 @@
|
||||
if(R.module)
|
||||
R.module.modules += I
|
||||
I.loc = R.module
|
||||
R.module.rebuild()
|
||||
R.module.rebuild_modules()
|
||||
R.activate_module(I)
|
||||
R.module.fix_modules()
|
||||
|
||||
|
||||
@@ -790,7 +790,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
|
||||
set name = "Display del() Log"
|
||||
set desc = "Display del's log of everything that's passed through it."
|
||||
|
||||
if(!check_rights(R_DEBUG))
|
||||
if(!check_rights(R_DEBUG|R_VIEWRUNTIMES))
|
||||
return
|
||||
|
||||
var/list/dellog = list("<B>List of things that have gone through qdel this round</B><BR><BR><ol>")
|
||||
@@ -822,7 +822,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
|
||||
set name = "Display Simple del() Log"
|
||||
set desc = "Display a compacted del's log."
|
||||
|
||||
if(!check_rights(R_DEBUG))
|
||||
if(!check_rights(R_DEBUG|R_VIEWRUNTIMES))
|
||||
return
|
||||
|
||||
var/dat = "<B>List of things that failed to GC this round</B><BR><BR>"
|
||||
|
||||
@@ -133,7 +133,6 @@
|
||||
area_whitelist = list(/area/medical/virology,
|
||||
/area/toxins,
|
||||
/area/medical/research,
|
||||
/area/medical/research_shuttle_dock,
|
||||
/area/crew_quarters/hor,
|
||||
/area/maintenance/asmaint2)
|
||||
|
||||
@@ -164,7 +163,6 @@
|
||||
TYPE_PSYCHIC)
|
||||
area_blacklist = list(/area/toxins,
|
||||
/area/medical/research,
|
||||
/area/medical/research_shuttle_dock,
|
||||
/area/crew_quarters/hor,
|
||||
/area/maintenance/asmaint2,
|
||||
/area/teleporter,
|
||||
|
||||
@@ -961,15 +961,13 @@
|
||||
if(1)
|
||||
if(iscoil(I))
|
||||
var/obj/item/stack/cable_coil/coil = I
|
||||
if(coil.amount < 5)
|
||||
if(coil.get_amount() < 5)
|
||||
to_chat(user, "You need more cable for this!")
|
||||
return
|
||||
|
||||
to_chat(user, "You wire \the [src]!")
|
||||
playsound(get_turf(src), coil.usesound, 50, 1)
|
||||
coil.amount -= 5
|
||||
if(!coil.amount)
|
||||
qdel(coil)
|
||||
coil.use(5)
|
||||
|
||||
buildstage = 2
|
||||
update_icon()
|
||||
|
||||
@@ -358,61 +358,69 @@ GLOBAL_DATUM_INIT(_preloader, /datum/dmm_suite/preloader, new())
|
||||
/datum/dmm_suite/proc/readlist(text, delimiter = ",")
|
||||
var/list/to_return = list()
|
||||
|
||||
var/position
|
||||
var/delimiter_position
|
||||
var/old_position = 1
|
||||
|
||||
do
|
||||
// find next delimiter that is not within "..."
|
||||
position = find_next_delimiter_position(text, old_position, delimiter)
|
||||
delimiter_position = find_next_delimiter_position(text, old_position, delimiter)
|
||||
|
||||
// check if this is a simple variable (as in list(var1, var2)) or an associative one (as in list(var1="foo", var2=7))
|
||||
var/equal_position = findtext(text, "=", old_position, position)
|
||||
var/equal_position = findtext(text, "=", old_position, delimiter_position)
|
||||
|
||||
var/trim_left = trim_text(copytext(text, old_position, (equal_position ? equal_position : position)), 1) // the name of the variable, must trim quotes to build a BYOND compliant associatives list
|
||||
old_position = position + 1
|
||||
// Take the left value of the association or just the value if it isn't an association
|
||||
var/left_value = copytext(text, old_position, (equal_position ? equal_position : delimiter_position))
|
||||
old_position = delimiter_position + 1
|
||||
|
||||
if(equal_position) // associative var, so do the association
|
||||
var/trim_right = trim_text(copytext(text, equal_position + 1, position)) // the content of the variable
|
||||
left_value = trim_text(left_value, TRUE) // the name of the variable, must trim quotes to build a BYOND compliant associatives list
|
||||
var/trim_right = trim_text(copytext(text, equal_position + 1, delimiter_position)) // the content of the variable
|
||||
|
||||
// Check for string
|
||||
// Make it read to the next delimiter, instead of the quote
|
||||
if(findtext(trim_right, quote, 1, 2))
|
||||
var/endquote = findtext(trim_right, quote, -1)
|
||||
if(!endquote)
|
||||
log_runtime(EXCEPTION("Terminating quote not found!"), src)
|
||||
// Our map writer escapes quotes and curly brackets to avoid
|
||||
// letting our simple parser choke on meanly-crafted names/etc
|
||||
// - so we decode it here so it's back to good ol' legibility
|
||||
trim_right = dmm_decode(copytext(trim_right, 2, endquote))
|
||||
|
||||
// Check for number
|
||||
else if(isnum(text2num(trim_right)))
|
||||
trim_right = text2num(trim_right)
|
||||
|
||||
// Check for null
|
||||
else if(trim_right == "null")
|
||||
trim_right = null
|
||||
|
||||
// Check for list
|
||||
else if(copytext(trim_right, 1, 5) == "list")
|
||||
trim_right = readlist(copytext(trim_right, 6, length(trim_right)))
|
||||
|
||||
// Check for file
|
||||
else if(copytext(trim_right, 1, 2) == "'")
|
||||
trim_right = file(copytext(trim_right, 2, length(trim_right)))
|
||||
|
||||
// Check for path
|
||||
else if(ispath(text2path(trim_right)))
|
||||
trim_right = text2path(trim_right)
|
||||
|
||||
to_return[trim_left] = trim_right
|
||||
to_return[left_value] = parse_value(trim_right)
|
||||
|
||||
else// simple var
|
||||
to_return[trim_left] = null
|
||||
to_return += parse_value(trim_text(left_value)) // Don't trim the quotes
|
||||
|
||||
while(position != 0)
|
||||
while(delimiter_position != 0)
|
||||
|
||||
return to_return
|
||||
/**
|
||||
* Tries to parse the given value_text. Will fallback on the value_text as a string if it fails
|
||||
*/
|
||||
/datum/dmm_suite/proc/parse_value(value_text)
|
||||
// Check for string
|
||||
// Make it read to the next delimiter, instead of the quote
|
||||
if(findtext(value_text, quote, 1, 2))
|
||||
var/endquote = findtext(value_text, quote, -1)
|
||||
if(!endquote)
|
||||
stack_trace("Terminating quote not found!")
|
||||
// Our map writer escapes quotes and curly brackets to avoid
|
||||
// letting our simple parser choke on meanly-crafted names/etc
|
||||
// - so we decode it here so it's back to good ol' legibility
|
||||
. = dmm_decode(copytext(value_text, 2, endquote))
|
||||
|
||||
// Check for number
|
||||
else if(isnum(text2num(value_text)))
|
||||
. = text2num(value_text)
|
||||
|
||||
// Check for null
|
||||
else if(value_text == "null")
|
||||
. = null
|
||||
|
||||
// Check for list
|
||||
else if(copytext(value_text, 1, 5) == "list")
|
||||
. = readlist(copytext(value_text, 6, length(value_text)))
|
||||
|
||||
// Check for file
|
||||
else if(copytext(value_text, 1, 2) == "'")
|
||||
. = file(copytext(value_text, 2, length(value_text)))
|
||||
|
||||
// Check for path
|
||||
else if(ispath(text2path(value_text)))
|
||||
. = text2path(value_text)
|
||||
|
||||
else
|
||||
. = value_text // Assume it is a string without quotes
|
||||
|
||||
/datum/dmm_suite/Destroy()
|
||||
..()
|
||||
@@ -475,7 +483,9 @@ GLOBAL_DATUM_INIT(_preloader, /datum/dmm_suite/preloader, new())
|
||||
if(initial(A.there_can_be_many))
|
||||
area_list[A] = new A
|
||||
else
|
||||
area_list[A] = locate(A)
|
||||
if(!GLOB.all_unique_areas[A])
|
||||
GLOB.all_unique_areas[A] = new A // No locate here else it will find a subtype of the one we're looking for
|
||||
area_list[A] = GLOB.all_unique_areas[A]
|
||||
|
||||
return area_list[A]
|
||||
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
// This is in its own file as it has so much stuff to contend with
|
||||
/client/proc/edit_2fa()
|
||||
if(!config._2fa_auth_host)
|
||||
alert(usr, "This server does not have 2FA enabled.")
|
||||
return
|
||||
// Client does not have 2FA enabled. Set it up.
|
||||
if(prefs._2fa_status == _2FA_DISABLED)
|
||||
// Get us an auth token
|
||||
var/datum/http_response/qrcr = wrap_http_get("[config._2fa_auth_host]/generateQR?ckey=[ckey]")
|
||||
// If this fails, shits gone bad
|
||||
if(qrcr.errored)
|
||||
alert(usr, "Something has gone VERY wrong ingame. Please inform the server host.\nError details: [qrcr.error]")
|
||||
return
|
||||
|
||||
if(qrcr.status_code != 200)
|
||||
alert(usr, "2FA QR code generation returned a non-200 code. Please inform the server host.\nError code: [qrcr.status_code]\nError details: [qrcr.body]")
|
||||
return
|
||||
|
||||
var/list/data = json_decode(qrcr.body)
|
||||
var/qr_img_src = data["qr_image"]
|
||||
var/datum/browser/B = new(usr, "2fa_qrc", "2FA QR Code", 600, 400)
|
||||
var/title_text = "<p>Below is a QR code to scan inside your authenticator app to generate 2FA codes. Please verify it before closing this window. (Behind this window is a text box)</p>"
|
||||
var/img_data = "<div style=\"text-align:center;\"><img src=\"[qr_img_src]\"></div>"
|
||||
B.set_content("[title_text][img_data]")
|
||||
B.open(FALSE)
|
||||
|
||||
var/entered_code = input(usr, "Please enter a code from your auth app. Failure to enter the code correctly will abort 2FA setup.", "2FA Validation")
|
||||
if(!entered_code)
|
||||
// Cleanup so they can start again
|
||||
var/datum/db_query/dbq = SSdbcore.NewQuery("DELETE FROM [format_table_name("2fa_secrets")] WHERE ckey=:ckey", list("ckey" = ckey))
|
||||
dbq.warn_execute()
|
||||
alert(usr, "2FA Setup aborted!")
|
||||
B.close()
|
||||
return
|
||||
|
||||
var/datum/http_response/vr = wrap_http_get("[config._2fa_auth_host]/validateCode?ckey=[ckey]&code=[entered_code]")
|
||||
// If this fails, shits gone bad
|
||||
if(vr.errored)
|
||||
alert(usr, "Something has gone VERY wrong ingame. Please inform the server host.\nError details: [vr.error]")
|
||||
B.close()
|
||||
return
|
||||
|
||||
if(vr.status_code != 200)
|
||||
// Cleanup so they can start again
|
||||
var/datum/db_query/dbq = SSdbcore.NewQuery("DELETE FROM [format_table_name("2fa_secrets")] WHERE ckey=:ckey", list("ckey" = ckey))
|
||||
dbq.warn_execute()
|
||||
|
||||
// See if its unauthorised. I used 400 for that dont at me
|
||||
if(vr.status_code == 400)
|
||||
alert(usr, "Invalid code entered. 2FA Setup aborted!")
|
||||
B.close()
|
||||
else
|
||||
alert(usr, "2FA validation returned a non-200 code. Please inform the server host.\nError code: [vr.status_code]\nError details: [vr.body]")
|
||||
B.close()
|
||||
return
|
||||
|
||||
// If we are here, they authed successfully
|
||||
alert(usr, "Congratulations. 2FA is now setup properly for your account. In preferences, you can change whether you want it to ask for a code on every connection or only when your IP changes")
|
||||
B.close()
|
||||
// Default to IP change only
|
||||
prefs._2fa_status = _2FA_ENABLED_IP
|
||||
prefs.save_preferences(src)
|
||||
prefs.ShowChoices(usr)
|
||||
return
|
||||
|
||||
|
||||
// If we are here, they just want to change the mode
|
||||
var/option = alert(usr, "Would you like to change 2FA mode or disable it entirely?", "2FA Mode", "Enable (Always)", "Enable (On IP Change)", "Deactivate")
|
||||
switch(option)
|
||||
if("Enable (Always)")
|
||||
prefs._2fa_status = _2FA_ENABLED_ALWAYS
|
||||
prefs.save_preferences(src)
|
||||
prefs.ShowChoices(usr)
|
||||
if("Enable (On IP Change)")
|
||||
prefs._2fa_status = _2FA_ENABLED_IP
|
||||
prefs.save_preferences(src)
|
||||
prefs.ShowChoices(usr)
|
||||
if("Deactivate")
|
||||
var/confirm = alert(usr, "Are you SURE you want to deactivate 2FA?", "WARNING", "Yes", "No")
|
||||
if(confirm != "Yes")
|
||||
return
|
||||
|
||||
// Prompt them for a code to make sure they know what they are doing
|
||||
var/entered_code = input(usr, "Please enter a code from your auth app", "2FA Validation")
|
||||
if(!entered_code)
|
||||
alert(usr, "2FA deactivation aborted!")
|
||||
return
|
||||
|
||||
var/datum/http_response/vr = wrap_http_get("[config._2fa_auth_host]/validateCode?ckey=[ckey]&code=[entered_code]")
|
||||
// If this fails, shits gone bad
|
||||
if(vr.errored)
|
||||
alert(usr, "Something has gone VERY wrong ingame. Please inform the server host.\nError details: [vr.error]")
|
||||
return
|
||||
|
||||
if(vr.status_code != 200)
|
||||
// See if its unauthorised. I used 400 for that dont at me
|
||||
if(vr.status_code == 400)
|
||||
alert(usr, "Invalid code entered. 2FA deactivation aborted!")
|
||||
else
|
||||
alert(usr, "2FA validation returned non-200 code. Please inform the server host.\nError code: [vr.status_code]\nError details: [vr.body]")
|
||||
return
|
||||
|
||||
// If we are here, they authed properly
|
||||
var/datum/db_query/dbq = SSdbcore.NewQuery("DELETE FROM [format_table_name("2fa_secrets")] WHERE ckey=:ckey", list("ckey" = ckey))
|
||||
dbq.warn_execute()
|
||||
prefs._2fa_status = _2FA_DISABLED
|
||||
prefs.save_preferences(src)
|
||||
prefs.ShowChoices(usr)
|
||||
alert(usr, "2FA disabled successfully")
|
||||
|
||||
/datum/preferences/proc/_2fastatus_to_text()
|
||||
switch(_2fa_status)
|
||||
if(_2FA_DISABLED)
|
||||
return "Disabled"
|
||||
if(_2FA_ENABLED_IP)
|
||||
return "Enabled (Will prompt on IP changes)"
|
||||
if(_2FA_ENABLED_ALWAYS)
|
||||
return "Enabled (Will prompt every time)"
|
||||
|
||||
|
||||
// Proc to wrap HTTP requests properly, without needing SShttp firing
|
||||
/proc/wrap_http_get(url)
|
||||
var/datum/http_request/req = new()
|
||||
req.prepare(RUSTG_HTTP_METHOD_GET, url)
|
||||
req.begin_async()
|
||||
// Check if we are complete
|
||||
UNTIL(req.is_complete())
|
||||
var/datum/http_response/res = req.into_response()
|
||||
|
||||
return res
|
||||
|
||||
@@ -44,7 +44,6 @@ You can set verify to TRUE if you want send() to sleep until the client has the
|
||||
if(client.cache.Find(asset_name) || client.sending.Find(asset_name))
|
||||
return 0
|
||||
|
||||
log_asset("Sending asset [asset_name] to client [client]")
|
||||
client << browse_rsc(SSassets.cache[asset_name], asset_name)
|
||||
if(!verify) // Can't access the asset cache browser, rip.
|
||||
client.cache += asset_name
|
||||
@@ -93,7 +92,6 @@ You can set verify to TRUE if you want send() to sleep until the client has the
|
||||
to_chat(client, "Sending Resources...")
|
||||
for(var/asset in unreceived)
|
||||
if(asset in SSassets.cache)
|
||||
log_asset("Sending asset [asset] to client [client]")
|
||||
client << browse_rsc(SSassets.cache[asset], asset)
|
||||
|
||||
if(!verify) // Can't access the asset cache browser, rip.
|
||||
|
||||
@@ -205,6 +205,8 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
|
||||
var/gear_tab = "General"
|
||||
// Parallax
|
||||
var/parallax = PARALLAX_HIGH
|
||||
/// 2FA status
|
||||
var/_2fa_status = _2FA_DISABLED
|
||||
/// Do we want to force our runechat colour to be white?
|
||||
var/force_white_runechat = FALSE
|
||||
|
||||
@@ -448,6 +450,7 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
|
||||
// LEFT SIDE OF THE PAGE
|
||||
dat += "<table><tr><td width='340px' height='300px' valign='top'>"
|
||||
dat += "<h2>General Settings</h2>"
|
||||
dat += "<b>2FA Setup:</b> <a href='?_src_=prefs;preference=edit_2fa'>[_2fastatus_to_text()]</a><br>"
|
||||
if(user.client.holder)
|
||||
dat += "<b>Adminhelp sound:</b> <a href='?_src_=prefs;preference=hear_adminhelps'><b>[(sound & SOUND_ADMINHELP)?"On":"Off"]</b></a><br>"
|
||||
dat += "<b>AFK Cryoing:</b> <a href='?_src_=prefs;preference=afk_watch'>[(toggles2 & PREFTOGGLE_2_AFKWATCH) ? "Yes" : "No"]</a><br>"
|
||||
@@ -1415,7 +1418,8 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
|
||||
if(S.autohiss_basic_map)
|
||||
var/list/autohiss_choice = list("Off" = AUTOHISS_OFF, "Basic" = AUTOHISS_BASIC, "Full" = AUTOHISS_FULL)
|
||||
var/new_autohiss_pref = input(user, "Choose your character's auto-accent level:", "Character Preference") as null|anything in autohiss_choice
|
||||
autohiss_mode = autohiss_choice[new_autohiss_pref]
|
||||
if(new_autohiss_pref)
|
||||
autohiss_mode = autohiss_choice[new_autohiss_pref]
|
||||
|
||||
if("metadata")
|
||||
var/new_metadata = input(user, "Enter any information you'd like others to see, such as Roleplay-preferences:", "Game Preference" , metadata) as message|null
|
||||
@@ -2124,6 +2128,11 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
|
||||
if(parent && parent.mob && parent.mob.hud_used)
|
||||
parent.mob.hud_used.update_parallax_pref()
|
||||
|
||||
if("edit_2fa")
|
||||
// Do this async so we arent holding up a topic() call
|
||||
INVOKE_ASYNC(user.client, /client.proc/edit_2fa)
|
||||
return // We return here to avoid focus being lost
|
||||
|
||||
|
||||
ShowChoices(user)
|
||||
return 1
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
clientfps,
|
||||
atklog,
|
||||
fuid,
|
||||
parallax
|
||||
parallax,
|
||||
2fa_status
|
||||
FROM [format_table_name("player")]
|
||||
WHERE ckey=:ckey"}, list(
|
||||
"ckey" = C.ckey
|
||||
@@ -45,6 +46,7 @@
|
||||
atklog = text2num(query.item[14])
|
||||
fuid = text2num(query.item[15])
|
||||
parallax = text2num(query.item[16])
|
||||
_2fa_status = query.item[17]
|
||||
|
||||
qdel(query)
|
||||
|
||||
@@ -93,7 +95,8 @@
|
||||
volume_mixer=:volume_mixer,
|
||||
lastchangelog=:lastchangelog,
|
||||
clientfps=:clientfps,
|
||||
parallax=:parallax
|
||||
parallax=:parallax,
|
||||
2fa_status=:_2fa_status
|
||||
WHERE ckey=:ckey"}, list(
|
||||
// OH GOD THE PARAMETERS
|
||||
"ooccolour" = ooccolor,
|
||||
@@ -111,7 +114,8 @@
|
||||
"lastchangelog" = lastchangelog,
|
||||
"clientfps" = clientfps,
|
||||
"parallax" = parallax,
|
||||
"ckey" = C.ckey
|
||||
"_2fa_status" = _2fa_status,
|
||||
"ckey" = C.ckey,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -424,9 +424,9 @@
|
||||
..()
|
||||
|
||||
/obj/item/clothing/glasses/thermal/monocle
|
||||
name = "thermoncle"
|
||||
name = "thermonocle"
|
||||
desc = "A thermal monocle."
|
||||
icon_state = "thermoncle"
|
||||
icon_state = "thermonocle"
|
||||
flags_cover = null //doesn't protect eyes because it's a monocle, duh
|
||||
|
||||
/obj/item/clothing/glasses/thermal/eyepatch
|
||||
|
||||
@@ -141,7 +141,7 @@
|
||||
user.visible_message("[user] places \the [src] against [M]'s chest and listens attentively.", "You place \the [src] against [M]'s chest...")
|
||||
var/obj/item/organ/internal/H = M.get_int_organ(/obj/item/organ/internal/heart)
|
||||
var/obj/item/organ/internal/L = M.get_int_organ(/obj/item/organ/internal/lungs)
|
||||
if((H && M.pulse) || (L && !HAS_TRAIT(M, TRAIT_NOBREATH)))
|
||||
if(M.pulse && (H || (L && !HAS_TRAIT(M, TRAIT_NOBREATH))))
|
||||
var/color = "notice"
|
||||
if(H)
|
||||
var/heart_sound
|
||||
|
||||
@@ -245,7 +245,7 @@
|
||||
var/obj/item/stack/SD
|
||||
while(amt > 0)
|
||||
S = locate(A) in surroundings
|
||||
if(S.amount >= amt)
|
||||
if(S.get_amount() >= amt)
|
||||
if(!locate(S.type) in Deletion)
|
||||
SD = new S.type()
|
||||
Deletion += SD
|
||||
|
||||
@@ -114,6 +114,9 @@
|
||||
icon_state = "enzyme"
|
||||
list_reagents = list("enzyme" = 50)
|
||||
|
||||
/obj/item/reagent_containers/food/condiment/enzyme/cyborg_recharge(coeff, emagged)
|
||||
reagents.check_and_add("enzyme", volume, 2 * coeff) // Only recharge if the current amount of enzyme is under `volume`.
|
||||
|
||||
/obj/item/reagent_containers/food/condiment/sugar
|
||||
name = "sugar bottle"
|
||||
desc = "Tasty spacey sugar!"
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
return 1
|
||||
if(istype(O,/obj/item/stack))
|
||||
var/obj/item/stack/S = O
|
||||
if(S.amount > 1)
|
||||
if(S.get_amount() > 1)
|
||||
var/obj/item/stack/to_add = S.split(user, 1)
|
||||
to_add.forceMove(src)
|
||||
user.visible_message("<span class='notice'>[user] adds one of [S] to [src].</span>", "<span class='notice'>You add one of [S] to [src].</span>")
|
||||
|
||||
@@ -127,11 +127,13 @@ GLOBAL_LIST_EMPTY(karma_spenders)
|
||||
continue
|
||||
if(M == src)
|
||||
continue
|
||||
if(M.get_preference(PREFTOGGLE_DISABLE_KARMA))
|
||||
continue
|
||||
if(!isobserver(src) && isNonCrewAntag(M))
|
||||
continue // Don't include special roles for non-observers, because players use it to meta
|
||||
karma_list += M
|
||||
|
||||
if(!karma_list.len)
|
||||
if(!length(karma_list))
|
||||
to_chat(usr, "<span class='warning'>There's no-one to spend your karma on.</span>")
|
||||
return
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
if(istype(M))
|
||||
if(isnewplayer(M)) // People in the lobby screen; only have their ckey as a name.
|
||||
continue
|
||||
if(isobserver(M))
|
||||
if(isobserver(M) && M.client)
|
||||
ghosts += list(serialized)
|
||||
else if(M.mind == null)
|
||||
npcs += list(serialized)
|
||||
|
||||
@@ -307,7 +307,7 @@
|
||||
return FALSE
|
||||
if(istype(I, /obj/item/stack))
|
||||
var/obj/item/stack/S = I
|
||||
if(S.amount == 0)
|
||||
if(!S.get_amount())
|
||||
qdel(I)
|
||||
return FALSE
|
||||
if(put_in_active_hand(I))
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
for(var/P in GLOB.dead_mob_list)
|
||||
var/mob/M = P
|
||||
if((M.client?.prefs.toggles2 & PREFTOGGLE_2_DEATHMESSAGE) && (isobserver(M) || M.stat == DEAD))
|
||||
to_chat(M, "<span class='deadsay'><b>[mind.name]</b> has died at <b>[area_name]</b>. (<a href='?src=[M.UID()];jump=\ref[src]'>JMP</a>)</span>")
|
||||
to_chat(M, "<span class='deadsay'><b>[mind.name]</b> has died at <b>[area_name]</b>. (<a href='?src=[M.UID()];jump=\ref[T]'>JMP</a>)</span>")
|
||||
|
||||
if(SSticker && SSticker.mode)
|
||||
SSticker.mode.check_win()
|
||||
|
||||
@@ -527,7 +527,7 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
|
||||
if(check_unable(AI_CHECK_WIRELESS))
|
||||
return
|
||||
|
||||
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 || stat)
|
||||
return
|
||||
|
||||
|
||||
@@ -179,62 +179,6 @@
|
||||
to_chat(user, "<span class='warning'>Nothing on \the [T] is useful to you.</span>")
|
||||
return
|
||||
|
||||
//PRETTIER TOOL LIST.
|
||||
/mob/living/silicon/robot/drone/installed_modules()
|
||||
|
||||
if(weapon_lock)
|
||||
to_chat(src, "<span class='warning'>Weapon lock active, unable to use modules! Count:[weaponlock_time]</span>")
|
||||
return
|
||||
|
||||
if(!module)
|
||||
module = new /obj/item/robot_module/drone(src)
|
||||
|
||||
var/dat = "<HEAD><TITLE>Drone modules</TITLE><META HTTP-EQUIV='Refresh' CONTENT='10'></HEAD><BODY>\n"
|
||||
dat += {"<A HREF='?src=[UID()];mach_close=robotmod'>Close</A>
|
||||
<BR>
|
||||
<BR>
|
||||
<B>Activated Modules</B>
|
||||
<BR>
|
||||
Module 1: [module_state_1 ? "<A HREF=?src=[UID()];mod=\ref[module_state_1]>[module_state_1]<A>" : "No Module"]<BR>
|
||||
Module 2: [module_state_2 ? "<A HREF=?src=[UID()];mod=\ref[module_state_2]>[module_state_2]<A>" : "No Module"]<BR>
|
||||
Module 3: [module_state_3 ? "<A HREF=?src=[UID()];mod=\ref[module_state_3]>[module_state_3]<A>" : "No Module"]<BR>
|
||||
<BR>
|
||||
<B>Installed Modules</B><BR><BR>"}
|
||||
|
||||
|
||||
var/tools = "<B>Tools and devices</B><BR>"
|
||||
var/resources = "<BR><B>Resources</B><BR>"
|
||||
|
||||
for(var/O in module.modules)
|
||||
|
||||
var/module_string = ""
|
||||
|
||||
if(!O)
|
||||
module_string += text("<B>Resource depleted</B><BR>")
|
||||
else if(activated(O))
|
||||
module_string += text("[O]: <B>Activated</B><BR>")
|
||||
else
|
||||
module_string += text("[O]: <A HREF=?src=[UID()];act=\ref[O]>Activate</A><BR>")
|
||||
|
||||
if((istype(O,/obj/item) || istype(O,/obj/item)) && !(istype(O,/obj/item/stack/cable_coil)))
|
||||
tools += module_string
|
||||
else
|
||||
resources += module_string
|
||||
|
||||
dat += tools
|
||||
|
||||
if(emagged)
|
||||
if(!module.emag)
|
||||
dat += text("<B>Resource depleted</B><BR>")
|
||||
else if(activated(module.emag))
|
||||
dat += text("[module.emag]: <B>Activated</B><BR>")
|
||||
else
|
||||
dat += text("[module.emag]: <A HREF=?src=[UID()];act=\ref[module.emag]>Activate</A><BR>")
|
||||
|
||||
dat += resources
|
||||
|
||||
src << browse(dat, "window=robotmod&can_close=0")
|
||||
|
||||
//Putting the decompiler here to avoid doing list checks every tick.
|
||||
/mob/living/silicon/robot/drone/use_power()
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
return 1
|
||||
|
||||
/mob/living/silicon/robot/proc/activate_module(obj/item/O)
|
||||
if(!(locate(O) in src.module.modules) && O != src.module.emag)
|
||||
if(!(locate(O) in module.modules) && !(O in module.emag_modules))
|
||||
return
|
||||
if(activated(O))
|
||||
to_chat(src, "Already activated")
|
||||
|
||||
@@ -470,6 +470,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
|
||||
speed = 0 // Remove upgrades.
|
||||
ionpulse = FALSE
|
||||
magpulse = FALSE
|
||||
weapons_unlock = FALSE
|
||||
add_language("Robot Talk", TRUE)
|
||||
if("lava" in weather_immunities) // Remove the lava-immunity effect given by a printable upgrade
|
||||
weather_immunities -= "lava"
|
||||
@@ -623,17 +624,27 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
|
||||
else
|
||||
stat(null, text("No Cell Inserted!"))
|
||||
|
||||
/mob/living/silicon/robot/proc/show_gps_coords()
|
||||
if(locate(/obj/item/gps/cyborg) in module.modules)
|
||||
var/turf/T = get_turf(src)
|
||||
stat(null, "GPS: [COORD(T)]")
|
||||
|
||||
/mob/living/silicon/robot/proc/show_stack_energy()
|
||||
for(var/storage in module.storages) // Storages should only contain `/datum/robot_energy_storage`
|
||||
var/datum/robot_energy_storage/R = storage
|
||||
stat(null, "[R.statpanel_name]: [R.energy] / [R.max_energy]")
|
||||
|
||||
// update the status screen display
|
||||
/mob/living/silicon/robot/Stat()
|
||||
..()
|
||||
statpanel("Status")
|
||||
if(client.statpanel == "Status")
|
||||
show_cell_power()
|
||||
var/total_user_contents = GetAllContents()
|
||||
if(locate(/obj/item/gps/cyborg) in total_user_contents)
|
||||
var/turf/T = get_turf(src)
|
||||
stat(null, "GPS: [COORD(T)]")
|
||||
if(!statpanel("Status"))
|
||||
return // They aren't looking at the status panel.
|
||||
|
||||
show_cell_power()
|
||||
|
||||
if(module)
|
||||
show_gps_coords()
|
||||
show_stack_energy()
|
||||
|
||||
/mob/living/silicon/robot/restrained()
|
||||
return 0
|
||||
@@ -762,16 +773,12 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
|
||||
to_chat(user, "<span class='warning'>You must access the borg's internals!</span>")
|
||||
else if(!src.module && U.require_module)
|
||||
to_chat(user, "<span class='warning'>The borg must choose a module before it can be upgraded!</span>")
|
||||
else if(U.locked)
|
||||
to_chat(user, "<span class='warning'>The upgrade is locked and cannot be used yet!</span>")
|
||||
else
|
||||
if(!user.drop_item())
|
||||
return
|
||||
if(U.action(src))
|
||||
user.visible_message("<span class = 'notice'>[user] applied [U] to [src].</span>", "<span class='notice'>You apply [U] to [src].</span>")
|
||||
user.visible_message("<span class='notice'>[user] applied [U] to [src].</span>", "<span class='notice'>You apply [U] to [src].</span>")
|
||||
U.forceMove(src)
|
||||
else
|
||||
to_chat(user, "<span class='danger'>Upgrade error.</span>")
|
||||
|
||||
else if(istype(W, /obj/item/mmi_radio_upgrade))
|
||||
if(!opened)
|
||||
@@ -898,7 +905,19 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
|
||||
spark_system.start()
|
||||
..()
|
||||
|
||||
/mob/living/silicon/robot/emag_act(user as mob)
|
||||
// Here so admins can unemag borgs.
|
||||
/mob/living/silicon/robot/unemag()
|
||||
SetEmagged(FALSE)
|
||||
if(!module)
|
||||
return
|
||||
uneq_all()
|
||||
module.module_type = initial(module.module_type)
|
||||
update_module_icon()
|
||||
module.unemag()
|
||||
clear_supplied_laws()
|
||||
laws = new /datum/ai_laws/crewsimov
|
||||
|
||||
/mob/living/silicon/robot/emag_act(mob/user)
|
||||
if(!ishuman(user) && !issilicon(user))
|
||||
return
|
||||
var/mob/living/M = user
|
||||
@@ -913,7 +932,8 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
|
||||
return
|
||||
|
||||
if(opened)//Cover is open
|
||||
if(emagged) return//Prevents the X has hit Y with Z message also you cant emag them twice
|
||||
if(emagged)
|
||||
return //Prevents the X has hit Y with Z message also you cant emag them twice
|
||||
if(wiresexposed)
|
||||
to_chat(user, "You must close the panel first")
|
||||
return
|
||||
@@ -921,11 +941,10 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
|
||||
sleep(6)
|
||||
SetEmagged(TRUE)
|
||||
SetLockdown(1) //Borgs were getting into trouble because they would attack the emagger before the new laws were shown
|
||||
if(src.hud_used)
|
||||
src.hud_used.update_robot_modules_display() //Shows/hides the emag item if the inventory screen is already open.
|
||||
if(hud_used)
|
||||
hud_used.update_robot_modules_display() //Shows/hides the emag item if the inventory screen is already open.
|
||||
disconnect_from_ai()
|
||||
to_chat(user, "You emag [src]'s interface.")
|
||||
// message_admins("[key_name_admin(user)] emagged cyborg [key_name_admin(src)]. Laws overridden.")
|
||||
log_game("[key_name(user)] emagged cyborg [key_name(src)]. Laws overridden.")
|
||||
clear_supplied_laws()
|
||||
clear_inherent_laws()
|
||||
@@ -951,17 +970,11 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
|
||||
laws.show_laws(src)
|
||||
to_chat(src, "<span class='boldwarning'>ALERT: [M.real_name] is your new master. Obey your new laws and [M.p_their()] commands.</span>")
|
||||
SetLockdown(0)
|
||||
if(src.module && istype(src.module, /obj/item/robot_module/miner))
|
||||
for(var/obj/item/pickaxe/drill/cyborg/D in src.module.modules)
|
||||
qdel(D)
|
||||
src.module.modules += new /obj/item/pickaxe/drill/cyborg/diamond(src.module)
|
||||
src.module.rebuild()
|
||||
if(src.module && istype(src.module, /obj/item/robot_module/medical))
|
||||
for(var/obj/item/borg_defib/F in src.module.modules)
|
||||
F.safety = 0
|
||||
if(module)
|
||||
module.emag_act()
|
||||
module.module_type = "Malf" // For the cool factor
|
||||
update_module_icon()
|
||||
module.rebuild_modules() // This will add the emagged items to the borgs inventory.
|
||||
update_icons()
|
||||
return
|
||||
|
||||
@@ -1029,51 +1042,6 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
|
||||
/mob/living/silicon/robot/proc/borg_icons() // Exists so that robot/destroyer can override it
|
||||
return
|
||||
|
||||
/mob/living/silicon/robot/proc/installed_modules()
|
||||
if(weapon_lock)
|
||||
to_chat(src, "<span class='warning'>Weapon lock active, unable to use modules! Count:[weaponlock_time]</span>")
|
||||
return
|
||||
|
||||
if(!module)
|
||||
pick_module()
|
||||
return
|
||||
var/dat = {"<A HREF='?src=[UID()];mach_close=robotmod'>Close</A>
|
||||
<BR>
|
||||
<BR>
|
||||
<B>Activated Modules</B>
|
||||
<BR>
|
||||
<table border='0'>
|
||||
<tr><td>Module 1:</td><td>[module_state_1 ? "<A HREF=?src=[UID()];mod=\ref[module_state_1]>[module_state_1]<A>" : "No Module"]</td></tr>
|
||||
<tr><td>Module 2:</td><td>[module_state_2 ? "<A HREF=?src=[UID()];mod=\ref[module_state_2]>[module_state_2]<A>" : "No Module"]</td></tr>
|
||||
<tr><td>Module 3:</td><td>[module_state_3 ? "<A HREF=?src=[UID()];mod=\ref[module_state_3]>[module_state_3]<A>" : "No Module"]</td></tr>
|
||||
</table><BR>
|
||||
<B>Installed Modules</B><BR><BR>
|
||||
|
||||
<table border='0'>"}
|
||||
for(var/obj in module.modules)
|
||||
if(!obj)
|
||||
dat += text("<tr><td><B>Resource depleted</B></td></tr>")
|
||||
else if(activated(obj))
|
||||
dat += text("<tr><td>[obj]</td><td><B>Activated</B></td></tr>")
|
||||
else
|
||||
dat += text("<tr><td>[obj]</td><td><A HREF=?src=[UID()];act=\ref[obj]>Activate</A></td></tr>")
|
||||
if(emagged || weapons_unlock)
|
||||
if(activated(module.emag))
|
||||
dat += text("<tr><td>[module.emag]</td><td><B>Activated</B></td></tr>")
|
||||
else
|
||||
dat += text("<tr><td>[module.emag]</td><td><A HREF=?src=[UID()];act=\ref[module.emag]>Activate</A></td></tr>")
|
||||
dat += "</table>"
|
||||
/*
|
||||
if(activated(obj))
|
||||
dat += text("[obj]: \[<B>Activated</B> | <A HREF=?src=[UID()];deact=\ref[obj]>Deactivate</A>\]<BR>")
|
||||
else
|
||||
dat += text("[obj]: \[<A HREF=?src=[UID()];act=\ref[obj]>Activate</A> | <B>Deactivated</B>\]<BR>")
|
||||
*/
|
||||
var/datum/browser/popup = new(src, "robotmod", "Modules")
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
|
||||
|
||||
/mob/living/silicon/robot/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
@@ -1099,7 +1067,6 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
|
||||
return 1
|
||||
|
||||
activate_module(O)
|
||||
installed_modules()
|
||||
|
||||
//Show alerts window if user clicked on "Show alerts" in chat
|
||||
if(href_list["showalerts"])
|
||||
@@ -1122,7 +1089,6 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
|
||||
to_chat(src, "Module isn't activated.")
|
||||
else
|
||||
to_chat(src, "Module isn't activated")
|
||||
installed_modules()
|
||||
return 1
|
||||
|
||||
return 1
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -449,6 +449,7 @@
|
||||
|
||||
var/dat = "<html><body><center>"
|
||||
dat += "Round Duration: [round(hours)]h [round(mins)]m<br>"
|
||||
dat += "<b>The station alert level is: [get_security_level_colors()]</b><br>"
|
||||
|
||||
if(SSshuttle.emergency.mode >= SHUTTLE_ESCAPE)
|
||||
dat += "<font color='red'><b>The station has been evacuated.</b></font><br>"
|
||||
|
||||
@@ -596,7 +596,7 @@ GLOBAL_LIST_INIT(cable_coil_recipes, list (new/datum/stack_recipe("cable restrai
|
||||
|
||||
/obj/item/stack/cable_coil/examine(mob/user)
|
||||
. = ..()
|
||||
if(in_range(user, src))
|
||||
if(in_range(user, src) && !is_cyborg)
|
||||
if(get_amount() == 1)
|
||||
. += "A short piece of power cable."
|
||||
else if(get_amount() == 2)
|
||||
@@ -612,10 +612,10 @@ GLOBAL_LIST_INIT(cable_coil_recipes, list (new/datum/stack_recipe("cable restrai
|
||||
if(istype(W, /obj/item/stack/cable_coil))
|
||||
var/obj/item/stack/cable_coil/C = W
|
||||
// Cable merging is handled by parent proc
|
||||
if(C.amount >= MAXCOIL)
|
||||
if(C.get_amount() >= MAXCOIL)
|
||||
to_chat(user, "The coil is as long as it will get.")
|
||||
return
|
||||
if( (C.amount + src.amount <= MAXCOIL) )
|
||||
if((C.get_amount() + get_amount() <= MAXCOIL))
|
||||
to_chat(user, "You join the cable coils together.")
|
||||
return
|
||||
else
|
||||
@@ -861,7 +861,11 @@ GLOBAL_LIST_INIT(cable_coil_recipes, list (new/datum/stack_recipe("cable restrai
|
||||
return color
|
||||
|
||||
/obj/item/stack/cable_coil/cyborg
|
||||
name = "cyborg cable coil"
|
||||
energy_type = /datum/robot_energy_storage/cable
|
||||
is_cyborg = TRUE
|
||||
|
||||
/obj/item/stack/cable_coil/cyborg/update_icon()
|
||||
return // icon_state should always be a full cable
|
||||
|
||||
/obj/item/stack/cable_coil/cyborg/attack_self(mob/user)
|
||||
var/cablecolor = input(user,"Pick a cable color.","Cable Color") in list("red","yellow","green","blue","pink","orange","cyan","white")
|
||||
|
||||
@@ -249,6 +249,8 @@
|
||||
/obj/machinery/power/port_gen/pacman/proc/overheat()
|
||||
overheating++
|
||||
if(overheating > 60)
|
||||
message_admins("Pacman overheated at [ADMIN_JMP(loc)]. Last touched by: [fingerprintslast ? "[fingerprintslast]" : "*null*"].")
|
||||
log_game("Pacman overheated at [COORD(loc)]. Last touched by: [fingerprintslast ? "[fingerprintslast]" : "*null*"].")
|
||||
explode()
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/explode()
|
||||
|
||||
@@ -149,7 +149,7 @@
|
||||
return
|
||||
|
||||
var/obj/item/stack/cable_coil/C = I
|
||||
if(C.amount < 10)
|
||||
if(C.get_amount() < 10)
|
||||
to_chat(user, "<span class='alert'>You need more wires.</span>")
|
||||
return
|
||||
|
||||
|
||||
@@ -220,7 +220,7 @@
|
||||
if(istype(W, /obj/item/stack/sheet/glass) || istype(W, /obj/item/stack/sheet/rglass))
|
||||
var/obj/item/stack/sheet/S = W
|
||||
if(S.use(2))
|
||||
glass_type = W.type
|
||||
glass_type = S.merge_type
|
||||
playsound(loc, S.usesound, 50, 1)
|
||||
user.visible_message("[user] places the glass on the solar assembly.", "<span class='notice'>You place the glass on the solar assembly.</span>")
|
||||
if(tracker)
|
||||
|
||||
@@ -216,6 +216,7 @@
|
||||
/obj/machinery/gateway,
|
||||
/obj/structure/lattice,
|
||||
/obj/structure/grille,
|
||||
/obj/structure/cable,
|
||||
/obj/machinery/the_singularitygen/tesla,
|
||||
/obj/machinery/constructable_frame/machine_frame))
|
||||
|
||||
|
||||
@@ -55,3 +55,12 @@
|
||||
/obj/item/gun/energy/disabler/cyborg/newshot()
|
||||
..()
|
||||
robocharge()
|
||||
|
||||
/obj/item/gun/energy/disabler/cyborg/cyborg_recharge(coeff, emagged)
|
||||
if(cell.charge < cell.maxcharge)
|
||||
var/obj/item/ammo_casing/energy/E = ammo_type[select]
|
||||
cell.give(E.e_cost * coeff)
|
||||
on_recharge()
|
||||
update_icon()
|
||||
else
|
||||
charge_tick = 0
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
return 0
|
||||
for(var/obj/effect/ebeam/medical/B in turf)// Don't cross the str-beams!
|
||||
if(B.owner != current_beam)
|
||||
turf.visible_message("<span class='boldwarning'>The medbeams cross and EXPLODE!</span>")
|
||||
turf.visible_message("<span class='userdanger'>The medbeams cross and EXPLODE!</span>")
|
||||
explosion(B.loc,0,3,5,8)
|
||||
qdel(dummy)
|
||||
return 0
|
||||
|
||||
@@ -1011,7 +1011,7 @@
|
||||
reagent_state = LIQUID
|
||||
color = "#FFDCFF"
|
||||
taste_description = "stability"
|
||||
var/list/drug_list = list("crank","methamphetamine","space_drugs","psilocybin","ephedrine","epinephrine","stimulants","bath_salts","lsd","thc")
|
||||
var/list/drug_list = list("crank", "methamphetamine", "space_drugs", "synaptizine", "psilocybin", "ephedrine", "epinephrine", "stimulants", "stimulative_agent", "bath_salts", "lsd", "thc")
|
||||
|
||||
/datum/reagent/medicine/haloperidol/on_mob_life(mob/living/M)
|
||||
var/update_flags = STATUS_UPDATE_NONE
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user