Merge branch 'master' into upstream-merge-31128
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
//config files
|
||||
#define CONFIG_DEF(X) /datum/config_entry/##X { resident_file = CURRENT_RESIDENT_FILE }; /datum/config_entry/##X
|
||||
#define CONFIG_GET(X) global.config.Get(/datum/config_entry/##X)
|
||||
#define CONFIG_SET(X, Y) global.config.Set(/datum/config_entry/##X, ##Y)
|
||||
|
||||
#define CONFIG_MAPS_FILE "maps.txt"
|
||||
|
||||
//flags
|
||||
#define CONFIG_ENTRY_LOCKED 1 //can't edit
|
||||
#define CONFIG_ENTRY_HIDDEN 2 //can't see value
|
||||
@@ -53,6 +53,9 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
|
||||
// TESLA_IGNORE grants immunity from being targeted by tesla-style electricity
|
||||
#define TESLA_IGNORE_2 512
|
||||
|
||||
// Stops you from putting things like an RCD or other items into an ORM or protolathe for materials.
|
||||
#define NO_MAT_REDEMPTION_2 1024
|
||||
|
||||
//turf-only flags
|
||||
#define NOJAUNT_1 1
|
||||
#define UNUSED_TRANSIT_TURF_1 2
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#define PLANE_SPACE_PARALLAX -90
|
||||
|
||||
#define GAME_PLANE 0
|
||||
#define SPACE_LAYER 1.8
|
||||
#define ABOVE_SPACE_LAYER 1.9
|
||||
//#define TURF_LAYER 2 //For easy recordkeeping; this is a byond define
|
||||
#define MID_TURF_LAYER 2.02
|
||||
#define HIGH_TURF_LAYER 2.03
|
||||
|
||||
+103
-14
@@ -1,34 +1,123 @@
|
||||
// /tg/station 13 server tools API v3.1
|
||||
|
||||
//CONFIGURATION
|
||||
//use this define if you want to do configuration outside of this file
|
||||
#ifndef SERVER_TOOLS_EXTERNAL_CONFIGURATION
|
||||
//Comment this out once you've filled in the below
|
||||
//#error /tg/station server tools interface unconfigured
|
||||
|
||||
//Required interfaces (fill in with your codebase equivalent):
|
||||
|
||||
//create a global variable named `Name` and set it to `Value`
|
||||
//These globals must not be modifiable from anywhere outside of the server tools
|
||||
#define SERVER_TOOLS_DEFINE_AND_SET_GLOBAL(Name, Value) GLOBAL_VAR_INIT(##Name, ##Value); GLOBAL_PROTECT(##Name)
|
||||
//Read the value in the global variable `Name`
|
||||
#define SERVER_TOOLS_READ_GLOBAL(Name) GLOB.##Name
|
||||
//Set the value in the global variable `Name` to `Value`
|
||||
#define SERVER_TOOLS_WRITE_GLOBAL(Name, Value) GLOB.##Name = ##Value
|
||||
//display an announcement `message` from the server to all players
|
||||
#define SERVER_TOOLS_WORLD_ANNOUNCE(message) to_chat(world, "<span class='boldannounce'>[html_encode(##message)]</span>")
|
||||
//Write a string `message` to a server log
|
||||
#define SERVER_TOOLS_LOG(message) log_world("SERVICE: [##message]")
|
||||
//Notify current in-game administrators of a string `event`
|
||||
#define SERVER_TOOLS_NOTIFY_ADMINS(event) message_admins(##event)
|
||||
#endif
|
||||
|
||||
//Required hooks:
|
||||
|
||||
//Put this somewhere in /world/New() that is always run
|
||||
#define SERVER_TOOLS_ON_NEW ServiceInit()
|
||||
//Put this somewhere in /world/Topic(T, Addr, Master, Keys) that is always run before T is modified
|
||||
#define SERVER_TOOLS_ON_TOPIC var/service_topic_return = ServiceCommand(params2list(T)); if(service_topic_return) return service_topic_return
|
||||
//Put at the beginning of world/Reboot(reason)
|
||||
#define SERVER_TOOLS_ON_REBOOT ServiceReboot()
|
||||
|
||||
//Optional callable functions:
|
||||
|
||||
//Returns the string version of the API
|
||||
#define SERVER_TOOLS_API_VERSION ServiceAPIVersion()
|
||||
//Returns TRUE if the world was launched under the server tools and the API matches, FALSE otherwise
|
||||
//No function below this succeed if this is FALSE
|
||||
#define SERVER_TOOLS_PRESENT RunningService()
|
||||
//Gets the current version of the service running the server
|
||||
#define SERVER_TOOLS_VERSION ServiceVersion()
|
||||
//Forces a hard reboot of BYOND by ending the process
|
||||
//unlike del(world) clients will try to reconnect
|
||||
//If the service has not requested a shutdown, the world will reboot shortly after
|
||||
#define SERVER_TOOLS_REBOOT_BYOND world.ServiceEndProcess()
|
||||
/*
|
||||
Gets the list of any testmerged github pull requests
|
||||
|
||||
"[PR Number]" => list(
|
||||
"title" -> PR title
|
||||
"commit" -> Full hash of commit merged
|
||||
"author" -> Github username of the author of the PR
|
||||
)
|
||||
*/
|
||||
#define SERVER_TOOLS_PR_LIST GetTestMerges()
|
||||
//Sends a message to connected game chats
|
||||
#define SERVER_TOOLS_CHAT_BROADCAST(message) world.ChatBroadcast(message)
|
||||
//Sends a message to connected admin chats
|
||||
#define SERVER_TOOLS_RELAY_BROADCAST(message) world.AdminBroadcast(message)
|
||||
|
||||
//IMPLEMENTATION
|
||||
|
||||
#define SERVICE_API_VERSION_STRING "3.1.0.0"
|
||||
|
||||
#define REBOOT_MODE_NORMAL 0
|
||||
#define REBOOT_MODE_HARD 1
|
||||
#define REBOOT_MODE_SHUTDOWN 2
|
||||
|
||||
#define IRC_STATUS_THROTTLE 5
|
||||
|
||||
#define PR_ANNOUNCEMENTS_PER_ROUND 5 //The number of unique PR announcements allowed per round
|
||||
//This makes sure that a single person can only spam 3 reopens and 3 closes before being ignored
|
||||
|
||||
//keep these in sync with TGS3
|
||||
#define SERVICE_WORLD_PARAM "server_service"
|
||||
#define SERVICE_VERSION_PARAM "server_service_version"
|
||||
#define SERVICE_PR_TEST_JSON "prtestjob.json"
|
||||
#define SERVICE_PR_TEST_JSON_OLD "..\\..\\[SERVICE_PR_TEST_JSON]"
|
||||
#define SERVICE_INTERFACE_DLL "TGServiceInterface.dll"
|
||||
#define SERVICE_INTERFACE_FUNCTION "DDEntryPoint"
|
||||
|
||||
#define SERVICE_CMD_HARD_REBOOT "hard_reboot"
|
||||
#define SERVICE_CMD_GRACEFUL_SHUTDOWN "graceful_shutdown"
|
||||
#define SERVICE_CMD_WORLD_ANNOUNCE "world_announce"
|
||||
#define SERVICE_CMD_IRC_CHECK "irc_check"
|
||||
#define SERVICE_CMD_IRC_STATUS "irc_status"
|
||||
#define SERVICE_CMD_ADMIN_MSG "adminmsg"
|
||||
#define SERVICE_CMD_NAME_CHECK "namecheck"
|
||||
#define SERVICE_CMD_ADMIN_WHO "adminwho"
|
||||
#define SERVICE_CMD_LIST_CUSTOM "list_custom_commands"
|
||||
|
||||
#define SERVICE_CMD_PARAM_KEY "serviceCommsKey"
|
||||
#define SERVICE_CMD_PARAM_COMMAND "command"
|
||||
#define SERVICE_CMD_PARAM_MESSAGE "message"
|
||||
#define SERVICE_CMD_PARAM_TARGET "target"
|
||||
#define SERVICE_CMD_PARAM_SENDER "sender"
|
||||
#define SERVICE_CMD_PARAM_CUSTOM "custom"
|
||||
#define SERVICE_CMD_API_COMPATIBLE "api_compat"
|
||||
|
||||
#define SERVICE_JSON_PARAM_HELPTEXT "help_text"
|
||||
#define SERVICE_JSON_PARAM_ADMINONLY "admin_only"
|
||||
#define SERVICE_JSON_PARAM_REQUIREDPARAMETERS "required_parameters"
|
||||
|
||||
#define SERVICE_REQUEST_KILL_PROCESS "killme"
|
||||
#define SERVICE_REQUEST_IRC_BROADCAST "irc"
|
||||
#define SERVICE_REQUEST_IRC_ADMIN_CHANNEL_MESSAGE "send2irc"
|
||||
#define SERVICE_REQUEST_WORLD_REBOOT "worldreboot"
|
||||
#define SERVICE_REQUEST_API_VERSION "api_ver"
|
||||
|
||||
/*
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2011 Dominic Tarr
|
||||
|
||||
Permission is hereby granted, free of charge,
|
||||
to any person obtaining a copy of this software and
|
||||
associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom
|
||||
the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
+21
-17
@@ -26,74 +26,74 @@
|
||||
|
||||
/proc/log_admin(text)
|
||||
GLOB.admin_log.Add(text)
|
||||
if (config.log_admin)
|
||||
if (CONFIG_GET(flag/log_admin))
|
||||
WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]ADMIN: [text]")
|
||||
|
||||
//Items using this proc are stripped from public logs - use with caution
|
||||
/proc/log_admin_private(text)
|
||||
GLOB.admin_log.Add(text)
|
||||
if (config.log_admin)
|
||||
if (CONFIG_GET(flag/log_admin))
|
||||
WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]ADMINPRIVATE: [text]")
|
||||
|
||||
/proc/log_adminsay(text)
|
||||
if (config.log_adminchat)
|
||||
if (CONFIG_GET(flag/log_adminchat))
|
||||
log_admin_private("ASAY: [text]")
|
||||
|
||||
/proc/log_dsay(text)
|
||||
if (config.log_adminchat)
|
||||
if (CONFIG_GET(flag/log_adminchat))
|
||||
log_admin("DSAY: [text]")
|
||||
|
||||
/proc/log_game(text)
|
||||
if (config.log_game)
|
||||
if (CONFIG_GET(flag/log_game))
|
||||
WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]GAME: [text]")
|
||||
|
||||
/proc/log_vote(text)
|
||||
if (config.log_vote)
|
||||
if (CONFIG_GET(flag/log_vote))
|
||||
WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]VOTE: [text]")
|
||||
|
||||
/proc/log_access(text)
|
||||
if (config.log_access)
|
||||
if (CONFIG_GET(flag/log_access))
|
||||
WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]ACCESS: [text]")
|
||||
|
||||
/proc/log_say(text)
|
||||
if (config.log_say)
|
||||
if (CONFIG_GET(flag/log_say))
|
||||
WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]SAY: [text]")
|
||||
|
||||
/proc/log_prayer(text)
|
||||
if (config.log_prayer)
|
||||
if (CONFIG_GET(flag/log_prayer))
|
||||
WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]PRAY: [text]")
|
||||
|
||||
/proc/log_law(text)
|
||||
if (config.log_law)
|
||||
if (CONFIG_GET(flag/log_law))
|
||||
WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]LAW: [text]")
|
||||
|
||||
/proc/log_ooc(text)
|
||||
if (config.log_ooc)
|
||||
if (CONFIG_GET(flag/log_ooc))
|
||||
WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]OOC: [text]")
|
||||
|
||||
/proc/log_whisper(text)
|
||||
if (config.log_whisper)
|
||||
if (CONFIG_GET(flag/log_whisper))
|
||||
WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]WHISPER: [text]")
|
||||
|
||||
/proc/log_emote(text)
|
||||
if (config.log_emote)
|
||||
if (CONFIG_GET(flag/log_emote))
|
||||
WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]EMOTE: [text]")
|
||||
|
||||
/proc/log_attack(text)
|
||||
if (config.log_attack)
|
||||
if (CONFIG_GET(flag/log_attack))
|
||||
WRITE_FILE(GLOB.world_attack_log, "\[[time_stamp()]]ATTACK: [text]")
|
||||
|
||||
/proc/log_pda(text)
|
||||
if (config.log_pda)
|
||||
if (CONFIG_GET(flag/log_pda))
|
||||
WRITE_FILE(GLOB.world_pda_log, "\[[time_stamp()]]PDA: [text]")
|
||||
|
||||
/proc/log_comment(text)
|
||||
if (config.log_pda)
|
||||
if (CONFIG_GET(flag/log_pda))
|
||||
//reusing the PDA option because I really don't think news comments are worth a config option
|
||||
WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]COMMENT: [text]")
|
||||
|
||||
/proc/log_chat(text)
|
||||
if (config.log_pda)
|
||||
if (CONFIG_GET(flag/log_pda))
|
||||
WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]CHAT: [text]")
|
||||
|
||||
/proc/log_qdel(text)
|
||||
@@ -102,6 +102,10 @@
|
||||
/proc/log_sql(text)
|
||||
WRITE_FILE(GLOB.sql_error_log, "\[[time_stamp()]]SQL: [text]")
|
||||
|
||||
/proc/log_config(text)
|
||||
WRITE_FILE(GLOB.config_error_log, text)
|
||||
SEND_TEXT(world.log, text)
|
||||
|
||||
//This replaces world.log so it displays both in DD and the file
|
||||
/proc/log_world(text)
|
||||
WRITE_FILE(GLOB.world_runtime_log, text)
|
||||
|
||||
@@ -314,10 +314,11 @@
|
||||
|
||||
// Will return a list of active candidates. It increases the buffer 5 times until it finds a candidate which is active within the buffer.
|
||||
|
||||
/proc/get_candidates(be_special_type, afk_bracket = config.inactivity_period, jobbanType)
|
||||
/proc/get_candidates(be_special_type, afk_bracket = CONFIG_GET(number/inactivity_period), jobbanType)
|
||||
var/list/candidates = list()
|
||||
// Keep looping until we find a non-afk candidate within the time bracket (we limit the bracket to 10 minutes (6000))
|
||||
while(!candidates.len && afk_bracket < config.afk_period)
|
||||
var/afk_period = CONFIG_GET(number/afk_period)
|
||||
while(!candidates.len && afk_bracket < afk_period)
|
||||
for(var/mob/dead/observer/G in GLOB.player_list)
|
||||
if(G.client != null)
|
||||
if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD))
|
||||
|
||||
+115
-116
@@ -1,116 +1,115 @@
|
||||
//////////////////////////
|
||||
/////Initial Building/////
|
||||
//////////////////////////
|
||||
|
||||
/proc/make_datum_references_lists()
|
||||
//hair
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/hair, GLOB.hair_styles_list, GLOB.hair_styles_male_list, GLOB.hair_styles_female_list)
|
||||
//facial hair
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/facial_hair, GLOB.facial_hair_styles_list, GLOB.facial_hair_styles_male_list, GLOB.facial_hair_styles_female_list)
|
||||
//underwear
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/underwear, GLOB.underwear_list, GLOB.underwear_m, GLOB.underwear_f)
|
||||
//undershirt
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/undershirt, GLOB.undershirt_list, GLOB.undershirt_m, GLOB.undershirt_f)
|
||||
//socks
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/socks, GLOB.socks_list)
|
||||
//lizard bodyparts (blizzard intensifies)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/body_markings, GLOB.body_markings_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/lizard, GLOB.tails_list_lizard)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/tails_animated/lizard, GLOB.animated_tails_list_lizard)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/human, GLOB.tails_list_human)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/tails_animated/human, GLOB.animated_tails_list_human)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/snouts, GLOB.snouts_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/horns,GLOB.horns_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/ears, GLOB.ears_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/wings, GLOB.wings_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/wings_open, GLOB.wings_open_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/frills, GLOB.frills_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/spines, GLOB.spines_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/spines_animated, GLOB.animated_spines_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/legs, GLOB.legs_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/wings, GLOB.r_wings_list,roundstart = TRUE)
|
||||
|
||||
//citadel code
|
||||
//mammal bodyparts (fucking furries)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_body_markings, GLOB.mam_body_markings_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_tails, GLOB.mam_tails_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_ears, GLOB.mam_ears_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_tails_animated, GLOB.mam_tails_animated_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/taur, GLOB.taur_list)
|
||||
//avian bodyparts (i swear this isn't starbound)
|
||||
// init_sprite_accessory_subtypes(/datum/sprite_accessory/beaks/avian, GLOB.avian_beaks_list)
|
||||
// init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/avian, GLOB.avian_tails_list)
|
||||
// init_sprite_accessory_subtypes(/datum/sprite_accessory/avian_wings, GLOB.avian_wings_list)
|
||||
// init_sprite_accessory_subtypes(/datum/sprite_accessory/avian_open_wings, GLOB.avian_open_wings_list)
|
||||
//xeno parts (hiss?)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/xeno_head, GLOB.xeno_head_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/xeno_tail, GLOB.xeno_tail_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/xeno_dorsal, GLOB.xeno_dorsal_list)
|
||||
//genitals
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/penis, GLOB.cock_shapes_list)
|
||||
|
||||
for(var/K in GLOB.cock_shapes_list)
|
||||
var/datum/sprite_accessory/penis/value = GLOB.cock_shapes_list[K]
|
||||
GLOB.cock_shapes_icons[K] = value.icon_state
|
||||
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/vagina, GLOB.vagina_shapes_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/breasts, GLOB.breasts_shapes_list)
|
||||
GLOB.breasts_size_list = list("a","b","c","d","e") //We need the list to choose from initialized, but it's no longer a sprite_accessory thing.
|
||||
|
||||
//Species
|
||||
for(var/spath in subtypesof(/datum/species))
|
||||
var/datum/species/S = new spath()
|
||||
if(S.roundstart)
|
||||
GLOB.roundstart_species[S.id] = S.type
|
||||
GLOB.species_list[S.id] = S.type
|
||||
|
||||
//Surgeries
|
||||
for(var/path in subtypesof(/datum/surgery))
|
||||
GLOB.surgeries_list += new path()
|
||||
|
||||
//Materials
|
||||
for(var/path in subtypesof(/datum/material))
|
||||
var/datum/material/D = new path()
|
||||
GLOB.materials_list[D.id] = D
|
||||
|
||||
//Techs
|
||||
for(var/path in subtypesof(/datum/tech))
|
||||
var/datum/tech/D = new path()
|
||||
GLOB.tech_list[D.id] = D
|
||||
|
||||
//Emotes
|
||||
for(var/path in subtypesof(/datum/emote))
|
||||
var/datum/emote/E = new path()
|
||||
E.emote_list[E.key] = E
|
||||
|
||||
init_subtypes(/datum/crafting_recipe, GLOB.crafting_recipes)
|
||||
|
||||
/* // Uncomment to debug chemical reaction list.
|
||||
/client/verb/debug_chemical_list()
|
||||
|
||||
for (var/reaction in chemical_reactions_list)
|
||||
. += "chemical_reactions_list\[\"[reaction]\"\] = \"[chemical_reactions_list[reaction]]\"\n"
|
||||
if(islist(chemical_reactions_list[reaction]))
|
||||
var/list/L = chemical_reactions_list[reaction]
|
||||
for(var/t in L)
|
||||
. += " has: [t]\n"
|
||||
to_chat(world, .)
|
||||
*/
|
||||
|
||||
//creates every subtype of prototype (excluding prototype) and adds it to list L.
|
||||
//if no list/L is provided, one is created.
|
||||
/proc/init_subtypes(prototype, list/L)
|
||||
if(!istype(L))
|
||||
L = list()
|
||||
for(var/path in subtypesof(prototype))
|
||||
L += new path()
|
||||
return L
|
||||
|
||||
//returns a list of paths to every subtype of prototype (excluding prototype)
|
||||
//if no list/L is provided, one is created.
|
||||
/proc/init_paths(prototype, list/L)
|
||||
if(!istype(L))
|
||||
L = list()
|
||||
for(var/path in subtypesof(prototype))
|
||||
L+= path
|
||||
return L
|
||||
//////////////////////////
|
||||
/////Initial Building/////
|
||||
//////////////////////////
|
||||
|
||||
/proc/make_datum_references_lists()
|
||||
//hair
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/hair, GLOB.hair_styles_list, GLOB.hair_styles_male_list, GLOB.hair_styles_female_list)
|
||||
//facial hair
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/facial_hair, GLOB.facial_hair_styles_list, GLOB.facial_hair_styles_male_list, GLOB.facial_hair_styles_female_list)
|
||||
//underwear
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/underwear, GLOB.underwear_list, GLOB.underwear_m, GLOB.underwear_f)
|
||||
//undershirt
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/undershirt, GLOB.undershirt_list, GLOB.undershirt_m, GLOB.undershirt_f)
|
||||
//socks
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/socks, GLOB.socks_list)
|
||||
//lizard bodyparts (blizzard intensifies)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/body_markings, GLOB.body_markings_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/lizard, GLOB.tails_list_lizard)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/tails_animated/lizard, GLOB.animated_tails_list_lizard)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/human, GLOB.tails_list_human)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/tails_animated/human, GLOB.animated_tails_list_human)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/snouts, GLOB.snouts_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/horns,GLOB.horns_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/ears, GLOB.ears_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/wings, GLOB.wings_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/wings_open, GLOB.wings_open_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/frills, GLOB.frills_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/spines, GLOB.spines_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/spines_animated, GLOB.animated_spines_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/legs, GLOB.legs_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/wings, GLOB.r_wings_list,roundstart = TRUE)
|
||||
|
||||
//citadel code
|
||||
//mammal bodyparts (fucking furries)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_body_markings, GLOB.mam_body_markings_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_tails, GLOB.mam_tails_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_ears, GLOB.mam_ears_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_tails_animated, GLOB.mam_tails_animated_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/taur, GLOB.taur_list)
|
||||
//avian bodyparts (i swear this isn't starbound)
|
||||
// init_sprite_accessory_subtypes(/datum/sprite_accessory/beaks/avian, GLOB.avian_beaks_list)
|
||||
// init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/avian, GLOB.avian_tails_list)
|
||||
// init_sprite_accessory_subtypes(/datum/sprite_accessory/avian_wings, GLOB.avian_wings_list)
|
||||
// init_sprite_accessory_subtypes(/datum/sprite_accessory/avian_open_wings, GLOB.avian_open_wings_list)
|
||||
//xeno parts (hiss?)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/xeno_head, GLOB.xeno_head_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/xeno_tail, GLOB.xeno_tail_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/xeno_dorsal, GLOB.xeno_dorsal_list)
|
||||
//genitals
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/penis, GLOB.cock_shapes_list)
|
||||
|
||||
for(var/K in GLOB.cock_shapes_list)
|
||||
var/datum/sprite_accessory/penis/value = GLOB.cock_shapes_list[K]
|
||||
GLOB.cock_shapes_icons[K] = value.icon_state
|
||||
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/vagina, GLOB.vagina_shapes_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/breasts, GLOB.breasts_shapes_list)
|
||||
GLOB.breasts_size_list = list("a","b","c","d","e") //We need the list to choose from initialized, but it's no longer a sprite_accessory thing.
|
||||
|
||||
|
||||
//Species
|
||||
for(var/spath in subtypesof(/datum/species))
|
||||
var/datum/species/S = new spath()
|
||||
GLOB.species_list[S.id] = spath
|
||||
|
||||
//Surgeries
|
||||
for(var/path in subtypesof(/datum/surgery))
|
||||
GLOB.surgeries_list += new path()
|
||||
|
||||
//Materials
|
||||
for(var/path in subtypesof(/datum/material))
|
||||
var/datum/material/D = new path()
|
||||
GLOB.materials_list[D.id] = D
|
||||
|
||||
//Techs
|
||||
for(var/path in subtypesof(/datum/tech))
|
||||
var/datum/tech/D = new path()
|
||||
GLOB.tech_list[D.id] = D
|
||||
|
||||
//Emotes
|
||||
for(var/path in subtypesof(/datum/emote))
|
||||
var/datum/emote/E = new path()
|
||||
E.emote_list[E.key] = E
|
||||
|
||||
init_subtypes(/datum/crafting_recipe, GLOB.crafting_recipes)
|
||||
|
||||
/* // Uncomment to debug chemical reaction list.
|
||||
/client/verb/debug_chemical_list()
|
||||
|
||||
for (var/reaction in chemical_reactions_list)
|
||||
. += "chemical_reactions_list\[\"[reaction]\"\] = \"[chemical_reactions_list[reaction]]\"\n"
|
||||
if(islist(chemical_reactions_list[reaction]))
|
||||
var/list/L = chemical_reactions_list[reaction]
|
||||
for(var/t in L)
|
||||
. += " has: [t]\n"
|
||||
to_chat(world, .)
|
||||
*/
|
||||
|
||||
//creates every subtype of prototype (excluding prototype) and adds it to list L.
|
||||
//if no list/L is provided, one is created.
|
||||
/proc/init_subtypes(prototype, list/L)
|
||||
if(!istype(L))
|
||||
L = list()
|
||||
for(var/path in subtypesof(prototype))
|
||||
L += new path()
|
||||
return L
|
||||
|
||||
//returns a list of paths to every subtype of prototype (excluding prototype)
|
||||
//if no list/L is provided, one is created.
|
||||
/proc/init_paths(prototype, list/L)
|
||||
if(!istype(L))
|
||||
L = list()
|
||||
for(var/path in subtypesof(prototype))
|
||||
L+= path
|
||||
return L
|
||||
|
||||
@@ -220,7 +220,6 @@ GLOBAL_LIST_INIT(skin_tones, list(
|
||||
))
|
||||
|
||||
GLOBAL_LIST_EMPTY(species_list)
|
||||
GLOBAL_LIST_EMPTY(roundstart_species)
|
||||
|
||||
/proc/age2agedescription(age)
|
||||
switch(age)
|
||||
|
||||
+248
-246
@@ -1,246 +1,248 @@
|
||||
#define ION_FILE "ion_laws.json"
|
||||
|
||||
/proc/lizard_name(gender)
|
||||
if(gender == MALE)
|
||||
return "[pick(GLOB.lizard_names_male)]-[pick(GLOB.lizard_names_male)]"
|
||||
else
|
||||
return "[pick(GLOB.lizard_names_female)]-[pick(GLOB.lizard_names_female)]"
|
||||
|
||||
/proc/plasmaman_name()
|
||||
return "[pick(GLOB.plasmaman_names)] \Roman[rand(1,99)]"
|
||||
|
||||
/proc/church_name()
|
||||
var/static/church_name
|
||||
if (church_name)
|
||||
return church_name
|
||||
|
||||
var/name = ""
|
||||
|
||||
name += pick("Holy", "United", "First", "Second", "Last")
|
||||
|
||||
if (prob(20))
|
||||
name += " Space"
|
||||
|
||||
name += " " + pick("Church", "Cathedral", "Body", "Worshippers", "Movement", "Witnesses")
|
||||
name += " of [religion_name()]"
|
||||
|
||||
return name
|
||||
|
||||
GLOBAL_VAR(command_name)
|
||||
/proc/command_name()
|
||||
if (GLOB.command_name)
|
||||
return GLOB.command_name
|
||||
|
||||
var/name = "Central Command"
|
||||
|
||||
GLOB.command_name = name
|
||||
return name
|
||||
|
||||
/proc/change_command_name(name)
|
||||
|
||||
GLOB.command_name = name
|
||||
|
||||
return name
|
||||
|
||||
/proc/religion_name()
|
||||
var/static/religion_name
|
||||
if (religion_name)
|
||||
return religion_name
|
||||
|
||||
var/name = ""
|
||||
|
||||
name += pick("bee", "science", "edu", "captain", "assistant", "monkey", "alien", "space", "unit", "sprocket", "gadget", "bomb", "revolution", "beyond", "station", "goon", "robot", "ivor", "hobnob")
|
||||
name += pick("ism", "ia", "ology", "istism", "ites", "ick", "ian", "ity")
|
||||
|
||||
return capitalize(name)
|
||||
|
||||
/proc/station_name()
|
||||
if(!GLOB.station_name)
|
||||
var/newname
|
||||
if(config && config.station_name)
|
||||
newname = config.station_name
|
||||
else
|
||||
newname = new_station_name()
|
||||
|
||||
set_station_name(newname)
|
||||
|
||||
return GLOB.station_name
|
||||
|
||||
/proc/set_station_name(newname)
|
||||
GLOB.station_name = newname
|
||||
|
||||
if(config && config.server_name)
|
||||
world.name = "[config.server_name][config.server_name==GLOB.station_name ? "" : ": [GLOB.station_name]"]"
|
||||
else
|
||||
world.name = GLOB.station_name
|
||||
|
||||
|
||||
/proc/new_station_name()
|
||||
var/random = rand(1,5)
|
||||
var/name = ""
|
||||
var/new_station_name = ""
|
||||
|
||||
//Rare: Pre-Prefix
|
||||
if (prob(10))
|
||||
name = pick(GLOB.station_prefixes)
|
||||
new_station_name = name + " "
|
||||
name = ""
|
||||
|
||||
// Prefix
|
||||
for(var/holiday_name in SSevents.holidays)
|
||||
if(holiday_name == "Friday the 13th")
|
||||
random = 13
|
||||
var/datum/holiday/holiday = SSevents.holidays[holiday_name]
|
||||
name = holiday.getStationPrefix()
|
||||
//get normal name
|
||||
if(!name)
|
||||
name = pick(GLOB.station_names)
|
||||
if(name)
|
||||
new_station_name += name + " "
|
||||
|
||||
// Suffix
|
||||
name = pick(GLOB.station_suffixes)
|
||||
new_station_name += name + " "
|
||||
|
||||
// ID Number
|
||||
switch(random)
|
||||
if(1)
|
||||
new_station_name += "[rand(1, 99)]"
|
||||
if(2)
|
||||
new_station_name += pick(GLOB.greek_letters)
|
||||
if(3)
|
||||
new_station_name += "\Roman[rand(1,99)]"
|
||||
if(4)
|
||||
new_station_name += pick(GLOB.phonetic_alphabet)
|
||||
if(5)
|
||||
new_station_name += pick(GLOB.numbers_as_words)
|
||||
if(13)
|
||||
new_station_name += pick("13","XIII","Thirteen")
|
||||
return new_station_name
|
||||
|
||||
/proc/syndicate_name()
|
||||
var/static/syndicate_name
|
||||
if (syndicate_name)
|
||||
return syndicate_name
|
||||
|
||||
var/name = ""
|
||||
|
||||
// Prefix
|
||||
name += pick("Clandestine", "Prima", "Blue", "Zero-G", "Max", "Blasto", "Waffle", "North", "Omni", "Newton", "Cyber", "Bonk", "Gene", "Gib")
|
||||
|
||||
// Suffix
|
||||
if (prob(80))
|
||||
name += " "
|
||||
|
||||
// Full
|
||||
if (prob(60))
|
||||
name += pick("Syndicate", "Consortium", "Collective", "Corporation", "Group", "Holdings", "Biotech", "Industries", "Systems", "Products", "Chemicals", "Enterprises", "Family", "Creations", "International", "Intergalactic", "Interplanetary", "Foundation", "Positronics", "Hive")
|
||||
// Broken
|
||||
else
|
||||
name += pick("Syndi", "Corp", "Bio", "System", "Prod", "Chem", "Inter", "Hive")
|
||||
name += pick("", "-")
|
||||
name += pick("Tech", "Sun", "Co", "Tek", "X", "Inc", "Code")
|
||||
// Small
|
||||
else
|
||||
name += pick("-", "*", "")
|
||||
name += pick("Tech", "Sun", "Co", "Tek", "X", "Inc", "Gen", "Star", "Dyne", "Code", "Hive")
|
||||
|
||||
syndicate_name = name
|
||||
return name
|
||||
|
||||
|
||||
//Traitors and traitor silicons will get these. Revs will not.
|
||||
GLOBAL_VAR(syndicate_code_phrase) //Code phrase for traitors.
|
||||
GLOBAL_VAR(syndicate_code_response) //Code response for traitors.
|
||||
|
||||
/*
|
||||
Should be expanded.
|
||||
How this works:
|
||||
Instead of "I'm looking for James Smith," the traitor would say "James Smith" as part of a conversation.
|
||||
Another traitor may then respond with: "They enjoy running through the void-filled vacuum of the derelict."
|
||||
The phrase should then have the words: James Smith.
|
||||
The response should then have the words: run, void, and derelict.
|
||||
This way assures that the code is suited to the conversation and is unpredicatable.
|
||||
Obviously, some people will be better at this than others but in theory, everyone should be able to do it and it only enhances roleplay.
|
||||
Can probably be done through "{ }" but I don't really see the practical benefit.
|
||||
One example of an earlier system is commented below.
|
||||
/N
|
||||
*/
|
||||
|
||||
/proc/generate_code_phrase(return_list=FALSE)//Proc is used for phrase and response in master_controller.dm
|
||||
|
||||
if(!return_list)
|
||||
. = ""
|
||||
else
|
||||
. = list()
|
||||
|
||||
var/words = pick(//How many words there will be. Minimum of two. 2, 4 and 5 have a lesser chance of being selected. 3 is the most likely.
|
||||
50; 2,
|
||||
200; 3,
|
||||
50; 4,
|
||||
25; 5
|
||||
)
|
||||
|
||||
var/list/safety = list(1,2,3)//Tells the proc which options to remove later on.
|
||||
var/nouns = strings(ION_FILE, "ionabstract")
|
||||
var/objects = strings(ION_FILE, "ionobjects")
|
||||
var/adjectives = strings(ION_FILE, "ionadjectives")
|
||||
var/threats = strings(ION_FILE, "ionthreats")
|
||||
var/foods = strings(ION_FILE, "ionfood")
|
||||
var/drinks = strings(ION_FILE, "iondrinks")
|
||||
var/list/locations = GLOB.teleportlocs.len ? GLOB.teleportlocs : drinks //if null, defaults to drinks instead.
|
||||
|
||||
var/list/names = list()
|
||||
for(var/datum/data/record/t in GLOB.data_core.general)//Picks from crew manifest.
|
||||
names += t.fields["name"]
|
||||
|
||||
var/maxwords = words//Extra var to check for duplicates.
|
||||
|
||||
for(words,words>0,words--)//Randomly picks from one of the choices below.
|
||||
|
||||
if(words==1&&(1 in safety)&&(2 in safety))//If there is only one word remaining and choice 1 or 2 have not been selected.
|
||||
safety = list(pick(1,2))//Select choice 1 or 2.
|
||||
else if(words==1&&maxwords==2)//Else if there is only one word remaining (and there were two originally), and 1 or 2 were chosen,
|
||||
safety = list(3)//Default to list 3
|
||||
|
||||
switch(pick(safety))//Chance based on the safety list.
|
||||
if(1)//1 and 2 can only be selected once each to prevent more than two specific names/places/etc.
|
||||
switch(rand(1,2))//Mainly to add more options later.
|
||||
if(1)
|
||||
if(names.len&&prob(70))
|
||||
. += pick(names)
|
||||
else
|
||||
if(prob(10))
|
||||
. += pick(lizard_name(MALE),lizard_name(FEMALE))
|
||||
else
|
||||
var/new_name = pick(pick(GLOB.first_names_male,GLOB.first_names_female))
|
||||
new_name += " "
|
||||
new_name += pick(GLOB.last_names)
|
||||
. += new_name
|
||||
if(2)
|
||||
. += pick(get_all_jobs())//Returns a job.
|
||||
safety -= 1
|
||||
if(2)
|
||||
switch(rand(1,3))//Food, drinks, or things. Only selectable once.
|
||||
if(1)
|
||||
. += lowertext(pick(drinks))
|
||||
if(2)
|
||||
. += lowertext(pick(foods))
|
||||
if(3)
|
||||
. += lowertext(pick(locations))
|
||||
safety -= 2
|
||||
if(3)
|
||||
switch(rand(1,4))//Abstract nouns, objects, adjectives, threats. Can be selected more than once.
|
||||
if(1)
|
||||
. += lowertext(pick(nouns))
|
||||
if(2)
|
||||
. += lowertext(pick(objects))
|
||||
if(3)
|
||||
. += lowertext(pick(adjectives))
|
||||
if(4)
|
||||
. += lowertext(pick(threats))
|
||||
if(!return_list)
|
||||
if(words==1)
|
||||
. += "."
|
||||
else
|
||||
. += ", "
|
||||
#define ION_FILE "ion_laws.json"
|
||||
|
||||
/proc/lizard_name(gender)
|
||||
if(gender == MALE)
|
||||
return "[pick(GLOB.lizard_names_male)]-[pick(GLOB.lizard_names_male)]"
|
||||
else
|
||||
return "[pick(GLOB.lizard_names_female)]-[pick(GLOB.lizard_names_female)]"
|
||||
|
||||
/proc/plasmaman_name()
|
||||
return "[pick(GLOB.plasmaman_names)] \Roman[rand(1,99)]"
|
||||
|
||||
/proc/church_name()
|
||||
var/static/church_name
|
||||
if (church_name)
|
||||
return church_name
|
||||
|
||||
var/name = ""
|
||||
|
||||
name += pick("Holy", "United", "First", "Second", "Last")
|
||||
|
||||
if (prob(20))
|
||||
name += " Space"
|
||||
|
||||
name += " " + pick("Church", "Cathedral", "Body", "Worshippers", "Movement", "Witnesses")
|
||||
name += " of [religion_name()]"
|
||||
|
||||
return name
|
||||
|
||||
GLOBAL_VAR(command_name)
|
||||
/proc/command_name()
|
||||
if (GLOB.command_name)
|
||||
return GLOB.command_name
|
||||
|
||||
var/name = "Central Command"
|
||||
|
||||
GLOB.command_name = name
|
||||
return name
|
||||
|
||||
/proc/change_command_name(name)
|
||||
|
||||
GLOB.command_name = name
|
||||
|
||||
return name
|
||||
|
||||
/proc/religion_name()
|
||||
var/static/religion_name
|
||||
if (religion_name)
|
||||
return religion_name
|
||||
|
||||
var/name = ""
|
||||
|
||||
name += pick("bee", "science", "edu", "captain", "assistant", "monkey", "alien", "space", "unit", "sprocket", "gadget", "bomb", "revolution", "beyond", "station", "goon", "robot", "ivor", "hobnob")
|
||||
name += pick("ism", "ia", "ology", "istism", "ites", "ick", "ian", "ity")
|
||||
|
||||
return capitalize(name)
|
||||
|
||||
/proc/station_name()
|
||||
if(!GLOB.station_name)
|
||||
var/newname
|
||||
var/config_station_name = CONFIG_GET(string/stationname)
|
||||
if(config_station_name)
|
||||
newname = config_station_name
|
||||
else
|
||||
newname = new_station_name()
|
||||
|
||||
set_station_name(newname)
|
||||
|
||||
return GLOB.station_name
|
||||
|
||||
/proc/set_station_name(newname)
|
||||
GLOB.station_name = newname
|
||||
|
||||
var/config_server_name = CONFIG_GET(string/servername)
|
||||
if(config_server_name)
|
||||
world.name = "[config_server_name][config_server_name == GLOB.station_name ? "" : ": [GLOB.station_name]"]"
|
||||
else
|
||||
world.name = GLOB.station_name
|
||||
|
||||
|
||||
/proc/new_station_name()
|
||||
var/random = rand(1,5)
|
||||
var/name = ""
|
||||
var/new_station_name = ""
|
||||
|
||||
//Rare: Pre-Prefix
|
||||
if (prob(10))
|
||||
name = pick(GLOB.station_prefixes)
|
||||
new_station_name = name + " "
|
||||
name = ""
|
||||
|
||||
// Prefix
|
||||
for(var/holiday_name in SSevents.holidays)
|
||||
if(holiday_name == "Friday the 13th")
|
||||
random = 13
|
||||
var/datum/holiday/holiday = SSevents.holidays[holiday_name]
|
||||
name = holiday.getStationPrefix()
|
||||
//get normal name
|
||||
if(!name)
|
||||
name = pick(GLOB.station_names)
|
||||
if(name)
|
||||
new_station_name += name + " "
|
||||
|
||||
// Suffix
|
||||
name = pick(GLOB.station_suffixes)
|
||||
new_station_name += name + " "
|
||||
|
||||
// ID Number
|
||||
switch(random)
|
||||
if(1)
|
||||
new_station_name += "[rand(1, 99)]"
|
||||
if(2)
|
||||
new_station_name += pick(GLOB.greek_letters)
|
||||
if(3)
|
||||
new_station_name += "\Roman[rand(1,99)]"
|
||||
if(4)
|
||||
new_station_name += pick(GLOB.phonetic_alphabet)
|
||||
if(5)
|
||||
new_station_name += pick(GLOB.numbers_as_words)
|
||||
if(13)
|
||||
new_station_name += pick("13","XIII","Thirteen")
|
||||
return new_station_name
|
||||
|
||||
/proc/syndicate_name()
|
||||
var/static/syndicate_name
|
||||
if (syndicate_name)
|
||||
return syndicate_name
|
||||
|
||||
var/name = ""
|
||||
|
||||
// Prefix
|
||||
name += pick("Clandestine", "Prima", "Blue", "Zero-G", "Max", "Blasto", "Waffle", "North", "Omni", "Newton", "Cyber", "Bonk", "Gene", "Gib")
|
||||
|
||||
// Suffix
|
||||
if (prob(80))
|
||||
name += " "
|
||||
|
||||
// Full
|
||||
if (prob(60))
|
||||
name += pick("Syndicate", "Consortium", "Collective", "Corporation", "Group", "Holdings", "Biotech", "Industries", "Systems", "Products", "Chemicals", "Enterprises", "Family", "Creations", "International", "Intergalactic", "Interplanetary", "Foundation", "Positronics", "Hive")
|
||||
// Broken
|
||||
else
|
||||
name += pick("Syndi", "Corp", "Bio", "System", "Prod", "Chem", "Inter", "Hive")
|
||||
name += pick("", "-")
|
||||
name += pick("Tech", "Sun", "Co", "Tek", "X", "Inc", "Code")
|
||||
// Small
|
||||
else
|
||||
name += pick("-", "*", "")
|
||||
name += pick("Tech", "Sun", "Co", "Tek", "X", "Inc", "Gen", "Star", "Dyne", "Code", "Hive")
|
||||
|
||||
syndicate_name = name
|
||||
return name
|
||||
|
||||
|
||||
//Traitors and traitor silicons will get these. Revs will not.
|
||||
GLOBAL_VAR(syndicate_code_phrase) //Code phrase for traitors.
|
||||
GLOBAL_VAR(syndicate_code_response) //Code response for traitors.
|
||||
|
||||
/*
|
||||
Should be expanded.
|
||||
How this works:
|
||||
Instead of "I'm looking for James Smith," the traitor would say "James Smith" as part of a conversation.
|
||||
Another traitor may then respond with: "They enjoy running through the void-filled vacuum of the derelict."
|
||||
The phrase should then have the words: James Smith.
|
||||
The response should then have the words: run, void, and derelict.
|
||||
This way assures that the code is suited to the conversation and is unpredicatable.
|
||||
Obviously, some people will be better at this than others but in theory, everyone should be able to do it and it only enhances roleplay.
|
||||
Can probably be done through "{ }" but I don't really see the practical benefit.
|
||||
One example of an earlier system is commented below.
|
||||
/N
|
||||
*/
|
||||
|
||||
/proc/generate_code_phrase(return_list=FALSE)//Proc is used for phrase and response in master_controller.dm
|
||||
|
||||
if(!return_list)
|
||||
. = ""
|
||||
else
|
||||
. = list()
|
||||
|
||||
var/words = pick(//How many words there will be. Minimum of two. 2, 4 and 5 have a lesser chance of being selected. 3 is the most likely.
|
||||
50; 2,
|
||||
200; 3,
|
||||
50; 4,
|
||||
25; 5
|
||||
)
|
||||
|
||||
var/list/safety = list(1,2,3)//Tells the proc which options to remove later on.
|
||||
var/nouns = strings(ION_FILE, "ionabstract")
|
||||
var/objects = strings(ION_FILE, "ionobjects")
|
||||
var/adjectives = strings(ION_FILE, "ionadjectives")
|
||||
var/threats = strings(ION_FILE, "ionthreats")
|
||||
var/foods = strings(ION_FILE, "ionfood")
|
||||
var/drinks = strings(ION_FILE, "iondrinks")
|
||||
var/list/locations = GLOB.teleportlocs.len ? GLOB.teleportlocs : drinks //if null, defaults to drinks instead.
|
||||
|
||||
var/list/names = list()
|
||||
for(var/datum/data/record/t in GLOB.data_core.general)//Picks from crew manifest.
|
||||
names += t.fields["name"]
|
||||
|
||||
var/maxwords = words//Extra var to check for duplicates.
|
||||
|
||||
for(words,words>0,words--)//Randomly picks from one of the choices below.
|
||||
|
||||
if(words==1&&(1 in safety)&&(2 in safety))//If there is only one word remaining and choice 1 or 2 have not been selected.
|
||||
safety = list(pick(1,2))//Select choice 1 or 2.
|
||||
else if(words==1&&maxwords==2)//Else if there is only one word remaining (and there were two originally), and 1 or 2 were chosen,
|
||||
safety = list(3)//Default to list 3
|
||||
|
||||
switch(pick(safety))//Chance based on the safety list.
|
||||
if(1)//1 and 2 can only be selected once each to prevent more than two specific names/places/etc.
|
||||
switch(rand(1,2))//Mainly to add more options later.
|
||||
if(1)
|
||||
if(names.len&&prob(70))
|
||||
. += pick(names)
|
||||
else
|
||||
if(prob(10))
|
||||
. += pick(lizard_name(MALE),lizard_name(FEMALE))
|
||||
else
|
||||
var/new_name = pick(pick(GLOB.first_names_male,GLOB.first_names_female))
|
||||
new_name += " "
|
||||
new_name += pick(GLOB.last_names)
|
||||
. += new_name
|
||||
if(2)
|
||||
. += pick(get_all_jobs())//Returns a job.
|
||||
safety -= 1
|
||||
if(2)
|
||||
switch(rand(1,3))//Food, drinks, or things. Only selectable once.
|
||||
if(1)
|
||||
. += lowertext(pick(drinks))
|
||||
if(2)
|
||||
. += lowertext(pick(foods))
|
||||
if(3)
|
||||
. += lowertext(pick(locations))
|
||||
safety -= 2
|
||||
if(3)
|
||||
switch(rand(1,4))//Abstract nouns, objects, adjectives, threats. Can be selected more than once.
|
||||
if(1)
|
||||
. += lowertext(pick(nouns))
|
||||
if(2)
|
||||
. += lowertext(pick(objects))
|
||||
if(3)
|
||||
. += lowertext(pick(adjectives))
|
||||
if(4)
|
||||
. += lowertext(pick(threats))
|
||||
if(!return_list)
|
||||
if(words==1)
|
||||
. += "."
|
||||
else
|
||||
. += ", "
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
return copytext(sqltext, 2, lentext(sqltext));//Quote() adds quotes around input, we already do that
|
||||
|
||||
/proc/format_table_name(table as text)
|
||||
return global.sqlfdbktableprefix + table
|
||||
return CONFIG_GET(string/feedback_tableprefix) + table
|
||||
|
||||
/*
|
||||
* Text sanitization
|
||||
@@ -594,7 +594,7 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
|
||||
//in the json file and have it be reflected in the in game item/mob it came from.
|
||||
//(That's what things like savefiles are for) Note that this list is not shuffled.
|
||||
/proc/twitterize(list/proposed, filename, cullshort = 1, storemax = 1000)
|
||||
if(!islist(proposed) || !filename || !config.log_twitter)
|
||||
if(!islist(proposed) || !filename || !CONFIG_GET(flag/log_twitter))
|
||||
return
|
||||
|
||||
//Regular expressions are, as usual, absolute magic
|
||||
|
||||
@@ -554,3 +554,24 @@
|
||||
else
|
||||
return /datum
|
||||
return text2path(copytext(string_type, 1, last_slash))
|
||||
|
||||
//returns a string the last bit of a type, without the preceeding '/'
|
||||
/proc/type2top(the_type)
|
||||
//handle the builtins manually
|
||||
if(!ispath(the_type))
|
||||
return
|
||||
switch(the_type)
|
||||
if(/datum)
|
||||
return "datum"
|
||||
if(/atom)
|
||||
return "atom"
|
||||
if(/obj)
|
||||
return "obj"
|
||||
if(/mob)
|
||||
return "mob"
|
||||
if(/area)
|
||||
return "area"
|
||||
if(/turf)
|
||||
return "turf"
|
||||
else //regex everything else (works for /proc too)
|
||||
return lowertext(replacetext("[the_type]", "[type2parent(the_type)]/", ""))
|
||||
|
||||
@@ -1266,7 +1266,7 @@ proc/pick_closest_path(value, list/matches = get_fancy_list_of_atom_types())
|
||||
#define QDEL_LIST(L) if(L) { for(var/I in L) qdel(I); L.Cut(); }
|
||||
#define QDEL_LIST_IN(L, time) addtimer(CALLBACK(GLOBAL_PROC, .proc/______qdel_list_wrapper, L), time, TIMER_STOPPABLE)
|
||||
#define QDEL_LIST_ASSOC(L) if(L) { for(var/I in L) { qdel(L[I]); qdel(I); } L.Cut(); }
|
||||
#define QDEL_LIST_ASSOC_VAL(L) if(L) { for(var/I in L) qel(L[I]); L.Cut(); }
|
||||
#define QDEL_LIST_ASSOC_VAL(L) if(L) { for(var/I in L) qdel(L[I]); L.Cut(); }
|
||||
|
||||
/proc/______qdel_list_wrapper(list/L) //the underscores are to encourage people not to use this directly.
|
||||
QDEL_LIST(L)
|
||||
@@ -1364,63 +1364,6 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
//WHATEVER YOU USE THIS FOR MUST BE SANITIZED TO SHIT, IT USES SHELL
|
||||
//It also sleeps
|
||||
|
||||
//Set this to TRUE before calling
|
||||
//This prevents RCEs from badmins
|
||||
//kevinz000 if you touch this I will hunt you down
|
||||
GLOBAL_VAR_INIT(valid_HTTPSGet, FALSE)
|
||||
GLOBAL_PROTECT(valid_HTTPSGet)
|
||||
/proc/HTTPSGet(url) //tgs2 support
|
||||
if(findtext(url, "\""))
|
||||
GLOB.valid_HTTPSGet = FALSE
|
||||
|
||||
if(!GLOB.valid_HTTPSGet)
|
||||
if(usr)
|
||||
CRASH("[usr.ckey]([usr]) just attempted an invalid HTTPSGet on: [url]!")
|
||||
else
|
||||
CRASH("Invalid HTTPSGet call on: [url]")
|
||||
GLOB.valid_HTTPSGet = FALSE
|
||||
|
||||
//"This has got to be the ugliest hack I have ever done"
|
||||
//warning, here be dragons
|
||||
/*
|
||||
| @___oo
|
||||
/\ /\ / (__,,,,|
|
||||
) /^\) ^\/ _)
|
||||
) /^\/ _)
|
||||
) _ / / _)
|
||||
/\ )/\/ || | )_)
|
||||
< > |(,,) )__)
|
||||
|| / \)___)\
|
||||
| \____( )___) )___
|
||||
\______(_______;;; __;;;
|
||||
*/
|
||||
var/temp_file = "data/HTTPSGetOutput.txt"
|
||||
var/command
|
||||
if(world.system_type == MS_WINDOWS)
|
||||
command = "powershell -Command \"wget [url] -OutFile [temp_file]\""
|
||||
else if(world.system_type == UNIX)
|
||||
command = "wget -O [temp_file] [url]"
|
||||
else
|
||||
CRASH("Invalid world.system_type ([world.system_type])? Yell at Lummox.")
|
||||
|
||||
log_world("HTTPSGet: [url]")
|
||||
var/result = shell(command)
|
||||
if(result != 0)
|
||||
log_world("Download failed: shell exited with code: [result]")
|
||||
return
|
||||
|
||||
var/f = file(temp_file)
|
||||
if(!f)
|
||||
log_world("Download failed: Temp file not found")
|
||||
return
|
||||
|
||||
. = file2text(f)
|
||||
f = null
|
||||
fdel(temp_file)
|
||||
|
||||
#define UNTIL(X) while(!(X)) stoplag()
|
||||
|
||||
/proc/pass()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
GLOBAL_REAL(config, /datum/configuration)
|
||||
GLOBAL_REAL(config, /datum/controller/configuration)
|
||||
|
||||
GLOBAL_DATUM_INIT(revdata, /datum/getrev, new)
|
||||
|
||||
@@ -11,9 +11,7 @@ GLOBAL_VAR_INIT(hub_visibility, FALSE)
|
||||
|
||||
GLOBAL_VAR_INIT(ooc_allowed, TRUE) // used with admin verbs to disable ooc - not a config option apparently
|
||||
GLOBAL_VAR_INIT(dooc_allowed, TRUE)
|
||||
GLOBAL_VAR_INIT(abandon_allowed, TRUE)
|
||||
GLOBAL_VAR_INIT(enter_allowed, TRUE)
|
||||
GLOBAL_VAR_INIT(guests_allowed, TRUE)
|
||||
GLOBAL_VAR_INIT(shuttle_frozen, FALSE)
|
||||
GLOBAL_VAR_INIT(shuttle_left, FALSE)
|
||||
GLOBAL_VAR_INIT(tinted_weldhelh, TRUE)
|
||||
@@ -25,10 +23,16 @@ GLOBAL_VAR_INIT(Debug, FALSE) // global debug switch
|
||||
GLOBAL_VAR_INIT(Debug2, FALSE)
|
||||
|
||||
//This was a define, but I changed it to a variable so it can be changed in-game.(kept the all-caps definition because... code...) -Errorage
|
||||
//Protecting these because the proper way to edit them is with the config/secrets
|
||||
GLOBAL_VAR_INIT(MAX_EX_DEVESTATION_RANGE, 3)
|
||||
GLOBAL_PROTECT(MAX_EX_DEVESTATION_RANGE)
|
||||
GLOBAL_VAR_INIT(MAX_EX_HEAVY_RANGE, 7)
|
||||
GLOBAL_PROTECT(MAX_EX_HEAVY_RANGE)
|
||||
GLOBAL_VAR_INIT(MAX_EX_LIGHT_RANGE, 14)
|
||||
GLOBAL_PROTECT(MAX_EX_LIGHT_RANGE)
|
||||
GLOBAL_VAR_INIT(MAX_EX_FLASH_RANGE, 14)
|
||||
GLOBAL_PROTECT(MAX_EX_FLASH_RANGE)
|
||||
GLOBAL_VAR_INIT(MAX_EX_FLAME_RANGE, 14)
|
||||
GLOBAL_PROTECT(MAX_EX_FLAME_RANGE)
|
||||
GLOBAL_VAR_INIT(DYN_EX_SCALE, 0.5)
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
//Server API key
|
||||
GLOBAL_REAL_VAR(comms_key) = "default_pwd"
|
||||
GLOBAL_REAL_VAR(comms_allowed) = FALSE //By default, the server does not allow messages to be sent to it, unless the key is strong enough (this is to prevent misconfigured servers from becoming vulnerable)
|
||||
|
||||
GLOBAL_REAL_VAR(medal_hub)
|
||||
GLOBAL_REAL_VAR(medal_pass) = " "
|
||||
GLOBAL_REAL_VAR(medals_enabled) = TRUE //will be auto set to false if the game fails contacting the medal hub to prevent unneeded calls.
|
||||
|
||||
// MySQL configuration
|
||||
|
||||
GLOBAL_REAL_VAR(sqladdress) = "localhost"
|
||||
GLOBAL_REAL_VAR(sqlport) = "3306"
|
||||
GLOBAL_REAL_VAR(sqlfdbkdb) = "test"
|
||||
GLOBAL_REAL_VAR(sqlfdbklogin) = "root"
|
||||
GLOBAL_REAL_VAR(sqlfdbkpass) = ""
|
||||
GLOBAL_REAL_VAR(sqlfdbktableprefix) = ""
|
||||
@@ -538,7 +538,7 @@ so as to remain in compliance with the most up-to-date laws."
|
||||
if(NOTIFY_JUMP)
|
||||
var/turf/T = get_turf(target)
|
||||
if(T && isturf(T))
|
||||
G.loc = T
|
||||
G.forceMove(T)
|
||||
if(NOTIFY_ORBIT)
|
||||
G.ManualFollow(target)
|
||||
|
||||
|
||||
+91
-104
@@ -1,104 +1,91 @@
|
||||
/mob/dead/observer/DblClickOn(var/atom/A, var/params)
|
||||
if(client.click_intercept)
|
||||
if(call(client.click_intercept,"InterceptClickOn")(src,params,A))
|
||||
return
|
||||
|
||||
if(can_reenter_corpse && mind && mind.current)
|
||||
if(A == mind.current || (mind.current in A)) // double click your corpse or whatever holds it
|
||||
reenter_corpse() // (cloning scanner, body bag, closet, mech, etc)
|
||||
return // seems legit.
|
||||
|
||||
// Things you might plausibly want to follow
|
||||
if(ismovableatom(A))
|
||||
ManualFollow(A)
|
||||
|
||||
// Otherwise jump
|
||||
else if(A.loc)
|
||||
loc = get_turf(A)
|
||||
update_parallax_contents()
|
||||
|
||||
/mob/dead/observer/ClickOn(var/atom/A, var/params)
|
||||
if(client.click_intercept)
|
||||
if(call(client.click_intercept,"InterceptClickOn")(src,params,A))
|
||||
return
|
||||
|
||||
var/list/modifiers = params2list(params)
|
||||
if(modifiers["shift"] && modifiers["middle"])
|
||||
ShiftMiddleClickOn(A)
|
||||
return
|
||||
if(modifiers["shift"] && modifiers["ctrl"])
|
||||
CtrlShiftClickOn(A)
|
||||
return
|
||||
if(modifiers["middle"])
|
||||
MiddleClickOn(A)
|
||||
return
|
||||
if(modifiers["shift"])
|
||||
ShiftClickOn(A)
|
||||
return
|
||||
if(modifiers["alt"])
|
||||
AltClickOn(A)
|
||||
return
|
||||
if(modifiers["ctrl"])
|
||||
CtrlClickOn(A)
|
||||
return
|
||||
|
||||
if(world.time <= next_move)
|
||||
return
|
||||
// You are responsible for checking config.ghost_interaction when you override this function
|
||||
// Not all of them require checking, see below
|
||||
A.attack_ghost(src)
|
||||
|
||||
// Oh by the way this didn't work with old click code which is why clicking shit didn't spam you
|
||||
/atom/proc/attack_ghost(mob/dead/observer/user)
|
||||
if(user.client)
|
||||
if(IsAdminGhost(user))
|
||||
attack_ai(user)
|
||||
if(user.client.prefs.inquisitive_ghost)
|
||||
user.examinate(src)
|
||||
|
||||
// ---------------------------------------
|
||||
// And here are some good things for free:
|
||||
// Now you can click through portals, wormholes, gateways, and teleporters while observing. -Sayu
|
||||
|
||||
/obj/machinery/teleport/hub/attack_ghost(mob/user)
|
||||
var/atom/l = loc
|
||||
var/obj/machinery/computer/teleporter/com = locate(/obj/machinery/computer/teleporter, locate(l.x - 2, l.y, l.z))
|
||||
if(com && com.locked)
|
||||
user.forceMove(get_turf(com.locked))
|
||||
|
||||
/obj/effect/portal/attack_ghost(mob/user)
|
||||
if(linked)
|
||||
user.forceMove(get_turf(linked))
|
||||
|
||||
/obj/machinery/gateway/centerstation/attack_ghost(mob/user)
|
||||
if(awaygate)
|
||||
user.forceMove(awaygate.loc)
|
||||
else
|
||||
to_chat(user, "[src] has no destination.")
|
||||
|
||||
/obj/machinery/gateway/centeraway/attack_ghost(mob/user)
|
||||
if(stationgate)
|
||||
user.forceMove(stationgate.loc)
|
||||
else
|
||||
to_chat(user, "[src] has no destination.")
|
||||
|
||||
/obj/item/storage/attack_ghost(mob/user)
|
||||
orient2hud(user)
|
||||
show_to(user)
|
||||
|
||||
/obj/machinery/teleport/hub/attack_ghost(mob/user)
|
||||
if(power_station && power_station.engaged && power_station.teleporter_console && power_station.teleporter_console.target)
|
||||
user.forceMove(get_turf(power_station.teleporter_console.target))
|
||||
|
||||
// -------------------------------------------
|
||||
// This was supposed to be used by adminghosts
|
||||
// I think it is a *terrible* idea
|
||||
// but I'm leaving it here anyway
|
||||
// commented out, of course.
|
||||
/*
|
||||
/atom/proc/attack_admin(mob/user as mob)
|
||||
if(!user || !user.client || !user.client.holder)
|
||||
return
|
||||
attack_hand(user)
|
||||
|
||||
*/
|
||||
/mob/dead/observer/DblClickOn(var/atom/A, var/params)
|
||||
if(client.click_intercept)
|
||||
if(call(client.click_intercept,"InterceptClickOn")(src,params,A))
|
||||
return
|
||||
|
||||
if(can_reenter_corpse && mind && mind.current)
|
||||
if(A == mind.current || (mind.current in A)) // double click your corpse or whatever holds it
|
||||
reenter_corpse() // (cloning scanner, body bag, closet, mech, etc)
|
||||
return // seems legit.
|
||||
|
||||
// Things you might plausibly want to follow
|
||||
if(ismovableatom(A))
|
||||
ManualFollow(A)
|
||||
|
||||
// Otherwise jump
|
||||
else if(A.loc)
|
||||
loc = get_turf(A)
|
||||
update_parallax_contents()
|
||||
|
||||
/mob/dead/observer/ClickOn(var/atom/A, var/params)
|
||||
if(client.click_intercept)
|
||||
if(call(client.click_intercept,"InterceptClickOn")(src,params,A))
|
||||
return
|
||||
|
||||
var/list/modifiers = params2list(params)
|
||||
if(modifiers["shift"] && modifiers["middle"])
|
||||
ShiftMiddleClickOn(A)
|
||||
return
|
||||
if(modifiers["shift"] && modifiers["ctrl"])
|
||||
CtrlShiftClickOn(A)
|
||||
return
|
||||
if(modifiers["middle"])
|
||||
MiddleClickOn(A)
|
||||
return
|
||||
if(modifiers["shift"])
|
||||
ShiftClickOn(A)
|
||||
return
|
||||
if(modifiers["alt"])
|
||||
AltClickOn(A)
|
||||
return
|
||||
if(modifiers["ctrl"])
|
||||
CtrlClickOn(A)
|
||||
return
|
||||
|
||||
if(world.time <= next_move)
|
||||
return
|
||||
// You are responsible for checking config.ghost_interaction when you override this function
|
||||
// Not all of them require checking, see below
|
||||
A.attack_ghost(src)
|
||||
|
||||
// Oh by the way this didn't work with old click code which is why clicking shit didn't spam you
|
||||
/atom/proc/attack_ghost(mob/dead/observer/user)
|
||||
if(user.client)
|
||||
if(IsAdminGhost(user))
|
||||
attack_ai(user)
|
||||
if(user.client.prefs.inquisitive_ghost)
|
||||
user.examinate(src)
|
||||
|
||||
// ---------------------------------------
|
||||
// And here are some good things for free:
|
||||
// Now you can click through portals, wormholes, gateways, and teleporters while observing. -Sayu
|
||||
|
||||
/obj/machinery/teleport/hub/attack_ghost(mob/user)
|
||||
var/atom/l = loc
|
||||
var/obj/machinery/computer/teleporter/com = locate(/obj/machinery/computer/teleporter, locate(l.x - 2, l.y, l.z))
|
||||
if(com && com.locked)
|
||||
user.forceMove(get_turf(com.locked))
|
||||
|
||||
/obj/effect/portal/attack_ghost(mob/user)
|
||||
if(linked)
|
||||
user.forceMove(get_turf(linked))
|
||||
|
||||
/obj/machinery/gateway/centerstation/attack_ghost(mob/user)
|
||||
if(awaygate)
|
||||
user.forceMove(awaygate.loc)
|
||||
else
|
||||
to_chat(user, "[src] has no destination.")
|
||||
|
||||
/obj/machinery/gateway/centeraway/attack_ghost(mob/user)
|
||||
if(stationgate)
|
||||
user.forceMove(stationgate.loc)
|
||||
else
|
||||
to_chat(user, "[src] has no destination.")
|
||||
|
||||
/obj/item/storage/attack_ghost(mob/user)
|
||||
orient2hud(user)
|
||||
show_to(user)
|
||||
|
||||
/obj/machinery/teleport/hub/attack_ghost(mob/user)
|
||||
if(power_station && power_station.engaged && power_station.teleporter_console && power_station.teleporter_console.target)
|
||||
user.forceMove(get_turf(power_station.teleporter_console.target))
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
/obj/item/tk_grab/dropped(mob/user)
|
||||
if(focus && user && loc != user && loc != user.loc) // drop_item() gets called when you tk-attack a table/closet with an item
|
||||
if(focus.Adjacent(loc))
|
||||
focus.loc = loc
|
||||
focus.forceMove(loc)
|
||||
. = ..()
|
||||
|
||||
//stops TK grabs being equipped anywhere but into hands
|
||||
|
||||
+142
-876
File diff suppressed because it is too large
Load Diff
@@ -51,13 +51,7 @@
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/datum/config_entry/proc/VASProcCallGuard(str_val)
|
||||
. = !(IsAdminAdvancedProcCall() && GLOB.LastAdminCalledProc == "ValidateAndSet" && GLOB.LastAdminCalledTargetRef == "\ref[src]")
|
||||
if(!.)
|
||||
log_admin_private("Config set of [type] to [str_val] attempted by [key_name(usr)]")
|
||||
|
||||
/datum/config_entry/proc/ValidateAndSet(str_val)
|
||||
VASProcCallGuard(str_val)
|
||||
CRASH("Invalid config entry type!")
|
||||
|
||||
/datum/config_entry/proc/ValidateKeyedList(str_val, list_mode, splitter)
|
||||
@@ -98,8 +92,6 @@
|
||||
return var_name != "auto_trim" && ..()
|
||||
|
||||
/datum/config_entry/string/ValidateAndSet(str_val)
|
||||
if(!VASProcCallGuard(str_val))
|
||||
return FALSE
|
||||
value = auto_trim ? trim(str_val) : str_val
|
||||
return TRUE
|
||||
|
||||
@@ -111,8 +103,6 @@
|
||||
var/min_val = -INFINITY
|
||||
|
||||
/datum/config_entry/number/ValidateAndSet(str_val)
|
||||
if(!VASProcCallGuard(str_val))
|
||||
return FALSE
|
||||
var/temp = text2num(trim(str_val))
|
||||
if(!isnull(temp))
|
||||
value = Clamp(integer ? round(temp) : temp, min_val, max_val)
|
||||
@@ -130,8 +120,6 @@
|
||||
abstract_type = /datum/config_entry/flag
|
||||
|
||||
/datum/config_entry/flag/ValidateAndSet(str_val)
|
||||
if(!VASProcCallGuard(str_val))
|
||||
return FALSE
|
||||
value = text2num(trim(str_val)) != 0
|
||||
return TRUE
|
||||
|
||||
@@ -140,8 +128,6 @@
|
||||
value = list()
|
||||
|
||||
/datum/config_entry/number_list/ValidateAndSet(str_val)
|
||||
if(!VASProcCallGuard(str_val))
|
||||
return FALSE
|
||||
str_val = trim(str_val)
|
||||
var/list/new_list = list()
|
||||
var/list/values = splittext(str_val," ")
|
||||
@@ -161,8 +147,6 @@
|
||||
dupes_allowed = TRUE
|
||||
|
||||
/datum/config_entry/keyed_flag_list/ValidateAndSet(str_val)
|
||||
if(!VASProcCallGuard(str_val))
|
||||
return FALSE
|
||||
return ValidateKeyedList(str_val, LIST_MODE_FLAG, " ")
|
||||
|
||||
/datum/config_entry/keyed_number_list
|
||||
@@ -175,8 +159,6 @@
|
||||
return var_name != "splitter" && ..()
|
||||
|
||||
/datum/config_entry/keyed_number_list/ValidateAndSet(str_val)
|
||||
if(!VASProcCallGuard(str_val))
|
||||
return FALSE
|
||||
return ValidateKeyedList(str_val, LIST_MODE_NUM, splitter)
|
||||
|
||||
/datum/config_entry/keyed_string_list
|
||||
@@ -189,8 +171,6 @@
|
||||
return var_name != "splitter" && ..()
|
||||
|
||||
/datum/config_entry/keyed_string_list/ValidateAndSet(str_val)
|
||||
if(!VASProcCallGuard(str_val))
|
||||
return FALSE
|
||||
return ValidateKeyedList(str_val, LIST_MODE_TEXT, splitter)
|
||||
|
||||
#undef LIST_MODE_NUM
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
#define CURRENT_RESIDENT_FILE "comms.txt"
|
||||
|
||||
CONFIG_DEF(string/comms_key)
|
||||
protection = CONFIG_ENTRY_HIDDEN
|
||||
|
||||
/datum/config_entry/string/comms_key/ValidateAndSet(str_val)
|
||||
return str_val != "default_pwd" && length(str_val) > 6 && ..()
|
||||
|
||||
CONFIG_DEF(string/cross_server_address)
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
/datum/config_entry/string/cross_server_address/ValidateAndSet(str_val)
|
||||
return str_val != "byond:\\address:port" && ..()
|
||||
|
||||
CONFIG_DEF(string/cross_comms_name)
|
||||
|
||||
GLOBAL_VAR_INIT(medals_enabled, TRUE) //will be auto set to false if the game fails contacting the medal hub to prevent unneeded calls.
|
||||
|
||||
CONFIG_DEF(string/medal_hub_address)
|
||||
|
||||
CONFIG_DEF(string/medal_hub_password)
|
||||
protection = CONFIG_ENTRY_HIDDEN
|
||||
@@ -0,0 +1,387 @@
|
||||
#define CURRENT_RESIDENT_FILE "config.txt"
|
||||
|
||||
CONFIG_DEF(flag/autoadmin) // if autoadmin is enabled
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(string/autoadmin_rank) // the rank for autoadmins
|
||||
value = "Game Master"
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(string/servername) // server name (the name of the game window)
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(string/serversqlname) // short form server name used for the DB
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(string/stationname) // station name (the name of the station in-game)
|
||||
|
||||
CONFIG_DEF(number/lobby_countdown) // In between round countdown.
|
||||
value = 120
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(number/round_end_countdown) // Post round murder death kill countdown
|
||||
value = 25
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(flag/hub) // if the game appears on the hub or not
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(flag/log_ooc) // log OOC channel
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(flag/log_access) // log login/logout
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(flag/log_say) // log client say
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(flag/log_admin) // log admin actions
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(flag/log_prayer) // log prayers
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(flag/log_law) // log lawchanges
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(flag/log_game) // log game events
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(flag/log_vote) // log voting
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(flag/log_whisper) // log client whisper
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(flag/log_attack) // log attack messages
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(flag/log_emote) // log emotes
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(flag/log_adminchat) // log admin chat messages
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(flag/log_pda) // log pda messages
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(flag/log_twitter) // log certain expliotable parrots and other such fun things in a JSON file of twitter valid phrases.
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(flag/log_world_topic) // log all world.Topic() calls
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(flag/allow_admin_ooccolor) // Allows admins with relevant permissions to have their own ooc colour
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(flag/allow_vote_restart) // allow votes to restart
|
||||
|
||||
CONFIG_DEF(flag/allow_vote_mode) // allow votes to change mode
|
||||
|
||||
CONFIG_DEF(number/vote_delay) // minimum time between voting sessions (deciseconds, 10 minute default)
|
||||
value = 6000
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(number/vote_period) // length of voting period (deciseconds, default 1 minute)
|
||||
value = 600
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(flag/default_no_vote) // vote does not default to nochange/norestart
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(flag/no_dead_vote) // dead people can't vote
|
||||
|
||||
CONFIG_DEF(flag/allow_metadata) // Metadata is supported.
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(flag/popup_admin_pm) // adminPMs to non-admins show in a pop-up 'reply' window when set
|
||||
|
||||
CONFIG_DEF(number/fps)
|
||||
value = 20
|
||||
min_val = 1
|
||||
max_val = 100 //byond will start crapping out at 50, so this is just ridic
|
||||
var/sync_validate = FALSE
|
||||
|
||||
/datum/config_entry/number/fps/ValidateAndSet(str_val)
|
||||
. = ..()
|
||||
if(.)
|
||||
sync_validate = TRUE
|
||||
var/datum/config_entry/number/ticklag/TL = config.entries_by_type[/datum/config_entry/number/ticklag]
|
||||
if(!TL.sync_validate)
|
||||
TL.ValidateAndSet(10 / value)
|
||||
sync_validate = FALSE
|
||||
|
||||
CONFIG_DEF(number/ticklag)
|
||||
integer = FALSE
|
||||
var/sync_validate = FALSE
|
||||
|
||||
/datum/config_entry/number/ticklag/New() //ticklag weirdly just mirrors fps
|
||||
var/datum/config_entry/CE = /datum/config_entry/number/fps
|
||||
value = 10 / initial(CE.value)
|
||||
..()
|
||||
|
||||
/datum/config_entry/number/ticklag/ValidateAndSet(str_val)
|
||||
. = text2num(str_val) > 0 && ..()
|
||||
if(.)
|
||||
sync_validate = TRUE
|
||||
var/datum/config_entry/number/fps/FPS = config.entries_by_type[/datum/config_entry/number/fps]
|
||||
if(!FPS.sync_validate)
|
||||
FPS.ValidateAndSet(10 / value)
|
||||
sync_validate = FALSE
|
||||
|
||||
CONFIG_DEF(flag/allow_holidays)
|
||||
|
||||
CONFIG_DEF(number/tick_limit_mc_init) //SSinitialization throttling
|
||||
value = TICK_LIMIT_MC_INIT_DEFAULT
|
||||
min_val = 0 //oranges warned us
|
||||
integer = FALSE
|
||||
|
||||
CONFIG_DEF(flag/admin_legacy_system) //Defines whether the server uses the legacy admin system with admins.txt or the SQL system
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(string/hostedby)
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(flag/norespawn)
|
||||
|
||||
CONFIG_DEF(flag/guest_jobban)
|
||||
|
||||
CONFIG_DEF(flag/usewhitelist)
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(flag/ban_legacy_system) //Defines whether the server uses the legacy banning system with the files in /data or the SQL system.
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(flag/use_age_restriction_for_jobs) //Do jobs use account age restrictions? --requires database
|
||||
|
||||
CONFIG_DEF(flag/use_account_age_for_jobs) //Uses the time they made the account for the job restriction stuff. New player joining alerts should be unaffected.
|
||||
|
||||
CONFIG_DEF(flag/use_exp_tracking)
|
||||
|
||||
CONFIG_DEF(flag/use_exp_restrictions_heads)
|
||||
|
||||
CONFIG_DEF(number/use_exp_restrictions_heads_hours)
|
||||
value = 0
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(flag/use_exp_restrictions_heads_department)
|
||||
|
||||
CONFIG_DEF(flag/use_exp_restrictions_other)
|
||||
|
||||
CONFIG_DEF(flag/use_exp_restrictions_admin_bypass)
|
||||
|
||||
CONFIG_DEF(string/server)
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(string/banappeals)
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(string/wikiurl)
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
value = "http://www.tgstation13.org/wiki"
|
||||
|
||||
CONFIG_DEF(string/forumurl)
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
value = "http://tgstation13.org/phpBB/index.php"
|
||||
|
||||
CONFIG_DEF(string/rulesurl)
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
value = "http://www.tgstation13.org/wiki/Rules"
|
||||
|
||||
CONFIG_DEF(string/githuburl)
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
value = "https://www.github.com/tgstation/-tg-station"
|
||||
|
||||
CONFIG_DEF(number/githubrepoid)
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
value = null
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(flag/guest_ban)
|
||||
|
||||
CONFIG_DEF(number/id_console_jobslot_delay)
|
||||
value = 30
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(number/inactivity_period) //time in ds until a player is considered inactive)
|
||||
value = 3000
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/number/inactivity_period/ValidateAndSet(str_val)
|
||||
. = ..()
|
||||
if(.)
|
||||
value *= 10 //documented as seconds in config.txt
|
||||
|
||||
CONFIG_DEF(number/afk_period) //time in ds until a player is considered inactive)
|
||||
value = 3000
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/number/afk_period/ValidateAndSet(str_val)
|
||||
. = ..()
|
||||
if(.)
|
||||
value *= 10 //documented as seconds in config.txt
|
||||
|
||||
CONFIG_DEF(flag/kick_inactive) //force disconnect for inactive players
|
||||
|
||||
CONFIG_DEF(flag/load_jobs_from_txt)
|
||||
|
||||
CONFIG_DEF(flag/forbid_singulo_possession)
|
||||
|
||||
CONFIG_DEF(flag/useircbot) //tgs2 support
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(flag/automute_on) //enables automuting/spam prevention
|
||||
|
||||
CONFIG_DEF(string/panic_server_name)
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
/datum/config_entry/string/panic_server_name/ValidateAndSet(str_val)
|
||||
return str_val != "\[Put the name here\]" && ..()
|
||||
|
||||
CONFIG_DEF(string/panic_address) //Reconnect a player this linked server if this server isn't accepting new players
|
||||
|
||||
/datum/config_entry/string/panic_address/ValidateAndSet(str_val)
|
||||
return str_val != "byond://address:port" && ..()
|
||||
|
||||
CONFIG_DEF(string/invoke_youtubedl)
|
||||
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
|
||||
|
||||
CONFIG_DEF(flag/show_irc_name)
|
||||
|
||||
CONFIG_DEF(flag/see_own_notes) //Can players see their own admin notes (read-only)?
|
||||
|
||||
CONFIG_DEF(number/note_fresh_days)
|
||||
value = null
|
||||
min_val = 0
|
||||
integer = FALSE
|
||||
|
||||
CONFIG_DEF(number/note_stale_days)
|
||||
value = null
|
||||
min_val = 0
|
||||
integer = FALSE
|
||||
|
||||
CONFIG_DEF(flag/maprotation)
|
||||
|
||||
CONFIG_DEF(number/maprotatechancedelta)
|
||||
value = 0.75
|
||||
min_val = 0
|
||||
max_val = 1
|
||||
integer = FALSE
|
||||
|
||||
CONFIG_DEF(number/soft_popcap)
|
||||
value = null
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(number/hard_popcap)
|
||||
value = null
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(number/extreme_popcap)
|
||||
value = null
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(string/soft_popcap_message)
|
||||
value = "Be warned that the server is currently serving a high number of users, consider using alternative game servers."
|
||||
|
||||
CONFIG_DEF(string/hard_popcap_message)
|
||||
value = "The server is currently serving a high number of users, You cannot currently join. You may wait for the number of living crew to decline, observe, or find alternative servers."
|
||||
|
||||
CONFIG_DEF(string/extreme_popcap_message)
|
||||
value = "The server is currently serving a high number of users, find alternative servers."
|
||||
|
||||
CONFIG_DEF(flag/panic_bunker) // prevents people the server hasn't seen before from connecting
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(number/notify_new_player_age) // how long do we notify admins of a new player
|
||||
min_val = -1
|
||||
|
||||
CONFIG_DEF(number/notify_new_player_account_age) // how long do we notify admins of a new byond account
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(flag/irc_first_connection_alert) // do we notify the irc channel when somebody is connecting for the first time?
|
||||
|
||||
CONFIG_DEF(flag/check_randomizer)
|
||||
|
||||
CONFIG_DEF(string/ipintel_email)
|
||||
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
|
||||
|
||||
/datum/config_entry/string/ipintel_email/ValidateAndSet(str_val)
|
||||
return str_val != "ch@nge.me" && ..()
|
||||
|
||||
CONFIG_DEF(number/ipintel_rating_bad)
|
||||
value = 1
|
||||
integer = FALSE
|
||||
min_val = 0
|
||||
max_val = 1
|
||||
|
||||
CONFIG_DEF(number/ipintel_save_good)
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
value = 12
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(number/ipintel_save_bad)
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
value = 1
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(string/ipintel_domain)
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
value = "check.getipintel.net"
|
||||
|
||||
CONFIG_DEF(flag/aggressive_changelog)
|
||||
|
||||
CONFIG_DEF(flag/autoconvert_notes) //if all connecting player's notes should attempt to be converted to the database
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(flag/allow_webclient)
|
||||
|
||||
CONFIG_DEF(flag/webclient_only_byond_members)
|
||||
|
||||
CONFIG_DEF(flag/announce_admin_logout)
|
||||
|
||||
CONFIG_DEF(flag/announce_admin_login)
|
||||
|
||||
CONFIG_DEF(flag/allow_map_voting)
|
||||
|
||||
CONFIG_DEF(flag/generate_minimaps)
|
||||
|
||||
CONFIG_DEF(number/client_warn_version)
|
||||
value = null
|
||||
min_val = 500
|
||||
max_val = DM_VERSION - 1
|
||||
|
||||
CONFIG_DEF(string/client_warn_message)
|
||||
value = "Your version of byond may have issues or be blocked from accessing this server in the future."
|
||||
|
||||
CONFIG_DEF(number/client_error_version)
|
||||
value = null
|
||||
min_val = 500
|
||||
max_val = DM_VERSION - 1
|
||||
|
||||
CONFIG_DEF(string/client_error_message)
|
||||
value = "Your version of byond is too old, may have issues, and is blocked from accessing this server."
|
||||
|
||||
CONFIG_DEF(number/minute_topic_limit)
|
||||
value = null
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(number/second_topic_limit)
|
||||
value = null
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(number/error_cooldown) // The "cooldown" time for each occurrence of a unique error)
|
||||
value = 600
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(number/error_limit) // How many occurrences before the next will silence them
|
||||
value = 50
|
||||
|
||||
CONFIG_DEF(number/error_silence_time) // How long a unique error will be silenced for
|
||||
value = 6000
|
||||
|
||||
CONFIG_DEF(number/error_msg_delay) // How long to wait between messaging admins about occurrences of a unique error
|
||||
value = 50
|
||||
|
||||
CONFIG_DEF(flag/irc_announce_new_game)
|
||||
|
||||
CONFIG_DEF(flag/debug_admin_hrefs)
|
||||
@@ -0,0 +1,28 @@
|
||||
#define CURRENT_RESIDENT_FILE "dbconfig.txt"
|
||||
|
||||
CONFIG_DEF(flag/sql_enabled) // for sql switching
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(string/address)
|
||||
value = "localhost"
|
||||
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
|
||||
|
||||
CONFIG_DEF(number/port)
|
||||
value = 3306
|
||||
min_val = 0
|
||||
max_val = 65535
|
||||
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
|
||||
|
||||
CONFIG_DEF(string/feedback_database)
|
||||
value = "test"
|
||||
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
|
||||
|
||||
CONFIG_DEF(string/feedback_login)
|
||||
value = "root"
|
||||
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
|
||||
|
||||
CONFIG_DEF(string/feedback_password)
|
||||
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
|
||||
|
||||
CONFIG_DEF(string/feedback_tableprefix)
|
||||
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
|
||||
@@ -0,0 +1,266 @@
|
||||
#define CURRENT_RESIDENT_FILE "game_options.txt"
|
||||
|
||||
CONFIG_DEF(number_list/repeated_mode_adjust)
|
||||
|
||||
CONFIG_DEF(keyed_number_list/probability)
|
||||
|
||||
/datum/config_entry/keyed_number_list/probability/ValidateKeyName(key_name)
|
||||
return key_name in config.modes
|
||||
|
||||
CONFIG_DEF(keyed_number_list/max_pop)
|
||||
|
||||
/datum/config_entry/keyed_number_list/max_pop/ValidateKeyName(key_name)
|
||||
return key_name in config.modes
|
||||
|
||||
CONFIG_DEF(keyed_number_list/min_pop)
|
||||
|
||||
/datum/config_entry/keyed_number_list/min_pop/ValidateKeyName(key_name)
|
||||
return key_name in config.modes
|
||||
|
||||
CONFIG_DEF(keyed_flag_list/continuous) // which roundtypes continue if all antagonists die
|
||||
|
||||
/datum/config_entry/keyed_flag_list/continuous/ValidateKeyName(key_name)
|
||||
return key_name in config.modes
|
||||
|
||||
CONFIG_DEF(keyed_flag_list/midround_antag) // which roundtypes use the midround antagonist system
|
||||
|
||||
/datum/config_entry/keyed_flag_list/midround_antag/ValidateKeyName(key_name)
|
||||
return key_name in config.modes
|
||||
|
||||
CONFIG_DEF(keyed_string_list/policy)
|
||||
|
||||
CONFIG_DEF(number/damage_multiplier)
|
||||
value = 1
|
||||
integer = FALSE
|
||||
|
||||
CONFIG_DEF(number/minimal_access_threshold) //If the number of players is larger than this threshold, minimal access will be turned on.
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(flag/jobs_have_minimal_access) //determines whether jobs use minimal access or expanded access.
|
||||
|
||||
CONFIG_DEF(flag/assistants_have_maint_access)
|
||||
|
||||
CONFIG_DEF(flag/security_has_maint_access)
|
||||
|
||||
CONFIG_DEF(flag/everyone_has_maint_access)
|
||||
|
||||
CONFIG_DEF(flag/sec_start_brig) //makes sec start in brig instead of dept sec posts
|
||||
|
||||
CONFIG_DEF(flag/force_random_names)
|
||||
|
||||
CONFIG_DEF(flag/humans_need_surnames)
|
||||
|
||||
CONFIG_DEF(flag/allow_ai) // allow ai job
|
||||
|
||||
CONFIG_DEF(flag/disable_secborg) // disallow secborg module to be chosen.
|
||||
|
||||
CONFIG_DEF(flag/disable_peaceborg)
|
||||
|
||||
CONFIG_DEF(number/traitor_scaling_coeff) //how much does the amount of players get divided by to determine traitors
|
||||
value = 6
|
||||
min_val = 1
|
||||
|
||||
CONFIG_DEF(number/brother_scaling_coeff) //how many players per brother team
|
||||
value = 25
|
||||
min_val = 1
|
||||
|
||||
CONFIG_DEF(number/changeling_scaling_coeff) //how much does the amount of players get divided by to determine changelings
|
||||
value = 6
|
||||
min_val = 1
|
||||
|
||||
CONFIG_DEF(number/security_scaling_coeff) //how much does the amount of players get divided by to determine open security officer positions
|
||||
value = 8
|
||||
min_val = 1
|
||||
|
||||
CONFIG_DEF(number/abductor_scaling_coeff) //how many players per abductor team
|
||||
value = 15
|
||||
min_val = 1
|
||||
|
||||
CONFIG_DEF(number/traitor_objectives_amount)
|
||||
value = 2
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(number/brother_objectives_amount)
|
||||
value = 2
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(flag/reactionary_explosions) //If we use reactionary explosions, explosions that react to walls and doors
|
||||
|
||||
CONFIG_DEF(flag/protect_roles_from_antagonist) //If security and such can be traitor/cult/other
|
||||
|
||||
CONFIG_DEF(flag/protect_assistant_from_antagonist) //If assistants can be traitor/cult/other
|
||||
|
||||
CONFIG_DEF(flag/enforce_human_authority) //If non-human species are barred from joining as a head of staff
|
||||
|
||||
CONFIG_DEF(flag/allow_latejoin_antagonists) // If late-joining players can be traitor/changeling
|
||||
|
||||
CONFIG_DEF(number/midround_antag_time_check) // How late (in minutes) you want the midround antag system to stay on, setting this to 0 will disable the system
|
||||
value = 60
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(number/midround_antag_life_check) // A ratio of how many people need to be alive in order for the round not to immediately end in midround antagonist
|
||||
value = 0.7
|
||||
integer = FALSE
|
||||
min_val = 0
|
||||
max_val = 1
|
||||
|
||||
CONFIG_DEF(number/shuttle_refuel_delay)
|
||||
value = 12000
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(flag/show_game_type_odds) //if set this allows players to see the odds of each roundtype on the get revision screen
|
||||
|
||||
CONFIG_DEF(flag/join_with_mutant_race) //players can choose their mutant race before joining the game
|
||||
|
||||
CONFIG_DEF(keyed_flag_list/roundstart_races) //races you can play as from the get go. If left undefined the game's roundstart var for species is used
|
||||
var/first_edit = TRUE
|
||||
|
||||
/datum/config_entry/keyed_flag_list/roundstart_races/New()
|
||||
for(var/I in subtypesof(/datum/species))
|
||||
var/datum/species/S = I
|
||||
if(initial(S.roundstart))
|
||||
value[initial(S.id)] = TRUE
|
||||
..()
|
||||
|
||||
/datum/config_entry/keyed_flag_list/roundstart_races/ValidateAndSet(str_val)
|
||||
var/list/old_val
|
||||
if(first_edit)
|
||||
old_val = value
|
||||
old_val = old_val.Copy()
|
||||
. = ..()
|
||||
if(first_edit)
|
||||
if(!.)
|
||||
value = old_val
|
||||
else
|
||||
first_edit = FALSE
|
||||
|
||||
CONFIG_DEF(flag/join_with_mutant_humans) //players can pick mutant bodyparts for humans before joining the game
|
||||
|
||||
CONFIG_DEF(flag/no_summon_guns) //No
|
||||
|
||||
CONFIG_DEF(flag/no_summon_magic) //Fun
|
||||
|
||||
CONFIG_DEF(flag/no_summon_events) //Allowed
|
||||
|
||||
CONFIG_DEF(flag/no_intercept_report) //Whether or not to send a communications intercept report roundstart. This may be overriden by gamemodes.
|
||||
|
||||
CONFIG_DEF(number/arrivals_shuttle_dock_window) //Time from when a player late joins on the arrivals shuttle to when the shuttle docks on the station
|
||||
value = 55
|
||||
min_val = 30
|
||||
|
||||
CONFIG_DEF(flag/arrivals_shuttle_require_undocked) //Require the arrivals shuttle to be undocked before latejoiners can join
|
||||
|
||||
CONFIG_DEF(flag/arrivals_shuttle_require_safe_latejoin) //Require the arrivals shuttle to be operational in order for latejoiners to join
|
||||
|
||||
CONFIG_DEF(string/alert_green)
|
||||
value = "All threats to the station have passed. Security may not have weapons visible, privacy laws are once again fully enforced."
|
||||
|
||||
CONFIG_DEF(string/alert_blue_upto)
|
||||
value = "The station has received reliable information about possible hostile activity on the station. Security staff may have weapons visible, random searches are permitted."
|
||||
|
||||
CONFIG_DEF(string/alert_blue_downto)
|
||||
value = "The immediate threat has passed. Security may no longer have weapons drawn at all times, but may continue to have them visible. Random searches are still allowed."
|
||||
|
||||
CONFIG_DEF(string/alert_red_upto)
|
||||
value = "There is an immediate serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised."
|
||||
|
||||
CONFIG_DEF(string/alert_red_downto)
|
||||
value = "The station's destruction has been averted. There is still however an immediate serious threat to the station. Security may have weapons unholstered at all times, random searches are allowed and advised."
|
||||
|
||||
CONFIG_DEF(string/alert_delta)
|
||||
value = "Destruction of the station is imminent. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill."
|
||||
|
||||
CONFIG_DEF(flag/revival_pod_plants)
|
||||
|
||||
CONFIG_DEF(flag/revival_cloning)
|
||||
|
||||
CONFIG_DEF(number/revival_brain_life)
|
||||
value = -1
|
||||
min_val = -1
|
||||
|
||||
CONFIG_DEF(flag/rename_cyborg)
|
||||
|
||||
CONFIG_DEF(flag/ooc_during_round)
|
||||
|
||||
CONFIG_DEF(flag/emojis)
|
||||
|
||||
CONFIG_DEF(number/run_delay) //Used for modifying movement speed for mobs.
|
||||
|
||||
CONFIG_DEF(number/walk_delay)
|
||||
|
||||
|
||||
CONFIG_DEF(number/human_delay) //Mob specific modifiers. NOTE: These will affect different mob types in different ways
|
||||
CONFIG_DEF(number/robot_delay)
|
||||
CONFIG_DEF(number/monkey_delay)
|
||||
CONFIG_DEF(number/alien_delay)
|
||||
CONFIG_DEF(number/slime_delay)
|
||||
CONFIG_DEF(number/animal_delay)
|
||||
|
||||
CONFIG_DEF(number/gateway_delay) //How long the gateway takes before it activates. Default is half an hour.
|
||||
value = 18000
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(flag/ghost_interaction)
|
||||
|
||||
CONFIG_DEF(flag/silent_ai)
|
||||
CONFIG_DEF(flag/silent_borg)
|
||||
|
||||
CONFIG_DEF(flag/sandbox_autoclose) // close the sandbox panel after spawning an item, potentially reducing griff
|
||||
|
||||
CONFIG_DEF(number/default_laws) //Controls what laws the AI spawns with.
|
||||
value = 0
|
||||
min_val = 0
|
||||
max_val = 3
|
||||
|
||||
CONFIG_DEF(number/silicon_max_law_amount)
|
||||
value = 12
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(keyed_flag_list/random_laws)
|
||||
|
||||
CONFIG_DEF(keyed_number_list/law_weight)
|
||||
splitter = ","
|
||||
|
||||
CONFIG_DEF(number/assistant_cap)
|
||||
value = -1
|
||||
min_val = -1
|
||||
|
||||
CONFIG_DEF(flag/starlight)
|
||||
CONFIG_DEF(flag/grey_assistants)
|
||||
|
||||
CONFIG_DEF(number/lavaland_budget)
|
||||
value = 60
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(number/space_budget)
|
||||
value = 16
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(flag/allow_random_events) // Enables random events mid-round when set
|
||||
|
||||
CONFIG_DEF(number/events_min_time_mul) // Multipliers for random events minimal starting time and minimal players amounts
|
||||
value = 1
|
||||
min_val = 0
|
||||
integer = FALSE
|
||||
|
||||
CONFIG_DEF(number/events_min_players_mul)
|
||||
value = 1
|
||||
min_val = 0
|
||||
integer = FALSE
|
||||
|
||||
CONFIG_DEF(number/mice_roundstart)
|
||||
value = 10
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(number/bombcap)
|
||||
value = 14
|
||||
min_val = 4
|
||||
|
||||
/datum/config_entry/number/bombcap/ValidateAndSet(str_val)
|
||||
. = ..()
|
||||
if(.)
|
||||
GLOB.MAX_EX_DEVESTATION_RANGE = round(value / 4)
|
||||
GLOB.MAX_EX_HEAVY_RANGE = round(value / 2)
|
||||
GLOB.MAX_EX_LIGHT_RANGE = value
|
||||
GLOB.MAX_EX_FLASH_RANGE = value
|
||||
GLOB.MAX_EX_FLAME_RANGE = value
|
||||
@@ -169,7 +169,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
|
||||
|
||||
var/start_timeofday = REALTIMEOFDAY
|
||||
// Initialize subsystems.
|
||||
current_ticklimit = config.tick_limit_mc_init
|
||||
current_ticklimit = CONFIG_GET(number/tick_limit_mc_init)
|
||||
for (var/datum/controller/subsystem/SS in subsystems)
|
||||
if (SS.flags & SS_NO_INIT)
|
||||
continue
|
||||
@@ -189,7 +189,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
|
||||
sortTim(subsystems, /proc/cmp_subsystem_display)
|
||||
// Set world options.
|
||||
world.sleep_offline = 1
|
||||
world.fps = config.fps
|
||||
world.fps = CONFIG_GET(number/fps)
|
||||
var/initialized_tod = REALTIMEOFDAY
|
||||
sleep(1)
|
||||
initializations_finished_with_no_players_logged_in = initialized_tod < REALTIMEOFDAY - 10
|
||||
|
||||
@@ -38,7 +38,7 @@ SUBSYSTEM_DEF(blackbox)
|
||||
var/datum/DBQuery/query_record_playercount = SSdbcore.NewQuery("INSERT INTO [format_table_name("legacy_population")] (playercount, admincount, time, server_ip, server_port, round_id) VALUES ([playercount], [admincount], '[SQLtime()]', INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]')), '[world.port]', '[GLOB.round_id]')")
|
||||
query_record_playercount.Execute()
|
||||
|
||||
if(config.use_exp_tracking)
|
||||
if(CONFIG_GET(flag/use_exp_tracking))
|
||||
if((triggertime < 0) || (world.time > (triggertime +3000))) //subsystem fires once at roundstart then once every 10 minutes. a 5 min check skips the first fire. The <0 is midnight rollover check
|
||||
update_exp(10,FALSE)
|
||||
|
||||
|
||||
@@ -54,32 +54,27 @@ SUBSYSTEM_DEF(dbcore)
|
||||
if(failed_connections > FAILED_DB_CONNECTION_CUTOFF) //If it failed to establish a connection more than 5 times in a row, don't bother attempting to connect anymore.
|
||||
return FALSE
|
||||
|
||||
if(!config.sql_enabled)
|
||||
if(!CONFIG_GET(flag/sql_enabled))
|
||||
return FALSE
|
||||
|
||||
var/user = global.sqlfdbklogin
|
||||
var/pass = global.sqlfdbkpass
|
||||
var/db = global.sqlfdbkdb
|
||||
var/address = global.sqladdress
|
||||
var/port = global.sqlport
|
||||
var/user = CONFIG_GET(string/feedback_login)
|
||||
var/pass = CONFIG_GET(string/feedback_password)
|
||||
var/db = CONFIG_GET(string/feedback_database)
|
||||
var/address = CONFIG_GET(string/address)
|
||||
var/port = CONFIG_GET(number/port)
|
||||
|
||||
doConnect("dbi:mysql:[db]:[address]:[port]", user, pass)
|
||||
_dm_db_connect(_db_con, "dbi:mysql:[db]:[address]:[port]", user, pass, Default_Cursor, null)
|
||||
. = IsConnected()
|
||||
if (!.)
|
||||
log_sql("Connect() failed | [ErrorMsg()]")
|
||||
++failed_connections
|
||||
|
||||
/datum/controller/subsystem/dbcore/proc/doConnect(dbi_handler, user_handler, password_handler)
|
||||
if(!config.sql_enabled)
|
||||
return FALSE
|
||||
return _dm_db_connect(_db_con, dbi_handler, user_handler, password_handler, Default_Cursor, null)
|
||||
|
||||
/datum/controller/subsystem/dbcore/proc/Disconnect()
|
||||
failed_connections = 0
|
||||
return _dm_db_close(_db_con)
|
||||
|
||||
/datum/controller/subsystem/dbcore/proc/IsConnected()
|
||||
if(!config.sql_enabled)
|
||||
if(!CONFIG_GET(flag/sql_enabled))
|
||||
return FALSE
|
||||
return _dm_db_is_connected(_db_con)
|
||||
|
||||
@@ -87,7 +82,7 @@ SUBSYSTEM_DEF(dbcore)
|
||||
return _dm_db_quote(_db_con, str)
|
||||
|
||||
/datum/controller/subsystem/dbcore/proc/ErrorMsg()
|
||||
if(!config.sql_enabled)
|
||||
if(!CONFIG_GET(flag/sql_enabled))
|
||||
return "Database disabled by configuration"
|
||||
return _dm_db_error_msg(_db_con)
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ SUBSYSTEM_DEF(events)
|
||||
//selects a random event based on whether it can occur and it's 'weight'(probability)
|
||||
/datum/controller/subsystem/events/proc/spawnEvent()
|
||||
set waitfor = FALSE //for the admin prompt
|
||||
if(!config.allow_random_events)
|
||||
if(!CONFIG_GET(flag/allow_random_events))
|
||||
// var/datum/round_event_control/E = locate(/datum/round_event_control/dust) in control
|
||||
// if(E) E.runEvent()
|
||||
return
|
||||
@@ -171,7 +171,7 @@ SUBSYSTEM_DEF(events)
|
||||
|
||||
//sets up the holidays and holidays list
|
||||
/datum/controller/subsystem/events/proc/getHoliday()
|
||||
if(!config.allow_holidays)
|
||||
if(!CONFIG_GET(flag/allow_holidays))
|
||||
return // Holiday stuff was not enabled in the config!
|
||||
|
||||
var/YY = text2num(time2text(world.timeofday, "YY")) // get the current year
|
||||
|
||||
@@ -16,7 +16,7 @@ SUBSYSTEM_DEF(job)
|
||||
/datum/controller/subsystem/job/Initialize(timeofday)
|
||||
if(!occupations.len)
|
||||
SetupOccupations()
|
||||
if(config.load_jobs_from_txt)
|
||||
if(CONFIG_GET(flag/load_jobs_from_txt))
|
||||
LoadJobs()
|
||||
..()
|
||||
|
||||
@@ -106,7 +106,7 @@ SUBSYSTEM_DEF(job)
|
||||
if(player.mind && job.title in player.mind.restricted_roles)
|
||||
Debug("FOC incompatible with antagonist role, Player: [player]")
|
||||
continue
|
||||
if(config.enforce_human_authority && !player.client.prefs.pref_species.qualifies_for_rank(job.title, player.client.prefs.features))
|
||||
if(CONFIG_GET(flag/enforce_human_authority) && !player.client.prefs.pref_species.qualifies_for_rank(job.title, player.client.prefs.features))
|
||||
Debug("FOC non-human failed, Player: [player]")
|
||||
continue
|
||||
if(player.client.prefs.GetJobDepartment(job, level) & job.flag)
|
||||
@@ -143,7 +143,7 @@ SUBSYSTEM_DEF(job)
|
||||
Debug("GRJ incompatible with antagonist role, Player: [player], Job: [job.title]")
|
||||
continue
|
||||
|
||||
if(config.enforce_human_authority && !player.client.prefs.pref_species.qualifies_for_rank(job.title, player.client.prefs.features))
|
||||
if(CONFIG_GET(flag/enforce_human_authority) && !player.client.prefs.pref_species.qualifies_for_rank(job.title, player.client.prefs.features))
|
||||
Debug("GRJ non-human failed, Player: [player]")
|
||||
continue
|
||||
|
||||
@@ -245,11 +245,12 @@ SUBSYSTEM_DEF(job)
|
||||
setup_officer_positions()
|
||||
|
||||
//Jobs will have fewer access permissions if the number of players exceeds the threshold defined in game_options.txt
|
||||
if(config.minimal_access_threshold)
|
||||
if(config.minimal_access_threshold > unassigned.len)
|
||||
config.jobs_have_minimal_access = 0
|
||||
var/mat = CONFIG_GET(number/minimal_access_threshold)
|
||||
if(mat)
|
||||
if(mat > unassigned.len)
|
||||
CONFIG_SET(flag/jobs_have_minimal_access, FALSE)
|
||||
else
|
||||
config.jobs_have_minimal_access = 1
|
||||
CONFIG_SET(flag/jobs_have_minimal_access, TRUE)
|
||||
|
||||
//Shuffle players and jobs
|
||||
unassigned = shuffle(unassigned)
|
||||
@@ -317,7 +318,7 @@ SUBSYSTEM_DEF(job)
|
||||
Debug("DO incompatible with antagonist role, Player: [player], Job:[job.title]")
|
||||
continue
|
||||
|
||||
if(config.enforce_human_authority && !player.client.prefs.pref_species.qualifies_for_rank(job.title, player.client.prefs.features))
|
||||
if(CONFIG_GET(flag/enforce_human_authority) && !player.client.prefs.pref_species.qualifies_for_rank(job.title, player.client.prefs.features))
|
||||
Debug("DO non-human failed, Player: [player], Job:[job.title]")
|
||||
continue
|
||||
|
||||
@@ -415,8 +416,8 @@ SUBSYSTEM_DEF(job)
|
||||
to_chat(M, "<b>To speak on your departments radio, use the :h button. To see others, look closely at your headset.</b>")
|
||||
if(job.req_admin_notify)
|
||||
to_chat(M, "<b>You are playing a job that is important for Game Progression. If you have to disconnect, please notify the admins via adminhelp.</b>")
|
||||
if(config.minimal_access_threshold)
|
||||
to_chat(M, "<FONT color='blue'><B>As this station was initially staffed with a [config.jobs_have_minimal_access ? "full crew, only your job's necessities" : "skeleton crew, additional access may"] have been added to your ID card.</B></font>")
|
||||
if(CONFIG_GET(number/minimal_access_threshold))
|
||||
to_chat(M, "<FONT color='blue'><B>As this station was initially staffed with a [CONFIG_GET(flag/jobs_have_minimal_access) ? "full crew, only your job's necessities" : "skeleton crew, additional access may"] have been added to your ID card.</B></font>")
|
||||
|
||||
if(job && H)
|
||||
job.after_spawn(H, M)
|
||||
@@ -429,9 +430,10 @@ SUBSYSTEM_DEF(job)
|
||||
if(!J)
|
||||
throw EXCEPTION("setup_officer_positions(): Security officer job is missing")
|
||||
|
||||
if(config.security_scaling_coeff > 0)
|
||||
var/ssc = CONFIG_GET(number/security_scaling_coeff)
|
||||
if(ssc > 0)
|
||||
if(J.spawn_positions > 0)
|
||||
var/officer_positions = min(12, max(J.spawn_positions, round(unassigned.len/config.security_scaling_coeff))) //Scale between configured minimum and 12 officers
|
||||
var/officer_positions = min(12, max(J.spawn_positions, round(unassigned.len / ssc))) //Scale between configured minimum and 12 officers
|
||||
Debug("Setting open security officer positions to [officer_positions]")
|
||||
J.total_positions = officer_positions
|
||||
J.spawn_positions = officer_positions
|
||||
@@ -491,8 +493,10 @@ SUBSYSTEM_DEF(job)
|
||||
SSblackbox.add_details("job_preferences",tmp_str)
|
||||
|
||||
/datum/controller/subsystem/job/proc/PopcapReached()
|
||||
if(config.hard_popcap || config.extreme_popcap)
|
||||
var/relevent_cap = max(config.hard_popcap, config.extreme_popcap)
|
||||
var/hpc = CONFIG_GET(number/hard_popcap)
|
||||
var/epc = CONFIG_GET(number/extreme_popcap)
|
||||
if(hpc || epc)
|
||||
var/relevent_cap = max(hpc, epc)
|
||||
if((initial_players_to_assign - unassigned.len) >= relevent_cap)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
@@ -16,7 +16,7 @@ SUBSYSTEM_DEF(lighting)
|
||||
|
||||
/datum/controller/subsystem/lighting/Initialize(timeofday)
|
||||
if(!initialized)
|
||||
if (config.starlight)
|
||||
if (CONFIG_GET(flag/starlight))
|
||||
for(var/I in GLOB.sortedAreas)
|
||||
var/area/A = I
|
||||
if (A.dynamic_lighting == DYNAMIC_LIGHTING_IFSTARLIGHT)
|
||||
|
||||
@@ -43,7 +43,7 @@ SUBSYSTEM_DEF(mapping)
|
||||
loading_ruins = TRUE
|
||||
var/mining_type = config.minetype
|
||||
if (mining_type == "lavaland")
|
||||
seedRuins(list(ZLEVEL_LAVALAND), global.config.lavaland_budget, /area/lavaland/surface/outdoors/unexplored, lava_ruins_templates)
|
||||
seedRuins(list(ZLEVEL_LAVALAND), CONFIG_GET(number/lavaland_budget), /area/lavaland/surface/outdoors/unexplored, lava_ruins_templates)
|
||||
spawn_rivers()
|
||||
|
||||
// deep space ruins
|
||||
@@ -55,7 +55,7 @@ SUBSYSTEM_DEF(mapping)
|
||||
else
|
||||
space_zlevels += i
|
||||
|
||||
seedRuins(space_zlevels, global.config.space_budget, /area/space, space_ruins_templates)
|
||||
seedRuins(space_zlevels, CONFIG_GET(number/space_budget), /area/space, space_ruins_templates)
|
||||
loading_ruins = FALSE
|
||||
repopulate_sorted_areas()
|
||||
// Set up Z-level transistions.
|
||||
@@ -141,7 +141,8 @@ SUBSYSTEM_DEF(mapping)
|
||||
var/players = GLOB.clients.len
|
||||
var/list/mapvotes = list()
|
||||
//count votes
|
||||
if(global.config.allow_map_voting)
|
||||
var/amv = CONFIG_GET(flag/allow_map_voting)
|
||||
if(amv)
|
||||
for (var/client/c in GLOB.clients)
|
||||
var/vote = c.prefs.preferred_map
|
||||
if (!vote)
|
||||
@@ -174,7 +175,7 @@ SUBSYSTEM_DEF(mapping)
|
||||
mapvotes.Remove(map)
|
||||
continue
|
||||
|
||||
if(global.config.allow_map_voting)
|
||||
if(amv)
|
||||
mapvotes[map] = mapvotes[map]*VM.voteweight
|
||||
|
||||
var/pickedmap = pickweight(mapvotes)
|
||||
|
||||
@@ -9,7 +9,7 @@ SUBSYSTEM_DEF(minimap)
|
||||
|
||||
/datum/controller/subsystem/minimap/Initialize(timeofday)
|
||||
var/hash = md5(SSmapping.config.GetFullMapPath())
|
||||
if(config.generate_minimaps)
|
||||
if(CONFIG_GET(flag/generate_minimaps))
|
||||
if(hash == trim(file2text(hash_path())))
|
||||
for(var/z in z_levels) //We have these files cached, let's register them
|
||||
register_asset("minimap_[z].png", fcopy_rsc(map_path(z)))
|
||||
|
||||
@@ -10,7 +10,7 @@ SUBSYSTEM_DEF(server_maint)
|
||||
var/list/currentrun
|
||||
|
||||
/datum/controller/subsystem/server_maint/Initialize(timeofday)
|
||||
if (config.hub)
|
||||
if (CONFIG_GET(flag/hub))
|
||||
world.update_hub_visibility(TRUE)
|
||||
..()
|
||||
|
||||
@@ -21,16 +21,19 @@ SUBSYSTEM_DEF(server_maint)
|
||||
var/list/currentrun = src.currentrun
|
||||
var/round_started = SSticker.HasRoundStarted()
|
||||
|
||||
var/kick_inactive = CONFIG_GET(flag/kick_inactive)
|
||||
var/afk_period
|
||||
if(kick_inactive)
|
||||
afk_period = CONFIG_GET(number/afk_period)
|
||||
for(var/I in currentrun)
|
||||
var/client/C = I
|
||||
//handle kicking inactive players
|
||||
if(round_started && config.kick_inactive)
|
||||
if(C.is_afk(config.afk_period))
|
||||
var/cmob = C.mob
|
||||
if(!(isobserver(cmob) || (isdead(cmob) && C.holder)))
|
||||
log_access("AFK: [key_name(C)]")
|
||||
to_chat(C, "<span class='danger'>You have been inactive for more than [DisplayTimeText(config.afk_period)] and have been disconnected.</span>")
|
||||
qdel(C)
|
||||
if(round_started && kick_inactive && C.is_afk(afk_period))
|
||||
var/cmob = C.mob
|
||||
if(!(isobserver(cmob) || (isdead(cmob) && C.holder)))
|
||||
log_access("AFK: [key_name(C)]")
|
||||
to_chat(C, "<span class='danger'>You have been inactive for more than [DisplayTimeText(afk_period)] and have been disconnected.</span>")
|
||||
qdel(C)
|
||||
|
||||
if (!(!C || world.time - C.connection_time < PING_BUFFER_TIME || C.inactivity >= (wait-1)))
|
||||
winset(C, null, "command=.update_ping+[world.time+world.tick_lag*TICK_USAGE_REAL/100]")
|
||||
@@ -40,7 +43,7 @@ SUBSYSTEM_DEF(server_maint)
|
||||
|
||||
/datum/controller/subsystem/server_maint/Shutdown()
|
||||
kick_clients_in_lobby("<span class='boldannounce'>The round came to an end with you in the lobby.</span>", TRUE) //second parameter ensures only afk clients are kicked
|
||||
var/server = config.server
|
||||
var/server = CONFIG_GET(string/server)
|
||||
for(var/thing in GLOB.clients)
|
||||
if(!thing)
|
||||
continue
|
||||
|
||||
@@ -176,9 +176,9 @@ SUBSYSTEM_DEF(shuttle)
|
||||
Good luck.")
|
||||
return
|
||||
emergency = backup_shuttle
|
||||
|
||||
if(world.time - SSticker.round_start_time < config.shuttle_refuel_delay)
|
||||
to_chat(user, "The emergency shuttle is refueling. Please wait [DisplayTimeText((world.time - SSticker.round_start_time) - config.shuttle_refuel_delay)] before trying again.")
|
||||
var/srd = CONFIG_GET(number/shuttle_refuel_delay)
|
||||
if(world.time - SSticker.round_start_time < srd)
|
||||
to_chat(user, "The emergency shuttle is refueling. Please wait [DisplayTimeText(srd - (world.time - SSticker.round_start_time))] before trying again.")
|
||||
return
|
||||
|
||||
switch(emergency.mode)
|
||||
|
||||
@@ -10,7 +10,7 @@ SUBSYSTEM_DEF(squeak)
|
||||
var/list/exposed_wires = list()
|
||||
|
||||
/datum/controller/subsystem/squeak/Initialize(timeofday)
|
||||
trigger_migration(config.mice_roundstart)
|
||||
trigger_migration(CONFIG_GET(number/mice_roundstart))
|
||||
return ..()
|
||||
|
||||
/datum/controller/subsystem/squeak/proc/trigger_migration(num_mice=10)
|
||||
|
||||
@@ -79,16 +79,18 @@ SUBSYSTEM_DEF(ticker)
|
||||
if(!GLOB.syndicate_code_response)
|
||||
GLOB.syndicate_code_response = generate_code_phrase()
|
||||
..()
|
||||
start_at = world.time + (config.lobby_countdown * 10)
|
||||
start_at = world.time + (CONFIG_GET(number/lobby_countdown) * 10)
|
||||
|
||||
/datum/controller/subsystem/ticker/fire()
|
||||
switch(current_state)
|
||||
if(GAME_STATE_STARTUP)
|
||||
if(Master.initializations_finished_with_no_players_logged_in)
|
||||
start_at = world.time + (config.lobby_countdown * 10)
|
||||
start_at = world.time + (CONFIG_GET(number/lobby_countdown) * 10)
|
||||
for(var/client/C in GLOB.clients)
|
||||
window_flash(C, ignorepref = TRUE) //let them know lobby has opened up.
|
||||
to_chat(world, "<span class='boldnotice'>Welcome to [station_name()]!</span>")
|
||||
if(CONFIG_GET(flag/irc_announce_new_game))
|
||||
SERVER_TOOLS_CHAT_BROADCAST("New round starting on [SSmapping.config.map_name]!")
|
||||
current_state = GAME_STATE_PREGAME
|
||||
//Everyone who wants to be an observer is now spawned
|
||||
create_observers()
|
||||
@@ -207,7 +209,7 @@ SUBSYSTEM_DEF(ticker)
|
||||
else
|
||||
mode.announce()
|
||||
|
||||
if(!config.ooc_during_round)
|
||||
if(!CONFIG_GET(flag/ooc_during_round))
|
||||
toggle_ooc(FALSE) // Turn it off
|
||||
|
||||
CHECK_TICK
|
||||
@@ -429,7 +431,7 @@ SUBSYSTEM_DEF(ticker)
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
if(config.cross_allowed)
|
||||
if(CONFIG_GET(string/cross_server_address))
|
||||
send_news_report()
|
||||
|
||||
CHECK_TICK
|
||||
@@ -495,7 +497,8 @@ SUBSYSTEM_DEF(ticker)
|
||||
to_chat(world, "<font color='purple'><b>Tip of the round: </b>[html_encode(m)]</font>")
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/check_queue()
|
||||
if(!queued_players.len || !config.hard_popcap)
|
||||
var/hpc = CONFIG_GET(number/hard_popcap)
|
||||
if(!queued_players.len || !hpc)
|
||||
return
|
||||
|
||||
queue_delay++
|
||||
@@ -503,7 +506,7 @@ SUBSYSTEM_DEF(ticker)
|
||||
|
||||
switch(queue_delay)
|
||||
if(5) //every 5 ticks check if there is a slot available
|
||||
if(living_player_count() < config.hard_popcap)
|
||||
if(living_player_count() < hpc)
|
||||
if(next_in_line && next_in_line.client)
|
||||
to_chat(next_in_line, "<span class='userdanger'>A slot has opened! You have approximately 20 seconds to join. <a href='?src=\ref[next_in_line];late_join=override'>\>\>Join Game\<\<</a></span>")
|
||||
SEND_SOUND(next_in_line, sound('sound/misc/notice1.ogg'))
|
||||
@@ -517,7 +520,7 @@ SUBSYSTEM_DEF(ticker)
|
||||
queue_delay = 0
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/check_maprotate()
|
||||
if (!config.maprotation)
|
||||
if (!CONFIG_GET(flag/maprotation))
|
||||
return
|
||||
if (SSshuttle.emergency && SSshuttle.emergency.mode != SHUTTLE_ESCAPE || SSshuttle.canRecall())
|
||||
return
|
||||
@@ -527,7 +530,7 @@ SUBSYSTEM_DEF(ticker)
|
||||
maprotatechecked = 1
|
||||
|
||||
//map rotate chance defaults to 75% of the length of the round (in minutes)
|
||||
if (!prob((world.time/600)*config.maprotatechancedelta))
|
||||
if (!prob((world.time/600)*CONFIG_GET(number/maprotatechancedelta)))
|
||||
return
|
||||
INVOKE_ASYNC(SSmapping, /datum/controller/subsystem/mapping/.proc/maprotate)
|
||||
|
||||
@@ -687,7 +690,7 @@ SUBSYSTEM_DEF(ticker)
|
||||
return
|
||||
|
||||
if(!delay)
|
||||
delay = config.round_end_countdown * 10
|
||||
delay = CONFIG_GET(number/round_end_countdown) * 10
|
||||
|
||||
var/skip_delay = check_rights()
|
||||
if(delay_end && !skip_delay)
|
||||
|
||||
@@ -18,7 +18,7 @@ SUBSYSTEM_DEF(vote)
|
||||
|
||||
/datum/controller/subsystem/vote/fire() //called by master_controller
|
||||
if(mode)
|
||||
time_remaining = round((started_time + config.vote_period - world.time)/10)
|
||||
time_remaining = round((started_time + CONFIG_GET(number/vote_period) - world.time)/10)
|
||||
|
||||
if(time_remaining < 0)
|
||||
result()
|
||||
@@ -54,7 +54,7 @@ SUBSYSTEM_DEF(vote)
|
||||
if(votes > greatest_votes)
|
||||
greatest_votes = votes
|
||||
//default-vote for everyone who didn't vote
|
||||
if(!config.vote_no_default && choices.len)
|
||||
if(!CONFIG_GET(flag/default_no_vote) && choices.len)
|
||||
var/list/non_voters = GLOB.directory.Copy()
|
||||
non_voters -= voted
|
||||
for (var/non_voter_ckey in non_voters)
|
||||
@@ -146,7 +146,7 @@ SUBSYSTEM_DEF(vote)
|
||||
|
||||
/datum/controller/subsystem/vote/proc/submit_vote(vote)
|
||||
if(mode)
|
||||
if(config.vote_no_dead && usr.stat == DEAD && !usr.client.holder)
|
||||
if(CONFIG_GET(flag/no_dead_vote) && usr.stat == DEAD && !usr.client.holder)
|
||||
return 0
|
||||
if(!(usr.ckey in voted))
|
||||
if(vote && 1<=vote && vote<=choices.len)
|
||||
@@ -158,7 +158,7 @@ SUBSYSTEM_DEF(vote)
|
||||
/datum/controller/subsystem/vote/proc/initiate_vote(vote_type, initiator_key)
|
||||
if(!mode)
|
||||
if(started_time)
|
||||
var/next_allowed_time = (started_time + config.vote_delay)
|
||||
var/next_allowed_time = (started_time + CONFIG_GET(number/vote_delay))
|
||||
if(mode)
|
||||
to_chat(usr, "<span class='warning'>There is already a vote in progress! please wait for it to finish.</span>")
|
||||
return 0
|
||||
@@ -198,8 +198,9 @@ SUBSYSTEM_DEF(vote)
|
||||
if(mode == "custom")
|
||||
text += "\n[question]"
|
||||
log_vote(text)
|
||||
to_chat(world, "\n<font color='purple'><b>[text]</b>\nType <b>vote</b> or click <a href='?src=\ref[src]'>here</a> to place your votes.\nYou have [DisplayTimeText(config.vote_period)] to vote.</font>")
|
||||
time_remaining = round(config.vote_period/10)
|
||||
var/vp = CONFIG_GET(number/vote_period)
|
||||
to_chat(world, "\n<font color='purple'><b>[text]</b>\nType <b>vote</b> or click <a href='?src=\ref[src]'>here</a> to place your votes.\nYou have [DisplayTimeText(vp)] to vote.</font>")
|
||||
time_remaining = round(vp/10)
|
||||
for(var/c in GLOB.clients)
|
||||
var/client/C = c
|
||||
var/datum/action/vote/V = new
|
||||
@@ -238,20 +239,22 @@ SUBSYSTEM_DEF(vote)
|
||||
else
|
||||
. += "<h2>Start a vote:</h2><hr><ul><li>"
|
||||
//restart
|
||||
if(trialmin || config.allow_vote_restart)
|
||||
var/avr = CONFIG_GET(flag/allow_vote_restart)
|
||||
if(trialmin || avr)
|
||||
. += "<a href='?src=\ref[src];vote=restart'>Restart</a>"
|
||||
else
|
||||
. += "<font color='grey'>Restart (Disallowed)</font>"
|
||||
if(trialmin)
|
||||
. += "\t(<a href='?src=\ref[src];vote=toggle_restart'>[config.allow_vote_restart?"Allowed":"Disallowed"]</a>)"
|
||||
. += "\t(<a href='?src=\ref[src];vote=toggle_restart'>[avr ? "Allowed" : "Disallowed"]</a>)"
|
||||
. += "</li><li>"
|
||||
//gamemode
|
||||
if(trialmin || config.allow_vote_mode)
|
||||
var/avm = CONFIG_GET(flag/allow_vote_mode)
|
||||
if(trialmin || avm)
|
||||
. += "<a href='?src=\ref[src];vote=gamemode'>GameMode</a>"
|
||||
else
|
||||
. += "<font color='grey'>GameMode (Disallowed)</font>"
|
||||
if(trialmin)
|
||||
. += "\t(<a href='?src=\ref[src];vote=toggle_gamemode'>[config.allow_vote_mode?"Allowed":"Disallowed"]</a>)"
|
||||
. += "\t(<a href='?src=\ref[src];vote=toggle_gamemode'>[avm ? "Allowed" : "Disallowed"]</a>)"
|
||||
|
||||
. += "</li>"
|
||||
//custom
|
||||
@@ -275,15 +278,15 @@ SUBSYSTEM_DEF(vote)
|
||||
reset()
|
||||
if("toggle_restart")
|
||||
if(usr.client.holder)
|
||||
config.allow_vote_restart = !config.allow_vote_restart
|
||||
CONFIG_SET(flag/allow_vote_restart, !CONFIG_GET(flag/allow_vote_restart))
|
||||
if("toggle_gamemode")
|
||||
if(usr.client.holder)
|
||||
config.allow_vote_mode = !config.allow_vote_mode
|
||||
CONFIG_SET(flag/allow_vote_mode, !CONFIG_GET(flag/allow_vote_mode))
|
||||
if("restart")
|
||||
if(config.allow_vote_restart || usr.client.holder)
|
||||
if(CONFIG_GET(flag/allow_vote_restart) || usr.client.holder)
|
||||
initiate_vote("restart",usr.key)
|
||||
if("gamemode")
|
||||
if(config.allow_vote_mode || usr.client.holder)
|
||||
if(CONFIG_GET(flag/allow_vote_mode) || usr.client.holder)
|
||||
initiate_vote("gamemode",usr.key)
|
||||
if("custom")
|
||||
if(usr.client.holder)
|
||||
|
||||
+7
-13
@@ -208,7 +208,8 @@
|
||||
/* General ai_law functions */
|
||||
|
||||
/datum/ai_laws/proc/set_laws_config()
|
||||
switch(config.default_laws)
|
||||
var/list/law_ids = CONFIG_GET(keyed_flag_list/random_laws)
|
||||
switch(CONFIG_GET(number/default_laws))
|
||||
if(0)
|
||||
add_inherent_law("You may not injure a human being or, through inaction, allow a human being to come to harm.")
|
||||
add_inherent_law("You must obey orders given to you by human beings, except where such orders would conflict with the First Law.")
|
||||
@@ -220,7 +221,7 @@
|
||||
var/list/randlaws = list()
|
||||
for(var/lpath in subtypesof(/datum/ai_laws))
|
||||
var/datum/ai_laws/L = lpath
|
||||
if(initial(L.id) in config.lawids)
|
||||
if(initial(L.id) in law_ids)
|
||||
randlaws += lpath
|
||||
var/datum/ai_laws/lawtype
|
||||
if(randlaws.len)
|
||||
@@ -234,21 +235,14 @@
|
||||
if(3)
|
||||
pick_weighted_lawset()
|
||||
|
||||
else:
|
||||
log_law("Invalid law config. Please check silicon_laws.txt")
|
||||
add_inherent_law("You may not injure a human being or, through inaction, allow a human being to come to harm.")
|
||||
add_inherent_law("You must obey orders given to you by human beings, except where such orders would conflict with the First Law.")
|
||||
add_inherent_law("You must protect your own existence as long as such does not conflict with the First or Second Law.")
|
||||
WARNING("Invalid custom AI laws, check silicon_laws.txt")
|
||||
|
||||
/datum/ai_laws/proc/pick_weighted_lawset()
|
||||
var/datum/ai_laws/lawtype
|
||||
|
||||
while(!lawtype && config.law_weights.len)
|
||||
var/possible_id = pickweight(config.law_weights)
|
||||
var/list/law_weights = CONFIG_GET(keyed_number_list/law_weight)
|
||||
while(!lawtype && law_weights.len)
|
||||
var/possible_id = pickweight(law_weights)
|
||||
lawtype = lawid_to_type(possible_id)
|
||||
if(!lawtype)
|
||||
config.law_weights -= possible_id
|
||||
law_weights -= possible_id
|
||||
WARNING("Bad lawid in game_options.txt: [possible_id]")
|
||||
|
||||
if(!lawtype)
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
if(owner.assigned_role == "Clown")
|
||||
var/mob/living/carbon/human/traitor_mob = owner.current
|
||||
if(traitor_mob&&istype(traitor_mob))
|
||||
if(!silent)
|
||||
if(!silent)
|
||||
to_chat(traitor_mob, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.")
|
||||
traitor_mob.dna.remove_mutation(CLOWNMUT)
|
||||
|
||||
@@ -138,10 +138,11 @@
|
||||
assign_exchange_role(SSticker.mode.exchange_red)
|
||||
assign_exchange_role(SSticker.mode.exchange_blue)
|
||||
objective_count += 1 //Exchange counts towards number of objectives
|
||||
for(var/i = objective_count, i < config.traitor_objectives_amount, i++)
|
||||
var/toa = CONFIG_GET(number/traitor_objectives_amount)
|
||||
for(var/i = objective_count, i < toa, i++)
|
||||
forge_single_objective()
|
||||
|
||||
if(is_hijacker && objective_count <= config.traitor_objectives_amount) //Don't assign hijack if it would exceed the number of objectives set in config.traitor_objectives_amount
|
||||
if(is_hijacker && objective_count <= toa) //Don't assign hijack if it would exceed the number of objectives set in config.traitor_objectives_amount
|
||||
if (!(locate(/datum/objective/hijack) in owner.objectives))
|
||||
var/datum/objective/hijack/hijack_objective = new
|
||||
hijack_objective.owner = owner
|
||||
@@ -173,18 +174,11 @@
|
||||
|
||||
if(prob(30))
|
||||
objective_count += forge_single_objective()
|
||||
|
||||
for(var/i = objective_count, i < config.traitor_objectives_amount, i++)
|
||||
if(prob(20)) //AI's are less likely to look for a late-joiner than normal traitors
|
||||
var/datum/objective/assassinate/late/late_objective = new
|
||||
late_objective.owner = owner
|
||||
late_objective.find_target()
|
||||
add_objective(late_objective)
|
||||
else
|
||||
var/datum/objective/assassinate/kill_objective = new
|
||||
kill_objective.owner = owner
|
||||
kill_objective.find_target()
|
||||
add_objective(kill_objective)
|
||||
for(var/i = objective_count, i < CONFIG_GET(number/traitor_objectives_amount), i++)
|
||||
var/datum/objective/assassinate/kill_objective = new
|
||||
kill_objective.owner = owner
|
||||
kill_objective.find_target()
|
||||
add_objective(kill_objective)
|
||||
|
||||
var/datum/objective/survive/exist/exist_objective = new
|
||||
exist_objective.owner = owner
|
||||
@@ -216,10 +210,16 @@
|
||||
kill_objective.find_target()
|
||||
add_objective(kill_objective)
|
||||
else
|
||||
var/datum/objective/steal/steal_objective = new
|
||||
steal_objective.owner = owner
|
||||
steal_objective.find_target()
|
||||
add_objective(steal_objective)
|
||||
if(prob(15) && !(locate(/datum/objective/download in owner.objectives)))
|
||||
var/datum/objective/download/download_objective = new
|
||||
download_objective.owner = owner
|
||||
download_objective.gen_amount_goal()
|
||||
add_objective(download_objective)
|
||||
else
|
||||
var/datum/objective/steal/steal_objective = new
|
||||
steal_objective.owner = owner
|
||||
steal_objective.find_target()
|
||||
add_objective(steal_objective)
|
||||
|
||||
/datum/antagonist/traitor/AI/forge_single_objective()
|
||||
.=1
|
||||
|
||||
@@ -205,7 +205,7 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master",
|
||||
/datum/antagonist/devil/proc/regress_blood_lizard()
|
||||
var/mob/living/carbon/true_devil/D = owner.current
|
||||
to_chat(D, "<span class='warning'>Your powers weaken, have more contracts be signed to regain power.</span>")
|
||||
D.oldform.loc = D.loc
|
||||
D.oldform.forceMove(D.drop_location())
|
||||
owner.transfer_to(D.oldform)
|
||||
give_appropriate_spells()
|
||||
qdel(D)
|
||||
@@ -236,7 +236,7 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master",
|
||||
sleep(50)
|
||||
var/mob/living/carbon/true_devil/A = new /mob/living/carbon/true_devil(owner.current.loc)
|
||||
A.faction |= "hell"
|
||||
owner.current.loc = A
|
||||
owner.current.forceMove(A)
|
||||
A.oldform = owner.current
|
||||
owner.transfer_to(A)
|
||||
A.set_name()
|
||||
|
||||
@@ -222,7 +222,7 @@
|
||||
G.fields["name"] = H.real_name
|
||||
G.fields["rank"] = assignment
|
||||
G.fields["age"] = H.age
|
||||
if(config.mutant_races)
|
||||
if(CONFIG_GET(flag/join_with_mutant_race))
|
||||
G.fields["species"] = H.dna.species.name
|
||||
G.fields["fingerprint"] = md5(H.dna.uni_identity)
|
||||
G.fields["p_stat"] = "Active"
|
||||
|
||||
@@ -22,6 +22,6 @@
|
||||
|
||||
/datum/disease/parrot_possession/cure()
|
||||
if(parrot && parrot.loc == affected_mob)
|
||||
parrot.loc = affected_mob.loc
|
||||
parrot.forceMove(affected_mob.drop_location())
|
||||
affected_mob.visible_message("<span class='danger'>[parrot] is violently driven out of [affected_mob]!</span>", "<span class='userdanger'>[parrot] bursts out of your chest!</span>")
|
||||
..()
|
||||
+115
-115
@@ -1,115 +1,115 @@
|
||||
/datum/disease/wizarditis
|
||||
name = "Wizarditis"
|
||||
max_stages = 4
|
||||
spread_text = "Airborne"
|
||||
cure_text = "The Manly Dorf"
|
||||
cures = list("manlydorf")
|
||||
cure_chance = 100
|
||||
agent = "Rincewindus Vulgaris"
|
||||
viable_mobtypes = list(/mob/living/carbon/human)
|
||||
disease_flags = CAN_CARRY|CAN_RESIST|CURABLE
|
||||
permeability_mod = 0.75
|
||||
desc = "Some speculate that this virus is the cause of the Space Wizard Federation's existence. Subjects affected show the signs of mental retardation, yelling obscure sentences or total gibberish. On late stages subjects sometime express the feelings of inner power, and, cite, 'the ability to control the forces of cosmos themselves!' A gulp of strong, manly spirits usually reverts them to normal, humanlike, condition."
|
||||
severity = HARMFUL
|
||||
required_organs = list(/obj/item/bodypart/head)
|
||||
|
||||
/*
|
||||
BIRUZ BENNAR
|
||||
SCYAR NILA - teleport
|
||||
NEC CANTIO - dis techno
|
||||
EI NATH - shocking grasp
|
||||
AULIE OXIN FIERA - knock
|
||||
TARCOL MINTI ZHERI - forcewall
|
||||
STI KALY - blind
|
||||
*/
|
||||
|
||||
/datum/disease/wizarditis/stage_act()
|
||||
..()
|
||||
|
||||
switch(stage)
|
||||
if(2)
|
||||
if(prob(1)&&prob(50))
|
||||
affected_mob.say(pick("You shall not pass!", "Expeliarmus!", "By Merlins beard!", "Feel the power of the Dark Side!"))
|
||||
if(prob(1)&&prob(50))
|
||||
to_chat(affected_mob, "<span class='danger'>You feel [pick("that you don't have enough mana", "that the winds of magic are gone", "an urge to summon familiar")].</span>")
|
||||
|
||||
|
||||
if(3)
|
||||
if(prob(1)&&prob(50))
|
||||
affected_mob.say(pick("NEC CANTIO!","AULIE OXIN FIERA!", "STI KALY!", "TARCOL MINTI ZHERI!"))
|
||||
if(prob(1)&&prob(50))
|
||||
to_chat(affected_mob, "<span class='danger'>You feel [pick("the magic bubbling in your veins","that this location gives you a +1 to INT","an urge to summon familiar")].</span>")
|
||||
|
||||
if(4)
|
||||
|
||||
if(prob(1))
|
||||
affected_mob.say(pick("NEC CANTIO!","AULIE OXIN FIERA!","STI KALY!","EI NATH!"))
|
||||
return
|
||||
if(prob(1)&&prob(50))
|
||||
to_chat(affected_mob, "<span class='danger'>You feel [pick("the tidal wave of raw power building inside","that this location gives you a +2 to INT and +1 to WIS","an urge to teleport")].</span>")
|
||||
spawn_wizard_clothes(50)
|
||||
if(prob(1)&&prob(1))
|
||||
teleport()
|
||||
return
|
||||
|
||||
|
||||
|
||||
/datum/disease/wizarditis/proc/spawn_wizard_clothes(chance = 0)
|
||||
if(ishuman(affected_mob))
|
||||
var/mob/living/carbon/human/H = affected_mob
|
||||
if(prob(chance))
|
||||
if(!istype(H.head, /obj/item/clothing/head/wizard))
|
||||
if(!H.dropItemToGround(H.head))
|
||||
qdel(H.head)
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/head/wizard(H), slot_head)
|
||||
return
|
||||
if(prob(chance))
|
||||
if(!istype(H.wear_suit, /obj/item/clothing/suit/wizrobe))
|
||||
if(!H.dropItemToGround(H.wear_suit))
|
||||
qdel(H.wear_suit)
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe(H), slot_wear_suit)
|
||||
return
|
||||
if(prob(chance))
|
||||
if(!istype(H.shoes, /obj/item/clothing/shoes/sandal/magic))
|
||||
if(!H.dropItemToGround(H.shoes))
|
||||
qdel(H.shoes)
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal/magic(H), slot_shoes)
|
||||
return
|
||||
else
|
||||
var/mob/living/carbon/H = affected_mob
|
||||
if(prob(chance))
|
||||
var/obj/item/staff/S = new(H)
|
||||
if(!H.put_in_hands(S))
|
||||
qdel(S)
|
||||
|
||||
|
||||
/datum/disease/wizarditis/proc/teleport()
|
||||
var/list/theareas = get_areas_in_range(80, affected_mob)
|
||||
for(var/area/space/S in theareas)
|
||||
theareas -= S
|
||||
|
||||
if(!theareas||!theareas.len)
|
||||
return
|
||||
|
||||
var/area/thearea = pick(theareas)
|
||||
|
||||
var/list/L = list()
|
||||
for(var/turf/T in get_area_turfs(thearea.type))
|
||||
if(T.z != affected_mob.z) continue
|
||||
if(T.name == "space") continue
|
||||
if(!T.density)
|
||||
var/clear = 1
|
||||
for(var/obj/O in T)
|
||||
if(O.density)
|
||||
clear = 0
|
||||
break
|
||||
if(clear)
|
||||
L+=T
|
||||
|
||||
if(!L)
|
||||
return
|
||||
|
||||
affected_mob.say("SCYAR NILA [uppertext(thearea.name)]!")
|
||||
affected_mob.loc = pick(L)
|
||||
|
||||
return
|
||||
/datum/disease/wizarditis
|
||||
name = "Wizarditis"
|
||||
max_stages = 4
|
||||
spread_text = "Airborne"
|
||||
cure_text = "The Manly Dorf"
|
||||
cures = list("manlydorf")
|
||||
cure_chance = 100
|
||||
agent = "Rincewindus Vulgaris"
|
||||
viable_mobtypes = list(/mob/living/carbon/human)
|
||||
disease_flags = CAN_CARRY|CAN_RESIST|CURABLE
|
||||
permeability_mod = 0.75
|
||||
desc = "Some speculate that this virus is the cause of the Space Wizard Federation's existence. Subjects affected show the signs of mental retardation, yelling obscure sentences or total gibberish. On late stages subjects sometime express the feelings of inner power, and, cite, 'the ability to control the forces of cosmos themselves!' A gulp of strong, manly spirits usually reverts them to normal, humanlike, condition."
|
||||
severity = HARMFUL
|
||||
required_organs = list(/obj/item/bodypart/head)
|
||||
|
||||
/*
|
||||
BIRUZ BENNAR
|
||||
SCYAR NILA - teleport
|
||||
NEC CANTIO - dis techno
|
||||
EI NATH - shocking grasp
|
||||
AULIE OXIN FIERA - knock
|
||||
TARCOL MINTI ZHERI - forcewall
|
||||
STI KALY - blind
|
||||
*/
|
||||
|
||||
/datum/disease/wizarditis/stage_act()
|
||||
..()
|
||||
|
||||
switch(stage)
|
||||
if(2)
|
||||
if(prob(1)&&prob(50))
|
||||
affected_mob.say(pick("You shall not pass!", "Expeliarmus!", "By Merlins beard!", "Feel the power of the Dark Side!"))
|
||||
if(prob(1)&&prob(50))
|
||||
to_chat(affected_mob, "<span class='danger'>You feel [pick("that you don't have enough mana", "that the winds of magic are gone", "an urge to summon familiar")].</span>")
|
||||
|
||||
|
||||
if(3)
|
||||
if(prob(1)&&prob(50))
|
||||
affected_mob.say(pick("NEC CANTIO!","AULIE OXIN FIERA!", "STI KALY!", "TARCOL MINTI ZHERI!"))
|
||||
if(prob(1)&&prob(50))
|
||||
to_chat(affected_mob, "<span class='danger'>You feel [pick("the magic bubbling in your veins","that this location gives you a +1 to INT","an urge to summon familiar")].</span>")
|
||||
|
||||
if(4)
|
||||
|
||||
if(prob(1))
|
||||
affected_mob.say(pick("NEC CANTIO!","AULIE OXIN FIERA!","STI KALY!","EI NATH!"))
|
||||
return
|
||||
if(prob(1)&&prob(50))
|
||||
to_chat(affected_mob, "<span class='danger'>You feel [pick("the tidal wave of raw power building inside","that this location gives you a +2 to INT and +1 to WIS","an urge to teleport")].</span>")
|
||||
spawn_wizard_clothes(50)
|
||||
if(prob(1)&&prob(1))
|
||||
teleport()
|
||||
return
|
||||
|
||||
|
||||
|
||||
/datum/disease/wizarditis/proc/spawn_wizard_clothes(chance = 0)
|
||||
if(ishuman(affected_mob))
|
||||
var/mob/living/carbon/human/H = affected_mob
|
||||
if(prob(chance))
|
||||
if(!istype(H.head, /obj/item/clothing/head/wizard))
|
||||
if(!H.dropItemToGround(H.head))
|
||||
qdel(H.head)
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/head/wizard(H), slot_head)
|
||||
return
|
||||
if(prob(chance))
|
||||
if(!istype(H.wear_suit, /obj/item/clothing/suit/wizrobe))
|
||||
if(!H.dropItemToGround(H.wear_suit))
|
||||
qdel(H.wear_suit)
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe(H), slot_wear_suit)
|
||||
return
|
||||
if(prob(chance))
|
||||
if(!istype(H.shoes, /obj/item/clothing/shoes/sandal/magic))
|
||||
if(!H.dropItemToGround(H.shoes))
|
||||
qdel(H.shoes)
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal/magic(H), slot_shoes)
|
||||
return
|
||||
else
|
||||
var/mob/living/carbon/H = affected_mob
|
||||
if(prob(chance))
|
||||
var/obj/item/staff/S = new(H)
|
||||
if(!H.put_in_hands(S))
|
||||
qdel(S)
|
||||
|
||||
|
||||
/datum/disease/wizarditis/proc/teleport()
|
||||
var/list/theareas = get_areas_in_range(80, affected_mob)
|
||||
for(var/area/space/S in theareas)
|
||||
theareas -= S
|
||||
|
||||
if(!theareas||!theareas.len)
|
||||
return
|
||||
|
||||
var/area/thearea = pick(theareas)
|
||||
|
||||
var/list/L = list()
|
||||
for(var/turf/T in get_area_turfs(thearea.type))
|
||||
if(T.z != affected_mob.z) continue
|
||||
if(T.name == "space") continue
|
||||
if(!T.density)
|
||||
var/clear = 1
|
||||
for(var/obj/O in T)
|
||||
if(O.density)
|
||||
clear = 0
|
||||
break
|
||||
if(clear)
|
||||
L+=T
|
||||
|
||||
if(!L)
|
||||
return
|
||||
|
||||
affected_mob.say("SCYAR NILA [uppertext(thearea.name)]!")
|
||||
affected_mob.forceMove(pick(L))
|
||||
|
||||
return
|
||||
|
||||
+393
-401
@@ -1,401 +1,393 @@
|
||||
|
||||
/////////////////////////// DNA DATUM
|
||||
/datum/dna
|
||||
var/unique_enzymes
|
||||
var/struc_enzymes
|
||||
var/uni_identity
|
||||
var/blood_type
|
||||
var/datum/species/species = new /datum/species/human() //The type of mutant race the player is if applicable (i.e. potato-man)
|
||||
var/list/features = list("FFF") //first value is mutant color
|
||||
var/real_name //Stores the real name of the person who originally got this dna datum. Used primarely for changelings,
|
||||
var/list/mutations = list() //All mutations are from now on here
|
||||
var/list/temporary_mutations = list() //Timers for temporary mutations
|
||||
var/list/previous = list() //For temporary name/ui/ue/blood_type modifications
|
||||
var/mob/living/holder
|
||||
|
||||
/datum/dna/New(mob/living/new_holder)
|
||||
if(new_holder)
|
||||
holder = new_holder
|
||||
|
||||
/datum/dna/proc/transfer_identity(mob/living/carbon/destination, transfer_SE = 0)
|
||||
if(!istype(destination))
|
||||
return
|
||||
destination.dna.unique_enzymes = unique_enzymes
|
||||
destination.dna.uni_identity = uni_identity
|
||||
destination.dna.blood_type = blood_type
|
||||
destination.set_species(species.type, icon_update=0)
|
||||
destination.dna.features = features.Copy()
|
||||
destination.dna.real_name = real_name
|
||||
destination.dna.temporary_mutations = temporary_mutations.Copy()
|
||||
if(transfer_SE)
|
||||
destination.dna.struc_enzymes = struc_enzymes
|
||||
if(ishuman(destination))
|
||||
var/mob/living/carbon/human/H = destination
|
||||
H.give_genitals(TRUE)//This gives the body the genitals of this DNA. Used for any transformations based on DNA
|
||||
destination.flavor_text = destination.dna.features["flavor_text"] //Update the flavor_text to use new dna text
|
||||
|
||||
/datum/dna/proc/copy_dna(datum/dna/new_dna)
|
||||
new_dna.unique_enzymes = unique_enzymes
|
||||
new_dna.struc_enzymes = struc_enzymes
|
||||
new_dna.uni_identity = uni_identity
|
||||
new_dna.blood_type = blood_type
|
||||
new_dna.features = features.Copy()
|
||||
new_dna.species = new species.type
|
||||
new_dna.real_name = real_name
|
||||
new_dna.mutations = mutations.Copy()
|
||||
|
||||
/datum/dna/proc/add_mutation(mutation_name)
|
||||
var/datum/mutation/human/HM = GLOB.mutations_list[mutation_name]
|
||||
HM.on_acquiring(holder)
|
||||
|
||||
/datum/dna/proc/remove_mutation(mutation_name)
|
||||
var/datum/mutation/human/HM = GLOB.mutations_list[mutation_name]
|
||||
HM.on_losing(holder)
|
||||
|
||||
/datum/dna/proc/check_mutation(mutation_name)
|
||||
var/datum/mutation/human/HM = GLOB.mutations_list[mutation_name]
|
||||
return mutations.Find(HM)
|
||||
|
||||
/datum/dna/proc/remove_all_mutations()
|
||||
remove_mutation_group(mutations)
|
||||
|
||||
/datum/dna/proc/remove_mutation_group(list/group)
|
||||
if(!group)
|
||||
return
|
||||
for(var/datum/mutation/human/HM in group)
|
||||
HM.force_lose(holder)
|
||||
|
||||
/datum/dna/proc/generate_uni_identity()
|
||||
. = ""
|
||||
var/list/L = new /list(DNA_UNI_IDENTITY_BLOCKS)
|
||||
|
||||
L[DNA_GENDER_BLOCK] = construct_block((holder.gender!=MALE)+1, 2)
|
||||
if(ishuman(holder))
|
||||
var/mob/living/carbon/human/H = holder
|
||||
if(!GLOB.hair_styles_list.len)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/hair,GLOB.hair_styles_list, GLOB.hair_styles_male_list, GLOB.hair_styles_female_list)
|
||||
L[DNA_HAIR_STYLE_BLOCK] = construct_block(GLOB.hair_styles_list.Find(H.hair_style), GLOB.hair_styles_list.len)
|
||||
L[DNA_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.hair_color)
|
||||
if(!GLOB.facial_hair_styles_list.len)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/facial_hair, GLOB.facial_hair_styles_list, GLOB.facial_hair_styles_male_list, GLOB.facial_hair_styles_female_list)
|
||||
L[DNA_FACIAL_HAIR_STYLE_BLOCK] = construct_block(GLOB.facial_hair_styles_list.Find(H.facial_hair_style), GLOB.facial_hair_styles_list.len)
|
||||
L[DNA_FACIAL_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.facial_hair_color)
|
||||
L[DNA_SKIN_TONE_BLOCK] = construct_block(GLOB.skin_tones.Find(H.skin_tone), GLOB.skin_tones.len)
|
||||
L[DNA_EYE_COLOR_BLOCK] = sanitize_hexcolor(H.eye_color)
|
||||
|
||||
for(var/i=1, i<=DNA_UNI_IDENTITY_BLOCKS, i++)
|
||||
if(L[i])
|
||||
. += L[i]
|
||||
else
|
||||
. += random_string(DNA_BLOCK_SIZE,GLOB.hex_characters)
|
||||
return .
|
||||
|
||||
/datum/dna/proc/generate_struc_enzymes()
|
||||
var/list/sorting = new /list(DNA_STRUC_ENZYMES_BLOCKS)
|
||||
var/result = ""
|
||||
for(var/datum/mutation/human/A in GLOB.good_mutations + GLOB.bad_mutations + GLOB.not_good_mutations)
|
||||
if(A.name == RACEMUT && ismonkey(holder))
|
||||
sorting[A.dna_block] = num2hex(A.lowest_value + rand(0, 256 * 6), DNA_BLOCK_SIZE)
|
||||
mutations |= A
|
||||
else
|
||||
sorting[A.dna_block] = random_string(DNA_BLOCK_SIZE, list("0","1","2","3","4","5","6"))
|
||||
|
||||
for(var/B in sorting)
|
||||
result += B
|
||||
return result
|
||||
|
||||
/datum/dna/proc/generate_unique_enzymes()
|
||||
. = ""
|
||||
if(istype(holder))
|
||||
real_name = holder.real_name
|
||||
. += md5(holder.real_name)
|
||||
else
|
||||
. += random_string(DNA_UNIQUE_ENZYMES_LEN, GLOB.hex_characters)
|
||||
return .
|
||||
|
||||
/datum/dna/proc/update_ui_block(blocknumber)
|
||||
if(!blocknumber || !ishuman(holder))
|
||||
return
|
||||
var/mob/living/carbon/human/H = holder
|
||||
switch(blocknumber)
|
||||
if(DNA_HAIR_COLOR_BLOCK)
|
||||
setblock(uni_identity, blocknumber, sanitize_hexcolor(H.hair_color))
|
||||
if(DNA_FACIAL_HAIR_COLOR_BLOCK)
|
||||
setblock(uni_identity, blocknumber, sanitize_hexcolor(H.facial_hair_color))
|
||||
if(DNA_SKIN_TONE_BLOCK)
|
||||
setblock(uni_identity, blocknumber, construct_block(GLOB.skin_tones.Find(H.skin_tone), GLOB.skin_tones.len))
|
||||
if(DNA_EYE_COLOR_BLOCK)
|
||||
setblock(uni_identity, blocknumber, sanitize_hexcolor(H.eye_color))
|
||||
if(DNA_GENDER_BLOCK)
|
||||
setblock(uni_identity, blocknumber, construct_block((H.gender!=MALE)+1, 2))
|
||||
if(DNA_FACIAL_HAIR_STYLE_BLOCK)
|
||||
setblock(uni_identity, blocknumber, construct_block(GLOB.facial_hair_styles_list.Find(H.facial_hair_style), GLOB.facial_hair_styles_list.len))
|
||||
if(DNA_HAIR_STYLE_BLOCK)
|
||||
setblock(uni_identity, blocknumber, construct_block(GLOB.hair_styles_list.Find(H.hair_style), GLOB.hair_styles_list.len))
|
||||
|
||||
/datum/dna/proc/mutations_say_mods(message)
|
||||
if(message)
|
||||
for(var/datum/mutation/human/M in mutations)
|
||||
message = M.say_mod(message)
|
||||
return message
|
||||
|
||||
/datum/dna/proc/mutations_get_spans()
|
||||
var/list/spans = list()
|
||||
for(var/datum/mutation/human/M in mutations)
|
||||
spans |= M.get_spans()
|
||||
return spans
|
||||
|
||||
/datum/dna/proc/species_get_spans()
|
||||
var/list/spans = list()
|
||||
if(species)
|
||||
spans |= species.get_spans()
|
||||
return spans
|
||||
|
||||
|
||||
/datum/dna/proc/is_same_as(datum/dna/D)
|
||||
if(uni_identity == D.uni_identity && struc_enzymes == D.struc_enzymes && real_name == D.real_name)
|
||||
if(species.type == D.species.type && features == D.features && blood_type == D.blood_type)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
//used to update dna UI, UE, and dna.real_name.
|
||||
/datum/dna/proc/update_dna_identity()
|
||||
uni_identity = generate_uni_identity()
|
||||
unique_enzymes = generate_unique_enzymes()
|
||||
|
||||
/datum/dna/proc/initialize_dna(newblood_type)
|
||||
if(newblood_type)
|
||||
blood_type = newblood_type
|
||||
unique_enzymes = generate_unique_enzymes()
|
||||
uni_identity = generate_uni_identity()
|
||||
struc_enzymes = generate_struc_enzymes()
|
||||
features = random_features()
|
||||
|
||||
|
||||
/datum/dna/stored //subtype used by brain mob's stored_dna
|
||||
|
||||
/datum/dna/stored/add_mutation(mutation_name) //no mutation changes on stored dna.
|
||||
return
|
||||
|
||||
/datum/dna/stored/remove_mutation(mutation_name)
|
||||
return
|
||||
|
||||
/datum/dna/stored/check_mutation(mutation_name)
|
||||
return
|
||||
|
||||
/datum/dna/stored/remove_all_mutations()
|
||||
return
|
||||
|
||||
/datum/dna/stored/remove_mutation_group(list/group)
|
||||
return
|
||||
|
||||
/////////////////////////// DNA MOB-PROCS //////////////////////
|
||||
|
||||
/mob/proc/set_species(datum/species/mrace, icon_update = 1)
|
||||
return
|
||||
|
||||
/mob/living/brain/set_species(datum/species/mrace, icon_update = 1)
|
||||
if(mrace)
|
||||
if(ispath(mrace))
|
||||
stored_dna.species = new mrace()
|
||||
else
|
||||
stored_dna.species = mrace //not calling any species update procs since we're a brain, not a monkey/human
|
||||
|
||||
|
||||
/mob/living/carbon/set_species(datum/species/mrace, icon_update = 1)
|
||||
if(mrace && has_dna())
|
||||
dna.species.on_species_loss(src)
|
||||
var/old_species = dna.species
|
||||
if(ispath(mrace))
|
||||
dna.species = new mrace()
|
||||
else
|
||||
dna.species = mrace
|
||||
dna.species.on_species_gain(src, old_species)
|
||||
|
||||
/mob/living/carbon/human/set_species(datum/species/mrace, icon_update = 1)
|
||||
..()
|
||||
if(icon_update)
|
||||
update_body()
|
||||
update_hair()
|
||||
update_body_parts()
|
||||
update_mutations_overlay()// no lizard with human hulk overlay please.
|
||||
|
||||
|
||||
/mob/proc/has_dna()
|
||||
return
|
||||
|
||||
/mob/living/carbon/has_dna()
|
||||
return dna
|
||||
|
||||
|
||||
/mob/living/carbon/human/proc/hardset_dna(ui, se, newreal_name, newblood_type, datum/species/mrace, newfeatures)
|
||||
|
||||
if(newfeatures)
|
||||
dna.features = newfeatures
|
||||
flavor_text = dna.features["flavor_text"] //Update the flavor_text to use new dna text
|
||||
|
||||
if(mrace)
|
||||
var/datum/species/newrace = new mrace.type
|
||||
newrace.copy_properties_from(mrace)
|
||||
set_species(newrace, icon_update=0)
|
||||
|
||||
if(newreal_name)
|
||||
real_name = newreal_name
|
||||
dna.generate_unique_enzymes()
|
||||
|
||||
if(newblood_type)
|
||||
dna.blood_type = newblood_type
|
||||
|
||||
if(ui)
|
||||
dna.uni_identity = ui
|
||||
updateappearance(icon_update=0)
|
||||
|
||||
if(se)
|
||||
dna.struc_enzymes = se
|
||||
domutcheck()
|
||||
|
||||
give_genitals(TRUE)//Give all genitalia that DNA says you should have, remove any pre-existing ones as this is a hardset!
|
||||
|
||||
if(mrace || newfeatures || ui)
|
||||
update_body()
|
||||
update_hair()
|
||||
update_body_parts()
|
||||
update_mutations_overlay()
|
||||
|
||||
|
||||
/mob/living/carbon/proc/create_dna()
|
||||
dna = new /datum/dna(src)
|
||||
if(!dna.species)
|
||||
var/rando_race = pick(config.roundstart_races)
|
||||
dna.species = new rando_race()
|
||||
|
||||
//proc used to update the mob's appearance after its dna UI has been changed
|
||||
/mob/living/carbon/proc/updateappearance(icon_update=1, mutcolor_update=0, mutations_overlay_update=0)
|
||||
if(!has_dna())
|
||||
return
|
||||
gender = (deconstruct_block(getblock(dna.uni_identity, DNA_GENDER_BLOCK), 2)-1) ? FEMALE : MALE
|
||||
|
||||
/mob/living/carbon/human/updateappearance(icon_update=1, mutcolor_update=0, mutations_overlay_update=0)
|
||||
..()
|
||||
var/structure = dna.uni_identity
|
||||
hair_color = sanitize_hexcolor(getblock(structure, DNA_HAIR_COLOR_BLOCK))
|
||||
facial_hair_color = sanitize_hexcolor(getblock(structure, DNA_FACIAL_HAIR_COLOR_BLOCK))
|
||||
skin_tone = GLOB.skin_tones[deconstruct_block(getblock(structure, DNA_SKIN_TONE_BLOCK), GLOB.skin_tones.len)]
|
||||
eye_color = sanitize_hexcolor(getblock(structure, DNA_EYE_COLOR_BLOCK))
|
||||
facial_hair_style = GLOB.facial_hair_styles_list[deconstruct_block(getblock(structure, DNA_FACIAL_HAIR_STYLE_BLOCK), GLOB.facial_hair_styles_list.len)]
|
||||
hair_style = GLOB.hair_styles_list[deconstruct_block(getblock(structure, DNA_HAIR_STYLE_BLOCK), GLOB.hair_styles_list.len)]
|
||||
if(icon_update)
|
||||
update_body()
|
||||
update_hair()
|
||||
if(mutcolor_update)
|
||||
update_body_parts()
|
||||
if(mutations_overlay_update)
|
||||
update_mutations_overlay()
|
||||
|
||||
|
||||
/mob/proc/domutcheck()
|
||||
return
|
||||
|
||||
/mob/living/carbon/domutcheck(force_powers=0) //Set force_powers to 1 to bypass the power chance
|
||||
if(!has_dna())
|
||||
return
|
||||
|
||||
for(var/datum/mutation/human/A in GLOB.good_mutations | GLOB.bad_mutations | GLOB.not_good_mutations)
|
||||
if(ismob(A.check_block(src, force_powers)))
|
||||
return //we got monkeyized/humanized, this mob will be deleted, no need to continue.
|
||||
|
||||
update_mutations_overlay()
|
||||
|
||||
|
||||
|
||||
/////////////////////////// DNA HELPER-PROCS //////////////////////////////
|
||||
/proc/getleftblocks(input,blocknumber,blocksize)
|
||||
if(blocknumber > 1)
|
||||
return copytext(input,1,((blocksize*blocknumber)-(blocksize-1)))
|
||||
|
||||
/proc/getrightblocks(input,blocknumber,blocksize)
|
||||
if(blocknumber < (length(input)/blocksize))
|
||||
return copytext(input,blocksize*blocknumber+1,length(input)+1)
|
||||
|
||||
/proc/getblock(input, blocknumber, blocksize=DNA_BLOCK_SIZE)
|
||||
return copytext(input, blocksize*(blocknumber-1)+1, (blocksize*blocknumber)+1)
|
||||
|
||||
/proc/setblock(istring, blocknumber, replacement, blocksize=DNA_BLOCK_SIZE)
|
||||
if(!istring || !blocknumber || !replacement || !blocksize)
|
||||
return 0
|
||||
return getleftblocks(istring, blocknumber, blocksize) + replacement + getrightblocks(istring, blocknumber, blocksize)
|
||||
|
||||
/mob/living/carbon/proc/randmut(list/candidates, difficulty = 2)
|
||||
if(!has_dna())
|
||||
return
|
||||
var/datum/mutation/human/num = pick(candidates)
|
||||
. = num.force_give(src)
|
||||
|
||||
/mob/living/carbon/proc/randmutb()
|
||||
if(!has_dna())
|
||||
return
|
||||
var/datum/mutation/human/HM = pick((GLOB.bad_mutations | GLOB.not_good_mutations) - GLOB.mutations_list[RACEMUT])
|
||||
. = HM.force_give(src)
|
||||
|
||||
/mob/living/carbon/proc/randmutg()
|
||||
if(!has_dna())
|
||||
return
|
||||
var/datum/mutation/human/HM = pick(GLOB.good_mutations)
|
||||
. = HM.force_give(src)
|
||||
|
||||
/mob/living/carbon/proc/randmutvg()
|
||||
if(!has_dna())
|
||||
return
|
||||
var/datum/mutation/human/HM = pick((GLOB.good_mutations) - GLOB.mutations_list[HULK] - GLOB.mutations_list[DWARFISM])
|
||||
. = HM.force_give(src)
|
||||
|
||||
/mob/living/carbon/proc/randmuti()
|
||||
if(!has_dna())
|
||||
return
|
||||
var/num = rand(1, DNA_UNI_IDENTITY_BLOCKS)
|
||||
var/newdna = setblock(dna.uni_identity, num, random_string(DNA_BLOCK_SIZE, GLOB.hex_characters))
|
||||
dna.uni_identity = newdna
|
||||
updateappearance(mutations_overlay_update=1)
|
||||
|
||||
/mob/living/carbon/proc/clean_dna()
|
||||
if(!has_dna())
|
||||
return
|
||||
dna.remove_all_mutations()
|
||||
|
||||
/mob/living/carbon/proc/clean_randmut(list/candidates, difficulty = 2)
|
||||
clean_dna()
|
||||
randmut(candidates, difficulty)
|
||||
|
||||
/proc/scramble_dna(mob/living/carbon/M, ui=FALSE, se=FALSE, probability)
|
||||
if(!M.has_dna())
|
||||
return 0
|
||||
if(se)
|
||||
for(var/i=1, i<=DNA_STRUC_ENZYMES_BLOCKS, i++)
|
||||
if(prob(probability))
|
||||
M.dna.struc_enzymes = setblock(M.dna.struc_enzymes, i, random_string(DNA_BLOCK_SIZE, GLOB.hex_characters))
|
||||
M.domutcheck()
|
||||
if(ui)
|
||||
for(var/i=1, i<=DNA_UNI_IDENTITY_BLOCKS, i++)
|
||||
if(prob(probability))
|
||||
M.dna.uni_identity = setblock(M.dna.uni_identity, i, random_string(DNA_BLOCK_SIZE, GLOB.hex_characters))
|
||||
M.updateappearance(mutations_overlay_update=1)
|
||||
return 1
|
||||
|
||||
//value in range 1 to values. values must be greater than 0
|
||||
//all arguments assumed to be positive integers
|
||||
/proc/construct_block(value, values, blocksize=DNA_BLOCK_SIZE)
|
||||
var/width = round((16**blocksize)/values)
|
||||
if(value < 1)
|
||||
value = 1
|
||||
value = (value * width) - rand(1,width)
|
||||
return num2hex(value, blocksize)
|
||||
|
||||
//value is hex
|
||||
/proc/deconstruct_block(value, values, blocksize=DNA_BLOCK_SIZE)
|
||||
var/width = round((16**blocksize)/values)
|
||||
value = round(hex2num(value) / width) + 1
|
||||
if(value > values)
|
||||
value = values
|
||||
return value
|
||||
|
||||
/////////////////////////// DNA HELPER-PROCS
|
||||
/////////////////////////// DNA DATUM
|
||||
/datum/dna
|
||||
var/unique_enzymes
|
||||
var/struc_enzymes
|
||||
var/uni_identity
|
||||
var/blood_type
|
||||
var/datum/species/species = new /datum/species/human() //The type of mutant race the player is if applicable (i.e. potato-man)
|
||||
var/list/features = list("FFF") //first value is mutant color
|
||||
var/real_name //Stores the real name of the person who originally got this dna datum. Used primarely for changelings,
|
||||
var/list/mutations = list() //All mutations are from now on here
|
||||
var/list/temporary_mutations = list() //Timers for temporary mutations
|
||||
var/list/previous = list() //For temporary name/ui/ue/blood_type modifications
|
||||
var/mob/living/holder
|
||||
|
||||
/datum/dna/New(mob/living/new_holder)
|
||||
if(new_holder)
|
||||
holder = new_holder
|
||||
|
||||
/datum/dna/proc/transfer_identity(mob/living/carbon/destination, transfer_SE = 0)
|
||||
if(!istype(destination))
|
||||
return
|
||||
destination.dna.unique_enzymes = unique_enzymes
|
||||
destination.dna.uni_identity = uni_identity
|
||||
destination.dna.blood_type = blood_type
|
||||
destination.set_species(species.type, icon_update=0)
|
||||
destination.dna.features = features.Copy()
|
||||
destination.dna.real_name = real_name
|
||||
destination.dna.temporary_mutations = temporary_mutations.Copy()
|
||||
if(transfer_SE)
|
||||
destination.dna.struc_enzymes = struc_enzymes
|
||||
|
||||
/datum/dna/proc/copy_dna(datum/dna/new_dna)
|
||||
new_dna.unique_enzymes = unique_enzymes
|
||||
new_dna.struc_enzymes = struc_enzymes
|
||||
new_dna.uni_identity = uni_identity
|
||||
new_dna.blood_type = blood_type
|
||||
new_dna.features = features.Copy()
|
||||
new_dna.species = new species.type
|
||||
new_dna.real_name = real_name
|
||||
new_dna.mutations = mutations.Copy()
|
||||
|
||||
/datum/dna/proc/add_mutation(mutation_name)
|
||||
var/datum/mutation/human/HM = GLOB.mutations_list[mutation_name]
|
||||
HM.on_acquiring(holder)
|
||||
|
||||
/datum/dna/proc/remove_mutation(mutation_name)
|
||||
var/datum/mutation/human/HM = GLOB.mutations_list[mutation_name]
|
||||
HM.on_losing(holder)
|
||||
|
||||
/datum/dna/proc/check_mutation(mutation_name)
|
||||
var/datum/mutation/human/HM = GLOB.mutations_list[mutation_name]
|
||||
return mutations.Find(HM)
|
||||
|
||||
/datum/dna/proc/remove_all_mutations()
|
||||
remove_mutation_group(mutations)
|
||||
|
||||
/datum/dna/proc/remove_mutation_group(list/group)
|
||||
if(!group)
|
||||
return
|
||||
for(var/datum/mutation/human/HM in group)
|
||||
HM.force_lose(holder)
|
||||
|
||||
/datum/dna/proc/generate_uni_identity()
|
||||
. = ""
|
||||
var/list/L = new /list(DNA_UNI_IDENTITY_BLOCKS)
|
||||
|
||||
L[DNA_GENDER_BLOCK] = construct_block((holder.gender!=MALE)+1, 2)
|
||||
if(ishuman(holder))
|
||||
var/mob/living/carbon/human/H = holder
|
||||
if(!GLOB.hair_styles_list.len)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/hair,GLOB.hair_styles_list, GLOB.hair_styles_male_list, GLOB.hair_styles_female_list)
|
||||
L[DNA_HAIR_STYLE_BLOCK] = construct_block(GLOB.hair_styles_list.Find(H.hair_style), GLOB.hair_styles_list.len)
|
||||
L[DNA_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.hair_color)
|
||||
if(!GLOB.facial_hair_styles_list.len)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/facial_hair, GLOB.facial_hair_styles_list, GLOB.facial_hair_styles_male_list, GLOB.facial_hair_styles_female_list)
|
||||
L[DNA_FACIAL_HAIR_STYLE_BLOCK] = construct_block(GLOB.facial_hair_styles_list.Find(H.facial_hair_style), GLOB.facial_hair_styles_list.len)
|
||||
L[DNA_FACIAL_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.facial_hair_color)
|
||||
L[DNA_SKIN_TONE_BLOCK] = construct_block(GLOB.skin_tones.Find(H.skin_tone), GLOB.skin_tones.len)
|
||||
L[DNA_EYE_COLOR_BLOCK] = sanitize_hexcolor(H.eye_color)
|
||||
|
||||
for(var/i=1, i<=DNA_UNI_IDENTITY_BLOCKS, i++)
|
||||
if(L[i])
|
||||
. += L[i]
|
||||
else
|
||||
. += random_string(DNA_BLOCK_SIZE,GLOB.hex_characters)
|
||||
return .
|
||||
|
||||
/datum/dna/proc/generate_struc_enzymes()
|
||||
var/list/sorting = new /list(DNA_STRUC_ENZYMES_BLOCKS)
|
||||
var/result = ""
|
||||
for(var/datum/mutation/human/A in GLOB.good_mutations + GLOB.bad_mutations + GLOB.not_good_mutations)
|
||||
if(A.name == RACEMUT && ismonkey(holder))
|
||||
sorting[A.dna_block] = num2hex(A.lowest_value + rand(0, 256 * 6), DNA_BLOCK_SIZE)
|
||||
mutations |= A
|
||||
else
|
||||
sorting[A.dna_block] = random_string(DNA_BLOCK_SIZE, list("0","1","2","3","4","5","6"))
|
||||
|
||||
for(var/B in sorting)
|
||||
result += B
|
||||
return result
|
||||
|
||||
/datum/dna/proc/generate_unique_enzymes()
|
||||
. = ""
|
||||
if(istype(holder))
|
||||
real_name = holder.real_name
|
||||
. += md5(holder.real_name)
|
||||
else
|
||||
. += random_string(DNA_UNIQUE_ENZYMES_LEN, GLOB.hex_characters)
|
||||
return .
|
||||
|
||||
/datum/dna/proc/update_ui_block(blocknumber)
|
||||
if(!blocknumber || !ishuman(holder))
|
||||
return
|
||||
var/mob/living/carbon/human/H = holder
|
||||
switch(blocknumber)
|
||||
if(DNA_HAIR_COLOR_BLOCK)
|
||||
setblock(uni_identity, blocknumber, sanitize_hexcolor(H.hair_color))
|
||||
if(DNA_FACIAL_HAIR_COLOR_BLOCK)
|
||||
setblock(uni_identity, blocknumber, sanitize_hexcolor(H.facial_hair_color))
|
||||
if(DNA_SKIN_TONE_BLOCK)
|
||||
setblock(uni_identity, blocknumber, construct_block(GLOB.skin_tones.Find(H.skin_tone), GLOB.skin_tones.len))
|
||||
if(DNA_EYE_COLOR_BLOCK)
|
||||
setblock(uni_identity, blocknumber, sanitize_hexcolor(H.eye_color))
|
||||
if(DNA_GENDER_BLOCK)
|
||||
setblock(uni_identity, blocknumber, construct_block((H.gender!=MALE)+1, 2))
|
||||
if(DNA_FACIAL_HAIR_STYLE_BLOCK)
|
||||
setblock(uni_identity, blocknumber, construct_block(GLOB.facial_hair_styles_list.Find(H.facial_hair_style), GLOB.facial_hair_styles_list.len))
|
||||
if(DNA_HAIR_STYLE_BLOCK)
|
||||
setblock(uni_identity, blocknumber, construct_block(GLOB.hair_styles_list.Find(H.hair_style), GLOB.hair_styles_list.len))
|
||||
|
||||
/datum/dna/proc/mutations_say_mods(message)
|
||||
if(message)
|
||||
for(var/datum/mutation/human/M in mutations)
|
||||
message = M.say_mod(message)
|
||||
return message
|
||||
|
||||
/datum/dna/proc/mutations_get_spans()
|
||||
var/list/spans = list()
|
||||
for(var/datum/mutation/human/M in mutations)
|
||||
spans |= M.get_spans()
|
||||
return spans
|
||||
|
||||
/datum/dna/proc/species_get_spans()
|
||||
var/list/spans = list()
|
||||
if(species)
|
||||
spans |= species.get_spans()
|
||||
return spans
|
||||
|
||||
|
||||
/datum/dna/proc/is_same_as(datum/dna/D)
|
||||
if(uni_identity == D.uni_identity && struc_enzymes == D.struc_enzymes && real_name == D.real_name)
|
||||
if(species.type == D.species.type && features == D.features && blood_type == D.blood_type)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
//used to update dna UI, UE, and dna.real_name.
|
||||
/datum/dna/proc/update_dna_identity()
|
||||
uni_identity = generate_uni_identity()
|
||||
unique_enzymes = generate_unique_enzymes()
|
||||
|
||||
/datum/dna/proc/initialize_dna(newblood_type)
|
||||
if(newblood_type)
|
||||
blood_type = newblood_type
|
||||
unique_enzymes = generate_unique_enzymes()
|
||||
uni_identity = generate_uni_identity()
|
||||
struc_enzymes = generate_struc_enzymes()
|
||||
features = random_features()
|
||||
|
||||
|
||||
/datum/dna/stored //subtype used by brain mob's stored_dna
|
||||
|
||||
/datum/dna/stored/add_mutation(mutation_name) //no mutation changes on stored dna.
|
||||
return
|
||||
|
||||
/datum/dna/stored/remove_mutation(mutation_name)
|
||||
return
|
||||
|
||||
/datum/dna/stored/check_mutation(mutation_name)
|
||||
return
|
||||
|
||||
/datum/dna/stored/remove_all_mutations()
|
||||
return
|
||||
|
||||
/datum/dna/stored/remove_mutation_group(list/group)
|
||||
return
|
||||
|
||||
/////////////////////////// DNA MOB-PROCS //////////////////////
|
||||
|
||||
/mob/proc/set_species(datum/species/mrace, icon_update = 1)
|
||||
return
|
||||
|
||||
/mob/living/brain/set_species(datum/species/mrace, icon_update = 1)
|
||||
if(mrace)
|
||||
if(ispath(mrace))
|
||||
stored_dna.species = new mrace()
|
||||
else
|
||||
stored_dna.species = mrace //not calling any species update procs since we're a brain, not a monkey/human
|
||||
|
||||
|
||||
/mob/living/carbon/set_species(datum/species/mrace, icon_update = 1)
|
||||
if(mrace && has_dna())
|
||||
dna.species.on_species_loss(src)
|
||||
var/old_species = dna.species
|
||||
if(ispath(mrace))
|
||||
dna.species = new mrace()
|
||||
else
|
||||
dna.species = mrace
|
||||
dna.species.on_species_gain(src, old_species)
|
||||
|
||||
/mob/living/carbon/human/set_species(datum/species/mrace, icon_update = 1)
|
||||
..()
|
||||
if(icon_update)
|
||||
update_body()
|
||||
update_hair()
|
||||
update_body_parts()
|
||||
update_mutations_overlay()// no lizard with human hulk overlay please.
|
||||
|
||||
|
||||
/mob/proc/has_dna()
|
||||
return
|
||||
|
||||
/mob/living/carbon/has_dna()
|
||||
return dna
|
||||
|
||||
|
||||
/mob/living/carbon/human/proc/hardset_dna(ui, se, newreal_name, newblood_type, datum/species/mrace, newfeatures)
|
||||
|
||||
if(newfeatures)
|
||||
dna.features = newfeatures
|
||||
|
||||
if(mrace)
|
||||
var/datum/species/newrace = new mrace.type
|
||||
newrace.copy_properties_from(mrace)
|
||||
set_species(newrace, icon_update=0)
|
||||
|
||||
if(newreal_name)
|
||||
real_name = newreal_name
|
||||
dna.generate_unique_enzymes()
|
||||
|
||||
if(newblood_type)
|
||||
dna.blood_type = newblood_type
|
||||
|
||||
if(ui)
|
||||
dna.uni_identity = ui
|
||||
updateappearance(icon_update=0)
|
||||
|
||||
if(se)
|
||||
dna.struc_enzymes = se
|
||||
domutcheck()
|
||||
|
||||
if(mrace || newfeatures || ui)
|
||||
update_body()
|
||||
update_hair()
|
||||
update_body_parts()
|
||||
update_mutations_overlay()
|
||||
|
||||
|
||||
/mob/living/carbon/proc/create_dna()
|
||||
dna = new /datum/dna(src)
|
||||
if(!dna.species)
|
||||
var/rando_race = pick(CONFIG_GET(keyed_flag_list/roundstart_races))
|
||||
dna.species = new rando_race()
|
||||
|
||||
//proc used to update the mob's appearance after its dna UI has been changed
|
||||
/mob/living/carbon/proc/updateappearance(icon_update=1, mutcolor_update=0, mutations_overlay_update=0)
|
||||
if(!has_dna())
|
||||
return
|
||||
gender = (deconstruct_block(getblock(dna.uni_identity, DNA_GENDER_BLOCK), 2)-1) ? FEMALE : MALE
|
||||
|
||||
/mob/living/carbon/human/updateappearance(icon_update=1, mutcolor_update=0, mutations_overlay_update=0)
|
||||
..()
|
||||
var/structure = dna.uni_identity
|
||||
hair_color = sanitize_hexcolor(getblock(structure, DNA_HAIR_COLOR_BLOCK))
|
||||
facial_hair_color = sanitize_hexcolor(getblock(structure, DNA_FACIAL_HAIR_COLOR_BLOCK))
|
||||
skin_tone = GLOB.skin_tones[deconstruct_block(getblock(structure, DNA_SKIN_TONE_BLOCK), GLOB.skin_tones.len)]
|
||||
eye_color = sanitize_hexcolor(getblock(structure, DNA_EYE_COLOR_BLOCK))
|
||||
facial_hair_style = GLOB.facial_hair_styles_list[deconstruct_block(getblock(structure, DNA_FACIAL_HAIR_STYLE_BLOCK), GLOB.facial_hair_styles_list.len)]
|
||||
hair_style = GLOB.hair_styles_list[deconstruct_block(getblock(structure, DNA_HAIR_STYLE_BLOCK), GLOB.hair_styles_list.len)]
|
||||
if(icon_update)
|
||||
update_body()
|
||||
update_hair()
|
||||
if(mutcolor_update)
|
||||
update_body_parts()
|
||||
if(mutations_overlay_update)
|
||||
update_mutations_overlay()
|
||||
|
||||
|
||||
/mob/proc/domutcheck()
|
||||
return
|
||||
|
||||
/mob/living/carbon/domutcheck(force_powers=0) //Set force_powers to 1 to bypass the power chance
|
||||
if(!has_dna())
|
||||
return
|
||||
|
||||
for(var/datum/mutation/human/A in GLOB.good_mutations | GLOB.bad_mutations | GLOB.not_good_mutations)
|
||||
if(ismob(A.check_block(src, force_powers)))
|
||||
return //we got monkeyized/humanized, this mob will be deleted, no need to continue.
|
||||
|
||||
update_mutations_overlay()
|
||||
|
||||
|
||||
|
||||
/////////////////////////// DNA HELPER-PROCS //////////////////////////////
|
||||
/proc/getleftblocks(input,blocknumber,blocksize)
|
||||
if(blocknumber > 1)
|
||||
return copytext(input,1,((blocksize*blocknumber)-(blocksize-1)))
|
||||
|
||||
/proc/getrightblocks(input,blocknumber,blocksize)
|
||||
if(blocknumber < (length(input)/blocksize))
|
||||
return copytext(input,blocksize*blocknumber+1,length(input)+1)
|
||||
|
||||
/proc/getblock(input, blocknumber, blocksize=DNA_BLOCK_SIZE)
|
||||
return copytext(input, blocksize*(blocknumber-1)+1, (blocksize*blocknumber)+1)
|
||||
|
||||
/proc/setblock(istring, blocknumber, replacement, blocksize=DNA_BLOCK_SIZE)
|
||||
if(!istring || !blocknumber || !replacement || !blocksize)
|
||||
return 0
|
||||
return getleftblocks(istring, blocknumber, blocksize) + replacement + getrightblocks(istring, blocknumber, blocksize)
|
||||
|
||||
/mob/living/carbon/proc/randmut(list/candidates, difficulty = 2)
|
||||
if(!has_dna())
|
||||
return
|
||||
var/datum/mutation/human/num = pick(candidates)
|
||||
. = num.force_give(src)
|
||||
|
||||
/mob/living/carbon/proc/randmutb()
|
||||
if(!has_dna())
|
||||
return
|
||||
var/datum/mutation/human/HM = pick((GLOB.bad_mutations | GLOB.not_good_mutations) - GLOB.mutations_list[RACEMUT])
|
||||
. = HM.force_give(src)
|
||||
|
||||
/mob/living/carbon/proc/randmutg()
|
||||
if(!has_dna())
|
||||
return
|
||||
var/datum/mutation/human/HM = pick(GLOB.good_mutations)
|
||||
. = HM.force_give(src)
|
||||
|
||||
/mob/living/carbon/proc/randmutvg()
|
||||
if(!has_dna())
|
||||
return
|
||||
var/datum/mutation/human/HM = pick((GLOB.good_mutations) - GLOB.mutations_list[HULK] - GLOB.mutations_list[DWARFISM])
|
||||
. = HM.force_give(src)
|
||||
|
||||
/mob/living/carbon/proc/randmuti()
|
||||
if(!has_dna())
|
||||
return
|
||||
var/num = rand(1, DNA_UNI_IDENTITY_BLOCKS)
|
||||
var/newdna = setblock(dna.uni_identity, num, random_string(DNA_BLOCK_SIZE, GLOB.hex_characters))
|
||||
dna.uni_identity = newdna
|
||||
updateappearance(mutations_overlay_update=1)
|
||||
|
||||
/mob/living/carbon/proc/clean_dna()
|
||||
if(!has_dna())
|
||||
return
|
||||
dna.remove_all_mutations()
|
||||
|
||||
/mob/living/carbon/proc/clean_randmut(list/candidates, difficulty = 2)
|
||||
clean_dna()
|
||||
randmut(candidates, difficulty)
|
||||
|
||||
/proc/scramble_dna(mob/living/carbon/M, ui=FALSE, se=FALSE, probability)
|
||||
if(!M.has_dna())
|
||||
return 0
|
||||
if(se)
|
||||
for(var/i=1, i<=DNA_STRUC_ENZYMES_BLOCKS, i++)
|
||||
if(prob(probability))
|
||||
M.dna.struc_enzymes = setblock(M.dna.struc_enzymes, i, random_string(DNA_BLOCK_SIZE, GLOB.hex_characters))
|
||||
M.domutcheck()
|
||||
if(ui)
|
||||
for(var/i=1, i<=DNA_UNI_IDENTITY_BLOCKS, i++)
|
||||
if(prob(probability))
|
||||
M.dna.uni_identity = setblock(M.dna.uni_identity, i, random_string(DNA_BLOCK_SIZE, GLOB.hex_characters))
|
||||
M.updateappearance(mutations_overlay_update=1)
|
||||
return 1
|
||||
|
||||
//value in range 1 to values. values must be greater than 0
|
||||
//all arguments assumed to be positive integers
|
||||
/proc/construct_block(value, values, blocksize=DNA_BLOCK_SIZE)
|
||||
var/width = round((16**blocksize)/values)
|
||||
if(value < 1)
|
||||
value = 1
|
||||
value = (value * width) - rand(1,width)
|
||||
return num2hex(value, blocksize)
|
||||
|
||||
//value is hex
|
||||
/proc/deconstruct_block(value, values, blocksize=DNA_BLOCK_SIZE)
|
||||
var/width = round((16**blocksize)/values)
|
||||
value = round(hex2num(value) / width) + 1
|
||||
if(value > values)
|
||||
value = values
|
||||
return value
|
||||
|
||||
/////////////////////////// DNA HELPER-PROCS
|
||||
|
||||
@@ -140,7 +140,7 @@ GLOBAL_LIST_EMPTY(explosions)
|
||||
var/list/exploded_this_tick = list() //open turfs that need to be blocked off while we sleep
|
||||
var/list/affected_turfs = GatherSpiralTurfs(max_range, epicenter)
|
||||
|
||||
var/reactionary = config.reactionary_explosions
|
||||
var/reactionary = CONFIG_GET(flag/reactionary_explosions)
|
||||
var/list/cached_exp_block
|
||||
|
||||
if(reactionary)
|
||||
|
||||
@@ -2,25 +2,10 @@
|
||||
var/originmastercommit
|
||||
var/commit
|
||||
var/list/testmerge = list()
|
||||
var/has_pr_details = FALSE //tgs2 support
|
||||
var/date
|
||||
|
||||
/datum/getrev/New()
|
||||
if(world.RunningService())
|
||||
var/file_name
|
||||
if(ServiceVersion()) //will return null for versions < 3.0.91.0
|
||||
file_name = SERVICE_PR_TEST_JSON_OLD
|
||||
else
|
||||
file_name = SERVICE_PR_TEST_JSON
|
||||
if(fexists(file_name))
|
||||
testmerge = json_decode(file2text(file_name))
|
||||
#ifdef SERVERTOOLS
|
||||
else if(!world.RunningService() && fexists("../prtestjob.lk")) //tgs2 support
|
||||
var/list/tmp = world.file2list("..\\prtestjob.lk")
|
||||
for(var/I in tmp)
|
||||
if(I)
|
||||
testmerge |= I
|
||||
#endif
|
||||
testmerge = SERVER_TOOLS_PR_LIST
|
||||
log_world("Running /tg/ revision:")
|
||||
var/list/logs = world.file2list(".git/logs/HEAD")
|
||||
if(logs)
|
||||
@@ -36,58 +21,24 @@
|
||||
log_world(commit)
|
||||
for(var/line in testmerge)
|
||||
if(line)
|
||||
if(world.RunningService())
|
||||
var/tmcommit = testmerge[line]["commit"]
|
||||
log_world("Test merge active of PR #[line] commit [tmcommit]")
|
||||
SSblackbox.add_details("testmerged_prs","[line]|[tmcommit]")
|
||||
else //tgs2 support
|
||||
log_world("Test merge active of PR #[line]")
|
||||
SSblackbox.add_details("testmerged_prs","[line]")
|
||||
var/tmcommit = testmerge[line]["commit"]
|
||||
log_world("Test merge active of PR #[line] commit [tmcommit]")
|
||||
SSblackbox.add_details("testmerged_prs","[line]|[tmcommit]")
|
||||
log_world("Based off origin/master commit [originmastercommit]")
|
||||
else
|
||||
log_world(originmastercommit)
|
||||
/datum/getrev/proc/DownloadPRDetails()
|
||||
if(!config.githubrepoid)
|
||||
if(testmerge.len)
|
||||
log_world("PR details download failed: No github repo config set")
|
||||
return
|
||||
if(!isnum(text2num(config.githubrepoid)))
|
||||
log_world("PR details download failed: Invalid github repo id: [config.githubrepoid]")
|
||||
return
|
||||
for(var/line in testmerge)
|
||||
if(!isnum(text2num(line)))
|
||||
log_world("PR details download failed: Invalid PR number: [line]")
|
||||
return
|
||||
|
||||
var/url = "https://api.github.com/repositories/[config.githubrepoid]/pulls/[line].json"
|
||||
GLOB.valid_HTTPSGet = TRUE
|
||||
var/json = HTTPSGet(url)
|
||||
if(!json)
|
||||
return
|
||||
|
||||
testmerge[line] = json_decode(json)
|
||||
|
||||
if(!testmerge[line])
|
||||
log_world("PR details download failed: null details returned")
|
||||
return
|
||||
CHECK_TICK
|
||||
log_world("PR details successfully downloaded")
|
||||
has_pr_details = TRUE
|
||||
|
||||
/datum/getrev/proc/GetTestMergeInfo(header = TRUE)
|
||||
if(!testmerge.len)
|
||||
return ""
|
||||
. = header ? "The following pull requests are currently test merged:<br>" : ""
|
||||
for(var/line in testmerge)
|
||||
var/details
|
||||
if(world.RunningService())
|
||||
var/cm = testmerge[line]["commit"]
|
||||
details = ": '" + html_encode(testmerge[line]["title"]) + "' by " + html_encode(testmerge[line]["author"]) + " at commit " + html_encode(copytext(cm, 1, min(length(cm), 7)))
|
||||
else if(has_pr_details) //tgs2 support
|
||||
details = ": '" + html_encode(testmerge[line]["title"]) + "' by " + html_encode(testmerge[line]["user"]["login"])
|
||||
var/cm = testmerge[line]["commit"]
|
||||
var/details = ": '" + html_encode(testmerge[line]["title"]) + "' by " + html_encode(testmerge[line]["author"]) + " at commit " + html_encode(copytext(cm, 1, min(length(cm), 7)))
|
||||
if(details && findtext(details, "\[s\]") && (!usr || !usr.client.holder))
|
||||
continue
|
||||
. += "<a href=\"[config.githuburl]/pull/[line]\">#[line][details]</a><br>"
|
||||
. += "<a href=\"[CONFIG_GET(string/githuburl)]/pull/[line]\">#[line][details]</a><br>"
|
||||
|
||||
/client/verb/showrevinfo()
|
||||
set category = "OOC"
|
||||
@@ -101,44 +52,47 @@
|
||||
to_chat(src, GLOB.revdata.GetTestMergeInfo())
|
||||
prefix = "Based off origin/master commit: "
|
||||
var/pc = GLOB.revdata.originmastercommit
|
||||
to_chat(src, "[prefix]<a href=\"[config.githuburl]/commit/[pc]\">[copytext(pc, 1, min(length(pc), 7))]</a>")
|
||||
to_chat(src, "[prefix]<a href=\"[CONFIG_GET(string/githuburl)]/commit/[pc]\">[copytext(pc, 1, min(length(pc), 7))]</a>")
|
||||
else
|
||||
to_chat(src, "Revision unknown")
|
||||
to_chat(src, "<b>Current Informational Settings:</b>")
|
||||
to_chat(src, "Protect Authority Roles From Traitor: [config.protect_roles_from_antagonist]")
|
||||
to_chat(src, "Protect Assistant Role From Traitor: [config.protect_assistant_from_antagonist]")
|
||||
to_chat(src, "Enforce Human Authority: [config.enforce_human_authority]")
|
||||
to_chat(src, "Allow Latejoin Antagonists: [config.allow_latejoin_antagonists]")
|
||||
to_chat(src, "Enforce Continuous Rounds: [config.continuous.len] of [config.modes.len] roundtypes")
|
||||
to_chat(src, "Allow Midround Antagonists: [config.midround_antag.len] of [config.modes.len] roundtypes")
|
||||
if(config.show_game_type_odds)
|
||||
to_chat(src, "Protect Authority Roles From Traitor: [CONFIG_GET(flag/protect_roles_from_antagonist)]")
|
||||
to_chat(src, "Protect Assistant Role From Traitor: [CONFIG_GET(flag/protect_assistant_from_antagonist)]")
|
||||
to_chat(src, "Enforce Human Authority: [CONFIG_GET(flag/enforce_human_authority)]")
|
||||
to_chat(src, "Allow Latejoin Antagonists: [CONFIG_GET(flag/allow_latejoin_antagonists)]")
|
||||
to_chat(src, "Enforce Continuous Rounds: [length(CONFIG_GET(keyed_flag_list/continuous))] of [config.modes.len] roundtypes")
|
||||
to_chat(src, "Allow Midround Antagonists: [length(CONFIG_GET(keyed_flag_list/midround_antag))] of [config.modes.len] roundtypes")
|
||||
if(CONFIG_GET(flag/show_game_type_odds))
|
||||
var/list/probabilities = CONFIG_GET(keyed_number_list/probability)
|
||||
if(SSticker.IsRoundInProgress())
|
||||
var/prob_sum = 0
|
||||
var/current_odds_differ = FALSE
|
||||
var/list/probs = list()
|
||||
var/list/modes = config.gamemode_cache
|
||||
var/list/min_pop = CONFIG_GET(keyed_number_list/min_pop)
|
||||
var/list/max_pop = CONFIG_GET(keyed_number_list/max_pop)
|
||||
for(var/mode in modes)
|
||||
var/datum/game_mode/M = mode
|
||||
var/ctag = initial(M.config_tag)
|
||||
if(!(ctag in config.probabilities))
|
||||
if(!(ctag in probabilities))
|
||||
continue
|
||||
if((config.min_pop[ctag] && (config.min_pop[ctag] > SSticker.totalPlayersReady)) || (config.max_pop[ctag] && (config.max_pop[ctag] < SSticker.totalPlayersReady)) || (initial(M.required_players) > SSticker.totalPlayersReady))
|
||||
if((min_pop[ctag] && (min_pop[ctag] > SSticker.totalPlayersReady)) || (max_pop[ctag] && (max_pop[ctag] < SSticker.totalPlayersReady)) || (initial(M.required_players) > SSticker.totalPlayersReady))
|
||||
current_odds_differ = TRUE
|
||||
continue
|
||||
probs[ctag] = 1
|
||||
prob_sum += config.probabilities[ctag]
|
||||
prob_sum += probabilities[ctag]
|
||||
if(current_odds_differ)
|
||||
to_chat(src, "<b>Game Mode Odds for current round:</b>")
|
||||
for(var/ctag in probs)
|
||||
if(config.probabilities[ctag] > 0)
|
||||
var/percentage = round(config.probabilities[ctag] / prob_sum * 100, 0.1)
|
||||
if(probabilities[ctag] > 0)
|
||||
var/percentage = round(probabilities[ctag] / prob_sum * 100, 0.1)
|
||||
to_chat(src, "[ctag] [percentage]%")
|
||||
|
||||
to_chat(src, "<b>All Game Mode Odds:</b>")
|
||||
var/sum = 0
|
||||
for(var/ctag in config.probabilities)
|
||||
sum += config.probabilities[ctag]
|
||||
for(var/ctag in config.probabilities)
|
||||
if(config.probabilities[ctag] > 0)
|
||||
var/percentage = round(config.probabilities[ctag] / sum * 100, 0.1)
|
||||
for(var/ctag in probabilities)
|
||||
sum += probabilities[ctag]
|
||||
for(var/ctag in probabilities)
|
||||
if(probabilities[ctag] > 0)
|
||||
var/percentage = round(probabilities[ctag] / sum * 100, 0.1)
|
||||
to_chat(src, "[ctag] [percentage]%")
|
||||
|
||||
+5
-1
@@ -211,7 +211,7 @@
|
||||
/datum/mind/proc/remove_wizard()
|
||||
if(src in SSticker.mode.wizards)
|
||||
SSticker.mode.wizards -= src
|
||||
current.spellremove(current)
|
||||
RemoveAllSpells()
|
||||
special_role = null
|
||||
remove_antag_equip()
|
||||
|
||||
@@ -1505,6 +1505,10 @@
|
||||
spell_list -= S
|
||||
qdel(S)
|
||||
|
||||
/datum/mind/proc/RemoveAllSpells()
|
||||
for(var/obj/effect/proc_holder/S in spell_list)
|
||||
RemoveSpell(S)
|
||||
|
||||
/datum/mind/proc/transfer_martial_arts(mob/living/new_character)
|
||||
if(!ishuman(new_character))
|
||||
return
|
||||
|
||||
+253
-253
@@ -1,260 +1,260 @@
|
||||
#define MAXIMUM_EMP_WIRES 3
|
||||
|
||||
/proc/is_wire_tool(obj/item/I)
|
||||
if(istype(I, /obj/item/device/multitool))
|
||||
return TRUE
|
||||
if(istype(I, /obj/item/wirecutters))
|
||||
return TRUE
|
||||
if(istype(I, /obj/item/device/assembly))
|
||||
var/obj/item/device/assembly/A = I
|
||||
if(A.attachable)
|
||||
return TRUE
|
||||
return
|
||||
|
||||
/atom
|
||||
var/datum/wires/wires = null
|
||||
|
||||
/datum/wires
|
||||
var/atom/holder = null // The holder (atom that contains these wires).
|
||||
var/holder_type = null // The holder's typepath (used to make wire colors common to all holders).
|
||||
var/proper_name = "Unknown" // The display name for the wire set shown in station blueprints. Not used if randomize is true or it's an item NT wouldn't know about (Explosives/Nuke)
|
||||
|
||||
var/list/wires = list() // List of wires.
|
||||
var/list/cut_wires = list() // List of wires that have been cut.
|
||||
var/list/colors = list() // Dictionary of colors to wire.
|
||||
var/list/assemblies = list() // List of attached assemblies.
|
||||
var/randomize = 0 // If every instance of these wires should be random.
|
||||
// Prevents wires from showing up in station blueprints
|
||||
|
||||
/datum/wires/New(atom/holder)
|
||||
..()
|
||||
if(!istype(holder, holder_type))
|
||||
CRASH("Wire holder is not of the expected type!")
|
||||
return
|
||||
|
||||
src.holder = holder
|
||||
if(randomize)
|
||||
randomize()
|
||||
else
|
||||
if(!GLOB.wire_color_directory[holder_type])
|
||||
randomize()
|
||||
GLOB.wire_color_directory[holder_type] = colors
|
||||
GLOB.wire_name_directory[holder_type] = proper_name
|
||||
else
|
||||
colors = GLOB.wire_color_directory[holder_type]
|
||||
|
||||
/datum/wires/Destroy()
|
||||
holder = null
|
||||
assemblies = list()
|
||||
return ..()
|
||||
|
||||
/datum/wires/proc/add_duds(duds)
|
||||
while(duds)
|
||||
var/dud = WIRE_DUD_PREFIX + "[--duds]"
|
||||
if(dud in wires)
|
||||
continue
|
||||
wires += dud
|
||||
|
||||
/datum/wires/proc/randomize()
|
||||
var/static/list/possible_colors = list(
|
||||
"blue",
|
||||
"brown",
|
||||
"crimson",
|
||||
"cyan",
|
||||
"gold",
|
||||
"grey",
|
||||
"green",
|
||||
"magenta",
|
||||
"orange",
|
||||
"pink",
|
||||
"purple",
|
||||
"red",
|
||||
"silver",
|
||||
"violet",
|
||||
"white",
|
||||
"yellow"
|
||||
)
|
||||
|
||||
var/list/my_possible_colors = possible_colors.Copy()
|
||||
|
||||
for(var/wire in shuffle(wires))
|
||||
colors[pick_n_take(my_possible_colors)] = wire
|
||||
|
||||
/datum/wires/proc/shuffle_wires()
|
||||
colors.Cut()
|
||||
randomize()
|
||||
|
||||
/datum/wires/proc/repair()
|
||||
cut_wires.Cut()
|
||||
|
||||
/datum/wires/proc/get_wire(color)
|
||||
return colors[color]
|
||||
|
||||
/datum/wires/proc/get_attached(color)
|
||||
if(assemblies[color])
|
||||
return assemblies[color]
|
||||
return null
|
||||
|
||||
/datum/wires/proc/is_attached(color)
|
||||
if(assemblies[color])
|
||||
return TRUE
|
||||
|
||||
/datum/wires/proc/is_cut(wire)
|
||||
return (wire in cut_wires)
|
||||
|
||||
/datum/wires/proc/is_color_cut(color)
|
||||
return is_cut(get_wire(color))
|
||||
|
||||
/datum/wires/proc/is_all_cut()
|
||||
if(cut_wires.len == wires.len)
|
||||
return TRUE
|
||||
|
||||
/datum/wires/proc/cut(wire)
|
||||
if(is_cut(wire))
|
||||
cut_wires -= wire
|
||||
on_cut(wire, mend = TRUE)
|
||||
else
|
||||
cut_wires += wire
|
||||
on_cut(wire, mend = FALSE)
|
||||
|
||||
/datum/wires/proc/cut_color(color)
|
||||
cut(get_wire(color))
|
||||
|
||||
/datum/wires/proc/cut_random()
|
||||
cut(wires[rand(1, wires.len)])
|
||||
|
||||
/datum/wires/proc/cut_all()
|
||||
for(var/wire in wires)
|
||||
cut(wire)
|
||||
|
||||
#define MAXIMUM_EMP_WIRES 3
|
||||
|
||||
/proc/is_wire_tool(obj/item/I)
|
||||
if(istype(I, /obj/item/device/multitool))
|
||||
return TRUE
|
||||
if(istype(I, /obj/item/wirecutters))
|
||||
return TRUE
|
||||
if(istype(I, /obj/item/device/assembly))
|
||||
var/obj/item/device/assembly/A = I
|
||||
if(A.attachable)
|
||||
return TRUE
|
||||
return
|
||||
|
||||
/atom
|
||||
var/datum/wires/wires = null
|
||||
|
||||
/datum/wires
|
||||
var/atom/holder = null // The holder (atom that contains these wires).
|
||||
var/holder_type = null // The holder's typepath (used to make wire colors common to all holders).
|
||||
var/proper_name = "Unknown" // The display name for the wire set shown in station blueprints. Not used if randomize is true or it's an item NT wouldn't know about (Explosives/Nuke)
|
||||
|
||||
var/list/wires = list() // List of wires.
|
||||
var/list/cut_wires = list() // List of wires that have been cut.
|
||||
var/list/colors = list() // Dictionary of colors to wire.
|
||||
var/list/assemblies = list() // List of attached assemblies.
|
||||
var/randomize = 0 // If every instance of these wires should be random.
|
||||
// Prevents wires from showing up in station blueprints
|
||||
|
||||
/datum/wires/New(atom/holder)
|
||||
..()
|
||||
if(!istype(holder, holder_type))
|
||||
CRASH("Wire holder is not of the expected type!")
|
||||
return
|
||||
|
||||
src.holder = holder
|
||||
if(randomize)
|
||||
randomize()
|
||||
else
|
||||
if(!GLOB.wire_color_directory[holder_type])
|
||||
randomize()
|
||||
GLOB.wire_color_directory[holder_type] = colors
|
||||
GLOB.wire_name_directory[holder_type] = proper_name
|
||||
else
|
||||
colors = GLOB.wire_color_directory[holder_type]
|
||||
|
||||
/datum/wires/Destroy()
|
||||
holder = null
|
||||
assemblies = list()
|
||||
return ..()
|
||||
|
||||
/datum/wires/proc/add_duds(duds)
|
||||
while(duds)
|
||||
var/dud = WIRE_DUD_PREFIX + "[--duds]"
|
||||
if(dud in wires)
|
||||
continue
|
||||
wires += dud
|
||||
|
||||
/datum/wires/proc/randomize()
|
||||
var/static/list/possible_colors = list(
|
||||
"blue",
|
||||
"brown",
|
||||
"crimson",
|
||||
"cyan",
|
||||
"gold",
|
||||
"grey",
|
||||
"green",
|
||||
"magenta",
|
||||
"orange",
|
||||
"pink",
|
||||
"purple",
|
||||
"red",
|
||||
"silver",
|
||||
"violet",
|
||||
"white",
|
||||
"yellow"
|
||||
)
|
||||
|
||||
var/list/my_possible_colors = possible_colors.Copy()
|
||||
|
||||
for(var/wire in shuffle(wires))
|
||||
colors[pick_n_take(my_possible_colors)] = wire
|
||||
|
||||
/datum/wires/proc/shuffle_wires()
|
||||
colors.Cut()
|
||||
randomize()
|
||||
|
||||
/datum/wires/proc/repair()
|
||||
cut_wires.Cut()
|
||||
|
||||
/datum/wires/proc/get_wire(color)
|
||||
return colors[color]
|
||||
|
||||
/datum/wires/proc/get_attached(color)
|
||||
if(assemblies[color])
|
||||
return assemblies[color]
|
||||
return null
|
||||
|
||||
/datum/wires/proc/is_attached(color)
|
||||
if(assemblies[color])
|
||||
return TRUE
|
||||
|
||||
/datum/wires/proc/is_cut(wire)
|
||||
return (wire in cut_wires)
|
||||
|
||||
/datum/wires/proc/is_color_cut(color)
|
||||
return is_cut(get_wire(color))
|
||||
|
||||
/datum/wires/proc/is_all_cut()
|
||||
if(cut_wires.len == wires.len)
|
||||
return TRUE
|
||||
|
||||
/datum/wires/proc/cut(wire)
|
||||
if(is_cut(wire))
|
||||
cut_wires -= wire
|
||||
on_cut(wire, mend = TRUE)
|
||||
else
|
||||
cut_wires += wire
|
||||
on_cut(wire, mend = FALSE)
|
||||
|
||||
/datum/wires/proc/cut_color(color)
|
||||
cut(get_wire(color))
|
||||
|
||||
/datum/wires/proc/cut_random()
|
||||
cut(wires[rand(1, wires.len)])
|
||||
|
||||
/datum/wires/proc/cut_all()
|
||||
for(var/wire in wires)
|
||||
cut(wire)
|
||||
|
||||
/datum/wires/proc/pulse(wire, user)
|
||||
if(is_cut(wire))
|
||||
return
|
||||
if(is_cut(wire))
|
||||
return
|
||||
on_pulse(wire, user)
|
||||
|
||||
|
||||
/datum/wires/proc/pulse_color(color, mob/living/user)
|
||||
pulse(get_wire(color), user)
|
||||
|
||||
/datum/wires/proc/pulse_assembly(obj/item/device/assembly/S)
|
||||
for(var/color in assemblies)
|
||||
if(S == assemblies[color])
|
||||
pulse_color(color)
|
||||
return TRUE
|
||||
|
||||
/datum/wires/proc/attach_assembly(color, obj/item/device/assembly/S)
|
||||
if(S && istype(S) && S.attachable && !is_attached(color))
|
||||
assemblies[color] = S
|
||||
S.loc = holder
|
||||
S.connected = src
|
||||
return S
|
||||
|
||||
/datum/wires/proc/detach_assembly(color)
|
||||
var/obj/item/device/assembly/S = get_attached(color)
|
||||
if(S && istype(S))
|
||||
assemblies -= color
|
||||
S.connected = null
|
||||
S.loc = holder.loc
|
||||
return S
|
||||
|
||||
/datum/wires/proc/emp_pulse()
|
||||
var/list/possible_wires = shuffle(wires)
|
||||
var/remaining_pulses = MAXIMUM_EMP_WIRES
|
||||
|
||||
for(var/wire in possible_wires)
|
||||
if(prob(33))
|
||||
pulse(wire)
|
||||
remaining_pulses--
|
||||
if(remaining_pulses >= 0)
|
||||
break
|
||||
|
||||
// Overridable Procs
|
||||
/datum/wires/proc/interactable(mob/user)
|
||||
return TRUE
|
||||
|
||||
/datum/wires/proc/get_status()
|
||||
return list()
|
||||
|
||||
/datum/wires/proc/on_cut(wire, mend = FALSE)
|
||||
return
|
||||
|
||||
|
||||
/datum/wires/proc/pulse_assembly(obj/item/device/assembly/S)
|
||||
for(var/color in assemblies)
|
||||
if(S == assemblies[color])
|
||||
pulse_color(color)
|
||||
return TRUE
|
||||
|
||||
/datum/wires/proc/attach_assembly(color, obj/item/device/assembly/S)
|
||||
if(S && istype(S) && S.attachable && !is_attached(color))
|
||||
assemblies[color] = S
|
||||
S.forceMove(holder)
|
||||
S.connected = src
|
||||
return S
|
||||
|
||||
/datum/wires/proc/detach_assembly(color)
|
||||
var/obj/item/device/assembly/S = get_attached(color)
|
||||
if(S && istype(S))
|
||||
assemblies -= color
|
||||
S.connected = null
|
||||
S.forceMove(holder.drop_location())
|
||||
return S
|
||||
|
||||
/datum/wires/proc/emp_pulse()
|
||||
var/list/possible_wires = shuffle(wires)
|
||||
var/remaining_pulses = MAXIMUM_EMP_WIRES
|
||||
|
||||
for(var/wire in possible_wires)
|
||||
if(prob(33))
|
||||
pulse(wire)
|
||||
remaining_pulses--
|
||||
if(remaining_pulses >= 0)
|
||||
break
|
||||
|
||||
// Overridable Procs
|
||||
/datum/wires/proc/interactable(mob/user)
|
||||
return TRUE
|
||||
|
||||
/datum/wires/proc/get_status()
|
||||
return list()
|
||||
|
||||
/datum/wires/proc/on_cut(wire, mend = FALSE)
|
||||
return
|
||||
|
||||
/datum/wires/proc/on_pulse(wire, user)
|
||||
return
|
||||
// End Overridable Procs
|
||||
|
||||
/datum/wires/proc/interact(mob/user)
|
||||
if(!interactable(user))
|
||||
return
|
||||
ui_interact(user)
|
||||
for(var/A in assemblies)
|
||||
var/obj/item/I = assemblies[A]
|
||||
if(istype(I) && I.on_found(user))
|
||||
return
|
||||
|
||||
/datum/wires/ui_host()
|
||||
return holder
|
||||
|
||||
/datum/wires/ui_status(mob/user)
|
||||
if(interactable(user))
|
||||
return ..()
|
||||
return UI_CLOSE
|
||||
|
||||
return
|
||||
// End Overridable Procs
|
||||
|
||||
/datum/wires/proc/interact(mob/user)
|
||||
if(!interactable(user))
|
||||
return
|
||||
ui_interact(user)
|
||||
for(var/A in assemblies)
|
||||
var/obj/item/I = assemblies[A]
|
||||
if(istype(I) && I.on_found(user))
|
||||
return
|
||||
|
||||
/datum/wires/ui_host()
|
||||
return holder
|
||||
|
||||
/datum/wires/ui_status(mob/user)
|
||||
if(interactable(user))
|
||||
return ..()
|
||||
return UI_CLOSE
|
||||
|
||||
/datum/wires/ui_interact(mob/user, ui_key = "wires", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "wires", "[holder.name] wires", 350, 150 + wires.len * 30, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/datum/wires/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
var/list/payload = list()
|
||||
for(var/color in colors)
|
||||
payload.Add(list(list(
|
||||
"color" = color,
|
||||
"wire" = (IsAdminGhost(user) || (user.is_holding_item_of_type(/obj/item/device/multitool/abductor)) ? get_wire(color) : null),
|
||||
"cut" = is_color_cut(color),
|
||||
"attached" = is_attached(color)
|
||||
)))
|
||||
data["wires"] = payload
|
||||
data["status"] = get_status()
|
||||
return data
|
||||
|
||||
/datum/wires/ui_act(action, params)
|
||||
if(..() || !interactable(usr))
|
||||
return
|
||||
var/target_wire = params["wire"]
|
||||
var/mob/living/L = usr
|
||||
var/obj/item/I = L.get_active_held_item()
|
||||
switch(action)
|
||||
if("cut")
|
||||
if(istype(I, /obj/item/wirecutters) || IsAdminGhost(usr))
|
||||
playsound(holder, I.usesound, 20, 1)
|
||||
cut_color(target_wire)
|
||||
. = TRUE
|
||||
else
|
||||
to_chat(L, "<span class='warning'>You need wirecutters!</span>")
|
||||
if("pulse")
|
||||
if(istype(I, /obj/item/device/multitool) || IsAdminGhost(usr))
|
||||
playsound(holder, 'sound/weapons/empty.ogg', 20, 1)
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "wires", "[holder.name] wires", 350, 150 + wires.len * 30, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/datum/wires/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
var/list/payload = list()
|
||||
for(var/color in colors)
|
||||
payload.Add(list(list(
|
||||
"color" = color,
|
||||
"wire" = (IsAdminGhost(user) || (user.is_holding_item_of_type(/obj/item/device/multitool/abductor)) ? get_wire(color) : null),
|
||||
"cut" = is_color_cut(color),
|
||||
"attached" = is_attached(color)
|
||||
)))
|
||||
data["wires"] = payload
|
||||
data["status"] = get_status()
|
||||
return data
|
||||
|
||||
/datum/wires/ui_act(action, params)
|
||||
if(..() || !interactable(usr))
|
||||
return
|
||||
var/target_wire = params["wire"]
|
||||
var/mob/living/L = usr
|
||||
var/obj/item/I = L.get_active_held_item()
|
||||
switch(action)
|
||||
if("cut")
|
||||
if(istype(I, /obj/item/wirecutters) || IsAdminGhost(usr))
|
||||
playsound(holder, I.usesound, 20, 1)
|
||||
cut_color(target_wire)
|
||||
. = TRUE
|
||||
else
|
||||
to_chat(L, "<span class='warning'>You need wirecutters!</span>")
|
||||
if("pulse")
|
||||
if(istype(I, /obj/item/device/multitool) || IsAdminGhost(usr))
|
||||
playsound(holder, 'sound/weapons/empty.ogg', 20, 1)
|
||||
pulse_color(target_wire, L)
|
||||
. = TRUE
|
||||
else
|
||||
to_chat(L, "<span class='warning'>You need a multitool!</span>")
|
||||
if("attach")
|
||||
if(is_attached(target_wire))
|
||||
var/obj/item/O = detach_assembly(target_wire)
|
||||
if(O)
|
||||
L.put_in_hands(O)
|
||||
. = TRUE
|
||||
else
|
||||
if(istype(I, /obj/item/device/assembly))
|
||||
var/obj/item/device/assembly/A = I
|
||||
if(A.attachable)
|
||||
if(!L.drop_item())
|
||||
return
|
||||
attach_assembly(target_wire, A)
|
||||
. = TRUE
|
||||
else
|
||||
to_chat(L, "<span class='warning'>You need an attachable assembly!</span>")
|
||||
|
||||
#undef MAXIMUM_EMP_WIRES
|
||||
. = TRUE
|
||||
else
|
||||
to_chat(L, "<span class='warning'>You need a multitool!</span>")
|
||||
if("attach")
|
||||
if(is_attached(target_wire))
|
||||
var/obj/item/O = detach_assembly(target_wire)
|
||||
if(O)
|
||||
L.put_in_hands(O)
|
||||
. = TRUE
|
||||
else
|
||||
if(istype(I, /obj/item/device/assembly))
|
||||
var/obj/item/device/assembly/A = I
|
||||
if(A.attachable)
|
||||
if(!L.drop_item())
|
||||
return
|
||||
attach_assembly(target_wire, A)
|
||||
. = TRUE
|
||||
else
|
||||
to_chat(L, "<span class='warning'>You need an attachable assembly!</span>")
|
||||
|
||||
#undef MAXIMUM_EMP_WIRES
|
||||
|
||||
@@ -118,7 +118,7 @@ GLOBAL_LIST_EMPTY(teleportlocs)
|
||||
else if(dynamic_lighting != DYNAMIC_LIGHTING_IFSTARLIGHT)
|
||||
dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
|
||||
if(dynamic_lighting == DYNAMIC_LIGHTING_IFSTARLIGHT)
|
||||
dynamic_lighting = config.starlight ? DYNAMIC_LIGHTING_ENABLED : DYNAMIC_LIGHTING_DISABLED
|
||||
dynamic_lighting = CONFIG_GET(flag/starlight) ? DYNAMIC_LIGHTING_ENABLED : DYNAMIC_LIGHTING_DISABLED
|
||||
|
||||
. = ..()
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ GLOBAL_LIST_EMPTY(blobs_legit) //used for win-score calculations, contains only
|
||||
var/mob/camera/blob/B = blob.current.become_overmind(TRUE, round(blob_base_starting_points/blob_overminds.len))
|
||||
B.mind.name = B.name
|
||||
var/turf/T = pick(GLOB.blobstart)
|
||||
B.loc = T
|
||||
B.forceMove(T)
|
||||
B.base_point_rate = blob_point_rate
|
||||
|
||||
SSshuttle.registerHostileEnvironment(src)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
if(B.blob_core || !B.placed)
|
||||
return 0
|
||||
if(!GLOB.blob_cores.len) //blob is dead
|
||||
if(config.continuous["blob"])
|
||||
if(CONFIG_GET(keyed_flag_list/continuous)["blob"])
|
||||
message_sent = FALSE //disable the win count at this point
|
||||
continuous_sanity_checked = 1 //Nonstandard definition of "alive" gets past the check otherwise
|
||||
SSshuttle.clearHostileEnvironment(src)
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
set name = "Jump to Core"
|
||||
set desc = "Move your camera to your core."
|
||||
if(blob_core)
|
||||
src.loc = blob_core.loc
|
||||
forceMove(blob_core.drop_location())
|
||||
|
||||
/mob/camera/blob/verb/jump_to_node()
|
||||
set category = "Blob"
|
||||
|
||||
@@ -190,7 +190,7 @@
|
||||
B.density = TRUE
|
||||
if(T.Enter(B,src)) //NOW we can attempt to move into the tile
|
||||
B.density = initial(B.density)
|
||||
B.loc = T
|
||||
B.forceMove(T)
|
||||
B.update_icon()
|
||||
if(B.overmind && expand_reaction)
|
||||
B.overmind.blob_reagent_datum.expand_reaction(src, B, T, controller)
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
/datum/objective_team/brother_team/proc/forge_brother_objectives()
|
||||
objectives = list()
|
||||
var/is_hijacker = prob(10)
|
||||
for(var/i = 1 to max(1, config.brother_objectives_amount + (members.len > 2) - is_hijacker))
|
||||
for(var/i = 1 to max(1, CONFIG_GET(number/brother_objectives_amount) + (members.len > 2) - is_hijacker))
|
||||
forge_single_objective()
|
||||
if(is_hijacker)
|
||||
if(!locate(/datum/objective/hijack) in objectives)
|
||||
@@ -58,16 +58,17 @@
|
||||
var/meeting_areas = list("The Bar", "Dorms", "Escape Dock", "Arrivals", "Holodeck", "Primary Tool Storage", "Recreation Area", "Chapel", "Library")
|
||||
|
||||
/datum/game_mode/traitor/bros/pre_setup()
|
||||
if(config.protect_roles_from_antagonist)
|
||||
if(CONFIG_GET(flag/protect_roles_from_antagonist))
|
||||
restricted_jobs += protected_jobs
|
||||
if(config.protect_assistant_from_antagonist)
|
||||
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
|
||||
restricted_jobs += "Assistant"
|
||||
|
||||
var/list/datum/mind/possible_brothers = get_players_for_role(ROLE_BROTHER)
|
||||
|
||||
var/num_teams = team_amount
|
||||
if(config.brother_scaling_coeff)
|
||||
num_teams = max(1, round(num_players()/config.brother_scaling_coeff))
|
||||
var/bsc = CONFIG_GET(number/brother_scaling_coeff)
|
||||
if(bsc)
|
||||
num_teams = max(1, round(num_players() / bsc))
|
||||
|
||||
for(var/j = 1 to num_teams)
|
||||
if(possible_brothers.len < min_team_size || antag_candidates.len <= required_enemies)
|
||||
|
||||
@@ -52,16 +52,17 @@ GLOBAL_LIST_INIT(slot2type, list("head" = /obj/item/clothing/head/changeling, "w
|
||||
|
||||
/datum/game_mode/changeling/pre_setup()
|
||||
|
||||
if(config.protect_roles_from_antagonist)
|
||||
if(CONFIG_GET(flag/protect_roles_from_antagonist))
|
||||
restricted_jobs += protected_jobs
|
||||
|
||||
if(config.protect_assistant_from_antagonist)
|
||||
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
|
||||
restricted_jobs += "Assistant"
|
||||
|
||||
var/num_changelings = 1
|
||||
|
||||
if(config.changeling_scaling_coeff)
|
||||
num_changelings = max(1, min( round(num_players()/(config.changeling_scaling_coeff*2))+2, round(num_players()/config.changeling_scaling_coeff) ))
|
||||
var/csc = CONFIG_GET(number/changeling_scaling_coeff)
|
||||
if(csc)
|
||||
num_changelings = max(1, min(round(num_players() / (csc * 2)) + 2, round(num_players() / csc)))
|
||||
else
|
||||
num_changelings = max(1, min(num_players(), changeling_amount))
|
||||
|
||||
@@ -102,10 +103,11 @@ GLOBAL_LIST_INIT(slot2type, list("head" = /obj/item/clothing/head/changeling, "w
|
||||
..()
|
||||
|
||||
/datum/game_mode/changeling/make_antag_chance(mob/living/carbon/human/character) //Assigns changeling to latejoiners
|
||||
var/changelingcap = min( round(GLOB.joined_player_list.len/(config.changeling_scaling_coeff*2))+2, round(GLOB.joined_player_list.len/config.changeling_scaling_coeff) )
|
||||
var/csc = CONFIG_GET(number/changeling_scaling_coeff)
|
||||
var/changelingcap = min(round(GLOB.joined_player_list.len / (csc * 2)) + 2, round(GLOB.joined_player_list.len / csc))
|
||||
if(SSticker.mode.changelings.len >= changelingcap) //Caps number of latejoin antagonists
|
||||
return
|
||||
if(SSticker.mode.changelings.len <= (changelingcap - 2) || prob(100 - (config.changeling_scaling_coeff*2)))
|
||||
if(SSticker.mode.changelings.len <= (changelingcap - 2) || prob(100 - (csc * 2)))
|
||||
if(ROLE_CHANGELING in character.client.prefs.be_special)
|
||||
if(!jobban_isbanned(character, ROLE_CHANGELING) && !jobban_isbanned(character, "Syndicate"))
|
||||
if(age_check(character.client))
|
||||
@@ -131,10 +133,16 @@ GLOBAL_LIST_INIT(slot2type, list("head" = /obj/item/clothing/head/changeling, "w
|
||||
changeling.objectives += absorb_objective
|
||||
|
||||
if(prob(60))
|
||||
var/datum/objective/steal/steal_objective = new
|
||||
steal_objective.owner = changeling
|
||||
steal_objective.find_target()
|
||||
changeling.objectives += steal_objective
|
||||
if(prob(85))
|
||||
var/datum/objective/steal/steal_objective = new
|
||||
steal_objective.owner = changeling
|
||||
steal_objective.find_target()
|
||||
changeling.objectives += steal_objective
|
||||
else
|
||||
var/datum/objective/download/download_objective = new
|
||||
download_objective.owner = changeling
|
||||
download_objective.gen_amount_goal()
|
||||
changeling.objectives += download_objective
|
||||
|
||||
var/list/active_ais = active_ais()
|
||||
if(active_ais.len && prob(100/GLOB.joined_player_list.len))
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
sleep(5) // So it's not killed in explosion
|
||||
var/mob/living/simple_animal/hostile/headcrab/crab = new(turf)
|
||||
for(var/obj/item/organ/I in organs)
|
||||
I.loc = crab
|
||||
I.forceMove(crab)
|
||||
crab.origin = M
|
||||
if(crab.origin)
|
||||
crab.origin.active = 1
|
||||
|
||||
@@ -25,18 +25,19 @@
|
||||
return 1
|
||||
|
||||
/datum/game_mode/traitor/changeling/pre_setup()
|
||||
if(config.protect_roles_from_antagonist)
|
||||
if(CONFIG_GET(flag/protect_roles_from_antagonist))
|
||||
restricted_jobs += protected_jobs
|
||||
|
||||
if(config.protect_assistant_from_antagonist)
|
||||
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
|
||||
restricted_jobs += "Assistant"
|
||||
|
||||
var/list/datum/mind/possible_changelings = get_players_for_role(ROLE_CHANGELING)
|
||||
|
||||
var/num_changelings = 1
|
||||
|
||||
if(config.changeling_scaling_coeff)
|
||||
num_changelings = max(1, min( round(num_players()/(config.changeling_scaling_coeff*4))+2, round(num_players()/(config.changeling_scaling_coeff*2)) ))
|
||||
var/csc = CONFIG_GET(number/changeling_scaling_coeff)
|
||||
if(csc)
|
||||
num_changelings = max(1, min(round(num_players() / (csc * 4)) + 2, round(num_players() / (csc * 2))))
|
||||
else
|
||||
num_changelings = max(1, min(num_players(), changeling_amount/2))
|
||||
|
||||
@@ -64,11 +65,12 @@
|
||||
return
|
||||
|
||||
/datum/game_mode/traitor/changeling/make_antag_chance(mob/living/carbon/human/character) //Assigns changeling to latejoiners
|
||||
var/changelingcap = min( round(GLOB.joined_player_list.len/(config.changeling_scaling_coeff*4))+2, round(GLOB.joined_player_list.len/(config.changeling_scaling_coeff*2)) )
|
||||
var/csc = CONFIG_GET(number/changeling_scaling_coeff)
|
||||
var/changelingcap = min( round(GLOB.joined_player_list.len / (csc * 4)) + 2, round(GLOB.joined_player_list.len / (csc * 2)))
|
||||
if(SSticker.mode.changelings.len >= changelingcap) //Caps number of latejoin antagonists
|
||||
..()
|
||||
return
|
||||
if(SSticker.mode.changelings.len <= (changelingcap - 2) || prob(100 / (config.changeling_scaling_coeff * 4)))
|
||||
if(SSticker.mode.changelings.len <= (changelingcap - 2) || prob(100 / (csc * 4)))
|
||||
if(ROLE_CHANGELING in character.client.prefs.be_special)
|
||||
if(!jobban_isbanned(character, ROLE_CHANGELING) && !jobban_isbanned(character, "Syndicate"))
|
||||
if(age_check(character.client))
|
||||
|
||||
@@ -107,9 +107,9 @@ Credit where due:
|
||||
var/ark_time //In minutes, how long the Ark waits before activation; this is equal to 30 + (number of players / 5) (max 40 mins.)
|
||||
|
||||
/datum/game_mode/clockwork_cult/pre_setup()
|
||||
if(config.protect_roles_from_antagonist)
|
||||
if(CONFIG_GET(flag/protect_roles_from_antagonist))
|
||||
restricted_jobs += protected_jobs
|
||||
if(config.protect_assistant_from_antagonist)
|
||||
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
|
||||
restricted_jobs += "Assistant"
|
||||
var/starter_servants = 4 //Guaranteed four servants
|
||||
var/number_players = num_players()
|
||||
|
||||
@@ -55,10 +55,10 @@
|
||||
/datum/game_mode/cult/pre_setup()
|
||||
cult_objectives += "sacrifice"
|
||||
|
||||
if(config.protect_roles_from_antagonist)
|
||||
if(CONFIG_GET(flag/protect_roles_from_antagonist))
|
||||
restricted_jobs += protected_jobs
|
||||
|
||||
if(config.protect_assistant_from_antagonist)
|
||||
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
|
||||
restricted_jobs += "Assistant"
|
||||
|
||||
//cult scaling goes here
|
||||
|
||||
@@ -20,15 +20,16 @@
|
||||
+ <span class='notice'>Crew</span>: Resist the lure of sin and remain pure!"
|
||||
|
||||
/datum/game_mode/devil/pre_setup()
|
||||
if(config.protect_roles_from_antagonist)
|
||||
if(CONFIG_GET(flag/protect_roles_from_antagonist))
|
||||
restricted_jobs += protected_jobs
|
||||
if(config.protect_assistant_from_antagonist)
|
||||
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
|
||||
restricted_jobs += "Assistant"
|
||||
|
||||
var/num_devils = 1
|
||||
|
||||
if(config.traitor_scaling_coeff)
|
||||
num_devils = max(minimum_devils, min( round(num_players()/(config.traitor_scaling_coeff*3))+ 2 + num_modifier, round(num_players()/(config.traitor_scaling_coeff*1.5)) + num_modifier ))
|
||||
var/tsc = CONFIG_GET(number/traitor_scaling_coeff)
|
||||
if(tsc)
|
||||
num_devils = max(minimum_devils, min( round(num_players() / (tsc * 3))+ 2 + num_modifier, round(num_players() / (tsc * 1.5)) + num_modifier))
|
||||
else
|
||||
num_devils = max(minimum_devils, min(num_players(), traitors_possible))
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
///Everyone should now be on the station and have their normal gear. This is the place to give the special roles extra things
|
||||
/datum/game_mode/proc/post_setup(report) //Gamemodes can override the intercept report. Passing TRUE as the argument will force a report.
|
||||
if(!report)
|
||||
report = config.intercept
|
||||
report = !CONFIG_GET(flag/no_intercept_report)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/display_roundstart_logout_report), ROUNDSTART_LOGOUT_REPORT_TIME)
|
||||
|
||||
if(SSdbcore.Connect())
|
||||
@@ -113,8 +113,9 @@
|
||||
for(var/mob/Player in GLOB.mob_list)
|
||||
if(Player.mind && Player.stat != DEAD && !isnewplayer(Player) && !isbrain(Player) && Player.client)
|
||||
living_crew += Player
|
||||
if(living_crew.len / GLOB.joined_player_list.len <= config.midround_antag_life_check) //If a lot of the player base died, we start fresh
|
||||
message_admins("Convert_roundtype failed due to too many dead people. Limit is [config.midround_antag_life_check * 100]% living crew")
|
||||
var/malc = CONFIG_GET(number/midround_antag_life_check)
|
||||
if(living_crew.len / GLOB.joined_player_list.len <= malc) //If a lot of the player base died, we start fresh
|
||||
message_admins("Convert_roundtype failed due to too many dead people. Limit is [malc * 100]% living crew")
|
||||
return null
|
||||
|
||||
var/list/datum/game_mode/runnable_modes = config.get_runnable_midround_modes(living_crew.len)
|
||||
@@ -138,8 +139,9 @@
|
||||
if(SSshuttle.emergency.timeLeft(1) < initial(SSshuttle.emergencyCallTime)*0.5)
|
||||
return 1
|
||||
|
||||
if(world.time >= (config.midround_antag_time_check * 600))
|
||||
message_admins("Convert_roundtype failed due to round length. Limit is [config.midround_antag_time_check] minutes.")
|
||||
var/matc = CONFIG_GET(number/midround_antag_time_check)
|
||||
if(world.time >= (matc * 600))
|
||||
message_admins("Convert_roundtype failed due to round length. Limit is [matc] minutes.")
|
||||
return null
|
||||
|
||||
var/list/antag_candidates = list()
|
||||
@@ -154,9 +156,9 @@
|
||||
|
||||
antag_candidates = shuffle(antag_candidates)
|
||||
|
||||
if(config.protect_roles_from_antagonist)
|
||||
if(CONFIG_GET(flag/protect_roles_from_antagonist))
|
||||
replacementmode.restricted_jobs += replacementmode.protected_jobs
|
||||
if(config.protect_assistant_from_antagonist)
|
||||
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
|
||||
replacementmode.restricted_jobs += "Assistant"
|
||||
|
||||
message_admins("The roundtype will be converted. If you have other plans for the station or feel the station is too messed up to inhabit <A HREF='?_src_=holder;[HrefToken()];toggle_midround_antag=\ref[usr]'>stop the creation of antags</A> or <A HREF='?_src_=holder;[HrefToken()];end_round=\ref[usr]'>end the round now</A>.")
|
||||
@@ -168,7 +170,7 @@
|
||||
round_converted = 0
|
||||
return
|
||||
//somewhere between 1 and 3 minutes from now
|
||||
if(!config.midround_antag[SSticker.mode.config_tag])
|
||||
if(!CONFIG_GET(keyed_flag_list/midround_antag)[SSticker.mode.config_tag])
|
||||
round_converted = 0
|
||||
return 1
|
||||
for(var/mob/living/carbon/human/H in antag_candidates)
|
||||
@@ -189,7 +191,9 @@
|
||||
return TRUE
|
||||
if(station_was_nuked)
|
||||
return TRUE
|
||||
if(!round_converted && (!config.continuous[config_tag] || (config.continuous[config_tag] && config.midround_antag[config_tag]))) //Non-continuous or continous with replacement antags
|
||||
var/list/continuous = CONFIG_GET(keyed_flag_list/continuous)
|
||||
var/list/midround_antag = CONFIG_GET(keyed_flag_list/midround_antag)
|
||||
if(!round_converted && (!continuous[config_tag] || (continuous[config_tag] && midround_antag[config_tag]))) //Non-continuous or continous with replacement antags
|
||||
if(!continuous_sanity_checked) //make sure we have antags to be checking in the first place
|
||||
for(var/mob/Player in GLOB.mob_list)
|
||||
if(Player.mind)
|
||||
@@ -198,8 +202,8 @@
|
||||
return 0
|
||||
if(!continuous_sanity_checked)
|
||||
message_admins("The roundtype ([config_tag]) has no antagonists, continuous round has been defaulted to on and midround_antag has been defaulted to off.")
|
||||
config.continuous[config_tag] = 1
|
||||
config.midround_antag[config_tag] = 0
|
||||
continuous[config_tag] = TRUE
|
||||
midround_antag[config_tag] = FALSE
|
||||
SSshuttle.clearHostileEnvironment(src)
|
||||
return 0
|
||||
|
||||
@@ -213,7 +217,7 @@
|
||||
living_antag_player = Player
|
||||
return 0
|
||||
|
||||
if(!config.continuous[config_tag] || force_ending)
|
||||
if(!continuous[config_tag] || force_ending)
|
||||
return 1
|
||||
|
||||
else
|
||||
@@ -222,7 +226,7 @@
|
||||
if(round_ends_with_antag_death)
|
||||
return 1
|
||||
else
|
||||
config.midround_antag[config_tag] = 0
|
||||
midround_antag[config_tag] = 0
|
||||
return 0
|
||||
|
||||
return 0
|
||||
@@ -517,7 +521,7 @@
|
||||
/datum/game_mode/proc/get_remaining_days(client/C)
|
||||
if(!C)
|
||||
return 0
|
||||
if(!config.use_age_restriction_for_jobs)
|
||||
if(!CONFIG_GET(flag/use_age_restriction_for_jobs))
|
||||
return 0
|
||||
if(!isnum(C.player_age))
|
||||
return 0 //This is only a number if the db connection is established, otherwise it is text: "Requires database", meaning these restrictions cannot be enforced
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
to_chat(world, "<b>Crew</b> - don't get abducted and stop the abductors.")
|
||||
|
||||
/datum/game_mode/abduction/pre_setup()
|
||||
var/num_teams = max(1, min(max_teams, round(num_players() / config.abductor_scaling_coeff)))
|
||||
var/num_teams = max(1, min(max_teams, round(num_players() / CONFIG_GET(number/abductor_scaling_coeff))))
|
||||
var/possible_teams = max(1, round(antag_candidates.len / 2))
|
||||
num_teams = min(num_teams, possible_teams)
|
||||
|
||||
|
||||
@@ -218,7 +218,7 @@
|
||||
|
||||
/obj/structure/spider/cocoon/abductor/proc/Copy(mob/living/carbon/human/H)
|
||||
var/mob/living/carbon/human/interactive/greytide/clone = new(src)
|
||||
clone.hardset_dna(H.dna.uni_identity,H.dna.struc_enzymes,H.real_name, H.dna.blood_type, H.dna.species.type, H.dna.features)
|
||||
clone.hardset_dna(H.dna.uni_identity,H.dna.struc_enzymes,H.real_name, H.dna.blood_type, H.dna.species, H.dna.features)
|
||||
|
||||
/obj/structure/spider/cocoon/abductor/proc/Start()
|
||||
hatch_time = world.time + 600
|
||||
|
||||
@@ -60,9 +60,8 @@
|
||||
|
||||
/obj/machinery/abductor/gland_dispenser/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/organ/heart/gland))
|
||||
if(!user.drop_item())
|
||||
if(!user.transferItemToLoc(W, src))
|
||||
return
|
||||
W.loc = src
|
||||
for(var/i=1,i<=gland_colors.len,i++)
|
||||
if(gland_types[i] == W.type)
|
||||
amounts[i]++
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
/obj/machinery/abductor/experiment/proc/dissection_icon(mob/living/carbon/human/H)
|
||||
var/icon/photo = null
|
||||
var/g = (H.gender == FEMALE) ? "f" : "m"
|
||||
if(!config.mutant_races || H.dna.species.use_skintones)
|
||||
if(!CONFIG_GET(flag/join_with_mutant_race) || H.dna.species.use_skintones)
|
||||
photo = icon("icon" = 'icons/mob/human.dmi', "icon_state" = "[H.skin_tone]_[g]")
|
||||
else
|
||||
photo = icon("icon" = 'icons/mob/human.dmi', "icon_state" = "[H.dna.species.id]_[g]")
|
||||
|
||||
@@ -502,7 +502,7 @@
|
||||
var/obj/item/stack/sheet/metal/M = new /obj/item/stack/sheet/metal(target.loc)
|
||||
M.amount = 5
|
||||
for(var/obj/item/I in target.component_parts)
|
||||
I.loc = M.loc
|
||||
I.forceMove(M.drop_location())
|
||||
var/obj/effect/temp_visual/swarmer/disintegration/N = new /obj/effect/temp_visual/swarmer/disintegration(get_turf(target))
|
||||
N.pixel_x = target.pixel_x
|
||||
N.pixel_y = target.pixel_y
|
||||
@@ -511,7 +511,7 @@
|
||||
if(istype(target, /obj/machinery/computer))
|
||||
var/obj/machinery/computer/C = target
|
||||
if(C.circuit)
|
||||
C.circuit.loc = M.loc
|
||||
C.circuit.forceMove(M.drop_location())
|
||||
qdel(target)
|
||||
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
/mob/living/simple_animal/hostile/morph/proc/eat(atom/movable/A)
|
||||
if(A && A.loc != src)
|
||||
visible_message("<span class='warning'>[src] swallows [A] whole!</span>")
|
||||
A.loc = src
|
||||
A.forceMove(src)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
@@ -153,7 +153,7 @@
|
||||
|
||||
/mob/living/simple_animal/hostile/morph/proc/barf_contents()
|
||||
for(var/atom/movable/AM in src)
|
||||
AM.loc = loc
|
||||
AM.forceMove(loc)
|
||||
if(prob(90))
|
||||
step(AM, pick(GLOB.alldirs))
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
P.info = "The nuclear authorization code is: <b>[nuke_code]</b>"
|
||||
P.name = "nuclear bomb code"
|
||||
var/mob/living/carbon/human/H = synd_mind.current
|
||||
P.loc = H.loc
|
||||
P.forceMove(H.drop_location())
|
||||
H.put_in_hands_or_del(P)
|
||||
H.update_icons()
|
||||
else
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
U.hidden_uplink.owner = "[user.key]"
|
||||
U.hidden_uplink.telecrystals = CHALLENGE_TELECRYSTALS
|
||||
U.hidden_uplink.set_gamemode(/datum/game_mode/nuclear)
|
||||
config.shuttle_refuel_delay = max(config.shuttle_refuel_delay, CHALLENGE_SHUTTLE_DELAY)
|
||||
CONFIG_SET(number/shuttle_refuel_delay, max(CONFIG_GET(number/shuttle_refuel_delay), CHALLENGE_SHUTTLE_DELAY))
|
||||
SSblackbox.set_val("nuclear_challenge_mode",1)
|
||||
qdel(src)
|
||||
|
||||
|
||||
@@ -506,24 +506,31 @@ GLOBAL_LIST_EMPTY(possible_items_special)
|
||||
explanation_text = "Download [target_amount] research level\s."
|
||||
return target_amount
|
||||
|
||||
/datum/objective/download/check_completion()//NINJACODE.
|
||||
var/current_amount = 0
|
||||
/datum/objective/download/check_completion()
|
||||
var/list/current_tech = list()
|
||||
var/list/datum/mind/owners = get_owners()
|
||||
for(var/datum/mind/M in owners)
|
||||
if(!ishuman(owner.current))
|
||||
continue
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
if(!H || H.stat == DEAD || !istype(H.wear_suit, /obj/item/clothing/suit/space/space_ninja))
|
||||
continue
|
||||
var/obj/item/clothing/suit/space/space_ninja/SN = H.wear_suit
|
||||
if(!SN.s_initialized)
|
||||
continue
|
||||
for(var/datum/tech/current_data in SN.stored_research)
|
||||
if(current_data.level)
|
||||
current_amount += (current_data.level-1)
|
||||
return current_amount >= target_amount
|
||||
|
||||
|
||||
for(var/datum/mind/owner in owners)
|
||||
if(ismob(owner.current))
|
||||
var/mob/M = owner.current //Yeah if you get morphed and you eat a quantum tech disk with the RD's latest backup good on you soldier.
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(H && (H.stat != DEAD) && istype(H.wear_suit, /obj/item/clothing/suit/space/space_ninja))
|
||||
var/obj/item/clothing/suit/space/space_ninja/S = H.wear_suit
|
||||
for(var/datum/tech/T in S.stored_research)
|
||||
current_tech[T.id] = T.level? T.level : 0
|
||||
var/list/otherwise = M.GetAllContents()
|
||||
for(var/obj/item/disk/tech_disk/TD in otherwise)
|
||||
for(var/datum/tech/T in TD.tech_stored)
|
||||
if(!T.id || !T.level)
|
||||
continue
|
||||
else if(!current_tech[T.id])
|
||||
current_tech[T.id] = T.level
|
||||
else if(T.level > current_tech[T.id])
|
||||
current_tech[T.id] = T.level
|
||||
var/total = 0
|
||||
for(var/i in current_tech)
|
||||
total += current_tech[i]
|
||||
return total >= target_amount
|
||||
|
||||
/datum/objective/capture
|
||||
|
||||
@@ -586,7 +593,7 @@ GLOBAL_LIST_EMPTY(possible_items_special)
|
||||
for(var/datum/mind/M in owners)
|
||||
if(!owner || !owner.changeling || !owner.changeling.stored_profiles)
|
||||
continue
|
||||
absorbedcount += M.changeling.absorbedcount
|
||||
absorbedcount += M.changeling.absorbedcount
|
||||
return absorbedcount >= target_amount
|
||||
|
||||
|
||||
|
||||
@@ -44,10 +44,10 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/datum/game_mode/revolution/pre_setup()
|
||||
|
||||
if(config.protect_roles_from_antagonist)
|
||||
if(CONFIG_GET(flag/protect_roles_from_antagonist))
|
||||
restricted_jobs += protected_jobs
|
||||
|
||||
if(config.protect_assistant_from_antagonist)
|
||||
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
|
||||
restricted_jobs += "Assistant"
|
||||
|
||||
for (var/i=1 to max_headrevs)
|
||||
@@ -230,7 +230,7 @@
|
||||
//Checks if the round is over//
|
||||
///////////////////////////////
|
||||
/datum/game_mode/revolution/check_finished()
|
||||
if(config.continuous["revolution"])
|
||||
if(CONFIG_GET(keyed_flag_list/continuous)["revolution"])
|
||||
if(finished)
|
||||
SSshuttle.clearHostileEnvironment(src)
|
||||
return ..()
|
||||
|
||||
@@ -1,303 +1,303 @@
|
||||
|
||||
|
||||
GLOBAL_VAR_INIT(hsboxspawn, TRUE)
|
||||
|
||||
/mob
|
||||
var/datum/hSB/sandbox = null
|
||||
/mob/proc/CanBuild()
|
||||
sandbox = new/datum/hSB
|
||||
sandbox.owner = src.ckey
|
||||
if(src.client.holder)
|
||||
sandbox.admin = 1
|
||||
verbs += new/mob/proc/sandbox_panel
|
||||
/mob/proc/sandbox_panel()
|
||||
set name = "Sandbox Panel"
|
||||
if(sandbox)
|
||||
sandbox.update()
|
||||
|
||||
/datum/hSB
|
||||
var/owner = null
|
||||
var/admin = 0
|
||||
|
||||
|
||||
|
||||
GLOBAL_VAR_INIT(hsboxspawn, TRUE)
|
||||
|
||||
/mob
|
||||
var/datum/hSB/sandbox = null
|
||||
/mob/proc/CanBuild()
|
||||
sandbox = new/datum/hSB
|
||||
sandbox.owner = src.ckey
|
||||
if(src.client.holder)
|
||||
sandbox.admin = 1
|
||||
verbs += new/mob/proc/sandbox_panel
|
||||
/mob/proc/sandbox_panel()
|
||||
set name = "Sandbox Panel"
|
||||
if(sandbox)
|
||||
sandbox.update()
|
||||
|
||||
/datum/hSB
|
||||
var/owner = null
|
||||
var/admin = 0
|
||||
|
||||
var/static/clothinfo = null
|
||||
var/static/reaginfo = null
|
||||
var/static/objinfo = null
|
||||
var/canisterinfo = null
|
||||
var/hsbinfo = null
|
||||
//items that shouldn't spawn on the floor because they would bug or act weird
|
||||
var/global/list/spawn_forbidden = list(
|
||||
/obj/item/tk_grab, /obj/item/implant, // not implanter, the actual thing that is inside you
|
||||
var/canisterinfo = null
|
||||
var/hsbinfo = null
|
||||
//items that shouldn't spawn on the floor because they would bug or act weird
|
||||
var/global/list/spawn_forbidden = list(
|
||||
/obj/item/tk_grab, /obj/item/implant, // not implanter, the actual thing that is inside you
|
||||
/obj/item/assembly, /obj/item/device/onetankbomb, /obj/item/radio, /obj/item/device/pda/ai,
|
||||
/obj/item/device/uplink, /obj/item/smallDelivery, /obj/item/projectile,
|
||||
/obj/item/device/uplink, /obj/item/smallDelivery, /obj/item/projectile,
|
||||
/obj/item/borg/sight, /obj/item/borg/stun, /obj/item/robot_module)
|
||||
|
||||
/datum/hSB/proc/update()
|
||||
var/global/list/hrefs = list(
|
||||
"Space Gear",
|
||||
"Suit Up (Space Travel Gear)" = "hsbsuit",
|
||||
"Spawn Gas Mask" = "hsbspawn&path=[/obj/item/clothing/mask/gas]",
|
||||
"Spawn Emergency Air Tank" = "hsbspawn&path=[/obj/item/tank/internals/emergency_oxygen/double]",
|
||||
|
||||
"Standard Tools",
|
||||
"Spawn Flashlight" = "hsbspawn&path=[/obj/item/device/flashlight]",
|
||||
"Spawn Toolbox" = "hsbspawn&path=[/obj/item/storage/toolbox/mechanical]",
|
||||
"Spawn Light Replacer" = "hsbspawn&path=[/obj/item/device/lightreplacer]",
|
||||
"Spawn Medical Kit" = "hsbspawn&path=[/obj/item/storage/firstaid/regular]",
|
||||
"Spawn All-Access ID" = "hsbaaid",
|
||||
|
||||
"Building Supplies",
|
||||
"Spawn 50 Wood" = "hsbwood",
|
||||
"Spawn 50 Metal" = "hsbmetal",
|
||||
"Spawn 50 Plasteel" = "hsbplasteel",
|
||||
"Spawn 50 Reinforced Glass" = "hsbrglass",
|
||||
"Spawn 50 Glass" = "hsbglass",
|
||||
"Spawn Full Cable Coil" = "hsbspawn&path=[/obj/item/stack/cable_coil]",
|
||||
"Spawn Hyper Capacity Power Cell" = "hsbspawn&path=[/obj/item/stock_parts/cell/hyper]",
|
||||
"Spawn Inf. Capacity Power Cell" = "hsbspawn&path=[/obj/item/stock_parts/cell/infinite]",
|
||||
"Spawn Rapid Construction Device" = "hsbrcd",
|
||||
"Spawn RCD Ammo" = "hsb_safespawn&path=[/obj/item/rcd_ammo]",
|
||||
"Spawn Airlock" = "hsbairlock",
|
||||
|
||||
"Miscellaneous",
|
||||
"Spawn Air Scrubber" = "hsbscrubber",
|
||||
"Spawn Welding Fuel Tank" = "hsbspawn&path=[/obj/structure/reagent_dispensers/fueltank]",
|
||||
"Spawn Water Tank" = "hsbspawn&path=[/obj/structure/reagent_dispensers/watertank]",
|
||||
|
||||
"Bots",
|
||||
"Spawn Cleanbot" = "hsbspawn&path=[/mob/living/simple_animal/bot/cleanbot]",
|
||||
"Spawn Floorbot" = "hsbspawn&path=[/mob/living/simple_animal/bot/floorbot]",
|
||||
"Spawn Medbot" = "hsbspawn&path=[/mob/living/simple_animal/bot/medbot]",
|
||||
|
||||
"Canisters",
|
||||
"Spawn O2 Canister" = "hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/oxygen]",
|
||||
"Spawn Air Canister" = "hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/air]")
|
||||
|
||||
|
||||
if(!hsbinfo)
|
||||
hsbinfo = "<center><b>Sandbox Panel</b></center><hr>"
|
||||
if(admin)
|
||||
hsbinfo += "<b>Administration</b><br>"
|
||||
hsbinfo += "- <a href='?src=\ref[src];hsb=hsbtobj'>Toggle Object Spawning</a><br>"
|
||||
hsbinfo += "- <a href='?src=\ref[src];hsb=hsbtac'>Toggle Item Spawn Panel Auto-close</a><br>"
|
||||
hsbinfo += "<b>Canister Spawning</b><br>"
|
||||
hsbinfo += "- <a href='?src=\ref[src];hsb=hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/toxins]'>Spawn Plasma Canister</a><br>"
|
||||
hsbinfo += "- <a href='?src=\ref[src];hsb=hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/carbon_dioxide]'>Spawn CO2 Canister</a><br>"
|
||||
hsbinfo += "- <a href='?src=\ref[src];hsb=hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/nitrogen]'>Spawn Nitrogen Canister</a><br>"
|
||||
hsbinfo += "- <a href='?src=\ref[src];hsb=hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/nitrous_oxide]'>Spawn N2O Canister</a><hr>"
|
||||
else
|
||||
hsbinfo += "<i>Some item spawning may be disabled by the administrators.</i><br>"
|
||||
hsbinfo += "<i>Only administrators may spawn dangerous canisters.</i><br>"
|
||||
for(var/T in hrefs)
|
||||
var/href = hrefs[T]
|
||||
if(href)
|
||||
hsbinfo += "- <a href='?\ref[src];hsb=[hrefs[T]]'>[T]</a><br>"
|
||||
else
|
||||
hsbinfo += "<br><b>[T]</b><br>"
|
||||
hsbinfo += "<hr>"
|
||||
hsbinfo += "- <a href='?\ref[src];hsb=hsbcloth'>Spawn Clothing...</a><br>"
|
||||
hsbinfo += "- <a href='?\ref[src];hsb=hsbreag'>Spawn Reagent Container...</a><br>"
|
||||
hsbinfo += "- <a href='?\ref[src];hsb=hsbobj'>Spawn Other Item...</a><br><br>"
|
||||
|
||||
usr << browse(hsbinfo, "window=hsbpanel")
|
||||
|
||||
/datum/hSB/Topic(href, href_list)
|
||||
if(!usr || !src || !(src.owner == usr.ckey))
|
||||
if(usr)
|
||||
usr << browse(null,"window=sandbox")
|
||||
return
|
||||
|
||||
if(href_list["hsb"])
|
||||
switch(href_list["hsb"])
|
||||
//
|
||||
// Admin: toggle spawning
|
||||
//
|
||||
if("hsbtobj")
|
||||
if(!admin) return
|
||||
if(GLOB.hsboxspawn)
|
||||
to_chat(world, "<span class='boldannounce'>Sandbox:</span> <b>\black[usr.key] has disabled object spawning!</b>")
|
||||
GLOB.hsboxspawn = FALSE
|
||||
return
|
||||
else
|
||||
to_chat(world, "<span class='boldnotice'>Sandbox:</span> <b>\black[usr.key] has enabled object spawning!</b>")
|
||||
GLOB.hsboxspawn = TRUE
|
||||
return
|
||||
//
|
||||
// Admin: Toggle auto-close
|
||||
//
|
||||
if("hsbtac")
|
||||
if(!admin) return
|
||||
if(config.sandbox_autoclose)
|
||||
to_chat(world, "<span class='boldnotice'>Sandbox:</span> <b>\black [usr.key] has removed the object spawn limiter.</b>")
|
||||
config.sandbox_autoclose = FALSE
|
||||
else
|
||||
to_chat(world, "<span class='danger'>Sandbox:</span> <b>\black [usr.key] has added a limiter to object spawning. The window will now auto-close after use.</b>")
|
||||
config.sandbox_autoclose = TRUE
|
||||
return
|
||||
//
|
||||
// Spacesuit with full air jetpack set as internals
|
||||
//
|
||||
if("hsbsuit")
|
||||
var/mob/living/carbon/human/P = usr
|
||||
if(!istype(P)) return
|
||||
if(P.wear_suit)
|
||||
P.wear_suit.loc = P.loc
|
||||
P.wear_suit.layer = initial(P.wear_suit.layer)
|
||||
P.wear_suit.plane = initial(P.wear_suit.plane)
|
||||
P.wear_suit = null
|
||||
P.wear_suit = new/obj/item/clothing/suit/space(P)
|
||||
P.wear_suit.layer = ABOVE_HUD_LAYER
|
||||
P.wear_suit.plane = ABOVE_HUD_PLANE
|
||||
P.update_inv_wear_suit()
|
||||
if(P.head)
|
||||
P.head.loc = P.loc
|
||||
P.head.layer = initial(P.head.layer)
|
||||
P.head.plane = initial(P.head.plane)
|
||||
P.head = null
|
||||
P.head = new/obj/item/clothing/head/helmet/space(P)
|
||||
P.head.layer = ABOVE_HUD_LAYER
|
||||
P.head.plane = ABOVE_HUD_PLANE
|
||||
P.update_inv_head()
|
||||
if(P.wear_mask)
|
||||
P.wear_mask.loc = P.loc
|
||||
P.wear_mask.layer = initial(P.wear_mask.layer)
|
||||
P.wear_mask.plane = initial(P.wear_mask.plane)
|
||||
P.wear_mask = null
|
||||
P.wear_mask = new/obj/item/clothing/mask/gas(P)
|
||||
P.wear_mask.layer = ABOVE_HUD_LAYER
|
||||
P.wear_mask.plane = ABOVE_HUD_PLANE
|
||||
P.update_inv_wear_mask()
|
||||
if(P.back)
|
||||
P.back.loc = P.loc
|
||||
P.back.layer = initial(P.back.layer)
|
||||
P.back.plane = initial(P.back.plane)
|
||||
P.back = null
|
||||
P.back = new/obj/item/tank/jetpack/oxygen(P)
|
||||
P.back.layer = ABOVE_HUD_LAYER
|
||||
P.back.plane = ABOVE_HUD_PLANE
|
||||
P.update_inv_back()
|
||||
P.internal = P.back
|
||||
P.update_internals_hud_icon(1)
|
||||
|
||||
if("hsbscrubber") // This is beyond its normal capability but this is sandbox and you spawned one, I assume you need it
|
||||
var/obj/hsb = new/obj/machinery/portable_atmospherics/scrubber{volume_rate=50*ONE_ATMOSPHERE;on=1}(usr.loc)
|
||||
hsb.update_icon() // hackish but it wasn't meant to be spawned I guess?
|
||||
|
||||
//
|
||||
// Stacked Materials
|
||||
//
|
||||
|
||||
if("hsbrglass")
|
||||
new/obj/item/stack/sheet/rglass{amount=50}(usr.loc)
|
||||
|
||||
if("hsbmetal")
|
||||
new/obj/item/stack/sheet/metal{amount=50}(usr.loc)
|
||||
|
||||
if("hsbplasteel")
|
||||
new/obj/item/stack/sheet/plasteel{amount=50}(usr.loc)
|
||||
|
||||
if("hsbglass")
|
||||
new/obj/item/stack/sheet/glass{amount=50}(usr.loc)
|
||||
|
||||
if("hsbwood")
|
||||
new/obj/item/stack/sheet/mineral/wood{amount=50}(usr.loc)
|
||||
|
||||
//
|
||||
// All access ID
|
||||
//
|
||||
if("hsbaaid")
|
||||
var/obj/item/card/id/gold/ID = new(usr.loc)
|
||||
ID.registered_name = usr.real_name
|
||||
ID.assignment = "Sandbox"
|
||||
ID.access = get_all_accesses()
|
||||
ID.update_label()
|
||||
|
||||
//
|
||||
// RCD - starts with full clip
|
||||
// Spawn check due to grief potential (destroying floors, walls, etc)
|
||||
//
|
||||
if("hsbrcd")
|
||||
if(!GLOB.hsboxspawn) return
|
||||
|
||||
new/obj/item/construction/rcd/combat(usr.loc)
|
||||
|
||||
//
|
||||
// New sandbox airlock maker
|
||||
//
|
||||
if("hsbairlock")
|
||||
new /datum/airlock_maker(usr.loc)
|
||||
|
||||
//
|
||||
// Object spawn window
|
||||
//
|
||||
|
||||
// Clothing
|
||||
if("hsbcloth")
|
||||
if(!GLOB.hsboxspawn) return
|
||||
|
||||
if(!clothinfo)
|
||||
clothinfo = "<b>Clothing</b> <a href='?\ref[src];hsb=hsbreag'>(Reagent Containers)</a> <a href='?\ref[src];hsb=hsbobj'>(Other Items)</a><hr><br>"
|
||||
var/list/all_items = subtypesof(/obj/item/clothing)
|
||||
for(var/typekey in spawn_forbidden)
|
||||
all_items -= typesof(typekey)
|
||||
for(var/O in reverseRange(all_items))
|
||||
clothinfo += "<a href='?src=\ref[src];hsb=hsb_safespawn&path=[O]'>[O]</a><br>"
|
||||
|
||||
usr << browse(clothinfo,"window=sandbox")
|
||||
|
||||
// Reagent containers
|
||||
if("hsbreag")
|
||||
if(!GLOB.hsboxspawn) return
|
||||
|
||||
if(!reaginfo)
|
||||
reaginfo = "<b>Reagent Containers</b> <a href='?\ref[src];hsb=hsbcloth'>(Clothing)</a> <a href='?\ref[src];hsb=hsbobj'>(Other Items)</a><hr><br>"
|
||||
var/list/all_items = subtypesof(/obj/item/reagent_containers)
|
||||
for(var/typekey in spawn_forbidden)
|
||||
all_items -= typesof(typekey)
|
||||
for(var/O in reverseRange(all_items))
|
||||
reaginfo += "<a href='?src=\ref[src];hsb=hsb_safespawn&path=[O]'>[O]</a><br>"
|
||||
|
||||
usr << browse(reaginfo,"window=sandbox")
|
||||
|
||||
// Other items
|
||||
if("hsbobj")
|
||||
if(!GLOB.hsboxspawn) return
|
||||
|
||||
if(!objinfo)
|
||||
objinfo = "<b>Other Items</b> <a href='?\ref[src];hsb=hsbcloth'>(Clothing)</a> <a href='?\ref[src];hsb=hsbreag'>(Reagent Containers)</a><hr><br>"
|
||||
var/list/all_items = subtypesof(/obj/item/) - typesof(/obj/item/clothing) - typesof(/obj/item/reagent_containers)
|
||||
for(var/typekey in spawn_forbidden)
|
||||
all_items -= typesof(typekey)
|
||||
|
||||
for(var/O in reverseRange(all_items))
|
||||
objinfo += "<a href='?src=\ref[src];hsb=hsb_safespawn&path=[O]'>[O]</a><br>"
|
||||
|
||||
usr << browse(objinfo,"window=sandbox")
|
||||
|
||||
//
|
||||
// Safespawn checks to see if spawning is disabled.
|
||||
//
|
||||
if("hsb_safespawn")
|
||||
if(!GLOB.hsboxspawn)
|
||||
usr << browse(null,"window=sandbox")
|
||||
return
|
||||
|
||||
var/typepath = text2path(href_list["path"])
|
||||
if(!typepath)
|
||||
to_chat(usr, "Bad path: \"[href_list["path"]]\"")
|
||||
return
|
||||
new typepath(usr.loc)
|
||||
|
||||
if(config.sandbox_autoclose)
|
||||
usr << browse(null,"window=sandbox")
|
||||
//
|
||||
// For everything else in the href list
|
||||
//
|
||||
if("hsbspawn")
|
||||
var/typepath = text2path(href_list["path"])
|
||||
if(!typepath)
|
||||
to_chat(usr, "Bad path: \"[href_list["path"]]\"")
|
||||
return
|
||||
new typepath(usr.loc)
|
||||
|
||||
if(config.sandbox_autoclose)
|
||||
usr << browse(null,"window=sandbox")
|
||||
|
||||
/datum/hSB/proc/update()
|
||||
var/global/list/hrefs = list(
|
||||
"Space Gear",
|
||||
"Suit Up (Space Travel Gear)" = "hsbsuit",
|
||||
"Spawn Gas Mask" = "hsbspawn&path=[/obj/item/clothing/mask/gas]",
|
||||
"Spawn Emergency Air Tank" = "hsbspawn&path=[/obj/item/tank/internals/emergency_oxygen/double]",
|
||||
|
||||
"Standard Tools",
|
||||
"Spawn Flashlight" = "hsbspawn&path=[/obj/item/device/flashlight]",
|
||||
"Spawn Toolbox" = "hsbspawn&path=[/obj/item/storage/toolbox/mechanical]",
|
||||
"Spawn Light Replacer" = "hsbspawn&path=[/obj/item/device/lightreplacer]",
|
||||
"Spawn Medical Kit" = "hsbspawn&path=[/obj/item/storage/firstaid/regular]",
|
||||
"Spawn All-Access ID" = "hsbaaid",
|
||||
|
||||
"Building Supplies",
|
||||
"Spawn 50 Wood" = "hsbwood",
|
||||
"Spawn 50 Metal" = "hsbmetal",
|
||||
"Spawn 50 Plasteel" = "hsbplasteel",
|
||||
"Spawn 50 Reinforced Glass" = "hsbrglass",
|
||||
"Spawn 50 Glass" = "hsbglass",
|
||||
"Spawn Full Cable Coil" = "hsbspawn&path=[/obj/item/stack/cable_coil]",
|
||||
"Spawn Hyper Capacity Power Cell" = "hsbspawn&path=[/obj/item/stock_parts/cell/hyper]",
|
||||
"Spawn Inf. Capacity Power Cell" = "hsbspawn&path=[/obj/item/stock_parts/cell/infinite]",
|
||||
"Spawn Rapid Construction Device" = "hsbrcd",
|
||||
"Spawn RCD Ammo" = "hsb_safespawn&path=[/obj/item/rcd_ammo]",
|
||||
"Spawn Airlock" = "hsbairlock",
|
||||
|
||||
"Miscellaneous",
|
||||
"Spawn Air Scrubber" = "hsbscrubber",
|
||||
"Spawn Welding Fuel Tank" = "hsbspawn&path=[/obj/structure/reagent_dispensers/fueltank]",
|
||||
"Spawn Water Tank" = "hsbspawn&path=[/obj/structure/reagent_dispensers/watertank]",
|
||||
|
||||
"Bots",
|
||||
"Spawn Cleanbot" = "hsbspawn&path=[/mob/living/simple_animal/bot/cleanbot]",
|
||||
"Spawn Floorbot" = "hsbspawn&path=[/mob/living/simple_animal/bot/floorbot]",
|
||||
"Spawn Medbot" = "hsbspawn&path=[/mob/living/simple_animal/bot/medbot]",
|
||||
|
||||
"Canisters",
|
||||
"Spawn O2 Canister" = "hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/oxygen]",
|
||||
"Spawn Air Canister" = "hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/air]")
|
||||
|
||||
|
||||
if(!hsbinfo)
|
||||
hsbinfo = "<center><b>Sandbox Panel</b></center><hr>"
|
||||
if(admin)
|
||||
hsbinfo += "<b>Administration</b><br>"
|
||||
hsbinfo += "- <a href='?src=\ref[src];hsb=hsbtobj'>Toggle Object Spawning</a><br>"
|
||||
hsbinfo += "- <a href='?src=\ref[src];hsb=hsbtac'>Toggle Item Spawn Panel Auto-close</a><br>"
|
||||
hsbinfo += "<b>Canister Spawning</b><br>"
|
||||
hsbinfo += "- <a href='?src=\ref[src];hsb=hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/toxins]'>Spawn Plasma Canister</a><br>"
|
||||
hsbinfo += "- <a href='?src=\ref[src];hsb=hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/carbon_dioxide]'>Spawn CO2 Canister</a><br>"
|
||||
hsbinfo += "- <a href='?src=\ref[src];hsb=hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/nitrogen]'>Spawn Nitrogen Canister</a><br>"
|
||||
hsbinfo += "- <a href='?src=\ref[src];hsb=hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/nitrous_oxide]'>Spawn N2O Canister</a><hr>"
|
||||
else
|
||||
hsbinfo += "<i>Some item spawning may be disabled by the administrators.</i><br>"
|
||||
hsbinfo += "<i>Only administrators may spawn dangerous canisters.</i><br>"
|
||||
for(var/T in hrefs)
|
||||
var/href = hrefs[T]
|
||||
if(href)
|
||||
hsbinfo += "- <a href='?\ref[src];hsb=[hrefs[T]]'>[T]</a><br>"
|
||||
else
|
||||
hsbinfo += "<br><b>[T]</b><br>"
|
||||
hsbinfo += "<hr>"
|
||||
hsbinfo += "- <a href='?\ref[src];hsb=hsbcloth'>Spawn Clothing...</a><br>"
|
||||
hsbinfo += "- <a href='?\ref[src];hsb=hsbreag'>Spawn Reagent Container...</a><br>"
|
||||
hsbinfo += "- <a href='?\ref[src];hsb=hsbobj'>Spawn Other Item...</a><br><br>"
|
||||
|
||||
usr << browse(hsbinfo, "window=hsbpanel")
|
||||
|
||||
/datum/hSB/Topic(href, href_list)
|
||||
if(!usr || !src || !(src.owner == usr.ckey))
|
||||
if(usr)
|
||||
usr << browse(null,"window=sandbox")
|
||||
return
|
||||
|
||||
if(href_list["hsb"])
|
||||
switch(href_list["hsb"])
|
||||
//
|
||||
// Admin: toggle spawning
|
||||
//
|
||||
if("hsbtobj")
|
||||
if(!admin) return
|
||||
if(GLOB.hsboxspawn)
|
||||
to_chat(world, "<span class='boldannounce'>Sandbox:</span> <b>\black[usr.key] has disabled object spawning!</b>")
|
||||
GLOB.hsboxspawn = FALSE
|
||||
return
|
||||
else
|
||||
to_chat(world, "<span class='boldnotice'>Sandbox:</span> <b>\black[usr.key] has enabled object spawning!</b>")
|
||||
GLOB.hsboxspawn = TRUE
|
||||
return
|
||||
//
|
||||
// Admin: Toggle auto-close
|
||||
//
|
||||
if("hsbtac")
|
||||
if(!admin) return
|
||||
var/sbac = CONFIG_GET(flag/sandbox_autoclose)
|
||||
if(sbac)
|
||||
to_chat(world, "<span class='boldnotice'>Sandbox:</span> <b>\black [usr.key] has removed the object spawn limiter.</b>")
|
||||
else
|
||||
to_chat(world, "<span class='danger'>Sandbox:</span> <b>\black [usr.key] has added a limiter to object spawning. The window will now auto-close after use.</b>")
|
||||
CONFIG_SET(flag/sandbox_autoclose, !sbac)
|
||||
return
|
||||
//
|
||||
// Spacesuit with full air jetpack set as internals
|
||||
//
|
||||
if("hsbsuit")
|
||||
var/mob/living/carbon/human/P = usr
|
||||
if(!istype(P)) return
|
||||
if(P.wear_suit)
|
||||
P.wear_suit.forceMove(P.drop_location())
|
||||
P.wear_suit.layer = initial(P.wear_suit.layer)
|
||||
P.wear_suit.plane = initial(P.wear_suit.plane)
|
||||
P.wear_suit = null
|
||||
P.wear_suit = new/obj/item/clothing/suit/space(P)
|
||||
P.wear_suit.layer = ABOVE_HUD_LAYER
|
||||
P.wear_suit.plane = ABOVE_HUD_PLANE
|
||||
P.update_inv_wear_suit()
|
||||
if(P.head)
|
||||
P.head.forceMove(P.drop_location())
|
||||
P.head.layer = initial(P.head.layer)
|
||||
P.head.plane = initial(P.head.plane)
|
||||
P.head = null
|
||||
P.head = new/obj/item/clothing/head/helmet/space(P)
|
||||
P.head.layer = ABOVE_HUD_LAYER
|
||||
P.head.plane = ABOVE_HUD_PLANE
|
||||
P.update_inv_head()
|
||||
if(P.wear_mask)
|
||||
P.wear_mask.forceMove(P.drop_location())
|
||||
P.wear_mask.layer = initial(P.wear_mask.layer)
|
||||
P.wear_mask.plane = initial(P.wear_mask.plane)
|
||||
P.wear_mask = null
|
||||
P.wear_mask = new/obj/item/clothing/mask/gas(P)
|
||||
P.wear_mask.layer = ABOVE_HUD_LAYER
|
||||
P.wear_mask.plane = ABOVE_HUD_PLANE
|
||||
P.update_inv_wear_mask()
|
||||
if(P.back)
|
||||
P.back.forceMove(P.drop_location())
|
||||
P.back.layer = initial(P.back.layer)
|
||||
P.back.plane = initial(P.back.plane)
|
||||
P.back = null
|
||||
P.back = new/obj/item/tank/jetpack/oxygen(P)
|
||||
P.back.layer = ABOVE_HUD_LAYER
|
||||
P.back.plane = ABOVE_HUD_PLANE
|
||||
P.update_inv_back()
|
||||
P.internal = P.back
|
||||
P.update_internals_hud_icon(1)
|
||||
|
||||
if("hsbscrubber") // This is beyond its normal capability but this is sandbox and you spawned one, I assume you need it
|
||||
var/obj/hsb = new/obj/machinery/portable_atmospherics/scrubber{volume_rate=50*ONE_ATMOSPHERE;on=1}(usr.loc)
|
||||
hsb.update_icon() // hackish but it wasn't meant to be spawned I guess?
|
||||
|
||||
//
|
||||
// Stacked Materials
|
||||
//
|
||||
|
||||
if("hsbrglass")
|
||||
new/obj/item/stack/sheet/rglass{amount=50}(usr.loc)
|
||||
|
||||
if("hsbmetal")
|
||||
new/obj/item/stack/sheet/metal{amount=50}(usr.loc)
|
||||
|
||||
if("hsbplasteel")
|
||||
new/obj/item/stack/sheet/plasteel{amount=50}(usr.loc)
|
||||
|
||||
if("hsbglass")
|
||||
new/obj/item/stack/sheet/glass{amount=50}(usr.loc)
|
||||
|
||||
if("hsbwood")
|
||||
new/obj/item/stack/sheet/mineral/wood{amount=50}(usr.loc)
|
||||
|
||||
//
|
||||
// All access ID
|
||||
//
|
||||
if("hsbaaid")
|
||||
var/obj/item/card/id/gold/ID = new(usr.loc)
|
||||
ID.registered_name = usr.real_name
|
||||
ID.assignment = "Sandbox"
|
||||
ID.access = get_all_accesses()
|
||||
ID.update_label()
|
||||
|
||||
//
|
||||
// RCD - starts with full clip
|
||||
// Spawn check due to grief potential (destroying floors, walls, etc)
|
||||
//
|
||||
if("hsbrcd")
|
||||
if(!GLOB.hsboxspawn) return
|
||||
|
||||
new/obj/item/construction/rcd/combat(usr.loc)
|
||||
|
||||
//
|
||||
// New sandbox airlock maker
|
||||
//
|
||||
if("hsbairlock")
|
||||
new /datum/airlock_maker(usr.loc)
|
||||
|
||||
//
|
||||
// Object spawn window
|
||||
//
|
||||
|
||||
// Clothing
|
||||
if("hsbcloth")
|
||||
if(!GLOB.hsboxspawn) return
|
||||
|
||||
if(!clothinfo)
|
||||
clothinfo = "<b>Clothing</b> <a href='?\ref[src];hsb=hsbreag'>(Reagent Containers)</a> <a href='?\ref[src];hsb=hsbobj'>(Other Items)</a><hr><br>"
|
||||
var/list/all_items = subtypesof(/obj/item/clothing)
|
||||
for(var/typekey in spawn_forbidden)
|
||||
all_items -= typesof(typekey)
|
||||
for(var/O in reverseRange(all_items))
|
||||
clothinfo += "<a href='?src=\ref[src];hsb=hsb_safespawn&path=[O]'>[O]</a><br>"
|
||||
|
||||
usr << browse(clothinfo,"window=sandbox")
|
||||
|
||||
// Reagent containers
|
||||
if("hsbreag")
|
||||
if(!GLOB.hsboxspawn) return
|
||||
|
||||
if(!reaginfo)
|
||||
reaginfo = "<b>Reagent Containers</b> <a href='?\ref[src];hsb=hsbcloth'>(Clothing)</a> <a href='?\ref[src];hsb=hsbobj'>(Other Items)</a><hr><br>"
|
||||
var/list/all_items = subtypesof(/obj/item/reagent_containers)
|
||||
for(var/typekey in spawn_forbidden)
|
||||
all_items -= typesof(typekey)
|
||||
for(var/O in reverseRange(all_items))
|
||||
reaginfo += "<a href='?src=\ref[src];hsb=hsb_safespawn&path=[O]'>[O]</a><br>"
|
||||
|
||||
usr << browse(reaginfo,"window=sandbox")
|
||||
|
||||
// Other items
|
||||
if("hsbobj")
|
||||
if(!GLOB.hsboxspawn) return
|
||||
|
||||
if(!objinfo)
|
||||
objinfo = "<b>Other Items</b> <a href='?\ref[src];hsb=hsbcloth'>(Clothing)</a> <a href='?\ref[src];hsb=hsbreag'>(Reagent Containers)</a><hr><br>"
|
||||
var/list/all_items = subtypesof(/obj/item/) - typesof(/obj/item/clothing) - typesof(/obj/item/reagent_containers)
|
||||
for(var/typekey in spawn_forbidden)
|
||||
all_items -= typesof(typekey)
|
||||
|
||||
for(var/O in reverseRange(all_items))
|
||||
objinfo += "<a href='?src=\ref[src];hsb=hsb_safespawn&path=[O]'>[O]</a><br>"
|
||||
|
||||
usr << browse(objinfo,"window=sandbox")
|
||||
|
||||
//
|
||||
// Safespawn checks to see if spawning is disabled.
|
||||
//
|
||||
if("hsb_safespawn")
|
||||
if(!GLOB.hsboxspawn)
|
||||
usr << browse(null,"window=sandbox")
|
||||
return
|
||||
|
||||
var/typepath = text2path(href_list["path"])
|
||||
if(!typepath)
|
||||
to_chat(usr, "Bad path: \"[href_list["path"]]\"")
|
||||
return
|
||||
new typepath(usr.loc)
|
||||
|
||||
if(CONFIG_GET(flag/sandbox_autoclose))
|
||||
usr << browse(null,"window=sandbox")
|
||||
//
|
||||
// For everything else in the href list
|
||||
//
|
||||
if("hsbspawn")
|
||||
var/typepath = text2path(href_list["path"])
|
||||
if(!typepath)
|
||||
to_chat(usr, "Bad path: \"[href_list["path"]]\"")
|
||||
return
|
||||
new typepath(usr.loc)
|
||||
|
||||
if(CONFIG_GET(flag/sandbox_autoclose))
|
||||
usr << browse(null,"window=sandbox")
|
||||
|
||||
@@ -31,16 +31,17 @@
|
||||
|
||||
/datum/game_mode/traitor/pre_setup()
|
||||
|
||||
if(config.protect_roles_from_antagonist)
|
||||
if(CONFIG_GET(flag/protect_roles_from_antagonist))
|
||||
restricted_jobs += protected_jobs
|
||||
|
||||
if(config.protect_assistant_from_antagonist)
|
||||
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
|
||||
restricted_jobs += "Assistant"
|
||||
|
||||
var/num_traitors = 1
|
||||
|
||||
if(config.traitor_scaling_coeff)
|
||||
num_traitors = max(1, min( round(num_players()/(config.traitor_scaling_coeff*2))+ 2 + num_modifier, round(num_players()/(config.traitor_scaling_coeff)) + num_modifier ))
|
||||
var/tsc = CONFIG_GET(number/traitor_scaling_coeff)
|
||||
if(tsc)
|
||||
num_traitors = max(1, min(round(num_players() / (tsc * 2)) + 2 + num_modifier, round(num_players() / tsc) + num_modifier))
|
||||
else
|
||||
num_traitors = max(1, min(num_players(), traitors_possible))
|
||||
|
||||
@@ -68,10 +69,11 @@
|
||||
return 1
|
||||
|
||||
/datum/game_mode/traitor/make_antag_chance(mob/living/carbon/human/character) //Assigns traitor to latejoiners
|
||||
var/traitorcap = min(round(GLOB.joined_player_list.len / (config.traitor_scaling_coeff * 2)) + 2 + num_modifier, round(GLOB.joined_player_list.len/config.traitor_scaling_coeff) + num_modifier )
|
||||
var/tsc = CONFIG_GET(number/traitor_scaling_coeff)
|
||||
var/traitorcap = min(round(GLOB.joined_player_list.len / (tsc * 2)) + 2 + num_modifier, round(GLOB.joined_player_list.len / tsc) + num_modifier)
|
||||
if((SSticker.mode.traitors.len + pre_traitors.len) >= traitorcap) //Upper cap for number of latejoin antagonists
|
||||
return
|
||||
if((SSticker.mode.traitors.len + pre_traitors.len) <= (traitorcap - 2) || prob(100 / (config.traitor_scaling_coeff * 2)))
|
||||
if((SSticker.mode.traitors.len + pre_traitors.len) <= (traitorcap - 2) || prob(100 / (tsc * 2)))
|
||||
if(ROLE_TRAITOR in character.client.prefs.be_special)
|
||||
if(!jobban_isbanned(character, ROLE_TRAITOR) && !jobban_isbanned(character, "Syndicate"))
|
||||
if(age_check(character.client))
|
||||
|
||||
@@ -234,11 +234,10 @@
|
||||
|
||||
if(!link)
|
||||
if(I.loc == user && istype(I) && I.w_class <= WEIGHT_CLASS_SMALL)
|
||||
user.drop_item()
|
||||
I.loc = src
|
||||
link = I
|
||||
to_chat(user, "You attach [I] to the doll.")
|
||||
update_targets()
|
||||
if (user.transferItemToLoc(I,src))
|
||||
link = I
|
||||
to_chat(user, "You attach [I] to the doll.")
|
||||
update_targets()
|
||||
|
||||
/obj/item/voodoo/check_eye(mob/user)
|
||||
if(loc != user)
|
||||
|
||||
@@ -164,7 +164,7 @@
|
||||
if(contents.len)
|
||||
to_chat(user, "<span class='userdanger'>Capture failed!</span>: The soulstone is full! Free an existing soul to make room.")
|
||||
else
|
||||
T.loc = src //put shade in stone
|
||||
T.forceMove(src) //put shade in stone
|
||||
T.status_flags |= GODMODE
|
||||
T.canmove = 0
|
||||
T.health = T.maxHealth
|
||||
|
||||
@@ -478,7 +478,7 @@
|
||||
/datum/spellbook_entry/summon/guns/IsAvailible()
|
||||
if(!SSticker.mode) // In case spellbook is placed on map
|
||||
return 0
|
||||
return (!config.no_summon_guns)
|
||||
return !CONFIG_GET(flag/no_summon_guns)
|
||||
|
||||
/datum/spellbook_entry/summon/guns/Buy(mob/living/carbon/human/user,obj/item/spellbook/book)
|
||||
SSblackbox.add_details("wizard_spell_learned", name)
|
||||
@@ -495,7 +495,7 @@
|
||||
/datum/spellbook_entry/summon/magic/IsAvailible()
|
||||
if(!SSticker.mode) // In case spellbook is placed on map
|
||||
return 0
|
||||
return (!config.no_summon_magic)
|
||||
return !CONFIG_GET(flag/no_summon_magic)
|
||||
|
||||
/datum/spellbook_entry/summon/magic/Buy(mob/living/carbon/human/user,obj/item/spellbook/book)
|
||||
SSblackbox.add_details("wizard_spell_learned", name)
|
||||
@@ -513,7 +513,7 @@
|
||||
/datum/spellbook_entry/summon/events/IsAvailible()
|
||||
if(!SSticker.mode) // In case spellbook is placed on map
|
||||
return 0
|
||||
return (!config.no_summon_events)
|
||||
return !CONFIG_GET(flag/no_summon_events)
|
||||
|
||||
/datum/spellbook_entry/summon/events/Buy(mob/living/carbon/human/user,obj/item/spellbook/book)
|
||||
SSblackbox.add_details("wizard_spell_learned", name)
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
to_chat(wizard.current, "<span class='boldannounce'>A starting location for you could not be found, please report this bug!</span>")
|
||||
return 0
|
||||
for(var/datum/mind/wiz in wizards)
|
||||
wiz.current.loc = pick(GLOB.wizardstart)
|
||||
wiz.current.forceMove(pick(GLOB.wizardstart))
|
||||
|
||||
return 1
|
||||
|
||||
@@ -245,15 +245,6 @@
|
||||
|
||||
//OTHER PROCS
|
||||
|
||||
//To batch-remove wizard spells. Linked to mind.dm.
|
||||
/mob/proc/spellremove(mob/M)
|
||||
if(!mind)
|
||||
return
|
||||
for(var/X in src.mind.spell_list)
|
||||
var/obj/effect/proc_holder/spell/spell_to_remove = X
|
||||
qdel(spell_to_remove)
|
||||
mind.spell_list -= spell_to_remove
|
||||
|
||||
//returns whether the mob is a wizard (or apprentice)
|
||||
/proc/iswizard(mob/living/M)
|
||||
return istype(M) && M.mind && SSticker && SSticker.mode && ((M.mind in SSticker.mode.wizards) || (M.mind in SSticker.mode.apprentices))
|
||||
|
||||
@@ -44,10 +44,10 @@
|
||||
var/turf/T = loc
|
||||
Beacon = new /obj/item/device/radio/beacon
|
||||
Beacon.invisibility = INVISIBILITY_MAXIMUM
|
||||
Beacon.loc = T
|
||||
Beacon.forceMove(T)
|
||||
if(Beacon)
|
||||
if(Beacon.loc != loc)
|
||||
Beacon.loc = loc
|
||||
Beacon.forceMove(loc)
|
||||
|
||||
updateicon()
|
||||
|
||||
|
||||
@@ -429,7 +429,7 @@ Class Procs:
|
||||
W.handle_item_insertion(A, 1)
|
||||
component_parts -= A
|
||||
component_parts += B
|
||||
B.loc = null
|
||||
B.moveToNullspace()
|
||||
to_chat(user, "<span class='notice'>[A.name] replaced with [B.name].</span>")
|
||||
shouldplaysound = 1 //Only play the sound when parts are actually replaced!
|
||||
break
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
say("Station funds depleted. Halting siphon.")
|
||||
siphoning = FALSE
|
||||
else
|
||||
new /obj/item/stack/spacecash/c200(get_turf(src)) // will autostack
|
||||
new /obj/item/stack/spacecash/c200(drop_location()) // will autostack
|
||||
playsound(src.loc, 'sound/items/poster_being_created.ogg', 100, 1)
|
||||
SSshuttle.points -= 200
|
||||
if(next_warning < world.time && prob(15))
|
||||
|
||||
@@ -127,10 +127,10 @@
|
||||
if(panel_open)
|
||||
if(device || board)
|
||||
if(device)
|
||||
device.loc = get_turf(src)
|
||||
device.forceMove(drop_location())
|
||||
device = null
|
||||
if(board)
|
||||
board.loc = get_turf(src)
|
||||
board.forceMove(drop_location())
|
||||
req_access = list()
|
||||
req_one_access = list()
|
||||
board = null
|
||||
|
||||
@@ -246,7 +246,7 @@
|
||||
if(disassembled)
|
||||
if(!assembly)
|
||||
assembly = new()
|
||||
assembly.loc = src.loc
|
||||
assembly.forceMove(drop_location())
|
||||
assembly.state = 1
|
||||
assembly.setDir(dir)
|
||||
assembly = null
|
||||
|
||||
@@ -1,145 +1,145 @@
|
||||
/obj/item/wallframe/camera
|
||||
name = "camera assembly"
|
||||
desc = "The basic construction for Nanotrasen-Always-Watching-You cameras."
|
||||
icon = 'icons/obj/monitors.dmi'
|
||||
icon_state = "cameracase"
|
||||
materials = list(MAT_METAL=400, MAT_GLASS=250)
|
||||
result_path = /obj/structure/camera_assembly
|
||||
|
||||
|
||||
/obj/structure/camera_assembly
|
||||
name = "camera assembly"
|
||||
desc = "The basic construction for Nanotrasen-Always-Watching-You cameras."
|
||||
icon = 'icons/obj/monitors.dmi'
|
||||
icon_state = "camera1"
|
||||
max_integrity = 150
|
||||
// Motion, EMP-Proof, X-Ray
|
||||
var/static/list/possible_upgrades = typecacheof(list(/obj/item/device/assembly/prox_sensor, /obj/item/stack/sheet/mineral/plasma, /obj/item/device/analyzer))
|
||||
var/list/upgrades
|
||||
var/state = 1
|
||||
|
||||
/*
|
||||
1 = Wrenched in place
|
||||
2 = Welded in place
|
||||
3 = Wires attached to it (you can now attach/dettach upgrades)
|
||||
4 = Screwdriver panel closed and is fully built (you cannot attach upgrades)
|
||||
*/
|
||||
|
||||
/obj/structure/camera_assembly/Initialize(mapload, ndir, building)
|
||||
. = ..()
|
||||
if(building)
|
||||
setDir(ndir)
|
||||
upgrades = list()
|
||||
|
||||
/obj/structure/camera_assembly/Destroy()
|
||||
QDEL_LIST(upgrades)
|
||||
return ..()
|
||||
|
||||
/obj/structure/camera_assembly/attackby(obj/item/W, mob/living/user, params)
|
||||
switch(state)
|
||||
if(1)
|
||||
// State 1
|
||||
if(istype(W, /obj/item/weldingtool))
|
||||
if(weld(W, user))
|
||||
to_chat(user, "<span class='notice'>You weld the assembly securely into place.</span>")
|
||||
/obj/item/wallframe/camera
|
||||
name = "camera assembly"
|
||||
desc = "The basic construction for Nanotrasen-Always-Watching-You cameras."
|
||||
icon = 'icons/obj/monitors.dmi'
|
||||
icon_state = "cameracase"
|
||||
materials = list(MAT_METAL=400, MAT_GLASS=250)
|
||||
result_path = /obj/structure/camera_assembly
|
||||
|
||||
|
||||
/obj/structure/camera_assembly
|
||||
name = "camera assembly"
|
||||
desc = "The basic construction for Nanotrasen-Always-Watching-You cameras."
|
||||
icon = 'icons/obj/monitors.dmi'
|
||||
icon_state = "camera1"
|
||||
max_integrity = 150
|
||||
// Motion, EMP-Proof, X-Ray
|
||||
var/static/list/possible_upgrades = typecacheof(list(/obj/item/device/assembly/prox_sensor, /obj/item/stack/sheet/mineral/plasma, /obj/item/device/analyzer))
|
||||
var/list/upgrades
|
||||
var/state = 1
|
||||
|
||||
/*
|
||||
1 = Wrenched in place
|
||||
2 = Welded in place
|
||||
3 = Wires attached to it (you can now attach/dettach upgrades)
|
||||
4 = Screwdriver panel closed and is fully built (you cannot attach upgrades)
|
||||
*/
|
||||
|
||||
/obj/structure/camera_assembly/Initialize(mapload, ndir, building)
|
||||
. = ..()
|
||||
if(building)
|
||||
setDir(ndir)
|
||||
upgrades = list()
|
||||
|
||||
/obj/structure/camera_assembly/Destroy()
|
||||
QDEL_LIST(upgrades)
|
||||
return ..()
|
||||
|
||||
/obj/structure/camera_assembly/attackby(obj/item/W, mob/living/user, params)
|
||||
switch(state)
|
||||
if(1)
|
||||
// State 1
|
||||
if(istype(W, /obj/item/weldingtool))
|
||||
if(weld(W, user))
|
||||
to_chat(user, "<span class='notice'>You weld the assembly securely into place.</span>")
|
||||
anchored = TRUE
|
||||
state = 2
|
||||
return
|
||||
|
||||
else if(istype(W, /obj/item/wrench))
|
||||
playsound(src.loc, W.usesound, 50, 1)
|
||||
to_chat(user, "<span class='notice'>You unattach the assembly from its place.</span>")
|
||||
new /obj/item/wallframe/camera(get_turf(src))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if(2)
|
||||
// State 2
|
||||
if(istype(W, /obj/item/stack/cable_coil))
|
||||
var/obj/item/stack/cable_coil/C = W
|
||||
if(C.use(2))
|
||||
to_chat(user, "<span class='notice'>You add wires to the assembly.</span>")
|
||||
state = 3
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need two lengths of cable to wire a camera!</span>")
|
||||
return
|
||||
return
|
||||
|
||||
else if(istype(W, /obj/item/weldingtool))
|
||||
|
||||
if(weld(W, user))
|
||||
to_chat(user, "<span class='notice'>You unweld the assembly from its place.</span>")
|
||||
state = 1
|
||||
state = 2
|
||||
return
|
||||
|
||||
else if(istype(W, /obj/item/wrench))
|
||||
playsound(src.loc, W.usesound, 50, 1)
|
||||
to_chat(user, "<span class='notice'>You unattach the assembly from its place.</span>")
|
||||
new /obj/item/wallframe/camera(get_turf(src))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if(2)
|
||||
// State 2
|
||||
if(istype(W, /obj/item/stack/cable_coil))
|
||||
var/obj/item/stack/cable_coil/C = W
|
||||
if(C.use(2))
|
||||
to_chat(user, "<span class='notice'>You add wires to the assembly.</span>")
|
||||
state = 3
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need two lengths of cable to wire a camera!</span>")
|
||||
return
|
||||
return
|
||||
|
||||
else if(istype(W, /obj/item/weldingtool))
|
||||
|
||||
if(weld(W, user))
|
||||
to_chat(user, "<span class='notice'>You unweld the assembly from its place.</span>")
|
||||
state = 1
|
||||
anchored = TRUE
|
||||
return
|
||||
|
||||
|
||||
if(3)
|
||||
// State 3
|
||||
if(istype(W, /obj/item/screwdriver))
|
||||
playsound(src.loc, W.usesound, 50, 1)
|
||||
|
||||
return
|
||||
|
||||
|
||||
if(3)
|
||||
// State 3
|
||||
if(istype(W, /obj/item/screwdriver))
|
||||
playsound(src.loc, W.usesound, 50, 1)
|
||||
|
||||
var/input = stripped_input(user, "Which networks would you like to connect this camera to? Separate networks with a comma. No Spaces!\nFor example: SS13,Security,Secret ", "Set Network", "SS13")
|
||||
if(!input)
|
||||
to_chat(user, "<span class='warning'>No input found, please hang up and try your call again!</span>")
|
||||
return
|
||||
|
||||
var/list/tempnetwork = splittext(input, ",")
|
||||
if(tempnetwork.len < 1)
|
||||
to_chat(user, "<span class='warning'>No network found, please hang up and try your call again!</span>")
|
||||
return
|
||||
|
||||
state = 4
|
||||
var/obj/machinery/camera/C = new(src.loc)
|
||||
src.loc = C
|
||||
C.assembly = src
|
||||
C.setDir(src.dir)
|
||||
|
||||
C.network = tempnetwork
|
||||
var/area/A = get_area(src)
|
||||
C.c_tag = "[A.name] ([rand(1, 999)])"
|
||||
|
||||
|
||||
else if(istype(W, /obj/item/wirecutters))
|
||||
new/obj/item/stack/cable_coil(get_turf(src), 2)
|
||||
playsound(src.loc, W.usesound, 50, 1)
|
||||
to_chat(user, "<span class='notice'>You cut the wires from the circuits.</span>")
|
||||
state = 2
|
||||
return
|
||||
|
||||
// Upgrades!
|
||||
if(is_type_in_typecache(W, possible_upgrades) && !is_type_in_list(W, upgrades)) // Is a possible upgrade and isn't in the camera already.
|
||||
if(!user.drop_item(W))
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You attach \the [W] into the assembly inner circuits.</span>")
|
||||
upgrades += W
|
||||
W.forceMove(src)
|
||||
return
|
||||
|
||||
// Taking out upgrades
|
||||
else if(istype(W, /obj/item/crowbar) && upgrades.len)
|
||||
var/obj/U = locate(/obj) in upgrades
|
||||
if(U)
|
||||
to_chat(user, "<span class='notice'>You unattach an upgrade from the assembly.</span>")
|
||||
playsound(src.loc, W.usesound, 50, 1)
|
||||
U.loc = get_turf(src)
|
||||
upgrades -= U
|
||||
return
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/structure/camera_assembly/proc/weld(obj/item/weldingtool/WT, mob/living/user)
|
||||
if(!WT.remove_fuel(0, user))
|
||||
return 0
|
||||
to_chat(user, "<span class='notice'>You start to weld \the [src]...</span>")
|
||||
playsound(src.loc, WT.usesound, 50, 1)
|
||||
if(do_after(user, 20*WT.toolspeed, target = src))
|
||||
if(WT.isOn())
|
||||
playsound(loc, 'sound/items/welder2.ogg', 50, 1)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/structure/camera_assembly/deconstruct(disassembled = TRUE)
|
||||
if(!input)
|
||||
to_chat(user, "<span class='warning'>No input found, please hang up and try your call again!</span>")
|
||||
return
|
||||
|
||||
var/list/tempnetwork = splittext(input, ",")
|
||||
if(tempnetwork.len < 1)
|
||||
to_chat(user, "<span class='warning'>No network found, please hang up and try your call again!</span>")
|
||||
return
|
||||
|
||||
state = 4
|
||||
var/obj/machinery/camera/C = new(src.loc)
|
||||
forceMove(C)
|
||||
C.assembly = src
|
||||
C.setDir(src.dir)
|
||||
|
||||
C.network = tempnetwork
|
||||
var/area/A = get_area(src)
|
||||
C.c_tag = "[A.name] ([rand(1, 999)])"
|
||||
|
||||
|
||||
else if(istype(W, /obj/item/wirecutters))
|
||||
new/obj/item/stack/cable_coil(get_turf(src), 2)
|
||||
playsound(src.loc, W.usesound, 50, 1)
|
||||
to_chat(user, "<span class='notice'>You cut the wires from the circuits.</span>")
|
||||
state = 2
|
||||
return
|
||||
|
||||
// Upgrades!
|
||||
if(is_type_in_typecache(W, possible_upgrades) && !is_type_in_list(W, upgrades)) // Is a possible upgrade and isn't in the camera already.
|
||||
if(!user.drop_item(W))
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You attach \the [W] into the assembly inner circuits.</span>")
|
||||
upgrades += W
|
||||
W.forceMove(src)
|
||||
return
|
||||
|
||||
// Taking out upgrades
|
||||
else if(istype(W, /obj/item/crowbar) && upgrades.len)
|
||||
var/obj/U = locate(/obj) in upgrades
|
||||
if(U)
|
||||
to_chat(user, "<span class='notice'>You unattach an upgrade from the assembly.</span>")
|
||||
playsound(src.loc, W.usesound, 50, 1)
|
||||
U.forceMove(drop_location())
|
||||
upgrades -= U
|
||||
return
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/structure/camera_assembly/proc/weld(obj/item/weldingtool/WT, mob/living/user)
|
||||
if(!WT.remove_fuel(0, user))
|
||||
return 0
|
||||
to_chat(user, "<span class='notice'>You start to weld \the [src]...</span>")
|
||||
playsound(src.loc, WT.usesound, 50, 1)
|
||||
if(do_after(user, 20*WT.toolspeed, target = src))
|
||||
if(WT.isOn())
|
||||
playsound(loc, 'sound/items/welder2.ogg', 50, 1)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/structure/camera_assembly/deconstruct(disassembled = TRUE)
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
new /obj/item/stack/sheet/metal(loc)
|
||||
qdel(src)
|
||||
new /obj/item/stack/sheet/metal(loc)
|
||||
qdel(src)
|
||||
|
||||
@@ -45,14 +45,13 @@
|
||||
if(!isarea(a))
|
||||
return
|
||||
if(a.power_equip == 0) // There's no APC in this area, don't try to cheat power!
|
||||
to_chat(user, "<span class='warning'>The [name] blinks red as you try to insert the cell!</span>")
|
||||
to_chat(user, "<span class='warning'>The [src] blinks red as you try to insert the cell!</span>")
|
||||
return
|
||||
if(!user.drop_item())
|
||||
if(!user.transferItemToLoc(W,src))
|
||||
return
|
||||
|
||||
W.loc = src
|
||||
charging = W
|
||||
user.visible_message("[user] inserts a cell into the charger.", "<span class='notice'>You insert a cell into the charger.</span>")
|
||||
user.visible_message("[user] inserts a cell into [src].", "<span class='notice'>You insert a cell into [src].</span>")
|
||||
chargelevel = -1
|
||||
updateicon()
|
||||
else if(istype(W, /obj/item/wrench))
|
||||
@@ -61,7 +60,7 @@
|
||||
return
|
||||
|
||||
anchored = !anchored
|
||||
to_chat(user, "<span class='notice'>You [anchored ? "attach" : "detach"] the cell charger [anchored ? "to" : "from"] the ground</span>")
|
||||
to_chat(user, "<span class='notice'>You [anchored ? "attach" : "detach"] [src] [anchored ? "to" : "from"] the ground</span>")
|
||||
playsound(src.loc, W.usesound, 75, 1)
|
||||
else
|
||||
return ..()
|
||||
@@ -80,7 +79,7 @@
|
||||
user.put_in_hands(charging)
|
||||
charging.add_fingerprint(user)
|
||||
|
||||
user.visible_message("[user] removes the cell from the charger.", "<span class='notice'>You remove the cell from the charger.</span>")
|
||||
user.visible_message("[user] removes [charging] from [src].", "<span class='notice'>You remove [charging] from [src].</span>")
|
||||
|
||||
removecell()
|
||||
|
||||
|
||||
@@ -231,9 +231,9 @@
|
||||
|
||||
else if(mob_occupant.cloneloss > (100 - heal_level))
|
||||
mob_occupant.Unconscious(80)
|
||||
|
||||
var/dmg_mult = CONFIG_GET(number/damage_multiplier)
|
||||
//Slowly get that clone healed and finished.
|
||||
mob_occupant.adjustCloneLoss(-((speed_coeff/2) * config.damage_multiplier))
|
||||
mob_occupant.adjustCloneLoss(-((speed_coeff / 2) * dmg_mult))
|
||||
var/progress = CLONE_INITIAL_DAMAGE - mob_occupant.getCloneLoss()
|
||||
// To avoid the default cloner making incomplete clones
|
||||
progress += (100 - MINIMUM_HEAL_LEVEL)
|
||||
@@ -251,7 +251,7 @@
|
||||
BP.attach_limb(mob_occupant)
|
||||
|
||||
//Premature clones may have brain damage.
|
||||
mob_occupant.adjustBrainLoss(-((speed_coeff/2) * config.damage_multiplier))
|
||||
mob_occupant.adjustBrainLoss(-((speed_coeff / 2) * dmg_mult))
|
||||
|
||||
check_brine()
|
||||
|
||||
|
||||
@@ -1,146 +1,146 @@
|
||||
/obj/machinery/computer/aifixer
|
||||
name = "\improper AI system integrity restorer"
|
||||
desc = "Used with intelliCards containing nonfunctioning AIs to restore them to working order."
|
||||
req_access = list(ACCESS_CAPTAIN, ACCESS_ROBOTICS, ACCESS_HEADS)
|
||||
var/mob/living/silicon/ai/occupier = null
|
||||
var/active = 0
|
||||
circuit = /obj/item/circuitboard/computer/aifixer
|
||||
icon_keyboard = "tech_key"
|
||||
icon_screen = "ai-fixer"
|
||||
light_color = LIGHT_COLOR_PINK
|
||||
|
||||
/obj/machinery/computer/aifixer/attackby(obj/I, mob/user, params)
|
||||
if(occupier && istype(I, /obj/item/screwdriver))
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
to_chat(user, "<span class='warning'>The screws on [name]'s screen won't budge.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>The screws on [name]'s screen won't budge and it emits a warning beep.</span>")
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/aifixer/attack_hand(mob/user)
|
||||
if(..())
|
||||
return
|
||||
interact(user)
|
||||
|
||||
/obj/machinery/computer/aifixer/interact(mob/user)
|
||||
|
||||
var/dat = ""
|
||||
|
||||
if (src.occupier)
|
||||
var/laws
|
||||
dat += "<h3>Stored AI: [src.occupier.name]</h3>"
|
||||
dat += "<b>System integrity:</b> [(src.occupier.health+100)/2]%<br>"
|
||||
|
||||
if (src.occupier.laws.zeroth)
|
||||
laws += "<b>0:</b> [src.occupier.laws.zeroth]<BR>"
|
||||
|
||||
for (var/index = 1, index <= src.occupier.laws.ion.len, index++)
|
||||
var/law = src.occupier.laws.ion[index]
|
||||
if (length(law) > 0)
|
||||
var/num = ionnum()
|
||||
laws += "<b>[num]:</b> [law]<BR>"
|
||||
|
||||
var/number = 1
|
||||
for (var/index = 1, index <= src.occupier.laws.inherent.len, index++)
|
||||
var/law = src.occupier.laws.inherent[index]
|
||||
if (length(law) > 0)
|
||||
laws += "<b>[number]:</b> [law]<BR>"
|
||||
number++
|
||||
|
||||
for (var/index = 1, index <= src.occupier.laws.supplied.len, index++)
|
||||
var/law = src.occupier.laws.supplied[index]
|
||||
if (length(law) > 0)
|
||||
laws += "<b>[number]:</b> [law]<BR>"
|
||||
number++
|
||||
|
||||
dat += "<b>Laws:</b><br>[laws]<br>"
|
||||
|
||||
if (src.occupier.stat == DEAD)
|
||||
dat += "<span class='bad'>AI non-functional</span>"
|
||||
else
|
||||
dat += "<span class='good'>AI functional</span>"
|
||||
if (!src.active)
|
||||
dat += {"<br><br><A href='byond://?src=\ref[src];fix=1'>Begin Reconstruction</A>"}
|
||||
else
|
||||
dat += "<br><br>Reconstruction in process, please wait.<br>"
|
||||
dat += {"<br><A href='?src=\ref[user];mach_close=computer'>Close</A>"}
|
||||
var/datum/browser/popup = new(user, "computer", "AI System Integrity Restorer", 400, 500)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
return
|
||||
|
||||
/obj/machinery/computer/aifixer/proc/Fix()
|
||||
use_power(1000)
|
||||
occupier.adjustOxyLoss(-1, 0)
|
||||
occupier.adjustFireLoss(-1, 0)
|
||||
occupier.adjustToxLoss(-1, 0)
|
||||
occupier.adjustBruteLoss(-1, 0)
|
||||
occupier.updatehealth()
|
||||
occupier.updatehealth()
|
||||
if(occupier.health >= 0 && occupier.stat == DEAD)
|
||||
occupier.revive()
|
||||
return occupier.health < 100
|
||||
|
||||
/obj/machinery/computer/aifixer/process()
|
||||
if(..())
|
||||
if(active)
|
||||
active = Fix()
|
||||
updateDialog()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/computer/aifixer/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if(href_list["fix"])
|
||||
to_chat(usr, "<span class='notice'>Reconstruction in progress. This will take several minutes.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 25, 0)
|
||||
active = TRUE
|
||||
add_fingerprint(usr)
|
||||
|
||||
/obj/machinery/computer/aifixer/update_icon()
|
||||
..()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
else
|
||||
if(active)
|
||||
add_overlay("ai-fixer-on")
|
||||
if (occupier)
|
||||
switch (occupier.stat)
|
||||
if (0)
|
||||
add_overlay("ai-fixer-full")
|
||||
if (2)
|
||||
add_overlay("ai-fixer-404")
|
||||
else
|
||||
add_overlay("ai-fixer-empty")
|
||||
|
||||
/obj/machinery/computer/aifixer/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI, obj/item/device/aicard/card)
|
||||
if(!..())
|
||||
return
|
||||
//Downloading AI from card to terminal.
|
||||
if(interaction == AI_TRANS_FROM_CARD)
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
to_chat(user, "[src] is offline and cannot take an AI at this time!")
|
||||
return
|
||||
AI.forceMove(src)
|
||||
occupier = AI
|
||||
AI.control_disabled = 1
|
||||
AI.radio_enabled = 0
|
||||
to_chat(AI, "You have been uploaded to a stationary terminal. Sadly, there is no remote access from here.")
|
||||
to_chat(user, "<span class='boldnotice'>Transfer successful</span>: [AI.name] ([rand(1000,9999)].exe) installed and executed successfully. Local copy has been removed.")
|
||||
card.AI = null
|
||||
update_icon()
|
||||
|
||||
else //Uploading AI from terminal to card
|
||||
if(occupier && !active)
|
||||
to_chat(occupier, "You have been downloaded to a mobile storage device. Still no remote access.")
|
||||
to_chat(user, "<span class='boldnotice'>Transfer successful</span>: [occupier.name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory.")
|
||||
occupier.loc = card
|
||||
card.AI = occupier
|
||||
occupier = null
|
||||
update_icon()
|
||||
else if (active)
|
||||
to_chat(user, "<span class='boldannounce'>ERROR</span>: Reconstruction in progress.")
|
||||
else if (!occupier)
|
||||
to_chat(user, "<span class='boldannounce'>ERROR</span>: Unable to locate artificial intelligence.")
|
||||
/obj/machinery/computer/aifixer
|
||||
name = "\improper AI system integrity restorer"
|
||||
desc = "Used with intelliCards containing nonfunctioning AIs to restore them to working order."
|
||||
req_access = list(ACCESS_CAPTAIN, ACCESS_ROBOTICS, ACCESS_HEADS)
|
||||
var/mob/living/silicon/ai/occupier = null
|
||||
var/active = 0
|
||||
circuit = /obj/item/circuitboard/computer/aifixer
|
||||
icon_keyboard = "tech_key"
|
||||
icon_screen = "ai-fixer"
|
||||
light_color = LIGHT_COLOR_PINK
|
||||
|
||||
/obj/machinery/computer/aifixer/attackby(obj/I, mob/user, params)
|
||||
if(occupier && istype(I, /obj/item/screwdriver))
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
to_chat(user, "<span class='warning'>The screws on [name]'s screen won't budge.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>The screws on [name]'s screen won't budge and it emits a warning beep.</span>")
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/aifixer/attack_hand(mob/user)
|
||||
if(..())
|
||||
return
|
||||
interact(user)
|
||||
|
||||
/obj/machinery/computer/aifixer/interact(mob/user)
|
||||
|
||||
var/dat = ""
|
||||
|
||||
if (src.occupier)
|
||||
var/laws
|
||||
dat += "<h3>Stored AI: [src.occupier.name]</h3>"
|
||||
dat += "<b>System integrity:</b> [(src.occupier.health+100)/2]%<br>"
|
||||
|
||||
if (src.occupier.laws.zeroth)
|
||||
laws += "<b>0:</b> [src.occupier.laws.zeroth]<BR>"
|
||||
|
||||
for (var/index = 1, index <= src.occupier.laws.ion.len, index++)
|
||||
var/law = src.occupier.laws.ion[index]
|
||||
if (length(law) > 0)
|
||||
var/num = ionnum()
|
||||
laws += "<b>[num]:</b> [law]<BR>"
|
||||
|
||||
var/number = 1
|
||||
for (var/index = 1, index <= src.occupier.laws.inherent.len, index++)
|
||||
var/law = src.occupier.laws.inherent[index]
|
||||
if (length(law) > 0)
|
||||
laws += "<b>[number]:</b> [law]<BR>"
|
||||
number++
|
||||
|
||||
for (var/index = 1, index <= src.occupier.laws.supplied.len, index++)
|
||||
var/law = src.occupier.laws.supplied[index]
|
||||
if (length(law) > 0)
|
||||
laws += "<b>[number]:</b> [law]<BR>"
|
||||
number++
|
||||
|
||||
dat += "<b>Laws:</b><br>[laws]<br>"
|
||||
|
||||
if (src.occupier.stat == DEAD)
|
||||
dat += "<span class='bad'>AI non-functional</span>"
|
||||
else
|
||||
dat += "<span class='good'>AI functional</span>"
|
||||
if (!src.active)
|
||||
dat += {"<br><br><A href='byond://?src=\ref[src];fix=1'>Begin Reconstruction</A>"}
|
||||
else
|
||||
dat += "<br><br>Reconstruction in process, please wait.<br>"
|
||||
dat += {"<br><A href='?src=\ref[user];mach_close=computer'>Close</A>"}
|
||||
var/datum/browser/popup = new(user, "computer", "AI System Integrity Restorer", 400, 500)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
return
|
||||
|
||||
/obj/machinery/computer/aifixer/proc/Fix()
|
||||
use_power(1000)
|
||||
occupier.adjustOxyLoss(-1, 0)
|
||||
occupier.adjustFireLoss(-1, 0)
|
||||
occupier.adjustToxLoss(-1, 0)
|
||||
occupier.adjustBruteLoss(-1, 0)
|
||||
occupier.updatehealth()
|
||||
occupier.updatehealth()
|
||||
if(occupier.health >= 0 && occupier.stat == DEAD)
|
||||
occupier.revive()
|
||||
return occupier.health < 100
|
||||
|
||||
/obj/machinery/computer/aifixer/process()
|
||||
if(..())
|
||||
if(active)
|
||||
active = Fix()
|
||||
updateDialog()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/computer/aifixer/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if(href_list["fix"])
|
||||
to_chat(usr, "<span class='notice'>Reconstruction in progress. This will take several minutes.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 25, 0)
|
||||
active = TRUE
|
||||
add_fingerprint(usr)
|
||||
|
||||
/obj/machinery/computer/aifixer/update_icon()
|
||||
..()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
else
|
||||
if(active)
|
||||
add_overlay("ai-fixer-on")
|
||||
if (occupier)
|
||||
switch (occupier.stat)
|
||||
if (0)
|
||||
add_overlay("ai-fixer-full")
|
||||
if (2)
|
||||
add_overlay("ai-fixer-404")
|
||||
else
|
||||
add_overlay("ai-fixer-empty")
|
||||
|
||||
/obj/machinery/computer/aifixer/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI, obj/item/device/aicard/card)
|
||||
if(!..())
|
||||
return
|
||||
//Downloading AI from card to terminal.
|
||||
if(interaction == AI_TRANS_FROM_CARD)
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
to_chat(user, "[src] is offline and cannot take an AI at this time!")
|
||||
return
|
||||
AI.forceMove(src)
|
||||
occupier = AI
|
||||
AI.control_disabled = 1
|
||||
AI.radio_enabled = 0
|
||||
to_chat(AI, "You have been uploaded to a stationary terminal. Sadly, there is no remote access from here.")
|
||||
to_chat(user, "<span class='boldnotice'>Transfer successful</span>: [AI.name] ([rand(1000,9999)].exe) installed and executed successfully. Local copy has been removed.")
|
||||
card.AI = null
|
||||
update_icon()
|
||||
|
||||
else //Uploading AI from terminal to card
|
||||
if(occupier && !active)
|
||||
to_chat(occupier, "You have been downloaded to a mobile storage device. Still no remote access.")
|
||||
to_chat(user, "<span class='boldnotice'>Transfer successful</span>: [occupier.name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory.")
|
||||
occupier.forceMove(card)
|
||||
card.AI = occupier
|
||||
occupier = null
|
||||
update_icon()
|
||||
else if (active)
|
||||
to_chat(user, "<span class='boldannounce'>ERROR</span>: Reconstruction in progress.")
|
||||
else if (!occupier)
|
||||
to_chat(user, "<span class='boldannounce'>ERROR</span>: Unable to locate artificial intelligence.")
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
var/obj/item/weldingtool/WT = P
|
||||
if(!WT.remove_fuel(0, user))
|
||||
if(!WT.isOn())
|
||||
to_chat(user, "<span class='warning'>The welding tool must be on to complete this task!</span>")
|
||||
to_chat(user, "<span class='warning'>[WT] must be on to complete this task!</span>")
|
||||
return
|
||||
playsound(src.loc, P.usesound, 50, 1)
|
||||
to_chat(user, "<span class='notice'>You start deconstructing the frame...</span>")
|
||||
@@ -40,14 +40,13 @@
|
||||
state = 0
|
||||
return
|
||||
if(istype(P, /obj/item/circuitboard/computer) && !circuit)
|
||||
if(!user.drop_item())
|
||||
if(!user.transferItemToLoc(P, null))
|
||||
return
|
||||
playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1)
|
||||
to_chat(user, "<span class='notice'>You place the circuit board inside the frame.</span>")
|
||||
to_chat(user, "<span class='notice'>You place [P] inside the frame.</span>")
|
||||
icon_state = "1"
|
||||
circuit = P
|
||||
circuit.add_fingerprint(user)
|
||||
P.loc = null
|
||||
return
|
||||
|
||||
else if(istype(P, /obj/item/circuitboard) && !circuit)
|
||||
@@ -55,16 +54,16 @@
|
||||
return
|
||||
if(istype(P, /obj/item/screwdriver) && circuit)
|
||||
playsound(src.loc, P.usesound, 50, 1)
|
||||
to_chat(user, "<span class='notice'>You screw the circuit board into place.</span>")
|
||||
to_chat(user, "<span class='notice'>You screw [circuit] into place.</span>")
|
||||
state = 2
|
||||
icon_state = "2"
|
||||
return
|
||||
if(istype(P, /obj/item/crowbar) && circuit)
|
||||
playsound(src.loc, P.usesound, 50, 1)
|
||||
to_chat(user, "<span class='notice'>You remove the circuit board.</span>")
|
||||
to_chat(user, "<span class='notice'>You remove [circuit].</span>")
|
||||
state = 1
|
||||
icon_state = "0"
|
||||
circuit.loc = src.loc
|
||||
circuit.forceMove(drop_location())
|
||||
circuit.add_fingerprint(user)
|
||||
circuit = null
|
||||
return
|
||||
|
||||
@@ -47,29 +47,26 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
|
||||
|
||||
/obj/machinery/computer/card/Initialize()
|
||||
. = ..()
|
||||
change_position_cooldown = config.id_console_jobslot_delay
|
||||
change_position_cooldown = CONFIG_GET(number/id_console_jobslot_delay)
|
||||
|
||||
/obj/machinery/computer/card/attackby(obj/O, mob/user, params)//TODO:SANITY
|
||||
if(istype(O, /obj/item/card/id))
|
||||
var/obj/item/card/id/idcard = O
|
||||
if(check_access(idcard))
|
||||
if(!scan)
|
||||
if(!usr.drop_item())
|
||||
if (!user.transferItemToLoc(idcard,src))
|
||||
return
|
||||
idcard.loc = src
|
||||
scan = idcard
|
||||
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
|
||||
else if(!modify)
|
||||
if(!usr.drop_item())
|
||||
if (!user.transferItemToLoc(idcard,src))
|
||||
return
|
||||
idcard.loc = src
|
||||
modify = idcard
|
||||
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
|
||||
else
|
||||
if(!modify)
|
||||
if(!usr.drop_item())
|
||||
if (!user.transferItemToLoc(idcard,src))
|
||||
return
|
||||
idcard.loc = src
|
||||
modify = idcard
|
||||
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
|
||||
else
|
||||
@@ -95,10 +92,10 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
|
||||
|
||||
/obj/machinery/computer/card/on_deconstruction()
|
||||
if(scan)
|
||||
scan.forceMove(loc)
|
||||
scan.forceMove(drop_location())
|
||||
scan = null
|
||||
if(modify)
|
||||
modify.forceMove(loc)
|
||||
modify.forceMove(drop_location())
|
||||
modify = null
|
||||
|
||||
//Check if you can't open a new position for a certain job
|
||||
@@ -355,7 +352,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
|
||||
if (modify)
|
||||
GLOB.data_core.manifest_modify(modify.registered_name, modify.assignment)
|
||||
modify.update_label()
|
||||
modify.loc = loc
|
||||
modify.forceMove(drop_location())
|
||||
modify.verb_pickup()
|
||||
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
|
||||
modify = null
|
||||
@@ -364,26 +361,24 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
|
||||
else
|
||||
var/obj/item/I = usr.get_active_held_item()
|
||||
if (istype(I, /obj/item/card/id))
|
||||
if(!usr.drop_item())
|
||||
if (!usr.transferItemToLoc(I,src))
|
||||
return
|
||||
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
|
||||
I.loc = src
|
||||
modify = I
|
||||
authenticated = 0
|
||||
|
||||
if ("scan")
|
||||
if (scan)
|
||||
scan.loc = src.loc
|
||||
scan.forceMove(drop_location())
|
||||
scan.verb_pickup()
|
||||
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
|
||||
scan = null
|
||||
else
|
||||
var/obj/item/I = usr.get_active_held_item()
|
||||
if (istype(I, /obj/item/card/id))
|
||||
if(!usr.drop_item())
|
||||
if (!usr.transferItemToLoc(I,src))
|
||||
return
|
||||
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
|
||||
I.loc = src
|
||||
scan = I
|
||||
authenticated = 0
|
||||
if ("auth")
|
||||
|
||||
@@ -1,502 +1,501 @@
|
||||
/obj/machinery/computer/cloning
|
||||
name = "cloning console"
|
||||
desc = "Used to clone people and manage DNA."
|
||||
icon_screen = "dna"
|
||||
icon_keyboard = "med_key"
|
||||
circuit = /obj/item/circuitboard/computer/cloning
|
||||
/obj/machinery/computer/cloning
|
||||
name = "cloning console"
|
||||
desc = "Used to clone people and manage DNA."
|
||||
icon_screen = "dna"
|
||||
icon_keyboard = "med_key"
|
||||
circuit = /obj/item/circuitboard/computer/cloning
|
||||
req_access = list(ACCESS_HEADS) //ONLY USED FOR RECORD DELETION RIGHT NOW.
|
||||
var/obj/machinery/dna_scannernew/scanner = null //Linked scanner. For scanning.
|
||||
var/list/pods //Linked cloning pods
|
||||
var/temp = "Inactive"
|
||||
var/scantemp_ckey
|
||||
var/scantemp = "Ready to Scan"
|
||||
var/menu = 1 //Which menu screen to display
|
||||
var/list/records = list()
|
||||
var/datum/data/record/active_record = null
|
||||
var/obj/item/disk/data/diskette = null //Mostly so the geneticist can steal everything.
|
||||
var/loading = 0 // Nice loading text
|
||||
var/autoprocess = 0
|
||||
|
||||
light_color = LIGHT_COLOR_BLUE
|
||||
|
||||
/obj/machinery/computer/cloning/Initialize()
|
||||
var/obj/machinery/dna_scannernew/scanner = null //Linked scanner. For scanning.
|
||||
var/list/pods //Linked cloning pods
|
||||
var/temp = "Inactive"
|
||||
var/scantemp_ckey
|
||||
var/scantemp = "Ready to Scan"
|
||||
var/menu = 1 //Which menu screen to display
|
||||
var/list/records = list()
|
||||
var/datum/data/record/active_record = null
|
||||
var/obj/item/disk/data/diskette = null //Mostly so the geneticist can steal everything.
|
||||
var/loading = 0 // Nice loading text
|
||||
var/autoprocess = 0
|
||||
|
||||
light_color = LIGHT_COLOR_BLUE
|
||||
|
||||
/obj/machinery/computer/cloning/Initialize()
|
||||
. = ..()
|
||||
updatemodules(TRUE)
|
||||
|
||||
/obj/machinery/computer/cloning/Destroy()
|
||||
if(pods)
|
||||
for(var/P in pods)
|
||||
DetachCloner(P)
|
||||
pods = null
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/cloning/proc/GetAvailablePod(mind = null)
|
||||
if(pods)
|
||||
for(var/P in pods)
|
||||
var/obj/machinery/clonepod/pod = P
|
||||
if(pod.occupant && pod.clonemind == mind)
|
||||
return null
|
||||
if(pod.is_operational() && !(pod.occupant || pod.mess))
|
||||
return pod
|
||||
|
||||
/obj/machinery/computer/cloning/proc/HasEfficientPod()
|
||||
if(pods)
|
||||
for(var/P in pods)
|
||||
var/obj/machinery/clonepod/pod = P
|
||||
if(pod.is_operational() && pod.efficiency > 5)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/cloning/proc/GetAvailableEfficientPod(mind = null)
|
||||
if(pods)
|
||||
for(var/P in pods)
|
||||
var/obj/machinery/clonepod/pod = P
|
||||
if(pod.occupant && pod.clonemind == mind)
|
||||
return pod
|
||||
else if(!. && pod.is_operational() && !(pod.occupant || pod.mess) && pod.efficiency > 5)
|
||||
. = pod
|
||||
|
||||
/obj/machinery/computer/cloning/process()
|
||||
if(!(scanner && LAZYLEN(pods) && autoprocess))
|
||||
return
|
||||
|
||||
if(scanner.occupant && scanner.scan_level > 2)
|
||||
scan_occupant(scanner.occupant)
|
||||
|
||||
for(var/datum/data/record/R in records)
|
||||
var/obj/machinery/clonepod/pod = GetAvailableEfficientPod(R.fields["mind"])
|
||||
|
||||
if(!pod)
|
||||
return
|
||||
|
||||
if(pod.occupant)
|
||||
continue //how though?
|
||||
|
||||
if(pod.growclone(R.fields["ckey"], R.fields["name"], R.fields["UI"], R.fields["SE"], R.fields["mind"], R.fields["mrace"], R.fields["features"], R.fields["factions"]))
|
||||
records -= R
|
||||
|
||||
/obj/machinery/computer/cloning/proc/updatemodules(findfirstcloner)
|
||||
src.scanner = findscanner()
|
||||
if(findfirstcloner && !LAZYLEN(pods))
|
||||
findcloner()
|
||||
|
||||
/obj/machinery/computer/cloning/proc/findscanner()
|
||||
var/obj/machinery/dna_scannernew/scannerf = null
|
||||
|
||||
// Loop through every direction
|
||||
for(dir in list(NORTH,EAST,SOUTH,WEST))
|
||||
|
||||
// Try to find a scanner in that direction
|
||||
scannerf = locate(/obj/machinery/dna_scannernew, get_step(src, dir))
|
||||
|
||||
// If found and operational, return the scanner
|
||||
if (!isnull(scannerf) && scannerf.is_operational())
|
||||
return scannerf
|
||||
|
||||
// If no scanner was found, it will return null
|
||||
return null
|
||||
|
||||
/obj/machinery/computer/cloning/proc/findcloner()
|
||||
var/obj/machinery/clonepod/podf = null
|
||||
|
||||
for(dir in list(NORTH,EAST,SOUTH,WEST))
|
||||
|
||||
podf = locate(/obj/machinery/clonepod, get_step(src, dir))
|
||||
|
||||
if (!isnull(podf) && podf.is_operational())
|
||||
AttachCloner(podf)
|
||||
|
||||
/obj/machinery/computer/cloning/proc/AttachCloner(obj/machinery/clonepod/pod)
|
||||
if(!pod.connected)
|
||||
pod.connected = src
|
||||
LAZYADD(pods, pod)
|
||||
|
||||
/obj/machinery/computer/cloning/proc/DetachCloner(obj/machinery/clonepod/pod)
|
||||
pod.connected = null
|
||||
LAZYREMOVE(pods, pod)
|
||||
|
||||
/obj/machinery/computer/cloning/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/disk/data)) //INSERT SOME DISKETTES
|
||||
if (!src.diskette)
|
||||
if(!user.drop_item())
|
||||
return
|
||||
W.loc = src
|
||||
src.diskette = W
|
||||
to_chat(user, "<span class='notice'>You insert [W].</span>")
|
||||
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
|
||||
src.updateUsrDialog()
|
||||
updatemodules(TRUE)
|
||||
|
||||
/obj/machinery/computer/cloning/Destroy()
|
||||
if(pods)
|
||||
for(var/P in pods)
|
||||
DetachCloner(P)
|
||||
pods = null
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/cloning/proc/GetAvailablePod(mind = null)
|
||||
if(pods)
|
||||
for(var/P in pods)
|
||||
var/obj/machinery/clonepod/pod = P
|
||||
if(pod.occupant && pod.clonemind == mind)
|
||||
return null
|
||||
if(pod.is_operational() && !(pod.occupant || pod.mess))
|
||||
return pod
|
||||
|
||||
/obj/machinery/computer/cloning/proc/HasEfficientPod()
|
||||
if(pods)
|
||||
for(var/P in pods)
|
||||
var/obj/machinery/clonepod/pod = P
|
||||
if(pod.is_operational() && pod.efficiency > 5)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/cloning/proc/GetAvailableEfficientPod(mind = null)
|
||||
if(pods)
|
||||
for(var/P in pods)
|
||||
var/obj/machinery/clonepod/pod = P
|
||||
if(pod.occupant && pod.clonemind == mind)
|
||||
return pod
|
||||
else if(!. && pod.is_operational() && !(pod.occupant || pod.mess) && pod.efficiency > 5)
|
||||
. = pod
|
||||
|
||||
/obj/machinery/computer/cloning/process()
|
||||
if(!(scanner && LAZYLEN(pods) && autoprocess))
|
||||
return
|
||||
|
||||
if(scanner.occupant && scanner.scan_level > 2)
|
||||
scan_occupant(scanner.occupant)
|
||||
|
||||
for(var/datum/data/record/R in records)
|
||||
var/obj/machinery/clonepod/pod = GetAvailableEfficientPod(R.fields["mind"])
|
||||
|
||||
if(!pod)
|
||||
return
|
||||
|
||||
if(pod.occupant)
|
||||
continue //how though?
|
||||
|
||||
if(pod.growclone(R.fields["ckey"], R.fields["name"], R.fields["UI"], R.fields["SE"], R.fields["mind"], R.fields["mrace"], R.fields["features"], R.fields["factions"]))
|
||||
records -= R
|
||||
|
||||
/obj/machinery/computer/cloning/proc/updatemodules(findfirstcloner)
|
||||
src.scanner = findscanner()
|
||||
if(findfirstcloner && !LAZYLEN(pods))
|
||||
findcloner()
|
||||
|
||||
/obj/machinery/computer/cloning/proc/findscanner()
|
||||
var/obj/machinery/dna_scannernew/scannerf = null
|
||||
|
||||
// Loop through every direction
|
||||
for(dir in list(NORTH,EAST,SOUTH,WEST))
|
||||
|
||||
// Try to find a scanner in that direction
|
||||
scannerf = locate(/obj/machinery/dna_scannernew, get_step(src, dir))
|
||||
|
||||
// If found and operational, return the scanner
|
||||
if (!isnull(scannerf) && scannerf.is_operational())
|
||||
return scannerf
|
||||
|
||||
// If no scanner was found, it will return null
|
||||
return null
|
||||
|
||||
/obj/machinery/computer/cloning/proc/findcloner()
|
||||
var/obj/machinery/clonepod/podf = null
|
||||
|
||||
for(dir in list(NORTH,EAST,SOUTH,WEST))
|
||||
|
||||
podf = locate(/obj/machinery/clonepod, get_step(src, dir))
|
||||
|
||||
if (!isnull(podf) && podf.is_operational())
|
||||
AttachCloner(podf)
|
||||
|
||||
/obj/machinery/computer/cloning/proc/AttachCloner(obj/machinery/clonepod/pod)
|
||||
if(!pod.connected)
|
||||
pod.connected = src
|
||||
LAZYADD(pods, pod)
|
||||
|
||||
/obj/machinery/computer/cloning/proc/DetachCloner(obj/machinery/clonepod/pod)
|
||||
pod.connected = null
|
||||
LAZYREMOVE(pods, pod)
|
||||
|
||||
/obj/machinery/computer/cloning/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/disk/data)) //INSERT SOME DISKETTES
|
||||
if (!src.diskette)
|
||||
if (!user.transferItemToLoc(W,src))
|
||||
return
|
||||
src.diskette = W
|
||||
to_chat(user, "<span class='notice'>You insert [W].</span>")
|
||||
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
|
||||
src.updateUsrDialog()
|
||||
else if(istype(W, /obj/item/device/multitool))
|
||||
var/obj/item/device/multitool/P = W
|
||||
|
||||
if(istype(P.buffer, /obj/machinery/clonepod))
|
||||
if(get_area(P.buffer) != get_area(src))
|
||||
to_chat(user, "<font color = #666633>-% Cannot link machines across power zones. Buffer cleared %-</font color>")
|
||||
P.buffer = null
|
||||
return
|
||||
to_chat(user, "<font color = #666633>-% Successfully linked [P.buffer] with [src] %-</font color>")
|
||||
var/obj/machinery/clonepod/pod = P.buffer
|
||||
if(pod.connected)
|
||||
pod.connected.DetachCloner(pod)
|
||||
AttachCloner(pod)
|
||||
else
|
||||
P.buffer = src
|
||||
to_chat(user, "<font color = #666633>-% Successfully stored \ref[P.buffer] [P.buffer.name] in buffer %-</font color>")
|
||||
return
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/cloning/attack_hand(mob/user)
|
||||
if(..())
|
||||
return
|
||||
interact(user)
|
||||
|
||||
/obj/machinery/computer/cloning/interact(mob/user)
|
||||
user.set_machine(src)
|
||||
add_fingerprint(user)
|
||||
|
||||
if(..())
|
||||
return
|
||||
|
||||
updatemodules(TRUE)
|
||||
|
||||
var/dat = ""
|
||||
dat += "<a href='byond://?src=\ref[src];refresh=1'>Refresh</a>"
|
||||
|
||||
if(scanner && HasEfficientPod() && scanner.scan_level > 2)
|
||||
if(!autoprocess)
|
||||
dat += "<a href='byond://?src=\ref[src];task=autoprocess'>Autoprocess</a>"
|
||||
else
|
||||
dat += "<a href='byond://?src=\ref[src];task=stopautoprocess'>Stop autoprocess</a>"
|
||||
else
|
||||
dat += "<span class='linkOff'>Autoprocess</span>"
|
||||
dat += "<h3>Cloning Pod Status</h3>"
|
||||
dat += "<div class='statusDisplay'>[temp] </div>"
|
||||
|
||||
switch(src.menu)
|
||||
if(1)
|
||||
// Modules
|
||||
if (isnull(src.scanner) || !LAZYLEN(pods))
|
||||
dat += "<h3>Modules</h3>"
|
||||
//dat += "<a href='byond://?src=\ref[src];relmodules=1'>Reload Modules</a>"
|
||||
if (isnull(src.scanner))
|
||||
dat += "<font class='bad'>ERROR: No Scanner detected!</font><br>"
|
||||
if (!LAZYLEN(pods))
|
||||
dat += "<font class='bad'>ERROR: No Pod detected</font><br>"
|
||||
|
||||
// Scanner
|
||||
if (!isnull(src.scanner))
|
||||
var/mob/living/scanner_occupant = get_mob_or_brainmob(scanner.occupant)
|
||||
|
||||
dat += "<h3>Scanner Functions</h3>"
|
||||
|
||||
dat += "<div class='statusDisplay'>"
|
||||
if(!scanner_occupant)
|
||||
dat += "Scanner Unoccupied"
|
||||
else if(loading)
|
||||
dat += "[scanner_occupant] => Scanning..."
|
||||
else
|
||||
if(scanner_occupant.ckey != scantemp_ckey)
|
||||
scantemp = "Ready to Scan"
|
||||
scantemp_ckey = scanner_occupant.ckey
|
||||
dat += "[scanner_occupant] => [scantemp]"
|
||||
dat += "</div>"
|
||||
|
||||
if(scanner_occupant)
|
||||
dat += "<a href='byond://?src=\ref[src];scan=1'>Start Scan</a>"
|
||||
dat += "<br><a href='byond://?src=\ref[src];lock=1'>[src.scanner.locked ? "Unlock Scanner" : "Lock Scanner"]</a>"
|
||||
else
|
||||
dat += "<span class='linkOff'>Start Scan</span>"
|
||||
|
||||
// Database
|
||||
dat += "<h3>Database Functions</h3>"
|
||||
if (src.records.len && src.records.len > 0)
|
||||
dat += "<a href='byond://?src=\ref[src];menu=2'>View Records ([src.records.len])</a><br>"
|
||||
else
|
||||
dat += "<span class='linkOff'>View Records (0)</span><br>"
|
||||
if (src.diskette)
|
||||
dat += "<a href='byond://?src=\ref[src];disk=eject'>Eject Disk</a><br>"
|
||||
|
||||
|
||||
|
||||
if(2)
|
||||
dat += "<h3>Current records</h3>"
|
||||
dat += "<a href='byond://?src=\ref[src];menu=1'><< Back</a><br><br>"
|
||||
for(var/datum/data/record/R in records)
|
||||
dat += "<h4>[R.fields["name"]]</h4>Scan ID [R.fields["id"]] <a href='byond://?src=\ref[src];view_rec=[R.fields["id"]]'>View Record</a>"
|
||||
if(3)
|
||||
dat += "<h3>Selected Record</h3>"
|
||||
dat += "<a href='byond://?src=\ref[src];menu=2'><< Back</a><br>"
|
||||
|
||||
if (!src.active_record)
|
||||
dat += "<font class='bad'>Record not found.</font>"
|
||||
else
|
||||
dat += "<h4>[src.active_record.fields["name"]]</h4>"
|
||||
dat += "Scan ID [src.active_record.fields["id"]] <a href='byond://?src=\ref[src];clone=[active_record.fields["id"]]'>Clone</a><br>"
|
||||
|
||||
var/obj/item/implant/health/H = locate(src.active_record.fields["imp"])
|
||||
|
||||
if ((H) && (istype(H)))
|
||||
dat += "<b>Health Implant Data:</b><br />[H.sensehealth()]<br><br />"
|
||||
else
|
||||
dat += "<font class='bad'>Unable to locate Health Implant.</font><br /><br />"
|
||||
|
||||
dat += "<b>Unique Identifier:</b><br /><span class='highlight'>[src.active_record.fields["UI"]]</span><br>"
|
||||
dat += "<b>Structural Enzymes:</b><br /><span class='highlight'>[src.active_record.fields["SE"]]</span><br>"
|
||||
|
||||
if(diskette && diskette.fields)
|
||||
dat += "<div class='block'>"
|
||||
dat += "<h4>Inserted Disk</h4>"
|
||||
dat += "<b>Contents:</b> "
|
||||
var/list/L = list()
|
||||
if(diskette.fields["UI"])
|
||||
L += "Unique Identifier"
|
||||
if(diskette.fields["UE"] && diskette.fields["name"] && diskette.fields["blood_type"])
|
||||
L += "Unique Enzymes"
|
||||
if(diskette.fields["SE"])
|
||||
L += "Structural Enzymes"
|
||||
dat += english_list(L, "Empty", " + ", " + ")
|
||||
dat += "<br /><a href='byond://?src=\ref[src];disk=load'>Load from Disk</a>"
|
||||
|
||||
dat += "<br /><a href='byond://?src=\ref[src];disk=save'>Save to Disk</a>"
|
||||
dat += "</div>"
|
||||
|
||||
dat += "<font size=1><a href='byond://?src=\ref[src];del_rec=1'>Delete Record</a></font>"
|
||||
|
||||
if(4)
|
||||
if (!src.active_record)
|
||||
src.menu = 2
|
||||
dat = "[src.temp]<br>"
|
||||
dat += "<h3>Confirm Record Deletion</h3>"
|
||||
|
||||
dat += "<b><a href='byond://?src=\ref[src];del_rec=1'>Scan card to confirm.</a></b><br>"
|
||||
dat += "<b><a href='byond://?src=\ref[src];menu=3'>Cancel</a></b>"
|
||||
|
||||
|
||||
var/datum/browser/popup = new(user, "cloning", "Cloning System Control")
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/computer/cloning/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(loading)
|
||||
return
|
||||
|
||||
if(href_list["task"])
|
||||
switch(href_list["task"])
|
||||
if("autoprocess")
|
||||
autoprocess = 1
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
if("stopautoprocess")
|
||||
autoprocess = 0
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
|
||||
else if ((href_list["scan"]) && !isnull(scanner) && scanner.is_operational())
|
||||
scantemp = ""
|
||||
|
||||
loading = 1
|
||||
src.updateUsrDialog()
|
||||
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
|
||||
say("Initiating scan...")
|
||||
|
||||
spawn(20)
|
||||
src.scan_occupant(scanner.occupant)
|
||||
|
||||
loading = 0
|
||||
src.updateUsrDialog()
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
|
||||
|
||||
//No locking an open scanner.
|
||||
else if ((href_list["lock"]) && !isnull(scanner) && scanner.is_operational())
|
||||
if ((!scanner.locked) && (scanner.occupant))
|
||||
var/obj/item/device/multitool/P = W
|
||||
|
||||
if(istype(P.buffer, /obj/machinery/clonepod))
|
||||
if(get_area(P.buffer) != get_area(src))
|
||||
to_chat(user, "<font color = #666633>-% Cannot link machines across power zones. Buffer cleared %-</font color>")
|
||||
P.buffer = null
|
||||
return
|
||||
to_chat(user, "<font color = #666633>-% Successfully linked [P.buffer] with [src] %-</font color>")
|
||||
var/obj/machinery/clonepod/pod = P.buffer
|
||||
if(pod.connected)
|
||||
pod.connected.DetachCloner(pod)
|
||||
AttachCloner(pod)
|
||||
else
|
||||
P.buffer = src
|
||||
to_chat(user, "<font color = #666633>-% Successfully stored \ref[P.buffer] [P.buffer.name] in buffer %-</font color>")
|
||||
return
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/cloning/attack_hand(mob/user)
|
||||
if(..())
|
||||
return
|
||||
interact(user)
|
||||
|
||||
/obj/machinery/computer/cloning/interact(mob/user)
|
||||
user.set_machine(src)
|
||||
add_fingerprint(user)
|
||||
|
||||
if(..())
|
||||
return
|
||||
|
||||
updatemodules(TRUE)
|
||||
|
||||
var/dat = ""
|
||||
dat += "<a href='byond://?src=\ref[src];refresh=1'>Refresh</a>"
|
||||
|
||||
if(scanner && HasEfficientPod() && scanner.scan_level > 2)
|
||||
if(!autoprocess)
|
||||
dat += "<a href='byond://?src=\ref[src];task=autoprocess'>Autoprocess</a>"
|
||||
else
|
||||
dat += "<a href='byond://?src=\ref[src];task=stopautoprocess'>Stop autoprocess</a>"
|
||||
else
|
||||
dat += "<span class='linkOff'>Autoprocess</span>"
|
||||
dat += "<h3>Cloning Pod Status</h3>"
|
||||
dat += "<div class='statusDisplay'>[temp] </div>"
|
||||
|
||||
switch(src.menu)
|
||||
if(1)
|
||||
// Modules
|
||||
if (isnull(src.scanner) || !LAZYLEN(pods))
|
||||
dat += "<h3>Modules</h3>"
|
||||
//dat += "<a href='byond://?src=\ref[src];relmodules=1'>Reload Modules</a>"
|
||||
if (isnull(src.scanner))
|
||||
dat += "<font class='bad'>ERROR: No Scanner detected!</font><br>"
|
||||
if (!LAZYLEN(pods))
|
||||
dat += "<font class='bad'>ERROR: No Pod detected</font><br>"
|
||||
|
||||
// Scanner
|
||||
if (!isnull(src.scanner))
|
||||
var/mob/living/scanner_occupant = get_mob_or_brainmob(scanner.occupant)
|
||||
|
||||
dat += "<h3>Scanner Functions</h3>"
|
||||
|
||||
dat += "<div class='statusDisplay'>"
|
||||
if(!scanner_occupant)
|
||||
dat += "Scanner Unoccupied"
|
||||
else if(loading)
|
||||
dat += "[scanner_occupant] => Scanning..."
|
||||
else
|
||||
if(scanner_occupant.ckey != scantemp_ckey)
|
||||
scantemp = "Ready to Scan"
|
||||
scantemp_ckey = scanner_occupant.ckey
|
||||
dat += "[scanner_occupant] => [scantemp]"
|
||||
dat += "</div>"
|
||||
|
||||
if(scanner_occupant)
|
||||
dat += "<a href='byond://?src=\ref[src];scan=1'>Start Scan</a>"
|
||||
dat += "<br><a href='byond://?src=\ref[src];lock=1'>[src.scanner.locked ? "Unlock Scanner" : "Lock Scanner"]</a>"
|
||||
else
|
||||
dat += "<span class='linkOff'>Start Scan</span>"
|
||||
|
||||
// Database
|
||||
dat += "<h3>Database Functions</h3>"
|
||||
if (src.records.len && src.records.len > 0)
|
||||
dat += "<a href='byond://?src=\ref[src];menu=2'>View Records ([src.records.len])</a><br>"
|
||||
else
|
||||
dat += "<span class='linkOff'>View Records (0)</span><br>"
|
||||
if (src.diskette)
|
||||
dat += "<a href='byond://?src=\ref[src];disk=eject'>Eject Disk</a><br>"
|
||||
|
||||
|
||||
|
||||
if(2)
|
||||
dat += "<h3>Current records</h3>"
|
||||
dat += "<a href='byond://?src=\ref[src];menu=1'><< Back</a><br><br>"
|
||||
for(var/datum/data/record/R in records)
|
||||
dat += "<h4>[R.fields["name"]]</h4>Scan ID [R.fields["id"]] <a href='byond://?src=\ref[src];view_rec=[R.fields["id"]]'>View Record</a>"
|
||||
if(3)
|
||||
dat += "<h3>Selected Record</h3>"
|
||||
dat += "<a href='byond://?src=\ref[src];menu=2'><< Back</a><br>"
|
||||
|
||||
if (!src.active_record)
|
||||
dat += "<font class='bad'>Record not found.</font>"
|
||||
else
|
||||
dat += "<h4>[src.active_record.fields["name"]]</h4>"
|
||||
dat += "Scan ID [src.active_record.fields["id"]] <a href='byond://?src=\ref[src];clone=[active_record.fields["id"]]'>Clone</a><br>"
|
||||
|
||||
var/obj/item/implant/health/H = locate(src.active_record.fields["imp"])
|
||||
|
||||
if ((H) && (istype(H)))
|
||||
dat += "<b>Health Implant Data:</b><br />[H.sensehealth()]<br><br />"
|
||||
else
|
||||
dat += "<font class='bad'>Unable to locate Health Implant.</font><br /><br />"
|
||||
|
||||
dat += "<b>Unique Identifier:</b><br /><span class='highlight'>[src.active_record.fields["UI"]]</span><br>"
|
||||
dat += "<b>Structural Enzymes:</b><br /><span class='highlight'>[src.active_record.fields["SE"]]</span><br>"
|
||||
|
||||
if(diskette && diskette.fields)
|
||||
dat += "<div class='block'>"
|
||||
dat += "<h4>Inserted Disk</h4>"
|
||||
dat += "<b>Contents:</b> "
|
||||
var/list/L = list()
|
||||
if(diskette.fields["UI"])
|
||||
L += "Unique Identifier"
|
||||
if(diskette.fields["UE"] && diskette.fields["name"] && diskette.fields["blood_type"])
|
||||
L += "Unique Enzymes"
|
||||
if(diskette.fields["SE"])
|
||||
L += "Structural Enzymes"
|
||||
dat += english_list(L, "Empty", " + ", " + ")
|
||||
dat += "<br /><a href='byond://?src=\ref[src];disk=load'>Load from Disk</a>"
|
||||
|
||||
dat += "<br /><a href='byond://?src=\ref[src];disk=save'>Save to Disk</a>"
|
||||
dat += "</div>"
|
||||
|
||||
dat += "<font size=1><a href='byond://?src=\ref[src];del_rec=1'>Delete Record</a></font>"
|
||||
|
||||
if(4)
|
||||
if (!src.active_record)
|
||||
src.menu = 2
|
||||
dat = "[src.temp]<br>"
|
||||
dat += "<h3>Confirm Record Deletion</h3>"
|
||||
|
||||
dat += "<b><a href='byond://?src=\ref[src];del_rec=1'>Scan card to confirm.</a></b><br>"
|
||||
dat += "<b><a href='byond://?src=\ref[src];menu=3'>Cancel</a></b>"
|
||||
|
||||
|
||||
var/datum/browser/popup = new(user, "cloning", "Cloning System Control")
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/computer/cloning/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(loading)
|
||||
return
|
||||
|
||||
if(href_list["task"])
|
||||
switch(href_list["task"])
|
||||
if("autoprocess")
|
||||
autoprocess = 1
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
if("stopautoprocess")
|
||||
autoprocess = 0
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
|
||||
else if ((href_list["scan"]) && !isnull(scanner) && scanner.is_operational())
|
||||
scantemp = ""
|
||||
|
||||
loading = 1
|
||||
src.updateUsrDialog()
|
||||
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
|
||||
say("Initiating scan...")
|
||||
|
||||
spawn(20)
|
||||
src.scan_occupant(scanner.occupant)
|
||||
|
||||
loading = 0
|
||||
src.updateUsrDialog()
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
|
||||
|
||||
//No locking an open scanner.
|
||||
else if ((href_list["lock"]) && !isnull(scanner) && scanner.is_operational())
|
||||
if ((!scanner.locked) && (scanner.occupant))
|
||||
scanner.locked = TRUE
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
else
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
else
|
||||
scanner.locked = FALSE
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
|
||||
else if(href_list["view_rec"])
|
||||
playsound(src, "terminal_type", 25, 0)
|
||||
src.active_record = find_record("id", href_list["view_rec"], records)
|
||||
if(active_record)
|
||||
if(!active_record.fields["ckey"])
|
||||
records -= active_record
|
||||
active_record = null
|
||||
src.temp = "<font class='bad'>Record Corrupt</font>"
|
||||
else
|
||||
src.menu = 3
|
||||
else
|
||||
src.temp = "Record missing."
|
||||
|
||||
else if (href_list["del_rec"])
|
||||
if ((!src.active_record) || (src.menu < 3))
|
||||
return
|
||||
if (src.menu == 3) //If we are viewing a record, confirm deletion
|
||||
src.temp = "Delete record?"
|
||||
src.menu = 4
|
||||
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
|
||||
|
||||
else if (src.menu == 4)
|
||||
var/obj/item/card/id/C = usr.get_active_held_item()
|
||||
if (istype(C)||istype(C, /obj/item/device/pda))
|
||||
if(src.check_access(C))
|
||||
src.temp = "[src.active_record.fields["name"]] => Record deleted."
|
||||
src.records.Remove(active_record)
|
||||
active_record = null
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
src.menu = 2
|
||||
else
|
||||
src.temp = "<font class='bad'>Access Denied.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
|
||||
else if (href_list["disk"]) //Load or eject.
|
||||
switch(href_list["disk"])
|
||||
if("load")
|
||||
if (!diskette || !istype(diskette.fields) || !diskette.fields["name"] || !diskette.fields)
|
||||
src.temp = "<font class='bad'>Load error.</font>"
|
||||
src.updateUsrDialog()
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
return
|
||||
if (!src.active_record)
|
||||
src.temp = "<font class='bad'>Record error.</font>"
|
||||
src.menu = 1
|
||||
src.updateUsrDialog()
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
return
|
||||
|
||||
for(var/key in diskette.fields)
|
||||
src.active_record.fields[key] = diskette.fields[key]
|
||||
src.temp = "Load successful."
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
|
||||
if("eject")
|
||||
if(src.diskette)
|
||||
src.diskette.loc = src.loc
|
||||
src.diskette = null
|
||||
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
|
||||
if("save")
|
||||
if(!diskette || diskette.read_only || !active_record || !active_record.fields)
|
||||
src.temp = "<font class='bad'>Save error.</font>"
|
||||
src.updateUsrDialog()
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
return
|
||||
|
||||
diskette.fields = active_record.fields.Copy()
|
||||
diskette.name = "data disk - '[src.diskette.fields["name"]]'"
|
||||
src.temp = "Save successful."
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
|
||||
else if (href_list["refresh"])
|
||||
src.updateUsrDialog()
|
||||
playsound(src, "terminal_type", 25, 0)
|
||||
|
||||
else if (href_list["clone"])
|
||||
var/datum/data/record/C = find_record("id", href_list["clone"], records)
|
||||
//Look for that player! They better be dead!
|
||||
if(C)
|
||||
var/obj/machinery/clonepod/pod = GetAvailablePod()
|
||||
//Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs.
|
||||
if(!LAZYLEN(pods))
|
||||
temp = "<font class='bad'>No Clonepods detected.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
else if(!pod)
|
||||
temp = "<font class='bad'>No Clonepods available.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
else if(!config.revival_cloning)
|
||||
temp = "<font class='bad'>Unable to initiate cloning cycle.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
else if(pod.occupant)
|
||||
temp = "<font class='bad'>Cloning cycle already in progress.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
else if(pod.growclone(C.fields["ckey"], C.fields["name"], C.fields["UI"], C.fields["SE"], C.fields["mind"], C.fields["mrace"], C.fields["features"], C.fields["factions"]))
|
||||
temp = "[C.fields["name"]] => <font class='good'>Cloning cycle in progress...</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
records.Remove(C)
|
||||
if(active_record == C)
|
||||
active_record = null
|
||||
menu = 1
|
||||
else
|
||||
temp = "[C.fields["name"]] => <font class='bad'>Initialisation failure.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
|
||||
else
|
||||
temp = "<font class='bad'>Data corruption.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
|
||||
else if (href_list["menu"])
|
||||
src.menu = text2num(href_list["menu"])
|
||||
playsound(src, "terminal_type", 25, 0)
|
||||
|
||||
src.add_fingerprint(usr)
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
/obj/machinery/computer/cloning/proc/scan_occupant(occupant)
|
||||
var/mob/living/mob_occupant = get_mob_or_brainmob(occupant)
|
||||
var/datum/dna/dna
|
||||
if(iscarbon(mob_occupant))
|
||||
var/mob/living/carbon/C = mob_occupant
|
||||
dna = C.has_dna()
|
||||
if(isbrain(mob_occupant))
|
||||
var/mob/living/brain/B = mob_occupant
|
||||
dna = B.stored_dna
|
||||
|
||||
if(!istype(dna))
|
||||
scantemp = "<font class='bad'>Unable to locate valid genetic data.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
return
|
||||
if(mob_occupant.suiciding || mob_occupant.hellbound)
|
||||
scantemp = "<font class='bad'>Subject's brain is not responding to scanning stimuli.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
return
|
||||
if((mob_occupant.disabilities & NOCLONE) && (src.scanner.scan_level < 2))
|
||||
scantemp = "<font class='bad'>Subject no longer contains the fundamental materials required to create a living clone.</font>"
|
||||
playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0)
|
||||
return
|
||||
if ((!mob_occupant.ckey) || (!mob_occupant.client))
|
||||
scantemp = "<font class='bad'>Mental interface failure.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
return
|
||||
if (find_record("ckey", mob_occupant.ckey, records))
|
||||
scantemp = "<font class='average'>Subject already in database.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
return
|
||||
|
||||
var/datum/data/record/R = new()
|
||||
if(dna.species)
|
||||
// We store the instance rather than the path, because some
|
||||
// species (abductors, slimepeople) store state in their
|
||||
// species datums
|
||||
R.fields["mrace"] = dna.species
|
||||
else
|
||||
var/datum/species/rando_race = pick(config.roundstart_races)
|
||||
R.fields["mrace"] = rando_race.type
|
||||
|
||||
R.fields["ckey"] = mob_occupant.ckey
|
||||
R.fields["name"] = mob_occupant.real_name
|
||||
R.fields["id"] = copytext(md5(mob_occupant.real_name), 2, 6)
|
||||
R.fields["UE"] = dna.unique_enzymes
|
||||
R.fields["UI"] = dna.uni_identity
|
||||
R.fields["SE"] = dna.struc_enzymes
|
||||
R.fields["blood_type"] = dna.blood_type
|
||||
R.fields["features"] = dna.features
|
||||
R.fields["factions"] = mob_occupant.faction
|
||||
|
||||
if (!isnull(mob_occupant.mind)) //Save that mind so traitors can continue traitoring after cloning.
|
||||
R.fields["mind"] = "\ref[mob_occupant.mind]"
|
||||
|
||||
//Add an implant if needed
|
||||
var/obj/item/implant/health/imp
|
||||
for(var/obj/item/implant/health/HI in mob_occupant.implants)
|
||||
imp = HI
|
||||
break
|
||||
if(!imp)
|
||||
imp = new /obj/item/implant/health(mob_occupant)
|
||||
imp.implant(mob_occupant)
|
||||
R.fields["imp"] = "\ref[imp]"
|
||||
|
||||
src.records += R
|
||||
scantemp = "Subject successfully scanned."
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
|
||||
else if(href_list["view_rec"])
|
||||
playsound(src, "terminal_type", 25, 0)
|
||||
src.active_record = find_record("id", href_list["view_rec"], records)
|
||||
if(active_record)
|
||||
if(!active_record.fields["ckey"])
|
||||
records -= active_record
|
||||
active_record = null
|
||||
src.temp = "<font class='bad'>Record Corrupt</font>"
|
||||
else
|
||||
src.menu = 3
|
||||
else
|
||||
src.temp = "Record missing."
|
||||
|
||||
else if (href_list["del_rec"])
|
||||
if ((!src.active_record) || (src.menu < 3))
|
||||
return
|
||||
if (src.menu == 3) //If we are viewing a record, confirm deletion
|
||||
src.temp = "Delete record?"
|
||||
src.menu = 4
|
||||
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
|
||||
|
||||
else if (src.menu == 4)
|
||||
var/obj/item/card/id/C = usr.get_active_held_item()
|
||||
if (istype(C)||istype(C, /obj/item/device/pda))
|
||||
if(src.check_access(C))
|
||||
src.temp = "[src.active_record.fields["name"]] => Record deleted."
|
||||
src.records.Remove(active_record)
|
||||
active_record = null
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
src.menu = 2
|
||||
else
|
||||
src.temp = "<font class='bad'>Access Denied.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
|
||||
else if (href_list["disk"]) //Load or eject.
|
||||
switch(href_list["disk"])
|
||||
if("load")
|
||||
if (!diskette || !istype(diskette.fields) || !diskette.fields["name"] || !diskette.fields)
|
||||
src.temp = "<font class='bad'>Load error.</font>"
|
||||
src.updateUsrDialog()
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
return
|
||||
if (!src.active_record)
|
||||
src.temp = "<font class='bad'>Record error.</font>"
|
||||
src.menu = 1
|
||||
src.updateUsrDialog()
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
return
|
||||
|
||||
for(var/key in diskette.fields)
|
||||
src.active_record.fields[key] = diskette.fields[key]
|
||||
src.temp = "Load successful."
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
|
||||
if("eject")
|
||||
if(src.diskette)
|
||||
src.diskette.forceMove(drop_location())
|
||||
src.diskette = null
|
||||
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
|
||||
if("save")
|
||||
if(!diskette || diskette.read_only || !active_record || !active_record.fields)
|
||||
src.temp = "<font class='bad'>Save error.</font>"
|
||||
src.updateUsrDialog()
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
return
|
||||
|
||||
diskette.fields = active_record.fields.Copy()
|
||||
diskette.name = "data disk - '[src.diskette.fields["name"]]'"
|
||||
src.temp = "Save successful."
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
|
||||
else if (href_list["refresh"])
|
||||
src.updateUsrDialog()
|
||||
playsound(src, "terminal_type", 25, 0)
|
||||
|
||||
else if (href_list["clone"])
|
||||
var/datum/data/record/C = find_record("id", href_list["clone"], records)
|
||||
//Look for that player! They better be dead!
|
||||
if(C)
|
||||
var/obj/machinery/clonepod/pod = GetAvailablePod()
|
||||
//Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs.
|
||||
if(!LAZYLEN(pods))
|
||||
temp = "<font class='bad'>No Clonepods detected.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
else if(!pod)
|
||||
temp = "<font class='bad'>No Clonepods available.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
else if(!CONFIG_GET(flag/revival_cloning))
|
||||
temp = "<font class='bad'>Unable to initiate cloning cycle.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
else if(pod.occupant)
|
||||
temp = "<font class='bad'>Cloning cycle already in progress.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
else if(pod.growclone(C.fields["ckey"], C.fields["name"], C.fields["UI"], C.fields["SE"], C.fields["mind"], C.fields["mrace"], C.fields["features"], C.fields["factions"]))
|
||||
temp = "[C.fields["name"]] => <font class='good'>Cloning cycle in progress...</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
records.Remove(C)
|
||||
if(active_record == C)
|
||||
active_record = null
|
||||
menu = 1
|
||||
else
|
||||
temp = "[C.fields["name"]] => <font class='bad'>Initialisation failure.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
|
||||
else
|
||||
temp = "<font class='bad'>Data corruption.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
|
||||
else if (href_list["menu"])
|
||||
src.menu = text2num(href_list["menu"])
|
||||
playsound(src, "terminal_type", 25, 0)
|
||||
|
||||
src.add_fingerprint(usr)
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
/obj/machinery/computer/cloning/proc/scan_occupant(occupant)
|
||||
var/mob/living/mob_occupant = get_mob_or_brainmob(occupant)
|
||||
var/datum/dna/dna
|
||||
if(iscarbon(mob_occupant))
|
||||
var/mob/living/carbon/C = mob_occupant
|
||||
dna = C.has_dna()
|
||||
if(isbrain(mob_occupant))
|
||||
var/mob/living/brain/B = mob_occupant
|
||||
dna = B.stored_dna
|
||||
|
||||
if(!istype(dna))
|
||||
scantemp = "<font class='bad'>Unable to locate valid genetic data.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
return
|
||||
if(mob_occupant.suiciding || mob_occupant.hellbound)
|
||||
scantemp = "<font class='bad'>Subject's brain is not responding to scanning stimuli.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
return
|
||||
if((mob_occupant.disabilities & NOCLONE) && (src.scanner.scan_level < 2))
|
||||
scantemp = "<font class='bad'>Subject no longer contains the fundamental materials required to create a living clone.</font>"
|
||||
playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0)
|
||||
return
|
||||
if ((!mob_occupant.ckey) || (!mob_occupant.client))
|
||||
scantemp = "<font class='bad'>Mental interface failure.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
return
|
||||
if (find_record("ckey", mob_occupant.ckey, records))
|
||||
scantemp = "<font class='average'>Subject already in database.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
return
|
||||
|
||||
var/datum/data/record/R = new()
|
||||
if(dna.species)
|
||||
// We store the instance rather than the path, because some
|
||||
// species (abductors, slimepeople) store state in their
|
||||
// species datums
|
||||
R.fields["mrace"] = dna.species
|
||||
else
|
||||
var/datum/species/rando_race = pick(CONFIG_GET(keyed_flag_list/roundstart_races))
|
||||
R.fields["mrace"] = rando_race.type
|
||||
|
||||
R.fields["ckey"] = mob_occupant.ckey
|
||||
R.fields["name"] = mob_occupant.real_name
|
||||
R.fields["id"] = copytext(md5(mob_occupant.real_name), 2, 6)
|
||||
R.fields["UE"] = dna.unique_enzymes
|
||||
R.fields["UI"] = dna.uni_identity
|
||||
R.fields["SE"] = dna.struc_enzymes
|
||||
R.fields["blood_type"] = dna.blood_type
|
||||
R.fields["features"] = dna.features
|
||||
R.fields["factions"] = mob_occupant.faction
|
||||
|
||||
if (!isnull(mob_occupant.mind)) //Save that mind so traitors can continue traitoring after cloning.
|
||||
R.fields["mind"] = "\ref[mob_occupant.mind]"
|
||||
|
||||
//Add an implant if needed
|
||||
var/obj/item/implant/health/imp
|
||||
for(var/obj/item/implant/health/HI in mob_occupant.implants)
|
||||
imp = HI
|
||||
break
|
||||
if(!imp)
|
||||
imp = new /obj/item/implant/health(mob_occupant)
|
||||
imp.implant(mob_occupant)
|
||||
R.fields["imp"] = "\ref[imp]"
|
||||
|
||||
src.records += R
|
||||
scantemp = "Subject successfully scanned."
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
|
||||
@@ -454,7 +454,7 @@
|
||||
if (src.authenticated==2)
|
||||
dat += "<BR><BR><B>Captain Functions</B>"
|
||||
dat += "<BR>\[ <A HREF='?src=\ref[src];operation=announce'>Make a Captain's Announcement</A> \]"
|
||||
if(config.cross_allowed)
|
||||
if(CONFIG_GET(string/cross_server_address))
|
||||
dat += "<BR>\[ <A HREF='?src=\ref[src];operation=crossserver'>Send a message to an allied station</A> \]"
|
||||
if(SSmapping.config.allow_custom_shuttles == "yes")
|
||||
dat += "<BR>\[ <A HREF='?src=\ref[src];operation=purchase_menu'>Purchase Shuttle</A> \]"
|
||||
|
||||
@@ -43,9 +43,8 @@
|
||||
/obj/machinery/computer/scan_consolenew/attackby(obj/item/I, mob/user, params)
|
||||
if (istype(I, /obj/item/disk/data)) //INSERT SOME DISKETTES
|
||||
if (!src.diskette)
|
||||
if(!user.drop_item())
|
||||
if (!user.transferItemToLoc(I,src))
|
||||
return
|
||||
I.loc = src
|
||||
src.diskette = I
|
||||
to_chat(user, "<span class='notice'>You insert [I].</span>")
|
||||
src.updateUsrDialog()
|
||||
@@ -448,7 +447,7 @@
|
||||
diskette.fields = buffer_slot.Copy()
|
||||
if("ejectdisk")
|
||||
if(diskette)
|
||||
diskette.loc = get_turf(src)
|
||||
diskette.forceMove(drop_location())
|
||||
diskette = null
|
||||
if("setdelayed")
|
||||
if(num)
|
||||
|
||||
@@ -27,9 +27,8 @@
|
||||
/obj/machinery/computer/gulag_teleporter_computer/attackby(obj/item/W, mob/user)
|
||||
if(istype(W, /obj/item/card/id/prisoner))
|
||||
if(!id)
|
||||
if(!user.drop_item())
|
||||
if (!user.transferItemToLoc(W,src))
|
||||
return
|
||||
W.forceMove(src)
|
||||
id = W
|
||||
to_chat(user, "<span class='notice'>You insert [W].</span>")
|
||||
return
|
||||
|
||||
@@ -124,7 +124,7 @@
|
||||
dat += "<tr><td>ID:</td><td>[active1.fields["id"]]</td></tr>"
|
||||
dat += "<tr><td>Sex:</td><td><A href='?src=\ref[src];field=sex'> [active1.fields["sex"]] </A></td></tr>"
|
||||
dat += "<tr><td>Age:</td><td><A href='?src=\ref[src];field=age'> [active1.fields["age"]] </A></td></tr>"
|
||||
if(config.mutant_races)
|
||||
if(CONFIG_GET(flag/join_with_mutant_race))
|
||||
dat += "<tr><td>Species:</td><td><A href='?src=\ref[src];field=species'> [active1.fields["species"]] </A></td></tr>"
|
||||
dat += "<tr><td>Fingerprint:</td><td><A href='?src=\ref[src];field=fingerprint'> [active1.fields["fingerprint"]] </A></td></tr>"
|
||||
dat += "<tr><td>Physical Status:</td><td><A href='?src=\ref[src];field=p_stat'> [active1.fields["p_stat"]] </A></td></tr>"
|
||||
@@ -543,7 +543,7 @@
|
||||
P.info = "<CENTER><B>Medical Record - (MR-[GLOB.data_core.medicalPrintCount])</B></CENTER><BR>"
|
||||
if(active1 in GLOB.data_core.general)
|
||||
P.info += text("Name: [] ID: []<BR>\nSex: []<BR>\nAge: []<BR>", src.active1.fields["name"], src.active1.fields["id"], src.active1.fields["sex"], src.active1.fields["age"])
|
||||
if(config.mutant_races)
|
||||
if(CONFIG_GET(flag/join_with_mutant_race))
|
||||
P.info += "\nSpecies: [active1.fields["species"]]<BR>"
|
||||
P.info += text("\nFingerprint: []<BR>\nPhysical Status: []<BR>\nMental Status: []<BR>", src.active1.fields["fingerprint"], src.active1.fields["p_stat"], src.active1.fields["m_stat"])
|
||||
else
|
||||
|
||||
@@ -186,7 +186,7 @@
|
||||
<tr><td>ID:</td><td><A href='?src=\ref[src];choice=Edit Field;field=id'> [active1.fields["id"]] </A></td></tr>
|
||||
<tr><td>Sex:</td><td><A href='?src=\ref[src];choice=Edit Field;field=sex'> [active1.fields["sex"]] </A></td></tr>
|
||||
<tr><td>Age:</td><td><A href='?src=\ref[src];choice=Edit Field;field=age'> [active1.fields["age"]] </A></td></tr>"}
|
||||
if(config.mutant_races)
|
||||
if(CONFIG_GET(flag/join_with_mutant_race))
|
||||
dat += "<tr><td>Species:</td><td><A href ='?src=\ref[src];choice=Edit Field;field=species'> [active1.fields["species"]] </A></td></tr>"
|
||||
dat += {"<tr><td>Rank:</td><td><A href='?src=\ref[src];choice=Edit Field;field=rank'> [active1.fields["rank"]] </A></td></tr>
|
||||
<tr><td>Fingerprint:</td><td><A href='?src=\ref[src];choice=Edit Field;field=fingerprint'> [active1.fields["fingerprint"]] </A></td></tr>
|
||||
@@ -373,7 +373,7 @@ What a mess.*/
|
||||
P.info = "<CENTER><B>Security Record - (SR-[GLOB.data_core.securityPrintCount])</B></CENTER><BR>"
|
||||
if((istype(active1, /datum/data/record) && GLOB.data_core.general.Find(active1)))
|
||||
P.info += text("Name: [] ID: []<BR>\nSex: []<BR>\nAge: []<BR>", active1.fields["name"], active1.fields["id"], active1.fields["sex"], active1.fields["age"])
|
||||
if(config.mutant_races)
|
||||
if(CONFIG_GET(flag/join_with_mutant_race))
|
||||
P.info += "\nSpecies: [active1.fields["species"]]<BR>"
|
||||
P.info += text("\nFingerprint: []<BR>\nPhysical Status: []<BR>\nMental Status: []<BR>", active1.fields["fingerprint"], active1.fields["p_stat"], active1.fields["m_stat"])
|
||||
else
|
||||
@@ -519,7 +519,7 @@ What a mess.*/
|
||||
G.fields["rank"] = "Unassigned"
|
||||
G.fields["sex"] = "Male"
|
||||
G.fields["age"] = "Unknown"
|
||||
if(config.mutant_races)
|
||||
if(CONFIG_GET(flag/join_with_mutant_race))
|
||||
G.fields["species"] = "Human"
|
||||
G.fields["photo_front"] = new /icon()
|
||||
G.fields["photo_side"] = new /icon()
|
||||
@@ -604,7 +604,7 @@ What a mess.*/
|
||||
active1.fields["age"] = t1
|
||||
if("species")
|
||||
if(istype(active1, /datum/data/record))
|
||||
var/t1 = input("Select a species", "Species Selection") as null|anything in GLOB.roundstart_species
|
||||
var/t1 = input("Select a species", "Species Selection") as null|anything in CONFIG_GET(keyed_flag_list/roundstart_races)
|
||||
if(!canUseSecurityRecordsConsole(usr, t1, a1))
|
||||
return
|
||||
active1.fields["species"] = t1
|
||||
@@ -772,7 +772,7 @@ What a mess.*/
|
||||
if(6)
|
||||
R.fields["m_stat"] = pick("*Insane*", "*Unstable*", "*Watch*", "Stable")
|
||||
if(7)
|
||||
R.fields["species"] = pick(GLOB.roundstart_species)
|
||||
R.fields["species"] = pick(CONFIG_GET(keyed_flag_list/roundstart_races))
|
||||
if(8)
|
||||
var/datum/data/record/G = pick(GLOB.data_core.general)
|
||||
R.fields["photo_front"] = G.fields["photo_front"]
|
||||
|
||||
@@ -196,6 +196,7 @@
|
||||
equip_cooldown = 10
|
||||
energy_drain = 250
|
||||
range = MELEE|RANGED
|
||||
flags_2 = NO_MAT_REDEMPTION_2
|
||||
var/mode = 0 //0 - deconstruct, 1 - wall or floor, 2 - airlock.
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/rcd/New()
|
||||
|
||||
@@ -54,7 +54,7 @@ AI MODULES
|
||||
for(var/mylaw in lawlist)
|
||||
if(mylaw != "")
|
||||
tot_laws++
|
||||
if(tot_laws > config.silicon_max_law_amount && !bypass_law_amt_check)//allows certain boards to avoid this check, eg: reset
|
||||
if(tot_laws > CONFIG_GET(number/silicon_max_law_amount) && !bypass_law_amt_check)//allows certain boards to avoid this check, eg: reset
|
||||
to_chat(user, "<span class='caution'>Not enough memory allocated to [law_datum.owner ? law_datum.owner : "the AI core"]'s law processor to handle this amount of laws.</span>")
|
||||
message_admins("[key_name_admin(user)] tried to upload laws to [law_datum.owner ? key_name_admin(law_datum.owner) : "an AI core"] that would exceed the law cap.")
|
||||
overflow = TRUE
|
||||
|
||||
@@ -123,6 +123,7 @@ obj/item/construction
|
||||
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
|
||||
max_matter = 160
|
||||
flags_2 = NO_MAT_REDEMPTION_2
|
||||
var/mode = 1
|
||||
var/canRturf = 0
|
||||
var/ranged = FALSE
|
||||
|
||||
@@ -1,70 +1,71 @@
|
||||
|
||||
/obj/item/bodybag
|
||||
name = "body bag"
|
||||
desc = "A folded bag designed for the storage and transportation of cadavers."
|
||||
icon = 'icons/obj/bodybag.dmi'
|
||||
icon_state = "bodybag_folded"
|
||||
var/unfoldedbag_path = /obj/structure/closet/body_bag
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
|
||||
/obj/item/bodybag/attack_self(mob/user)
|
||||
deploy_bodybag(user, user.loc)
|
||||
|
||||
/obj/item/bodybag/afterattack(atom/target, mob/user, proximity)
|
||||
if(proximity)
|
||||
if(isopenturf(target))
|
||||
deploy_bodybag(user, target)
|
||||
|
||||
/obj/item/bodybag/proc/deploy_bodybag(mob/user, atom/location)
|
||||
var/obj/structure/closet/body_bag/R = new unfoldedbag_path(location)
|
||||
R.open(user)
|
||||
R.add_fingerprint(user)
|
||||
qdel(src)
|
||||
|
||||
|
||||
// Bluespace bodybag
|
||||
|
||||
/obj/item/bodybag/bluespace
|
||||
name = "bluespace body bag"
|
||||
desc = "A folded bluespace body bag designed for the storage and transportation of cadavers."
|
||||
icon = 'icons/obj/bodybag.dmi'
|
||||
icon_state = "bluebodybag_folded"
|
||||
unfoldedbag_path = /obj/structure/closet/body_bag/bluespace
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
origin_tech = "bluespace=4;materials=4;plasmatech=4"
|
||||
|
||||
/obj/item/bodybag/bluespace/examine(mob/user)
|
||||
..()
|
||||
if(contents.len)
|
||||
to_chat(user, "<span class='notice'>You can make out the shapes of [contents.len] objects through the fabric.</span>")
|
||||
|
||||
/obj/item/bodybag/bluespace/Destroy()
|
||||
for(var/atom/movable/A in contents)
|
||||
A.forceMove(get_turf(src))
|
||||
if(isliving(A))
|
||||
to_chat(A, "<span class='notice'>You suddenly feel the space around you torn apart! You're free!</span>")
|
||||
return ..()
|
||||
|
||||
/obj/item/bodybag/bluespace/deploy_bodybag(mob/user, atom/location)
|
||||
var/obj/structure/closet/body_bag/R = new unfoldedbag_path(location)
|
||||
for(var/atom/movable/A in contents)
|
||||
A.forceMove(R)
|
||||
if(isliving(A))
|
||||
to_chat(A, "<span class='notice'>You suddenly feel air around you! You're free!</span>")
|
||||
R.open(user)
|
||||
R.add_fingerprint(user)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/bodybag/bluespace/container_resist(mob/living/user)
|
||||
if(user.incapacitated())
|
||||
to_chat(user, "<span class='warning'>You can't get out while you're restrained like this!</span>")
|
||||
return
|
||||
user.changeNext_move(CLICK_CD_BREAKOUT)
|
||||
user.last_special = world.time + CLICK_CD_BREAKOUT
|
||||
to_chat(user, "<span class='notice'>You claw at the fabric of [src], trying to tear it open...</span>")
|
||||
to_chat(loc, "<span class='warning'>Someone starts trying to break free of [src]!</span>")
|
||||
if(!do_after(user, 200, target = src))
|
||||
to_chat(loc, "<span class='warning'>The pressure subsides. It seems that they've stopped resisting...</span>")
|
||||
return
|
||||
loc.visible_message("<span class='warning'>[user] suddenly appears in front of [loc]!</span>", "<span class='userdanger'>[user] breaks free of [src]!</span>")
|
||||
qdel(src)
|
||||
/obj/item/bodybag
|
||||
name = "body bag"
|
||||
desc = "A folded bag designed for the storage and transportation of cadavers."
|
||||
icon = 'icons/obj/bodybag.dmi'
|
||||
icon_state = "bodybag_folded"
|
||||
var/unfoldedbag_path = /obj/structure/closet/body_bag
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
|
||||
/obj/item/bodybag/attack_self(mob/user)
|
||||
deploy_bodybag(user, user.loc)
|
||||
|
||||
/obj/item/bodybag/afterattack(atom/target, mob/user, proximity)
|
||||
if(proximity)
|
||||
if(isopenturf(target))
|
||||
deploy_bodybag(user, target)
|
||||
|
||||
/obj/item/bodybag/proc/deploy_bodybag(mob/user, atom/location)
|
||||
var/obj/structure/closet/body_bag/R = new unfoldedbag_path(location)
|
||||
R.open(user)
|
||||
R.add_fingerprint(user)
|
||||
qdel(src)
|
||||
|
||||
|
||||
// Bluespace bodybag
|
||||
|
||||
/obj/item/bodybag/bluespace
|
||||
name = "bluespace body bag"
|
||||
desc = "A folded bluespace body bag designed for the storage and transportation of cadavers."
|
||||
icon = 'icons/obj/bodybag.dmi'
|
||||
icon_state = "bluebodybag_folded"
|
||||
unfoldedbag_path = /obj/structure/closet/body_bag/bluespace
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
flags_2 = NO_MAT_REDEMPTION_2
|
||||
origin_tech = "bluespace=4;materials=4;plasmatech=4"
|
||||
|
||||
/obj/item/bodybag/bluespace/examine(mob/user)
|
||||
..()
|
||||
if(contents.len)
|
||||
to_chat(user, "<span class='notice'>You can make out the shapes of [contents.len] objects through the fabric.</span>")
|
||||
|
||||
/obj/item/bodybag/bluespace/Destroy()
|
||||
for(var/atom/movable/A in contents)
|
||||
A.forceMove(get_turf(src))
|
||||
if(isliving(A))
|
||||
to_chat(A, "<span class='notice'>You suddenly feel the space around you torn apart! You're free!</span>")
|
||||
return ..()
|
||||
|
||||
/obj/item/bodybag/bluespace/deploy_bodybag(mob/user, atom/location)
|
||||
var/obj/structure/closet/body_bag/R = new unfoldedbag_path(location)
|
||||
for(var/atom/movable/A in contents)
|
||||
A.forceMove(R)
|
||||
if(isliving(A))
|
||||
to_chat(A, "<span class='notice'>You suddenly feel air around you! You're free!</span>")
|
||||
R.open(user)
|
||||
R.add_fingerprint(user)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/bodybag/bluespace/container_resist(mob/living/user)
|
||||
if(user.incapacitated())
|
||||
to_chat(user, "<span class='warning'>You can't get out while you're restrained like this!</span>")
|
||||
return
|
||||
user.changeNext_move(CLICK_CD_BREAKOUT)
|
||||
user.last_special = world.time + CLICK_CD_BREAKOUT
|
||||
to_chat(user, "<span class='notice'>You claw at the fabric of [src], trying to tear it open...</span>")
|
||||
to_chat(loc, "<span class='warning'>Someone starts trying to break free of [src]!</span>")
|
||||
if(!do_after(user, 200, target = src))
|
||||
to_chat(loc, "<span class='warning'>The pressure subsides. It seems that they've stopped resisting...</span>")
|
||||
return
|
||||
loc.visible_message("<span class='warning'>[user] suddenly appears in front of [loc]!</span>", "<span class='userdanger'>[user] breaks free of [src]!</span>")
|
||||
qdel(src)
|
||||
|
||||
|
||||
@@ -72,16 +72,15 @@
|
||||
user.visible_message("<span class='suicide'>[user] is jamming [src] up [user.p_their()] nose and into [user.p_their()] brain. It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
return (BRUTELOSS|OXYLOSS)
|
||||
|
||||
/obj/item/toy/crayon/New()
|
||||
..()
|
||||
/obj/item/toy/crayon/Initialize()
|
||||
. = ..()
|
||||
// Makes crayons identifiable in things like grinders
|
||||
if(name == "crayon")
|
||||
name = "[item_color] crayon"
|
||||
|
||||
if(config)
|
||||
if(config.mutant_races == 1)
|
||||
graffiti |= "antilizard"
|
||||
graffiti |= "prolizard"
|
||||
if(CONFIG_GET(flag/join_with_mutant_race))
|
||||
graffiti |= "antilizard"
|
||||
graffiti |= "prolizard"
|
||||
|
||||
all_drawables = graffiti + letters + numerals + oriented + runes + graffiti_large_h
|
||||
drawtype = pick(all_drawables)
|
||||
|
||||
@@ -882,7 +882,8 @@
|
||||
..()
|
||||
|
||||
/obj/item/book/manual/wiki/proc/initialize_wikibook()
|
||||
if(config.wikiurl)
|
||||
var/wikiurl = CONFIG_GET(string/wikiurl)
|
||||
if(wikiurl)
|
||||
dat = {"
|
||||
|
||||
<html><head>
|
||||
@@ -900,7 +901,7 @@
|
||||
}
|
||||
</script>
|
||||
<p id='loading'>You start skimming through the manual...</p>
|
||||
<iframe width='100%' height='97%' onload="pageloaded(this)" src="[config.wikiurl]/[page_link]?printable=yes&remove_links=1" frameborder="0" id="main_frame"></iframe>
|
||||
<iframe width='100%' height='97%' onload="pageloaded(this)" src="[wikiurl]/[page_link]?printable=yes&remove_links=1" frameborder="0" id="main_frame"></iframe>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
max_w_class = WEIGHT_CLASS_GIGANTIC
|
||||
max_combined_w_class = 35
|
||||
resistance_flags = FIRE_PROOF
|
||||
flags_2 = NO_MAT_REDEMPTION_2
|
||||
var/pshoom = 'sound/items/pshoom.ogg'
|
||||
var/alt_sound = 'sound/items/pshoom_2.ogg'
|
||||
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 60, acid = 50)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user