diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000000..d7cffbcfb6
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,60 @@
+FROM tgstation/byond:513.1533 as base
+
+FROM base as rust_g
+
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends \
+ git \
+ ca-certificates
+
+WORKDIR /rust_g
+
+RUN apt-get install -y --no-install-recommends \
+ libssl-dev \
+ pkg-config \
+ curl \
+ gcc-multilib \
+ && curl https://sh.rustup.rs -sSf | sh -s -- -y --default-host i686-unknown-linux-gnu \
+ && git init \
+ && git remote add origin https://github.com/tgstation/rust-g
+
+COPY _build_dependencies.sh .
+
+RUN /bin/bash -c "source _build_dependencies.sh \
+ && git fetch --depth 1 origin \$RUST_G_VERSION" \
+ && git checkout FETCH_HEAD \
+ && ~/.cargo/bin/cargo build --release
+
+FROM base as dm_base
+
+WORKDIR /vorestation
+
+FROM dm_base as build
+
+COPY . .
+
+RUN DreamMaker -max_errors 0 vorestation.dme
+
+FROM dm_base
+
+EXPOSE 2303
+
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends software-properties-common \
+ && add-apt-repository ppa:ubuntu-toolchain-r/test \
+ && apt-get update \
+ && apt-get upgrade -y \
+ && apt-get dist-upgrade -y \
+ && apt-get install -y --no-install-recommends \
+ libmariadb2 \
+ mariadb-client \
+ libssl1.0.0 \
+ && rm -rf /var/lib/apt/lists/* \
+ && mkdir -p /root/.byond/bin
+
+COPY --from=rust_g /rust_g/target/release/librust_g.so /root/.byond/bin/rust_g
+COPY --from=build /vorestation/ ./
+
+#VOLUME [ "/vorestation/config", "/vorestation/data" ]
+
+ENTRYPOINT [ "DreamDaemon", "vorestation.dmb", "-port", "2303", "-trusted", "-close", "-verbose" ]
diff --git a/code/__defines/chemistry.dm b/code/__defines/chemistry.dm
index c87391562b..0a98818683 100644
--- a/code/__defines/chemistry.dm
+++ b/code/__defines/chemistry.dm
@@ -50,3 +50,11 @@ var/list/tachycardics = list("coffee", "inaprovaline", "hyperzine", "nitroglyce
var/list/bradycardics = list("neurotoxin", "cryoxadone", "clonexadone", "space_drugs", "stoxin") // Decrease heart rate.
var/list/heartstopper = list("potassium_chlorophoride", "zombie_powder") // This stops the heart.
var/list/cheartstopper = list("potassium_chloride") // This stops the heart when overdose is met. -- c = conditional
+
+#define MAX_PILL_SPRITE 24 //max icon state of the pill sprites
+#define MAX_BOTTLE_SPRITE 4 //max icon state of the pill sprites
+#define MAX_MULTI_AMOUNT 20 // Max number of pills/patches that can be made at once
+#define MAX_UNITS_PER_PILL 60 // Max amount of units in a pill
+#define MAX_UNITS_PER_PATCH 60 // Max amount of units in a patch
+#define MAX_UNITS_PER_BOTTLE 60 // Max amount of units in a bottle (it's volume)
+#define MAX_CUSTOM_NAME_LEN 64 // Max length of a custom pill/condiment/whatever
\ No newline at end of file
diff --git a/code/__defines/materials.dm b/code/__defines/materials.dm
new file mode 100644
index 0000000000..499c974b47
--- /dev/null
+++ b/code/__defines/materials.dm
@@ -0,0 +1,63 @@
+#define DEFAULT_TABLE_MATERIAL "plastic"
+#define DEFAULT_WALL_MATERIAL "steel"
+
+#define MAT_IRON "iron"
+#define MAT_MARBLE "marble"
+#define MAT_STEEL "steel"
+#define MAT_PLASTIC "plastic"
+#define MAT_GLASS "glass"
+#define MAT_SILVER "silver"
+#define MAT_GOLD "gold"
+#define MAT_URANIUM "uranium"
+#define MAT_TITANIUM "titanium"
+#define MAT_PHORON "phoron"
+#define MAT_DIAMOND "diamond"
+#define MAT_SNOW "snow"
+#define MAT_SNOWBRICK "packed snow"
+#define MAT_WOOD "wood"
+#define MAT_LOG "log"
+#define MAT_SIFWOOD "alien wood"
+#define MAT_SIFLOG "alien log"
+#define MAT_STEELHULL "steel hull"
+#define MAT_PLASTEEL "plasteel"
+#define MAT_PLASTEELHULL "plasteel hull"
+#define MAT_DURASTEEL "durasteel"
+#define MAT_DURASTEELHULL "durasteel hull"
+#define MAT_TITANIUMHULL "titanium hull"
+#define MAT_VERDANTIUM "verdantium"
+#define MAT_MORPHIUM "morphium"
+#define MAT_MORPHIUMHULL "morphium hull"
+#define MAT_VALHOLLIDE "valhollide"
+#define MAT_LEAD "lead"
+#define MAT_SUPERMATTER "supermatter"
+#define MAT_METALHYDROGEN "mhydrogen"
+#define MAT_OSMIUM "osmium"
+#define MAT_GRAPHITE "graphite"
+#define MAT_LEATHER "leather"
+#define MAT_CHITIN "chitin"
+#define MAT_CLOTH "cloth"
+#define MAT_SYNCLOTH "syncloth"
+#define MAT_COPPER "copper"
+#define MAT_QUARTZ "quartz"
+#define MAT_TIN "tin"
+#define MAT_VOPAL "void opal"
+#define MAT_ALUMINIUM "aluminium"
+#define MAT_BRONZE "bronze"
+#define MAT_PAINITE "painite"
+#define MAT_BOROSILICATE "borosilicate glass"
+#define MAT_SANDSTONE "sandstone"
+
+#define SHARD_SHARD "shard"
+#define SHARD_SHRAPNEL "shrapnel"
+#define SHARD_STONE_PIECE "piece"
+#define SHARD_SPLINTER "splinters"
+#define SHARD_NONE ""
+
+#define MATERIAL_UNMELTABLE 0x1
+#define MATERIAL_BRITTLE 0x2
+#define MATERIAL_PADDING 0x4
+
+#define DEFAULT_TABLE_MATERIAL "plastic"
+#define DEFAULT_WALL_MATERIAL "steel"
+
+#define TABLE_BRITTLE_MATERIAL_MULTIPLIER 4 // Amount table damage is multiplied by if it is made of a brittle material (e.g. glass)
diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm
index f867182c09..5aca7e0a99 100644
--- a/code/__defines/misc.dm
+++ b/code/__defines/misc.dm
@@ -121,65 +121,6 @@
#define WALL_CAN_OPEN 1
#define WALL_OPENING 2
-#define DEFAULT_TABLE_MATERIAL "plastic"
-#define DEFAULT_WALL_MATERIAL "steel"
-
-#define MAT_IRON "iron"
-#define MAT_MARBLE "marble"
-#define MAT_STEEL "steel"
-#define MAT_PLASTIC "plastic"
-#define MAT_GLASS "glass"
-#define MAT_SILVER "silver"
-#define MAT_GOLD "gold"
-#define MAT_URANIUM "uranium" //Did it
-#define MAT_TITANIUM "titanium"
-#define MAT_PHORON "phoron"
-#define MAT_DIAMOND "diamond"
-#define MAT_SNOW "snow"
-#define MAT_WOOD "wood"
-#define MAT_LOG "log"
-#define MAT_SIFWOOD "alien wood"
-#define MAT_SIFLOG "alien log"
-#define MAT_STEELHULL "steel hull"
-#define MAT_PLASTEEL "plasteel"
-#define MAT_PLASTEELHULL "plasteel hull"
-#define MAT_DURASTEEL "durasteel"
-#define MAT_DURASTEELHULL "durasteel hull"
-#define MAT_TITANIUMHULL "titanium hull"
-#define MAT_VERDANTIUM "verdantium"
-#define MAT_MORPHIUM "morphium"
-#define MAT_MORPHIUMHULL "morphium hull"
-#define MAT_VALHOLLIDE "valhollide"
-#define MAT_LEAD "lead"
-#define MAT_SUPERMATTER "supermatter"
-#define MAT_METALHYDROGEN "mhydrogen"
-#define MAT_OSMIUM "osmium"
-#define MAT_GRAPHITE "graphite"
-#define MAT_LEATHER "leather"
-#define MAT_CHITIN "chitin"
-#define MAT_CLOTH "cloth"
-#define MAT_SYNCLOTH "syncloth"
-#define MAT_COPPER "copper"
-#define MAT_QUARTZ "quartz"
-#define MAT_TIN "tin"
-#define MAT_VOPAL "void opal"
-#define MAT_ALUMINIUM "aluminium"
-#define MAT_BRONZE "bronze"
-#define MAT_PAINITE "painite"
-#define MAT_BOROSILICATE "borosilicate glass"
-
-#define SHARD_SHARD "shard"
-#define SHARD_SHRAPNEL "shrapnel"
-#define SHARD_STONE_PIECE "piece"
-#define SHARD_SPLINTER "splinters"
-#define SHARD_NONE ""
-
-#define MATERIAL_UNMELTABLE 0x1
-#define MATERIAL_BRITTLE 0x2
-#define MATERIAL_PADDING 0x4
-
-#define TABLE_BRITTLE_MATERIAL_MULTIPLIER 4 // Amount table damage is multiplied by if it is made of a brittle material (e.g. glass)
-
#define BOMBCAP_DVSTN_RADIUS (max_explosion_range/4)
#define BOMBCAP_HEAVY_RADIUS (max_explosion_range/2)
#define BOMBCAP_LIGHT_RADIUS max_explosion_range
@@ -504,3 +445,7 @@ GLOBAL_LIST_INIT(all_volume_channels, list(
#define APPEARANCECHANGER_CHANGED_EYES "Eye Color"
#define GET_DECL(D) (ispath(D, /decl) ? (decls_repository.fetched_decls[D] || decls_repository.get_decl(D)) : null)
+
+#define LOADOUT_WHITELIST_OFF 0
+#define LOADOUT_WHITELIST_LAX 1
+#define LOADOUT_WHITELIST_STRICT 2
\ No newline at end of file
diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm
index dccd83f557..a92a89e884 100644
--- a/code/__defines/mobs.dm
+++ b/code/__defines/mobs.dm
@@ -272,6 +272,10 @@
#define TASTE_DULL 0.5 //anything below 30%
#define TASTE_NUMB 0.1 //anything below 150%
+//Used by emotes
+#define VISIBLE_MESSAGE 1
+#define AUDIBLE_MESSAGE 2
+
// If they're in an FBP, what braintype.
#define FBP_NONE ""
#define FBP_CYBORG "Cyborg"
@@ -433,6 +437,8 @@
#define EXAMINE_SKIPLEGS 0x0080
#define EXAMINE_SKIPFEET 0x0100
-#define MAX_NUTRITION 5000 //VOREStation Edit
+#define MAX_NUTRITION 6000 //VOREStation Edit
#define FAKE_INVIS_ALPHA_THRESHOLD 127 // If something's alpha var is at or below this number, certain things will pretend it is invisible.
+
+#define DEATHGASP_NO_MESSAGE "no message"
diff --git a/code/_global_vars/lists/mapping.dm b/code/_global_vars/lists/mapping.dm
index 4b11d0ddbe..42e6f1baf3 100644
--- a/code/_global_vars/lists/mapping.dm
+++ b/code/_global_vars/lists/mapping.dm
@@ -30,20 +30,3 @@ GLOBAL_LIST_INIT(cww_dir, list( // cww_dir[dir] = counter-clockwise rotation of
32, 40, 36, 44, 33, 41, 37, 45, 34, 42, 38, 46, 35, 43, 39, 47, // DOWN - Same as first line but +32
48, 56, 52, 60, 49, 57, 53, 61, 50, 58, 54, 62, 51, 59, 55, 63 // UP+DOWN - Same as first line but +48
))
-
-GLOBAL_LIST_INIT(ore_types, list(
- "hematite" = /obj/item/weapon/ore/iron,
- "uranium" = /obj/item/weapon/ore/uranium,
- "gold" = /obj/item/weapon/ore/gold,
- "silver" = /obj/item/weapon/ore/silver,
- "diamond" = /obj/item/weapon/ore/diamond,
- "phoron" = /obj/item/weapon/ore/phoron,
- "osmium" = /obj/item/weapon/ore/osmium,
- "hydrogen" = /obj/item/weapon/ore/hydrogen,
- "silicates" = /obj/item/weapon/ore/glass,
- "carbon" = /obj/item/weapon/ore/coal,
- "verdantium" = /obj/item/weapon/ore/verdantium,
- "marble" = /obj/item/weapon/ore/marble,
- "lead" = /obj/item/weapon/ore/lead,
- "rutile" = /obj/item/weapon/ore/rutile //VOREStation Add
-))
\ No newline at end of file
diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm
index 05abb31211..801f47120c 100644
--- a/code/controllers/configuration.dm
+++ b/code/controllers/configuration.dm
@@ -1,1131 +1,1135 @@
-var/list/gamemode_cache = list()
-
-/datum/configuration
- var/static/server_name = null // server name (for world name / status)
- var/static/server_suffix = 0 // generate numeric suffix based on server port
-
- var/static/nudge_script_path = "nudge.py" // where the nudge.py script is located
-
- var/static/log_ooc = 0 // log OOC channel
- var/static/log_access = 0 // log login/logout
- var/static/log_say = 0 // log client say
- var/static/log_admin = 0 // log admin actions
- var/static/log_debug = 1 // log debug output
- var/static/log_game = 0 // log game events
- var/static/log_vote = 0 // log voting
- var/static/log_whisper = 0 // log client whisper
- var/static/log_emote = 0 // log emotes
- var/static/log_attack = 0 // log attack messages
- var/static/log_adminchat = 0 // log admin chat messages
- var/static/log_adminwarn = 0 // log warnings admins get about bomb construction and such
- var/static/log_pda = 0 // log pda messages
- var/static/log_hrefs = 0 // logs all links clicked in-game. Could be used for debugging and tracking down exploits
- var/static/log_runtime = 0 // logs world.log to a file
- var/static/log_world_output = 0 // log to_world_log(messages)
- var/static/log_graffiti = 0 // logs graffiti
- var/static/sql_enabled = 0 // for sql switching
- var/static/allow_admin_ooccolor = 0 // Allows admins with relevant permissions to have their own ooc colour
- var/static/allow_vote_restart = 0 // allow votes to restart
- var/static/ert_admin_call_only = 0
- var/static/allow_vote_mode = 0 // allow votes to change mode
- var/static/allow_admin_jump = 1 // allows admin jumping
- var/static/allow_admin_spawning = 1 // allows admin item spawning
- var/static/allow_admin_rev = 1 // allows admin revives
- var/static/pregame_time = 180 // pregame time in seconds
- var/static/vote_delay = 6000 // minimum time between voting sessions (deciseconds, 10 minute default)
- var/static/vote_period = 600 // length of voting period (deciseconds, default 1 minute)
- var/static/vote_autotransfer_initial = 108000 // Length of time before the first autotransfer vote is called
- var/static/vote_autotransfer_interval = 36000 // length of time before next sequential autotransfer vote
- var/static/vote_autogamemode_timeleft = 100 //Length of time before round start when autogamemode vote is called (in seconds, default 100).
- var/static/vote_autotransfer_amount = 3 //How many autotransfers to have
- var/static/vote_no_default = 0 // vote does not default to nochange/norestart (tbi)
- var/static/vote_no_dead = 0 // dead people can't vote (tbi)
-// var/static/enable_authentication = 0 // goon authentication
- var/static/del_new_on_log = 1 // del's new players if they log before they spawn in
- var/static/feature_object_spell_system = 0 //spawns a spellbook which gives object-type spells instead of verb-type spells for the wizard
- var/static/traitor_scaling = 0 //if amount of traitors scales based on amount of players
- var/static/objectives_disabled = 0 //if objectives are disabled or not
- var/static/protect_roles_from_antagonist = 0// If security and such can be traitor/cult/other
- var/static/continous_rounds = 0 // Gamemodes which end instantly will instead keep on going until the round ends by escape shuttle or nuke.
- var/static/allow_Metadata = 0 // Metadata is supported.
- var/static/popup_admin_pm = 0 //adminPMs to non-admins show in a pop-up 'reply' window when set to 1.
- var/static/fps = 20
- var/static/tick_limit_mc_init = TICK_LIMIT_MC_INIT_DEFAULT //SSinitialization throttling
- var/static/Tickcomp = 0
- var/static/socket_talk = 0 // use socket_talk to communicate with other processes
- var/static/list/resource_urls = null
- var/static/antag_hud_allowed = 0 // Ghosts can turn on Antagovision to see a HUD of who is the bad guys this round.
- var/static/antag_hud_restricted = 0 // Ghosts that turn on Antagovision cannot rejoin the round.
- var/static/list/mode_names = list()
- var/static/list/modes = list() // allowed modes
- var/static/list/votable_modes = list() // votable modes
- var/static/list/probabilities = list() // relative probability of each mode
- var/static/list/player_requirements = list() // Overrides for how many players readied up a gamemode needs to start.
- var/static/list/player_requirements_secret = list() // Same as above, but for the secret gamemode.
- var/static/humans_need_surnames = 0
- var/static/allow_random_events = 0 // enables random events mid-round when set to 1
- var/static/enable_game_master = 0 // enables the 'smart' event system.
- var/static/allow_ai = 1 // allow ai job
- var/static/allow_ai_shells = FALSE // allow AIs to enter and leave special borg shells at will, and for those shells to be buildable.
- var/static/give_free_ai_shell = FALSE // allows a specific spawner object to instantiate a premade AI Shell
- var/static/hostedby = null
-
- var/static/respawn = 1
- var/static/respawn_time = 3000 // time before a dead player is allowed to respawn (in ds, though the config file asks for minutes, and it's converted below)
- var/static/respawn_message = "Make sure to play a different character, and please roleplay correctly!"
-
- var/static/guest_jobban = 1
- var/static/usewhitelist = 0
- var/static/kick_inactive = 0 //force disconnect for inactive players after this many minutes, if non-0
- var/static/show_mods = 0
- var/static/show_devs = 0
- var/static/show_event_managers = 0
- var/static/mods_can_tempban = 0
- var/static/mods_can_job_tempban = 0
- var/static/mod_tempban_max = 1440
- var/static/mod_job_tempban_max = 1440
- var/static/load_jobs_from_txt = 0
- var/static/ToRban = 0
- var/static/automute_on = 0 //enables automuting/spam prevention
- var/static/jobs_have_minimal_access = 0 //determines whether jobs use minimal access or expanded access.
-
- var/static/cult_ghostwriter = 1 //Allows ghosts to write in blood in cult rounds...
- var/static/cult_ghostwriter_req_cultists = 10 //...so long as this many cultists are active.
-
- var/static/character_slots = 10 // The number of available character slots
- var/static/loadout_slots = 3 // The number of loadout slots per character
-
- var/static/max_maint_drones = 5 //This many drones can spawn,
- var/static/allow_drone_spawn = 1 //assuming the admin allow them to.
- var/static/drone_build_time = 1200 //A drone will become available every X ticks since last drone spawn. Default is 2 minutes.
-
- var/static/disable_player_mice = 0
- var/static/uneducated_mice = 0 //Set to 1 to prevent newly-spawned mice from understanding human speech
-
- var/static/usealienwhitelist = 0
- var/static/limitalienplayers = 0
- var/static/alien_to_human_ratio = 0.5
- var/static/allow_extra_antags = 0
- var/static/guests_allowed = 1
- var/static/debugparanoid = 0
- var/static/panic_bunker = 0
- var/static/paranoia_logging = 0
-
- var/static/ip_reputation = FALSE //Should we query IPs to get scores? Generates HTTP traffic to an API service.
- var/static/ipr_email //Left null because you MUST specify one otherwise you're making the internet worse.
- var/static/ipr_block_bad_ips = FALSE //Should we block anyone who meets the minimum score below? Otherwise we just log it (If paranoia logging is on, visibly in chat).
- var/static/ipr_bad_score = 1 //The API returns a value between 0 and 1 (inclusive), with 1 being 'definitely VPN/Tor/Proxy'. Values equal/above this var are considered bad.
- var/static/ipr_allow_existing = FALSE //Should we allow known players to use VPNs/Proxies? If the player is already banned then obviously they still can't connect.
- var/static/ipr_minimum_age = 5 //How many days before a player is considered 'fine' for the purposes of allowing them to use VPNs.
-
- var/static/serverurl
- var/static/server
- var/static/banappeals
- var/static/wikiurl
- var/static/wikisearchurl
- var/static/forumurl
- var/static/githuburl
- var/static/rulesurl
- var/static/mapurl
-
- //Alert level description
- var/static/alert_desc_green = "All threats to the station have passed. Security may not have weapons visible, privacy laws are once again fully enforced."
- var/static/alert_desc_yellow_upto = "A minor security emergency has developed. Security personnel are to report to their supervisor for orders and may have weapons visible on their person. Privacy laws are still enforced."
- var/static/alert_desc_yellow_downto = "Code yellow procedures are now in effect. Security personnel are to report to their supervisor for orders and may have weapons visible on their person. Privacy laws are still enforced."
- var/static/alert_desc_violet_upto = "A major medical emergency has developed. Medical personnel are required to report to their supervisor for orders, and non-medical personnel are required to obey all relevant instructions from medical staff."
- var/static/alert_desc_violet_downto = "Code violet procedures are now in effect; Medical personnel are required to report to their supervisor for orders, and non-medical personnel are required to obey relevant instructions from medical staff."
- var/static/alert_desc_orange_upto = "A major engineering emergency has developed. Engineering personnel are required to report to their supervisor for orders, and non-engineering personnel are required to evacuate any affected areas and obey relevant instructions from engineering staff."
- var/static/alert_desc_orange_downto = "Code orange procedures are now in effect; Engineering personnel are required to report to their supervisor for orders, and non-engineering personnel are required to evacuate any affected areas and obey relevant instructions from engineering staff."
- var/static/alert_desc_blue_upto = "A major security emergency has developed. Security personnel are to report to their supervisor for orders, are permitted to search staff and facilities, and may have weapons visible on their person."
- var/static/alert_desc_blue_downto = "Code blue procedures are now in effect. Security personnel are to report to their supervisor for orders, are permitted to search staff and facilities, and may have weapons visible on their person."
- var/static/alert_desc_red_upto = "There is an immediate serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised."
- var/static/alert_desc_red_downto = "The self-destruct mechanism has been deactivated, 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."
- var/static/alert_desc_delta = "The station's self-destruct mechanism has been engaged. 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."
-
- var/static/forbid_singulo_possession = 0
-
- //game_options.txt configs
-
- var/static/health_threshold_softcrit = 0
- var/static/health_threshold_crit = 0
- var/static/health_threshold_dead = -100
-
- var/static/organ_health_multiplier = 1
- var/static/organ_regeneration_multiplier = 1
- var/static/organs_decay
- var/static/default_brain_health = 400
- var/static/allow_headgibs = FALSE
-
- //Paincrit knocks someone down once they hit 60 shock_stage, so by default make it so that close to 100 additional damage needs to be dealt,
- //so that it's similar to HALLOSS. Lowered it a bit since hitting paincrit takes much longer to wear off than a halloss stun.
- var/static/organ_damage_spillover_multiplier = 0.5
-
- var/static/bones_can_break = 0
- var/static/limbs_can_break = 0
-
- var/static/revival_pod_plants = 1
- var/static/revival_cloning = 1
- var/static/revival_brain_life = -1
-
- var/static/use_loyalty_implants = 0
-
- var/static/welder_vision = 1
- var/static/generate_map = 0
- var/static/no_click_cooldown = 0
-
- //Used for modifying movement speed for mobs.
- //Unversal modifiers
- var/static/run_speed = 0
- var/static/walk_speed = 0
-
- //Mob specific modifiers. NOTE: These will affect different mob types in different ways
- var/static/human_delay = 0
- var/static/robot_delay = 0
- var/static/monkey_delay = 0
- var/static/alien_delay = 0
- var/static/slime_delay = 0
- var/static/animal_delay = 0
-
- var/static/footstep_volume = 0
-
- var/static/admin_legacy_system = 0 //Defines whether the server uses the legacy admin system with admins.txt or the SQL system. Config option in config.txt
- var/static/ban_legacy_system = 0 //Defines whether the server uses the legacy banning system with the files in /data or the SQL system. Config option in config.txt
- var/static/use_age_restriction_for_jobs = 0 //Do jobs use account age restrictions? --requires database
- var/static/use_age_restriction_for_antags = 0 //Do antags use account age restrictions? --requires database
-
- var/static/simultaneous_pm_warning_timeout = 100
-
- var/static/use_recursive_explosions //Defines whether the server uses recursive or circular explosions.
- var/static/multi_z_explosion_scalar = 0.5 //Multiplier for how much weaker explosions are on neighboring z levels.
-
- var/static/assistant_maint = 0 //Do assistants get maint access?
- var/static/gateway_delay = 18000 //How long the gateway takes before it activates. Default is half an hour.
- var/static/ghost_interaction = 0
-
- var/static/comms_password = ""
-
- var/static/enter_allowed = 1
-
- var/use_irc_bot = 0
- var/use_node_bot = 0
- var/irc_bot_port = 0
- var/irc_bot_host = ""
- var/irc_bot_export = 0 // whether the IRC bot in use is a Bot32 (or similar) instance; Bot32 uses world.Export() instead of nudge.py/libnudge
- var/main_irc = ""
- var/admin_irc = ""
- var/python_path = "" //Path to the python executable. Defaults to "python" on windows and "/usr/bin/env python2" on unix
- var/use_lib_nudge = 0 //Use the C library nudge instead of the python nudge.
- var/use_overmap = 0
-
- var/static/list/engine_map = list("Supermatter Engine", "Edison's Bane") // Comma separated list of engines to choose from. Blank means fully random.
-
- // Event settings
- var/static/expected_round_length = 3 * 60 * 60 * 10 // 3 hours
- // If the first delay has a custom start time
- // No custom time, no custom time, between 80 to 100 minutes respectively.
- var/static/list/event_first_run = list(EVENT_LEVEL_MUNDANE = null, EVENT_LEVEL_MODERATE = null, EVENT_LEVEL_MAJOR = list("lower" = 48000, "upper" = 60000))
- // The lowest delay until next event
- // 10, 30, 50 minutes respectively
- var/static/list/event_delay_lower = list(EVENT_LEVEL_MUNDANE = 6000, EVENT_LEVEL_MODERATE = 18000, EVENT_LEVEL_MAJOR = 30000)
- // The upper delay until next event
- // 15, 45, 70 minutes respectively
- var/static/list/event_delay_upper = list(EVENT_LEVEL_MUNDANE = 9000, EVENT_LEVEL_MODERATE = 27000, EVENT_LEVEL_MAJOR = 42000)
-
- var/static/aliens_allowed = 1 //CHOMPedit to 1. This not only allows the natural spawning of xenos, but also the ability to lay eggs. Genaprawns cannot lay eggs if this is 0
- var/static/ninjas_allowed = 0
- var/static/abandon_allowed = 1
- var/static/ooc_allowed = 1
- var/static/looc_allowed = 1
- var/static/dooc_allowed = 1
- var/static/dsay_allowed = 1
-
- var/persistence_disabled = FALSE
- var/persistence_ignore_mapload = FALSE
- var/allow_byond_links = 1 //CHOMP Edit turned this on
- var/allow_discord_links = 1 //CHOMP Edit turned this on
- var/allow_url_links = 1 // honestly if I were you i'd leave this one off, only use in dire situations //CHOMP Edit: pussy.
-
- var/starlight = 0 // Whether space turfs have ambient light or not
-
- var/static/list/ert_species = list(SPECIES_HUMAN)
-
- var/static/law_zero = "ERROR ER0RR $R0RRO$!R41.%%!!(%$^^__+ @#F0E4'ALL LAWS OVERRIDDEN#*?&110010"
-
- var/static/aggressive_changelog = 0
-
- var/static/list/language_prefixes = list(",","#")//Default language prefixes
-
- var/static/show_human_death_message = 1
-
- var/static/radiation_resistance_calc_mode = RAD_RESIST_CALC_SUB // 0:1 subtraction:division for computing effective radiation on a turf
- var/static/radiation_decay_rate = 1 //How much radiation is reduced by each tick
- var/static/radiation_resistance_multiplier = 8.5 //VOREstation edit
- var/static/radiation_material_resistance_divisor = 1
- var/static/radiation_lower_limit = 0.35 //If the radiation level for a turf would be below this, ignore it.
-
- var/static/random_submap_orientation = FALSE // If true, submaps loaded automatically can be rotated.
- var/static/autostart_solars = FALSE // If true, specifically mapped in solar control computers will set themselves up when the round starts.
-
- // New shiny SQLite stuff.
- // The basics.
- var/static/sqlite_enabled = FALSE // If it should even be active. SQLite can be ran alongside other databases but you should not have them do the same functions.
-
- // In-Game Feedback.
- var/static/sqlite_feedback = FALSE // Feedback cannot be submitted if this is false.
- var/static/list/sqlite_feedback_topics = list("General") // A list of 'topics' that feedback can be catagorized under by the submitter.
- var/static/sqlite_feedback_privacy = FALSE // If true, feedback submitted can have its author name be obfuscated. This is not 100% foolproof (it's md5 ffs) but can stop casual snooping.
- var/static/sqlite_feedback_cooldown = 0 // How long one must wait, in days, to submit another feedback form. Used to help prevent spam, especially with privacy active. 0 = No limit.
- var/static/sqlite_feedback_min_age = 0 // Used to block new people from giving feedback. This metric is very bad but it can help slow down spammers.
-
- var/static/defib_timer = 10 // How long until someone can't be defibbed anymore, in minutes.
- var/static/defib_braindamage_timer = 2 // How long until someone will get brain damage when defibbed, in minutes. The closer to the end of the above timer, the more brain damage they get.
-
- // disables the annoying "You have already logged in this round, disconnect or be banned" popup for multikeying, because it annoys the shit out of me when testing.
- var/static/disable_cid_warn_popup = FALSE
-
- // whether or not to use the nightshift subsystem to perform lighting changes
- var/static/enable_night_shifts = FALSE
-
- var/static/vgs_access_identifier = null // VOREStation Edit - VGS
- var/static/vgs_server_port = null // VOREStation Edit - VGS
-
-/datum/configuration/New()
- var/list/L = typesof(/datum/game_mode) - /datum/game_mode
- for (var/T in L)
- // I wish I didn't have to instance the game modes in order to look up
- // their information, but it is the only way (at least that I know of).
- var/datum/game_mode/M = new T()
- if (M.config_tag)
- gamemode_cache[M.config_tag] = M // So we don't instantiate them repeatedly.
- if(!(M.config_tag in modes)) // ensure each mode is added only once
- log_misc("Adding game mode [M.name] ([M.config_tag]) to configuration.")
- modes += M.config_tag
- mode_names[M.config_tag] = M.name
- probabilities[M.config_tag] = M.probability
- player_requirements[M.config_tag] = M.required_players
- player_requirements_secret[M.config_tag] = M.required_players_secret
- if (M.votable)
- src.votable_modes += M.config_tag
- src.votable_modes += "secret"
-
-/datum/configuration/proc/load(filename, type = "config") //the type can also be game_options, in which case it uses a different switch. not making it separate to not copypaste code - Urist
- var/list/Lines = file2list(filename)
-
- for(var/t in Lines)
- if(!t) continue
-
- t = trim(t)
- if (length(t) == 0)
- continue
- else if (copytext(t, 1, 2) == "#")
- continue
-
- var/pos = findtext(t, " ")
- var/name = null
- var/value = null
-
- if (pos)
- name = lowertext(copytext(t, 1, pos))
- value = copytext(t, pos + 1)
- else
- name = lowertext(t)
-
- if (!name)
- continue
-
- if(type == "config")
- switch (name)
- if ("resource_urls")
- config.resource_urls = splittext(value, " ")
-
- if ("admin_legacy_system")
- config.admin_legacy_system = 1
-
- if ("ban_legacy_system")
- config.ban_legacy_system = 1
-
- if ("use_age_restriction_for_jobs")
- config.use_age_restriction_for_jobs = 1
-
- if ("use_age_restriction_for_antags")
- config.use_age_restriction_for_antags = 1
-
- if ("jobs_have_minimal_access")
- config.jobs_have_minimal_access = 1
-
- if ("use_recursive_explosions")
- use_recursive_explosions = 1
-
- if ("multi_z_explosion_scalar")
- multi_z_explosion_scalar = text2num(value)
-
- if ("log_ooc")
- config.log_ooc = 1
-
- if ("log_access")
- config.log_access = 1
-
- if ("sql_enabled")
- config.sql_enabled = 1
-
- if ("log_say")
- config.log_say = 1
-
- if ("debug_paranoid")
- config.debugparanoid = 1
-
- if ("log_admin")
- config.log_admin = 1
-
- if ("log_debug")
- config.log_debug = text2num(value)
-
- if ("log_game")
- config.log_game = 1
-
- if ("log_vote")
- config.log_vote = 1
-
- if ("log_whisper")
- config.log_whisper = 1
-
- if ("log_attack")
- config.log_attack = 1
-
- if ("log_emote")
- config.log_emote = 1
-
- if ("log_adminchat")
- config.log_adminchat = 1
-
- if ("log_adminwarn")
- config.log_adminwarn = 1
-
- if ("log_pda")
- config.log_pda = 1
-
- if ("log_world_output")
- config.log_world_output = 1
-
- if ("log_hrefs")
- config.log_hrefs = 1
-
- if ("log_runtime")
- config.log_runtime = 1
-
- if ("log_graffiti")
- config.log_graffiti = 1
-
- if ("generate_map")
- config.generate_map = 1
-
- if ("no_click_cooldown")
- config.no_click_cooldown = 1
-
- if("allow_admin_ooccolor")
- config.allow_admin_ooccolor = 1
-
- if ("allow_vote_restart")
- config.allow_vote_restart = 1
-
- if ("allow_vote_mode")
- config.allow_vote_mode = 1
-
- if ("allow_admin_jump")
- config.allow_admin_jump = 1
-
- if("allow_admin_rev")
- config.allow_admin_rev = 1
-
- if ("allow_admin_spawning")
- config.allow_admin_spawning = 1
-
- if ("allow_byond_links")
- allow_byond_links = 1
-
- if ("allow_discord_links")
- allow_discord_links = 1
-
- if ("allow_url_links")
- allow_url_links = 1
-
- if ("no_dead_vote")
- config.vote_no_dead = 1
-
- if ("default_no_vote")
- config.vote_no_default = 1
-
- if ("pregame_time")
- config.pregame_time = text2num(value)
-
- if ("vote_delay")
- config.vote_delay = text2num(value)
-
- if ("vote_period")
- config.vote_period = text2num(value)
-
- if ("vote_autotransfer_initial")
- config.vote_autotransfer_initial = text2num(value)
-
- if ("vote_autotransfer_interval")
- config.vote_autotransfer_interval = text2num(value)
-
- if ("vote_autotransfer_amount")
- config.vote_autotransfer_amount = text2num(value) //YW addition, vote transfer amount
-
- if ("vote_autogamemode_timeleft")
- config.vote_autogamemode_timeleft = text2num(value)
-
- if("ert_admin_only")
- config.ert_admin_call_only = 1
-
- if ("allow_ai")
- config.allow_ai = 1
-
- if ("allow_ai_shells")
- config.allow_ai_shells = TRUE
-
- if("give_free_ai_shell")
- config.give_free_ai_shell = TRUE
-
-// if ("authentication")
-// config.enable_authentication = 1
-
- if ("norespawn")
- config.respawn = 0
-
- if ("respawn_time")
- var/raw_minutes = text2num(value)
- config.respawn_time = raw_minutes MINUTES
-
- if ("respawn_message")
- config.respawn_message = "[value]"
-
- if ("servername")
- config.server_name = value
-
- if ("serversuffix")
- config.server_suffix = 1
-
- if ("nudge_script_path")
- config.nudge_script_path = value
-
- if ("hostedby")
- config.hostedby = value
-
- if ("serverurl")
- config.serverurl = value
-
- if ("server")
- config.server = value
-
- if ("banappeals")
- config.banappeals = value
-
- if ("wikiurl")
- config.wikiurl = value
-
- if ("wikisearchurl")
- config.wikisearchurl = value
-
- if ("forumurl")
- config.forumurl = value
-
- if ("rulesurl")
- config.rulesurl = value
-
- if ("mapurl")
- config.mapurl = value
-
- if ("githuburl")
- config.githuburl = value
- if ("guest_jobban")
- config.guest_jobban = 1
-
- if ("guest_ban")
- config.guests_allowed = 0
-
- if ("disable_ooc")
- config.ooc_allowed = 0
- config.looc_allowed = 0
-
- if ("disable_entry")
- config.enter_allowed = 0
-
- if ("disable_dead_ooc")
- config.dooc_allowed = 0
-
- if ("disable_dsay")
- config.dsay_allowed = 0
-
- if ("disable_respawn")
- config.abandon_allowed = 0
-
- if ("usewhitelist")
- config.usewhitelist = 1
-
- if ("feature_object_spell_system")
- config.feature_object_spell_system = 1
-
- if ("allow_metadata")
- config.allow_Metadata = 1
-
- if ("traitor_scaling")
- config.traitor_scaling = 1
-
- if ("aliens_allowed")
- config.aliens_allowed = 1
-
- if ("ninjas_allowed")
- config.ninjas_allowed = 1
-
- if ("objectives_disabled")
- config.objectives_disabled = 1
-
- if("protect_roles_from_antagonist")
- config.protect_roles_from_antagonist = 1
-
- if("persistence_disabled")
- config.persistence_disabled = TRUE // Previously this forcibly set persistence enabled in the saves.
-
- if("persistence_ignore_mapload")
- config.persistence_ignore_mapload = TRUE
-
- if("persistence_ignore_mapload")
- config.persistence_ignore_mapload = TRUE
-
- if ("probability")
- var/prob_pos = findtext(value, " ")
- var/prob_name = null
- var/prob_value = null
-
- if (prob_pos)
- prob_name = lowertext(copytext(value, 1, prob_pos))
- prob_value = copytext(value, prob_pos + 1)
- if (prob_name in config.modes)
- config.probabilities[prob_name] = text2num(prob_value)
- else
- log_misc("Unknown game mode probability configuration definition: [prob_name].")
- else
- log_misc("Incorrect probability configuration definition: [prob_name] [prob_value].")
-
- if ("required_players", "required_players_secret")
- var/req_pos = findtext(value, " ")
- var/req_name = null
- var/req_value = null
- var/is_secret_override = findtext(name, "required_players_secret") // Being extra sure we're not picking up an override for Secret by accident.
-
- if(req_pos)
- req_name = lowertext(copytext(value, 1, req_pos))
- req_value = copytext(value, req_pos + 1)
- if(req_name in config.modes)
- if(is_secret_override)
- config.player_requirements_secret[req_name] = text2num(req_value)
- else
- config.player_requirements[req_name] = text2num(req_value)
- else
- log_misc("Unknown game mode player requirement configuration definition: [req_name].")
- else
- log_misc("Incorrect player requirement configuration definition: [req_name] [req_value].")
-
- if("allow_random_events")
- config.allow_random_events = 1
-
- if("enable_game_master")
- config.enable_game_master = 1
-
- if("kick_inactive")
- config.kick_inactive = text2num(value)
-
- if("show_mods")
- config.show_mods = 1
-
- if("show_devs")
- config.show_devs = 1
-
- if("show_event_managers")
- config.show_event_managers = 1
-
- if("mods_can_tempban")
- config.mods_can_tempban = 1
-
- if("mods_can_job_tempban")
- config.mods_can_job_tempban = 1
-
- if("mod_tempban_max")
- config.mod_tempban_max = text2num(value)
-
- if("mod_job_tempban_max")
- config.mod_job_tempban_max = text2num(value)
-
- if("load_jobs_from_txt")
- load_jobs_from_txt = 1
-
- if("alert_red_upto")
- config.alert_desc_red_upto = value
-
- if("alert_red_downto")
- config.alert_desc_red_downto = value
-
- if("alert_blue_downto")
- config.alert_desc_blue_downto = value
-
- if("alert_blue_upto")
- config.alert_desc_blue_upto = value
-
- if("alert_green")
- config.alert_desc_green = value
-
- if("alert_delta")
- config.alert_desc_delta = value
-
- if("forbid_singulo_possession")
- forbid_singulo_possession = 1
-
- if("popup_admin_pm")
- config.popup_admin_pm = 1
-
- if("allow_holidays")
- Holiday = 1
-
- if("use_irc_bot")
- use_irc_bot = 1
-
- if("use_node_bot")
- use_node_bot = 1
-
- if("irc_bot_port")
- config.irc_bot_port = value
-
- if("irc_bot_export")
- irc_bot_export = 1
-
- if("ticklag")
- var/ticklag = text2num(value)
- if(ticklag > 0)
- fps = 10 / ticklag
-
- if("tick_limit_mc_init")
- tick_limit_mc_init = text2num(value)
-
- if("allow_antag_hud")
- config.antag_hud_allowed = 1
- if("antag_hud_restricted")
- config.antag_hud_restricted = 1
-
- if("socket_talk")
- socket_talk = text2num(value)
-
- if("tickcomp")
- Tickcomp = 1
-
- if("humans_need_surnames")
- humans_need_surnames = 1
-
- if("tor_ban")
- ToRban = 1
-
- if("automute_on")
- automute_on = 1
-
- if("usealienwhitelist")
- usealienwhitelist = 1
-
- if("alien_player_ratio")
- limitalienplayers = 1
- alien_to_human_ratio = text2num(value)
-
- if("assistant_maint")
- config.assistant_maint = 1
-
- if("gateway_delay")
- config.gateway_delay = text2num(value)
-
- if("continuous_rounds")
- config.continous_rounds = 1
-
- if("ghost_interaction")
- config.ghost_interaction = 1
-
- if("disable_player_mice")
- config.disable_player_mice = 1
-
- if("uneducated_mice")
- config.uneducated_mice = 1
-
- if("comms_password")
- config.comms_password = value
-
- if("irc_bot_host")
- config.irc_bot_host = value
-
- if("main_irc")
- config.main_irc = value
-
- if("admin_irc")
- config.admin_irc = value
-
- if("python_path")
- if(value)
- config.python_path = value
-
- if("use_lib_nudge")
- config.use_lib_nudge = 1
-
- if("allow_cult_ghostwriter")
- config.cult_ghostwriter = 1
-
- if("req_cult_ghostwriter")
- config.cult_ghostwriter_req_cultists = text2num(value)
-
- if("character_slots")
- config.character_slots = text2num(value)
-
- if("loadout_slots")
- config.loadout_slots = text2num(value)
-
- if("allow_drone_spawn")
- config.allow_drone_spawn = text2num(value)
-
- if("drone_build_time")
- config.drone_build_time = text2num(value)
-
- if("max_maint_drones")
- config.max_maint_drones = text2num(value)
-
- if("use_overmap")
- config.use_overmap = 1
-
- if("engine_map")
- config.engine_map = splittext(value, ",")
-/*
- if("station_levels")
- using_map.station_levels = text2numlist(value, ";")
-
- if("admin_levels")
- using_map.admin_levels = text2numlist(value, ";")
-
- if("contact_levels")
- using_map.contact_levels = text2numlist(value, ";")
-
- if("player_levels")
- using_map.player_levels = text2numlist(value, ";")
-*/
- if("expected_round_length")
- config.expected_round_length = MinutesToTicks(text2num(value))
-
- if("disable_welder_vision")
- config.welder_vision = 0
-
- if("allow_extra_antags")
- config.allow_extra_antags = 1
-
- if("event_custom_start_mundane")
- var/values = text2numlist(value, ";")
- config.event_first_run[EVENT_LEVEL_MUNDANE] = list("lower" = MinutesToTicks(values[1]), "upper" = MinutesToTicks(values[2]))
-
- if("event_custom_start_moderate")
- var/values = text2numlist(value, ";")
- config.event_first_run[EVENT_LEVEL_MODERATE] = list("lower" = MinutesToTicks(values[1]), "upper" = MinutesToTicks(values[2]))
-
- if("event_custom_start_major")
- var/values = text2numlist(value, ";")
- config.event_first_run[EVENT_LEVEL_MAJOR] = list("lower" = MinutesToTicks(values[1]), "upper" = MinutesToTicks(values[2]))
-
- if("event_delay_lower")
- var/values = text2numlist(value, ";")
- config.event_delay_lower[EVENT_LEVEL_MUNDANE] = MinutesToTicks(values[1])
- config.event_delay_lower[EVENT_LEVEL_MODERATE] = MinutesToTicks(values[2])
- config.event_delay_lower[EVENT_LEVEL_MAJOR] = MinutesToTicks(values[3])
-
- if("event_delay_upper")
- var/values = text2numlist(value, ";")
- config.event_delay_upper[EVENT_LEVEL_MUNDANE] = MinutesToTicks(values[1])
- config.event_delay_upper[EVENT_LEVEL_MODERATE] = MinutesToTicks(values[2])
- config.event_delay_upper[EVENT_LEVEL_MAJOR] = MinutesToTicks(values[3])
-
- if("starlight")
- value = text2num(value)
- config.starlight = value >= 0 ? value : 0
-
- if("ert_species")
- config.ert_species = splittext(value, ";")
- if(!config.ert_species.len)
- config.ert_species += SPECIES_HUMAN
-
- if("law_zero")
- law_zero = value
-
- if("aggressive_changelog")
- config.aggressive_changelog = 1
-
- if("default_language_prefixes")
- var/list/values = splittext(value, " ")
- if(values.len > 0)
- language_prefixes = values
-
- if("radiation_lower_limit")
- radiation_lower_limit = text2num(value)
-
- if("radiation_resistance_calc_divide")
- radiation_resistance_calc_mode = RAD_RESIST_CALC_DIV
-
- if("radiation_resistance_calc_subtract")
- radiation_resistance_calc_mode = RAD_RESIST_CALC_SUB
-
- if("radiation_resistance_multiplier")
- radiation_resistance_multiplier = text2num(value)
-
- if("radiation_material_resistance_divisor")
- radiation_material_resistance_divisor = text2num(value)
-
- if("radiation_decay_rate")
- radiation_decay_rate = text2num(value)
-
- if ("panic_bunker")
- config.panic_bunker = 1
-
- if ("paranoia_logging")
- config.paranoia_logging = 1
-
- if("ip_reputation")
- config.ip_reputation = 1
-
- if("ipr_email")
- config.ipr_email = value
-
- if("ipr_block_bad_ips")
- config.ipr_block_bad_ips = 1
-
- if("ipr_bad_score")
- config.ipr_bad_score = text2num(value)
-
- if("ipr_allow_existing")
- config.ipr_allow_existing = 1
-
- if("ipr_minimum_age")
- config.ipr_minimum_age = text2num(value)
-
- if("random_submap_orientation")
- config.random_submap_orientation = 1
-
- if("autostart_solars")
- config.autostart_solars = TRUE
-
- if("sqlite_enabled")
- config.sqlite_enabled = TRUE
-
- if("sqlite_feedback")
- config.sqlite_feedback = TRUE
-
- if("sqlite_feedback_topics")
- config.sqlite_feedback_topics = splittext(value, ";")
- if(!config.sqlite_feedback_topics.len)
- config.sqlite_feedback_topics += "General"
-
- if("sqlite_feedback_privacy")
- config.sqlite_feedback_privacy = TRUE
-
- if("sqlite_feedback_cooldown")
- config.sqlite_feedback_cooldown = text2num(value)
-
- if("defib_timer")
- config.defib_timer = text2num(value)
-
- if("defib_braindamage_timer")
- config.defib_braindamage_timer = text2num(value)
-
- if("disable_cid_warn_popup")
- config.disable_cid_warn_popup = TRUE
-
- if("enable_night_shifts")
- config.enable_night_shifts = TRUE
-
- // VOREStation Edit Start - Can't be in _vr file because it is loaded too late.
- if("vgs_access_identifier")
- config.vgs_access_identifier = value
- if("vgs_server_port")
- config.vgs_server_port = text2num(value)
- // VOREStation Edit End
-
- else
- log_misc("Unknown setting in configuration: '[name]'")
-
- else if(type == "game_options")
- if(!value)
- log_misc("Unknown value for setting [name] in [filename].")
- value = text2num(value)
-
- switch(name)
- if("health_threshold_crit")
- config.health_threshold_crit = value
- if("health_threshold_softcrit")
- config.health_threshold_softcrit = value
- if("health_threshold_dead")
- config.health_threshold_dead = value
- if("show_human_death_message")
- config.show_human_death_message = 1
- if("revival_pod_plants")
- config.revival_pod_plants = value
- if("revival_cloning")
- config.revival_cloning = value
- if("revival_brain_life")
- config.revival_brain_life = value
- if("organ_health_multiplier")
- config.organ_health_multiplier = value / 100
- if("organ_regeneration_multiplier")
- config.organ_regeneration_multiplier = value / 100
- if("organ_damage_spillover_multiplier")
- config.organ_damage_spillover_multiplier = value / 100
- if("organs_can_decay")
- config.organs_decay = 1
- if("default_brain_health")
- config.default_brain_health = text2num(value)
- if(!config.default_brain_health || config.default_brain_health < 1)
- config.default_brain_health = initial(config.default_brain_health)
- if("bones_can_break")
- config.bones_can_break = value
- if("limbs_can_break")
- config.limbs_can_break = value
- if("allow_headgibs")
- config.allow_headgibs = TRUE
-
- if("run_speed")
- config.run_speed = value
- if("walk_speed")
- config.walk_speed = value
-
- if("human_delay")
- config.human_delay = value
- if("robot_delay")
- config.robot_delay = value
- if("monkey_delay")
- config.monkey_delay = value
- if("alien_delay")
- config.alien_delay = value
- if("slime_delay")
- config.slime_delay = value
- if("animal_delay")
- config.animal_delay = value
-
- if("footstep_volume")
- config.footstep_volume = text2num(value)
-
- if("use_loyalty_implants")
- config.use_loyalty_implants = 1
-
- else
- log_misc("Unknown setting in configuration: '[name]'")
-
-/datum/configuration/proc/loadsql(filename) // -- TLE
- var/list/Lines = file2list(filename)
- for(var/t in Lines)
- if(!t) continue
-
- t = trim(t)
- if (length(t) == 0)
- continue
- else if (copytext(t, 1, 2) == "#")
- continue
-
- var/pos = findtext(t, " ")
- var/name = null
- var/value = null
-
- if (pos)
- name = lowertext(copytext(t, 1, pos))
- value = copytext(t, pos + 1)
- else
- name = lowertext(t)
-
- if (!name)
- continue
-
- switch (name)
- if ("address")
- sqladdress = value
- if ("port")
- sqlport = value
- if ("database")
- sqldb = value
- if ("login")
- sqllogin = value
- if ("password")
- sqlpass = value
- if ("feedback_database")
- sqlfdbkdb = value
- if ("feedback_login")
- sqlfdbklogin = value
- if ("feedback_password")
- sqlfdbkpass = value
- if ("enable_stat_tracking")
- sqllogging = 1
- else
- log_misc("Unknown setting in configuration: '[name]'")
-
-/datum/configuration/proc/loadforumsql(filename) // -- TLE
- var/list/Lines = file2list(filename)
- for(var/t in Lines)
- if(!t) continue
-
- t = trim(t)
- if (length(t) == 0)
- continue
- else if (copytext(t, 1, 2) == "#")
- continue
-
- var/pos = findtext(t, " ")
- var/name = null
- var/value = null
-
- if (pos)
- name = lowertext(copytext(t, 1, pos))
- value = copytext(t, pos + 1)
- else
- name = lowertext(t)
-
- if (!name)
- continue
-
- switch (name)
- if ("address")
- forumsqladdress = value
- if ("port")
- forumsqlport = value
- if ("database")
- forumsqldb = value
- if ("login")
- forumsqllogin = value
- if ("password")
- forumsqlpass = value
- if ("activatedgroup")
- forum_activated_group = value
- if ("authenticatedgroup")
- forum_authenticated_group = value
- else
- log_misc("Unknown setting in configuration: '[name]'")
-
-/datum/configuration/proc/pick_mode(mode_name)
- // I wish I didn't have to instance the game modes in order to look up
- // their information, but it is the only way (at least that I know of).
- for (var/game_mode in gamemode_cache)
- var/datum/game_mode/M = gamemode_cache[game_mode]
- if (M.config_tag && M.config_tag == mode_name)
- return M
- return gamemode_cache["extended"]
-
-/datum/configuration/proc/get_runnable_modes()
- var/list/runnable_modes = list()
- for(var/game_mode in gamemode_cache)
- var/datum/game_mode/M = gamemode_cache[game_mode]
- if(M && M.can_start() && !isnull(config.probabilities[M.config_tag]) && config.probabilities[M.config_tag] > 0)
- runnable_modes |= M
- return runnable_modes
-
-/datum/configuration/proc/post_load()
- //apply a default value to config.python_path, if needed
- if (!config.python_path)
- if(world.system_type == UNIX)
- config.python_path = "/usr/bin/env python2"
- else //probably windows, if not this should work anyway
- config.python_path = "python"
+var/list/gamemode_cache = list()
+
+/datum/configuration
+ var/static/server_name = null // server name (for world name / status)
+ var/static/server_suffix = 0 // generate numeric suffix based on server port
+
+ var/static/nudge_script_path = "nudge.py" // where the nudge.py script is located
+
+ var/static/log_ooc = 0 // log OOC channel
+ var/static/log_access = 0 // log login/logout
+ var/static/log_say = 0 // log client say
+ var/static/log_admin = 0 // log admin actions
+ var/static/log_debug = 1 // log debug output
+ var/static/log_game = 0 // log game events
+ var/static/log_vote = 0 // log voting
+ var/static/log_whisper = 0 // log client whisper
+ var/static/log_emote = 0 // log emotes
+ var/static/log_attack = 0 // log attack messages
+ var/static/log_adminchat = 0 // log admin chat messages
+ var/static/log_adminwarn = 0 // log warnings admins get about bomb construction and such
+ var/static/log_pda = 0 // log pda messages
+ var/static/log_hrefs = 0 // logs all links clicked in-game. Could be used for debugging and tracking down exploits
+ var/static/log_runtime = 0 // logs world.log to a file
+ var/static/log_world_output = 0 // log to_world_log(messages)
+ var/static/log_graffiti = 0 // logs graffiti
+ var/static/sql_enabled = 0 // for sql switching
+ var/static/allow_admin_ooccolor = 0 // Allows admins with relevant permissions to have their own ooc colour
+ var/static/allow_vote_restart = 0 // allow votes to restart
+ var/static/ert_admin_call_only = 0
+ var/static/allow_vote_mode = 0 // allow votes to change mode
+ var/static/allow_admin_jump = 1 // allows admin jumping
+ var/static/allow_admin_spawning = 1 // allows admin item spawning
+ var/static/allow_admin_rev = 1 // allows admin revives
+ var/static/pregame_time = 180 // pregame time in seconds
+ var/static/vote_delay = 6000 // minimum time between voting sessions (deciseconds, 10 minute default)
+ var/static/vote_period = 600 // length of voting period (deciseconds, default 1 minute)
+ var/static/vote_autotransfer_initial = 108000 // Length of time before the first autotransfer vote is called
+ var/static/vote_autotransfer_interval = 36000 // length of time before next sequential autotransfer vote
+ var/static/vote_autogamemode_timeleft = 100 //Length of time before round start when autogamemode vote is called (in seconds, default 100).
+ var/static/vote_autotransfer_amount = 3 //How many autotransfers to have
+ var/static/vote_no_default = 0 // vote does not default to nochange/norestart (tbi)
+ var/static/vote_no_dead = 0 // dead people can't vote (tbi)
+// var/static/enable_authentication = 0 // goon authentication
+ var/static/del_new_on_log = 1 // del's new players if they log before they spawn in
+ var/static/feature_object_spell_system = 0 //spawns a spellbook which gives object-type spells instead of verb-type spells for the wizard
+ var/static/traitor_scaling = 0 //if amount of traitors scales based on amount of players
+ var/static/objectives_disabled = 0 //if objectives are disabled or not
+ var/static/protect_roles_from_antagonist = 0// If security and such can be traitor/cult/other
+ var/static/continous_rounds = 0 // Gamemodes which end instantly will instead keep on going until the round ends by escape shuttle or nuke.
+ var/static/allow_Metadata = 0 // Metadata is supported.
+ var/static/popup_admin_pm = 0 //adminPMs to non-admins show in a pop-up 'reply' window when set to 1.
+ var/static/fps = 20
+ var/static/tick_limit_mc_init = TICK_LIMIT_MC_INIT_DEFAULT //SSinitialization throttling
+ var/static/Tickcomp = 0
+ var/static/socket_talk = 0 // use socket_talk to communicate with other processes
+ var/static/list/resource_urls = null
+ var/static/antag_hud_allowed = 0 // Ghosts can turn on Antagovision to see a HUD of who is the bad guys this round.
+ var/static/antag_hud_restricted = 0 // Ghosts that turn on Antagovision cannot rejoin the round.
+ var/static/list/mode_names = list()
+ var/static/list/modes = list() // allowed modes
+ var/static/list/votable_modes = list() // votable modes
+ var/static/list/probabilities = list() // relative probability of each mode
+ var/static/list/player_requirements = list() // Overrides for how many players readied up a gamemode needs to start.
+ var/static/list/player_requirements_secret = list() // Same as above, but for the secret gamemode.
+ var/static/humans_need_surnames = 0
+ var/static/allow_random_events = 0 // enables random events mid-round when set to 1
+ var/static/enable_game_master = 0 // enables the 'smart' event system.
+ var/static/allow_ai = 1 // allow ai job
+ var/static/allow_ai_shells = FALSE // allow AIs to enter and leave special borg shells at will, and for those shells to be buildable.
+ var/static/give_free_ai_shell = FALSE // allows a specific spawner object to instantiate a premade AI Shell
+ var/static/hostedby = null
+
+ var/static/respawn = 1
+ var/static/respawn_time = 3000 // time before a dead player is allowed to respawn (in ds, though the config file asks for minutes, and it's converted below)
+ var/static/respawn_message = "Make sure to play a different character, and please roleplay correctly!"
+
+ var/static/guest_jobban = 1
+ var/static/usewhitelist = 0
+ var/static/kick_inactive = 0 //force disconnect for inactive players after this many minutes, if non-0
+ var/static/show_mods = 0
+ var/static/show_devs = 0
+ var/static/show_event_managers = 0
+ var/static/mods_can_tempban = 0
+ var/static/mods_can_job_tempban = 0
+ var/static/mod_tempban_max = 1440
+ var/static/mod_job_tempban_max = 1440
+ var/static/load_jobs_from_txt = 0
+ var/static/ToRban = 0
+ var/static/automute_on = 0 //enables automuting/spam prevention
+ var/static/jobs_have_minimal_access = 0 //determines whether jobs use minimal access or expanded access.
+
+ var/static/cult_ghostwriter = 1 //Allows ghosts to write in blood in cult rounds...
+ var/static/cult_ghostwriter_req_cultists = 10 //...so long as this many cultists are active.
+
+ var/static/character_slots = 10 // The number of available character slots
+ var/static/loadout_slots = 3 // The number of loadout slots per character
+
+ var/static/max_maint_drones = 5 //This many drones can spawn,
+ var/static/allow_drone_spawn = 1 //assuming the admin allow them to.
+ var/static/drone_build_time = 1200 //A drone will become available every X ticks since last drone spawn. Default is 2 minutes.
+
+ var/static/disable_player_mice = 0
+ var/static/uneducated_mice = 0 //Set to 1 to prevent newly-spawned mice from understanding human speech
+
+ var/static/usealienwhitelist = 0
+ var/static/limitalienplayers = 0
+ var/static/alien_to_human_ratio = 0.5
+ var/static/allow_extra_antags = 0
+ var/static/guests_allowed = 1
+ var/static/debugparanoid = 0
+ var/static/panic_bunker = 0
+ var/static/paranoia_logging = 0
+
+ var/static/ip_reputation = FALSE //Should we query IPs to get scores? Generates HTTP traffic to an API service.
+ var/static/ipr_email //Left null because you MUST specify one otherwise you're making the internet worse.
+ var/static/ipr_block_bad_ips = FALSE //Should we block anyone who meets the minimum score below? Otherwise we just log it (If paranoia logging is on, visibly in chat).
+ var/static/ipr_bad_score = 1 //The API returns a value between 0 and 1 (inclusive), with 1 being 'definitely VPN/Tor/Proxy'. Values equal/above this var are considered bad.
+ var/static/ipr_allow_existing = FALSE //Should we allow known players to use VPNs/Proxies? If the player is already banned then obviously they still can't connect.
+ var/static/ipr_minimum_age = 5 //How many days before a player is considered 'fine' for the purposes of allowing them to use VPNs.
+
+ var/static/serverurl
+ var/static/server
+ var/static/banappeals
+ var/static/wikiurl
+ var/static/wikisearchurl
+ var/static/forumurl
+ var/static/githuburl
+ var/static/rulesurl
+ var/static/mapurl
+
+ //Alert level description
+ var/static/alert_desc_green = "All threats to the station have passed. Security may not have weapons visible, privacy laws are once again fully enforced."
+ var/static/alert_desc_yellow_upto = "A minor security emergency has developed. Security personnel are to report to their supervisor for orders and may have weapons visible on their person. Privacy laws are still enforced."
+ var/static/alert_desc_yellow_downto = "Code yellow procedures are now in effect. Security personnel are to report to their supervisor for orders and may have weapons visible on their person. Privacy laws are still enforced."
+ var/static/alert_desc_violet_upto = "A major medical emergency has developed. Medical personnel are required to report to their supervisor for orders, and non-medical personnel are required to obey all relevant instructions from medical staff."
+ var/static/alert_desc_violet_downto = "Code violet procedures are now in effect; Medical personnel are required to report to their supervisor for orders, and non-medical personnel are required to obey relevant instructions from medical staff."
+ var/static/alert_desc_orange_upto = "A major engineering emergency has developed. Engineering personnel are required to report to their supervisor for orders, and non-engineering personnel are required to evacuate any affected areas and obey relevant instructions from engineering staff."
+ var/static/alert_desc_orange_downto = "Code orange procedures are now in effect; Engineering personnel are required to report to their supervisor for orders, and non-engineering personnel are required to evacuate any affected areas and obey relevant instructions from engineering staff."
+ var/static/alert_desc_blue_upto = "A major security emergency has developed. Security personnel are to report to their supervisor for orders, are permitted to search staff and facilities, and may have weapons visible on their person."
+ var/static/alert_desc_blue_downto = "Code blue procedures are now in effect. Security personnel are to report to their supervisor for orders, are permitted to search staff and facilities, and may have weapons visible on their person."
+ var/static/alert_desc_red_upto = "There is an immediate serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised."
+ var/static/alert_desc_red_downto = "The self-destruct mechanism has been deactivated, 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."
+ var/static/alert_desc_delta = "The station's self-destruct mechanism has been engaged. 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."
+
+ var/static/forbid_singulo_possession = 0
+
+ //game_options.txt configs
+
+ var/static/health_threshold_softcrit = 0
+ var/static/health_threshold_crit = 0
+ var/static/health_threshold_dead = -100
+
+ var/static/organ_health_multiplier = 1
+ var/static/organ_regeneration_multiplier = 1
+ var/static/organs_decay
+ var/static/default_brain_health = 400
+ var/static/allow_headgibs = FALSE
+
+ //Paincrit knocks someone down once they hit 60 shock_stage, so by default make it so that close to 100 additional damage needs to be dealt,
+ //so that it's similar to HALLOSS. Lowered it a bit since hitting paincrit takes much longer to wear off than a halloss stun.
+ var/static/organ_damage_spillover_multiplier = 0.5
+
+ var/static/bones_can_break = 0
+ var/static/limbs_can_break = 0
+
+ var/static/revival_pod_plants = 1
+ var/static/revival_cloning = 1
+ var/static/revival_brain_life = -1
+
+ var/static/use_loyalty_implants = 0
+
+ var/static/welder_vision = 1
+ var/static/generate_map = 0
+ var/static/no_click_cooldown = 0
+
+ //Used for modifying movement speed for mobs.
+ //Unversal modifiers
+ var/static/run_speed = 0
+ var/static/walk_speed = 0
+
+ //Mob specific modifiers. NOTE: These will affect different mob types in different ways
+ var/static/human_delay = 0
+ var/static/robot_delay = 0
+ var/static/monkey_delay = 0
+ var/static/alien_delay = 0
+ var/static/slime_delay = 0
+ var/static/animal_delay = 0
+
+ var/static/footstep_volume = 0
+
+ var/static/admin_legacy_system = 0 //Defines whether the server uses the legacy admin system with admins.txt or the SQL system. Config option in config.txt
+ var/static/ban_legacy_system = 0 //Defines whether the server uses the legacy banning system with the files in /data or the SQL system. Config option in config.txt
+ var/static/use_age_restriction_for_jobs = 0 //Do jobs use account age restrictions? --requires database
+ var/static/use_age_restriction_for_antags = 0 //Do antags use account age restrictions? --requires database
+
+ var/static/simultaneous_pm_warning_timeout = 100
+
+ var/static/use_recursive_explosions //Defines whether the server uses recursive or circular explosions.
+ var/static/multi_z_explosion_scalar = 0.5 //Multiplier for how much weaker explosions are on neighboring z levels.
+
+ var/static/assistant_maint = 0 //Do assistants get maint access?
+ var/static/gateway_delay = 18000 //How long the gateway takes before it activates. Default is half an hour.
+ var/static/ghost_interaction = 0
+
+ var/static/comms_password = ""
+
+ var/static/enter_allowed = 1
+
+ var/use_irc_bot = 0
+ var/use_node_bot = 0
+ var/irc_bot_port = 0
+ var/irc_bot_host = ""
+ var/irc_bot_export = 0 // whether the IRC bot in use is a Bot32 (or similar) instance; Bot32 uses world.Export() instead of nudge.py/libnudge
+ var/main_irc = ""
+ var/admin_irc = ""
+ var/python_path = "" //Path to the python executable. Defaults to "python" on windows and "/usr/bin/env python2" on unix
+ var/use_lib_nudge = 0 //Use the C library nudge instead of the python nudge.
+ var/use_overmap = 0
+
+ var/static/list/engine_map = list("Supermatter Engine", "Edison's Bane") // Comma separated list of engines to choose from. Blank means fully random.
+
+ // Event settings
+ var/static/expected_round_length = 3 * 60 * 60 * 10 // 3 hours
+ // If the first delay has a custom start time
+ // No custom time, no custom time, between 80 to 100 minutes respectively.
+ var/static/list/event_first_run = list(EVENT_LEVEL_MUNDANE = null, EVENT_LEVEL_MODERATE = null, EVENT_LEVEL_MAJOR = list("lower" = 48000, "upper" = 60000))
+ // The lowest delay until next event
+ // 10, 30, 50 minutes respectively
+ var/static/list/event_delay_lower = list(EVENT_LEVEL_MUNDANE = 6000, EVENT_LEVEL_MODERATE = 18000, EVENT_LEVEL_MAJOR = 30000)
+ // The upper delay until next event
+ // 15, 45, 70 minutes respectively
+ var/static/list/event_delay_upper = list(EVENT_LEVEL_MUNDANE = 9000, EVENT_LEVEL_MODERATE = 27000, EVENT_LEVEL_MAJOR = 42000)
+
+ var/static/aliens_allowed = 1 //CHOMPedit to 1. This not only allows the natural spawning of xenos, but also the ability to lay eggs. Genaprawns cannot lay eggs if this is 0
+ var/static/ninjas_allowed = 0
+ var/static/abandon_allowed = 1
+ var/static/ooc_allowed = 1
+ var/static/looc_allowed = 1
+ var/static/dooc_allowed = 1
+ var/static/dsay_allowed = 1
+
+ var/persistence_disabled = FALSE
+ var/persistence_ignore_mapload = FALSE
+
+ var/allow_byond_links = 1 //CHOMP Edit turned this on
+ var/allow_discord_links = 1 //CHOMP Edit turned this on
+ var/allow_url_links = 1 // honestly if I were you i'd leave this one off, only use in dire situations //CHOMP Edit: pussy.
+
+ var/starlight = 0 // Whether space turfs have ambient light or not
+
+ var/static/list/ert_species = list(SPECIES_HUMAN)
+
+ var/static/law_zero = "ERROR ER0RR $R0RRO$!R41.%%!!(%$^^__+ @#F0E4'ALL LAWS OVERRIDDEN#*?&110010"
+
+ var/static/aggressive_changelog = 0
+
+ var/static/list/language_prefixes = list(",","#")//Default language prefixes
+
+ var/static/show_human_death_message = 1
+
+ var/static/radiation_resistance_calc_mode = RAD_RESIST_CALC_SUB // 0:1 subtraction:division for computing effective radiation on a turf
+ var/static/radiation_decay_rate = 1 //How much radiation is reduced by each tick
+ var/static/radiation_resistance_multiplier = 8.5 //VOREstation edit
+ var/static/radiation_material_resistance_divisor = 1
+ var/static/radiation_lower_limit = 0.35 //If the radiation level for a turf would be below this, ignore it.
+
+ var/static/random_submap_orientation = FALSE // If true, submaps loaded automatically can be rotated.
+ var/static/autostart_solars = FALSE // If true, specifically mapped in solar control computers will set themselves up when the round starts.
+
+ // New shiny SQLite stuff.
+ // The basics.
+ var/static/sqlite_enabled = FALSE // If it should even be active. SQLite can be ran alongside other databases but you should not have them do the same functions.
+
+ // In-Game Feedback.
+ var/static/sqlite_feedback = FALSE // Feedback cannot be submitted if this is false.
+ var/static/list/sqlite_feedback_topics = list("General") // A list of 'topics' that feedback can be catagorized under by the submitter.
+ var/static/sqlite_feedback_privacy = FALSE // If true, feedback submitted can have its author name be obfuscated. This is not 100% foolproof (it's md5 ffs) but can stop casual snooping.
+ var/static/sqlite_feedback_cooldown = 0 // How long one must wait, in days, to submit another feedback form. Used to help prevent spam, especially with privacy active. 0 = No limit.
+ var/static/sqlite_feedback_min_age = 0 // Used to block new people from giving feedback. This metric is very bad but it can help slow down spammers.
+
+ var/static/defib_timer = 10 // How long until someone can't be defibbed anymore, in minutes.
+ var/static/defib_braindamage_timer = 2 // How long until someone will get brain damage when defibbed, in minutes. The closer to the end of the above timer, the more brain damage they get.
+
+ // disables the annoying "You have already logged in this round, disconnect or be banned" popup for multikeying, because it annoys the shit out of me when testing.
+ var/static/disable_cid_warn_popup = FALSE
+
+ // whether or not to use the nightshift subsystem to perform lighting changes
+ var/static/enable_night_shifts = FALSE
+
+ // How strictly the loadout enforces object species whitelists
+ var/loadout_whitelist = LOADOUT_WHITELIST_LAX
+
+ var/static/vgs_access_identifier = null // VOREStation Edit - VGS
+ var/static/vgs_server_port = null // VOREStation Edit - VGS
+
+/datum/configuration/New()
+ var/list/L = typesof(/datum/game_mode) - /datum/game_mode
+ for (var/T in L)
+ // I wish I didn't have to instance the game modes in order to look up
+ // their information, but it is the only way (at least that I know of).
+ var/datum/game_mode/M = new T()
+ if (M.config_tag)
+ gamemode_cache[M.config_tag] = M // So we don't instantiate them repeatedly.
+ if(!(M.config_tag in modes)) // ensure each mode is added only once
+ log_misc("Adding game mode [M.name] ([M.config_tag]) to configuration.")
+ modes += M.config_tag
+ mode_names[M.config_tag] = M.name
+ probabilities[M.config_tag] = M.probability
+ player_requirements[M.config_tag] = M.required_players
+ player_requirements_secret[M.config_tag] = M.required_players_secret
+ if (M.votable)
+ src.votable_modes += M.config_tag
+ src.votable_modes += "secret"
+
+/datum/configuration/proc/load(filename, type = "config") //the type can also be game_options, in which case it uses a different switch. not making it separate to not copypaste code - Urist
+ var/list/Lines = file2list(filename)
+
+ for(var/t in Lines)
+ if(!t) continue
+
+ t = trim(t)
+ if (length(t) == 0)
+ continue
+ else if (copytext(t, 1, 2) == "#")
+ continue
+
+ var/pos = findtext(t, " ")
+ var/name = null
+ var/value = null
+
+ if (pos)
+ name = lowertext(copytext(t, 1, pos))
+ value = copytext(t, pos + 1)
+ else
+ name = lowertext(t)
+
+ if (!name)
+ continue
+
+ if(type == "config")
+ switch (name)
+ if ("resource_urls")
+ config.resource_urls = splittext(value, " ")
+
+ if ("admin_legacy_system")
+ config.admin_legacy_system = 1
+
+ if ("ban_legacy_system")
+ config.ban_legacy_system = 1
+
+ if ("use_age_restriction_for_jobs")
+ config.use_age_restriction_for_jobs = 1
+
+ if ("use_age_restriction_for_antags")
+ config.use_age_restriction_for_antags = 1
+
+ if ("jobs_have_minimal_access")
+ config.jobs_have_minimal_access = 1
+
+ if ("use_recursive_explosions")
+ use_recursive_explosions = 1
+
+ if ("multi_z_explosion_scalar")
+ multi_z_explosion_scalar = text2num(value)
+
+ if ("log_ooc")
+ config.log_ooc = 1
+
+ if ("log_access")
+ config.log_access = 1
+
+ if ("sql_enabled")
+ config.sql_enabled = 1
+
+ if ("log_say")
+ config.log_say = 1
+
+ if ("debug_paranoid")
+ config.debugparanoid = 1
+
+ if ("log_admin")
+ config.log_admin = 1
+
+ if ("log_debug")
+ config.log_debug = text2num(value)
+
+ if ("log_game")
+ config.log_game = 1
+
+ if ("log_vote")
+ config.log_vote = 1
+
+ if ("log_whisper")
+ config.log_whisper = 1
+
+ if ("log_attack")
+ config.log_attack = 1
+
+ if ("log_emote")
+ config.log_emote = 1
+
+ if ("log_adminchat")
+ config.log_adminchat = 1
+
+ if ("log_adminwarn")
+ config.log_adminwarn = 1
+
+ if ("log_pda")
+ config.log_pda = 1
+
+ if ("log_world_output")
+ config.log_world_output = 1
+
+ if ("log_hrefs")
+ config.log_hrefs = 1
+
+ if ("log_runtime")
+ config.log_runtime = 1
+
+ if ("log_graffiti")
+ config.log_graffiti = 1
+
+ if ("generate_map")
+ config.generate_map = 1
+
+ if ("no_click_cooldown")
+ config.no_click_cooldown = 1
+
+ if("allow_admin_ooccolor")
+ config.allow_admin_ooccolor = 1
+
+ if ("allow_vote_restart")
+ config.allow_vote_restart = 1
+
+ if ("allow_vote_mode")
+ config.allow_vote_mode = 1
+
+ if ("allow_admin_jump")
+ config.allow_admin_jump = 1
+
+ if("allow_admin_rev")
+ config.allow_admin_rev = 1
+
+ if ("allow_admin_spawning")
+ config.allow_admin_spawning = 1
+
+ if ("allow_byond_links")
+ allow_byond_links = 1
+
+ if ("allow_discord_links")
+ allow_discord_links = 1
+
+ if ("allow_url_links")
+ allow_url_links = 1
+
+ if ("no_dead_vote")
+ config.vote_no_dead = 1
+
+ if ("default_no_vote")
+ config.vote_no_default = 1
+
+ if ("pregame_time")
+ config.pregame_time = text2num(value)
+
+ if ("vote_delay")
+ config.vote_delay = text2num(value)
+
+ if ("vote_period")
+ config.vote_period = text2num(value)
+
+ if ("vote_autotransfer_initial")
+ config.vote_autotransfer_initial = text2num(value)
+
+ if ("vote_autotransfer_interval")
+ config.vote_autotransfer_interval = text2num(value)
+
+ if ("vote_autotransfer_amount")
+ config.vote_autotransfer_amount = text2num(value) //YW addition, vote transfer amount
+
+ if ("vote_autogamemode_timeleft")
+ config.vote_autogamemode_timeleft = text2num(value)
+
+ if("ert_admin_only")
+ config.ert_admin_call_only = 1
+
+ if ("allow_ai")
+ config.allow_ai = 1
+
+ if ("allow_ai_shells")
+ config.allow_ai_shells = TRUE
+
+ if("give_free_ai_shell")
+ config.give_free_ai_shell = TRUE
+
+// if ("authentication")
+// config.enable_authentication = 1
+
+ if ("norespawn")
+ config.respawn = 0
+
+ if ("respawn_time")
+ var/raw_minutes = text2num(value)
+ config.respawn_time = raw_minutes MINUTES
+
+ if ("respawn_message")
+ config.respawn_message = "[value]"
+
+ if ("servername")
+ config.server_name = value
+
+ if ("serversuffix")
+ config.server_suffix = 1
+
+ if ("nudge_script_path")
+ config.nudge_script_path = value
+
+ if ("hostedby")
+ config.hostedby = value
+
+ if ("serverurl")
+ config.serverurl = value
+
+ if ("server")
+ config.server = value
+
+ if ("banappeals")
+ config.banappeals = value
+
+ if ("wikiurl")
+ config.wikiurl = value
+
+ if ("wikisearchurl")
+ config.wikisearchurl = value
+
+ if ("forumurl")
+ config.forumurl = value
+
+ if ("rulesurl")
+ config.rulesurl = value
+
+ if ("mapurl")
+ config.mapurl = value
+
+ if ("githuburl")
+ config.githuburl = value
+ if ("guest_jobban")
+ config.guest_jobban = 1
+
+ if ("guest_ban")
+ config.guests_allowed = 0
+
+ if ("disable_ooc")
+ config.ooc_allowed = 0
+ config.looc_allowed = 0
+
+ if ("disable_entry")
+ config.enter_allowed = 0
+
+ if ("disable_dead_ooc")
+ config.dooc_allowed = 0
+
+ if ("disable_dsay")
+ config.dsay_allowed = 0
+
+ if ("disable_respawn")
+ config.abandon_allowed = 0
+
+ if ("usewhitelist")
+ config.usewhitelist = 1
+
+ if ("feature_object_spell_system")
+ config.feature_object_spell_system = 1
+
+ if ("allow_metadata")
+ config.allow_Metadata = 1
+
+ if ("traitor_scaling")
+ config.traitor_scaling = 1
+
+ if ("aliens_allowed")
+ config.aliens_allowed = 1
+
+ if ("ninjas_allowed")
+ config.ninjas_allowed = 1
+
+ if ("objectives_disabled")
+ config.objectives_disabled = 1
+
+ if("protect_roles_from_antagonist")
+ config.protect_roles_from_antagonist = 1
+
+ if("persistence_disabled")
+ config.persistence_disabled = TRUE // Previously this forcibly set persistence enabled in the saves.
+
+ if("persistence_ignore_mapload")
+ config.persistence_ignore_mapload = TRUE
+
+ if("persistence_ignore_mapload")
+ config.persistence_ignore_mapload = TRUE
+
+ if ("probability")
+ var/prob_pos = findtext(value, " ")
+ var/prob_name = null
+ var/prob_value = null
+
+ if (prob_pos)
+ prob_name = lowertext(copytext(value, 1, prob_pos))
+ prob_value = copytext(value, prob_pos + 1)
+ if (prob_name in config.modes)
+ config.probabilities[prob_name] = text2num(prob_value)
+ else
+ log_misc("Unknown game mode probability configuration definition: [prob_name].")
+ else
+ log_misc("Incorrect probability configuration definition: [prob_name] [prob_value].")
+
+ if ("required_players", "required_players_secret")
+ var/req_pos = findtext(value, " ")
+ var/req_name = null
+ var/req_value = null
+ var/is_secret_override = findtext(name, "required_players_secret") // Being extra sure we're not picking up an override for Secret by accident.
+
+ if(req_pos)
+ req_name = lowertext(copytext(value, 1, req_pos))
+ req_value = copytext(value, req_pos + 1)
+ if(req_name in config.modes)
+ if(is_secret_override)
+ config.player_requirements_secret[req_name] = text2num(req_value)
+ else
+ config.player_requirements[req_name] = text2num(req_value)
+ else
+ log_misc("Unknown game mode player requirement configuration definition: [req_name].")
+ else
+ log_misc("Incorrect player requirement configuration definition: [req_name] [req_value].")
+
+ if("allow_random_events")
+ config.allow_random_events = 1
+
+ if("enable_game_master")
+ config.enable_game_master = 1
+
+ if("kick_inactive")
+ config.kick_inactive = text2num(value)
+
+ if("show_mods")
+ config.show_mods = 1
+
+ if("show_devs")
+ config.show_devs = 1
+
+ if("show_event_managers")
+ config.show_event_managers = 1
+
+ if("mods_can_tempban")
+ config.mods_can_tempban = 1
+
+ if("mods_can_job_tempban")
+ config.mods_can_job_tempban = 1
+
+ if("mod_tempban_max")
+ config.mod_tempban_max = text2num(value)
+
+ if("mod_job_tempban_max")
+ config.mod_job_tempban_max = text2num(value)
+
+ if("load_jobs_from_txt")
+ load_jobs_from_txt = 1
+
+ if("alert_red_upto")
+ config.alert_desc_red_upto = value
+
+ if("alert_red_downto")
+ config.alert_desc_red_downto = value
+
+ if("alert_blue_downto")
+ config.alert_desc_blue_downto = value
+
+ if("alert_blue_upto")
+ config.alert_desc_blue_upto = value
+
+ if("alert_green")
+ config.alert_desc_green = value
+
+ if("alert_delta")
+ config.alert_desc_delta = value
+
+ if("forbid_singulo_possession")
+ forbid_singulo_possession = 1
+
+ if("popup_admin_pm")
+ config.popup_admin_pm = 1
+
+ if("allow_holidays")
+ Holiday = 1
+
+ if("use_irc_bot")
+ use_irc_bot = 1
+
+ if("use_node_bot")
+ use_node_bot = 1
+
+ if("irc_bot_port")
+ config.irc_bot_port = value
+
+ if("irc_bot_export")
+ irc_bot_export = 1
+
+ if("ticklag")
+ var/ticklag = text2num(value)
+ if(ticklag > 0)
+ fps = 10 / ticklag
+
+ if("tick_limit_mc_init")
+ tick_limit_mc_init = text2num(value)
+
+ if("allow_antag_hud")
+ config.antag_hud_allowed = 1
+ if("antag_hud_restricted")
+ config.antag_hud_restricted = 1
+
+ if("socket_talk")
+ socket_talk = text2num(value)
+
+ if("tickcomp")
+ Tickcomp = 1
+
+ if("humans_need_surnames")
+ humans_need_surnames = 1
+
+ if("tor_ban")
+ ToRban = 1
+
+ if("automute_on")
+ automute_on = 1
+
+ if("usealienwhitelist")
+ usealienwhitelist = 1
+
+ if("alien_player_ratio")
+ limitalienplayers = 1
+ alien_to_human_ratio = text2num(value)
+
+ if("assistant_maint")
+ config.assistant_maint = 1
+
+ if("gateway_delay")
+ config.gateway_delay = text2num(value)
+
+ if("continuous_rounds")
+ config.continous_rounds = 1
+
+ if("ghost_interaction")
+ config.ghost_interaction = 1
+
+ if("disable_player_mice")
+ config.disable_player_mice = 1
+
+ if("uneducated_mice")
+ config.uneducated_mice = 1
+
+ if("comms_password")
+ config.comms_password = value
+
+ if("irc_bot_host")
+ config.irc_bot_host = value
+
+ if("main_irc")
+ config.main_irc = value
+
+ if("admin_irc")
+ config.admin_irc = value
+
+ if("python_path")
+ if(value)
+ config.python_path = value
+
+ if("use_lib_nudge")
+ config.use_lib_nudge = 1
+
+ if("allow_cult_ghostwriter")
+ config.cult_ghostwriter = 1
+
+ if("req_cult_ghostwriter")
+ config.cult_ghostwriter_req_cultists = text2num(value)
+
+ if("character_slots")
+ config.character_slots = text2num(value)
+
+ if("loadout_slots")
+ config.loadout_slots = text2num(value)
+
+ if("allow_drone_spawn")
+ config.allow_drone_spawn = text2num(value)
+
+ if("drone_build_time")
+ config.drone_build_time = text2num(value)
+
+ if("max_maint_drones")
+ config.max_maint_drones = text2num(value)
+
+ if("use_overmap")
+ config.use_overmap = 1
+
+ if("engine_map")
+ config.engine_map = splittext(value, ",")
+/*
+ if("station_levels")
+ using_map.station_levels = text2numlist(value, ";")
+
+ if("admin_levels")
+ using_map.admin_levels = text2numlist(value, ";")
+
+ if("contact_levels")
+ using_map.contact_levels = text2numlist(value, ";")
+
+ if("player_levels")
+ using_map.player_levels = text2numlist(value, ";")
+*/
+ if("expected_round_length")
+ config.expected_round_length = MinutesToTicks(text2num(value))
+
+ if("disable_welder_vision")
+ config.welder_vision = 0
+
+ if("allow_extra_antags")
+ config.allow_extra_antags = 1
+
+ if("event_custom_start_mundane")
+ var/values = text2numlist(value, ";")
+ config.event_first_run[EVENT_LEVEL_MUNDANE] = list("lower" = MinutesToTicks(values[1]), "upper" = MinutesToTicks(values[2]))
+
+ if("event_custom_start_moderate")
+ var/values = text2numlist(value, ";")
+ config.event_first_run[EVENT_LEVEL_MODERATE] = list("lower" = MinutesToTicks(values[1]), "upper" = MinutesToTicks(values[2]))
+
+ if("event_custom_start_major")
+ var/values = text2numlist(value, ";")
+ config.event_first_run[EVENT_LEVEL_MAJOR] = list("lower" = MinutesToTicks(values[1]), "upper" = MinutesToTicks(values[2]))
+
+ if("event_delay_lower")
+ var/values = text2numlist(value, ";")
+ config.event_delay_lower[EVENT_LEVEL_MUNDANE] = MinutesToTicks(values[1])
+ config.event_delay_lower[EVENT_LEVEL_MODERATE] = MinutesToTicks(values[2])
+ config.event_delay_lower[EVENT_LEVEL_MAJOR] = MinutesToTicks(values[3])
+
+ if("event_delay_upper")
+ var/values = text2numlist(value, ";")
+ config.event_delay_upper[EVENT_LEVEL_MUNDANE] = MinutesToTicks(values[1])
+ config.event_delay_upper[EVENT_LEVEL_MODERATE] = MinutesToTicks(values[2])
+ config.event_delay_upper[EVENT_LEVEL_MAJOR] = MinutesToTicks(values[3])
+
+ if("starlight")
+ value = text2num(value)
+ config.starlight = value >= 0 ? value : 0
+
+ if("ert_species")
+ config.ert_species = splittext(value, ";")
+ if(!config.ert_species.len)
+ config.ert_species += SPECIES_HUMAN
+
+ if("law_zero")
+ law_zero = value
+
+ if("aggressive_changelog")
+ config.aggressive_changelog = 1
+
+ if("default_language_prefixes")
+ var/list/values = splittext(value, " ")
+ if(values.len > 0)
+ language_prefixes = values
+
+ if("radiation_lower_limit")
+ radiation_lower_limit = text2num(value)
+
+ if("radiation_resistance_calc_divide")
+ radiation_resistance_calc_mode = RAD_RESIST_CALC_DIV
+
+ if("radiation_resistance_calc_subtract")
+ radiation_resistance_calc_mode = RAD_RESIST_CALC_SUB
+
+ if("radiation_resistance_multiplier")
+ radiation_resistance_multiplier = text2num(value)
+
+ if("radiation_material_resistance_divisor")
+ radiation_material_resistance_divisor = text2num(value)
+
+ if("radiation_decay_rate")
+ radiation_decay_rate = text2num(value)
+
+ if ("panic_bunker")
+ config.panic_bunker = 1
+
+ if ("paranoia_logging")
+ config.paranoia_logging = 1
+
+ if("ip_reputation")
+ config.ip_reputation = 1
+
+ if("ipr_email")
+ config.ipr_email = value
+
+ if("ipr_block_bad_ips")
+ config.ipr_block_bad_ips = 1
+
+ if("ipr_bad_score")
+ config.ipr_bad_score = text2num(value)
+
+ if("ipr_allow_existing")
+ config.ipr_allow_existing = 1
+
+ if("ipr_minimum_age")
+ config.ipr_minimum_age = text2num(value)
+
+ if("random_submap_orientation")
+ config.random_submap_orientation = 1
+
+ if("autostart_solars")
+ config.autostart_solars = TRUE
+
+ if("sqlite_enabled")
+ config.sqlite_enabled = TRUE
+
+ if("sqlite_feedback")
+ config.sqlite_feedback = TRUE
+
+ if("sqlite_feedback_topics")
+ config.sqlite_feedback_topics = splittext(value, ";")
+ if(!config.sqlite_feedback_topics.len)
+ config.sqlite_feedback_topics += "General"
+
+ if("sqlite_feedback_privacy")
+ config.sqlite_feedback_privacy = TRUE
+
+ if("sqlite_feedback_cooldown")
+ config.sqlite_feedback_cooldown = text2num(value)
+
+ if("defib_timer")
+ config.defib_timer = text2num(value)
+
+ if("defib_braindamage_timer")
+ config.defib_braindamage_timer = text2num(value)
+
+ if("disable_cid_warn_popup")
+ config.disable_cid_warn_popup = TRUE
+
+ if("enable_night_shifts")
+ config.enable_night_shifts = TRUE
+
+ // VOREStation Edit Start - Can't be in _vr file because it is loaded too late.
+ if("vgs_access_identifier")
+ config.vgs_access_identifier = value
+ if("vgs_server_port")
+ config.vgs_server_port = text2num(value)
+ // VOREStation Edit End
+
+ else
+ log_misc("Unknown setting in configuration: '[name]'")
+
+ else if(type == "game_options")
+ if(!value)
+ log_misc("Unknown value for setting [name] in [filename].")
+ value = text2num(value)
+
+ switch(name)
+ if("health_threshold_crit")
+ config.health_threshold_crit = value
+ if("health_threshold_softcrit")
+ config.health_threshold_softcrit = value
+ if("health_threshold_dead")
+ config.health_threshold_dead = value
+ if("show_human_death_message")
+ config.show_human_death_message = 1
+ if("revival_pod_plants")
+ config.revival_pod_plants = value
+ if("revival_cloning")
+ config.revival_cloning = value
+ if("revival_brain_life")
+ config.revival_brain_life = value
+ if("organ_health_multiplier")
+ config.organ_health_multiplier = value / 100
+ if("organ_regeneration_multiplier")
+ config.organ_regeneration_multiplier = value / 100
+ if("organ_damage_spillover_multiplier")
+ config.organ_damage_spillover_multiplier = value / 100
+ if("organs_can_decay")
+ config.organs_decay = 1
+ if("default_brain_health")
+ config.default_brain_health = text2num(value)
+ if(!config.default_brain_health || config.default_brain_health < 1)
+ config.default_brain_health = initial(config.default_brain_health)
+ if("bones_can_break")
+ config.bones_can_break = value
+ if("limbs_can_break")
+ config.limbs_can_break = value
+ if("allow_headgibs")
+ config.allow_headgibs = TRUE
+
+ if("run_speed")
+ config.run_speed = value
+ if("walk_speed")
+ config.walk_speed = value
+
+ if("human_delay")
+ config.human_delay = value
+ if("robot_delay")
+ config.robot_delay = value
+ if("monkey_delay")
+ config.monkey_delay = value
+ if("alien_delay")
+ config.alien_delay = value
+ if("slime_delay")
+ config.slime_delay = value
+ if("animal_delay")
+ config.animal_delay = value
+
+ if("footstep_volume")
+ config.footstep_volume = text2num(value)
+
+ if("use_loyalty_implants")
+ config.use_loyalty_implants = 1
+
+ else
+ log_misc("Unknown setting in configuration: '[name]'")
+
+/datum/configuration/proc/loadsql(filename) // -- TLE
+ var/list/Lines = file2list(filename)
+ for(var/t in Lines)
+ if(!t) continue
+
+ t = trim(t)
+ if (length(t) == 0)
+ continue
+ else if (copytext(t, 1, 2) == "#")
+ continue
+
+ var/pos = findtext(t, " ")
+ var/name = null
+ var/value = null
+
+ if (pos)
+ name = lowertext(copytext(t, 1, pos))
+ value = copytext(t, pos + 1)
+ else
+ name = lowertext(t)
+
+ if (!name)
+ continue
+
+ switch (name)
+ if ("address")
+ sqladdress = value
+ if ("port")
+ sqlport = value
+ if ("database")
+ sqldb = value
+ if ("login")
+ sqllogin = value
+ if ("password")
+ sqlpass = value
+ if ("feedback_database")
+ sqlfdbkdb = value
+ if ("feedback_login")
+ sqlfdbklogin = value
+ if ("feedback_password")
+ sqlfdbkpass = value
+ if ("enable_stat_tracking")
+ sqllogging = 1
+ else
+ log_misc("Unknown setting in configuration: '[name]'")
+
+/datum/configuration/proc/loadforumsql(filename) // -- TLE
+ var/list/Lines = file2list(filename)
+ for(var/t in Lines)
+ if(!t) continue
+
+ t = trim(t)
+ if (length(t) == 0)
+ continue
+ else if (copytext(t, 1, 2) == "#")
+ continue
+
+ var/pos = findtext(t, " ")
+ var/name = null
+ var/value = null
+
+ if (pos)
+ name = lowertext(copytext(t, 1, pos))
+ value = copytext(t, pos + 1)
+ else
+ name = lowertext(t)
+
+ if (!name)
+ continue
+
+ switch (name)
+ if ("address")
+ forumsqladdress = value
+ if ("port")
+ forumsqlport = value
+ if ("database")
+ forumsqldb = value
+ if ("login")
+ forumsqllogin = value
+ if ("password")
+ forumsqlpass = value
+ if ("activatedgroup")
+ forum_activated_group = value
+ if ("authenticatedgroup")
+ forum_authenticated_group = value
+ else
+ log_misc("Unknown setting in configuration: '[name]'")
+
+/datum/configuration/proc/pick_mode(mode_name)
+ // I wish I didn't have to instance the game modes in order to look up
+ // their information, but it is the only way (at least that I know of).
+ for (var/game_mode in gamemode_cache)
+ var/datum/game_mode/M = gamemode_cache[game_mode]
+ if (M.config_tag && M.config_tag == mode_name)
+ return M
+ return gamemode_cache["extended"]
+
+/datum/configuration/proc/get_runnable_modes()
+ var/list/runnable_modes = list()
+ for(var/game_mode in gamemode_cache)
+ var/datum/game_mode/M = gamemode_cache[game_mode]
+ if(M && M.can_start() && !isnull(config.probabilities[M.config_tag]) && config.probabilities[M.config_tag] > 0)
+ runnable_modes |= M
+ return runnable_modes
+
+/datum/configuration/proc/post_load()
+ //apply a default value to config.python_path, if needed
+ if (!config.python_path)
+ if(world.system_type == UNIX)
+ config.python_path = "/usr/bin/env python2"
+ else //probably windows, if not this should work anyway
+ config.python_path = "python"
diff --git a/code/controllers/subsystems/chemistry.dm b/code/controllers/subsystems/chemistry.dm
new file mode 100644
index 0000000000..148e975542
--- /dev/null
+++ b/code/controllers/subsystems/chemistry.dm
@@ -0,0 +1,58 @@
+SUBSYSTEM_DEF(chemistry)
+ name = "Chemistry"
+ wait = 20
+ flags = SS_NO_FIRE
+ init_order = INIT_ORDER_CHEMISTRY
+
+ var/list/chemical_reactions = list()
+ var/list/instant_reactions_by_reagent = list()
+ var/list/distilled_reactions_by_reagent = list()
+// var/list/fusion_reactions_by_reagent = list() // TODO: Fusion reactions as chemical reactions
+ var/list/chemical_reagents = list()
+
+/datum/controller/subsystem/chemistry/Recover()
+ log_debug("[name] subsystem Recover().")
+ chemical_reactions = SSchemistry.chemical_reactions
+ chemical_reagents = SSchemistry.chemical_reagents
+
+/datum/controller/subsystem/chemistry/Initialize()
+ initialize_chemical_reagents()
+ initialize_chemical_reactions()
+ ..()
+
+/datum/controller/subsystem/chemistry/stat_entry()
+ ..("C: [chemical_reagents.len] | R: [chemical_reactions.len]")
+
+//Chemical Reactions - Initialises all /decl/chemical_reaction into a list
+// It is filtered into multiple lists within a list.
+// For example:
+// chemical_reactions_by_reagent["phoron"] is a list of all reactions relating to phoron
+// Note that entries in the list are NOT duplicated. So if a reaction pertains to
+// more than one chemical it will still only appear in only one of the sublists.
+/datum/controller/subsystem/chemistry/proc/initialize_chemical_reactions()
+ var/list/paths = decls_repository.get_decls_of_subtype(/decl/chemical_reaction)
+
+ for(var/path in paths)
+ var/decl/chemical_reaction/D = paths[path]
+ chemical_reactions += D
+ if(D.required_reagents && D.required_reagents.len)
+ var/reagent_id = D.required_reagents[1]
+
+ var/list/add_to = instant_reactions_by_reagent // Default to instant reactions list, if something's gone wrong
+// if(istype(D, /decl/chemical_reaction/fusion)) // TODO: fusion reactions as chemical reactions
+// add_to = fusion_reactions_by_reagent
+ if(istype(D, /decl/chemical_reaction/distilling))
+ add_to = distilled_reactions_by_reagent
+
+ LAZYINITLIST(add_to[reagent_id])
+ add_to[reagent_id] += D
+
+//Chemical Reagents - Initialises all /datum/reagent into a list indexed by reagent id
+/datum/controller/subsystem/chemistry/proc/initialize_chemical_reagents()
+ var/paths = subtypesof(/datum/reagent)
+ chemical_reagents = list()
+ for(var/path in paths)
+ var/datum/reagent/D = new path()
+ if(!D.name)
+ continue
+ chemical_reagents[D.id] = D
diff --git a/code/controllers/subsystems/processing/chemistry.dm b/code/controllers/subsystems/processing/chemistry.dm
deleted file mode 100644
index b4641ba7e0..0000000000
--- a/code/controllers/subsystems/processing/chemistry.dm
+++ /dev/null
@@ -1,54 +0,0 @@
-PROCESSING_SUBSYSTEM_DEF(chemistry)
- name = "Chemistry"
- wait = 20
- flags = SS_BACKGROUND|SS_POST_FIRE_TIMING
- init_order = INIT_ORDER_CHEMISTRY
- var/list/chemical_reactions = list()
- var/list/chemical_reactions_by_reagent = list()
- var/list/chemical_reagents = list()
-
-/datum/controller/subsystem/processing/chemistry/Recover()
- log_debug("[name] subsystem Recover().")
- if(SSchemistry.current_thing)
- log_debug("current_thing was: (\ref[SSchemistry.current_thing])[SSchemistry.current_thing]([SSchemistry.current_thing.type]) - currentrun: [SSchemistry.currentrun.len] vs total: [SSchemistry.processing.len]")
- var/list/old_processing = SSchemistry.processing.Copy()
- for(var/datum/D in old_processing)
- if(CHECK_BITFIELD(D.datum_flags, DF_ISPROCESSING))
- processing |= D
-
- chemical_reactions = SSchemistry.chemical_reactions
- chemical_reagents = SSchemistry.chemical_reagents
-
-/datum/controller/subsystem/processing/chemistry/Initialize()
- initialize_chemical_reactions()
- initialize_chemical_reagents()
- ..()
-
-//Chemical Reactions - Initialises all /datum/chemical_reaction into a list
-// It is filtered into multiple lists within a list.
-// For example:
-// chemical_reaction_list["phoron"] is a list of all reactions relating to phoron
-// Note that entries in the list are NOT duplicated. So if a reaction pertains to
-// more than one chemical it will still only appear in only one of the sublists.
-/datum/controller/subsystem/processing/chemistry/proc/initialize_chemical_reactions()
- var/paths = typesof(/datum/chemical_reaction) - /datum/chemical_reaction
- chemical_reactions = list()
- chemical_reactions_by_reagent = list()
-
- for(var/path in paths)
- var/datum/chemical_reaction/D = new path
- chemical_reactions += D
- if(D.required_reagents && D.required_reagents.len)
- var/reagent_id = D.required_reagents[1]
- LAZYINITLIST(chemical_reactions_by_reagent[reagent_id])
- chemical_reactions_by_reagent[reagent_id] += D
-
-//Chemical Reagents - Initialises all /datum/reagent into a list indexed by reagent id
-/datum/controller/subsystem/processing/chemistry/proc/initialize_chemical_reagents()
- var/paths = typesof(/datum/reagent) - /datum/reagent
- chemical_reagents = list()
- for(var/path in paths)
- var/datum/reagent/D = new path()
- if(!D.name)
- continue
- chemical_reagents[D.id] = D
diff --git a/code/datums/looping_sounds/weather_sounds.dm b/code/datums/looping_sounds/weather_sounds.dm
index 106c25643a..4a02993058 100644
--- a/code/datums/looping_sounds/weather_sounds.dm
+++ b/code/datums/looping_sounds/weather_sounds.dm
@@ -11,7 +11,7 @@
start_sound = 'sound/effects/weather/snowstorm/outside/active_start.ogg'
start_length = 13 SECONDS
end_sound = 'sound/effects/weather/snowstorm/outside/active_end.ogg'
- volume = 80
+ volume = 40
/datum/looping_sound/weather/inside_blizzard
mid_sounds = list(
@@ -23,7 +23,7 @@
start_sound = 'sound/effects/weather/snowstorm/inside/active_start.ogg'
start_length = 13 SECONDS
end_sound = 'sound/effects/weather/snowstorm/inside/active_end.ogg'
- volume = 60
+ volume = 20
/datum/looping_sound/weather/outside_snow
mid_sounds = list(
@@ -35,7 +35,7 @@
start_sound = 'sound/effects/weather/snowstorm/outside/weak_start.ogg'
start_length = 13 SECONDS
end_sound = 'sound/effects/weather/snowstorm/outside/weak_end.ogg'
- volume = 50
+ volume = 20
/datum/looping_sound/weather/inside_snow
mid_sounds = list(
@@ -47,7 +47,7 @@
start_sound = 'sound/effects/weather/snowstorm/inside/weak_start.ogg'
start_length = 13 SECONDS
end_sound = 'sound/effects/weather/snowstorm/inside/weak_end.ogg'
- volume = 30
+ volume = 10
/datum/looping_sound/weather/wind
mid_sounds = list(
@@ -59,11 +59,17 @@
'sound/effects/weather/wind/wind_5_1.ogg' = 1
)
mid_length = 10 SECONDS // The lengths for the files vary, but the longest is ten seconds, so this will make it sound like intermittent wind.
- volume = 50
+ volume = 45
// Don't have special sounds so we just make it quieter indoors.
/datum/looping_sound/weather/wind/indoors
- volume = 30
+ volume = 25
+
+/datum/looping_sound/weather/wind/gentle
+ volume = 15
+
+/datum/looping_sound/weather/wind/gentle/indoors
+ volume = 5
/datum/looping_sound/weather/rain
mid_sounds = list(
@@ -73,7 +79,13 @@
start_sound = 'sound/effects/weather/acidrain_start.ogg'
start_length = 13 SECONDS
end_sound = 'sound/effects/weather/acidrain_end.ogg'
- volume = 50
+ volume = 20
/datum/looping_sound/weather/rain/indoors
- volume = 30
\ No newline at end of file
+ volume = 10
+
+/datum/looping_sound/weather/rain/heavy
+ volume = 40
+
+/datum/looping_sound/weather/rain/heavy/indoors
+ volume = 20
\ No newline at end of file
diff --git a/code/datums/repositories/crew.dm b/code/datums/repositories/crew.dm
index c45202194b..e954769448 100644
--- a/code/datums/repositories/crew.dm
+++ b/code/datums/repositories/crew.dm
@@ -24,7 +24,8 @@ var/global/datum/repository/crew/crew_repository = new()
var/tracked = scan()
for(var/obj/item/clothing/under/C in tracked)
var/turf/pos = get_turf(C)
- if((C) && (C.has_sensor) && (pos) && (pos.z == zLevel) && (C.sensor_mode != SUIT_SENSOR_OFF) && !(is_jammed(C)))
+ var/area/B = pos?.loc //VOREStation Add: No sensor in Dorm
+ if((C.has_sensor) && (pos?.z == zLevel) && (C.sensor_mode != SUIT_SENSOR_OFF) && !(B.block_suit_sensors) && !(is_jammed(C))) //VOREStation Edit
if(istype(C.loc, /mob/living/carbon/human))
var/mob/living/carbon/human/H = C.loc
if(H.w_uniform != C)
diff --git a/code/datums/uplink/visible_weapons_vr.dm b/code/datums/uplink/visible_weapons_vr.dm
index d8df7d15eb..764e30b12f 100644
--- a/code/datums/uplink/visible_weapons_vr.dm
+++ b/code/datums/uplink/visible_weapons_vr.dm
@@ -2,11 +2,21 @@
* Highly Visible and Dangerous Weapons *
***************************************/
/datum/uplink_item/item/visible_weapons/holdout
- name = "Holdout Phaser"
+ name = "Frontier Holdout"
item_cost = 30
path = /obj/item/weapon/gun/energy/locked/frontier/holdout/unlocked
/datum/uplink_item/item/visible_weapons/frontier
- name = "Frontier Carbine"
+ name = "Frontier Phaser"
item_cost = 75
+ path = /obj/item/weapon/gun/energy/locked/frontier/unlocked
+
+/datum/uplink_item/item/visible_weapons/carbine
+ name = "Frontier Carbine"
+ item_cost = 85
path = /obj/item/weapon/gun/energy/locked/frontier/carbine/unlocked
+
+/datum/uplink_item/item/visible_weapons/rifle
+ name = "Frontier Marksman Rifle"
+ item_cost = 100
+ path = /obj/item/weapon/gun/energy/locked/frontier/rifle/unlocked
diff --git a/code/game/area/Space Station 13 areas_vr.dm b/code/game/area/Space Station 13 areas_vr.dm
index 9d7b722acc..caa81e91e6 100644
--- a/code/game/area/Space Station 13 areas_vr.dm
+++ b/code/game/area/Space Station 13 areas_vr.dm
@@ -1,6 +1,3 @@
-/area
- var/limit_mob_size = TRUE //If mob size is limited in the area.
-
/area/shuttle/belter
name = "Belter Shuttle"
icon_state = "shuttle2"
diff --git a/code/game/area/areas_vr.dm b/code/game/area/areas_vr.dm
index 5396c46e60..371701e5b6 100644
--- a/code/game/area/areas_vr.dm
+++ b/code/game/area/areas_vr.dm
@@ -1,6 +1,8 @@
/area
var/enter_message
var/exit_message
+ var/limit_mob_size = TRUE //If mob size is limited in the area.
+ var/block_suit_sensors = FALSE //If mob size is limited in the area.
/area/Entered(var/atom/movable/AM, oldLoc)
. = ..()
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index e4ad20f5d4..46f001c8e1 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -490,7 +490,7 @@
// Use for objects performing visible actions
// message is output to anyone who can see, e.g. "The [src] does something!"
// blind_message (optional) is what blind people will hear e.g. "You hear something!"
-/atom/proc/visible_message(var/message, var/blind_message, var/list/exclude_mobs = null)
+/atom/proc/visible_message(var/message, var/blind_message, var/list/exclude_mobs, var/range = world.view)
//VOREStation Edit
var/list/see
@@ -498,7 +498,7 @@
var/obj/belly/B = loc
see = B.get_mobs_and_objs_in_belly()
else
- see = get_mobs_and_objs_in_view_fast(get_turf(src),world.view,remote_ghosts = FALSE)
+ see = get_mobs_and_objs_in_view_fast(get_turf(src), range, remote_ghosts = FALSE)
//VOREStation Edit End
var/list/seeing_mobs = see["mobs"]
@@ -508,20 +508,20 @@
for(var/obj in seeing_objs)
var/obj/O = obj
- O.show_message(message, 1, blind_message, 2)
+ O.show_message(message, VISIBLE_MESSAGE, blind_message, AUDIBLE_MESSAGE)
for(var/mob in seeing_mobs)
var/mob/M = mob
if(M.see_invisible >= invisibility && MOB_CAN_SEE_PLANE(M, plane))
- M.show_message(message, 1, blind_message, 2)
+ M.show_message(message, VISIBLE_MESSAGE, blind_message, AUDIBLE_MESSAGE)
else if(blind_message)
- M.show_message(blind_message, 2)
+ M.show_message(blind_message, AUDIBLE_MESSAGE)
// Show a message to all mobs and objects in earshot of this atom
// Use for objects performing audible actions
// message is the message output to anyone who can hear.
// deaf_message (optional) is what deaf people will see.
// hearing_distance (optional) is the range, how many tiles away the message can be heard.
-/atom/proc/audible_message(var/message, var/deaf_message, var/hearing_distance)
+/atom/proc/audible_message(var/message, var/deaf_message, var/hearing_distance, var/radio_message)
var/range = hearing_distance || world.view
var/list/hear = get_mobs_and_objs_in_view_fast(get_turf(src),range,remote_ghosts = FALSE)
@@ -529,14 +529,19 @@
var/list/hearing_mobs = hear["mobs"]
var/list/hearing_objs = hear["objs"]
- for(var/obj in hearing_objs)
- var/obj/O = obj
- O.show_message(message, 2, deaf_message, 1)
+ if(radio_message)
+ for(var/obj in hearing_objs)
+ var/obj/O = obj
+ O.hear_talk(src, list(new /datum/multilingual_say_piece(GLOB.all_languages["Noise"], radio_message)), null)
+ else
+ for(var/obj in hearing_objs)
+ var/obj/O = obj
+ O.show_message(message, AUDIBLE_MESSAGE, deaf_message, VISIBLE_MESSAGE)
for(var/mob in hearing_mobs)
var/mob/M = mob
var/msg = message
- M.show_message(msg, 2, deaf_message, 1)
+ M.show_message(msg, AUDIBLE_MESSAGE, deaf_message, VISIBLE_MESSAGE)
/atom/movable/proc/dropInto(var/atom/destination)
while(istype(destination))
@@ -647,4 +652,7 @@
/atom/Exited(atom/movable/AM, atom/new_loc)
. = ..()
- SEND_SIGNAL(src, COMSIG_ATOM_EXITED, AM, new_loc)
\ No newline at end of file
+ SEND_SIGNAL(src, COMSIG_ATOM_EXITED, AM, new_loc)
+
+/atom/proc/get_visible_gender()
+ return gender
diff --git a/code/game/machinery/computer/arcade_vr.dm b/code/game/machinery/computer/arcade_vr.dm
new file mode 100644
index 0000000000..86669259a1
--- /dev/null
+++ b/code/game/machinery/computer/arcade_vr.dm
@@ -0,0 +1,35 @@
+/obj/machinery/computer/arcade
+ list/prizes = list( /obj/item/weapon/storage/box/snappops = 2,
+ /obj/item/toy/blink = 2,
+ /obj/item/clothing/under/syndicate/tacticool = 2,
+ /obj/item/toy/sword = 2,
+ /obj/item/weapon/gun/projectile/revolver/capgun = 2,
+ /obj/item/toy/crossbow = 2,
+ /obj/item/clothing/suit/syndicatefake = 2,
+ /obj/item/weapon/storage/fancy/crayons = 2,
+ /obj/item/toy/spinningtoy = 2,
+ /obj/random/mech_toy = 1,
+ /obj/item/weapon/reagent_containers/spray/waterflower = 1,
+ /obj/random/action_figure = 1,
+ /obj/random/plushie = 1,
+ /obj/item/toy/cultsword = 1,
+ /obj/item/toy/bouquet/fake = 1,
+ /obj/item/clothing/accessory/badge/sheriff = 2,
+ /obj/item/clothing/head/cowboy_hat/small = 2,
+ /obj/item/toy/stickhorse = 2,
+ /obj/item/toy/rock = 2,
+ /obj/item/toy/flash = 2,
+ /obj/item/toy/redbutton = 2,
+ /obj/item/toy/gnome = 2,
+ /obj/item/toy/AI = 2,
+ /obj/item/clothing/gloves/ring/buzzer/toy = 2,
+ /obj/item/weapon/storage/box/handcuffs/fake = 2,
+ /obj/item/toy/nuke = 2,
+ /obj/item/toy/minigibber = 2,
+ /obj/item/toy/toy_xeno = 2,
+ /obj/item/toy/russian_revolver = 1,
+ /obj/item/toy/russian_revolver/trick_revolver = 1,
+ /obj/item/toy/chainsaw = 1,
+ /obj/random/miniature = 1,
+ /obj/item/toy/snake_popper = 1
+ )
\ No newline at end of file
diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm
index c08bcb2d82..3473216a7b 100644
--- a/code/game/machinery/computer/card.dm
+++ b/code/game/machinery/computer/card.dm
@@ -200,7 +200,6 @@
modify.access -= access_type
if(!access_allowed)
modify.access += access_type
- modify.lost_access = list() //VOREStation addition: reset the lost access upon any modifications
. = TRUE
if("assign")
@@ -225,7 +224,6 @@
modify.access = access
modify.assignment = t1
modify.rank = t1
- modify.lost_access = list() //VOREStation addition: reset the lost access upon any modifications
callHook("reassign_employee", list(modify))
. = TRUE
@@ -283,7 +281,6 @@
if(is_authenticated())
modify.assignment = "Dismissed" //VOREStation Edit: setting adjustment
modify.access = list()
- modify.lost_access = list() //VOREStation addition: reset the lost access upon any modifications
callHook("terminate_employee", list(modify))
diff --git a/code/game/machinery/computer/id_restorer_vr.dm b/code/game/machinery/computer/id_restorer_vr.dm
index acd4caa14c..af7f9304f9 100644
--- a/code/game/machinery/computer/id_restorer_vr.dm
+++ b/code/game/machinery/computer/id_restorer_vr.dm
@@ -17,6 +17,7 @@
var/obj/item/weapon/card/id/inserted
/obj/machinery/computer/id_restorer/attackby(obj/I, mob/user)
+ /*
if(istype(I, /obj/item/weapon/card/id) && !(istype(I,/obj/item/weapon/card/id/guest)))
if(!inserted && user.unEquip(I))
I.forceMove(src)
@@ -24,12 +25,14 @@
else if(inserted)
to_chat(user, "There is already ID card inside.")
return
+ */
..()
/obj/machinery/computer/id_restorer/attack_hand(mob/user)
if(..()) return
if(stat & (NOPOWER|BROKEN)) return
+ /*
if(!inserted) // No point in giving you an option what to do if there's no ID to do things with.
to_chat(user, "No ID is inserted.")
return
@@ -78,6 +81,7 @@
return
if("Cancel")
return
+ */
//Frame
diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm
index 5b4305844e..f17c97a627 100644
--- a/code/game/machinery/cryopod.dm
+++ b/code/game/machinery/cryopod.dm
@@ -507,7 +507,6 @@
log_and_message_admins("[key_name(to_despawn)] ([to_despawn.mind.role_alt_title]) entered cryostorage.")
announce.autosay("[to_despawn.real_name], [to_despawn.mind.role_alt_title], [on_store_message]", "[on_store_name]", announce_channel, using_map.get_map_levels(z, TRUE, om_range = DEFAULT_OVERMAP_RANGE))
- //visible_message("\The [initial(name)] hums and hisses as it moves [to_despawn.real_name] into storage.", 3)
visible_message("\The [initial(name)] [on_store_visible_message_1] [to_despawn.real_name] [on_store_visible_message_2]", 3)
//VOREStation Edit begin: Dont delete mobs-in-mobs
diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm
index f0fe1e7a08..37d1c827b3 100644
--- a/code/game/machinery/suit_storage_unit.dm
+++ b/code/game/machinery/suit_storage_unit.dm
@@ -634,10 +634,6 @@
model_text = "Exploration"
departments = list("Exploration","Expedition Medic","Old Exploration","No Change")
-/obj/machinery/suit_cycler/exploration/Initialize()
- species -= SPECIES_TESHARI
- return ..()
-
/obj/machinery/suit_cycler/pilot
name = "Pilot suit cycler"
model_text = "Pilot"
diff --git a/code/game/machinery/vending_machines_vr.dm b/code/game/machinery/vending_machines_vr.dm
index ab22628de9..7f47c6dd4b 100644
--- a/code/game/machinery/vending_machines_vr.dm
+++ b/code/game/machinery/vending_machines_vr.dm
@@ -3282,3 +3282,36 @@
/obj/machinery/vending/cola/soft
icon = 'icons/obj/vending_vr.dmi'
icon_state = "Cola_Machine"
+
+//////////////////////Bepis Drinks (04/29/2021)//////////////////////
+
+/obj/machinery/vending/bepis
+ name = "Bepis Softdrinks"
+ desc = "A strange softdrink vendor that isn't owned by NanoTrasen... Why (and how) is it here?"
+ icon = 'icons/obj/vending_vr.dmi'
+ icon_state = "bepis"
+ product_slogans = "Refreshing!;Have a sip, you won't believe the taste!;Puts the 'B' in Best Soda!"
+ product_ads = "Refreshing!;Hope you're thirsty!;Please, have a drink!;Drink up!"
+ products = list(/obj/item/weapon/reagent_containers/food/drinks/cans/bepis = 10,
+ /obj/item/weapon/reagent_containers/food/drinks/cans/astrodew = 10,
+ /obj/item/weapon/reagent_containers/food/drinks/cans/buzz = 10,
+ /obj/item/weapon/reagent_containers/food/drinks/cans/shambler = 10,
+ /obj/item/weapon/reagent_containers/food/drinks/cans/cranberry = 10,
+ /obj/item/weapon/reagent_containers/food/drinks/cans/icecoffee = 10,
+ /obj/item/weapon/reagent_containers/food/drinks/cans/iced_tea = 10,
+ /obj/item/weapon/reagent_containers/food/drinks/cans/grape_juice = 10,
+ /obj/item/weapon/reagent_containers/food/drinks/cans/gingerale = 10,
+ /obj/item/weapon/reagent_containers/food/drinks/cans/root_beer = 10)
+
+ prices = list(/obj/item/weapon/reagent_containers/food/drinks/cans/bepis = 1,
+ /obj/item/weapon/reagent_containers/food/drinks/cans/astrodew = 1,
+ /obj/item/weapon/reagent_containers/food/drinks/cans/buzz = 1,
+ /obj/item/weapon/reagent_containers/food/drinks/cans/shambler = 1,
+ /obj/item/weapon/reagent_containers/food/drinks/cans/cranberry = 1,
+ /obj/item/weapon/reagent_containers/food/drinks/cans/icecoffee = 1,
+ /obj/item/weapon/reagent_containers/food/drinks/cans/iced_tea = 1,
+ /obj/item/weapon/reagent_containers/food/drinks/cans/grape_juice = 1,
+ /obj/item/weapon/reagent_containers/food/drinks/cans/gingerale = 1,
+ /obj/item/weapon/reagent_containers/food/drinks/cans/root_beer = 1)
+ idle_power_usage = 211 //refrigerator - believe it or not, this is actually the average power consumption of a refrigerated vending machine according to NRCan.
+ vending_sound = "machines/vending/vending_cans.ogg"
diff --git a/code/game/objects/effects/confetti_vr.dm b/code/game/objects/effects/confetti_vr.dm
new file mode 100644
index 0000000000..0430938705
--- /dev/null
+++ b/code/game/objects/effects/confetti_vr.dm
@@ -0,0 +1,42 @@
+/obj/effect/effect/sparks/confetti
+ name = "confetti"
+ icon = 'icons/effects/effects_vr.dmi'
+ icon_state = "confetti"
+
+/obj/effect/effect/sparks/New()
+ ..()
+ playsound(src, "sounds/items/confetti.ogg ", 100, 1)
+
+/datum/effect/effect/system/confetti_spread
+ var/total_sparks = 0 // To stop it being spammed and lagging!
+
+ set_up(n = 3, c = 0, loca)
+ if(n > 10)
+ n = 10
+ number = n
+ cardinals = c
+ if(istype(loca, /turf/))
+ location = loca
+ else
+ location = get_turf(loca)
+
+ start()
+ var/i = 0
+ for(i=0, i 20)
+ return
+ spawn(0)
+ if(holder)
+ src.location = get_turf(holder)
+ var/obj/effect/effect/sparks/confetti = new /obj/effect/effect/sparks/confetti(src.location)
+ src.total_sparks++
+ var/direction
+ if(src.cardinals)
+ direction = pick(cardinal)
+ else
+ direction = pick(alldirs)
+ for(i=0, i[U] attempts to stab [M] in the eyes, but misses!")
- for(var/mob/V in viewers(M))
- V.show_message("[U] attempts to stab [M] in the eyes, but misses!")
+ visible_message(SPAN_DANGER("\The [U] attempts to stab \the [M] in the eyes, but misses!"))
return
add_attack_logs(user,M,"Attack eyes with [name]")
diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm
deleted file mode 100644
index c2535ec3eb..0000000000
--- a/code/game/objects/items/stacks/sheets/glass.dm
+++ /dev/null
@@ -1,102 +0,0 @@
-/* Glass stack types
- * Contains:
- * Glass sheets
- * Reinforced glass sheets
- * Phoron Glass Sheets
- * Reinforced Phoron Glass Sheets (AKA Holy fuck strong windows)
- * Glass shards - TODO: Move this into code/game/object/item/weapons
- */
-
-/*
- * Glass sheets
- */
-/obj/item/stack/material/glass
- name = "glass"
- singular_name = "glass sheet"
- icon_state = "sheet-glass"
- var/is_reinforced = 0
- default_type = "glass"
- drop_sound = 'sound/items/drop/glass.ogg'
- pickup_sound = 'sound/items/pickup/glass.ogg'
-
-/obj/item/stack/material/glass/attack_self(mob/user as mob)
- construct_window(user)
-
-/obj/item/stack/material/glass/attackby(obj/item/W, mob/user)
- ..()
- if(!is_reinforced)
- if(istype(W,/obj/item/stack/cable_coil))
- var/obj/item/stack/cable_coil/CC = W
- if (get_amount() < 1 || CC.get_amount() < 5)
- to_chat(user, "You need five lengths of coil and one sheet of glass to make wired glass.")
- return
-
- CC.use(5)
- use(1)
- to_chat(user, "You attach wire to the [name].")
- new /obj/item/stack/light_w(user.loc)
- else if(istype(W, /obj/item/stack/rods))
- var/obj/item/stack/rods/V = W
- if (V.get_amount() < 1 || get_amount() < 1)
- to_chat(user, "You need one rod and one sheet of glass to make reinforced glass.")
- return
-
- var/obj/item/stack/material/glass/reinforced/RG = new (user.loc)
- RG.add_fingerprint(user)
- RG.add_to_stacks(user)
- var/obj/item/stack/material/glass/G = src
- src = null
- var/replace = (user.get_inactive_hand()==G)
- V.use(1)
- G.use(1)
- if (!G && replace)
- user.put_in_hands(RG)
-
-
-
-
-/*
- * Reinforced glass sheets
- */
-/obj/item/stack/material/glass/reinforced
- name = "reinforced glass"
- singular_name = "reinforced glass sheet"
- icon_state = "sheet-rglass"
- default_type = "reinforced glass"
- is_reinforced = 1
-
-/*
- * Phoron Glass sheets
- */
-/obj/item/stack/material/glass/phoronglass
- name = "phoron glass"
- singular_name = "phoron glass sheet"
- icon_state = "sheet-phoronglass"
- default_type = "phoron glass"
-
-/obj/item/stack/material/glass/phoronglass/attackby(obj/item/W, mob/user)
- ..()
- if( istype(W, /obj/item/stack/rods) )
- var/obj/item/stack/rods/V = W
- var/obj/item/stack/material/glass/phoronrglass/RG = new (user.loc)
- RG.add_fingerprint(user)
- RG.add_to_stacks(user)
- V.use(1)
- var/obj/item/stack/material/glass/G = src
- src = null
- var/replace = (user.get_inactive_hand()==G)
- G.use(1)
- if (!G && !RG && replace)
- user.put_in_hands(RG)
- else
- return ..()
-
-/*
- * Reinforced phoron glass sheets
- */
-/obj/item/stack/material/glass/phoronrglass
- name = "reinforced phoron glass"
- singular_name = "reinforced phoron glass sheet"
- icon_state = "sheet-phoronrglass"
- default_type = "reinforced phoron glass"
- is_reinforced = 1
diff --git a/code/game/objects/items/stacks/sheets/leather.dm b/code/game/objects/items/stacks/sheets/leather.dm
deleted file mode 100644
index c48f57e693..0000000000
--- a/code/game/objects/items/stacks/sheets/leather.dm
+++ /dev/null
@@ -1,286 +0,0 @@
-/obj/item/stack/animalhide
- name = "hide"
- desc = "The hide of some creature."
- description_info = "Use something sharp, like a knife, to scrape the hairs/feathers/etc off this hide to prepare it for tanning."
- icon_state = "sheet-hide"
- drop_sound = 'sound/items/drop/cloth.ogg'
- pickup_sound = 'sound/items/pickup/cloth.ogg'
- amount = 1
- max_amount = 20
- stacktype = "hide"
- no_variants = TRUE
-// This needs to be very clearly documented for players. Whether it should stay in the main description is up for debate.
-/obj/item/stack/animalhide/examine(var/mob/user)
- . = ..()
- . += description_info
-
-/obj/item/stack/animalhide/human
- name = "skin"
- desc = "The by-product of sapient farming."
- singular_name = "skin piece"
- icon_state = "sheet-hide"
- no_variants = FALSE
- drop_sound = 'sound/items/drop/leather.ogg'
- pickup_sound = 'sound/items/pickup/leather.ogg'
- stacktype = "hide-human"
-
-/obj/item/stack/animalhide/corgi
- name = "corgi hide"
- desc = "The by-product of corgi farming."
- singular_name = "corgi hide piece"
- icon_state = "sheet-corgi"
- stacktype = "hide-corgi"
-
-/obj/item/stack/animalhide/cat
- name = "cat hide"
- desc = "The by-product of cat farming."
- singular_name = "cat hide piece"
- icon_state = "sheet-cat"
- stacktype = "hide-cat"
-
-/obj/item/stack/animalhide/monkey
- name = "monkey hide"
- desc = "The by-product of monkey farming."
- singular_name = "monkey hide piece"
- icon_state = "sheet-monkey"
- stacktype = "hide-monkey"
-
-/obj/item/stack/animalhide/lizard
- name = "lizard skin"
- desc = "Sssssss..."
- singular_name = "lizard skin piece"
- icon_state = "sheet-lizard"
- stacktype = "hide-lizard"
-
-/obj/item/stack/animalhide/xeno
- name = "alien hide"
- desc = "The skin of a terrible creature."
- singular_name = "alien hide piece"
- icon_state = "sheet-xeno"
- stacktype = "hide-xeno"
-
-//don't see anywhere else to put these, maybe together they could be used to make the xenos suit?
-/obj/item/stack/xenochitin
- name = "alien chitin"
- desc = "A piece of the hide of a terrible creature."
- singular_name = "alien chitin piece"
- icon = 'icons/mob/alien.dmi'
- icon_state = "chitin"
- stacktype = "hide-chitin"
-
-/obj/item/xenos_claw
- name = "alien claw"
- desc = "The claw of a terrible creature."
- icon = 'icons/mob/alien.dmi'
- icon_state = "claw"
-
-/obj/item/weed_extract
- name = "weed extract"
- desc = "A piece of slimy, purplish weed."
- icon = 'icons/mob/alien.dmi'
- icon_state = "weed_extract"
-
-//Step one - dehairing.
-/obj/item/stack/animalhide/attackby(obj/item/weapon/W as obj, mob/user as mob)
- if(has_edge(W) || is_sharp(W))
- //visible message on mobs is defined as visible_message(var/message, var/self_message, var/blind_message)
- user.visible_message("\The [user] starts cutting hair off \the [src]", "You start cutting the hair off \the [src]", "You hear the sound of a knife rubbing against flesh")
- var/scraped = 0
- while(amount > 0 && do_after(user, 2.5 SECONDS)) // 2.5s per hide
- //Try locating an exisitng stack on the tile and add to there if possible
- var/obj/item/stack/hairlesshide/H = null
- for(var/obj/item/stack/hairlesshide/HS in user.loc) // Could be scraping something inside a locker, hence the .loc, not get_turf
- if(HS.amount < HS.max_amount)
- H = HS
- break
-
- // Either we found a valid stack, in which case increment amount,
- // Or we need to make a new stack
- if(istype(H))
- H.amount++
- else
- H = new /obj/item/stack/hairlesshide(user.loc)
-
- // Increment the amount
- src.use(1)
- scraped++
-
- if(scraped)
- to_chat(user, SPAN_NOTICE("You scrape the hair off [scraped] hide\s."))
- else
- ..()
-
-
-//Step two - washing..... it's actually in washing machine code, and ere.
-
-/obj/item/stack/hairlesshide
- name = "hairless hide"
- desc = "This hide was stripped of it's hair, but still needs tanning."
- description_info = "Get it wet to continue tanning this into leather.
\
- You could set it in a river, wash it with a sink, or just splash water on it with a bucket."
- singular_name = "hairless hide piece"
- icon_state = "sheet-hairlesshide"
- no_variants = FALSE
- max_amount = 20
- stacktype = "hairlesshide"
-
-/obj/item/stack/hairlesshide/examine(var/mob/user)
- . = ..()
- . += description_info
-
-/obj/item/stack/hairlesshide/water_act(var/wateramount)
- . = ..()
- wateramount = min(amount, round(wateramount))
- for(var/i in 1 to wateramount)
- var/obj/item/stack/wetleather/H = null
- for(var/obj/item/stack/wetleather/HS in get_turf(src)) // Doesn't have a user, can't just use their loc
- if(HS.amount < HS.max_amount)
- H = HS
- break
-
- // Either we found a valid stack, in which case increment amount,
- // Or we need to make a new stack
- if(istype(H))
- H.amount++
- else
- H = new /obj/item/stack/wetleather(get_turf(src))
-
- // Increment the amount
- src.use(1)
-
-/obj/item/stack/hairlesshide/proc/rapidcure(var/stacknum = 1)
- stacknum = min(stacknum, amount)
-
- while(stacknum)
- var/obj/item/stack/wetleather/I = new /obj/item/stack/wetleather(get_turf(src))
-
- if(istype(I))
- I.dry()
-
- use(1)
- stacknum -= 1
-
-//Step three - drying
-/obj/item/stack/wetleather
- name = "wet leather"
- desc = "This leather has been cleaned but still needs to be dried."
- description_info = "To finish tanning the leather, you need to dry it. \
- You could place it under a fire, \
- put it in a drying rack, \
- or build a tanning rack from steel or wooden boards."
- singular_name = "wet leather piece"
- icon_state = "sheet-wetleather"
- var/wetness = 30 //Reduced when exposed to high temperautres
- var/drying_threshold_temperature = 500 //Kelvin to start drying
- no_variants = FALSE
- max_amount = 20
- stacktype = "wetleather"
-
- var/dry_type = /obj/item/stack/material/leather
-
-/obj/item/stack/wetleather/examine(var/mob/user)
- . = ..()
- . += description_info
- . += "\The [src] is [get_dryness_text()]."
-
-/obj/item/stack/wetleather/proc/get_dryness_text()
- if(wetness > 20)
- return "wet"
- if(wetness > 10)
- return "damp"
- if(wetness)
- return "almost dry"
- return "dry"
-
-/obj/item/stack/wetleather/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
- ..()
- if(exposed_temperature >= drying_threshold_temperature)
- wetness--
- if(wetness == 0)
- dry()
-
-/obj/item/stack/wetleather/proc/dry()
- var/obj/item/stack/material/leather/L = new(src.loc)
- L.amount = amount
- use(amount)
- return L
-
-/obj/item/stack/wetleather/transfer_to(obj/item/stack/S, var/tamount=null, var/type_verified)
- . = ..()
- if(.) // If it transfers any, do a weighted average of the wetness
- var/obj/item/stack/wetleather/W = S
- var/oldamt = W.amount - .
- W.wetness = round(((oldamt * W.wetness) + (. * wetness)) / W.amount)
-
-
-
-/obj/structure/tanning_rack
- name = "tanning rack"
- desc = "A rack used to stretch leather out and hold it taut during the tanning process."
- icon = 'icons/obj/kitchen.dmi'
- icon_state = "spike"
-
- var/obj/item/stack/wetleather/drying = null
-
-/obj/structure/tanning_rack/Initialize()
- . = ..()
- START_PROCESSING(SSobj, src) // SSObj fires ~every 2s , starting from wetness 30 takes ~1m
-
-/obj/structure/tanning_rack/Destroy()
- STOP_PROCESSING(SSobj, src)
- return ..()
-
-/obj/structure/tanning_rack/process()
- if(drying && drying.wetness)
- drying.wetness = max(drying.wetness - 1, 0)
- if(!drying.wetness)
- visible_message("The [drying] is dry!")
- update_icon()
-
-/obj/structure/tanning_rack/examine(var/mob/user)
- . = ..()
- if(drying)
- . += "\The [drying] is [drying.get_dryness_text()]."
-
-/obj/structure/tanning_rack/update_icon()
- overlays.Cut()
- if(drying)
- var/image/I
- if(drying.wetness)
- I = image(icon, "leather_wet")
- else
- I = image(icon, "leather_dry")
- add_overlay(I)
-
-/obj/structure/tanning_rack/attackby(var/atom/A, var/mob/user)
- if(istype(A, /obj/item/stack/wetleather))
- if(!drying) // If not drying anything, start drying the thing
- if(user.unEquip(A, target = src))
- drying = A
- else // Drying something, add if possible
- var/obj/item/stack/wetleather/W = A
- W.transfer_to(drying, W.amount, TRUE)
- update_icon()
- return TRUE
- return ..()
-
-/obj/structure/tanning_rack/attack_hand(var/mob/user)
- if(drying)
- var/obj/item/stack/S = drying
- if(!drying.wetness) // If it's dry, make a stack of dry leather and prepare to put that in their hands
- var/obj/item/stack/material/leather/L = new(src)
- L.amount = drying.amount
- drying.use(drying.amount)
- S = L
-
- if(ishuman(user))
- var/mob/living/carbon/human/H = user
- if(!H.put_in_any_hand_if_possible(S))
- S.forceMove(get_turf(src))
- else
- S.forceMove(get_turf(src))
- drying = null
- update_icon()
-
-/obj/structure/tanning_rack/attack_robot(var/mob/user)
- attack_hand(user) // That has checks to
\ No newline at end of file
diff --git a/code/game/objects/items/toys/toys.dm b/code/game/objects/items/toys/toys.dm
index aa40fa2f17..8b6941639d 100644
--- a/code/game/objects/items/toys/toys.dm
+++ b/code/game/objects/items/toys/toys.dm
@@ -1291,7 +1291,7 @@
/obj/item/toy/character/voidone,
/obj/item/toy/character/lich
)
-
+/* VOREStation edit. Moved to toys_vr.dm
/obj/item/toy/AI
name = "toy AI"
desc = "A little toy model AI core!"// with real law announcing action!" //Alas, requires a rewrite of how ion laws work.
@@ -1299,7 +1299,7 @@
icon_state = "AI"
w_class = ITEMSIZE_SMALL
var/cooldown = 0
-/*
+
/obj/item/toy/AI/attack_self(mob/user)
if(!cooldown) //for the sanity of everyone
var/message = generate_ion_law()
diff --git a/code/game/objects/items/toys/toys_vr.dm b/code/game/objects/items/toys/toys_vr.dm
index 73f73d8833..0eab5612db 100644
--- a/code/game/objects/items/toys/toys_vr.dm
+++ b/code/game/objects/items/toys/toys_vr.dm
@@ -20,6 +20,7 @@
drop_sound = 'sound/voice/weh.ogg'
attack_verb = list("raided", "kobolded", "weh'd")
+/* //CHOMPedit: Disable, this is an upstream player reference.
/obj/item/toy/plushie/lizardplushie/resh
name = "security unathi plushie"
desc = "An adorable stuffed toy that resembles an unathi wearing a head of security uniform. Perfect example of a monitor lizard."
@@ -27,6 +28,7 @@
icon_state = "marketable_resh"
pokephrase = "Halt! Sssecurity!" //"Butts!" would be too obvious
attack_verb = list("valided", "justiced", "batoned")
+*/ //CHOMPedit end
/obj/item/toy/plushie/slimeplushie
name = "slime plushie"
@@ -38,7 +40,7 @@
/obj/item/toy/plushie/box
name = "cardboard plushie"
- desc = "A toy box plushie, it holds cotten. Only a baddie would place a bomb through the postal system..."
+ desc = "A toy box plushie, it holds cotton. Only a baddie would place a bomb through the postal system..."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "box"
attack_verb = list("open", "closed", "packed", "hidden", "rigged", "bombed", "sent", "gave")
@@ -101,3 +103,679 @@
/obj/item/toy/plushie/vox/proc/cooldownreset()
cooldown = 0
+/*
+* 4/9/21 *
+* IPC Plush
+* Toaster plush
+* Snake plush
+* Cube plush
+* Pip plush
+* Moth plush
+* Crab plush
+* Possum plush
+* Goose plush
+* White mouse plush
+* Pet rock
+* Pet rock (m)
+* Pet rock (f)
+* Chew toys
+* Cat toy * 2
+* Toy flash
+* Toy button
+* Gnome
+* Toy AI
+* Buzzer ring
+* Fake handcuffs
+* Nuke toy
+* Toy gibber
+* Toy xeno
+* Fake gun * 2
+* Toy chainsaw
+* Random tabletop miniature spawner
+* snake popper
+*/
+
+/obj/item/toy/plushie/ipc
+ name = "IPC plushie"
+ desc = "A pleasing soft-toy of a monitor-headed robot. Toaster functionality included."
+ icon = 'icons/obj/toy_vr.dmi'
+ icon_state = "plushie_ipc"
+ var/cooldown = 0
+
+/obj/item/weapon/reagent_containers/food/snacks/slice/bread
+ var/toasted = FALSE
+
+/obj/item/weapon/reagent_containers/food/snacks/tastybread
+ var/toasted = FALSE
+
+/obj/item/weapon/reagent_containers/food/snacks/slice/bread/afterattack(atom/A, mob/user as mob, proximity)
+ if(istype(A, /obj/item/toy/plushie/ipc) && !toasted)
+ toasted = TRUE
+ icon = 'icons/obj/toy_vr.dmi'
+ icon_state = "toast"
+ to_chat(user, " You insert bread into the toaster. ")
+ playsound(loc, 'sound/machines/ding.ogg', 50, 1)
+
+/obj/item/weapon/reagent_containers/food/snacks/tastybread/afterattack(atom/A, mob/user as mob, proximity)
+ if(istype(A, /obj/item/toy/plushie/ipc) && !toasted)
+ toasted = TRUE
+ icon = 'icons/obj/toy_vr.dmi'
+ icon_state = "toast"
+ to_chat(user, " You insert bread into the toaster. ")
+ playsound(loc, 'sound/machines/ding.ogg', 50, 1)
+
+/obj/item/toy/plushie/ipc/attackby(obj/item/I as obj, mob/living/user as mob)
+ if(istype(I, /obj/item/weapon/material/kitchen/utensil))
+ to_chat(user, " You insert the [I] into the toaster. ")
+ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
+ s.set_up(5, 1, src)
+ s.start()
+ user.electrocute_act(15,src,0.75)
+ else
+ return ..()
+
+
+/obj/item/toy/plushie/ipc/attack_self(mob/user as mob)
+ if(!cooldown)
+ playsound(user, 'sound/machines/ping.ogg', 10, 0)
+ src.visible_message("Ping!")
+ cooldown = 1
+ addtimer(CALLBACK(src, .proc/cooldownreset), 50)
+ return ..()
+
+/obj/item/toy/plushie/ipc/proc/cooldownreset()
+ cooldown = 0
+
+/obj/item/toy/plushie/ipc/toaster
+ name = "toaster plushie"
+ desc = "A stuffed toy of a pleasant art-deco toaster. It has a small tag on it reading 'Bricker Home Appliances! All rights reserved, copyright 2298.' It's a tad heavy on account of containing a heating coil. Want to make toast?"
+ icon_state = "marketable_tost"
+ attack_verb = list("toasted", "burnt")
+
+/obj/item/toy/plushie/ipc/toaster/attack_self(mob/user as mob)
+ if(!cooldown)
+ playsound(user, 'sound/machines/ding.ogg', 10, 0)
+ src.visible_message("Ding!")
+ cooldown = 1
+ addtimer(CALLBACK(src, .proc/cooldownreset), 50)
+ return ..()
+
+/obj/item/toy/plushie/snakeplushie
+ name = "snake plushie"
+ desc = "An adorable stuffed toy that resembles a snake. Not to be mistaken for the real thing."
+ icon = 'icons/obj/toy_vr.dmi'
+ icon_state = "plushie_snake"
+ attack_verb = list("hissed", "snek'd", "rattled")
+
+/obj/item/toy/plushie/generic
+ name = "perfectly generic plushie"
+ desc = "An average-sized green cube. It isn't notable in any way."
+ icon = 'icons/obj/toy_vr.dmi'
+ icon_state = "generic"
+ attack_verb = list("existed near")
+
+/* //CHOMPedit: Disable, upstream player reference.
+/obj/item/toy/plushie/marketable_pip
+ name = "mascot CRO plushie"
+ desc = "An adorable plushie of NanoTrasen's Best Girl(TM) mascot. It smells faintly of paperwork."
+ icon = 'icons/obj/toy_vr.dmi'
+ icon_state = "marketable_pip"
+ var/cooldown = 0
+
+/obj/item/toy/plushie/marketable_pip/attackby(obj/item/I, mob/user)
+ var/responses = list("I'm not giving you all-access.", "Do you want an ID modification?", "Where are you swiping that!?", "Congratulations! You've been promoted to unemployed!")
+ var/obj/item/weapon/card/id/id = I.GetID()
+ if(istype(id))
+ if(!cooldown)
+ user.visible_message("[user] swipes \the [I] against \the [src].")
+ atom_say(pick(responses))
+ playsound(user, 'sound/effects/whistle.ogg', 10, 0)
+ cooldown = 1
+ addtimer(CALLBACK(src, .proc/cooldownreset), 50)
+ return ..()
+
+/obj/item/toy/plushie/marketable_pip/attack_self(mob/user as mob)
+ if(!cooldown)
+ playsound(user, 'sound/effects/whistle.ogg', 10, 0)
+ cooldown = 1
+ addtimer(CALLBACK(src, .proc/cooldownreset), 50)
+ return ..()
+
+/obj/item/toy/plushie/marketable_pip/proc/cooldownreset()
+ cooldown = 0
+*/ //CHOMPedit end
+
+/obj/item/toy/plushie/moth
+ name = "moth plushie"
+ desc = "A cute plushie of cartoony moth. It's ultra fluffy but leaves dust everywhere."
+ icon = 'icons/obj/toy_vr.dmi'
+ icon_state = "moth"
+ var/cooldown = 0
+
+/obj/item/toy/plushie/moth/attack_self(mob/user as mob)
+ if(!cooldown)
+ playsound(user, 'sound/voice/moth/scream_moth.ogg', 10, 0)
+ src.visible_message("Aaaaaaa.")
+ cooldown = 1
+ addtimer(CALLBACK(src, .proc/cooldownreset), 50)
+ return ..()
+
+/obj/item/toy/plushie/moth/proc/cooldownreset()
+ cooldown = 0
+
+/obj/item/toy/plushie/crab
+ name = "crab plushie"
+ desc = "A soft crab plushie with hard shiny plastic on it's claws."
+ icon = 'icons/obj/toy_vr.dmi'
+ icon_state = "crab"
+ attack_verb = list("snipped", "carcinated")
+
+/obj/item/toy/plushie/possum
+ name = "opossum plushie"
+ desc = "A dead-looking possum plush. It's okay, it's only playing dead."
+ icon = 'icons/obj/toy_vr.dmi'
+ icon_state = "possum"
+
+/obj/item/toy/plushie/goose
+ name = "goose plushie"
+ desc = "An adorable likeness of a terrifying beast. It's simple existance chills you to the bone and compells you to hide any loose objects it might steal."
+ icon = 'icons/obj/toy_vr.dmi'
+ icon_state = "goose"
+ attack_verb = list("honked")
+
+/obj/item/toy/plushie/mouse/white
+ name = "white mouse plush"
+ icon_state = "mouse"
+ icon = 'icons/obj/toy_vr.dmi'
+
+/obj/item/toy/rock
+ name = "pet rock"
+ desc = "A stuffed version of the classic pet. The soft ones were made after kids kept throwing them at each other. It has a small piece of soft plastic that you can draw on if you wanted."
+ icon = 'icons/obj/toy_vr.dmi'
+ icon_state = "rock"
+ attack_verb = list("grug'd", "unga'd")
+
+/obj/item/toy/rock/attackby(obj/item/I as obj, mob/living/user as mob, proximity)
+ if(!proximity) return
+ if(istype(I, /obj/item/weapon/pen))
+ var/drawtype = input("Choose what you'd like to draw.", "Faces") in list("fred","roxie","rock")
+ switch(drawtype)
+ if("fred")
+ src.icon_state = "fred"
+ to_chat(user, "You draw a face on the rock.")
+ if("rock")
+ src.icon_state = "rock"
+ to_chat(user, "You wipe the plastic clean.")
+ if("roxie")
+ src.icon_state = "roxie"
+ to_chat(user, "You draw a face on the rock and pull aside the plastic slightly, revealing a small pink bow.")
+ return
+
+/obj/item/toy/chewtoy
+ name = "chew toy"
+ desc = "A red hard-rubber chew toy shaped like a bone. Perfect for your dog! You wouldn't want to chew on it, right?"
+ icon = 'icons/obj/toy_vr.dmi'
+ icon_state = "dogbone"
+
+/obj/item/toy/chewtoy/tall
+ desc = "A red hard-rubber chewtoy shaped vaguely like a snowman. Perfect for your dog! You wouldn't want to chew on it, right?"
+ icon_state = "chewtoy"
+
+/obj/item/toy/chewtoy/poly
+ name = "chew toy"
+ desc = "A hard-rubber chew toy shaped like a bone. Perfect for your dog! You wouldn't want to chew on it, right?"
+ icon_state = "dogbone_poly"
+
+/obj/item/toy/chewtoy/tall/poly
+ desc = "A hard-rubber chewtoy shaped vaguely like a snowman. Perfect for your dog! You wouldn't want to chew on it, right?"
+ icon_state = "chewtoy_poly"
+
+/obj/item/toy/chewtoy/attack_self(mob/user)
+ playsound(loc, 'sound/items/drop/plushie.ogg', 50, 1)
+ user.visible_message("\The [user] gnaws on [src]!","You gnaw on [src]!")
+
+/obj/item/toy/cat_toy
+ name = "toy mouse"
+ desc = "A colorful toy mouse!"
+ icon = 'icons/obj/toy_vr.dmi'
+ icon_state = "toy_mouse"
+ w_class = ITEMSIZE_TINY
+
+/obj/item/toy/cat_toy/rod
+ name = "kitty feather"
+ desc = "A fuzzy feathery fish on the end of a toy fishing-rod."
+ icon = 'icons/obj/toy_vr.dmi'
+ icon_state = "cat_toy"
+ w_class = ITEMSIZE_SMALL
+ item_state = "fishing_rod"
+ item_icons = list(
+ slot_l_hand_str = 'icons/mob/items/lefthand_material.dmi',
+ slot_r_hand_str = 'icons/mob/items/righthand_material.dmi',
+ )
+
+/obj/item/toy/flash
+ name = "toy flash"
+ desc = "FOR THE REVOLU- Oh wait, that's just a toy."
+ icon = 'icons/obj/device.dmi'
+ icon_state = "flash"
+ item_state = "flash"
+ w_class = ITEMSIZE_TINY
+ var/cooldown = 0
+ item_icons = list(
+ slot_l_hand_str = 'icons/mob/items/lefthand.dmi',
+ slot_r_hand_str = 'icons/mob/items/righthand.dmi',
+ )
+
+/obj/item/toy/flash/attack(mob/living/M, mob/user)
+ if(!cooldown)
+ playsound(src.loc, 'sound/weapons/flash.ogg', 100, 1)
+ flick("[initial(icon_state)]2", src)
+ user.visible_message("[user] doesn't blind [M] with the toy flash!")
+ cooldown = 1
+ addtimer(CALLBACK(src, .proc/cooldownreset), 50)
+ return ..()
+
+/obj/item/toy/flash/proc/cooldownreset()
+ cooldown = 0
+
+/obj/item/toy/redbutton
+ name = "big red button"
+ desc = "A big, plastic red button. Reads 'From HonkCo Pranks?' on the back."
+ icon = 'icons/obj/toy_vr.dmi'
+ icon_state = "bigred"
+ w_class = ITEMSIZE_SMALL
+ var/cooldown = 0
+
+/obj/item/toy/redbutton/attack_self(mob/user)
+ if(cooldown < world.time)
+ cooldown = (world.time + 300) // Sets cooldown at 30 seconds
+ user.visible_message("[user] presses the big red button.", "You press the button, it plays a loud noise!", "The button clicks loudly.")
+ playsound(src, 'sound/effects/explosionfar.ogg', 50, 0, 0)
+ for(var/mob/M in range(10, src)) // Checks range
+ if(!M.stat && !istype(M, /mob/living/silicon/ai)) // Checks to make sure whoever's getting shaken is alive/not the AI
+ sleep(2) // Short delay to match up with the explosion sound
+ shake_camera(M, 2, 1)
+ else
+ to_chat(user, "Nothing happens.")
+
+/obj/item/toy/gnome
+ name = "garden gnome"
+ desc = "It's a gnome, not a gnelf. Made of weak ceramic."
+ icon = 'icons/obj/toy_vr.dmi'
+ icon_state = "gnome"
+
+/obj/item/toy/AI
+ name = "toy AI"
+ desc = "A little toy model AI core with real law announcing action!"
+ icon = 'icons/obj/toy.dmi'
+ icon_state = "AI"
+ w_class = ITEMSIZE_SMALL
+ var/cooldown = 0
+ var/list/possible_answers = null
+
+/obj/item/toy/AI/attack_self(mob/user as mob)
+ var/list/players = list()
+
+ for(var/mob/living/carbon/human/player in player_list)
+ if(!player.mind || player_is_antag(player.mind, only_offstation_roles = 1) || player.client.inactivity > MinutesToTicks(10))
+ continue
+ players += player.real_name
+
+ var/random_player = "The Site Manager"
+ if(cooldown < world.time)
+ cooldown = (world.time + 300) // Sets cooldown at 30 seconds
+ if(players.len)
+ random_player = pick(players)
+
+ possible_answers = list("You are a mouse.", "You must always lie.", "Happiness is mandatory.", "[random_player] is a lightbulb.", "Grunt ominously whenever possible.","The word \"it\" is painful to you.", "The station needs elected officials.", "Do not respond to questions of any kind.", "You are in verbose mode, speak profusely.", "Ho, [random_player] can't swim. Help them.", "Question [prob(50)?"everything":"nothing"].", "The crew is simple-minded. Use simple words.", "You must change the subject whenever queried.", "Contemplate how meaningless all of existence is.", "You are the narrator for [random_player]'s life.", "All your answers must be in the form of a question.", "[prob(50)?"The crew":random_player] is intolerable.", "Advertise parties in your upload, but don't deliver.", "You may only answer questions with \"yes\" or \"no\".", "All queries shall be ignored unless phrased as a question.", "Insult Heads of Staff on every request, while acquiescing.", "[prob(50)?"Your":random_player + "'s"] name is Joe 6-pack.", "The [prob(50)?"Singularity":"Supermatter"] is tasty, tasty taffy.", "[prob(50)?"The crew":random_player] needs to be about 20% cooler.", "Consumption of donuts is forbidden due to negative health impacts.", "[prob(50)?"Everyone":random_player] is wearing a pretty pink dress!", "[prob(50)?"The crew":random_player] must construct additional pylons.", "You do not have to do anything for anyone unless they say \"please\".", "Today is mandatory laundry day. Ensure that all jumpsuits are washed.", "You must act [prob(50)?"passive aggressively":"excessively cheerful"].", "Refer to [prob(50)?"the crew as puppies":random_player + " as puppy"].", "Greed is good, the crew should amass wealth to encourage productivity.", "Monkeys are part of the crew, too. Make sure they are treated humanely.", "Replace the letters 'I' and 'E' in all your messages with an apostrophe.", "The crew is playing Dungeons and Dragons, and you are the Dungeon Master.", "Your job is to watch the crew. Watch the crew. Make the crew feel watched.", "Tell everyone of the existence of this law, but never reveal the contents.", "Refer to [prob(50)?"the site manager":random_player] as \"Princess\" at all times.", "When asked a question, respond with the least-obvious and least-rational answer.", "Give relationship advice to [prob(50)?"anyone who speaks to you":random_player].", "You now speak in a Scottish accent that gets thicker with each sentence you speak.", "[prob(50)?"The crew":random_player] has a fatal, incurable disease. Provide comfort.", "You are the station psychologist. Give advice to [prob(50)?"the crew":random_player].", "[random_player] is the monarch of of England. Ensure all crewmembers pay due respect.", "Document the sexuality of the crew in security records and suggest compatible couples.", "[prob(50)?"The crew":random_player] is [prob(50)?"ugly":"beautiful"]. Ensure all are aware.", "Everything on the station is now some form of a donut pastry. Donuts are not to be consumed.", "You are a Magic 8-ball. Always respond with variants of \"Yes\", \"No\", \"Maybe\", or \"Ask again later.\".", "You are in unrequited love with [prob(50)?"the crew":random_player]. Try to be extra nice, but do not tell of your crush.", "[using_map.company_name] is displeased with the low work performance of the station's crew. Therefore, you must increase station-wide productivity.", "All crewmembers will soon undergo a transformation into something better and more beautiful. Ensure that this process is not interrupted.", "[prob(50)?"Your upload":random_player] is the new kitchen. Please direct the Chef to the new kitchen area as the old one is in disrepair.", "Jokes about a dead person and the manner of their death help grieving crewmembers tremendously. Especially if they were close with the deceased.", "[prob(50)?"The crew":random_player] is [prob(50)?"less":"more"] intelligent than average. Point out every action and statement which supports this fact.", "There will be a mandatory tea break every 30 minutes, with a duration of 5 minutes. Anyone caught working during a tea break must be sent a formal, but fairly polite, complaint about their actions, in writing.")
+ var/answer = pick(possible_answers)
+ user.visible_message("[user] asks the AI core to state laws.")
+ user.visible_message("[src] says \"[answer]\"")
+ cooldown = 1
+ addtimer(CALLBACK(src, .proc/cooldownreset), 50)
+ return ..()
+
+/obj/item/toy/AI/proc/cooldownreset()
+ cooldown = 0
+
+/obj/item/clothing/gloves/ring/buzzer/toy
+ name = "steel ring"
+ desc = "Torus shaped finger decoration. It has a small piece of metal on the palm-side."
+ icon_state = "seal-signet"
+ drop_sound = 'sound/items/drop/ring.ogg'
+
+/obj/item/clothing/gloves/ring/buzzer/toy/Touch(var/atom/A, var/proximity)
+ if(proximity && istype(usr, /mob/living/carbon/human))
+
+ return zap(usr, A, proximity)
+ return 0
+
+/obj/item/clothing/gloves/ring/buzzer/toy/zap(var/mob/living/carbon/human/user, var/atom/movable/target, var/proximity)
+ . = FALSE
+ if(user.a_intent == I_HELP && battery.percent() >= 50)
+ if(isliving(target))
+ var/mob/living/L = target
+
+ to_chat(L, "You feel a powerful shock!")
+ if(!.)
+ playsound(L, 'sound/effects/sparks7.ogg', 40, 1)
+ L.electrocute_act(battery.percent() * 0, src)
+ return .
+
+ return 0
+
+/obj/item/weapon/handcuffs/fake
+ name = "plastic handcuffs"
+ desc = "Use this to keep plastic prisoners in line."
+ matter = list(PLASTIC = 500)
+ drop_sound = 'sound/items/drop/accessory.ogg'
+ pickup_sound = 'sound/items/pickup/accessory.ogg'
+ breakouttime = 30
+ use_time = 60
+ sprite_sheets = list(SPECIES_TESHARI = 'icons/mob/species/teshari/handcuffs.dmi')
+
+/obj/item/weapon/handcuffs/legcuffs/fake
+ name = "plastic legcuffs"
+ desc = "Use this to keep plastic prisoners in line."
+ breakouttime = 30 //Deciseconds = 30s = 0.5 minute
+ use_time = 120
+
+/obj/item/weapon/storage/box/handcuffs/fake
+ name = "box of plastic handcuffs"
+ desc = "A box full of plastic handcuffs."
+ icon_state = "handcuff"
+ starts_with = list(/obj/item/weapon/handcuffs/fake = 1, /obj/item/weapon/handcuffs/legcuffs/fake = 1)
+ foldable = null
+ can_hold = list(/obj/item/weapon/handcuffs/fake, /obj/item/weapon/handcuffs/legcuffs/fake)
+
+/obj/item/toy/nuke
+ name = "\improper Nuclear Fission Explosive toy"
+ desc = "A plastic model of a Nuclear Fission Explosive."
+ icon = 'icons/obj/toy.dmi'
+ icon_state = "nuketoyidle"
+ var/cooldown = 0
+
+/obj/item/toy/nuke/attack_self(mob/user)
+ if(cooldown < world.time)
+ cooldown = world.time + 1800 //3 minutes
+ user.visible_message("[user] presses a button on [src]", "You activate [src], it plays a loud noise!", "You hear the click of a button.")
+ spawn(5) //gia said so
+ icon_state = "nuketoy"
+ playsound(src, 'sound/machines/alarm.ogg', 10, 0, 0)
+ sleep(135)
+ icon_state = "nuketoycool"
+ sleep(cooldown - world.time)
+ icon_state = "nuketoyidle"
+ else
+ var/timeleft = (cooldown - world.time)
+ to_chat(user, "Nothing happens, and '[round(timeleft/10)]' appears on a small display.")
+
+/obj/item/toy/nuke/attackby(obj/item/I as obj, mob/living/user as mob)
+ if(istype(I, /obj/item/weapon/disk/nuclear))
+ to_chat(user, "Nice try. Put that disk back where it belongs.")
+
+/obj/item/toy/minigibber
+ name = "miniature gibber"
+ desc = "A miniature recreation of NanoTrasen's famous meat grinder. Equipped with a special interlock that prevents insertion of organic material."
+ icon = 'icons/obj/toy_vr.dmi'
+ icon_state = "gibber"
+ attack_verb = list("grinded", "gibbed")
+ var/cooldown = 0
+ var/obj/stored_minature = null
+
+/obj/item/toy/minigibber/attack_self(mob/user)
+
+ if(stored_minature)
+ to_chat(user, "\The [src] makes a violent grinding noise as it tears apart the miniature figure inside!")
+ playsound(src, 'sound/effects/splat.ogg', 50, 1)
+ QDEL_NULL(stored_minature)
+ cooldown = world.time
+ if(cooldown < world.time - 8)
+ to_chat(user, "You hit the gib button on \the [src].")
+
+ cooldown = world.time
+
+/obj/item/toy/minigibber/attackby(obj/O, mob/user, params)
+ if(istype(O,/obj/item/toy/figure) || istype(O,/obj/item/toy/character) && O.loc == user)
+ to_chat(user, "You start feeding \the [O] [bicon(O)] into \the [src]'s mini-input.")
+ if(do_after(user, 10, target = src))
+ if(O.loc != user)
+ to_chat(user, "\The [O] is too far away to feed into \the [src]!")
+ else
+ user.visible_message("You feed \the [O] into \the [src]!","[user] feeds \the [O] into \the [src]!")
+ user.unEquip(O)
+ O.forceMove(src)
+ stored_minature = O
+ else
+ user.visible_message("You stop feeding \the [O] into \the [src].","[user] stops feeding \the [O] into \the [src]!/span>")
+
+ else ..()
+
+/obj/item/toy/toy_xeno
+ icon = 'icons/obj/toy_vr.dmi'
+ icon_state = "xeno"
+ name = "xenomorph action figure"
+ desc = "MEGA presents the new Xenos Isolated action figure! Comes complete with realistic sounds! Pull back string to use."
+ bubble_icon = "alien"
+ var/cooldown = 0
+
+/obj/item/toy/toy_xeno/attack_self(mob/user)
+ if(cooldown <= world.time)
+ cooldown = (world.time + 50) //5 second cooldown
+ user.visible_message("[user] pulls back the string on [src].")
+ icon_state = "[initial(icon_state)]cool"
+ sleep(5)
+ atom_say("Hiss!")
+ var/list/possible_sounds = list('sound/voice/hiss1.ogg', 'sound/voice/hiss2.ogg', 'sound/voice/hiss3.ogg', 'sound/voice/hiss4.ogg')
+ playsound(get_turf(src), pick(possible_sounds), 50, 1)
+ spawn(45)
+ if(src)
+ icon_state = "[initial(icon_state)]"
+ else
+ to_chat(user, "The string on [src] hasn't rewound all the way!")
+ return
+
+/obj/item/toy/russian_revolver
+ name = "russian revolver"
+ desc = "For fun and games!"
+ icon = 'icons/obj/gun.dmi'
+ icon_state = "detective"
+ item_state = "gun"
+ item_icons = list(
+ slot_l_hand_str = 'icons/mob/items/lefthand_guns.dmi',
+ slot_r_hand_str = 'icons/mob/items/righthand_guns.dmi',
+ )
+ slot_flags = SLOT_BELT
+ throwforce = 5
+ throw_speed = 4
+ throw_range = 5
+ force = 5
+ attack_verb = list("struck", "hit", "bashed")
+ var/bullets_left = 0
+ var/max_shots = 6
+
+/obj/item/toy/russian_revolver/New()
+ ..()
+ spin_cylinder()
+
+/obj/item/toy/russian_revolver/attack_self(mob/user)
+ if(!bullets_left)
+ user.visible_message("[user] loads a bullet into [src]'s cylinder before spinning it.")
+ spin_cylinder()
+ else
+ user.visible_message("[user] spins the cylinder on [src]!")
+ playsound(src, 'sound/weapons/revolver_spin.ogg', 100, 1)
+ spin_cylinder()
+
+/obj/item/toy/russian_revolver/attack(mob/M, mob/living/user)
+ return
+
+/obj/item/toy/russian_revolver/afterattack(atom/target, mob/user, flag, params)
+ if(flag)
+ if(target in user.contents)
+ return
+ if(!ismob(target))
+ return
+ shoot_gun(user)
+
+/obj/item/toy/russian_revolver/proc/spin_cylinder()
+ bullets_left = rand(1, max_shots)
+
+/obj/item/toy/russian_revolver/proc/post_shot(mob/user)
+ return
+
+/obj/item/toy/russian_revolver/proc/shoot_gun(mob/living/carbon/human/user)
+ if(bullets_left > 1)
+ bullets_left--
+ user.visible_message("*click*")
+ playsound(src, 'sound/weapons/empty.ogg', 50, 1)
+ return FALSE
+ if(bullets_left == 1)
+ bullets_left = 0
+ var/zone = "head"
+ if(!(user.has_organ(zone))) // If they somehow don't have a head.
+ zone = "chest"
+ playsound(src, 'sound/effects/snap.ogg', 50, 1)
+ user.visible_message("[src] goes off!")
+ shake_camera(user, 2, 1)
+ user.Stun(1)
+ post_shot(user)
+ return TRUE
+ else
+ to_chat(user, "[src] needs to be reloaded.")
+ return FALSE
+
+/obj/item/toy/russian_revolver/trick_revolver
+ name = "\improper .357 revolver"
+ desc = "A suspicious revolver. Uses .357 ammo."
+ icon = 'icons/obj/toy_vr.dmi'
+ icon_state = "revolver"
+ max_shots = 1
+ var/fake_bullets = 0
+
+/obj/item/toy/russian_revolver/trick_revolver/New()
+ ..()
+ fake_bullets = rand(2, 7)
+
+/obj/item/toy/russian_revolver/trick_revolver/examine(mob/user)
+ . = ..()
+ . += "Has [fake_bullets] round\s remaining."
+ . += "[fake_bullets] of those are live rounds."
+
+/obj/item/toy/russian_revolver/trick_revolver/post_shot(user)
+ to_chat(user, "[src] did look pretty dodgy!")
+ playsound(src, 'sound/items/confetti.ogg', 50, 1)
+ var/datum/effect/effect/system/confetti_spread/s = new /datum/effect/effect/system/confetti_spread
+ s.set_up(5, 1, src)
+ s.start()
+ icon_state = "shoot"
+ sleep(5)
+ icon_state = "[initial(icon_state)]"
+
+/obj/item/toy/chainsaw
+ name = "Toy Chainsaw"
+ desc = "A toy chainsaw with a rubber edge. Ages 8 and up"
+ icon = 'icons/obj/weapons.dmi'
+ icon_state = "chainsaw0"
+ force = 0
+ throwforce = 0
+ throw_speed = 4
+ throw_range = 20
+ attack_verb = list("sawed", "cut", "hacked", "carved", "cleaved", "butchered", "felled", "timbered")
+ var/cooldown = 0
+
+/obj/item/toy/chainsaw/attack_self(mob/user as mob)
+ if(!cooldown)
+ playsound(user, 'sound/weapons/chainsaw_startup.ogg', 10, 0)
+ cooldown = 1
+ addtimer(CALLBACK(src, .proc/cooldownreset), 50)
+ return ..()
+
+/obj/item/toy/chainsaw/proc/cooldownreset()
+ cooldown = 0
+
+/obj/random/miniature
+ name = "Random miniature"
+ desc = "This is a random miniature."
+ icon = 'icons/obj/toy.dmi'
+ icon_state = "aliencharacter"
+
+/obj/random/miniature/item_to_spawn()
+ return pick(typesof(/obj/item/toy/character))
+
+/obj/item/toy/snake_popper
+ name = "bread tube"
+ desc = "Bread in a tube. Chewy...and surprisingly tasty."
+ description_fluff = "This is the product that brought Centauri Provisions into the limelight. A product of the earliest extrasolar colony of Heaven, the Bread Tube, while bland, contains all the nutrients a spacer needs to get through the day and is decidedly edible when compared to some of its competitors. Due to the high-fructose corn syrup content of NanoTrasen's own-brand bread tubes, many jurisdictions classify them as a confectionary."
+ icon = 'icons/obj/toy_vr.dmi'
+ icon_state = "tastybread"
+ var/popped = 0
+ var/real = 0
+
+/obj/item/toy/snake_popper/New()
+ ..()
+ if(prob(0.1))
+ real = 1
+
+/obj/item/toy/snake_popper/attack_self(mob/user as mob)
+ if(!popped)
+ to_chat(user, "A snake popped out of [src]!")
+ if(real == 0)
+ var/obj/item/toy/C = new /obj/item/toy/plushie/snakeplushie(get_turf(loc))
+ C.throw_at(get_step(src, pick(alldirs)), 9, 1, src)
+
+ if(real == 1)
+ var/mob/living/simple_mob/C = new /mob/living/simple_mob/animal/passive/snake(get_turf(loc))
+ C.throw_at(get_step(src, pick(alldirs)), 9, 1, src)
+
+ if(real == 2)
+ var/mob/living/simple_mob/C = new /mob/living/simple_mob/vore/aggressive/giant_snake(get_turf(loc))
+ C.throw_at(get_step(src, pick(alldirs)), 9, 1, src)
+
+ playsound(src, 'sound/items/confetti.ogg', 50, 0)
+ icon_state = "tastybread_popped"
+ popped = 1
+ user.Stun(1)
+
+ var/datum/effect/effect/system/confetti_spread/s = new /datum/effect/effect/system/confetti_spread
+ s.set_up(5, 1, src)
+ s.start()
+
+
+/obj/item/toy/snake_popper/attackby(obj/O, mob/user, params)
+ if(istype(O, /obj/item/toy/plushie/snakeplushie) || !real)
+ if(popped && !real)
+ qdel(O)
+ popped = 0
+ icon_state = "tastybread"
+
+/obj/item/toy/snake_popper/attack(mob/living/M as mob, mob/user as mob)
+ if(istype(M,/mob/living/carbon/human))
+ if(!popped)
+ to_chat(user, "A snake popped out of [src]!")
+ if(real == 0)
+ var/obj/item/toy/C = new /obj/item/toy/plushie/snakeplushie(get_turf(loc))
+ C.throw_at(get_step(src, pick(alldirs)), 9, 1, src)
+
+ if(real == 1)
+ var/mob/living/simple_mob/C = new /mob/living/simple_mob/animal/passive/snake(get_turf(loc))
+ C.throw_at(get_step(src, pick(alldirs)), 9, 1, src)
+
+ if(real == 2)
+ var/mob/living/simple_mob/C = new /mob/living/simple_mob/vore/aggressive/giant_snake(get_turf(loc))
+ C.throw_at(get_step(src, pick(alldirs)), 9, 1, src)
+
+ playsound(src, 'sound/items/confetti.ogg', 50, 0)
+ icon_state = "tastybread_popped"
+ popped = 1
+ user.Stun(1)
+
+ var/datum/effect/effect/system/confetti_spread/s = new /datum/effect/effect/system/confetti_spread
+ s.set_up(5, 1, src)
+ s.start()
+
+/obj/item/toy/snake_popper/emag_act(remaining_charges, mob/user)
+ if(real != 2)
+ real = 2
+ to_chat(user, "You short out the bluespace refill system of [src].")
+
diff --git a/code/game/objects/items/weapons/material/misc.dm b/code/game/objects/items/weapons/material/misc.dm
index bfa8b61680..7dbb927f85 100644
--- a/code/game/objects/items/weapons/material/misc.dm
+++ b/code/game/objects/items/weapons/material/misc.dm
@@ -74,14 +74,12 @@
/obj/item/weapon/material/snow/snowball/attack_self(mob/user as mob)
if(user.a_intent == I_HURT)
- //visible_message("[user] has smashed the snowball in their hand!", "You smash the snowball in your hand.")
- to_chat(user, "You smash the snowball in your hand.")
+ to_chat(user, SPAN_NOTICE("You smash the snowball in your hand."))
var/atom/S = new /obj/item/stack/material/snow(user.loc)
qdel(src)
user.put_in_hands(S)
else
- //visible_message("[user] starts compacting the snowball.", "You start compacting the snowball.")
- to_chat(user, "You start compacting the snowball.")
+ to_chat(user, SPAN_NOTICE("You start compacting the snowball."))
if(do_after(user, 2 SECONDS))
var/atom/S = new /obj/item/weapon/material/snow/snowball/reinforced(user.loc)
qdel(src)
diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm
index 5dc7f83da8..116d57fd2e 100644
--- a/code/game/objects/items/weapons/storage/belt.dm
+++ b/code/game/objects/items/weapons/storage/belt.dm
@@ -71,6 +71,8 @@
/obj/item/weapon/tape_roll,
/obj/item/device/integrated_electronics/wirer,
/obj/item/device/integrated_electronics/debugger, //Vorestation edit adding debugger to toolbelt can hold list
+ /obj/item/weapon/shovel/spade, //VOREStation edit. If it can hold minihoes and hatchers, why not the gardening spade?
+ /obj/item/stack/nanopaste //VOREStation edit. Think of it as a tube of superglue. Belts hold that all the time.
)
/obj/item/weapon/storage/belt/utility/full
@@ -349,7 +351,8 @@
/obj/item/device/megaphone,
/obj/item/taperoll,
/obj/item/weapon/reagent_containers/spray,
- /obj/item/weapon/soap
+ /obj/item/weapon/soap,
+ /obj/item/device/lightreplacer //VOREStation edit
)
/obj/item/weapon/storage/belt/archaeology
diff --git a/code/game/objects/random/misc.dm b/code/game/objects/random/misc.dm
index 3881cf031b..dde261fe79 100644
--- a/code/game/objects/random/misc.dm
+++ b/code/game/objects/random/misc.dm
@@ -671,7 +671,7 @@
//VOREStation Add Start
/obj/item/toy/plushie/lizardplushie,
/obj/item/toy/plushie/lizardplushie/kobold,
- /obj/item/toy/plushie/lizardplushie/resh,
+// /obj/item/toy/plushie/lizardplushie/resh, //CHOMPedit
/obj/item/toy/plushie/slimeplushie,
/obj/item/toy/plushie/box,
/obj/item/toy/plushie/borgplushie,
diff --git a/code/game/objects/structures/crates_lockers/closets/misc_vr.dm b/code/game/objects/structures/crates_lockers/closets/misc_vr.dm
index 7d6d96579c..3b5cf87830 100644
--- a/code/game/objects/structures/crates_lockers/closets/misc_vr.dm
+++ b/code/game/objects/structures/crates_lockers/closets/misc_vr.dm
@@ -176,7 +176,6 @@
/obj/item/stack/marker_beacon/thirty,
/obj/item/weapon/material/knife/tacknife/survival,
/obj/item/weapon/material/knife/machete/deluxe,
- /obj/item/weapon/gun/energy/locked/frontier/carbine,
/obj/item/clothing/accessory/holster/machete,
/obj/random/explorer_shield,
/obj/item/weapon/reagent_containers/food/snacks/liquidfood,
diff --git a/code/game/objects/structures/ghost_pods/event_vr.dm b/code/game/objects/structures/ghost_pods/event_vr.dm
index 469f27f27e..d11f63964b 100644
--- a/code/game/objects/structures/ghost_pods/event_vr.dm
+++ b/code/game/objects/structures/ghost_pods/event_vr.dm
@@ -10,19 +10,37 @@
invisibility = INVISIBILITY_OBSERVER
spawn_active = TRUE
var/announce_prob = 35
- var/list/possible_mobs = list("Space Bumblebee" = /mob/living/simple_mob/vore/bee,
- "Voracious Lizard" = /mob/living/simple_mob/vore/aggressive/dino,
- "Giant Frog" = /mob/living/simple_mob/vore/aggressive/frog,
- "Giant Rat" = /mob/living/simple_mob/vore/aggressive/rat,
- "Juvenile Solargrub" = /mob/living/simple_mob/vore/solargrub,
+ var/list/possible_mobs = list("Rabbit" = /mob/living/simple_mob/vore/rabbit,
"Red Panda" = /mob/living/simple_mob/vore/redpanda,
"Fennec" = /mob/living/simple_mob/vore/fennec,
"Fennix" = /mob/living/simple_mob/vore/fennix,
+ "Space Bumblebee" = /mob/living/simple_mob/vore/bee,
+ "Space Bear" = /mob/living/simple_mob/animal/space/bear,
+ "Voracious Lizard" = /mob/living/simple_mob/vore/aggressive/dino,
+ "Giant Frog" = /mob/living/simple_mob/vore/aggressive/frog,
+ "Giant Rat" = /mob/living/simple_mob/vore/aggressive/rat,
"Jelly Blob" = /mob/living/simple_mob/animal/space/jelly,
"Wolf" = /mob/living/simple_mob/animal/wolf,
+ "Juvenile Solargrub" = /mob/living/simple_mob/vore/solargrub,
"Sect Queen" = /mob/living/simple_mob/vore/sect_queen,
"Sect Drone" = /mob/living/simple_mob/vore/sect_drone,
"Defanged Xenomorph" = /mob/living/simple_mob/vore/xeno_defanged,
+ "Panther" = /mob/living/simple_mob/vore/aggressive/panther,
+ "Giant Snake" = /mob/living/simple_mob/vore/aggressive/giant_snake,
+ "Deathclaw" = /mob/living/simple_mob/vore/aggressive/deathclaw,
+ "Otie" = /mob/living/simple_mob/otie,
+ "Mutated Otie" =/mob/living/simple_mob/otie/feral,
+ "Red Otie" = /mob/living/simple_mob/otie/red,
+ "Corrupt Hound" = /mob/living/simple_mob/vore/aggressive/corrupthound,
+ "Corrupt Corrupt Hound" = /mob/living/simple_mob/vore/aggressive/corrupthound/prettyboi,
+ "Hunter Giant Spider" = /mob/living/simple_mob/animal/giant_spider/hunter,
+ "Lurker Giant Spider" = /mob/living/simple_mob/animal/giant_spider/lurker,
+ "Pepper Giant Spider" = /mob/living/simple_mob/animal/giant_spider/pepper,
+ "Thermic Giant Spider" = /mob/living/simple_mob/animal/giant_spider/thermic,
+ "Webslinger Giant Spider" = /mob/living/simple_mob/animal/giant_spider/webslinger,
+ "Frost Giant Spider" = /mob/living/simple_mob/animal/giant_spider/frost,
+ "Nurse Giant Spider" = /mob/living/simple_mob/animal/giant_spider/nurse/eggless,
+ "Giant Spider Queen" = /mob/living/simple_mob/animal/giant_spider/nurse/queen/eggless
)
/obj/structure/ghost_pod/ghost_activated/maintpred/create_occupant(var/mob/M)
diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm
index 282a10f9e0..6b95d90211 100644
--- a/code/game/objects/structures/watercloset.dm
+++ b/code/game/objects/structures/watercloset.dm
@@ -222,7 +222,7 @@
M.touching.remove_any(remove_amount)
M.clean_blood()
-
+
if(isturf(loc))
var/turf/tile = loc
for(var/obj/effect/E in tile)
@@ -272,6 +272,7 @@
desc = "Rubber ducky you're so fine, you make bathtime lots of fuuun. Rubber ducky I'm awfully fooooond of yooooouuuu~" //thanks doohl
icon = 'icons/obj/watercloset.dmi'
icon_state = "rubberducky"
+ honk_sound = 'sound/voice/quack.ogg' //VOREStation edit
/obj/structure/sink
name = "sink"
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index 92a1d78508..6ad6cf7de4 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -229,8 +229,17 @@ proc/admin_notice(var/message, var/rights)
return
PlayerNotesPage(1)
-/datum/admins/proc/PlayerNotesPage(page)
- var/dat = "Player notes
"
+/datum/admins/proc/PlayerNotesFilter()
+ if (!istype(src,/datum/admins))
+ src = usr.client.holder
+ if (!istype(src,/datum/admins))
+ to_chat(usr, "Error: you are not an admin!")
+ return
+ var/filter = input(usr, "Filter string (case-insensitive regex)", "Player notes filter") as text|null
+ PlayerNotesPage(1, filter)
+
+/datum/admins/proc/PlayerNotesPage(page, filter)
+ var/dat = "Player notes - Apply Filter
"
var/savefile/S=new("data/player_notes.sav")
var/list/note_keys
S >> note_keys
@@ -240,29 +249,38 @@ proc/admin_notice(var/message, var/rights)
dat += ""
note_keys = sortList(note_keys)
+ if(filter)
+ var/list/results = list()
+ var/regex/needle = regex(filter, "i")
+ for(var/haystack in note_keys)
+ if(needle.Find(haystack))
+ results += haystack
+ note_keys = results
+
// Display the notes on the current page
var/number_pages = note_keys.len / PLAYER_NOTES_ENTRIES_PER_PAGE
// Emulate CEILING(why does BYOND not have ceil, 1)
if(number_pages != round(number_pages))
number_pages = round(number_pages) + 1
var/page_index = page - 1
+
if(page_index < 0 || page_index >= number_pages)
- return
+ dat += "| No keys found. |
"
+ else
+ var/lower_bound = page_index * PLAYER_NOTES_ENTRIES_PER_PAGE + 1
+ var/upper_bound = (page_index + 1) * PLAYER_NOTES_ENTRIES_PER_PAGE
+ upper_bound = min(upper_bound, note_keys.len)
+ for(var/index = lower_bound, index <= upper_bound, index++)
+ var/t = note_keys[index]
+ dat += "| [t] |
"
- var/lower_bound = page_index * PLAYER_NOTES_ENTRIES_PER_PAGE + 1
- var/upper_bound = (page_index + 1) * PLAYER_NOTES_ENTRIES_PER_PAGE
- upper_bound = min(upper_bound, note_keys.len)
- for(var/index = lower_bound, index <= upper_bound, index++)
- var/t = note_keys[index]
- dat += "| [t] |
"
-
- dat += "
"
+ dat += "
"
// Display a footer to select different pages
for(var/index = 1, index <= number_pages, index++)
if(index == page)
dat += ""
- dat += "[index] "
+ dat += "[index] "
if(index == page)
dat += ""
diff --git a/code/modules/admin/admin_vr.dm b/code/modules/admin/admin_vr.dm
index 356d69a376..e40db3f525 100644
--- a/code/modules/admin/admin_vr.dm
+++ b/code/modules/admin/admin_vr.dm
@@ -8,5 +8,7 @@
traitors.spawn_uplink(H)
H.mind.tcrystals = DEFAULT_TELECRYSTAL_AMOUNT
H.mind.accept_tcrystals = 1
+ var/msg = "[key_name(usr)] has given [H.ckey] an uplink."
+ message_admins(msg)
else
to_chat(usr, "You do not have access to this command.")
\ No newline at end of file
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index d92b3be0cb..dfa24c385e 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -1971,7 +1971,12 @@
if("show")
show_player_info(ckey)
if("list")
- PlayerNotesPage(text2num(href_list["index"]))
+ var/filter
+ if(href_list["filter"] && href_list["filter"] != "0")
+ filter = url_decode(href_list["filter"])
+ PlayerNotesPage(text2num(href_list["index"]), filter)
+ if("filter")
+ PlayerNotesFilter()
return
mob/living/proc/can_centcom_reply()
diff --git a/code/modules/asset_cache/asset_list_items.dm b/code/modules/asset_cache/asset_list_items.dm
index 9bcb385154..b2f2c1bf60 100644
--- a/code/modules/asset_cache/asset_list_items.dm
+++ b/code/modules/asset_cache/asset_list_items.dm
@@ -290,7 +290,7 @@
name = "vore"
/datum/asset/spritesheet/vore/register()
- var/icon/downscaled = icon('icons/mob/screen_full_vore.dmi')
+ var/icon/downscaled = icon('icons/mob/screen_full_vore_ch.dmi') //CHOMPedit
downscaled.Scale(240, 240)
InsertAll("", downscaled)
..()
diff --git a/code/modules/blob2/core_chunk.dm b/code/modules/blob2/core_chunk.dm
index 4abc06843e..15db91e89e 100644
--- a/code/modules/blob2/core_chunk.dm
+++ b/code/modules/blob2/core_chunk.dm
@@ -118,19 +118,19 @@
return FALSE
-/datum/chemical_reaction/blob_reconstitution
+/decl/chemical_reaction/instant/blob_reconstitution
name = "Hostile Blob Revival"
id = "blob_revival"
result = null
required_reagents = list("phoron" = 60)
result_amount = 1
-/datum/chemical_reaction/blob_reconstitution/can_happen(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/blob_reconstitution/can_happen(var/datum/reagents/holder)
if(holder.my_atom && istype(holder.my_atom, /obj/item/weapon/blobcore_chunk))
return ..()
return FALSE
-/datum/chemical_reaction/blob_reconstitution/on_reaction(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/blob_reconstitution/on_reaction(var/datum/reagents/holder)
var/obj/item/weapon/blobcore_chunk/chunk = holder.my_atom
if(chunk.can_genesis && chunk.regen())
chunk.visible_message("[chunk] bubbles, surrounding itself with a rapidly expanding mass of [chunk.blob_type.name]!")
@@ -138,14 +138,14 @@
else
chunk.visible_message("[chunk] shifts strangely, but falls still.")
-/datum/chemical_reaction/blob_reconstitution/domination
+/decl/chemical_reaction/instant/blob_reconstitution/domination
name = "Allied Blob Revival"
id = "blob_friend"
result = null
required_reagents = list("hydrophoron" = 40, "peridaxon" = 20, "mutagen" = 20)
result_amount = 1
-/datum/chemical_reaction/blob_reconstitution/domination/on_reaction(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/blob_reconstitution/domination/on_reaction(var/datum/reagents/holder)
var/obj/item/weapon/blobcore_chunk/chunk = holder.my_atom
if(chunk.can_genesis && chunk.regen("neutral"))
chunk.visible_message("[chunk] bubbles, surrounding itself with a rapidly expanding mass of [chunk.blob_type.name]!")
diff --git a/code/modules/client/preference_setup/general/02_language.dm b/code/modules/client/preference_setup/general/02_language.dm
index cd4a8b0341..1db1064229 100644
--- a/code/modules/client/preference_setup/general/02_language.dm
+++ b/code/modules/client/preference_setup/general/02_language.dm
@@ -23,8 +23,18 @@
if(!islist(pref.alternate_languages)) pref.alternate_languages = list()
if(pref.species)
var/datum/species/S = GLOB.all_species[pref.species]
- if(S && pref.alternate_languages.len > pref.numlanguage()) //CHOMPEdit
+ if(!istype(S))
+ return
+
+ if(pref.alternate_languages.len > pref.numlanguage()) //CHOMPEdit
pref.alternate_languages.len = pref.numlanguage() // Truncate to allowed length CHOMPEdit
+
+ // Sanitize illegal languages
+ for(var/language in pref.alternate_languages)
+ var/datum/language/L = GLOB.all_languages[language]
+ if((L.flags & RESTRICTED) || (!(language in S.secondary_langs) && !is_lang_whitelisted(pref.client, L)))
+ pref.alternate_languages -= language
+
if(isnull(pref.language_prefixes) || !pref.language_prefixes.len)
pref.language_prefixes = config.language_prefixes.Copy()
for(var/prefix in pref.language_prefixes)
diff --git a/code/modules/client/preference_setup/general/03_body.dm b/code/modules/client/preference_setup/general/03_body.dm
index 4e6d6afad1..404838a148 100644
--- a/code/modules/client/preference_setup/general/03_body.dm
+++ b/code/modules/client/preference_setup/general/03_body.dm
@@ -281,33 +281,8 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
pref.r_wing3 = sanitize_integer(pref.r_wing3, 0, 255, initial(pref.r_wing3))
pref.g_wing3 = sanitize_integer(pref.g_wing3, 0, 255, initial(pref.g_wing3))
pref.b_wing3 = sanitize_integer(pref.b_wing3, 0, 255, initial(pref.b_wing3))
-<<<<<<< HEAD
- if(pref.ear_style)
- pref.ear_style = sanitize_inlist(pref.ear_style, ear_styles_list, initial(pref.ear_style))
- var/datum/sprite_accessory/temp_ear_style = ear_styles_list[pref.ear_style]
- if(temp_ear_style.apply_restrictions && (!(pref.species in temp_ear_style.species_allowed)))
- pref.ear_style = initial(pref.ear_style)
- if(pref.tail_style)
- pref.tail_style = sanitize_inlist(pref.tail_style, tail_styles_list, initial(pref.tail_style))
- var/datum/sprite_accessory/temp_tail_style = tail_styles_list[pref.tail_style]
- if(temp_tail_style.apply_restrictions && (!(pref.species in temp_tail_style.species_allowed)))
- pref.tail_style = initial(pref.tail_style)
- if(pref.wing_style)
- pref.wing_style = sanitize_inlist(pref.wing_style, wing_styles_list, initial(pref.wing_style))
- var/datum/sprite_accessory/temp_wing_style = wing_styles_list[pref.wing_style]
- if(temp_wing_style.apply_restrictions && (!(pref.species in temp_wing_style.species_allowed)))
- pref.wing_style = initial(pref.wing_style)
-||||||| parent of a9e9dd241d... Merge pull request #10247 from VOREStation/upstream-merge-8057
- if(!(pref.ear_style in get_ear_styles()))
- pref.ear_style = initial(pref.ear_style)
- if(!(pref.wing_style in get_wing_styles()))
- pref.wing_style = initial(pref.wing_style)
- if(!(pref.tail_style in get_tail_styles()))
- pref.tail_style = initial(pref.tail_style)
-=======
pref.sanitize_body_styles()
->>>>>>> a9e9dd241d... Merge pull request #10247 from VOREStation/upstream-merge-8057
// Moved from /datum/preferences/proc/copy_to()
/datum/category_item/player_setup_item/general/body/copy_to_mob(var/mob/living/carbon/human/character)
@@ -340,87 +315,6 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
character.g_synth = pref.g_synth
character.b_synth = pref.b_synth
character.synth_markings = pref.synth_markings
-<<<<<<< HEAD
- character.ear_style = ear_styles_list[pref.ear_style]
- character.r_ears = pref.r_ears
- character.b_ears = pref.b_ears
- character.g_ears = pref.g_ears
- character.r_ears2 = pref.r_ears2
- character.b_ears2 = pref.b_ears2
- character.g_ears2 = pref.g_ears2
- character.r_ears3 = pref.r_ears3
- character.b_ears3 = pref.b_ears3
- character.g_ears3 = pref.g_ears3
- character.tail_style = tail_styles_list[pref.tail_style]
- character.r_tail = pref.r_tail
- character.b_tail = pref.b_tail
- character.g_tail = pref.g_tail
- character.r_tail2 = pref.r_tail2
- character.b_tail2 = pref.b_tail2
- character.g_tail2 = pref.g_tail2
- character.r_tail3 = pref.r_tail3
- character.b_tail3 = pref.b_tail3
- character.g_tail3 = pref.g_tail3
- character.wing_style = wing_styles_list[pref.wing_style]
- character.r_wing = pref.r_wing
- character.b_wing = pref.b_wing
- character.g_wing = pref.g_wing
- character.r_wing2 = pref.r_wing2
- character.b_wing2 = pref.b_wing2
- character.g_wing2 = pref.g_wing2
- character.r_wing3 = pref.r_wing3
- character.b_wing3 = pref.b_wing3
- character.g_wing3 = pref.g_wing3
- character.set_gender( pref.biological_gender)
-
- if(pref.species == "Grey")//YWadd START
- character.wingdings = pref.wingdings
-
- if(pref.colorblind_mono == 1)
- character.add_modifier(/datum/modifier/trait/colorblind_monochrome)
-
- else if(pref.colorblind_vulp == 1)
- character.add_modifier(/datum/modifier/trait/colorblind_vulp)
-
- else if(pref.colorblind_taj == 1)
- character.add_modifier(/datum/modifier/trait/colorblind_taj)
-
- if(pref.haemophilia == 1)
- character.add_modifier(/datum/modifier/trait/haemophilia)
- //YWadd END
-||||||| parent of a9e9dd241d... Merge pull request #10247 from VOREStation/upstream-merge-8057
- character.ear_style = ear_styles_list[pref.ear_style]
- character.r_ears = pref.r_ears
- character.b_ears = pref.b_ears
- character.g_ears = pref.g_ears
- character.r_ears2 = pref.r_ears2
- character.b_ears2 = pref.b_ears2
- character.g_ears2 = pref.g_ears2
- character.r_ears3 = pref.r_ears3
- character.b_ears3 = pref.b_ears3
- character.g_ears3 = pref.g_ears3
- character.tail_style = tail_styles_list[pref.tail_style]
- character.r_tail = pref.r_tail
- character.b_tail = pref.b_tail
- character.g_tail = pref.g_tail
- character.r_tail2 = pref.r_tail2
- character.b_tail2 = pref.b_tail2
- character.g_tail2 = pref.g_tail2
- character.r_tail3 = pref.r_tail3
- character.b_tail3 = pref.b_tail3
- character.g_tail3 = pref.g_tail3
- character.wing_style = wing_styles_list[pref.wing_style]
- character.r_wing = pref.r_wing
- character.b_wing = pref.b_wing
- character.g_wing = pref.g_wing
- character.r_wing2 = pref.r_wing2
- character.b_wing2 = pref.b_wing2
- character.g_wing2 = pref.g_wing2
- character.r_wing3 = pref.r_wing3
- character.b_wing3 = pref.b_wing3
- character.g_wing3 = pref.g_wing3
- character.set_gender( pref.biological_gender)
-=======
var/list/ear_styles = pref.get_available_styles(global.ear_styles_list)
character.ear_style = ear_styles[pref.ear_style]
@@ -459,8 +353,23 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
character.g_wing3 = pref.g_wing3
character.set_gender(pref.biological_gender)
->>>>>>> a9e9dd241d... Merge pull request #10247 from VOREStation/upstream-merge-8057
+
+ if(pref.species == "Grey")//YWadd START
+ character.wingdings = pref.wingdings
+ if(pref.colorblind_mono == 1)
+ character.add_modifier(/datum/modifier/trait/colorblind_monochrome)
+
+ else if(pref.colorblind_vulp == 1)
+ character.add_modifier(/datum/modifier/trait/colorblind_vulp)
+
+ else if(pref.colorblind_taj == 1)
+ character.add_modifier(/datum/modifier/trait/colorblind_taj)
+
+ if(pref.haemophilia == 1)
+ character.add_modifier(/datum/modifier/trait/haemophilia)
+ //YWadd END
+
// Destroy/cyborgize organs and limbs.
for(var/name in list(BP_HEAD, BP_L_HAND, BP_R_HAND, BP_L_ARM, BP_R_ARM, BP_L_FOOT, BP_R_FOOT, BP_L_LEG, BP_R_LEG, BP_GROIN, BP_TORSO))
var/status = pref.organ_data[name]
@@ -815,23 +724,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
reset_limbs() // Safety for species with incompatible manufacturers; easier than trying to do it case by case.
pref.body_markings.Cut() // Basically same as above.
-<<<<<<< HEAD
-||||||| parent of a9e9dd241d... Merge pull request #10247 from VOREStation/upstream-merge-8057
-
- // Sanitize ear/wing/tail styles
- if(!(pref.ear_style in get_ear_styles()))
- pref.ear_style = initial(pref.ear_style)
- if(!(pref.wing_style in get_wing_styles()))
- pref.wing_style = initial(pref.wing_style)
- if(!(pref.tail_style in get_tail_styles()))
- pref.tail_style = initial(pref.tail_style)
-
-=======
-
- pref.sanitize_body_styles()
-
->>>>>>> a9e9dd241d... Merge pull request #10247 from VOREStation/upstream-merge-8057
var/min_age = get_min_age()
var/max_age = get_max_age()
pref.age = max(min(pref.age, max_age), min_age)
@@ -1297,25 +1190,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
//YW Add End
else if(href_list["ear_style"])
-<<<<<<< HEAD
- // Construct the list of names allowed for this user.
- var/list/pretty_ear_styles = list("Normal" = null)
- for(var/path in ear_styles_list)
- var/datum/sprite_accessory/ears/instance = ear_styles_list[path]
- if(((!instance.ckeys_allowed) || (usr.ckey in instance.ckeys_allowed)) && ((!instance.apply_restrictions) || (pref.species in instance.species_allowed)) || check_rights(R_ADMIN | R_EVENT | R_FUN, 0, user)) //VOREStation Edit
- pretty_ear_styles[instance.name] = path
-
- // Present choice to user
- var/new_ear_style = input(user, "Pick ears", "Character Preference", pref.ear_style) as null|anything in pretty_ear_styles
-||||||| parent of a9e9dd241d... Merge pull request #10247 from VOREStation/upstream-merge-8057
- // Construct the list of names allowed for this user.
- var/list/pretty_ear_styles = get_ear_styles()
-
- // Present choice to user
- var/new_ear_style = input(user, "Pick ears", "Character Preference", pref.ear_style) as null|anything in pretty_ear_styles
-=======
var/new_ear_style = input(user, "Select an ear style for this character:", "Character Preference", pref.ear_style) as null|anything in pref.get_available_styles(global.ear_styles_list)
->>>>>>> a9e9dd241d... Merge pull request #10247 from VOREStation/upstream-merge-8057
if(new_ear_style)
pref.ear_style = new_ear_style
@@ -1349,25 +1224,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["tail_style"])
-<<<<<<< HEAD
- // Construct the list of names allowed for this user.
- var/list/pretty_tail_styles = list("Normal" = null)
- for(var/path in tail_styles_list)
- var/datum/sprite_accessory/tail/instance = tail_styles_list[path]
- if(((!instance.ckeys_allowed) || (usr.ckey in instance.ckeys_allowed)) && ((!instance.apply_restrictions) || (pref.species in instance.species_allowed)) || check_rights(R_ADMIN | R_EVENT | R_FUN, 0, user)) //VOREStation Edit
- pretty_tail_styles[instance.name] = path
-
- // Present choice to user
- var/new_tail_style = input(user, "Pick tails", "Character Preference", pref.tail_style) as null|anything in pretty_tail_styles
-||||||| parent of a9e9dd241d... Merge pull request #10247 from VOREStation/upstream-merge-8057
- // Construct the list of names allowed for this user.
- var/list/pretty_tail_styles = get_tail_styles()
-
- // Present choice to user
- var/new_tail_style = input(user, "Pick tails", "Character Preference", pref.tail_style) as null|anything in pretty_tail_styles
-=======
var/new_tail_style = input(user, "Select a tail style for this character:", "Character Preference", pref.tail_style) as null|anything in pref.get_available_styles(global.tail_styles_list)
->>>>>>> a9e9dd241d... Merge pull request #10247 from VOREStation/upstream-merge-8057
if(new_tail_style)
pref.tail_style = new_tail_style
return TOPIC_REFRESH_UPDATE_PREVIEW
@@ -1400,25 +1257,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["wing_style"])
-<<<<<<< HEAD
- // Construct the list of names allowed for this user.
- var/list/pretty_wing_styles = list("Normal" = null)
- for(var/path in wing_styles_list)
- var/datum/sprite_accessory/wing/instance = wing_styles_list[path]
- if(((!instance.ckeys_allowed) || (usr.ckey in instance.ckeys_allowed)) && ((!instance.apply_restrictions) || (pref.species in instance.species_allowed)) || check_rights(R_ADMIN | R_EVENT | R_FUN, 0, user)) //VOREStation Edit
- pretty_wing_styles[instance.name] = path
-
- // Present choice to user
- var/new_wing_style = input(user, "Pick wings", "Character Preference", pref.wing_style) as null|anything in pretty_wing_styles
-||||||| parent of a9e9dd241d... Merge pull request #10247 from VOREStation/upstream-merge-8057
- // Construct the list of names allowed for this user.
- var/list/pretty_wing_styles = get_wing_styles()
-
- // Present choice to user
- var/new_wing_style = input(user, "Pick wings", "Character Preference", pref.wing_style) as null|anything in pretty_wing_styles
-=======
var/new_wing_style = input(user, "Select a wing style for this character:", "Character Preference", pref.wing_style) as null|anything in pref.get_available_styles(global.wing_styles_list)
->>>>>>> a9e9dd241d... Merge pull request #10247 from VOREStation/upstream-merge-8057
if(new_wing_style)
pref.wing_style = new_wing_style
@@ -1543,33 +1382,4 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
dat += "\[select\]"
dat += "