Merge branch 'master' into upstream-merge-31198

This commit is contained in:
LetterJay
2017-10-04 19:06:42 -04:00
committed by GitHub
408 changed files with 77323 additions and 10128 deletions
+10
View File
@@ -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
+9 -3
View File
@@ -9,6 +9,8 @@
#define ismovableatom(A) (istype(A, /atom/movable))
//Turfs
//#define isturf(A) (istype(A, /turf)) This is actually a byond built-in. Added here for completeness sake.
#define isopenturf(A) (istype(A, /turf/open))
#define isindestructiblefloor(A) (istype(A, /turf/open/indestructible))
@@ -136,6 +138,10 @@
#define isitem(A) (istype(A, /obj/item))
#define isstructure(A) (istype(A, /obj/structure))
#define ismecha(A) (istype(A, /obj/mecha))
#define is_cleanable(A) (istype(A, /obj/effect/decal/cleanable) || istype(A, /obj/effect/rune)) //if something is cleanable
#define isorgan(A) (istype(A, /obj/item/organ))
@@ -164,9 +170,9 @@ GLOBAL_LIST_INIT(pointed_types, typecacheof(list(
#define istimer(O) (istype(O, /obj/item/device/assembly/timer))
GLOBAL_LIST_INIT(glass_sheet_types, typecacheof(list(
/obj/item/stack/sheet/glass,
/obj/item/stack/sheet/rglass,
/obj/item/stack/sheet/plasmaglass,
/obj/item/stack/sheet/glass,
/obj/item/stack/sheet/rglass,
/obj/item/stack/sheet/plasmaglass,
/obj/item/stack/sheet/plasmarglass)))
#define is_glass_sheet(O) (is_type_in_typecache(O, GLOB.glass_sheet_types))
+4 -1
View File
@@ -6,7 +6,10 @@
#define PLANE_SPACE -95
#define PLANE_SPACE_PARALLAX -90
#define GAME_PLANE 0
#define GAME_PLANE -1
#define BLACKNESS_PLANE 0 //To keep from conflicts with SEE_BLACKNESS internals
#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
+2
View File
@@ -70,6 +70,8 @@
#define LIGHT_COLOR_TUNGSTEN "#FAE1AF" //Extremely diluted yellow, close to skin color (for some reason). rgb(250, 225, 175)
#define LIGHT_COLOR_HALOGEN "#F0FAFA" //Barely visible cyan-ish hue, as the doctor prescribed. rgb(240, 250, 250)
#define LIGHT_RANGE_FIRE 3 //How many tiles standard fires glow.
#define LIGHTING_PLANE_ALPHA_VISIBLE 255
#define LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE 192
#define LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE 128 //For lighting alpha, small amounts lead to big changes. even at 128 its hard to figure out what is dark and what is light, at 64 you almost can't even tell.
+106 -14
View File
@@ -1,34 +1,126 @@
// /tg/station 13 server tools API v3.1.0.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)
//The current amount of connected clients
#define SERVER_TOOLS_CLIENT_COUNT GLOB.clients.len
#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.1"
#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_API_COMPATIBLE "api_compat"
#define SERVICE_CMD_PLAYER_COUNT "client_count"
#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_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
View File
@@ -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)
+17 -2
View File
@@ -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))
@@ -330,6 +331,20 @@
afk_bracket += 600 // Add a minute to the bracket, for every attempt
return candidates
/proc/considered_alive(datum/mind/M, enforce_human = TRUE)
if(M && M.current)
if(enforce_human)
var/mob/living/carbon/human/H
if(ishuman(M.current))
H = M.current
return M.current.stat != DEAD && !issilicon(M.current) && !isbrain(M.current) && (!H || H.dna.species.id != "memezombies")
else if(isliving(M.current))
return M.current.stat != DEAD
return FALSE
/proc/considered_afk(datum/mind/M)
return !M || !M.current || !M.current.client || M.current.client.is_afk()
/proc/ScreenText(obj/O, maptext="", screen_loc="CENTER-7,CENTER-7", maptext_height=480, maptext_width=480)
if(!isobj(O))
O = new /obj/screen/text()
+115 -116
View File
@@ -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
-1
View File
@@ -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
View File
@@ -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
. += ", "
+4 -4
View File
@@ -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
@@ -443,8 +443,8 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
if(!limited)
t = replacetext(t, "((", "<font size=\"1\">")
t = replacetext(t, "))", "</font>")
t = replacetext(t, regex("^-{3,}$", "gm"), "<hr>")
t = replacetext(t, regex("^\\(-{3,})$", "gm"), "$1")
t = replacetext(t, regex("(-){3,}", "gm"), "<hr>")
t = replacetext(t, regex("^\\((-){3,}\\)$", "gm"), "$1")
// Parse lists
@@ -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
+21
View File
@@ -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)]/", ""))
+1 -58
View File
@@ -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()
+7 -3
View File
@@ -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
View File
@@ -15,6 +15,7 @@ GLOBAL_LIST_INIT(carp_names, world.file2list("strings/names/carp.txt"))
GLOBAL_LIST_INIT(golem_names, world.file2list("strings/names/golem.txt"))
GLOBAL_LIST_INIT(plasmaman_names, world.file2list("strings/names/plasmaman.txt"))
GLOBAL_LIST_INIT(posibrain_names, world.file2list("strings/names/posibrain.txt"))
GLOBAL_LIST_INIT(nightmare_names, world.file2list("strings/names/nightmare.txt"))
GLOBAL_LIST_INIT(verbs, world.file2list("strings/names/verbs.txt"))
-16
View File
@@ -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) = ""
+2 -3
View File
@@ -96,7 +96,7 @@
if(!modifiers["catcher"] && A.IsObscured())
return
if(istype(loc, /obj/mecha))
if(ismecha(loc))
var/obj/mecha/M = loc
return M.click_action(A,src,params)
@@ -327,7 +327,7 @@
ML.pulled(src)
/mob/living/carbon/human/CtrlClick(mob/user)
if(ishuman(user) && Adjacent(user))
if(ishuman(user) && Adjacent(user) && !user.incapacitated())
if(world.time < user.next_move)
return FALSE
var/mob/living/carbon/human/H = user
@@ -359,7 +359,6 @@
else
user.listed_turf = T
user.client.statpanel = T.name
user.Stat() //responsive ui pls
/mob/proc/TurfAdjacent(turf/T)
return T.Adjacent(src)
+1 -1
View File
@@ -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)
+5 -1
View File
@@ -28,7 +28,7 @@
icon_state = "act_equip"
/obj/screen/human/equip/Click()
if(istype(usr.loc, /obj/mecha)) // stops inventory actions in a mech
if(ismecha(usr.loc)) // stops inventory actions in a mech
return 1
var/mob/living/carbon/human/H = usr
H.quick_equip()
@@ -313,11 +313,15 @@
inv.hud = src
inv_slots[inv.slot_id] = inv
inv.update_icon()
update_locked_slots()
/datum/hud/human/update_locked_slots()
if(!mymob)
return
var/mob/living/carbon/human/H = mymob
if(!istype(H) || !H.dna.species)
return
var/datum/species/S = H.dna.species
for(var/obj/screen/inventory/inv in (static_inventory + toggleable_inventory))
if(inv.slot_id)
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -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
+2 -2
View File
@@ -596,10 +596,10 @@ obj/item/projectile/bullet/c10mm/soporific
if((blocked != 100) && isliving(target))
var/mob/living/L = target
L.blur_eyes(6)
if(L.staminaloss >= 40)
if(L.staminaloss >= 60)
L.Sleeping(250)
else
L.adjustStaminaLoss(58)
L.adjustStaminaLoss(25)
return 1
/obj/item/ammo_casing/c10mm/soporific
+25 -1
View File
@@ -30,6 +30,14 @@
item_color = null
tagname = null
/obj/item/clothing/accessory/medal/steele
name = "Insignia Of Steele"
desc = "An intricate pendant given to those who help a key member of the Steele Corporation."
icon = 'icons/obj/custom.dmi'
icon_state = "steele"
item_color = "steele"
medaltype = "medal-silver"
/*DirtyOldHarry*/
/obj/item/lighter/gold
@@ -55,6 +63,12 @@
item_color = "zombscarf"
dog_fashion = /datum/dog_fashion/head
/obj/item/clothing/suit/toggle/labcoat/mad/red
name = "\improper The Mad's labcoat"
desc = "An oddly special looking coat."
icon_state = "labred"
item_state = "labred"
/*PLACEHOLDER*/
@@ -117,4 +131,14 @@
desc = "You would swear this was in your nightmares after eating too many veggies."
icon_state = "hos-g"
item_state = "hos-g"
body_parts_covered = CHEST|GROIN|ARMS|LEGS
body_parts_covered = CHEST|GROIN|ARMS|LEGS
/*Slomek*/
/obj/item/reagent_containers/food/drinks/flask/russian
name = "russian flask"
desc = "Every good russian spaceman knows it's a good idea to bring along a couple of pints of whiskey wherever they go."
icon = 'icons/obj/custom.dmi'
icon_state = "russianflask"
item_state = "russianflask"
volume = 60
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
@@ -24,8 +24,7 @@ GLOBAL_PROTECT(config_dir)
LoadModes()
for(var/I in config_files)
LoadEntries(I)
if(Get(/datum/config_entry/flag/maprotation))
loadmaplist(CONFIG_MAPS_FILE)
loadmaplist(CONFIG_MAPS_FILE)
/datum/controller/configuration/Destroy()
entries_by_type.Cut()
@@ -75,6 +74,10 @@ GLOBAL_PROTECT(config_dir)
if(copytext(L, 1, 2) == "#")
continue
var/lockthis = copytext(L, 1, 2) == "@"
if(lockthis)
L = copytext(L, 2)
var/pos = findtext(L, " ")
var/entry = null
var/value = null
@@ -97,6 +100,9 @@ GLOBAL_PROTECT(config_dir)
log_config("Found [entry] in [filename] when it should have been in [E.resident_file]! Ignoring.")
continue
if(lockthis)
E.protection |= CONFIG_ENTRY_LOCKED
var/validated = E.ValidateAndSet(value)
if(!validated)
log_config("Failed to validate setting \"[value]\" for [entry]")
@@ -170,6 +176,7 @@ GLOBAL_PROTECT(config_dir)
/datum/controller/configuration/proc/loadmaplist(filename)
filename = "[GLOB.config_dir][filename]"
log_config("Loading config file [filename]...")
var/list/Lines = world.file2list(filename)
var/datum/map_config/currentmap = null
@@ -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,354 @@
#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)
CONFIG_DEF(string/serversqlname) // short form server name used for the DB
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
CONFIG_DEF(flag/log_ooc) // log OOC channel
CONFIG_DEF(flag/log_access) // log login/logout
CONFIG_DEF(flag/log_say) // log client say
CONFIG_DEF(flag/log_admin) // log admin actions
protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(flag/log_prayer) // log prayers
CONFIG_DEF(flag/log_law) // log lawchanges
CONFIG_DEF(flag/log_game) // log game events
CONFIG_DEF(flag/log_vote) // log voting
CONFIG_DEF(flag/log_whisper) // log client whisper
CONFIG_DEF(flag/log_attack) // log attack messages
CONFIG_DEF(flag/log_emote) // log emotes
CONFIG_DEF(flag/log_adminchat) // log admin chat messages
protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(flag/log_pda) // log pda messages
CONFIG_DEF(flag/log_twitter) // log certain expliotable parrots and other such fun things in a JSON file of twitter valid phrases.
CONFIG_DEF(flag/log_world_topic) // log all world.Topic() calls
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
CONFIG_DEF(flag/no_dead_vote) // dead people can't vote
CONFIG_DEF(flag/allow_metadata) // Metadata is supported.
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)
CONFIG_DEF(flag/norespawn)
CONFIG_DEF(flag/guest_jobban)
CONFIG_DEF(flag/usewhitelist)
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)
CONFIG_DEF(string/banappeals)
CONFIG_DEF(string/wikiurl)
value = "http://www.tgstation13.org/wiki"
CONFIG_DEF(string/forumurl)
value = "http://tgstation13.org/phpBB/index.php"
CONFIG_DEF(string/rulesurl)
value = "http://www.tgstation13.org/wiki/Rules"
CONFIG_DEF(string/githuburl)
value = "https://www.github.com/tgstation/-tg-station"
CONFIG_DEF(number/githubrepoid)
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)
/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
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)
/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)
value = 12
min_val = 0
CONFIG_DEF(number/ipintel_save_bad)
value = 1
min_val = 0
CONFIG_DEF(string/ipintel_domain)
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
+2 -2
View File
@@ -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
+1 -1
View File
@@ -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)
+9 -14
View File
@@ -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)
+2 -2
View File
@@ -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
+18 -14
View File
@@ -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
+1 -1
View File
@@ -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)
+5 -4
View File
@@ -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)
+1 -1
View File
@@ -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)))
+47 -39
View File
@@ -22,47 +22,54 @@ SUBSYSTEM_DEF(persistence)
/datum/controller/subsystem/persistence/proc/LoadSatchels()
var/placed_satchel = 0
var/path
var/obj/item/storage/backpack/satchel/flat/F = new()
if(fexists("data/npc_saves/SecretSatchels.sav")) //legacy compatability to convert old format to new
if(fexists("data/npc_saves/SecretSatchels.sav")) //legacy conversion. Will only ever run once.
var/savefile/secret_satchels = new /savefile("data/npc_saves/SecretSatchels.sav")
var/sav_text
secret_satchels[SSmapping.config.map_name] >> sav_text
fdel("data/npc_saves/SecretSatchels.sav")
if(sav_text)
old_secret_satchels = splittext(sav_text,"#")
if(old_secret_satchels.len >= 20)
var/satchel_string = pick_n_take(old_secret_satchels)
for(var/map in secret_satchels)
var/json_file = file("data/npc_saves/SecretSatchels[map].json")
var/list/legacy_secret_satchels = splittext(secret_satchels[map],"#")
var/list/satchels = list()
for(var/i=1,i<=legacy_secret_satchels.len,i++)
var/satchel_string = legacy_secret_satchels[i]
var/list/chosen_satchel = splittext(satchel_string,"|")
if(chosen_satchel.len == 3)
F.x = text2num(chosen_satchel[1])
F.y = text2num(chosen_satchel[2])
F.z = ZLEVEL_STATION_PRIMARY
path = text2path(chosen_satchel[3])
else
var/json_file = file("data/npc_saves/SecretSatchels[SSmapping.config.map_name].json")
if(!fexists(json_file))
return
var/list/json = json_decode(file2text(json_file))
old_secret_satchels = json["data"]
if(old_secret_satchels.len)
if(old_secret_satchels.len >= 20) //guards against low drop pools assuring that one player cannot reliably find his own gear.
var/pos = rand(1, old_secret_satchels.len)
old_secret_satchels.Cut(pos, pos+1)
F.x = old_secret_satchels[pos]["x"]
F.y = old_secret_satchels[pos]["y"]
F.z = ZLEVEL_STATION_PRIMARY
path = text2path(old_secret_satchels[pos]["saved_obj"])
if(!ispath(path))
return
if(isfloorturf(F.loc) && !istype(F.loc, /turf/open/floor/plating/))
F.hide(1)
new path(F)
placed_satchel++
var/list/free_satchels = list()
var/list/data = list()
data["x"] = text2num(chosen_satchel[1])
data["y"] = text2num(chosen_satchel[2])
data["saved_obj"] = chosen_satchel[3]
satchels += list(data)
var/list/file_data = list()
file_data["data"] = satchels
WRITE_FILE(json_file, json_encode(file_data))
fdel("data/npc_saves/SecretSatchels.sav")
var/json_file = file("data/npc_saves/SecretSatchels[SSmapping.config.map_name].json")
var/list/json = list()
if(fexists(json_file))
json = json_decode(file2text(json_file))
old_secret_satchels = json["data"]
var/obj/item/storage/backpack/satchel/flat/F
if(old_secret_satchels && old_secret_satchels.len >= 10) //guards against low drop pools assuring that one player cannot reliably find his own gear.
var/pos = rand(1, old_secret_satchels.len)
F = new()
old_secret_satchels.Cut(pos, pos+1 % old_secret_satchels.len)
F.x = old_secret_satchels[pos]["x"]
F.y = old_secret_satchels[pos]["y"]
F.z = ZLEVEL_STATION_PRIMARY
path = text2path(old_secret_satchels[pos]["saved_obj"])
if(F)
if(isfloorturf(F.loc) && !istype(F.loc, /turf/open/floor/plating/))
F.hide(1)
if(ispath(path))
new path(F)
placed_satchel++
var/free_satchels = 0
for(var/turf/T in shuffle(block(locate(TRANSITIONEDGE,TRANSITIONEDGE,ZLEVEL_STATION_PRIMARY), locate(world.maxx-TRANSITIONEDGE,world.maxy-TRANSITIONEDGE,ZLEVEL_STATION_PRIMARY)))) //Nontrivially expensive but it's roundstart only
if(isfloorturf(T) && !istype(T, /turf/open/floor/plating/))
free_satchels += new /obj/item/storage/backpack/satchel/flat/secret(T)
if(!isemptylist(free_satchels) && ((free_satchels.len + placed_satchel) >= (50 - old_secret_satchels.len) * 0.1)) //up to six tiles, more than enough to kill anything that moves
new /obj/item/storage/backpack/satchel/flat/secret(T)
free_satchels++
if((free_satchels + placed_satchel) == 10) //ten tiles, more than enough to kill anything that moves
break
/datum/controller/subsystem/persistence/proc/LoadPoly()
@@ -176,8 +183,8 @@ SUBSYSTEM_DEF(persistence)
CollectRoundtype()
/datum/controller/subsystem/persistence/proc/CollectSecretSatchels()
var/list/satchels = list()
satchel_blacklist = typecacheof(list(/obj/item/stack/tile/plasteel, /obj/item/crowbar))
var/list/satchels_to_add = list()
for(var/A in new_secret_satchels)
var/obj/item/storage/backpack/satchel/flat/F = A
if(QDELETED(F) || F.z != ZLEVEL_STATION_PRIMARY || F.invisibility != INVISIBILITY_MAXIMUM)
@@ -196,11 +203,12 @@ SUBSYSTEM_DEF(persistence)
data["x"] = F.x
data["y"] = F.y
data["saved_obj"] = pick(savable_obj)
satchels += list(data)
satchels_to_add += list(data)
var/json_file = file("data/npc_saves/SecretSatchels[SSmapping.config.map_name].json")
var/list/file_data = list()
file_data["data"] = satchels
fdel(json_file)
file_data["data"] = old_secret_satchels + satchels_to_add
WRITE_FILE(json_file, json_encode(file_data))
/datum/controller/subsystem/persistence/proc/CollectChiselMessages()
+12 -9
View File
@@ -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
+3 -3
View File
@@ -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)
+1 -1
View File
@@ -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)
+14 -9
View File
@@ -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
@@ -333,6 +335,8 @@ SUBSYSTEM_DEF(ticker)
var/num_shuttle_escapees = 0
to_chat(world, "<BR><BR><BR><FONT size=3><B>The round has ended.</B></FONT>")
if(LAZYLEN(GLOB.round_end_notifiees))
send2irc("Notice", "[GLOB.round_end_notifiees.Join(", ")] the round has ended.")
/* var/nocredits = config.no_credits_round_end
for(var/client/C in GLOB.clients)
@@ -429,7 +433,7 @@ SUBSYSTEM_DEF(ticker)
CHECK_TICK
if(config.cross_allowed)
if(CONFIG_GET(string/cross_server_address))
send_news_report()
CHECK_TICK
@@ -495,7 +499,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 +508,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 +522,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 +532,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 +692,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)
+17 -14
View File
@@ -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)
+47
View File
@@ -591,3 +591,50 @@
var/mob/M = owner
var/datum/language_holder/H = M.get_language_holder()
H.open_language_menu(usr)
/datum/action/innate/dash
name = "Dash"
desc = "Teleport to the targeted location."
icon_icon = 'icons/mob/actions/actions_items.dmi'
button_icon_state = "jetboot"
var/charged = TRUE
var/charge_rate = 250
var/mob/living/carbon/human/holder
var/obj/item/dashing_item
var/dash_sound = 'sound/magic/blink.ogg'
var/recharge_sound = 'sound/magic/charge.ogg'
var/beam_effect = "blur"
var/phasein = /obj/effect/temp_visual/dir_setting/ninja/phase
var/phaseout = /obj/effect/temp_visual/dir_setting/ninja/phase/out
/datum/action/innate/dash/Grant(mob/user, obj/dasher)
. = ..()
dashing_item = dasher
holder = user
/datum/action/innate/dash/IsAvailable()
if(charged)
return TRUE
else
return FALSE
/datum/action/innate/dash/Activate()
dashing_item.attack_self(holder) //Used to toggle dash behavior in the dashing item
/datum/action/innate/dash/proc/Teleport(mob/user, atom/target)
var/turf/T = get_turf(target)
if(target in view(user.client.view, get_turf(user)))
var/obj/spot1 = new phaseout(get_turf(user), user.dir)
user.forceMove(T)
playsound(T, dash_sound, 25, 1)
var/obj/spot2 = new phasein(get_turf(user), user.dir)
spot1.Beam(spot2,beam_effect,time=20)
charged = FALSE
holder.update_action_buttons_icon()
addtimer(CALLBACK(src, .proc/charge), charge_rate)
/datum/action/innate/dash/proc/charge()
charged = TRUE
holder.update_action_buttons_icon()
playsound(dashing_item, recharge_sound, 50, 1)
to_chat(holder, "<span class='warning'>[dashing_item] is ready for another jaunt.</span>")
+7 -13
View File
@@ -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)
+19 -19
View File
@@ -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
+2 -2
View File
@@ -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()
+8 -2
View File
@@ -17,6 +17,7 @@
var/show_on_examine
var/list/allowed_typecache
var/last_inserted_type
var/last_inserted_id
var/last_amount_inserted
var/last_insert_success
var/datum/callback/precondition
@@ -116,7 +117,7 @@
if(!amt)
return 0
insert_materials(S,amt)
last_inserted_id = insert_materials(S,amt)
last_inserted_type = S.type
S.use(amt)
last_amount_inserted = amt
@@ -133,17 +134,22 @@
if(!material_amount || !has_space(material_amount))
return 0
insert_materials(I, multiplier)
last_inserted_id = insert_materials(I, multiplier)
last_inserted_type = I.type
last_amount_inserted = material_amount
return material_amount
/datum/component/material_container/proc/insert_materials(obj/item/I, multiplier = 1) //for internal usage only
var/datum/material/M
var/primary_mat
var/max_mat_value = 0
for(var/MAT in materials)
M = materials[MAT]
M.amount += I.materials[MAT] * multiplier
total_amount += I.materials[MAT] * multiplier
if(I.materials[MAT] > max_mat_value)
primary_mat = MAT
return primary_mat
//For consuming material
//mats is a list of types of material to use and the corresponding amounts, example: list(MAT_METAL=100, MAT_GLASS=200)
+1 -1
View File
@@ -24,7 +24,7 @@
if(use_delay_override)
use_delay = use_delay_override
RegisterSignal(list(COMSIG_ATOM_ENTERED, COMSIG_ATOM_BLOB_ACT, COMSIG_ATOM_HULK_ATTACK, COMSIG_PARENT_ATTACKBY, COMSIG_MOVABLE_CROSSED, COMSIG_MOVABLE_COLLIDE, COMSIG_MOVABLE_IMPACT, COMSIG_ITEM_ATTACK, COMSIG_ITEM_ATTACK_OBJ, COMSIG_ITEM_ATTACK_OBJ), .proc/play_squeak)
RegisterSignal(list(COMSIG_ATOM_ENTERED, COMSIG_ATOM_BLOB_ACT, COMSIG_ATOM_HULK_ATTACK, COMSIG_PARENT_ATTACKBY, COMSIG_MOVABLE_CROSSED, COMSIG_MOVABLE_COLLIDE, COMSIG_MOVABLE_IMPACT, COMSIG_ITEM_ATTACK, COMSIG_ITEM_ATTACK_OBJ), .proc/play_squeak)
RegisterSignal(COMSIG_ITEM_ATTACK_SELF, .proc/use_squeak)
RegisterSignal(COMSIG_SHOES_STEP_ACTION, .proc/step_squeak)
+1 -1
View File
@@ -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"
+1 -1
View File
@@ -43,7 +43,7 @@
SSdisease.active_diseases += DD //Add it to the active diseases list, now that it's actually in a mob and being processed.
//Copy properties over. This is so edited diseases persist.
var/list/skipped = list("affected_mob","holder","carrier","stage","type","parent_type","vars","transformed","symptoms")
var/list/skipped = list("affected_mob","holder","carrier","stage","type","parent_type","vars","transformed","symptoms","processing")
for(var/V in DD.vars)
if(V in skipped)
continue
@@ -68,8 +68,8 @@ Bonus
/datum/symptom/viralreverse
name = "Viral aggressive metabolism"
desc = "The virus sacrifices its long term survivability to gain a near-instant spread when inside a host. \
The virus will start at the lastest stage, but will eventually decay and die off by itself."
desc = "The virus sacrifices its long term survivability to nearly instantly fully spread inside a host. \
The virus will start at the last stage, but will eventually decay and die off by itself."
stealth = -2
resistance = 1
stage_speed = 3
+1 -1
View File
@@ -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
View File
@@ -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
+398 -401
View File
@@ -1,401 +1,398 @@
/////////////////////////// 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
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()
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
+1 -1
View File
@@ -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)
+89 -89
View File
@@ -1,90 +1,90 @@
//Just new and forget
/datum/forced_movement
var/atom/movable/victim
var/atom/target
var/last_processed
var/steps_per_tick
var/allow_climbing
var/datum/callback/on_step
var/moved_at_all = FALSE
//as fast as ssfastprocess
/datum/forced_movement/New(atom/movable/_victim, atom/_target, _steps_per_tick = 0.5, _allow_climbing = FALSE, datum/callback/_on_step = null)
victim = _victim
target = _target
steps_per_tick = _steps_per_tick
allow_climbing = _allow_climbing
on_step = _on_step
. = ..()
if(_victim && _target && _steps_per_tick && !_victim.force_moving)
last_processed = world.time
_victim.force_moving = src
START_PROCESSING(SSfastprocess, src)
else
qdel(src) //if you want to overwrite the current forced movement, call qdel(victim.force_moving) before creating this
/datum/forced_movement/Destroy()
if(victim.force_moving == src)
victim.force_moving = null
if(moved_at_all)
victim.forceMove(victim.loc) //get the side effects of moving here that require us to currently not be force_moving aka reslipping on ice
STOP_PROCESSING(SSfastprocess, src)
victim = null
target = null
return ..()
/datum/forced_movement/process()
if(QDELETED(victim) || !victim.loc || QDELETED(target) || !target.loc)
qdel(src)
return
var/steps_to_take = round(steps_per_tick * (world.time - last_processed))
if(steps_to_take)
for(var/i in 1 to steps_to_take)
if(TryMove())
moved_at_all = TRUE
if(on_step)
on_step.InvokeAsync()
else
qdel(src)
return
last_processed = world.time
/datum/forced_movement/proc/TryMove(recursive = FALSE)
var/atom/movable/vic = victim //sanic
var/atom/tar = target
if(!recursive)
. = step_towards(vic, tar)
//shit way for getting around corners
if(!.)
if(tar.x > vic.x)
if(step(vic, EAST))
. = TRUE
else if(tar.x < vic.x)
if(step(vic, WEST))
. = TRUE
if(!.)
if(tar.y > vic.y)
if(step(vic, NORTH))
. = TRUE
else if(tar.y < vic.y)
if(step(vic, SOUTH))
. = TRUE
if(!.)
if(recursive)
return FALSE
else
. = TryMove(TRUE)
. = . && (vic.loc != tar.loc)
//Just new and forget
/datum/forced_movement
var/atom/movable/victim
var/atom/target
var/last_processed
var/steps_per_tick
var/allow_climbing
var/datum/callback/on_step
var/moved_at_all = FALSE
//as fast as ssfastprocess
/datum/forced_movement/New(atom/movable/_victim, atom/_target, _steps_per_tick = 0.5, _allow_climbing = FALSE, datum/callback/_on_step = null)
victim = _victim
target = _target
steps_per_tick = _steps_per_tick
allow_climbing = _allow_climbing
on_step = _on_step
. = ..()
if(_victim && _target && _steps_per_tick && !_victim.force_moving)
last_processed = world.time
_victim.force_moving = src
START_PROCESSING(SSfastprocess, src)
else
qdel(src) //if you want to overwrite the current forced movement, call qdel(victim.force_moving) before creating this
/datum/forced_movement/Destroy()
if(victim.force_moving == src)
victim.force_moving = null
if(moved_at_all)
victim.forceMove(victim.loc) //get the side effects of moving here that require us to currently not be force_moving aka reslipping on ice
STOP_PROCESSING(SSfastprocess, src)
victim = null
target = null
return ..()
/datum/forced_movement/process()
if(QDELETED(victim) || !victim.loc || QDELETED(target) || !target.loc)
qdel(src)
return
var/steps_to_take = round(steps_per_tick * (world.time - last_processed))
if(steps_to_take)
for(var/i in 1 to steps_to_take)
if(TryMove())
moved_at_all = TRUE
if(on_step)
on_step.InvokeAsync()
else
qdel(src)
return
last_processed = world.time
/datum/forced_movement/proc/TryMove(recursive = FALSE)
var/atom/movable/vic = victim //sanic
var/atom/tar = target
if(!recursive)
. = step_towards(vic, tar)
//shit way for getting around corners
if(!.)
if(tar.x > vic.x)
if(step(vic, EAST))
. = TRUE
else if(tar.x < vic.x)
if(step(vic, WEST))
. = TRUE
if(!.)
if(tar.y > vic.y)
if(step(vic, NORTH))
. = TRUE
else if(tar.y < vic.y)
if(step(vic, SOUTH))
. = TRUE
if(!.)
if(recursive)
return FALSE
else
. = TryMove(TRUE)
. = . && (vic.loc != tar.loc)
/mob/Collide(atom/A)
. = ..()
if(force_moving && force_moving.allow_climbing && istype(A, /obj/structure))
var/obj/structure/S = A
if(S.climbable)
S.do_climb(src)
. = ..()
if(force_moving && force_moving.allow_climbing && isstructure(A))
var/obj/structure/S = A
if(S.climbable)
S.do_climb(src)
+28 -74
View File
@@ -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]%")
+6 -1
View File
@@ -63,6 +63,7 @@
var/mob/living/enslaved_to //If this mind's master is another mob (i.e. adamantine golems)
var/datum/language_holder/language_holder
var/unconvertable = FALSE
/datum/mind/New(var/key)
src.key = key
@@ -211,7 +212,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 +1506,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
+31 -3
View File
@@ -71,7 +71,7 @@
/datum/status_effect/vanguard_shield/on_apply()
owner.log_message("gained Vanguard stun immunity", INDIVIDUAL_ATTACK_LOG)
owner.add_stun_absorption("vanguard", 200, 1, "'s yellow aura momentarily intensifies!", "Your ward absorbs the stun!", " radiating with a soft yellow light!")
owner.add_stun_absorption("vanguard", INFINITY, 1, "'s yellow aura momentarily intensifies!", "Your ward absorbs the stun!", " radiating with a soft yellow light!")
owner.visible_message("<span class='warning'>[owner] begins to faintly glow!</span>", "<span class='brass'>You will absorb all stuns for the next twenty seconds.</span>")
owner.SetStun(0, FALSE)
owner.SetKnockdown(0)
@@ -87,7 +87,8 @@
var/vanguard = owner.stun_absorption["vanguard"]
var/stuns_blocked = 0
if(vanguard)
stuns_blocked = round(min(vanguard["stuns_absorbed"] * 0.25, 20))
stuns_blocked = Floor(min(vanguard["stuns_absorbed"] * 0.25, 400))
vanguard["end_time"] = 0 //so it doesn't absorb the stuns we're about to apply
if(owner.stat != DEAD)
var/message_to_owner = "<span class='warning'>You feel your Vanguard quietly fade...</span>"
var/otheractiveabsorptions = FALSE
@@ -95,7 +96,6 @@
if(owner.stun_absorption[i]["end_time"] > world.time && owner.stun_absorption[i]["priority"] > vanguard["priority"])
otheractiveabsorptions = TRUE
if(!GLOB.ratvar_awakens && stuns_blocked && !otheractiveabsorptions)
vanguard["end_time"] = 0 //so it doesn't absorb the stuns we're about to apply
owner.Knockdown(stuns_blocked)
message_to_owner = "<span class='boldwarning'>The weight of the Vanguard's protection crashes down upon you!</span>"
if(stuns_blocked >= 300)
@@ -384,3 +384,31 @@
if(islist(owner.stun_absorption) && owner.stun_absorption["blooddrunk"])
owner.stun_absorption -= "blooddrunk"
/datum/status_effect/sword_spin
id = "Bastard Sword Spin"
duration = 50
tick_interval = 8
alert_type = null
/datum/status_effect/sword_spin/on_apply()
owner.visible_message("<span class='danger'>[owner] begins swinging the sword with inhuman strength!</span>")
var/oldcolor = owner.color
owner.color = "#ff0000"
owner.add_stun_absorption("bloody bastard sword", duration, 2, "doesn't even flinch as the sword's power courses through them!", "You shrug off the stun!", " glowing with a blazing red aura!")
owner.spin(duration,1)
animate(owner, color = oldcolor, time = duration, easing = EASE_IN)
addtimer(CALLBACK(owner, /atom/proc/update_atom_colour), duration)
playsound(owner, 'sound/weapons/fwoosh.wav', 75, 0)
return ..()
/datum/status_effect/sword_spin/tick()
playsound(owner, 'sound/weapons/fwoosh.wav', 75, 0)
var/obj/item/slashy
slashy = owner.get_active_held_item()
for(var/mob/living/M in orange(1,owner))
slashy.attack(M, owner)
/datum/status_effect/sword_spin/on_remove()
owner.visible_message("<span class='warning'>[owner]'s inhuman strength dissipates and the sword's runes grow cold!</span>")
@@ -27,7 +27,7 @@
probability = 90
/datum/weather/ash_storm/proc/is_ash_immune(mob/living/L)
if(istype(L.loc, /obj/mecha)) //Mechs are immune
if(ismecha(L.loc)) //Mechs are immune
return TRUE
if(ishuman(L)) //Are you immune?
var/mob/living/carbon/human/H = L
+253 -253
View File
@@ -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
+5 -1
View File
@@ -151,7 +151,11 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/maintenance/department/medical
name = "Medbay Maintenance"
icon_state = "asmaint"
icon_state = "medbay_maint"
/area/maintenance/department/medical/morgue
name = "Morgue Maintenance"
icon_state = "morgue_maint"
/area/maintenance/department/science
name = "Science Maintenance"
+1 -1
View File
@@ -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
. = ..()
+1
View File
@@ -189,6 +189,7 @@
/atom/proc/CollidedWith(atom/movable/AM)
set waitfor = FALSE
return
// Convenience proc to see if a container is open for chemistry handling
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -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"
+1 -1
View File
@@ -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)
+6 -5
View File
@@ -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)
+18 -10
View File
@@ -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
@@ -77,10 +77,10 @@
return
..()
/obj/effect/proc_holder/changeling/sting/transformation/can_sting(mob/user, mob/target)
/obj/effect/proc_holder/changeling/sting/transformation/can_sting(mob/user, mob/living/carbon/target)
if(!..())
return
if((target.disabilities & HUSK) || !target.has_dna())
if((target.disabilities & HUSK) || !iscarbon(target) || (NOTRANSSTING in target.dna.species.species_traits))
to_chat(user, "<span class='warning'>Our sting appears ineffective against its DNA.</span>")
return 0
return 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))
+4 -2
View File
@@ -53,6 +53,8 @@ Credit where due:
return FALSE
if(M.mind.enslaved_to && !is_servant_of_ratvar(M.mind.enslaved_to))
return FALSE
if(M.mind.unconvertable)
return FALSE
else
return FALSE
if(iscultist(M) || isconstruct(M) || M.isloyal() || ispAI(M))
@@ -107,9 +109,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()
@@ -75,7 +75,7 @@
if(GLOB.ratvar_awakens && L)
L.adjust_fire_stacks(damage_per_tick)
L.IgniteMob()
else if(istype(target, /obj/mecha))
else if(ismecha(target))
var/obj/mecha/M = target
M.take_damage(damage_per_tick * get_efficiency_mod(), BURN, "melee", 1, get_dir(src, M))
@@ -90,7 +90,7 @@
if(isliving(target))
var/mob/living/L = target
to_chat(L, "<span class='neovgre'>\"I SEE YOU!\"</span>\n<span class='userdanger'>[src]'s gaze [GLOB.ratvar_awakens ? "melts you alive" : "burns you"]!</span>")
else if(istype(target, /obj/mecha))
else if(ismecha(target))
var/obj/mecha/M = target
to_chat(M.occupant, "<span class='neovgre'>\"I SEE YOU!\"</span>" )
else if(prob(0.5)) //Extremely low chance because of how fast the subsystem it uses processes
+4 -2
View File
@@ -21,6 +21,8 @@
return FALSE
if(M.mind.enslaved_to && !iscultist(M.mind.enslaved_to))
return FALSE
if(M.mind.unconvertable)
return FALSE
else
return FALSE
if(M.isloyal() || issilicon(M) || isbot(M) || isdrone(M) || is_servant_of_ratvar(M))
@@ -55,10 +57,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
+164
View File
@@ -72,6 +72,170 @@
if(is_servant_of_ratvar(C) && C.reagents)
C.reagents.add_reagent("heparin", 1)
/obj/item/twohanded/required/cult_bastard
name = "bloody bastard sword"
desc = "An enormous sword used by Nar-Sien cultists to rapidly harvest the souls of non-believers."
w_class = WEIGHT_CLASS_HUGE
block_chance = 50
throwforce = 20
force = 35
armour_penetration = 45
throw_speed = 1
throw_range = 3
sharpness = IS_SHARP
light_color = "#ff0000"
attack_verb = list("cleaved", "slashed", "torn", "hacked", "ripped", "diced", "carved")
icon_state = "cultbastard"
item_state = "cultbastard"
hitsound = 'sound/weapons/bladeslice.ogg'
lefthand_file = 'icons/mob/inhands/64x64_lefthand.dmi'
righthand_file = 'icons/mob/inhands/64x64_righthand.dmi'
inhand_x_dimension = 64
inhand_y_dimension = 64
actions_types = list()
flags_2 = SLOWS_WHILE_IN_HAND_2
var/datum/action/innate/dash/cult/jaunt
var/datum/action/innate/cult/spin2win/linked_action
var/spinning = FALSE
var/spin_cooldown = 250
var/list/shards = list()
var/dash_toggled = TRUE
/obj/item/twohanded/required/cult_bastard/Initialize()
. = ..()
set_light(4)
jaunt = new(src)
linked_action = new(src)
/obj/item/twohanded/required/cult_bastard/can_be_pulled(user)
return FALSE
/obj/item/twohanded/required/cult_bastard/attack_self(mob/user)
dash_toggled = !dash_toggled
if(dash_toggled)
to_chat(loc, "<span class='notice'>You raise the [src] and prepare to jaunt with it.</span>")
else
to_chat(loc, "<span class='notice'>You lower the [src] and prepare to swing it normally.</span>")
/obj/item/twohanded/required/cult_bastard/pickup(mob/living/user)
. = ..()
if(!iscultist(user))
if(!is_servant_of_ratvar(user))
to_chat(user, "<span class='cultlarge'>\"I wouldn't advise that.\"</span>")
to_chat(user, "<span class='warning'>An overwhelming sense of nausea overpowers you!</span>")
user.Dizzy(80)
user.Knockdown(30)
return
else
to_chat(user, "<span class='cultlarge'>\"One of Ratvar's toys is trying to play with things [user.p_they()] shouldn't. Cute.\"</span>")
to_chat(user, "<span class='userdanger'>A horrible force yanks at your arm!</span>")
user.emote("scream")
user.apply_damage(30, BRUTE, pick("l_arm", "r_arm"))
user.Knockdown(50)
return
jaunt.Grant(user, src)
linked_action.Grant(user, src)
user.update_icons()
/obj/item/twohanded/required/cult_bastard/dropped(mob/user)
. = ..()
linked_action.Remove(user)
jaunt.Remove(user)
user.update_icons()
/obj/item/twohanded/required/cult_bastard/IsReflect()
if(spinning)
playsound(src, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 75, 1)
return TRUE
else
..()
/obj/item/twohanded/required/cult_bastard/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
if(prob(final_block_chance))
if(attack_type == PROJECTILE_ATTACK)
owner.visible_message("<span class='danger'>[owner] deflects [attack_text] with [src]!</span>")
playsound(src, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 100, 1)
return TRUE
else
playsound(src, 'sound/weapons/parry.ogg', 75, 1)
owner.visible_message("<span class='danger'>[owner] parries [attack_text] with [src]!</span>")
return TRUE
return FALSE
/obj/item/twohanded/required/cult_bastard/afterattack(atom/target, mob/user, proximity, click_parameters)
. = ..()
if(dash_toggled && jaunt.IsAvailable())
jaunt.Teleport(user, target)
return
if(!proximity)
return
if(ishuman(target))
var/mob/living/carbon/human/H = target
if(H.stat != CONSCIOUS)
var/obj/item/device/soulstone/SS = new /obj/item/device/soulstone(src)
SS.attack(H, user)
shards += SS
return
if(istype(target, /obj/structure/constructshell) && contents.len)
var/obj/item/device/soulstone/SS = contents[1]
if(istype(SS) && SS.transfer_soul("CONSTRUCT",target,user))
qdel(SS)
/datum/action/innate/dash/cult
name = "Rend the Veil"
desc = "Use the sword to shear open the flimsy fabric of this reality and teleport to your target."
icon_icon = 'icons/mob/actions/actions_cult.dmi'
button_icon_state = "phaseshift"
dash_sound = 'sound/magic/enter_blood.ogg'
recharge_sound = 'sound/magic/exit_blood.ogg'
beam_effect = "sendbeam"
phasein = /obj/effect/temp_visual/dir_setting/cult/phase
phaseout = /obj/effect/temp_visual/dir_setting/cult/phase/out
/datum/action/innate/dash/cult/IsAvailable()
if(iscultist(holder) && charged)
return TRUE
else
return FALSE
/datum/action/innate/cult/spin2win
name = "Geometer's Fury"
desc = "You draw on the power of the sword's ancient runes, spinning it wildly around you as you become immune to most attacks."
background_icon_state = "bg_demon"
button_icon_state = "sintouch"
var/cooldown = 0
var/mob/living/carbon/human/holder
var/obj/item/twohanded/required/cult_bastard/sword
/datum/action/innate/cult/spin2win/Grant(mob/user, obj/bastard)
. = ..()
sword = bastard
holder = user
/datum/action/innate/cult/spin2win/IsAvailable()
if(iscultist(holder) && cooldown <= world.time)
return TRUE
else
return FALSE
/datum/action/innate/cult/spin2win/Activate()
cooldown = world.time + sword.spin_cooldown
holder.changeNext_move(50)
holder.apply_status_effect(/datum/status_effect/sword_spin)
sword.spinning = TRUE
sword.block_chance = 100
sword.slowdown += 1.5
addtimer(CALLBACK(src, .proc/stop_spinning), 50)
holder.update_action_buttons_icon()
/datum/action/innate/cult/spin2win/proc/stop_spinning()
sword.spinning = FALSE
sword.block_chance = 50
sword.slowdown -= 1.5
sleep(sword.spin_cooldown)
holder.update_action_buttons_icon()
/obj/item/restraints/legcuffs/bola/cult
name = "nar'sien bola"
+1 -6
View File
@@ -100,17 +100,13 @@
if(cooldowntime > world.time)
to_chat(user, "<span class='cultitalic'>The magic in [src] is weak, it will be ready to use again in [DisplayTimeText(cooldowntime - world.time)].</span>")
return
var/choice = alert(user,"You study the schematics etched into the forge...",,"Shielded Robe","Flagellant's Robe","Nar-Sien Hardsuit")
var/choice = alert(user,"You study the schematics etched into the forge...",,"Shielded Robe","Flagellant's Robe","Bastard Sword")
var/pickedtype
switch(choice)
if("Shielded Robe")
pickedtype = /obj/item/clothing/suit/hooded/cultrobes/cult_shield
if("Flagellant's Robe")
pickedtype = /obj/item/clothing/suit/hooded/cultrobes/berserker
<<<<<<< HEAD
if("Nar-Sien Hardsuit")
pickedtype = /obj/item/clothing/suit/space/hardsuit/cult
=======
if("Bastard Sword")
if((world.time - SSticker.round_start_time) >= 12000)
pickedtype = /obj/item/twohanded/required/cult_bastard
@@ -119,7 +115,6 @@
to_chat(user, "<span class='cultitalic'>The forge fires are not yet hot enough for this weapon, give it another [DisplayTimeText(cooldowntime)].</span>")
cooldowntime = 0
return
>>>>>>> e997bc4... Merge pull request #31198 from Jordie0608/apparentlythisbuildcompletedthefirsttimeidkhow
if(src && !QDELETED(src) && anchored && pickedtype && Adjacent(user) && !user.incapacitated() && iscultist(user) && cooldowntime <= world.time)
cooldowntime = world.time + 2400
var/obj/item/N = new pickedtype(get_turf(src))
+5 -4
View File
@@ -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))
+18 -14
View File
@@ -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
+4 -3
View File
@@ -31,15 +31,16 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
var/max_i = 10//number of tries to spawn meteor.
while(!isspaceturf(pickedstart))
var/startSide = pick(GLOB.cardinals)
pickedstart = spaceDebrisStartLoc(startSide, ZLEVEL_STATION_PRIMARY)
pickedgoal = spaceDebrisFinishLoc(startSide, ZLEVEL_STATION_PRIMARY)
var/startZ = pick(GLOB.station_z_levels)
pickedstart = spaceDebrisStartLoc(startSide, startZ)
pickedgoal = spaceDebrisFinishLoc(startSide, startZ)
max_i--
if(max_i<=0)
return
var/Me = pickweight(meteortypes)
var/obj/effect/meteor/M = new Me(pickedstart)
M.dest = pickedgoal
M.z_original = ZLEVEL_STATION_PRIMARY
M.z_original = M.z
spawn(0)
walk_towards(M, M.dest, 1)
@@ -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]")
@@ -468,11 +468,8 @@
return
var/turf/open/floor/F
switch(z) //Only the station/lavaland
if(ZLEVEL_STATION_PRIMARY)
F =find_safe_turf(zlevels = ZLEVEL_STATION_PRIMARY, extended_safety_checks = TRUE)
if(ZLEVEL_LAVALAND)
F = find_safe_turf(zlevels = ZLEVEL_LAVALAND, extended_safety_checks = TRUE)
F = find_safe_turf(zlevels = z, extended_safety_checks = TRUE)
if(!F)
return
// If we're getting rid of a human, slap some energy cuffs on
@@ -502,7 +499,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 +508,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))
@@ -34,17 +34,13 @@
var/list/spawn_locs = list()
for(var/obj/effect/landmark/L in GLOB.landmarks_list)
for(var/obj/effect/landmark/revenantspawn/L in GLOB.landmarks_list)
if(isturf(L.loc))
switch(L.name)
if("revenantspawn")
spawn_locs += L.loc
spawn_locs += L.loc
if(!spawn_locs.len) //If we can't find any revenant spawns, try the carp spawns
for(var/obj/effect/landmark/L in GLOB.landmarks_list)
for(var/obj/effect/landmark/carpspawn/L in GLOB.landmarks_list)
if(isturf(L.loc))
switch(L.name)
if("carpspawn")
spawn_locs += L.loc
spawn_locs += L.loc
if(!spawn_locs.len) //If we can't find either, just spawn the revenant at the player's location
spawn_locs += get_turf(selected)
if(!spawn_locs.len) //If we can't find THAT, then just give up and cry
@@ -23,11 +23,9 @@
player_mind.active = 1
var/list/spawn_locs = list()
for(var/obj/effect/landmark/L in GLOB.landmarks_list)
for(var/obj/effect/landmark/carpspawn/L in GLOB.landmarks_list)
if(isturf(L.loc))
switch(L.name)
if("carpspawn")
spawn_locs += L.loc
spawn_locs += L.loc
if(!spawn_locs)
message_admins("No valid spawn locations found, aborting...")
+1 -1
View File
@@ -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)
+33 -36
View File
@@ -17,14 +17,6 @@
if(owner)
. += owner
/datum/objective/proc/considered_alive(var/datum/mind/M)
if(M && M.current)
var/mob/living/carbon/human/H
if(ishuman(M.current))
H = M.current
return M.current.stat != DEAD && !issilicon(M.current) && !isbrain(M.current) && (!H || H.dna.species.id != "memezombies")
return FALSE
/datum/objective/proc/considered_escaped(datum/mind/M)
if(!considered_alive(M))
return FALSE
@@ -37,9 +29,6 @@
return FALSE
return location.onCentCom() || location.onSyndieBase()
/datum/objective/proc/considered_afk(datum/mind/M)
return !M || !M.current || !M.current.client || M.current.client.is_afk()
/datum/objective/proc/check_completion()
return completed
@@ -348,13 +337,14 @@
return FALSE
return TRUE
//Like survive, but works for silicons and zombies and such.
/datum/objective/survive/exist/considered_alive(var/datum/mind/M)
if(M && M.current)
if(isliving(M.current))
var/mob/living/L = M.current
return L.stat != DEAD
return FALSE
/datum/objective/survive/exist //Like survive, but works for silicons and zombies and such.
/datum/objective/survive/exist/check_completion()
var/list/datum/mind/owners = get_owners()
for(var/datum/mind/M in owners)
if(!considered_alive(M, FALSE))
return FALSE
return TRUE
/datum/objective/martyr
explanation_text = "Die a glorious death."
@@ -506,24 +496,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 +583,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
+10 -8
View File
@@ -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 ..()
@@ -253,12 +253,14 @@
/datum/game_mode/proc/add_revolutionary(datum/mind/rev_mind)
if(rev_mind.assigned_role in GLOB.command_positions)
return 0
return FALSE
var/mob/living/carbon/human/H = rev_mind.current//Check to see if the potential rev is implanted
if(H.isloyal())
return 0
return FALSE
if((rev_mind in revolutionaries) || (rev_mind in head_revolutionaries))
return 0
return FALSE
if(rev_mind.unconvertable)
return FALSE
revolutionaries += rev_mind
if(iscarbon(rev_mind.current))
var/mob/living/carbon/carbon_mob = rev_mind.current
@@ -271,7 +273,7 @@
update_rev_icons_added(rev_mind)
if(jobban_isbanned(rev_mind.current, ROLE_REV))
INVOKE_ASYNC(src, .proc/replace_jobbaned_player, rev_mind.current, ROLE_REV, ROLE_REV)
return 1
return TRUE
//////////////////////////////////////////////////////////////////////////////
//Deals with players being converted from the revolution (Not a rev anymore)// // Modified to handle borged MMIs. Accepts another var if the target is being borged at the time -- Polymorph.
//////////////////////////////////////////////////////////////////////////////
@@ -329,7 +331,7 @@
/datum/game_mode/revolution/proc/check_heads_victory()
for(var/datum/mind/rev_mind in head_revolutionaries)
var/turf/T = get_turf(rev_mind.current)
if((rev_mind) && (rev_mind.current) && (rev_mind.current.stat != DEAD) && T && (T.z in GLOB.station_z_levels))
if(!considered_afk(rev_mind) && considered_alive(rev_mind) && (T.z in GLOB.station_z_levels))
if(ishuman(rev_mind.current))
return 0
return 1
+298 -298
View File
@@ -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")
+8 -6
View File
@@ -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))
+4 -5
View File
@@ -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)
+1 -2
View File
@@ -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
@@ -199,7 +199,6 @@
SSticker.mode.cult -= A.mind
SSticker.mode.update_cult_icons_removed(A.mind)
qdel(T)
user.drop_item()
qdel(src)
else
to_chat(user, "<span class='userdanger'>Creation failed!</span>: The soul stone is empty! Go kill someone!")
+3 -3
View File
@@ -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)

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